mirror of
https://github.com/godotengine/godot.git
synced 2024-11-27 06:33:16 +00:00
Merge pull request #50643 from groud/improve_tilemap_compatibility
This commit is contained in:
commit
59d98ed3bb
@ -300,6 +300,14 @@ struct Vector2i {
|
||||
return p_idx ? y : x;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ int min_axis() const {
|
||||
return x < y ? 0 : 1;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ int max_axis() const {
|
||||
return x < y ? 1 : 0;
|
||||
}
|
||||
|
||||
Vector2i min(const Vector2i &p_vector2i) const {
|
||||
return Vector2(MIN(x, p_vector2i.x), MIN(y, p_vector2i.y));
|
||||
}
|
||||
|
@ -36,6 +36,8 @@
|
||||
</return>
|
||||
<argument index="0" name="coords" type="Vector2i">
|
||||
</argument>
|
||||
<argument index="1" name="use_proxies" type="bool">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
@ -44,6 +46,8 @@
|
||||
</return>
|
||||
<argument index="0" name="coords" type="Vector2i">
|
||||
</argument>
|
||||
<argument index="1" name="use_proxies" type="bool">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
@ -52,6 +56,8 @@
|
||||
</return>
|
||||
<argument index="0" name="coords" type="Vector2i">
|
||||
</argument>
|
||||
<argument index="1" name="use_proxies" type="bool">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
|
@ -27,6 +27,40 @@
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="cleanup_invalid_tile_proxies">
|
||||
<return type="void">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="clear_tile_proxies">
|
||||
<return type="void">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_alternative_level_tile_proxy">
|
||||
<return type="Array">
|
||||
</return>
|
||||
<argument index="0" name="source_from" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="coords_from" type="Vector2i">
|
||||
</argument>
|
||||
<argument index="2" name="alternative_from" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_coords_level_tile_proxy">
|
||||
<return type="Array">
|
||||
</return>
|
||||
<argument index="0" name="source_from" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="coords_from" type="Vector2i">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_navigation_layer_layers" qualifiers="const">
|
||||
<return type="int">
|
||||
</return>
|
||||
@ -103,6 +137,14 @@
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_source_level_tile_proxy">
|
||||
<return type="int">
|
||||
</return>
|
||||
<argument index="0" name="source_from" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_terrain_color" qualifiers="const">
|
||||
<return type="Color">
|
||||
</return>
|
||||
@ -139,6 +181,28 @@
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="has_alternative_level_tile_proxy">
|
||||
<return type="bool">
|
||||
</return>
|
||||
<argument index="0" name="source_from" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="coords_from" type="Vector2i">
|
||||
</argument>
|
||||
<argument index="2" name="alternative_from" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="has_coords_level_tile_proxy">
|
||||
<return type="bool">
|
||||
</return>
|
||||
<argument index="0" name="source_from" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="coords_from" type="Vector2i">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="has_source" qualifiers="const">
|
||||
<return type="bool">
|
||||
</return>
|
||||
@ -147,6 +211,48 @@
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="has_source_level_tile_proxy">
|
||||
<return type="bool">
|
||||
</return>
|
||||
<argument index="0" name="source_from" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="map_tile_proxy" qualifiers="const">
|
||||
<return type="Array">
|
||||
</return>
|
||||
<argument index="0" name="source_from" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="coords_from" type="Vector2i">
|
||||
</argument>
|
||||
<argument index="2" name="alternative_from" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_alternative_level_tile_proxy">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="source_from" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="coords_from" type="Vector2i">
|
||||
</argument>
|
||||
<argument index="2" name="alternative_from" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_coords_level_tile_proxy">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="source_from" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="coords_from" type="Vector2i">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_source">
|
||||
<return type="void">
|
||||
</return>
|
||||
@ -155,6 +261,46 @@
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_source_level_tile_proxy">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="source_from" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_alternative_level_tile_proxy">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="source_from" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="coords_from" type="Vector2i">
|
||||
</argument>
|
||||
<argument index="2" name="alternative_from" type="int">
|
||||
</argument>
|
||||
<argument index="3" name="source_to" type="int">
|
||||
</argument>
|
||||
<argument index="4" name="coords_to" type="Vector2i">
|
||||
</argument>
|
||||
<argument index="5" name="alternative_to" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_coords_level_tile_proxy">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="p_source_from" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="coords_from" type="Vector2i">
|
||||
</argument>
|
||||
<argument index="2" name="source_to" type="int">
|
||||
</argument>
|
||||
<argument index="3" name="coords_to" type="Vector2i">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_navigation_layer_layers">
|
||||
<return type="void">
|
||||
</return>
|
||||
@ -225,6 +371,16 @@
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_source_level_tile_proxy">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="source_from" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="source_to" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_terrain_color">
|
||||
<return type="void">
|
||||
</return>
|
||||
|
320
editor/plugins/tiles/atlas_merging_dialog.cpp
Normal file
320
editor/plugins/tiles/atlas_merging_dialog.cpp
Normal file
@ -0,0 +1,320 @@
|
||||
/*************************************************************************/
|
||||
/* atlas_merging_dialog.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "atlas_merging_dialog.h"
|
||||
|
||||
#include "editor/editor_scale.h"
|
||||
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/gui/split_container.h"
|
||||
|
||||
void AtlasMergingDialog::_property_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) {
|
||||
_set(p_property, p_value);
|
||||
}
|
||||
|
||||
void AtlasMergingDialog::_generate_merged(Vector<Ref<TileSetAtlasSource>> p_atlas_sources, int p_max_columns) {
|
||||
merged.instantiate();
|
||||
merged_mapping.clear();
|
||||
|
||||
if (p_atlas_sources.size() >= 2) {
|
||||
Ref<Image> output_image;
|
||||
output_image.instantiate();
|
||||
output_image->create(1, 1, false, Image::FORMAT_RGBA8);
|
||||
|
||||
// Compute the new texture region size.
|
||||
Vector2i new_texture_region_size;
|
||||
for (int source_index = 0; source_index < p_atlas_sources.size(); source_index++) {
|
||||
Ref<TileSetAtlasSource> atlas_source = p_atlas_sources[source_index];
|
||||
new_texture_region_size = new_texture_region_size.max(atlas_source->get_texture_region_size());
|
||||
}
|
||||
|
||||
// Generate the merged TileSetAtlasSource.
|
||||
Vector2i atlas_offset;
|
||||
int line_height = 0;
|
||||
for (int source_index = 0; source_index < p_atlas_sources.size(); source_index++) {
|
||||
Ref<TileSetAtlasSource> atlas_source = p_atlas_sources[source_index];
|
||||
merged_mapping.push_back(Map<Vector2i, Vector2i>());
|
||||
|
||||
// Layout the tiles.
|
||||
Vector2i atlas_size;
|
||||
|
||||
for (int tile_index = 0; tile_index < atlas_source->get_tiles_count(); tile_index++) {
|
||||
Vector2i tile_id = atlas_source->get_tile_id(tile_index);
|
||||
atlas_size = atlas_size.max(tile_id + atlas_source->get_tile_size_in_atlas(tile_id));
|
||||
|
||||
Rect2i new_tile_rect_in_altas = Rect2i(atlas_offset + tile_id, atlas_source->get_tile_size_in_atlas(tile_id));
|
||||
|
||||
// Create tiles and alternatives, then copy their properties.
|
||||
for (int alternative_index = 0; alternative_index < atlas_source->get_alternative_tiles_count(tile_id); alternative_index++) {
|
||||
int alternative_id = atlas_source->get_alternative_tile_id(tile_id, alternative_index);
|
||||
if (alternative_id == 0) {
|
||||
merged->create_tile(new_tile_rect_in_altas.position, new_tile_rect_in_altas.size);
|
||||
} else {
|
||||
merged->create_alternative_tile(new_tile_rect_in_altas.position, alternative_index);
|
||||
}
|
||||
|
||||
// Copy the properties.
|
||||
TileData *original_tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(tile_id, alternative_id));
|
||||
List<PropertyInfo> properties;
|
||||
original_tile_data->get_property_list(&properties);
|
||||
for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
|
||||
const StringName &property_name = E->get().name;
|
||||
merged->set(property_name, original_tile_data->get(property_name));
|
||||
}
|
||||
|
||||
// Add to the mapping.
|
||||
merged_mapping[source_index][tile_id] = new_tile_rect_in_altas.position;
|
||||
}
|
||||
|
||||
// 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()));
|
||||
}
|
||||
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.
|
||||
line_height = MAX(atlas_size.y, line_height);
|
||||
atlas_offset.x += atlas_size.x;
|
||||
if (atlas_offset.x >= p_max_columns) {
|
||||
atlas_offset.x = 0;
|
||||
atlas_offset.y += line_height;
|
||||
line_height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Ref<ImageTexture> output_image_texture;
|
||||
output_image_texture.instantiate();
|
||||
output_image_texture->create_from_image(output_image);
|
||||
|
||||
merged->set_texture(output_image_texture);
|
||||
merged->set_texture_region_size(new_texture_region_size);
|
||||
}
|
||||
}
|
||||
|
||||
void AtlasMergingDialog::_update_texture() {
|
||||
Vector<int> selected = atlas_merging_atlases_list->get_selected_items();
|
||||
if (selected.size() >= 2) {
|
||||
Vector<Ref<TileSetAtlasSource>> to_merge;
|
||||
for (int i = 0; i < selected.size(); i++) {
|
||||
int source_id = atlas_merging_atlases_list->get_item_metadata(selected[i]);
|
||||
to_merge.push_back(tile_set->get_source(source_id));
|
||||
}
|
||||
_generate_merged(to_merge, next_line_after_column);
|
||||
preview->set_texture(merged->get_texture());
|
||||
preview->show();
|
||||
select_2_atlases_label->hide();
|
||||
get_ok_button()->set_disabled(false);
|
||||
merge_button->set_disabled(false);
|
||||
} else {
|
||||
_generate_merged(Vector<Ref<TileSetAtlasSource>>(), next_line_after_column);
|
||||
preview->set_texture(Ref<Texture2D>());
|
||||
preview->hide();
|
||||
select_2_atlases_label->show();
|
||||
get_ok_button()->set_disabled(true);
|
||||
merge_button->set_disabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AtlasMergingDialog::_merge_confirmed(String p_path) {
|
||||
ERR_FAIL_COND(!merged.is_valid());
|
||||
|
||||
Ref<ImageTexture> output_image_texture = merged->get_texture();
|
||||
output_image_texture->get_image()->save_png(p_path);
|
||||
|
||||
Ref<Texture2D> new_texture_resource = ResourceLoader::load(p_path, "Texture2D");
|
||||
merged->set_texture(new_texture_resource);
|
||||
|
||||
undo_redo->create_action("Merge TileSetAtlasSource");
|
||||
int next_id = tile_set->get_next_source_id();
|
||||
undo_redo->add_do_method(*tile_set, "add_source", merged, next_id);
|
||||
undo_redo->add_undo_method(*tile_set, "remove_source", next_id);
|
||||
|
||||
if (delete_original_atlases) {
|
||||
// Delete originals if needed.
|
||||
Vector<int> selected = atlas_merging_atlases_list->get_selected_items();
|
||||
for (int i = 0; i < selected.size(); i++) {
|
||||
int source_id = atlas_merging_atlases_list->get_item_metadata(selected[i]);
|
||||
Ref<TileSetAtlasSource> tas = tile_set->get_source(source_id);
|
||||
undo_redo->add_do_method(*tile_set, "remove_source", source_id);
|
||||
undo_redo->add_undo_method(*tile_set, "add_source", tas, source_id);
|
||||
|
||||
// Add the tile proxies.
|
||||
for (int tile_index = 0; tile_index < tas->get_tiles_count(); tile_index++) {
|
||||
Vector2i tile_id = tas->get_tile_id(tile_index);
|
||||
undo_redo->add_do_method(*tile_set, "set_coords_level_tile_proxy", source_id, tile_id, next_id, merged_mapping[i][tile_id]);
|
||||
if (tile_set->has_coords_level_tile_proxy(source_id, tile_id)) {
|
||||
Array a = tile_set->get_coords_level_tile_proxy(source_id, tile_id);
|
||||
undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", a[0], a[1]);
|
||||
} else {
|
||||
undo_redo->add_undo_method(*tile_set, "remove_coords_level_tile_proxy", source_id, tile_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
undo_redo->commit_action();
|
||||
commited_actions_count++;
|
||||
|
||||
hide();
|
||||
}
|
||||
|
||||
void AtlasMergingDialog::ok_pressed() {
|
||||
delete_original_atlases = false;
|
||||
editor_file_dialog->popup_file_dialog();
|
||||
}
|
||||
|
||||
void AtlasMergingDialog::cancel_pressed() {
|
||||
for (int i = 0; i < commited_actions_count; i++) {
|
||||
undo_redo->undo();
|
||||
}
|
||||
commited_actions_count = 0;
|
||||
}
|
||||
|
||||
void AtlasMergingDialog::custom_action(const String &p_action) {
|
||||
if (p_action == "merge") {
|
||||
delete_original_atlases = true;
|
||||
editor_file_dialog->popup_file_dialog();
|
||||
}
|
||||
}
|
||||
|
||||
bool AtlasMergingDialog::_set(const StringName &p_name, const Variant &p_value) {
|
||||
if (p_name == "next_line_after_column" && p_value.get_type() == Variant::INT) {
|
||||
next_line_after_column = p_value;
|
||||
_update_texture();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AtlasMergingDialog::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
if (p_name == "next_line_after_column") {
|
||||
r_ret = next_line_after_column;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AtlasMergingDialog::update_tile_set(Ref<TileSet> p_tile_set) {
|
||||
ERR_FAIL_COND(!p_tile_set.is_valid());
|
||||
tile_set = p_tile_set;
|
||||
|
||||
atlas_merging_atlases_list->clear();
|
||||
for (int i = 0; i < p_tile_set->get_source_count(); i++) {
|
||||
int source_id = p_tile_set->get_source_id(i);
|
||||
Ref<TileSetAtlasSource> atlas_source = p_tile_set->get_source(source_id);
|
||||
if (atlas_source.is_valid()) {
|
||||
Ref<Texture2D> texture = atlas_source->get_texture();
|
||||
if (texture.is_valid()) {
|
||||
String item_text = vformat("%s (id:%d)", texture->get_path().get_file(), source_id);
|
||||
atlas_merging_atlases_list->add_item(item_text, texture);
|
||||
atlas_merging_atlases_list->set_item_metadata(atlas_merging_atlases_list->get_item_count() - 1, source_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get_ok_button()->set_disabled(true);
|
||||
merge_button->set_disabled(true);
|
||||
|
||||
commited_actions_count = 0;
|
||||
}
|
||||
|
||||
AtlasMergingDialog::AtlasMergingDialog() {
|
||||
// Atlas merging window.
|
||||
set_title(TTR("Atlas Merging"));
|
||||
set_hide_on_ok(false);
|
||||
|
||||
// Ok buttons
|
||||
get_ok_button()->set_text(TTR("Merge (Keep original Atlases)"));
|
||||
get_ok_button()->set_disabled(true);
|
||||
merge_button = add_button(TTR("Merge"), true, "merge");
|
||||
merge_button->set_disabled(true);
|
||||
|
||||
HSplitContainer *atlas_merging_h_split_container = memnew(HSplitContainer);
|
||||
atlas_merging_h_split_container->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
atlas_merging_h_split_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
add_child(atlas_merging_h_split_container);
|
||||
|
||||
// Atlas sources item list.
|
||||
atlas_merging_atlases_list = memnew(ItemList);
|
||||
atlas_merging_atlases_list->set_fixed_icon_size(Size2i(60, 60) * EDSCALE);
|
||||
atlas_merging_atlases_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
atlas_merging_atlases_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
atlas_merging_atlases_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
|
||||
atlas_merging_atlases_list->set_custom_minimum_size(Size2(100, 200));
|
||||
atlas_merging_atlases_list->set_select_mode(ItemList::SELECT_MULTI);
|
||||
atlas_merging_atlases_list->connect("multi_selected", callable_mp(this, &AtlasMergingDialog::_update_texture).unbind(2));
|
||||
atlas_merging_h_split_container->add_child(atlas_merging_atlases_list);
|
||||
|
||||
VBoxContainer *atlas_merging_right_panel = memnew(VBoxContainer);
|
||||
atlas_merging_right_panel->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
atlas_merging_h_split_container->add_child(atlas_merging_right_panel);
|
||||
|
||||
// Settings.
|
||||
Label *settings_label = memnew(Label);
|
||||
settings_label->set_text(TTR("Settings:"));
|
||||
atlas_merging_right_panel->add_child(settings_label);
|
||||
|
||||
columns_editor_property = memnew(EditorPropertyInteger);
|
||||
columns_editor_property->set_label(TTR("Next Line After Column"));
|
||||
columns_editor_property->set_object_and_property(this, "next_line_after_column");
|
||||
columns_editor_property->update_property();
|
||||
columns_editor_property->connect("property_changed", callable_mp(this, &AtlasMergingDialog::_property_changed));
|
||||
atlas_merging_right_panel->add_child(columns_editor_property);
|
||||
|
||||
// Preview.
|
||||
Label *preview_label = memnew(Label);
|
||||
preview_label->set_text(TTR("Preview:"));
|
||||
atlas_merging_right_panel->add_child(preview_label);
|
||||
|
||||
preview = memnew(TextureRect);
|
||||
preview->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
preview->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
preview->set_expand(true);
|
||||
preview->hide();
|
||||
preview->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
|
||||
atlas_merging_right_panel->add_child(preview);
|
||||
|
||||
select_2_atlases_label = memnew(Label);
|
||||
select_2_atlases_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
select_2_atlases_label->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
select_2_atlases_label->set_align(Label::ALIGN_CENTER);
|
||||
select_2_atlases_label->set_valign(Label::VALIGN_CENTER);
|
||||
select_2_atlases_label->set_text(TTR("Please select two atlases or more."));
|
||||
atlas_merging_right_panel->add_child(select_2_atlases_label);
|
||||
|
||||
// The file dialog to choose the texture path.
|
||||
editor_file_dialog = memnew(EditorFileDialog);
|
||||
editor_file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
|
||||
editor_file_dialog->add_filter("*.png");
|
||||
editor_file_dialog->connect("file_selected", callable_mp(this, &AtlasMergingDialog::_merge_confirmed));
|
||||
add_child(editor_file_dialog);
|
||||
}
|
86
editor/plugins/tiles/atlas_merging_dialog.h
Normal file
86
editor/plugins/tiles/atlas_merging_dialog.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*************************************************************************/
|
||||
/* atlas_merging_dialog.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef ATLAS_MERGING_DIALOG_H
|
||||
#define ATLAS_MERGING_DIALOG_H
|
||||
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_properties.h"
|
||||
|
||||
#include "scene/gui/dialogs.h"
|
||||
#include "scene/gui/item_list.h"
|
||||
#include "scene/gui/texture_rect.h"
|
||||
#include "scene/resources/tile_set.h"
|
||||
|
||||
class AtlasMergingDialog : public ConfirmationDialog {
|
||||
GDCLASS(AtlasMergingDialog, ConfirmationDialog);
|
||||
|
||||
private:
|
||||
int commited_actions_count = 0;
|
||||
bool delete_original_atlases = true;
|
||||
Ref<TileSetAtlasSource> merged;
|
||||
LocalVector<Map<Vector2i, Vector2i>> merged_mapping;
|
||||
Ref<TileSet> tile_set;
|
||||
|
||||
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
|
||||
|
||||
// Settings.
|
||||
int next_line_after_column = 30;
|
||||
|
||||
// GUI.
|
||||
ItemList *atlas_merging_atlases_list;
|
||||
EditorPropertyVector2i *texture_region_size_editor_property;
|
||||
EditorPropertyInteger *columns_editor_property;
|
||||
TextureRect *preview;
|
||||
Label *select_2_atlases_label;
|
||||
EditorFileDialog *editor_file_dialog;
|
||||
Button *merge_button;
|
||||
|
||||
void _property_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing);
|
||||
|
||||
void _generate_merged(Vector<Ref<TileSetAtlasSource>> p_atlas_sources, int p_max_columns);
|
||||
void _update_texture();
|
||||
void _merge_confirmed(String p_path);
|
||||
|
||||
protected:
|
||||
virtual void ok_pressed() override;
|
||||
virtual void cancel_pressed() override;
|
||||
virtual void custom_action(const String &) override;
|
||||
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
|
||||
public:
|
||||
void update_tile_set(Ref<TileSet> p_tile_set);
|
||||
|
||||
AtlasMergingDialog();
|
||||
};
|
||||
|
||||
#endif // ATLAS_MERGING_DIALOG_H
|
@ -47,7 +47,7 @@ class TileAtlasView : public Control {
|
||||
private:
|
||||
TileSet *tile_set;
|
||||
TileSetAtlasSource *tile_set_atlas_source;
|
||||
int source_id = -1;
|
||||
int source_id = TileSet::INVALID_SOURCE;
|
||||
|
||||
enum DragType {
|
||||
DRAG_TYPE_NONE,
|
||||
|
@ -56,18 +56,11 @@ void TileMapEditorTilesPlugin::_notification(int p_what) {
|
||||
picker_button->set_icon(get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons")));
|
||||
erase_button->set_icon(get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons")));
|
||||
|
||||
toggle_grid_button->set_icon(get_theme_icon(SNAME("Grid"), SNAME("EditorIcons")));
|
||||
|
||||
missing_atlas_texture_icon = get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons"));
|
||||
|
||||
toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
|
||||
break;
|
||||
case NOTIFICATION_VISIBILITY_CHANGED:
|
||||
_stop_dragging();
|
||||
break;
|
||||
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED:
|
||||
toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,10 +78,6 @@ void TileMapEditorTilesPlugin::_on_scattering_spinbox_changed(double p_value) {
|
||||
scattering = p_value;
|
||||
}
|
||||
|
||||
void TileMapEditorTilesPlugin::_on_grid_toggled(bool p_pressed) {
|
||||
EditorSettings::get_singleton()->set("editors/tiles_editor/display_grid", p_pressed);
|
||||
}
|
||||
|
||||
void TileMapEditorTilesPlugin::_update_toolbar() {
|
||||
// Stop draggig if needed.
|
||||
_stop_dragging();
|
||||
@ -204,7 +193,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
|
||||
}
|
||||
|
||||
// Synchronize
|
||||
TilesEditor::get_singleton()->set_atlas_sources_lists_current(sources_list->get_current());
|
||||
TilesEditor::get_singleton()->set_sources_lists_current(sources_list->get_current());
|
||||
}
|
||||
|
||||
void TileMapEditorTilesPlugin::_update_bottom_panel() {
|
||||
@ -410,7 +399,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
|
||||
if (!tile_map_selection.is_empty()) {
|
||||
undo_redo->create_action(TTR("Delete tiles"));
|
||||
for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) {
|
||||
undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
undo_redo->add_do_method(tile_map, "set_cell", E->get(), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
undo_redo->add_undo_method(tile_map, "set_cell", E->get(), tile_map->get_cell_source_id(E->get()), tile_map->get_cell_atlas_coords(E->get()), tile_map->get_cell_alternative_tile(E->get()));
|
||||
}
|
||||
undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
|
||||
@ -441,7 +430,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
|
||||
if (!tile_map_selection.is_empty()) {
|
||||
undo_redo->create_action(TTR("Delete tiles"));
|
||||
for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) {
|
||||
undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
undo_redo->add_do_method(tile_map, "set_cell", E->get(), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
undo_redo->add_undo_method(tile_map, "set_cell", E->get(), tile_map->get_cell_source_id(E->get()), tile_map->get_cell_atlas_coords(E->get()), tile_map->get_cell_alternative_tile(E->get()));
|
||||
}
|
||||
undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
|
||||
@ -462,12 +451,12 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
|
||||
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 == -1) {
|
||||
if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
|
||||
continue;
|
||||
}
|
||||
Vector2i coords = E->key();
|
||||
if (!drag_modified.has(coords)) {
|
||||
drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
|
||||
drag_modified.insert(coords, tile_map->get_cell(coords));
|
||||
}
|
||||
tile_map->set_cell(coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
|
||||
}
|
||||
@ -478,12 +467,12 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
|
||||
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 == -1) {
|
||||
if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
|
||||
continue;
|
||||
}
|
||||
Vector2i coords = E->key();
|
||||
if (!drag_modified.has(coords)) {
|
||||
drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
|
||||
drag_modified.insert(coords, tile_map->get_cell(coords));
|
||||
}
|
||||
tile_map->set_cell(coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
|
||||
}
|
||||
@ -516,8 +505,8 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
|
||||
drag_modified.clear();
|
||||
for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) {
|
||||
Vector2i coords = E->get();
|
||||
drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
|
||||
tile_map->set_cell(coords, -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
drag_modified.insert(coords, tile_map->get_cell(coords));
|
||||
tile_map->set_cell(coords, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
}
|
||||
} else {
|
||||
// Select tiles
|
||||
@ -536,12 +525,12 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
|
||||
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 == -1) {
|
||||
if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
|
||||
continue;
|
||||
}
|
||||
Vector2i coords = E->key();
|
||||
if (!drag_modified.has(coords)) {
|
||||
drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
|
||||
drag_modified.insert(coords, tile_map->get_cell(coords));
|
||||
}
|
||||
tile_map->set_cell(coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
|
||||
}
|
||||
@ -562,12 +551,12 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
|
||||
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 == -1) {
|
||||
if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
|
||||
continue;
|
||||
}
|
||||
Vector2i coords = E->key();
|
||||
if (!drag_modified.has(coords)) {
|
||||
drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
|
||||
drag_modified.insert(coords, tile_map->get_cell(coords));
|
||||
}
|
||||
tile_map->set_cell(coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
|
||||
}
|
||||
@ -634,7 +623,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
|
||||
for (int x = rect.position.x; x < rect.get_end().x; x++) {
|
||||
for (int y = rect.position.y; y < rect.get_end().y; y++) {
|
||||
Vector2i coords = Vector2i(x, y);
|
||||
if (tile_map->get_cell_source_id(coords) != -1) {
|
||||
if (tile_map->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
|
||||
Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(coords) - tile_shape_size / 2, tile_shape_size));
|
||||
tile_set->draw_tile_shape(p_overlay, cell_region, Color(1.0, 1.0, 1.0), false);
|
||||
}
|
||||
@ -648,7 +637,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
|
||||
for (int x = rect.position.x; x < rect.get_end().x; x++) {
|
||||
for (int y = rect.position.y; y < rect.get_end().y; y++) {
|
||||
Vector2i coords = Vector2i(x, y);
|
||||
if (tile_map->get_cell_source_id(coords) != -1) {
|
||||
if (tile_map->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
|
||||
to_draw.insert(coords);
|
||||
}
|
||||
}
|
||||
@ -871,7 +860,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_
|
||||
|
||||
// Get or create the pattern.
|
||||
TileMapPattern erase_pattern;
|
||||
erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
erase_pattern.set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern;
|
||||
|
||||
Map<Vector2i, TileMapCell> output;
|
||||
@ -923,7 +912,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_rect(Vector2i p_start
|
||||
|
||||
// Get or create the pattern.
|
||||
TileMapPattern erase_pattern;
|
||||
erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
erase_pattern.set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern;
|
||||
|
||||
// Compute the offset to align things to the bottom or right.
|
||||
@ -974,7 +963,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
|
||||
|
||||
// Get or create the pattern.
|
||||
TileMapPattern erase_pattern;
|
||||
erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
erase_pattern.set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern;
|
||||
|
||||
Map<Vector2i, TileMapCell> output;
|
||||
@ -983,7 +972,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
|
||||
|
||||
// If we are filling empty tiles, compute the tilemap boundaries.
|
||||
Rect2i boundaries;
|
||||
if (source.source_id == -1) {
|
||||
if (source.source_id == TileSet::INVALID_SOURCE) {
|
||||
boundaries = tile_map->get_used_rect();
|
||||
}
|
||||
|
||||
@ -999,7 +988,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
|
||||
if (source.source_id == tile_map->get_cell_source_id(coords) &&
|
||||
source.get_atlas_coords() == tile_map->get_cell_atlas_coords(coords) &&
|
||||
source.alternative_tile == tile_map->get_cell_alternative_tile(coords) &&
|
||||
(source.source_id != -1 || boundaries.has_point(coords))) {
|
||||
(source.source_id != TileSet::INVALID_SOURCE || boundaries.has_point(coords))) {
|
||||
if (!erase_button->is_pressed() && random_tile_checkbox->is_pressed()) {
|
||||
// Paint a random tile.
|
||||
output.insert(coords, _pick_random_tile(pattern));
|
||||
@ -1027,7 +1016,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
|
||||
} else {
|
||||
// Replace all tiles like the source.
|
||||
TypedArray<Vector2i> to_check;
|
||||
if (source.source_id == -1) {
|
||||
if (source.source_id == TileSet::INVALID_SOURCE) {
|
||||
Rect2i rect = tile_map->get_used_rect();
|
||||
if (rect.size.x <= 0 || rect.size.y <= 0) {
|
||||
rect = Rect2i(p_coords, Vector2i(1, 1));
|
||||
@ -1045,7 +1034,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
|
||||
if (source.source_id == tile_map->get_cell_source_id(coords) &&
|
||||
source.get_atlas_coords() == tile_map->get_cell_atlas_coords(coords) &&
|
||||
source.alternative_tile == tile_map->get_cell_alternative_tile(coords) &&
|
||||
(source.source_id != -1 || boundaries.has_point(coords))) {
|
||||
(source.source_id != TileSet::INVALID_SOURCE || boundaries.has_point(coords))) {
|
||||
if (!erase_button->is_pressed() && random_tile_checkbox->is_pressed()) {
|
||||
// Paint a random tile.
|
||||
output.insert(coords, _pick_random_tile(pattern));
|
||||
@ -1102,7 +1091,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
|
||||
tile_map_selection.erase(coords);
|
||||
}
|
||||
} else {
|
||||
if (tile_map->get_cell_source_id(coords) != -1) {
|
||||
if (tile_map->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
|
||||
tile_map_selection.insert(coords);
|
||||
}
|
||||
}
|
||||
@ -1173,7 +1162,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
|
||||
for (int x = rect.position.x; x < rect.get_end().x; x++) {
|
||||
for (int y = rect.position.y; y < rect.get_end().y; y++) {
|
||||
Vector2i coords = Vector2i(x, y);
|
||||
if (tile_map->get_cell_source_id(coords) != -1) {
|
||||
if (tile_map->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
|
||||
coords_array.push_back(coords);
|
||||
}
|
||||
}
|
||||
@ -1198,7 +1187,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
|
||||
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 == -1) {
|
||||
if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
|
||||
continue;
|
||||
}
|
||||
undo_redo->add_do_method(tile_map, "set_cell", E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
|
||||
@ -1210,7 +1199,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
|
||||
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 == -1) {
|
||||
if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
|
||||
continue;
|
||||
}
|
||||
undo_redo->add_do_method(tile_map, "set_cell", E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
|
||||
@ -1221,7 +1210,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
|
||||
case DRAG_TYPE_BUCKET: {
|
||||
undo_redo->create_action(TTR("Paint tiles"));
|
||||
for (Map<Vector2i, TileMapCell>::Element *E = drag_modified.front(); E; E = E->next()) {
|
||||
if (!erase_button->is_pressed() && E->get().source_id == -1) {
|
||||
if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
|
||||
continue;
|
||||
}
|
||||
undo_redo->add_do_method(tile_map, "set_cell", E->key(), tile_map->get_cell_source_id(E->key()), tile_map->get_cell_atlas_coords(E->key()), tile_map->get_cell_alternative_tile(E->key()));
|
||||
@ -1249,7 +1238,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
|
||||
void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
|
||||
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
|
||||
if (!tile_map) {
|
||||
hovered_tile.source_id = -1;
|
||||
hovered_tile.source_id = TileSet::INVALID_SOURCE;
|
||||
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
|
||||
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
|
||||
tile_set_selection.clear();
|
||||
@ -1260,7 +1249,7 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
|
||||
|
||||
Ref<TileSet> tile_set = tile_map->get_tileset();
|
||||
if (!tile_set.is_valid()) {
|
||||
hovered_tile.source_id = -1;
|
||||
hovered_tile.source_id = TileSet::INVALID_SOURCE;
|
||||
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
|
||||
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
|
||||
tile_set_selection.clear();
|
||||
@ -1271,7 +1260,7 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
|
||||
|
||||
int source_index = sources_list->get_current();
|
||||
if (source_index < 0 || source_index >= sources_list->get_item_count()) {
|
||||
hovered_tile.source_id = -1;
|
||||
hovered_tile.source_id = TileSet::INVALID_SOURCE;
|
||||
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
|
||||
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
|
||||
tile_set_selection.clear();
|
||||
@ -1287,7 +1276,7 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
|
||||
!tile_set->has_source(hovered_tile.source_id) ||
|
||||
!tile_set->get_source(hovered_tile.source_id)->has_tile(hovered_tile.get_atlas_coords()) ||
|
||||
!tile_set->get_source(hovered_tile.source_id)->has_alternative_tile(hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile)) {
|
||||
hovered_tile.source_id = -1;
|
||||
hovered_tile.source_id = TileSet::INVALID_SOURCE;
|
||||
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
|
||||
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
|
||||
}
|
||||
@ -1403,7 +1392,7 @@ void TileMapEditorTilesPlugin::_update_tileset_selection_from_selection_pattern(
|
||||
TypedArray<Vector2i> used_cells = selection_pattern->get_used_cells();
|
||||
for (int i = 0; i < used_cells.size(); i++) {
|
||||
Vector2i coords = used_cells[i];
|
||||
if (selection_pattern->get_cell_source_id(coords) != -1) {
|
||||
if (selection_pattern->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
|
||||
tile_set_selection.insert(TileMapCell(selection_pattern->get_cell_source_id(coords), selection_pattern->get_cell_atlas_coords(coords), selection_pattern->get_cell_alternative_tile(coords)));
|
||||
}
|
||||
}
|
||||
@ -1475,7 +1464,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
|
||||
}
|
||||
|
||||
void TileMapEditorTilesPlugin::_tile_atlas_control_mouse_exited() {
|
||||
hovered_tile.source_id = -1;
|
||||
hovered_tile.source_id = TileSet::INVALID_SOURCE;
|
||||
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
|
||||
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
|
||||
tile_set_dragging_selection = false;
|
||||
@ -1634,7 +1623,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
|
||||
}
|
||||
|
||||
void TileMapEditorTilesPlugin::_tile_alternatives_control_mouse_exited() {
|
||||
hovered_tile.source_id = -1;
|
||||
hovered_tile.source_id = TileSet::INVALID_SOURCE;
|
||||
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
|
||||
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
|
||||
tile_set_dragging_selection = false;
|
||||
@ -1856,19 +1845,6 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
|
||||
|
||||
_on_random_tile_checkbox_toggled(false);
|
||||
|
||||
// Wide empty separation control.
|
||||
Control *h_empty_space = memnew(Control);
|
||||
h_empty_space->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
toolbar->add_child(h_empty_space);
|
||||
|
||||
// Grid toggle.
|
||||
toggle_grid_button = memnew(Button);
|
||||
toggle_grid_button->set_flat(true);
|
||||
toggle_grid_button->set_toggle_mode(true);
|
||||
toggle_grid_button->set_tooltip(TTR("Toggle grid visibility."));
|
||||
toggle_grid_button->connect("toggled", callable_mp(this, &TileMapEditorTilesPlugin::_on_grid_toggled));
|
||||
toolbar->add_child(toggle_grid_button);
|
||||
|
||||
// Default tool.
|
||||
paint_tool_button->set_pressed(true);
|
||||
_update_toolbar();
|
||||
@ -1898,8 +1874,8 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
|
||||
sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
|
||||
sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_fix_selected_and_hovered).unbind(1));
|
||||
sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_bottom_panel).unbind(1));
|
||||
sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_sources_lists_current));
|
||||
sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_atlas_sources_list), varray(sources_list));
|
||||
sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_sources_lists_current));
|
||||
sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_sources_list), varray(sources_list));
|
||||
atlas_sources_split_container->add_child(sources_list);
|
||||
|
||||
// Tile atlas source.
|
||||
@ -2968,7 +2944,7 @@ void TileMapEditorTerrainsPlugin::_update_terrains_cache() {
|
||||
}
|
||||
|
||||
TileMapCell empty_cell;
|
||||
empty_cell.source_id = -1;
|
||||
empty_cell.source_id = TileSet::INVALID_SOURCE;
|
||||
empty_cell.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
|
||||
empty_cell.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
|
||||
per_terrain_terrains_tile_patterns_tiles[i][empty_pattern].insert(empty_cell);
|
||||
@ -3190,6 +3166,9 @@ void TileMapEditor::_notification(int p_what) {
|
||||
case NOTIFICATION_THEME_CHANGED:
|
||||
missing_tile_texture = get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"));
|
||||
warning_pattern_texture = get_theme_icon(SNAME("WarningPattern"), SNAME("EditorIcons"));
|
||||
advanced_menu_button->set_icon(get_theme_icon(SNAME("Tools"), SNAME("EditorIcons")));
|
||||
toggle_grid_button->set_icon(get_theme_icon(SNAME("Grid"), SNAME("EditorIcons")));
|
||||
toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
|
||||
break;
|
||||
case NOTIFICATION_INTERNAL_PROCESS:
|
||||
if (is_visible_in_tree() && tileset_changed_needs_update) {
|
||||
@ -3199,6 +3178,44 @@ void TileMapEditor::_notification(int p_what) {
|
||||
tileset_changed_needs_update = false;
|
||||
}
|
||||
break;
|
||||
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED:
|
||||
toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TileMapEditor::_on_grid_toggled(bool p_pressed) {
|
||||
EditorSettings::get_singleton()->set("editors/tiles_editor/display_grid", p_pressed);
|
||||
}
|
||||
|
||||
void TileMapEditor::_advanced_menu_button_id_pressed(int p_id) {
|
||||
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
|
||||
if (!tile_map) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<TileSet> tile_set = tile_map->get_tileset();
|
||||
if (!tile_set.is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_id == 0) { // Replace Tile Proxies
|
||||
undo_redo->create_action(TTR("Replace Tiles with Proxies"));
|
||||
TypedArray<Vector2i> used_cells = tile_map->get_used_cells();
|
||||
for (int i = 0; i < used_cells.size(); i++) {
|
||||
Vector2i cell_coords = used_cells[i];
|
||||
TileMapCell from = tile_map->get_cell(cell_coords);
|
||||
Array to_array = tile_set->map_tile_proxy(from.source_id, from.get_atlas_coords(), from.alternative_tile);
|
||||
TileMapCell to;
|
||||
to.source_id = to_array[0];
|
||||
to.set_atlas_coords(to_array[1]);
|
||||
to.alternative_tile = to_array[2];
|
||||
if (from != to) {
|
||||
undo_redo->add_do_method(tile_map, "set_cell", cell_coords, to.source_id, to.get_atlas_coords(), to.alternative_tile);
|
||||
undo_redo->add_undo_method(tile_map, "set_cell", cell_coords, from.source_id, from.get_atlas_coords(), from.alternative_tile);
|
||||
}
|
||||
}
|
||||
undo_redo->commit_action();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3349,7 +3366,6 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
|
||||
Vector2i tile_shape_size = tile_set->get_tile_size();
|
||||
|
||||
// Draw tiles with invalid IDs in the grid.
|
||||
float icon_ratio = MIN(missing_tile_texture->get_size().x / tile_set->get_tile_size().x, missing_tile_texture->get_size().y / tile_set->get_tile_size().y) / 3;
|
||||
TypedArray<Vector2i> used_cells = tile_map->get_used_cells();
|
||||
for (int i = 0; i < used_cells.size(); i++) {
|
||||
Vector2i coords = used_cells[i];
|
||||
@ -3365,25 +3381,33 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
|
||||
|
||||
if (!source || !source->has_tile(tile_atlas_coords) || !source->has_alternative_tile(tile_atlas_coords, tile_alternative_tile)) {
|
||||
// Generate a random color from the hashed values of the tiles.
|
||||
Array to_hash;
|
||||
to_hash.push_back(tile_source_id);
|
||||
to_hash.push_back(tile_atlas_coords);
|
||||
to_hash.push_back(tile_alternative_tile);
|
||||
uint32_t hash = RandomPCG(to_hash.hash()).rand();
|
||||
Array a = tile_set->map_tile_proxy(tile_source_id, tile_atlas_coords, tile_alternative_tile);
|
||||
if (int(a[0]) == tile_source_id && Vector2i(a[1]) == tile_atlas_coords && int(a[2]) == tile_alternative_tile) {
|
||||
// Only display the pattern if we have no proxy tile.
|
||||
Array to_hash;
|
||||
to_hash.push_back(tile_source_id);
|
||||
to_hash.push_back(tile_atlas_coords);
|
||||
to_hash.push_back(tile_alternative_tile);
|
||||
uint32_t hash = RandomPCG(to_hash.hash()).rand();
|
||||
|
||||
Color color;
|
||||
color = color.from_hsv(
|
||||
(float)((hash >> 24) & 0xFF) / 256.0,
|
||||
Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0),
|
||||
Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0),
|
||||
0.8);
|
||||
Color color;
|
||||
color = color.from_hsv(
|
||||
(float)((hash >> 24) & 0xFF) / 256.0,
|
||||
Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0),
|
||||
Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0),
|
||||
0.8);
|
||||
|
||||
// Draw the scaled tile.
|
||||
Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(coords) - Vector2(tile_shape_size) / 2, Vector2(tile_shape_size)));
|
||||
tile_set->draw_tile_shape(p_overlay, cell_region, color, true, warning_pattern_texture);
|
||||
// Draw the scaled tile.
|
||||
Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(coords) - Vector2(tile_shape_size) / 2, Vector2(tile_shape_size)));
|
||||
tile_set->draw_tile_shape(p_overlay, cell_region, color, true, warning_pattern_texture);
|
||||
}
|
||||
|
||||
// Draw the warning icon.
|
||||
Rect2 rect = Rect2(xform.xform(tile_map->map_to_world(coords)) - (icon_ratio * missing_tile_texture->get_size() * xform.get_scale() / 2), icon_ratio * missing_tile_texture->get_size() * xform.get_scale());
|
||||
int min_axis = missing_tile_texture->get_size().min_axis();
|
||||
Vector2 icon_size;
|
||||
icon_size[min_axis] = tile_set->get_tile_size()[min_axis] / 3;
|
||||
icon_size[(min_axis + 1) % 2] = (icon_size[min_axis] * missing_tile_texture->get_size()[(min_axis + 1) % 2] / missing_tile_texture->get_size()[min_axis]);
|
||||
Rect2 rect = Rect2(xform.xform(tile_map->map_to_world(coords)) - (icon_size * xform.get_scale() / 2), icon_size * xform.get_scale());
|
||||
p_overlay->draw_texture_rect(missing_tile_texture, rect);
|
||||
}
|
||||
}
|
||||
@ -3503,6 +3527,26 @@ TileMapEditor::TileMapEditor() {
|
||||
tilemap_toolbar->add_child(tile_map_editor_plugins[i]->get_toolbar());
|
||||
}
|
||||
|
||||
// Wide empty separation control.
|
||||
Control *h_empty_space = memnew(Control);
|
||||
h_empty_space->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
tilemap_toolbar->add_child(h_empty_space);
|
||||
|
||||
// Grid toggle.
|
||||
toggle_grid_button = memnew(Button);
|
||||
toggle_grid_button->set_flat(true);
|
||||
toggle_grid_button->set_toggle_mode(true);
|
||||
toggle_grid_button->set_tooltip(TTR("Toggle grid visibility."));
|
||||
toggle_grid_button->connect("toggled", callable_mp(this, &TileMapEditor::_on_grid_toggled));
|
||||
tilemap_toolbar->add_child(toggle_grid_button);
|
||||
|
||||
// Advanced settings menu button.
|
||||
advanced_menu_button = memnew(MenuButton);
|
||||
advanced_menu_button->set_flat(true);
|
||||
advanced_menu_button->get_popup()->add_item(TTR("Automatically Replace Tiles with Proxies"));
|
||||
advanced_menu_button->get_popup()->connect("id_pressed", callable_mp(this, &TileMapEditor::_advanced_menu_button_id_pressed));
|
||||
tilemap_toolbar->add_child(advanced_menu_button);
|
||||
|
||||
missing_tileset_label = memnew(Label);
|
||||
missing_tileset_label->set_text(TTR("The edited TileMap node has no TileSet resource."));
|
||||
missing_tileset_label->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
|
@ -82,9 +82,6 @@ private:
|
||||
void _on_random_tile_checkbox_toggled(bool p_pressed);
|
||||
void _on_scattering_spinbox_changed(double p_value);
|
||||
|
||||
Button *toggle_grid_button;
|
||||
void _on_grid_toggled(bool p_pressed);
|
||||
|
||||
void _update_toolbar();
|
||||
|
||||
///// Tilemap editing. /////
|
||||
@ -300,6 +297,7 @@ class TileMapEditor : public VBoxContainer {
|
||||
GDCLASS(TileMapEditor, VBoxContainer);
|
||||
|
||||
private:
|
||||
UndoRedo *undo_redo = EditorNode::get_undo_redo();
|
||||
bool tileset_changed_needs_update = false;
|
||||
ObjectID tile_map_id;
|
||||
|
||||
@ -309,6 +307,12 @@ private:
|
||||
// Toolbar.
|
||||
HBoxContainer *tilemap_toolbar;
|
||||
|
||||
Button *toggle_grid_button;
|
||||
void _on_grid_toggled(bool p_pressed);
|
||||
|
||||
MenuButton *advanced_menu_button;
|
||||
void _advanced_menu_button_id_pressed(int p_id);
|
||||
|
||||
// Bottom panel
|
||||
Label *missing_tileset_label;
|
||||
Tabs *tabs;
|
||||
|
476
editor/plugins/tiles/tile_proxies_manager_dialog.cpp
Normal file
476
editor/plugins/tiles/tile_proxies_manager_dialog.cpp
Normal file
@ -0,0 +1,476 @@
|
||||
/*************************************************************************/
|
||||
/* tile_proxies_manager_dialog.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "tile_proxies_manager_dialog.h"
|
||||
|
||||
#include "editor/editor_scale.h"
|
||||
|
||||
void TileProxiesManagerDialog::_right_clicked(int p_item, Vector2 p_local_mouse_pos, Object *p_item_list) {
|
||||
ItemList *item_list = Object::cast_to<ItemList>(p_item_list);
|
||||
popup_menu->set_size(Vector2(1, 1));
|
||||
popup_menu->set_position(get_position() + item_list->get_global_mouse_position());
|
||||
popup_menu->popup();
|
||||
}
|
||||
|
||||
void TileProxiesManagerDialog::_menu_id_pressed(int p_id) {
|
||||
if (p_id == 0) {
|
||||
// Delete.
|
||||
_delete_selected_bindings();
|
||||
}
|
||||
}
|
||||
|
||||
void TileProxiesManagerDialog::_delete_selected_bindings() {
|
||||
undo_redo->create_action("Remove Tile Proxies");
|
||||
|
||||
Vector<int> source_level_selected = source_level_list->get_selected_items();
|
||||
for (int i = 0; i < source_level_selected.size(); i++) {
|
||||
int key = source_level_list->get_item_metadata(source_level_selected[i]);
|
||||
int val = tile_set->get_source_level_tile_proxy(key);
|
||||
undo_redo->add_do_method(*tile_set, "remove_source_level_tile_proxy", key);
|
||||
undo_redo->add_undo_method(*tile_set, "set_source_level_tile_proxy", key, val);
|
||||
}
|
||||
|
||||
Vector<int> coords_level_selected = coords_level_list->get_selected_items();
|
||||
for (int i = 0; i < coords_level_selected.size(); i++) {
|
||||
Array key = coords_level_list->get_item_metadata(coords_level_selected[i]);
|
||||
Array val = tile_set->get_coords_level_tile_proxy(key[0], key[1]);
|
||||
undo_redo->add_do_method(*tile_set, "remove_coords_level_tile_proxy", key[0], key[1]);
|
||||
undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", key[0], key[1], val[0], val[1]);
|
||||
}
|
||||
|
||||
Vector<int> alternative_level_selected = alternative_level_list->get_selected_items();
|
||||
for (int i = 0; i < alternative_level_selected.size(); i++) {
|
||||
Array key = alternative_level_list->get_item_metadata(alternative_level_selected[i]);
|
||||
Array val = tile_set->get_coords_level_tile_proxy(key[0], key[1]);
|
||||
undo_redo->add_do_method(*tile_set, "remove_alternative_level_tile_proxy", key[0], key[1], key[2]);
|
||||
undo_redo->add_undo_method(*tile_set, "set_alternative_level_tile_proxy", key[0], key[1], key[2], val[0], val[1], val[2]);
|
||||
}
|
||||
undo_redo->add_do_method(this, "_update_lists");
|
||||
undo_redo->add_undo_method(this, "_update_lists");
|
||||
undo_redo->commit_action();
|
||||
|
||||
commited_actions_count += 1;
|
||||
}
|
||||
|
||||
void TileProxiesManagerDialog::_update_lists() {
|
||||
source_level_list->clear();
|
||||
coords_level_list->clear();
|
||||
alternative_level_list->clear();
|
||||
|
||||
Array proxies = tile_set->get_source_level_tile_proxies();
|
||||
for (int i = 0; i < proxies.size(); i++) {
|
||||
Array proxy = proxies[i];
|
||||
String text = vformat("%s", proxy[0]).rpad(5) + "-> " + vformat("%s", proxy[1]);
|
||||
int id = source_level_list->add_item(text);
|
||||
source_level_list->set_item_metadata(id, proxy[0]);
|
||||
}
|
||||
|
||||
proxies = tile_set->get_coords_level_tile_proxies();
|
||||
for (int i = 0; i < proxies.size(); i++) {
|
||||
Array proxy = proxies[i];
|
||||
String text = vformat("%s, %s", proxy[0], proxy[1]).rpad(17) + "-> " + vformat("%s, %s", proxy[2], proxy[3]);
|
||||
int id = coords_level_list->add_item(text);
|
||||
coords_level_list->set_item_metadata(id, proxy.slice(0, 2));
|
||||
}
|
||||
|
||||
proxies = tile_set->get_alternative_level_tile_proxies();
|
||||
for (int i = 0; i < proxies.size(); i++) {
|
||||
Array proxy = proxies[i];
|
||||
String text = vformat("%s, %s, %s", proxy[0], proxy[1], proxy[2]).rpad(24) + "-> " + vformat("%s, %s, %s", proxy[3], proxy[4], proxy[5]);
|
||||
int id = alternative_level_list->add_item(text);
|
||||
alternative_level_list->set_item_metadata(id, proxy.slice(0, 3));
|
||||
}
|
||||
}
|
||||
|
||||
void TileProxiesManagerDialog::_update_enabled_property_editors() {
|
||||
if (from.source_id == TileSet::INVALID_SOURCE) {
|
||||
from.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
|
||||
to.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
|
||||
from.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
|
||||
to.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
|
||||
coords_from_property_editor->hide();
|
||||
coords_to_property_editor->hide();
|
||||
alternative_from_property_editor->hide();
|
||||
alternative_to_property_editor->hide();
|
||||
} else if (from.get_atlas_coords().x == -1 || from.get_atlas_coords().y == -1) {
|
||||
from.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
|
||||
to.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
|
||||
coords_from_property_editor->show();
|
||||
coords_to_property_editor->show();
|
||||
alternative_from_property_editor->hide();
|
||||
alternative_to_property_editor->hide();
|
||||
} else {
|
||||
coords_from_property_editor->show();
|
||||
coords_to_property_editor->show();
|
||||
alternative_from_property_editor->show();
|
||||
alternative_to_property_editor->show();
|
||||
}
|
||||
|
||||
source_from_property_editor->update_property();
|
||||
source_to_property_editor->update_property();
|
||||
coords_from_property_editor->update_property();
|
||||
coords_to_property_editor->update_property();
|
||||
alternative_from_property_editor->update_property();
|
||||
alternative_to_property_editor->update_property();
|
||||
}
|
||||
|
||||
void TileProxiesManagerDialog::_property_changed(const String &p_path, const Variant &p_value, const String &p_name, bool p_changing) {
|
||||
_set(p_path, p_value);
|
||||
}
|
||||
|
||||
void TileProxiesManagerDialog::_add_button_pressed() {
|
||||
if (from.source_id != TileSet::INVALID_SOURCE && to.source_id != TileSet::INVALID_SOURCE) {
|
||||
Vector2i from_coords = from.get_atlas_coords();
|
||||
Vector2i to_coords = to.get_atlas_coords();
|
||||
if (from_coords.x >= 0 && from_coords.y >= 0 && to_coords.x >= 0 && to_coords.y >= 0) {
|
||||
if (from.alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE && to.alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE) {
|
||||
undo_redo->create_action("Create Alternative-level Tile Proxy");
|
||||
undo_redo->add_do_method(*tile_set, "set_alternative_level_tile_proxy", from.source_id, from.get_atlas_coords(), from.alternative_tile, to.source_id, to.get_atlas_coords(), to.alternative_tile);
|
||||
if (tile_set->has_alternative_level_tile_proxy(from.source_id, from.get_atlas_coords(), from.alternative_tile)) {
|
||||
Array a = tile_set->get_alternative_level_tile_proxy(from.source_id, from.get_atlas_coords(), from.alternative_tile);
|
||||
undo_redo->add_undo_method(*tile_set, "set_alternative_level_tile_proxy", to.source_id, to.get_atlas_coords(), to.alternative_tile, a[0], a[1], a[2]);
|
||||
} else {
|
||||
undo_redo->add_undo_method(*tile_set, "remove_alternative_level_tile_proxy", from.source_id, from.get_atlas_coords(), from.alternative_tile);
|
||||
}
|
||||
} else {
|
||||
undo_redo->create_action("Create Coords-level Tile Proxy");
|
||||
undo_redo->add_do_method(*tile_set, "set_coords_level_tile_proxy", from.source_id, from.get_atlas_coords(), to.source_id, to.get_atlas_coords());
|
||||
if (tile_set->has_coords_level_tile_proxy(from.source_id, from.get_atlas_coords())) {
|
||||
Array a = tile_set->get_coords_level_tile_proxy(from.source_id, from.get_atlas_coords());
|
||||
undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", to.source_id, to.get_atlas_coords(), a[0], a[1]);
|
||||
} else {
|
||||
undo_redo->add_undo_method(*tile_set, "remove_coords_level_tile_proxy", from.source_id, from.get_atlas_coords());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
undo_redo->create_action("Create source-level Tile Proxy");
|
||||
undo_redo->add_do_method(*tile_set, "set_source_level_tile_proxy", from.source_id, to.source_id);
|
||||
if (tile_set->has_source_level_tile_proxy(from.source_id)) {
|
||||
undo_redo->add_undo_method(*tile_set, "set_source_level_tile_proxy", to.source_id, tile_set->get_source_level_tile_proxy(from.source_id));
|
||||
} else {
|
||||
undo_redo->add_undo_method(*tile_set, "remove_source_level_tile_proxy", from.source_id);
|
||||
}
|
||||
}
|
||||
undo_redo->add_do_method(this, "_update_lists");
|
||||
undo_redo->add_undo_method(this, "_update_lists");
|
||||
undo_redo->commit_action();
|
||||
commited_actions_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void TileProxiesManagerDialog::_clear_invalid_button_pressed() {
|
||||
undo_redo->create_action("Delete All Invalid Tile Proxies");
|
||||
|
||||
undo_redo->add_do_method(*tile_set, "cleanup_invalid_tile_proxies");
|
||||
|
||||
Array proxies = tile_set->get_source_level_tile_proxies();
|
||||
for (int i = 0; i < proxies.size(); i++) {
|
||||
Array proxy = proxies[i];
|
||||
undo_redo->add_undo_method(*tile_set, "set_source_level_tile_proxy", proxy[0], proxy[1]);
|
||||
}
|
||||
|
||||
proxies = tile_set->get_coords_level_tile_proxies();
|
||||
for (int i = 0; i < proxies.size(); i++) {
|
||||
Array proxy = proxies[i];
|
||||
undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", proxy[0], proxy[1], proxy[2], proxy[3]);
|
||||
}
|
||||
|
||||
proxies = tile_set->get_alternative_level_tile_proxies();
|
||||
for (int i = 0; i < proxies.size(); i++) {
|
||||
Array proxy = proxies[i];
|
||||
undo_redo->add_undo_method(*tile_set, "set_alternative_level_tile_proxy", proxy[0], proxy[1], proxy[2], proxy[3], proxy[4], proxy[5]);
|
||||
}
|
||||
undo_redo->add_do_method(this, "_update_lists");
|
||||
undo_redo->add_undo_method(this, "_update_lists");
|
||||
undo_redo->commit_action();
|
||||
}
|
||||
|
||||
void TileProxiesManagerDialog::_clear_all_button_pressed() {
|
||||
undo_redo->create_action("Delete All Tile Proxies");
|
||||
|
||||
undo_redo->add_do_method(*tile_set, "clear_tile_proxies");
|
||||
|
||||
Array proxies = tile_set->get_source_level_tile_proxies();
|
||||
for (int i = 0; i < proxies.size(); i++) {
|
||||
Array proxy = proxies[i];
|
||||
undo_redo->add_undo_method(*tile_set, "set_source_level_tile_proxy", proxy[0], proxy[1]);
|
||||
}
|
||||
|
||||
proxies = tile_set->get_coords_level_tile_proxies();
|
||||
for (int i = 0; i < proxies.size(); i++) {
|
||||
Array proxy = proxies[i];
|
||||
undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", proxy[0], proxy[1], proxy[2], proxy[3]);
|
||||
}
|
||||
|
||||
proxies = tile_set->get_alternative_level_tile_proxies();
|
||||
for (int i = 0; i < proxies.size(); i++) {
|
||||
Array proxy = proxies[i];
|
||||
undo_redo->add_undo_method(*tile_set, "set_alternative_level_tile_proxy", proxy[0], proxy[1], proxy[2], proxy[3], proxy[4], proxy[5]);
|
||||
}
|
||||
undo_redo->add_do_method(this, "_update_lists");
|
||||
undo_redo->add_undo_method(this, "_update_lists");
|
||||
undo_redo->commit_action();
|
||||
}
|
||||
|
||||
bool TileProxiesManagerDialog::_set(const StringName &p_name, const Variant &p_value) {
|
||||
if (p_name == "from_source") {
|
||||
from.source_id = MAX(int(p_value), -1);
|
||||
} else if (p_name == "from_coords") {
|
||||
from.set_atlas_coords(Vector2i(p_value).max(Vector2i(-1, -1)));
|
||||
} else if (p_name == "from_alternative") {
|
||||
from.alternative_tile = MAX(int(p_value), -1);
|
||||
} else if (p_name == "to_source") {
|
||||
to.source_id = MAX(int(p_value), 0);
|
||||
} else if (p_name == "to_coords") {
|
||||
to.set_atlas_coords(Vector2i(p_value).max(Vector2i(0, 0)));
|
||||
} else if (p_name == "to_alternative") {
|
||||
to.alternative_tile = MAX(int(p_value), 0);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
_update_enabled_property_editors();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TileProxiesManagerDialog::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
if (p_name == "from_source") {
|
||||
r_ret = from.source_id;
|
||||
} else if (p_name == "from_coords") {
|
||||
r_ret = from.get_atlas_coords();
|
||||
} else if (p_name == "from_alternative") {
|
||||
r_ret = from.alternative_tile;
|
||||
} else if (p_name == "to_source") {
|
||||
r_ret = to.source_id;
|
||||
} else if (p_name == "to_coords") {
|
||||
r_ret = to.get_atlas_coords();
|
||||
} else if (p_name == "to_alternative") {
|
||||
r_ret = to.alternative_tile;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TileProxiesManagerDialog::_unhandled_key_input(Ref<InputEvent> p_event) {
|
||||
ERR_FAIL_COND(p_event.is_null());
|
||||
|
||||
if (p_event->is_pressed() && !p_event->is_echo() && (Object::cast_to<InputEventKey>(p_event.ptr()) || Object::cast_to<InputEventJoypadButton>(p_event.ptr()) || Object::cast_to<InputEventAction>(*p_event))) {
|
||||
if (!is_inside_tree() || !is_visible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (popup_menu->activate_item_by_event(p_event, false)) {
|
||||
set_input_as_handled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TileProxiesManagerDialog::cancel_pressed() {
|
||||
for (int i = 0; i < commited_actions_count; i++) {
|
||||
undo_redo->undo();
|
||||
}
|
||||
commited_actions_count = 0;
|
||||
}
|
||||
|
||||
void TileProxiesManagerDialog::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("_update_lists"), &TileProxiesManagerDialog::_update_lists);
|
||||
ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &TileProxiesManagerDialog::_unhandled_key_input);
|
||||
}
|
||||
|
||||
void TileProxiesManagerDialog::update_tile_set(Ref<TileSet> p_tile_set) {
|
||||
ERR_FAIL_COND(!p_tile_set.is_valid());
|
||||
tile_set = p_tile_set;
|
||||
commited_actions_count = 0;
|
||||
_update_lists();
|
||||
}
|
||||
|
||||
TileProxiesManagerDialog::TileProxiesManagerDialog() {
|
||||
// Tile proxy management window.
|
||||
set_title(TTR("Tile Proxies Management"));
|
||||
set_process_unhandled_key_input(true);
|
||||
|
||||
to.source_id = 0;
|
||||
to.set_atlas_coords(Vector2i());
|
||||
to.alternative_tile = 0;
|
||||
|
||||
VBoxContainer *vbox_container = memnew(VBoxContainer);
|
||||
vbox_container->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
vbox_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
add_child(vbox_container);
|
||||
|
||||
Label *source_level_label = memnew(Label);
|
||||
source_level_label->set_text(TTR("Source-level proxies"));
|
||||
vbox_container->add_child(source_level_label);
|
||||
|
||||
source_level_list = memnew(ItemList);
|
||||
source_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
source_level_list->set_select_mode(ItemList::SELECT_MULTI);
|
||||
source_level_list->set_allow_rmb_select(true);
|
||||
source_level_list->connect("item_rmb_selected", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(source_level_list));
|
||||
vbox_container->add_child(source_level_list);
|
||||
|
||||
Label *coords_level_label = memnew(Label);
|
||||
coords_level_label->set_text(TTR("Coords-level proxies"));
|
||||
vbox_container->add_child(coords_level_label);
|
||||
|
||||
coords_level_list = memnew(ItemList);
|
||||
coords_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
coords_level_list->set_select_mode(ItemList::SELECT_MULTI);
|
||||
coords_level_list->set_allow_rmb_select(true);
|
||||
coords_level_list->connect("item_rmb_selected", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(coords_level_list));
|
||||
vbox_container->add_child(coords_level_list);
|
||||
|
||||
Label *alternative_level_label = memnew(Label);
|
||||
alternative_level_label->set_text(TTR("Alternative-level proxies"));
|
||||
vbox_container->add_child(alternative_level_label);
|
||||
|
||||
alternative_level_list = memnew(ItemList);
|
||||
alternative_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
alternative_level_list->set_select_mode(ItemList::SELECT_MULTI);
|
||||
alternative_level_list->set_allow_rmb_select(true);
|
||||
alternative_level_list->connect("item_rmb_selected", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(alternative_level_list));
|
||||
vbox_container->add_child(alternative_level_list);
|
||||
|
||||
popup_menu = memnew(PopupMenu);
|
||||
popup_menu->add_shortcut(ED_GET_SHORTCUT("ui_text_delete"));
|
||||
popup_menu->connect("id_pressed", callable_mp(this, &TileProxiesManagerDialog::_menu_id_pressed));
|
||||
add_child(popup_menu);
|
||||
|
||||
// Add proxy panel.
|
||||
HSeparator *h_separator = memnew(HSeparator);
|
||||
vbox_container->add_child(h_separator);
|
||||
|
||||
Label *add_label = memnew(Label);
|
||||
add_label->set_text(TTR("Add a new tile proxy:"));
|
||||
vbox_container->add_child(add_label);
|
||||
|
||||
HBoxContainer *hboxcontainer = memnew(HBoxContainer);
|
||||
vbox_container->add_child(hboxcontainer);
|
||||
|
||||
// From
|
||||
VBoxContainer *vboxcontainer_from = memnew(VBoxContainer);
|
||||
vboxcontainer_from->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
hboxcontainer->add_child(vboxcontainer_from);
|
||||
|
||||
source_from_property_editor = memnew(EditorPropertyInteger);
|
||||
source_from_property_editor->set_label(TTR("From Source"));
|
||||
source_from_property_editor->set_object_and_property(this, "from_source");
|
||||
source_from_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
|
||||
source_from_property_editor->set_selectable(false);
|
||||
source_from_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
source_from_property_editor->setup(-1, 99999, 1, true, false);
|
||||
vboxcontainer_from->add_child(source_from_property_editor);
|
||||
|
||||
coords_from_property_editor = memnew(EditorPropertyVector2i);
|
||||
coords_from_property_editor->set_label(TTR("From Coords"));
|
||||
coords_from_property_editor->set_object_and_property(this, "from_coords");
|
||||
coords_from_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
|
||||
coords_from_property_editor->set_selectable(false);
|
||||
coords_from_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
coords_from_property_editor->setup(-1, 99999, true);
|
||||
coords_from_property_editor->hide();
|
||||
vboxcontainer_from->add_child(coords_from_property_editor);
|
||||
|
||||
alternative_from_property_editor = memnew(EditorPropertyInteger);
|
||||
alternative_from_property_editor->set_label(TTR("From Alternative"));
|
||||
alternative_from_property_editor->set_object_and_property(this, "from_alternative");
|
||||
alternative_from_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
|
||||
alternative_from_property_editor->set_selectable(false);
|
||||
alternative_from_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
alternative_from_property_editor->setup(-1, 99999, 1, true, false);
|
||||
alternative_from_property_editor->hide();
|
||||
vboxcontainer_from->add_child(alternative_from_property_editor);
|
||||
|
||||
// To
|
||||
VBoxContainer *vboxcontainer_to = memnew(VBoxContainer);
|
||||
vboxcontainer_to->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
hboxcontainer->add_child(vboxcontainer_to);
|
||||
|
||||
source_to_property_editor = memnew(EditorPropertyInteger);
|
||||
source_to_property_editor->set_label(TTR("To Source"));
|
||||
source_to_property_editor->set_object_and_property(this, "to_source");
|
||||
source_to_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
|
||||
source_to_property_editor->set_selectable(false);
|
||||
source_to_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
source_to_property_editor->setup(-1, 99999, 1, true, false);
|
||||
vboxcontainer_to->add_child(source_to_property_editor);
|
||||
|
||||
coords_to_property_editor = memnew(EditorPropertyVector2i);
|
||||
coords_to_property_editor->set_label(TTR("To Coords"));
|
||||
coords_to_property_editor->set_object_and_property(this, "to_coords");
|
||||
coords_to_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
|
||||
coords_to_property_editor->set_selectable(false);
|
||||
coords_to_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
coords_to_property_editor->setup(-1, 99999, true);
|
||||
coords_to_property_editor->hide();
|
||||
vboxcontainer_to->add_child(coords_to_property_editor);
|
||||
|
||||
alternative_to_property_editor = memnew(EditorPropertyInteger);
|
||||
alternative_to_property_editor->set_label(TTR("To Alternative"));
|
||||
alternative_to_property_editor->set_object_and_property(this, "to_alternative");
|
||||
alternative_to_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
|
||||
alternative_to_property_editor->set_selectable(false);
|
||||
alternative_to_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
alternative_to_property_editor->setup(-1, 99999, 1, true, false);
|
||||
alternative_to_property_editor->hide();
|
||||
vboxcontainer_to->add_child(alternative_to_property_editor);
|
||||
|
||||
Button *add_button = memnew(Button);
|
||||
add_button->set_text(TTR("Add"));
|
||||
add_button->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
|
||||
add_button->connect("pressed", callable_mp(this, &TileProxiesManagerDialog::_add_button_pressed));
|
||||
vbox_container->add_child(add_button);
|
||||
|
||||
h_separator = memnew(HSeparator);
|
||||
vbox_container->add_child(h_separator);
|
||||
|
||||
// Generic actions.
|
||||
Label *generic_actions_label = memnew(Label);
|
||||
generic_actions_label->set_text(TTR("Global actions:"));
|
||||
vbox_container->add_child(generic_actions_label);
|
||||
|
||||
hboxcontainer = memnew(HBoxContainer);
|
||||
vbox_container->add_child(hboxcontainer);
|
||||
|
||||
Button *clear_invalid_button = memnew(Button);
|
||||
clear_invalid_button->set_text(TTR("Clear Invalid"));
|
||||
clear_invalid_button->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
|
||||
clear_invalid_button->connect("pressed", callable_mp(this, &TileProxiesManagerDialog::_clear_invalid_button_pressed));
|
||||
hboxcontainer->add_child(clear_invalid_button);
|
||||
|
||||
Button *clear_all_button = memnew(Button);
|
||||
clear_all_button->set_text(TTR("Clear All"));
|
||||
clear_all_button->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
|
||||
clear_all_button->connect("pressed", callable_mp(this, &TileProxiesManagerDialog::_clear_all_button_pressed));
|
||||
hboxcontainer->add_child(clear_all_button);
|
||||
|
||||
h_separator = memnew(HSeparator);
|
||||
vbox_container->add_child(h_separator);
|
||||
}
|
90
editor/plugins/tiles/tile_proxies_manager_dialog.h
Normal file
90
editor/plugins/tiles/tile_proxies_manager_dialog.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*************************************************************************/
|
||||
/* tile_proxies_manager_dialog.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef TILE_PROXIES_MANAGER_DIALOG_H
|
||||
#define TILE_PROXIES_MANAGER_DIALOG_H
|
||||
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_properties.h"
|
||||
|
||||
#include "scene/gui/dialogs.h"
|
||||
#include "scene/gui/item_list.h"
|
||||
#include "scene/resources/tile_set.h"
|
||||
|
||||
class TileProxiesManagerDialog : public ConfirmationDialog {
|
||||
GDCLASS(TileProxiesManagerDialog, ConfirmationDialog);
|
||||
|
||||
private:
|
||||
int commited_actions_count = 0;
|
||||
Ref<TileSet> tile_set;
|
||||
|
||||
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
|
||||
|
||||
TileMapCell from;
|
||||
TileMapCell to;
|
||||
|
||||
// GUI
|
||||
ItemList *source_level_list;
|
||||
ItemList *coords_level_list;
|
||||
ItemList *alternative_level_list;
|
||||
|
||||
EditorPropertyInteger *source_from_property_editor;
|
||||
EditorPropertyVector2i *coords_from_property_editor;
|
||||
EditorPropertyInteger *alternative_from_property_editor;
|
||||
EditorPropertyInteger *source_to_property_editor;
|
||||
EditorPropertyVector2i *coords_to_property_editor;
|
||||
EditorPropertyInteger *alternative_to_property_editor;
|
||||
|
||||
PopupMenu *popup_menu;
|
||||
void _right_clicked(int p_item, Vector2 p_local_mouse_pos, Object *p_item_list);
|
||||
void _menu_id_pressed(int p_id);
|
||||
void _delete_selected_bindings();
|
||||
void _update_lists();
|
||||
void _update_enabled_property_editors();
|
||||
void _property_changed(const String &p_path, const Variant &p_value, const String &p_name, bool p_changing);
|
||||
void _add_button_pressed();
|
||||
|
||||
void _clear_invalid_button_pressed();
|
||||
void _clear_all_button_pressed();
|
||||
|
||||
protected:
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
void _unhandled_key_input(Ref<InputEvent> p_event);
|
||||
virtual void cancel_pressed() override;
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void update_tile_set(Ref<TileSet> p_tile_set);
|
||||
|
||||
TileProxiesManagerDialog();
|
||||
};
|
||||
|
||||
#endif // TILE_PROXIES_MANAGER_DIALOG_H
|
@ -745,7 +745,7 @@ void TileSetAtlasSourceEditor::_update_atlas_view() {
|
||||
button->add_theme_style_override("hover", memnew(StyleBoxEmpty));
|
||||
button->add_theme_style_override("focus", memnew(StyleBoxEmpty));
|
||||
button->add_theme_style_override("pressed", memnew(StyleBoxEmpty));
|
||||
button->connect("pressed", callable_mp(tile_set_atlas_source, &TileSetAtlasSource::create_alternative_tile), varray(tile_id, -1));
|
||||
button->connect("pressed", callable_mp(tile_set_atlas_source, &TileSetAtlasSource::create_alternative_tile), varray(tile_id, TileSetSource::INVALID_TILE_ALTERNATIVE));
|
||||
button->set_rect(Rect2(Vector2(pos.x, pos.y + (y_increment - texture_region_base_size.y) / 2.0), Vector2(texture_region_base_size_min, texture_region_base_size_min)));
|
||||
button->set_expand_icon(true);
|
||||
|
||||
|
@ -65,7 +65,7 @@ private:
|
||||
private:
|
||||
Ref<TileSet> tile_set;
|
||||
TileSetAtlasSource *tile_set_atlas_source = nullptr;
|
||||
int source_id = -1;
|
||||
int source_id = TileSet::INVALID_SOURCE;
|
||||
|
||||
protected:
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
@ -108,7 +108,7 @@ private:
|
||||
|
||||
Ref<TileSet> tile_set;
|
||||
TileSetAtlasSource *tile_set_atlas_source = nullptr;
|
||||
int tile_set_atlas_source_id = -1;
|
||||
int tile_set_atlas_source_id = TileSet::INVALID_SOURCE;
|
||||
|
||||
UndoRedo *undo_redo = EditorNode::get_undo_redo();
|
||||
|
||||
|
@ -50,7 +50,7 @@ void TileSetEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, C
|
||||
|
||||
if (p_from == sources_list) {
|
||||
// Handle dropping a texture in the list of atlas resources.
|
||||
int source_id = -1;
|
||||
int source_id = TileSet::INVALID_SOURCE;
|
||||
int added = 0;
|
||||
Dictionary d = p_data;
|
||||
Vector<String> files = d["files"];
|
||||
@ -77,7 +77,7 @@ void TileSetEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, C
|
||||
}
|
||||
|
||||
// Update the selected source (thus triggering an update).
|
||||
_update_atlas_sources_list(source_id);
|
||||
_update_sources_list(source_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,11 +114,11 @@ bool TileSetEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_dat
|
||||
return false;
|
||||
}
|
||||
|
||||
void TileSetEditor::_update_atlas_sources_list(int force_selected_id) {
|
||||
void TileSetEditor::_update_sources_list(int force_selected_id) {
|
||||
ERR_FAIL_COND(!tile_set.is_valid());
|
||||
|
||||
// Get the previously selected id.
|
||||
int old_selected = -1;
|
||||
int old_selected = TileSet::INVALID_SOURCE;
|
||||
if (sources_list->get_current() >= 0) {
|
||||
int source_id = sources_list->get_item_metadata(sources_list->get_current());
|
||||
if (tile_set->has_source(source_id)) {
|
||||
@ -126,7 +126,7 @@ void TileSetEditor::_update_atlas_sources_list(int force_selected_id) {
|
||||
}
|
||||
}
|
||||
|
||||
int to_select = -1;
|
||||
int to_select = TileSet::INVALID_SOURCE;
|
||||
if (force_selected_id >= 0) {
|
||||
to_select = force_selected_id;
|
||||
} else if (old_selected >= 0) {
|
||||
@ -200,7 +200,7 @@ void TileSetEditor::_update_atlas_sources_list(int force_selected_id) {
|
||||
_source_selected(sources_list->get_current());
|
||||
|
||||
// Synchronize the lists.
|
||||
TilesEditor::get_singleton()->set_atlas_sources_lists_current(sources_list->get_current());
|
||||
TilesEditor::get_singleton()->set_sources_lists_current(sources_list->get_current());
|
||||
}
|
||||
|
||||
void TileSetEditor::_source_selected(int p_source_index) {
|
||||
@ -235,6 +235,23 @@ void TileSetEditor::_source_selected(int p_source_index) {
|
||||
}
|
||||
}
|
||||
|
||||
void TileSetEditor::_source_delete_pressed() {
|
||||
ERR_FAIL_COND(!tile_set.is_valid());
|
||||
|
||||
// Update the selected source.
|
||||
int to_delete = sources_list->get_item_metadata(sources_list->get_current());
|
||||
|
||||
Ref<TileSetSource> source = tile_set->get_source(to_delete);
|
||||
|
||||
// Remove the source.
|
||||
undo_redo->create_action(TTR("Remove source"));
|
||||
undo_redo->add_do_method(*tile_set, "remove_source", to_delete);
|
||||
undo_redo->add_undo_method(*tile_set, "add_source", source, to_delete);
|
||||
undo_redo->commit_action();
|
||||
|
||||
_update_sources_list();
|
||||
}
|
||||
|
||||
void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
|
||||
ERR_FAIL_COND(!tile_set.is_valid());
|
||||
|
||||
@ -251,7 +268,7 @@ void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
|
||||
undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
|
||||
undo_redo->commit_action();
|
||||
|
||||
_update_atlas_sources_list(source_id);
|
||||
_update_sources_list(source_id);
|
||||
} break;
|
||||
case 1: {
|
||||
int source_id = tile_set->get_next_source_id();
|
||||
@ -264,28 +281,26 @@ void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
|
||||
undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
|
||||
undo_redo->commit_action();
|
||||
|
||||
_update_atlas_sources_list(source_id);
|
||||
_update_sources_list(source_id);
|
||||
} break;
|
||||
default:
|
||||
ERR_FAIL();
|
||||
}
|
||||
}
|
||||
|
||||
void TileSetEditor::_source_delete_pressed() {
|
||||
void TileSetEditor::_sources_advanced_menu_id_pressed(int p_id_pressed) {
|
||||
ERR_FAIL_COND(!tile_set.is_valid());
|
||||
|
||||
// Update the selected source.
|
||||
int to_delete = sources_list->get_item_metadata(sources_list->get_current());
|
||||
|
||||
Ref<TileSetSource> source = tile_set->get_source(to_delete);
|
||||
|
||||
// Remove the source.
|
||||
undo_redo->create_action(TTR("Remove source"));
|
||||
undo_redo->add_do_method(*tile_set, "remove_source", to_delete);
|
||||
undo_redo->add_undo_method(*tile_set, "add_source", source, to_delete);
|
||||
undo_redo->commit_action();
|
||||
|
||||
_update_atlas_sources_list();
|
||||
switch (p_id_pressed) {
|
||||
case 0: {
|
||||
atlas_merging_dialog->update_tile_set(tile_set);
|
||||
atlas_merging_dialog->popup_centered_ratio(0.5);
|
||||
} break;
|
||||
case 1: {
|
||||
tile_proxies_manager_dialog->update_tile_set(tile_set);
|
||||
tile_proxies_manager_dialog->popup_centered_ratio(0.5);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void TileSetEditor::_notification(int p_what) {
|
||||
@ -294,6 +309,7 @@ void TileSetEditor::_notification(int p_what) {
|
||||
case NOTIFICATION_THEME_CHANGED:
|
||||
sources_delete_button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
|
||||
sources_add_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
|
||||
sources_advanced_menu_button->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
|
||||
missing_texture_texture = get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons"));
|
||||
break;
|
||||
case NOTIFICATION_INTERNAL_PROCESS:
|
||||
@ -301,7 +317,7 @@ void TileSetEditor::_notification(int p_what) {
|
||||
if (tile_set.is_valid()) {
|
||||
tile_set->set_edited(true);
|
||||
}
|
||||
_update_atlas_sources_list();
|
||||
_update_sources_list();
|
||||
tile_set_changed_needs_update = false;
|
||||
}
|
||||
break;
|
||||
@ -414,7 +430,7 @@ void TileSetEditor::edit(Ref<TileSet> p_tile_set) {
|
||||
// Add the listener again.
|
||||
if (tile_set.is_valid()) {
|
||||
tile_set->connect("changed", callable_mp(this, &TileSetEditor::_tile_set_changed));
|
||||
_update_atlas_sources_list();
|
||||
_update_sources_list();
|
||||
}
|
||||
|
||||
tile_set_atlas_source_editor->hide();
|
||||
@ -447,8 +463,8 @@ TileSetEditor::TileSetEditor() {
|
||||
sources_list->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
sources_list->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
sources_list->connect("item_selected", callable_mp(this, &TileSetEditor::_source_selected));
|
||||
sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_sources_lists_current));
|
||||
sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_atlas_sources_list), varray(sources_list));
|
||||
sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_sources_lists_current));
|
||||
sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_sources_list), varray(sources_list));
|
||||
sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
|
||||
sources_list->set_drag_forwarding(this);
|
||||
split_container_left_side->add_child(sources_list);
|
||||
@ -470,6 +486,19 @@ TileSetEditor::TileSetEditor() {
|
||||
sources_add_button->get_popup()->connect("id_pressed", callable_mp(this, &TileSetEditor::_source_add_id_pressed));
|
||||
sources_bottom_actions->add_child(sources_add_button);
|
||||
|
||||
sources_advanced_menu_button = memnew(MenuButton);
|
||||
sources_advanced_menu_button->set_flat(true);
|
||||
sources_advanced_menu_button->get_popup()->add_item(TTR("Open Atlas Merging Tool"));
|
||||
sources_advanced_menu_button->get_popup()->add_item(TTR("Manage Tile Proxies"));
|
||||
sources_advanced_menu_button->get_popup()->connect("id_pressed", callable_mp(this, &TileSetEditor::_sources_advanced_menu_id_pressed));
|
||||
sources_bottom_actions->add_child(sources_advanced_menu_button);
|
||||
|
||||
atlas_merging_dialog = memnew(AtlasMergingDialog);
|
||||
add_child(atlas_merging_dialog);
|
||||
|
||||
tile_proxies_manager_dialog = memnew(TileProxiesManagerDialog);
|
||||
add_child(tile_proxies_manager_dialog);
|
||||
|
||||
// Right side container.
|
||||
VBoxContainer *split_container_right_side = memnew(VBoxContainer);
|
||||
split_container_right_side->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
@ -489,7 +518,7 @@ TileSetEditor::TileSetEditor() {
|
||||
tile_set_atlas_source_editor = memnew(TileSetAtlasSourceEditor);
|
||||
tile_set_atlas_source_editor->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
tile_set_atlas_source_editor->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
tile_set_atlas_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_atlas_sources_list));
|
||||
tile_set_atlas_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_sources_list));
|
||||
split_container_right_side->add_child(tile_set_atlas_source_editor);
|
||||
tile_set_atlas_source_editor->hide();
|
||||
|
||||
@ -497,7 +526,7 @@ TileSetEditor::TileSetEditor() {
|
||||
tile_set_scenes_collection_source_editor = memnew(TileSetScenesCollectionSourceEditor);
|
||||
tile_set_scenes_collection_source_editor->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
tile_set_scenes_collection_source_editor->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
tile_set_scenes_collection_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_atlas_sources_list));
|
||||
tile_set_scenes_collection_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_sources_list));
|
||||
split_container_right_side->add_child(tile_set_scenes_collection_source_editor);
|
||||
tile_set_scenes_collection_source_editor->hide();
|
||||
|
||||
|
@ -31,8 +31,10 @@
|
||||
#ifndef TILE_SET_EDITOR_H
|
||||
#define TILE_SET_EDITOR_H
|
||||
|
||||
#include "atlas_merging_dialog.h"
|
||||
#include "scene/gui/box_container.h"
|
||||
#include "scene/resources/tile_set.h"
|
||||
#include "tile_proxies_manager_dialog.h"
|
||||
#include "tile_set_atlas_source_editor.h"
|
||||
#include "tile_set_scenes_collection_source_editor.h"
|
||||
|
||||
@ -51,16 +53,21 @@ private:
|
||||
|
||||
UndoRedo *undo_redo = EditorNode::get_undo_redo();
|
||||
|
||||
void _update_atlas_sources_list(int force_selected_id = -1);
|
||||
void _update_sources_list(int force_selected_id = -1);
|
||||
|
||||
// -- Sources management --
|
||||
// Sources management.
|
||||
Button *sources_delete_button;
|
||||
MenuButton *sources_add_button;
|
||||
MenuButton *sources_advanced_menu_button;
|
||||
ItemList *sources_list;
|
||||
Ref<Texture2D> missing_texture_texture;
|
||||
void _source_selected(int p_source_index);
|
||||
void _source_add_id_pressed(int p_id_pressed);
|
||||
void _source_delete_pressed();
|
||||
void _source_add_id_pressed(int p_id_pressed);
|
||||
void _sources_advanced_menu_id_pressed(int p_id_pressed);
|
||||
|
||||
AtlasMergingDialog *atlas_merging_dialog;
|
||||
TileProxiesManagerDialog *tile_proxies_manager_dialog;
|
||||
|
||||
void _tile_set_changed();
|
||||
|
||||
|
@ -118,11 +118,11 @@ void TilesEditor::_update_editors() {
|
||||
CanvasItemEditor::get_singleton()->update_viewport();
|
||||
}
|
||||
|
||||
void TilesEditor::set_atlas_sources_lists_current(int p_current) {
|
||||
void TilesEditor::set_sources_lists_current(int p_current) {
|
||||
atlas_sources_lists_current = p_current;
|
||||
}
|
||||
|
||||
void TilesEditor::synchronize_atlas_sources_list(Object *p_current) {
|
||||
void TilesEditor::synchronize_sources_list(Object *p_current) {
|
||||
ItemList *item_list = Object::cast_to<ItemList>(p_current);
|
||||
ERR_FAIL_COND(!item_list);
|
||||
|
||||
|
@ -76,8 +76,8 @@ public:
|
||||
void forward_canvas_draw_over_viewport(Control *p_overlay) { tilemap_editor->forward_canvas_draw_over_viewport(p_overlay); }
|
||||
|
||||
// To synchronize the atlas sources lists.
|
||||
void set_atlas_sources_lists_current(int p_current);
|
||||
void synchronize_atlas_sources_list(Object *p_current);
|
||||
void set_sources_lists_current(int p_current);
|
||||
void synchronize_sources_list(Object *p_current);
|
||||
|
||||
void set_atlas_view_transform(float p_zoom, Vector2 p_scroll);
|
||||
void synchronize_atlas_view(Object *p_current);
|
||||
|
@ -58,7 +58,7 @@ void TileMapPattern::remove_cell(const Vector2i &p_coords, bool p_update_size) {
|
||||
}
|
||||
|
||||
int TileMapPattern::get_cell_source_id(const Vector2i &p_coords) const {
|
||||
ERR_FAIL_COND_V(!pattern.has(p_coords), -1);
|
||||
ERR_FAIL_COND_V(!pattern.has(p_coords), TileSet::INVALID_SOURCE);
|
||||
|
||||
return pattern[p_coords].source_id;
|
||||
}
|
||||
@ -113,7 +113,7 @@ void TileMapPattern::clear() {
|
||||
};
|
||||
|
||||
void TileMapPattern::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapPattern::set_cell, DEFVAL(-1), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE));
|
||||
ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapPattern::set_cell, DEFVAL(TileSet::INVALID_SOURCE), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE));
|
||||
ClassDB::bind_method(D_METHOD("has_cell", "coords"), &TileMapPattern::has_cell);
|
||||
ClassDB::bind_method(D_METHOD("remove_cell", "coords"), &TileMapPattern::remove_cell);
|
||||
ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords"), &TileMapPattern::get_cell_source_id);
|
||||
@ -513,15 +513,15 @@ void TileMap::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i
|
||||
Vector2i atlas_coords = p_atlas_coords;
|
||||
int alternative_tile = p_alternative_tile;
|
||||
|
||||
if ((source_id == -1 || atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE) &&
|
||||
(source_id != -1 || atlas_coords != TileSetSource::INVALID_ATLAS_COORDS || alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE)) {
|
||||
if ((source_id == TileSet::INVALID_SOURCE || atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE) &&
|
||||
(source_id != TileSet::INVALID_SOURCE || atlas_coords != TileSetSource::INVALID_ATLAS_COORDS || alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE)) {
|
||||
WARN_PRINT("Setting a cell a cell as empty requires both source_id, atlas_coord and alternative_tile to be set to their respective \"invalid\" values. Values were thus changes accordingly.");
|
||||
source_id = -1;
|
||||
source_id = TileSet::INVALID_SOURCE;
|
||||
atlas_coords = TileSetSource::INVALID_ATLAS_COORDS;
|
||||
alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
|
||||
}
|
||||
|
||||
if (!E && source_id == -1) {
|
||||
if (!E && source_id == TileSet::INVALID_SOURCE) {
|
||||
return; // Nothing to do, the tile is already empty.
|
||||
}
|
||||
|
||||
@ -530,7 +530,7 @@ void TileMap::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i
|
||||
|
||||
Map<Vector2i, TileMapQuadrant>::Element *Q = quadrant_map.find(qk);
|
||||
|
||||
if (source_id == -1) {
|
||||
if (source_id == TileSet::INVALID_SOURCE) {
|
||||
// Erase existing cell in the tile map.
|
||||
tile_map.erase(pk);
|
||||
|
||||
@ -579,18 +579,23 @@ void TileMap::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i
|
||||
}
|
||||
}
|
||||
|
||||
int TileMap::get_cell_source_id(const Vector2i &p_coords) const {
|
||||
int TileMap::get_cell_source_id(const Vector2i &p_coords, bool p_use_proxies) const {
|
||||
// Get a cell source id from position
|
||||
const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords);
|
||||
|
||||
if (!E) {
|
||||
return -1;
|
||||
return TileSet::INVALID_SOURCE;
|
||||
}
|
||||
|
||||
if (p_use_proxies && tile_set.is_valid()) {
|
||||
Array proxyed = tile_set->map_tile_proxy(E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
|
||||
return proxyed[0];
|
||||
}
|
||||
|
||||
return E->get().source_id;
|
||||
}
|
||||
|
||||
Vector2i TileMap::get_cell_atlas_coords(const Vector2i &p_coords) const {
|
||||
Vector2i TileMap::get_cell_atlas_coords(const Vector2i &p_coords, bool p_use_proxies) const {
|
||||
// Get a cell source id from position
|
||||
const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords);
|
||||
|
||||
@ -598,10 +603,15 @@ Vector2i TileMap::get_cell_atlas_coords(const Vector2i &p_coords) const {
|
||||
return TileSetSource::INVALID_ATLAS_COORDS;
|
||||
}
|
||||
|
||||
if (p_use_proxies && tile_set.is_valid()) {
|
||||
Array proxyed = tile_set->map_tile_proxy(E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
|
||||
return proxyed[1];
|
||||
}
|
||||
|
||||
return E->get().get_atlas_coords();
|
||||
}
|
||||
|
||||
int TileMap::get_cell_alternative_tile(const Vector2i &p_coords) const {
|
||||
int TileMap::get_cell_alternative_tile(const Vector2i &p_coords, bool p_use_proxies) const {
|
||||
// Get a cell source id from position
|
||||
const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords);
|
||||
|
||||
@ -609,6 +619,11 @@ int TileMap::get_cell_alternative_tile(const Vector2i &p_coords) const {
|
||||
return TileSetSource::INVALID_TILE_ALTERNATIVE;
|
||||
}
|
||||
|
||||
if (p_use_proxies && tile_set.is_valid()) {
|
||||
Array proxyed = tile_set->map_tile_proxy(E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
|
||||
return proxyed[2];
|
||||
}
|
||||
|
||||
return E->get().alternative_tile;
|
||||
}
|
||||
|
||||
@ -697,11 +712,18 @@ void TileMap::set_pattern(Vector2i p_position, const TileMapPattern *p_pattern)
|
||||
}
|
||||
}
|
||||
|
||||
TileMapCell TileMap::get_cell(const Vector2i &p_coords) const {
|
||||
TileMapCell TileMap::get_cell(const Vector2i &p_coords, bool p_use_proxies) const {
|
||||
if (!tile_map.has(p_coords)) {
|
||||
return TileMapCell();
|
||||
} else {
|
||||
return tile_map.find(p_coords)->get();
|
||||
TileMapCell c = tile_map.find(p_coords)->get();
|
||||
if (p_use_proxies && tile_set.is_valid()) {
|
||||
Array proxyed = tile_set->map_tile_proxy(c.source_id, c.get_atlas_coords(), c.alternative_tile);
|
||||
c.source_id = proxyed[0];
|
||||
c.set_atlas_coords(proxyed[1]);
|
||||
c.alternative_tile = proxyed[2];
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
@ -720,7 +742,7 @@ void TileMap::fix_invalid_tiles() {
|
||||
}
|
||||
}
|
||||
for (Set<Vector2i>::Element *E = coords.front(); E; E = E->next()) {
|
||||
set_cell(E->get(), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
set_cell(E->get(), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -799,25 +821,28 @@ void TileMap::_set_tile_data(const Vector<int> &p_data) {
|
||||
SWAP(local[9], local[10]);
|
||||
}
|
||||
#endif
|
||||
// Extracts position in TileMap.
|
||||
int16_t x = decode_uint16(&local[0]);
|
||||
int16_t y = decode_uint16(&local[2]);
|
||||
|
||||
if (format == FORMAT_3) {
|
||||
uint16_t source_id = decode_uint16(&local[4]);
|
||||
uint16_t atlas_coords_x = decode_uint16(&local[6]);
|
||||
uint16_t atlas_coords_y = decode_uint32(&local[8]);
|
||||
uint16_t atlas_coords_y = decode_uint16(&local[8]);
|
||||
uint16_t alternative_tile = decode_uint16(&local[10]);
|
||||
set_cell(Vector2i(x, y), source_id, Vector2i(atlas_coords_x, atlas_coords_y), alternative_tile);
|
||||
} else {
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
uint32_t v = decode_uint32(&local[4]);
|
||||
v &= (1 << 29) - 1;
|
||||
// Previous decated format.
|
||||
|
||||
// We generate an alternative tile number out of the the flags
|
||||
// An option should create the alternative in the tileset for compatibility
|
||||
uint32_t v = decode_uint32(&local[4]);
|
||||
// Extract the transform flags that used to be in the tilemap.
|
||||
bool flip_h = v & (1 << 29);
|
||||
bool flip_v = v & (1 << 30);
|
||||
bool transpose = v & (1 << 31);
|
||||
v &= (1 << 29) - 1;
|
||||
|
||||
// Extract autotile/atlas coords.
|
||||
int16_t coord_x = 0;
|
||||
int16_t coord_y = 0;
|
||||
if (format == FORMAT_2) {
|
||||
@ -825,13 +850,17 @@ void TileMap::_set_tile_data(const Vector<int> &p_data) {
|
||||
coord_y = decode_uint16(&local[10]);
|
||||
}
|
||||
|
||||
int compatibility_alternative_tile = ((int)flip_h) + ((int)flip_v << 1) + ((int)transpose << 2);
|
||||
|
||||
if (tile_set.is_valid()) {
|
||||
v = tile_set->compatibility_get_source_for_tile_id(v);
|
||||
Array a = tile_set->compatibility_tilemap_map(v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose);
|
||||
if (a.size() == 3) {
|
||||
set_cell(Vector2i(x, y), a[0], a[1], a[2]);
|
||||
} else {
|
||||
ERR_PRINT(vformat("No valid tile in Tileset for: tile:%s coords:%s flip_h:%s flip_v:%s transpose:%s", v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose));
|
||||
}
|
||||
} else {
|
||||
int compatibility_alternative_tile = ((int)flip_h) + ((int)flip_v << 1) + ((int)transpose << 2);
|
||||
set_cell(Vector2i(x, y), v, Vector2i(coord_x, coord_y), compatibility_alternative_tile);
|
||||
}
|
||||
|
||||
set_cell(Vector2i(x, y), v, Vector2i(coord_x, coord_y), compatibility_alternative_tile);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -1727,10 +1756,10 @@ void TileMap::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_navigation_visibility_mode", "show_navigation"), &TileMap::set_navigation_visibility_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_navigation_visibility_mode"), &TileMap::get_navigation_visibility_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMap::set_cell, DEFVAL(-1), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE));
|
||||
ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords"), &TileMap::get_cell_source_id);
|
||||
ClassDB::bind_method(D_METHOD("get_cell_atlas_coords", "coords"), &TileMap::get_cell_atlas_coords);
|
||||
ClassDB::bind_method(D_METHOD("get_cell_alternative_tile", "coords"), &TileMap::get_cell_alternative_tile);
|
||||
ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMap::set_cell, DEFVAL(TileSet::INVALID_SOURCE), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE));
|
||||
ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords", "use_proxies"), &TileMap::get_cell_source_id);
|
||||
ClassDB::bind_method(D_METHOD("get_cell_atlas_coords", "coords", "use_proxies"), &TileMap::get_cell_atlas_coords);
|
||||
ClassDB::bind_method(D_METHOD("get_cell_alternative_tile", "coords", "use_proxies"), &TileMap::get_cell_alternative_tile);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("fix_invalid_tiles"), &TileMap::fix_invalid_tiles);
|
||||
ClassDB::bind_method(D_METHOD("get_surrounding_tiles", "coords"), &TileMap::get_surrounding_tiles);
|
||||
|
@ -265,16 +265,16 @@ public:
|
||||
VisibilityMode get_navigation_visibility_mode();
|
||||
|
||||
void set_cell(const Vector2i &p_coords, int p_source_id = -1, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
int get_cell_source_id(const Vector2i &p_coords) const;
|
||||
Vector2i get_cell_atlas_coords(const Vector2i &p_coords) const;
|
||||
int get_cell_alternative_tile(const Vector2i &p_coords) const;
|
||||
int get_cell_source_id(const Vector2i &p_coords, bool p_use_proxies = false) const;
|
||||
Vector2i get_cell_atlas_coords(const Vector2i &p_coords, bool p_use_proxies = false) const;
|
||||
int get_cell_alternative_tile(const Vector2i &p_coords, bool p_use_proxies = false) const;
|
||||
|
||||
TileMapPattern *get_pattern(TypedArray<Vector2i> p_coords_array);
|
||||
Vector2i map_pattern(Vector2i p_position_in_tilemap, Vector2i p_coords_in_pattern, const TileMapPattern *p_pattern);
|
||||
void set_pattern(Vector2i p_position, const TileMapPattern *p_pattern);
|
||||
|
||||
// Not exposed to users
|
||||
TileMapCell get_cell(const Vector2i &p_coords) const;
|
||||
TileMapCell get_cell(const Vector2i &p_coords, bool p_use_proxies = false) const;
|
||||
Map<Vector2i, TileMapQuadrant> &get_quadrant_map();
|
||||
int get_effective_quadrant_size() const;
|
||||
|
||||
|
@ -41,6 +41,8 @@
|
||||
|
||||
/////////////////////////////// TileSet //////////////////////////////////////
|
||||
|
||||
const int TileSet::INVALID_SOURCE = -1;
|
||||
|
||||
const char *TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[] = {
|
||||
"right_side",
|
||||
"right_corner",
|
||||
@ -127,8 +129,8 @@ void TileSet::_compute_next_source_id() {
|
||||
|
||||
// Sources management
|
||||
int TileSet::add_source(Ref<TileSetSource> p_tile_set_source, int p_atlas_source_id_override) {
|
||||
ERR_FAIL_COND_V(!p_tile_set_source.is_valid(), -1);
|
||||
ERR_FAIL_COND_V_MSG(p_atlas_source_id_override >= 0 && (sources.has(p_atlas_source_id_override)), -1, vformat("Cannot create TileSet atlas source. Another atlas source exists with id %d.", p_atlas_source_id_override));
|
||||
ERR_FAIL_COND_V(!p_tile_set_source.is_valid(), TileSet::INVALID_SOURCE);
|
||||
ERR_FAIL_COND_V_MSG(p_atlas_source_id_override >= 0 && (sources.has(p_atlas_source_id_override)), TileSet::INVALID_SOURCE, vformat("Cannot create TileSet atlas source. Another atlas source exists with id %d.", p_atlas_source_id_override));
|
||||
|
||||
int new_source_id = p_atlas_source_id_override >= 0 ? p_atlas_source_id_override : next_source_id;
|
||||
sources[new_source_id] = p_tile_set_source;
|
||||
@ -191,7 +193,7 @@ int TileSet::get_source_count() const {
|
||||
}
|
||||
|
||||
int TileSet::get_source_id(int p_index) const {
|
||||
ERR_FAIL_INDEX_V(p_index, source_ids.size(), -1);
|
||||
ERR_FAIL_INDEX_V(p_index, source_ids.size(), TileSet::INVALID_SOURCE);
|
||||
return source_ids[p_index];
|
||||
}
|
||||
|
||||
@ -607,6 +609,254 @@ Variant::Type TileSet::get_custom_data_type(int p_layer_id) const {
|
||||
return custom_data_layers[p_layer_id].type;
|
||||
}
|
||||
|
||||
void TileSet::set_source_level_tile_proxy(int p_source_from, int p_source_to) {
|
||||
ERR_FAIL_COND(p_source_from == TileSet::INVALID_SOURCE || p_source_to == TileSet::INVALID_SOURCE);
|
||||
|
||||
source_level_proxies[p_source_from] = p_source_to;
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
int TileSet::get_source_level_tile_proxy(int p_source_from) {
|
||||
ERR_FAIL_COND_V(!source_level_proxies.has(p_source_from), TileSet::INVALID_SOURCE);
|
||||
|
||||
return source_level_proxies[p_source_from];
|
||||
}
|
||||
|
||||
bool TileSet::has_source_level_tile_proxy(int p_source_from) {
|
||||
return source_level_proxies.has(p_source_from);
|
||||
}
|
||||
|
||||
void TileSet::remove_source_level_tile_proxy(int p_source_from) {
|
||||
ERR_FAIL_COND(!source_level_proxies.has(p_source_from));
|
||||
|
||||
source_level_proxies.erase(p_source_from);
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void TileSet::set_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_source_to, Vector2i p_coords_to) {
|
||||
ERR_FAIL_COND(p_source_from == TileSet::INVALID_SOURCE || p_source_to == TileSet::INVALID_SOURCE);
|
||||
ERR_FAIL_COND(p_coords_from == TileSetSource::INVALID_ATLAS_COORDS || p_coords_to == TileSetSource::INVALID_ATLAS_COORDS);
|
||||
|
||||
Array from;
|
||||
from.push_back(p_source_from);
|
||||
from.push_back(p_coords_from);
|
||||
|
||||
Array to;
|
||||
to.push_back(p_source_to);
|
||||
to.push_back(p_coords_to);
|
||||
|
||||
coords_level_proxies[from] = to;
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
Array TileSet::get_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from) {
|
||||
Array from;
|
||||
from.push_back(p_source_from);
|
||||
from.push_back(p_coords_from);
|
||||
|
||||
ERR_FAIL_COND_V(!coords_level_proxies.has(from), Array());
|
||||
|
||||
return coords_level_proxies[from];
|
||||
}
|
||||
|
||||
bool TileSet::has_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from) {
|
||||
Array from;
|
||||
from.push_back(p_source_from);
|
||||
from.push_back(p_coords_from);
|
||||
|
||||
return coords_level_proxies.has(from);
|
||||
}
|
||||
|
||||
void TileSet::remove_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from) {
|
||||
Array from;
|
||||
from.push_back(p_source_from);
|
||||
from.push_back(p_coords_from);
|
||||
|
||||
ERR_FAIL_COND(!coords_level_proxies.has(from));
|
||||
|
||||
coords_level_proxies.erase(from);
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void TileSet::set_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from, int p_source_to, Vector2i p_coords_to, int p_alternative_to) {
|
||||
ERR_FAIL_COND(p_source_from == TileSet::INVALID_SOURCE || p_source_to == TileSet::INVALID_SOURCE);
|
||||
ERR_FAIL_COND(p_coords_from == TileSetSource::INVALID_ATLAS_COORDS || p_coords_to == TileSetSource::INVALID_ATLAS_COORDS);
|
||||
|
||||
Array from;
|
||||
from.push_back(p_source_from);
|
||||
from.push_back(p_coords_from);
|
||||
from.push_back(p_alternative_from);
|
||||
|
||||
Array to;
|
||||
to.push_back(p_source_to);
|
||||
to.push_back(p_coords_to);
|
||||
to.push_back(p_alternative_to);
|
||||
|
||||
alternative_level_proxies[from] = to;
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
Array TileSet::get_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from) {
|
||||
Array from;
|
||||
from.push_back(p_source_from);
|
||||
from.push_back(p_coords_from);
|
||||
from.push_back(p_alternative_from);
|
||||
|
||||
ERR_FAIL_COND_V(!alternative_level_proxies.has(from), Array());
|
||||
|
||||
return alternative_level_proxies[from];
|
||||
}
|
||||
|
||||
bool TileSet::has_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from) {
|
||||
Array from;
|
||||
from.push_back(p_source_from);
|
||||
from.push_back(p_coords_from);
|
||||
from.push_back(p_alternative_from);
|
||||
|
||||
return alternative_level_proxies.has(from);
|
||||
}
|
||||
|
||||
void TileSet::remove_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from) {
|
||||
Array from;
|
||||
from.push_back(p_source_from);
|
||||
from.push_back(p_coords_from);
|
||||
from.push_back(p_alternative_from);
|
||||
|
||||
ERR_FAIL_COND(!alternative_level_proxies.has(from));
|
||||
|
||||
alternative_level_proxies.erase(from);
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
Array TileSet::get_source_level_tile_proxies() const {
|
||||
Array output;
|
||||
for (Map<int, int>::Element *E = source_level_proxies.front(); E; E = E->next()) {
|
||||
Array proxy;
|
||||
proxy.push_back(E->key());
|
||||
proxy.push_back(E->get());
|
||||
output.push_back(proxy);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
Array TileSet::get_coords_level_tile_proxies() const {
|
||||
Array output;
|
||||
for (Map<Array, Array>::Element *E = coords_level_proxies.front(); E; E = E->next()) {
|
||||
Array proxy;
|
||||
proxy.append_array(E->key());
|
||||
proxy.append_array(E->get());
|
||||
output.push_back(proxy);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
Array TileSet::get_alternative_level_tile_proxies() const {
|
||||
Array output;
|
||||
for (Map<Array, Array>::Element *E = alternative_level_proxies.front(); E; E = E->next()) {
|
||||
Array proxy;
|
||||
proxy.append_array(E->key());
|
||||
proxy.append_array(E->get());
|
||||
output.push_back(proxy);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
Array TileSet::map_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from) const {
|
||||
Array from;
|
||||
from.push_back(p_source_from);
|
||||
from.push_back(p_coords_from);
|
||||
from.push_back(p_alternative_from);
|
||||
|
||||
// Check if the tile is valid, and if so, don't map the tile and return the input.
|
||||
if (has_source(p_source_from)) {
|
||||
Ref<TileSetSource> source = get_source(p_source_from);
|
||||
if (source->has_tile(p_coords_from) && source->has_alternative_tile(p_coords_from, p_alternative_from)) {
|
||||
return from;
|
||||
}
|
||||
}
|
||||
|
||||
// Source, coords and alternative match.
|
||||
if (alternative_level_proxies.has(from)) {
|
||||
return alternative_level_proxies[from].duplicate();
|
||||
}
|
||||
|
||||
// Source and coords match.
|
||||
from.pop_back();
|
||||
if (coords_level_proxies.has(from)) {
|
||||
Array output = coords_level_proxies[from].duplicate();
|
||||
output.push_back(p_alternative_from);
|
||||
return output;
|
||||
}
|
||||
|
||||
// Source matches.
|
||||
if (source_level_proxies.has(p_source_from)) {
|
||||
Array output;
|
||||
output.push_back(source_level_proxies[p_source_from]);
|
||||
output.push_back(p_coords_from);
|
||||
output.push_back(p_alternative_from);
|
||||
return output;
|
||||
}
|
||||
|
||||
Array output;
|
||||
output.push_back(p_source_from);
|
||||
output.push_back(p_coords_from);
|
||||
output.push_back(p_alternative_from);
|
||||
return output;
|
||||
}
|
||||
|
||||
void TileSet::cleanup_invalid_tile_proxies() {
|
||||
// Source level.
|
||||
Vector<int> source_to_remove;
|
||||
for (Map<int, int>::Element *E = source_level_proxies.front(); E; E = E->next()) {
|
||||
if (has_source(E->key())) {
|
||||
source_to_remove.append(E->key());
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < source_to_remove.size(); i++) {
|
||||
remove_source_level_tile_proxy(source_to_remove[i]);
|
||||
}
|
||||
|
||||
// Coords level.
|
||||
Vector<Array> coords_to_remove;
|
||||
for (Map<Array, Array>::Element *E = coords_level_proxies.front(); E; E = E->next()) {
|
||||
Array a = E->key();
|
||||
if (has_source(a[0]) && get_source(a[0])->has_tile(a[1])) {
|
||||
coords_to_remove.append(a);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < coords_to_remove.size(); i++) {
|
||||
Array a = coords_to_remove[i];
|
||||
remove_coords_level_tile_proxy(a[0], a[1]);
|
||||
}
|
||||
|
||||
// Alternative level.
|
||||
Vector<Array> alternative_to_remove;
|
||||
for (Map<Array, Array>::Element *E = alternative_level_proxies.front(); E; E = E->next()) {
|
||||
Array a = E->key();
|
||||
if (has_source(a[0]) && get_source(a[0])->has_tile(a[1]) && get_source(a[0])->has_alternative_tile(a[1], a[2])) {
|
||||
alternative_to_remove.append(a);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < alternative_to_remove.size(); i++) {
|
||||
Array a = alternative_to_remove[i];
|
||||
remove_alternative_level_tile_proxy(a[0], a[1], a[2]);
|
||||
}
|
||||
}
|
||||
|
||||
void TileSet::clear_tile_proxies() {
|
||||
source_level_proxies.clear();
|
||||
coords_level_proxies.clear();
|
||||
alternative_level_proxies.clear();
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
Vector<Vector2> TileSet::get_tile_shape_polygon() {
|
||||
Vector<Vector2> points;
|
||||
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
|
||||
@ -1539,7 +1789,7 @@ const Vector2i TileSetSource::INVALID_ATLAS_COORDS = Vector2i(-1, -1);
|
||||
const int TileSetSource::INVALID_TILE_ALTERNATIVE = -1;
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
void TileSet::compatibility_conversion() {
|
||||
void TileSet::_compatibility_conversion() {
|
||||
for (Map<int, CompatibilityTileData *>::Element *E = compatibility_data.front(); E; E = E->next()) {
|
||||
CompatibilityTileData *ctd = E->value();
|
||||
|
||||
@ -1551,13 +1801,93 @@ void TileSet::compatibility_conversion() {
|
||||
|
||||
// Handle each tile as a new source. Not optimal but at least it should stay compatible.
|
||||
switch (ctd->tile_mode) {
|
||||
case 0: // SINGLE_TILE
|
||||
// TODO
|
||||
break;
|
||||
case 1: // AUTO_TILE
|
||||
// TODO
|
||||
break;
|
||||
case 2: // ATLAS_TILE
|
||||
case COMPATIBILITY_TILE_MODE_SINGLE_TILE: {
|
||||
atlas_source->set_margins(ctd->region.get_position());
|
||||
atlas_source->set_texture_region_size(ctd->region.get_size());
|
||||
|
||||
Vector2i coords;
|
||||
for (int flags = 0; flags < 8; flags++) {
|
||||
bool flip_h = flags & 1;
|
||||
bool flip_v = flags & 2;
|
||||
bool transpose = flags & 4;
|
||||
|
||||
int alternative_tile = 0;
|
||||
if (!atlas_source->has_tile(coords)) {
|
||||
atlas_source->create_tile(coords);
|
||||
} else {
|
||||
alternative_tile = atlas_source->create_alternative_tile(coords);
|
||||
}
|
||||
|
||||
// Add to the mapping.
|
||||
Array key_array;
|
||||
key_array.push_back(flip_h);
|
||||
key_array.push_back(flip_v);
|
||||
key_array.push_back(transpose);
|
||||
|
||||
Array value_array;
|
||||
value_array.push_back(source_id);
|
||||
value_array.push_back(coords);
|
||||
value_array.push_back(alternative_tile);
|
||||
|
||||
if (!compatibility_tilemap_mapping.has(E->key())) {
|
||||
compatibility_tilemap_mapping[E->key()] = Map<Array, Array>();
|
||||
}
|
||||
compatibility_tilemap_mapping[E->key()][key_array] = value_array;
|
||||
compatibility_tilemap_mapping_tile_modes[E->key()] = COMPATIBILITY_TILE_MODE_SINGLE_TILE;
|
||||
|
||||
TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(coords, alternative_tile));
|
||||
|
||||
tile_data->set_flip_h(flip_h);
|
||||
tile_data->set_flip_v(flip_v);
|
||||
tile_data->set_transpose(transpose);
|
||||
tile_data->tile_set_material(ctd->material);
|
||||
tile_data->set_modulate(ctd->modulate);
|
||||
tile_data->set_z_index(ctd->z_index);
|
||||
|
||||
if (ctd->occluder.is_valid()) {
|
||||
if (get_occlusion_layers_count() < 1) {
|
||||
set_occlusion_layers_count(1);
|
||||
}
|
||||
tile_data->set_occluder(0, ctd->occluder);
|
||||
}
|
||||
if (ctd->navigation.is_valid()) {
|
||||
if (get_navigation_layers_count() < 1) {
|
||||
set_navigation_layers_count(1);
|
||||
}
|
||||
tile_data->set_navigation_polygon(0, ctd->autotile_navpoly_map[coords]);
|
||||
}
|
||||
|
||||
tile_data->set_z_index(ctd->z_index);
|
||||
|
||||
// Add the shapes.
|
||||
if (ctd->shapes.size() > 0) {
|
||||
if (get_physics_layers_count() < 1) {
|
||||
set_physics_layers_count(1);
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < ctd->shapes.size(); k++) {
|
||||
CompatibilityShapeData csd = ctd->shapes[k];
|
||||
if (csd.autotile_coords == coords) {
|
||||
Ref<ConvexPolygonShape2D> convex_shape = csd.shape; // Only ConvexPolygonShape2D are supported, which is the default type used by the 3.x editor
|
||||
if (convex_shape.is_valid()) {
|
||||
Vector<Vector2> polygon = convex_shape->get_points();
|
||||
for (int point_index = 0; point_index < polygon.size(); point_index++) {
|
||||
polygon.write[point_index] = csd.transform.xform(polygon[point_index]);
|
||||
}
|
||||
tile_data->set_collision_polygons_count(0, tile_data->get_collision_polygons_count(0) + 1);
|
||||
int index = tile_data->get_collision_polygons_count(0) - 1;
|
||||
tile_data->set_collision_polygon_one_way(0, index, csd.one_way);
|
||||
tile_data->set_collision_polygon_one_way_margin(0, index, csd.one_way_margin);
|
||||
tile_data->set_collision_polygon_points(0, index, polygon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case COMPATIBILITY_TILE_MODE_AUTO_TILE: {
|
||||
// Not supported. It would need manual conversion.
|
||||
} break;
|
||||
case COMPATIBILITY_TILE_MODE_ATLAS_TILE: {
|
||||
atlas_source->set_margins(ctd->region.get_position());
|
||||
atlas_source->set_separation(Vector2i(ctd->autotile_spacing, ctd->autotile_spacing));
|
||||
atlas_source->set_texture_region_size(ctd->autotile_tile_size);
|
||||
@ -1578,6 +1908,25 @@ void TileSet::compatibility_conversion() {
|
||||
} else {
|
||||
alternative_tile = atlas_source->create_alternative_tile(coords);
|
||||
}
|
||||
|
||||
// Add to the mapping.
|
||||
Array key_array;
|
||||
key_array.push_back(coords);
|
||||
key_array.push_back(flip_h);
|
||||
key_array.push_back(flip_v);
|
||||
key_array.push_back(transpose);
|
||||
|
||||
Array value_array;
|
||||
value_array.push_back(source_id);
|
||||
value_array.push_back(coords);
|
||||
value_array.push_back(alternative_tile);
|
||||
|
||||
if (!compatibility_tilemap_mapping.has(E->key())) {
|
||||
compatibility_tilemap_mapping[E->key()] = Map<Array, Array>();
|
||||
}
|
||||
compatibility_tilemap_mapping[E->key()][key_array] = value_array;
|
||||
compatibility_tilemap_mapping_tile_modes[E->key()] = COMPATIBILITY_TILE_MODE_ATLAS_TILE;
|
||||
|
||||
TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(coords, alternative_tile));
|
||||
|
||||
tile_data->set_flip_h(flip_h);
|
||||
@ -1641,7 +1990,7 @@ void TileSet::compatibility_conversion() {
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
|
||||
// Offset all shapes
|
||||
@ -1655,9 +2004,6 @@ void TileSet::compatibility_conversion() {
|
||||
convex->set_points(points);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the mapping to the map
|
||||
compatibility_source_mapping.insert(E->key(), source_id);
|
||||
}
|
||||
|
||||
// Reset compatibility data
|
||||
@ -1666,14 +2012,50 @@ void TileSet::compatibility_conversion() {
|
||||
}
|
||||
compatibility_data = Map<int, CompatibilityTileData *>();
|
||||
}
|
||||
|
||||
Array TileSet::compatibility_tilemap_map(int p_tile_id, Vector2i p_coords, bool p_flip_h, bool p_flip_v, bool p_transpose) {
|
||||
Array cannot_convert_array;
|
||||
cannot_convert_array.push_back(TileSet::INVALID_SOURCE);
|
||||
cannot_convert_array.push_back(TileSetAtlasSource::INVALID_ATLAS_COORDS);
|
||||
cannot_convert_array.push_back(TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
|
||||
|
||||
if (!compatibility_tilemap_mapping.has(p_tile_id)) {
|
||||
return cannot_convert_array;
|
||||
}
|
||||
|
||||
int tile_mode = compatibility_tilemap_mapping_tile_modes[p_tile_id];
|
||||
switch (tile_mode) {
|
||||
case COMPATIBILITY_TILE_MODE_SINGLE_TILE: {
|
||||
Array a;
|
||||
a.push_back(p_flip_h);
|
||||
a.push_back(p_flip_v);
|
||||
a.push_back(p_transpose);
|
||||
return compatibility_tilemap_mapping[p_tile_id][a];
|
||||
}
|
||||
case COMPATIBILITY_TILE_MODE_AUTO_TILE:
|
||||
return cannot_convert_array;
|
||||
break;
|
||||
case COMPATIBILITY_TILE_MODE_ATLAS_TILE: {
|
||||
Array a;
|
||||
a.push_back(p_coords);
|
||||
a.push_back(p_flip_h);
|
||||
a.push_back(p_flip_v);
|
||||
a.push_back(p_transpose);
|
||||
return compatibility_tilemap_mapping[p_tile_id][a];
|
||||
}
|
||||
default:
|
||||
return cannot_convert_array;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
|
||||
Vector<String> components = String(p_name).split("/", true, 2);
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
// TODO: THIS IS HOW WE CHECK IF WE HAVE A DEPRECATED RESOURCE
|
||||
// This should be moved to a dedicated conversion system
|
||||
// TODO: This should be moved to a dedicated conversion system (see #50691)
|
||||
if (components.size() >= 1 && components[0].is_valid_int()) {
|
||||
int id = components[0].to_int();
|
||||
|
||||
@ -1809,29 +2191,23 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
|
||||
/*
|
||||
// IGNORED FOR NOW, they seem duplicated data compared to the shapes array
|
||||
} else if (what == "shape") {
|
||||
// TODO
|
||||
} else if (what == "shape_offset") {
|
||||
// TODO
|
||||
} else if (what == "shape_transform") {
|
||||
// TODO
|
||||
} else if (what == "shape_one_way") {
|
||||
// TODO
|
||||
} else if (what == "shape_one_way_margin") {
|
||||
// TODO
|
||||
}
|
||||
// IGNORED FOR NOW, maybe useless ?
|
||||
else if (what == "occluder_offset") {
|
||||
// Not
|
||||
} else if (what == "navigation_offset") {
|
||||
// TODO
|
||||
}
|
||||
*/
|
||||
|
||||
} else if (what == "z_index") {
|
||||
ctd->z_index = p_value;
|
||||
|
||||
// TODO: remove the conversion from here, it's not where it should be done
|
||||
compatibility_conversion();
|
||||
// TODO: remove the conversion from here, it's not where it should be done (see #50691)
|
||||
_compatibility_conversion();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@ -1966,6 +2342,31 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
|
||||
add_source(p_value, source_id);
|
||||
}
|
||||
return true;
|
||||
} else if (components.size() == 2 && components[0] == "tile_proxies") {
|
||||
ERR_FAIL_COND_V(p_value.get_type() != Variant::ARRAY, false);
|
||||
Array a = p_value;
|
||||
ERR_FAIL_COND_V(a.size() % 2 != 0, false);
|
||||
if (components[1] == "source_level") {
|
||||
for (int i = 0; i < a.size(); i += 2) {
|
||||
set_source_level_tile_proxy(a[i], a[i + 1]);
|
||||
}
|
||||
return true;
|
||||
} else if (components[1] == "coords_level") {
|
||||
for (int i = 0; i < a.size(); i += 2) {
|
||||
Array key = a[i];
|
||||
Array value = a[i + 1];
|
||||
set_coords_level_tile_proxy(key[0], key[1], value[0], value[1]);
|
||||
}
|
||||
return true;
|
||||
} else if (components[1] == "alternative_level") {
|
||||
for (int i = 0; i < a.size(); i += 2) {
|
||||
Array key = a[i];
|
||||
Array value = a[i + 1];
|
||||
set_alternative_level_tile_proxy(key[0], key[1], key[2], value[0], value[1], value[2]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
@ -2065,6 +2466,33 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (components.size() == 2 && components[0] == "tile_proxies") {
|
||||
if (components[1] == "source_level") {
|
||||
Array a;
|
||||
for (Map<int, int>::Element *E = source_level_proxies.front(); E; E = E->next()) {
|
||||
a.push_back(E->key());
|
||||
a.push_back(E->get());
|
||||
}
|
||||
r_ret = a;
|
||||
return true;
|
||||
} else if (components[1] == "coords_level") {
|
||||
Array a;
|
||||
for (Map<Array, Array>::Element *E = coords_level_proxies.front(); E; E = E->next()) {
|
||||
a.push_back(E->key());
|
||||
a.push_back(E->get());
|
||||
}
|
||||
r_ret = a;
|
||||
return true;
|
||||
} else if (components[1] == "alternative_level") {
|
||||
Array a;
|
||||
for (Map<Array, Array>::Element *E = alternative_level_proxies.front(); E; E = E->next()) {
|
||||
a.push_back(E->key());
|
||||
a.push_back(E->get());
|
||||
}
|
||||
r_ret = a;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -2138,12 +2566,19 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
|
||||
p_list->push_back(PropertyInfo(Variant::INT, vformat("sources/%d", E_source->key()), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
|
||||
}
|
||||
|
||||
// Tile Proxies.
|
||||
// Note: proxies need to be set after sources are set.
|
||||
p_list->push_back(PropertyInfo(Variant::NIL, "Tile Proxies", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
|
||||
p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/source_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
|
||||
p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/coords_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
|
||||
p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/alternative_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
|
||||
}
|
||||
|
||||
void TileSet::_bind_methods() {
|
||||
// Sources management.
|
||||
ClassDB::bind_method(D_METHOD("get_next_source_id"), &TileSet::get_next_source_id);
|
||||
ClassDB::bind_method(D_METHOD("add_source", "atlas_source_id_override"), &TileSet::add_source, DEFVAL(-1));
|
||||
ClassDB::bind_method(D_METHOD("add_source", "atlas_source_id_override"), &TileSet::add_source, DEFVAL(TileSet::INVALID_SOURCE));
|
||||
ClassDB::bind_method(D_METHOD("remove_source", "source_id"), &TileSet::remove_source);
|
||||
ClassDB::bind_method(D_METHOD("set_source_id", "source_id"), &TileSet::set_source_id);
|
||||
ClassDB::bind_method(D_METHOD("get_source_count"), &TileSet::get_source_count);
|
||||
@ -2212,6 +2647,27 @@ void TileSet::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_custom_data_layers_count", "custom_data_layers_count"), &TileSet::set_custom_data_layers_count);
|
||||
ClassDB::bind_method(D_METHOD("get_custom_data_layers_count"), &TileSet::get_custom_data_layers_count);
|
||||
|
||||
// Tile proxies
|
||||
ClassDB::bind_method(D_METHOD("set_source_level_tile_proxy", "source_from", "source_to"), &TileSet::set_source_level_tile_proxy);
|
||||
ClassDB::bind_method(D_METHOD("get_source_level_tile_proxy", "source_from"), &TileSet::get_source_level_tile_proxy);
|
||||
ClassDB::bind_method(D_METHOD("has_source_level_tile_proxy", "source_from"), &TileSet::has_source_level_tile_proxy);
|
||||
ClassDB::bind_method(D_METHOD("remove_source_level_tile_proxy", "source_from"), &TileSet::remove_source_level_tile_proxy);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_coords_level_tile_proxy", "p_source_from", "coords_from", "source_to", "coords_to"), &TileSet::set_coords_level_tile_proxy);
|
||||
ClassDB::bind_method(D_METHOD("get_coords_level_tile_proxy", "source_from", "coords_from"), &TileSet::get_coords_level_tile_proxy);
|
||||
ClassDB::bind_method(D_METHOD("has_coords_level_tile_proxy", "source_from", "coords_from"), &TileSet::has_coords_level_tile_proxy);
|
||||
ClassDB::bind_method(D_METHOD("remove_coords_level_tile_proxy", "source_from", "coords_from"), &TileSet::remove_coords_level_tile_proxy);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_alternative_level_tile_proxy", "source_from", "coords_from", "alternative_from", "source_to", "coords_to", "alternative_to"), &TileSet::set_alternative_level_tile_proxy);
|
||||
ClassDB::bind_method(D_METHOD("get_alternative_level_tile_proxy", "source_from", "coords_from", "alternative_from"), &TileSet::get_alternative_level_tile_proxy);
|
||||
ClassDB::bind_method(D_METHOD("has_alternative_level_tile_proxy", "source_from", "coords_from", "alternative_from"), &TileSet::has_alternative_level_tile_proxy);
|
||||
ClassDB::bind_method(D_METHOD("remove_alternative_level_tile_proxy", "source_from", "coords_from", "alternative_from"), &TileSet::remove_alternative_level_tile_proxy);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("map_tile_proxy", "source_from", "coords_from", "alternative_from"), &TileSet::map_tile_proxy);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("cleanup_invalid_tile_proxies"), &TileSet::cleanup_invalid_tile_proxies);
|
||||
ClassDB::bind_method(D_METHOD("clear_tile_proxies"), &TileSet::clear_tile_proxies);
|
||||
|
||||
ADD_GROUP("Rendering", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uv_clipping"), "set_uv_clipping", "is_uv_clipping");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "y_sorting"), "set_y_sorting", "is_y_sorting");
|
||||
@ -2755,8 +3211,8 @@ void TileSetAtlasSource::clear_tiles_outside_texture() {
|
||||
}
|
||||
|
||||
int TileSetAtlasSource::create_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_id_override) {
|
||||
ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), -1, vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
|
||||
ERR_FAIL_COND_V_MSG(p_alternative_id_override >= 0 && tiles[p_atlas_coords].alternatives.has(p_alternative_id_override), -1, vformat("Cannot create alternative tile. Another alternative exists with id %d.", p_alternative_id_override));
|
||||
ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), TileSetSource::INVALID_TILE_ALTERNATIVE, vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
|
||||
ERR_FAIL_COND_V_MSG(p_alternative_id_override >= 0 && tiles[p_atlas_coords].alternatives.has(p_alternative_id_override), TileSetSource::INVALID_TILE_ALTERNATIVE, vformat("Cannot create alternative tile. Another alternative exists with id %d.", p_alternative_id_override));
|
||||
|
||||
int new_alternative_id = p_alternative_id_override >= 0 ? p_alternative_id_override : tiles[p_atlas_coords].next_alternative_id;
|
||||
|
||||
@ -2809,7 +3265,7 @@ bool TileSetAtlasSource::has_alternative_tile(const Vector2i p_atlas_coords, int
|
||||
}
|
||||
|
||||
int TileSetAtlasSource::get_next_alternative_tile_id(const Vector2i p_atlas_coords) const {
|
||||
ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), -1, vformat("The TileSetAtlasSource atlas has no tile at %s.", String(p_atlas_coords)));
|
||||
ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), TileSetSource::INVALID_TILE_ALTERNATIVE, vformat("The TileSetAtlasSource atlas has no tile at %s.", String(p_atlas_coords)));
|
||||
return tiles[p_atlas_coords].next_alternative_id;
|
||||
}
|
||||
|
||||
@ -2819,8 +3275,8 @@ int TileSetAtlasSource::get_alternative_tiles_count(const Vector2i p_atlas_coord
|
||||
}
|
||||
|
||||
int TileSetAtlasSource::get_alternative_tile_id(const Vector2i p_atlas_coords, int p_index) const {
|
||||
ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), -1, vformat("The TileSetAtlasSource atlas has no tile at %s.", String(p_atlas_coords)));
|
||||
ERR_FAIL_INDEX_V(p_index, tiles[p_atlas_coords].alternatives_ids.size(), -1);
|
||||
ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), TileSetSource::INVALID_TILE_ALTERNATIVE, vformat("The TileSetAtlasSource atlas has no tile at %s.", String(p_atlas_coords)));
|
||||
ERR_FAIL_INDEX_V(p_index, tiles[p_atlas_coords].alternatives_ids.size(), TileSetSource::INVALID_TILE_ALTERNATIVE);
|
||||
|
||||
return tiles[p_atlas_coords].alternatives_ids[p_index];
|
||||
}
|
||||
@ -2861,7 +3317,7 @@ void TileSetAtlasSource::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_tile_at_coords", "atlas_coords"), &TileSetAtlasSource::get_tile_at_coords);
|
||||
|
||||
// Alternative tiles
|
||||
ClassDB::bind_method(D_METHOD("create_alternative_tile", "atlas_coords", "alternative_id_override"), &TileSetAtlasSource::create_alternative_tile, DEFVAL(-1));
|
||||
ClassDB::bind_method(D_METHOD("create_alternative_tile", "atlas_coords", "alternative_id_override"), &TileSetAtlasSource::create_alternative_tile, DEFVAL(INVALID_TILE_ALTERNATIVE));
|
||||
ClassDB::bind_method(D_METHOD("remove_alternative_tile", "atlas_coords", "alternative_tile"), &TileSetAtlasSource::remove_alternative_tile);
|
||||
ClassDB::bind_method(D_METHOD("set_alternative_tile_id", "atlas_coords", "alternative_tile", "new_id"), &TileSetAtlasSource::set_alternative_tile_id);
|
||||
ClassDB::bind_method(D_METHOD("has_alternative_tile", "atlas_coords", "alternative_tile"), &TileSetAtlasSource::has_alternative_tile);
|
||||
@ -2948,7 +3404,7 @@ bool TileSetScenesCollectionSource::has_alternative_tile(const Vector2i p_atlas_
|
||||
}
|
||||
|
||||
int TileSetScenesCollectionSource::create_scene_tile(Ref<PackedScene> p_packed_scene, int p_id_override) {
|
||||
ERR_FAIL_COND_V_MSG(p_id_override >= 0 && scenes.has(p_id_override), -1, vformat("Cannot create scene tile. Another scene tile exists with id %d.", p_id_override));
|
||||
ERR_FAIL_COND_V_MSG(p_id_override >= 0 && scenes.has(p_id_override), INVALID_TILE_ALTERNATIVE, vformat("Cannot create scene tile. Another scene tile exists with id %d.", p_id_override));
|
||||
|
||||
int new_scene_id = p_id_override >= 0 ? p_id_override : next_scene_id;
|
||||
|
||||
@ -3096,7 +3552,7 @@ void TileSetScenesCollectionSource::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_scene_tiles_count"), &TileSetScenesCollectionSource::get_scene_tiles_count);
|
||||
ClassDB::bind_method(D_METHOD("get_scene_tile_id", "index"), &TileSetScenesCollectionSource::get_scene_tile_id);
|
||||
ClassDB::bind_method(D_METHOD("has_scene_tile_id", "id"), &TileSetScenesCollectionSource::has_scene_tile_id);
|
||||
ClassDB::bind_method(D_METHOD("create_scene_tile", "packed_scene", "id_override"), &TileSetScenesCollectionSource::create_scene_tile, DEFVAL(-1));
|
||||
ClassDB::bind_method(D_METHOD("create_scene_tile", "packed_scene", "id_override"), &TileSetScenesCollectionSource::create_scene_tile, DEFVAL(INVALID_TILE_ALTERNATIVE));
|
||||
ClassDB::bind_method(D_METHOD("set_scene_tile_id", "id", "new_id"), &TileSetScenesCollectionSource::set_scene_tile_id);
|
||||
ClassDB::bind_method(D_METHOD("set_scene_tile_scene", "id", "packed_scene"), &TileSetScenesCollectionSource::set_scene_tile_scene);
|
||||
ClassDB::bind_method(D_METHOD("get_scene_tile_scene", "id"), &TileSetScenesCollectionSource::get_scene_tile_scene);
|
||||
@ -3919,7 +4375,7 @@ void TileSetPluginAtlasRendering::update_dirty_quadrants(TileMap *p_tile_map, Se
|
||||
|
||||
// Iterate over the cells of the quadrant.
|
||||
for (Map<Vector2i, Vector2i, TileMapQuadrant::CoordsWorldComparator>::Element *E_cell = q.world_to_map.front(); E_cell; E_cell = E_cell->next()) {
|
||||
TileMapCell c = p_tile_map->get_cell(E_cell->value());
|
||||
TileMapCell c = p_tile_map->get_cell(E_cell->value(), true);
|
||||
|
||||
TileSetSource *source;
|
||||
if (tile_set->has_source(c.source_id)) {
|
||||
@ -4059,7 +4515,7 @@ void TileSetPluginAtlasRendering::draw_quadrant_debug(TileMap *p_tile_map, TileM
|
||||
RenderingServer *rs = RenderingServer::get_singleton();
|
||||
Vector2 quadrant_pos = p_tile_map->map_to_world(p_quadrant->coords * p_tile_map->get_effective_quadrant_size());
|
||||
for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) {
|
||||
const TileMapCell &c = p_tile_map->get_cell(E_cell->get());
|
||||
const TileMapCell &c = p_tile_map->get_cell(E_cell->get(), true);
|
||||
|
||||
TileSetSource *source;
|
||||
if (tile_set->has_source(c.source_id)) {
|
||||
@ -4151,7 +4607,7 @@ void TileSetPluginAtlasPhysics::update_dirty_quadrants(TileMap *p_tile_map, Self
|
||||
}
|
||||
|
||||
for (Set<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) {
|
||||
TileMapCell c = p_tile_map->get_cell(E_cell->get());
|
||||
TileMapCell c = p_tile_map->get_cell(E_cell->get(), true);
|
||||
|
||||
TileSetSource *source;
|
||||
if (tile_set->has_source(c.source_id)) {
|
||||
@ -4276,7 +4732,7 @@ void TileSetPluginAtlasPhysics::draw_quadrant_debug(TileMap *p_tile_map, TileMap
|
||||
|
||||
Color debug_collision_color = p_tile_map->get_tree()->get_debug_collisions_color();
|
||||
for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) {
|
||||
TileMapCell c = p_tile_map->get_cell(E_cell->get());
|
||||
TileMapCell c = p_tile_map->get_cell(E_cell->get(), true);
|
||||
|
||||
Transform2D xform;
|
||||
xform.set_origin(p_tile_map->map_to_world(E_cell->get()) - quadrant_pos);
|
||||
@ -4370,7 +4826,7 @@ void TileSetPluginAtlasNavigation::update_dirty_quadrants(TileMap *p_tile_map, S
|
||||
|
||||
// Get the navigation polygons and create regions.
|
||||
for (Set<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) {
|
||||
TileMapCell c = p_tile_map->get_cell(E_cell->get());
|
||||
TileMapCell c = p_tile_map->get_cell(E_cell->get(), true);
|
||||
|
||||
TileSetSource *source;
|
||||
if (tile_set->has_source(c.source_id)) {
|
||||
@ -4455,7 +4911,7 @@ void TileSetPluginAtlasNavigation::draw_quadrant_debug(TileMap *p_tile_map, Tile
|
||||
Vector2 quadrant_pos = p_tile_map->map_to_world(p_quadrant->coords * p_tile_map->get_effective_quadrant_size());
|
||||
|
||||
for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) {
|
||||
TileMapCell c = p_tile_map->get_cell(E_cell->get());
|
||||
TileMapCell c = p_tile_map->get_cell(E_cell->get(), true);
|
||||
|
||||
TileSetSource *source;
|
||||
if (tile_set->has_source(c.source_id)) {
|
||||
@ -4526,7 +4982,7 @@ void TileSetPluginScenesCollections::update_dirty_quadrants(TileMap *p_tile_map,
|
||||
|
||||
// Recreate the scenes.
|
||||
for (Set<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) {
|
||||
const TileMapCell &c = p_tile_map->get_cell(E_cell->get());
|
||||
const TileMapCell &c = p_tile_map->get_cell(E_cell->get(), true);
|
||||
|
||||
TileSetSource *source;
|
||||
if (tile_set->has_source(c.source_id)) {
|
||||
@ -4585,7 +5041,7 @@ void TileSetPluginScenesCollections::draw_quadrant_debug(TileMap *p_tile_map, Ti
|
||||
RenderingServer *rs = RenderingServer::get_singleton();
|
||||
Vector2 quadrant_pos = p_tile_map->map_to_world(p_quadrant->coords * p_tile_map->get_effective_quadrant_size());
|
||||
for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) {
|
||||
const TileMapCell &c = p_tile_map->get_cell(E_cell->get());
|
||||
const TileMapCell &c = p_tile_map->get_cell(E_cell->get(), true);
|
||||
|
||||
TileSetSource *source;
|
||||
if (tile_set->has_source(c.source_id)) {
|
||||
|
@ -79,15 +79,15 @@ private:
|
||||
Vector2 tex_offset;
|
||||
Ref<ShaderMaterial> material;
|
||||
Rect2 region;
|
||||
int tile_mode;
|
||||
Color modulate;
|
||||
int tile_mode = 0;
|
||||
Color modulate = Color(1, 1, 1);
|
||||
|
||||
// Atlas or autotiles data
|
||||
int autotile_bitmask_mode;
|
||||
int autotile_bitmask_mode = 0;
|
||||
Vector2 autotile_icon_coordinate;
|
||||
Size2i autotile_tile_size = Size2i(16, 16);
|
||||
|
||||
int autotile_spacing;
|
||||
int autotile_spacing = 0;
|
||||
Map<Vector2i, int> autotile_bitmask_flags;
|
||||
Map<Vector2i, Ref<OccluderPolygon2D>> autotile_occluder_map;
|
||||
Map<Vector2i, Ref<NavigationPolygon>> autotile_navpoly_map;
|
||||
@ -99,23 +99,29 @@ private:
|
||||
Vector2 occluder_offset;
|
||||
Ref<NavigationPolygon> navigation;
|
||||
Vector2 navigation_offset;
|
||||
int z_index;
|
||||
int z_index = 0;
|
||||
};
|
||||
|
||||
Map<int, CompatibilityTileData *> compatibility_data = Map<int, CompatibilityTileData *>();
|
||||
Map<int, int> compatibility_source_mapping = Map<int, int>();
|
||||
enum CompatibilityTileMode {
|
||||
COMPATIBILITY_TILE_MODE_SINGLE_TILE = 0,
|
||||
COMPATIBILITY_TILE_MODE_AUTO_TILE,
|
||||
COMPATIBILITY_TILE_MODE_ATLAS_TILE,
|
||||
};
|
||||
|
||||
private:
|
||||
void compatibility_conversion();
|
||||
Map<int, CompatibilityTileData *> compatibility_data;
|
||||
Map<int, int> compatibility_tilemap_mapping_tile_modes;
|
||||
Map<int, Map<Array, Array>> compatibility_tilemap_mapping;
|
||||
|
||||
void _compatibility_conversion();
|
||||
|
||||
public:
|
||||
int compatibility_get_source_for_tile_id(int p_old_source) {
|
||||
return compatibility_source_mapping[p_old_source];
|
||||
};
|
||||
|
||||
// Format of output array [source_id, atlas_coords, alternative]
|
||||
Array compatibility_tilemap_map(int p_tile_id, Vector2i p_coords, bool p_flip_h, bool p_flip_v, bool p_transpose);
|
||||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
public:
|
||||
static const int INVALID_SOURCE; // -1;
|
||||
|
||||
enum CellNeighbor {
|
||||
CELL_NEIGHBOR_RIGHT_SIDE = 0,
|
||||
CELL_NEIGHBOR_RIGHT_CORNER,
|
||||
@ -165,7 +171,6 @@ public:
|
||||
TILE_OFFSET_AXIS_VERTICAL,
|
||||
};
|
||||
|
||||
public:
|
||||
struct PackedSceneSource {
|
||||
Ref<PackedScene> scene;
|
||||
Vector2 offset;
|
||||
@ -246,6 +251,11 @@ private:
|
||||
void _compute_next_source_id();
|
||||
void _source_changed();
|
||||
|
||||
// Tile proxies
|
||||
Map<int, int> source_level_proxies;
|
||||
Map<Array, Array> coords_level_proxies;
|
||||
Map<Array, Array> alternative_level_proxies;
|
||||
|
||||
// Helpers
|
||||
Vector<Point2> _get_square_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
|
||||
Vector<Point2> _get_square_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
|
||||
@ -341,6 +351,31 @@ public:
|
||||
void set_custom_data_type(int p_layer_id, Variant::Type p_value);
|
||||
Variant::Type get_custom_data_type(int p_layer_id) const;
|
||||
|
||||
// Tiles proxies.
|
||||
void set_source_level_tile_proxy(int p_source_from, int p_source_to);
|
||||
int get_source_level_tile_proxy(int p_source_from);
|
||||
bool has_source_level_tile_proxy(int p_source_from);
|
||||
void remove_source_level_tile_proxy(int p_source_from);
|
||||
|
||||
void set_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_source_to, Vector2i p_coords_to);
|
||||
Array get_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from);
|
||||
bool has_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from);
|
||||
void remove_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from);
|
||||
|
||||
void set_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from, int p_source_to, Vector2i p_coords_to, int p_alternative_to);
|
||||
Array get_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from);
|
||||
bool has_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from);
|
||||
void remove_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from);
|
||||
|
||||
Array get_source_level_tile_proxies() const;
|
||||
Array get_coords_level_tile_proxies() const;
|
||||
Array get_alternative_level_tile_proxies() const;
|
||||
|
||||
Array map_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from) const;
|
||||
|
||||
void cleanup_invalid_tile_proxies();
|
||||
void clear_tile_proxies();
|
||||
|
||||
// Helpers
|
||||
Vector<Vector2> get_tile_shape_polygon();
|
||||
void draw_tile_shape(CanvasItem *p_canvas_item, Rect2 p_region, Color p_color, bool p_filled = false, Ref<Texture2D> p_texture = Ref<Texture2D>());
|
||||
|
Loading…
Reference in New Issue
Block a user