summaryrefslogtreecommitdiffstats
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/tile_map.compat.inc10
-rw-r--r--scene/2d/tile_map.cpp808
-rw-r--r--scene/2d/tile_map.h16
-rw-r--r--scene/2d/tile_map_layer.cpp646
-rw-r--r--scene/2d/tile_map_layer.h60
-rw-r--r--scene/main/canvas_item.cpp2
-rw-r--r--scene/main/canvas_item.h4
-rw-r--r--scene/resources/tile_set.cpp626
-rw-r--r--scene/resources/tile_set.h7
9 files changed, 1103 insertions, 1076 deletions
diff --git a/scene/2d/tile_map.compat.inc b/scene/2d/tile_map.compat.inc
index ed216173c7..04937bdf7e 100644
--- a/scene/2d/tile_map.compat.inc
+++ b/scene/2d/tile_map.compat.inc
@@ -42,10 +42,20 @@ int TileMap::_get_quadrant_size_compat_81070() const {
return get_rendering_quadrant_size();
}
+TileMap::VisibilityMode TileMap::_get_collision_visibility_mode_bind_compat_87115() {
+ return get_collision_visibility_mode();
+}
+
+TileMap::VisibilityMode TileMap::_get_navigation_visibility_mode_bind_compat_87115() {
+ return get_navigation_visibility_mode();
+}
+
void TileMap::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("get_used_rect"), &TileMap::_get_used_rect_bind_compat_78328);
ClassDB::bind_compatibility_method(D_METHOD("set_quadrant_size", "quadrant_size"), &TileMap::_set_quadrant_size_compat_81070);
ClassDB::bind_compatibility_method(D_METHOD("get_quadrant_size"), &TileMap::_get_quadrant_size_compat_81070);
+ ClassDB::bind_compatibility_method(D_METHOD("get_collision_visibility_mode"), &TileMap::_get_collision_visibility_mode_bind_compat_87115);
+ ClassDB::bind_compatibility_method(D_METHOD("get_navigation_visibility_mode"), &TileMap::_get_navigation_visibility_mode_bind_compat_87115);
}
#endif
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index decbbab476..24eefce99d 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -167,7 +167,7 @@ void TileMap::set_selected_layer(int p_layer_id) {
emit_signal(CoreStringNames::get_singleton()->changed);
// Update the layers modulation.
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_SELECTED_LAYER);
}
}
@@ -178,45 +178,9 @@ int TileMap::get_selected_layer() const {
void TileMap::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- for (Ref<TileMapLayer> &layer : layers) {
- layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_IN_TREE);
- }
- } break;
-
- case NOTIFICATION_EXIT_TREE: {
- for (Ref<TileMapLayer> &layer : layers) {
- layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_IN_TREE);
- }
- } break;
-
- case TileMap::NOTIFICATION_ENTER_CANVAS: {
- for (Ref<TileMapLayer> &layer : layers) {
- layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_IN_CANVAS);
- }
- } break;
-
- case TileMap::NOTIFICATION_EXIT_CANVAS: {
- for (Ref<TileMapLayer> &layer : layers) {
- layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_IN_CANVAS);
- }
- } break;
-
- case NOTIFICATION_DRAW: {
- // Rendering.
- if (tile_set.is_valid()) {
- RenderingServer::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), is_y_sort_enabled());
- }
- } break;
-
- case TileMap::NOTIFICATION_VISIBILITY_CHANGED: {
- for (Ref<TileMapLayer> &layer : layers) {
- layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_VISIBILITY);
- }
- } break;
-
case TileMap::NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
- // Physics.
+ // This is only executed when collision_animatable is enabled.
+
bool in_editor = false;
#ifdef TOOLS_ENABLED
in_editor = Engine::get_singleton()->is_editor_hint();
@@ -224,39 +188,30 @@ void TileMap::_notification(int p_what) {
if (is_inside_tree() && collision_animatable && !in_editor) {
// Update transform on the physics tick when in animatable mode.
last_valid_transform = new_transform;
+ print_line("Physics: ", new_transform);
set_notify_local_transform(false);
set_global_transform(new_transform);
- _update_notify_local_transform();
- }
- } break;
-
- case NOTIFICATION_TRANSFORM_CHANGED: {
- // Physics.
- for (Ref<TileMapLayer> &layer : layers) {
- layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_XFORM);
+ set_notify_local_transform(true);
}
} break;
case TileMap::NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
- for (Ref<TileMapLayer> &layer : layers) {
- layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_LOCAL_XFORM);
- }
+ // This is only executed when collision_animatable is enabled.
- // Physics.
bool in_editor = false;
#ifdef TOOLS_ENABLED
in_editor = Engine::get_singleton()->is_editor_hint();
#endif
- // Only active when animatable. Send the new transform to the physics...
if (is_inside_tree() && collision_animatable && !in_editor) {
// Store last valid transform.
new_transform = get_global_transform();
+ print_line("local XFORM: ", last_valid_transform);
// ... but then revert changes.
set_notify_local_transform(false);
set_global_transform(last_valid_transform);
- _update_notify_local_transform();
+ set_notify_local_transform(true);
}
} break;
}
@@ -285,7 +240,7 @@ void TileMap::_internal_update() {
}
// Update dirty quadrants on layers.
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->internal_update();
}
@@ -308,7 +263,7 @@ void TileMap::set_tileset(const Ref<TileSet> &p_tileset) {
tile_set->connect_changed(callable_mp(this, &TileMap::_tile_set_changed));
}
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_TILE_SET);
}
@@ -323,7 +278,7 @@ void TileMap::set_rendering_quadrant_size(int p_size) {
ERR_FAIL_COND_MSG(p_size < 1, "TileMapQuadrant size cannot be smaller than 1.");
rendering_quadrant_size = p_size;
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE);
}
emit_signal(CoreStringNames::get_singleton()->changed);
@@ -429,10 +384,11 @@ void TileMap::add_layer(int p_to_pos) {
ERR_FAIL_INDEX(p_to_pos, (int)layers.size() + 1);
// Must clear before adding the layer.
- Ref<TileMapLayer> new_layer;
- new_layer.instantiate();
- new_layer->set_tile_map(this);
+ TileMapLayer *new_layer = memnew(TileMapLayer);
layers.insert(p_to_pos, new_layer);
+ add_child(new_layer);
+ new_layer->set_name(vformat("Layer%d", p_to_pos));
+ move_child(new_layer, p_to_pos);
for (uint32_t i = 0; i < layers.size(); i++) {
layers[i]->set_layer_index_in_tile_map_node(i);
}
@@ -449,10 +405,11 @@ void TileMap::move_layer(int p_layer, int p_to_pos) {
ERR_FAIL_INDEX(p_to_pos, (int)layers.size() + 1);
// Clear before shuffling layers.
- Ref<TileMapLayer> layer = layers[p_layer];
+ TileMapLayer *layer = layers[p_layer];
layers.insert(p_to_pos, layer);
layers.remove_at(p_to_pos < p_layer ? p_layer + 1 : p_layer);
for (uint32_t i = 0; i < layers.size(); i++) {
+ move_child(layer, i);
layers[i]->set_layer_index_in_tile_map_node(i);
}
queue_internal_update();
@@ -471,6 +428,7 @@ void TileMap::remove_layer(int p_layer) {
ERR_FAIL_INDEX(p_layer, (int)layers.size());
// Clear before removing the layer.
+ layers[p_layer]->queue_free();
layers.remove_at(p_layer);
for (uint32_t i = 0; i < layers.size(); i++) {
layers[i]->set_layer_index_in_tile_map_node(i);
@@ -513,7 +471,6 @@ Color TileMap::get_layer_modulate(int p_layer) const {
void TileMap::set_layer_y_sort_enabled(int p_layer, bool p_y_sort_enabled) {
TILEMAP_CALL_FOR_LAYER(p_layer, set_y_sort_enabled, p_y_sort_enabled);
- _update_notify_local_transform();
}
bool TileMap::is_layer_y_sort_enabled(int p_layer) const {
@@ -552,17 +509,16 @@ RID TileMap::get_layer_navigation_map(int p_layer) const {
TILEMAP_CALL_FOR_LAYER_V(p_layer, RID(), get_navigation_map);
}
-void TileMap::set_collision_animatable(bool p_enabled) {
- if (collision_animatable == p_enabled) {
+void TileMap::set_collision_animatable(bool p_collision_animatable) {
+ if (collision_animatable == p_collision_animatable) {
return;
}
- collision_animatable = p_enabled;
- _update_notify_local_transform();
- set_physics_process_internal(p_enabled);
- for (Ref<TileMapLayer> &layer : layers) {
- layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_COLLISION_ANIMATABLE);
+ collision_animatable = p_collision_animatable;
+ set_notify_local_transform(p_collision_animatable);
+ set_physics_process_internal(p_collision_animatable);
+ for (TileMapLayer *layer : layers) {
+ layer->set_use_kinematic_bodies(layer);
}
- emit_signal(CoreStringNames::get_singleton()->changed);
}
bool TileMap::is_collision_animatable() const {
@@ -574,13 +530,13 @@ void TileMap::set_collision_visibility_mode(TileMap::VisibilityMode p_show_colli
return;
}
collision_visibility_mode = p_show_collision;
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_COLLISION_VISIBILITY_MODE);
}
emit_signal(CoreStringNames::get_singleton()->changed);
}
-TileMap::VisibilityMode TileMap::get_collision_visibility_mode() {
+TileMap::VisibilityMode TileMap::get_collision_visibility_mode() const {
return collision_visibility_mode;
}
@@ -589,13 +545,13 @@ void TileMap::set_navigation_visibility_mode(TileMap::VisibilityMode p_show_navi
return;
}
navigation_visibility_mode = p_show_navigation;
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_NAVIGATION_VISIBILITY_MODE);
}
emit_signal(CoreStringNames::get_singleton()->changed);
}
-TileMap::VisibilityMode TileMap::get_navigation_visibility_mode() {
+TileMap::VisibilityMode TileMap::get_navigation_visibility_mode() const {
return navigation_visibility_mode;
}
@@ -604,7 +560,7 @@ void TileMap::set_y_sort_enabled(bool p_enable) {
return;
}
Node2D::set_y_sort_enabled(p_enable);
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED);
}
emit_signal(CoreStringNames::get_singleton()->changed);
@@ -640,27 +596,8 @@ Ref<TileMapPattern> TileMap::get_pattern(int p_layer, TypedArray<Vector2i> p_coo
}
Vector2i TileMap::map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern) {
- ERR_FAIL_COND_V(p_pattern.is_null(), Vector2i());
- ERR_FAIL_COND_V(!p_pattern->has_cell(p_coords_in_pattern), Vector2i());
-
- Vector2i output = p_position_in_tilemap + p_coords_in_pattern;
- if (tile_set->get_tile_shape() != TileSet::TILE_SHAPE_SQUARE) {
- if (tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STACKED) {
- if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(p_position_in_tilemap.y % 2) && bool(p_coords_in_pattern.y % 2)) {
- output.x += 1;
- } else if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(p_position_in_tilemap.x % 2) && bool(p_coords_in_pattern.x % 2)) {
- output.y += 1;
- }
- } else if (tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STACKED_OFFSET) {
- if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(p_position_in_tilemap.y % 2) && bool(p_coords_in_pattern.y % 2)) {
- output.x -= 1;
- } else if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(p_position_in_tilemap.x % 2) && bool(p_coords_in_pattern.x % 2)) {
- output.y -= 1;
- }
- }
- }
-
- return output;
+ ERR_FAIL_COND_V(!tile_set.is_valid(), Vector2i());
+ return tile_set->map_pattern(p_position_in_tilemap, p_coords_in_pattern, p_pattern);
}
void TileMap::set_pattern(int p_layer, const Vector2i &p_position, const Ref<TileMapPattern> p_pattern) {
@@ -700,7 +637,7 @@ TileMapCell TileMap::get_cell(int p_layer, const Vector2i &p_coords, bool p_use_
}
Vector2i TileMap::get_coords_for_body_rid(RID p_physics_body) {
- for (const Ref<TileMapLayer> &layer : layers) {
+ for (const TileMapLayer *layer : layers) {
if (layer->has_body_rid(p_physics_body)) {
return layer->get_coords_for_body_rid(p_physics_body);
}
@@ -718,7 +655,7 @@ int TileMap::get_layer_for_body_rid(RID p_physics_body) {
}
void TileMap::fix_invalid_tiles() {
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->fix_invalid_tiles();
}
}
@@ -728,7 +665,7 @@ void TileMap::clear_layer(int p_layer) {
}
void TileMap::clear() {
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->clear();
}
}
@@ -742,7 +679,7 @@ void TileMap::notify_runtime_tile_data_update(int p_layer) {
if (p_layer >= 0) {
TILEMAP_CALL_FOR_LAYER(p_layer, notify_tile_map_change, TileMapLayer::DIRTY_FLAGS_TILE_MAP_RUNTIME_UPDATE);
} else {
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_RUNTIME_UPDATE);
}
}
@@ -780,9 +717,9 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
else if (p_name == "tile_data") { // Kept for compatibility reasons.
if (p_value.is_array()) {
if (layers.size() == 0) {
- Ref<TileMapLayer> new_layer;
- new_layer.instantiate();
- new_layer->set_tile_map(this);
+ TileMapLayer *new_layer = memnew(TileMapLayer);
+ add_child(new_layer);
+ new_layer->set_name("Layer0");
new_layer->set_layer_index_in_tile_map_node(0);
layers.push_back(new_layer);
}
@@ -804,9 +741,9 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
if (index >= (int)layers.size()) {
while (index >= (int)layers.size()) {
- Ref<TileMapLayer> new_layer;
- new_layer.instantiate();
- new_layer->set_tile_map(this);
+ TileMapLayer *new_layer = memnew(TileMapLayer);
+ add_child(new_layer);
+ new_layer->set_name(vformat("Layer%d", index));
new_layer->set_layer_index_in_tile_map_node(index);
layers.push_back(new_layer);
}
@@ -985,623 +922,23 @@ bool TileMap::_property_get_revert(const StringName &p_name, Variant &r_property
}
Vector2 TileMap::map_to_local(const Vector2i &p_pos) const {
- // SHOULD RETURN THE CENTER OF THE CELL.
ERR_FAIL_COND_V(!tile_set.is_valid(), Vector2());
-
- Vector2 ret = p_pos;
- TileSet::TileShape tile_shape = tile_set->get_tile_shape();
- TileSet::TileOffsetAxis tile_offset_axis = tile_set->get_tile_offset_axis();
-
- if (tile_shape == TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE || tile_shape == TileSet::TILE_SHAPE_HEXAGON || tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- // Technically, those 3 shapes are equivalent, as they are basically half-offset, but with different levels or overlap.
- // square = no overlap, hexagon = 0.25 overlap, isometric = 0.5 overlap.
- if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- switch (tile_set->get_tile_layout()) {
- case TileSet::TILE_LAYOUT_STACKED:
- ret = Vector2(ret.x + (Math::posmod(ret.y, 2) == 0 ? 0.0 : 0.5), ret.y);
- break;
- case TileSet::TILE_LAYOUT_STACKED_OFFSET:
- ret = Vector2(ret.x + (Math::posmod(ret.y, 2) == 1 ? 0.0 : 0.5), ret.y);
- break;
- case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
- ret = Vector2(ret.x + ret.y / 2, ret.y);
- break;
- case TileSet::TILE_LAYOUT_STAIRS_DOWN:
- ret = Vector2(ret.x / 2, ret.y * 2 + ret.x);
- break;
- case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
- ret = Vector2((ret.x + ret.y) / 2, ret.y - ret.x);
- break;
- case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
- ret = Vector2((ret.x - ret.y) / 2, ret.y + ret.x);
- break;
- }
- } else { // TILE_OFFSET_AXIS_VERTICAL.
- switch (tile_set->get_tile_layout()) {
- case TileSet::TILE_LAYOUT_STACKED:
- ret = Vector2(ret.x, ret.y + (Math::posmod(ret.x, 2) == 0 ? 0.0 : 0.5));
- break;
- case TileSet::TILE_LAYOUT_STACKED_OFFSET:
- ret = Vector2(ret.x, ret.y + (Math::posmod(ret.x, 2) == 1 ? 0.0 : 0.5));
- break;
- case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
- ret = Vector2(ret.x * 2 + ret.y, ret.y / 2);
- break;
- case TileSet::TILE_LAYOUT_STAIRS_DOWN:
- ret = Vector2(ret.x, ret.y + ret.x / 2);
- break;
- case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
- ret = Vector2(ret.x + ret.y, (ret.y - ret.x) / 2);
- break;
- case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
- ret = Vector2(ret.x - ret.y, (ret.y + ret.x) / 2);
- break;
- }
- }
- }
-
- // Multiply by the overlapping ratio.
- double overlapping_ratio = 1.0;
- if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- overlapping_ratio = 0.5;
- } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) {
- overlapping_ratio = 0.75;
- }
- ret.y *= overlapping_ratio;
- } else { // TILE_OFFSET_AXIS_VERTICAL.
- if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- overlapping_ratio = 0.5;
- } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) {
- overlapping_ratio = 0.75;
- }
- ret.x *= overlapping_ratio;
- }
-
- return (ret + Vector2(0.5, 0.5)) * tile_set->get_tile_size();
+ return tile_set->map_to_local(p_pos);
}
-Vector2i TileMap::local_to_map(const Vector2 &p_local_position) const {
+Vector2i TileMap::local_to_map(const Vector2 &p_pos) const {
ERR_FAIL_COND_V(!tile_set.is_valid(), Vector2i());
-
- Vector2 ret = p_local_position;
- ret /= tile_set->get_tile_size();
-
- TileSet::TileShape tile_shape = tile_set->get_tile_shape();
- TileSet::TileOffsetAxis tile_offset_axis = tile_set->get_tile_offset_axis();
- TileSet::TileLayout tile_layout = tile_set->get_tile_layout();
-
- // Divide by the overlapping ratio.
- double overlapping_ratio = 1.0;
- if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- overlapping_ratio = 0.5;
- } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) {
- overlapping_ratio = 0.75;
- }
- ret.y /= overlapping_ratio;
- } else { // TILE_OFFSET_AXIS_VERTICAL.
- if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- overlapping_ratio = 0.5;
- } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) {
- overlapping_ratio = 0.75;
- }
- ret.x /= overlapping_ratio;
- }
-
- // For each half-offset shape, we check if we are in the corner of the tile, and thus should correct the local position accordingly.
- if (tile_shape == TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE || tile_shape == TileSet::TILE_SHAPE_HEXAGON || tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- // Technically, those 3 shapes are equivalent, as they are basically half-offset, but with different levels or overlap.
- // square = no overlap, hexagon = 0.25 overlap, isometric = 0.5 overlap.
- if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- // Smart floor of the position
- Vector2 raw_pos = ret;
- if (Math::posmod(Math::floor(ret.y), 2) ^ (tile_layout == TileSet::TILE_LAYOUT_STACKED_OFFSET)) {
- ret = Vector2(Math::floor(ret.x + 0.5) - 0.5, Math::floor(ret.y));
- } else {
- ret = ret.floor();
- }
-
- // Compute the tile offset, and if we might the output for a neighbor top tile.
- Vector2 in_tile_pos = raw_pos - ret;
- bool in_top_left_triangle = (in_tile_pos - Vector2(0.5, 0.0)).cross(Vector2(-0.5, 1.0 / overlapping_ratio - 1)) <= 0;
- bool in_top_right_triangle = (in_tile_pos - Vector2(0.5, 0.0)).cross(Vector2(0.5, 1.0 / overlapping_ratio - 1)) > 0;
-
- switch (tile_layout) {
- case TileSet::TILE_LAYOUT_STACKED:
- ret = ret.floor();
- if (in_top_left_triangle) {
- ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 0 : -1, -1);
- } else if (in_top_right_triangle) {
- ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 1 : 0, -1);
- }
- break;
- case TileSet::TILE_LAYOUT_STACKED_OFFSET:
- ret = ret.floor();
- if (in_top_left_triangle) {
- ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? -1 : 0, -1);
- } else if (in_top_right_triangle) {
- ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 0 : 1, -1);
- }
- break;
- case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
- ret = Vector2(ret.x - ret.y / 2, ret.y).floor();
- if (in_top_left_triangle) {
- ret += Vector2i(0, -1);
- } else if (in_top_right_triangle) {
- ret += Vector2i(1, -1);
- }
- break;
- case TileSet::TILE_LAYOUT_STAIRS_DOWN:
- ret = Vector2(ret.x * 2, ret.y / 2 - ret.x).floor();
- if (in_top_left_triangle) {
- ret += Vector2i(-1, 0);
- } else if (in_top_right_triangle) {
- ret += Vector2i(1, -1);
- }
- break;
- case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
- ret = Vector2(ret.x - ret.y / 2, ret.y / 2 + ret.x).floor();
- if (in_top_left_triangle) {
- ret += Vector2i(0, -1);
- } else if (in_top_right_triangle) {
- ret += Vector2i(1, 0);
- }
- break;
- case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
- ret = Vector2(ret.x + ret.y / 2, ret.y / 2 - ret.x).floor();
- if (in_top_left_triangle) {
- ret += Vector2i(-1, 0);
- } else if (in_top_right_triangle) {
- ret += Vector2i(0, -1);
- }
- break;
- }
- } else { // TILE_OFFSET_AXIS_VERTICAL.
- // Smart floor of the position.
- Vector2 raw_pos = ret;
- if (Math::posmod(Math::floor(ret.x), 2) ^ (tile_layout == TileSet::TILE_LAYOUT_STACKED_OFFSET)) {
- ret = Vector2(Math::floor(ret.x), Math::floor(ret.y + 0.5) - 0.5);
- } else {
- ret = ret.floor();
- }
-
- // Compute the tile offset, and if we might the output for a neighbor top tile.
- Vector2 in_tile_pos = raw_pos - ret;
- bool in_top_left_triangle = (in_tile_pos - Vector2(0.0, 0.5)).cross(Vector2(1.0 / overlapping_ratio - 1, -0.5)) > 0;
- bool in_bottom_left_triangle = (in_tile_pos - Vector2(0.0, 0.5)).cross(Vector2(1.0 / overlapping_ratio - 1, 0.5)) <= 0;
-
- switch (tile_layout) {
- case TileSet::TILE_LAYOUT_STACKED:
- ret = ret.floor();
- if (in_top_left_triangle) {
- ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 0 : -1);
- } else if (in_bottom_left_triangle) {
- ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 1 : 0);
- }
- break;
- case TileSet::TILE_LAYOUT_STACKED_OFFSET:
- ret = ret.floor();
- if (in_top_left_triangle) {
- ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? -1 : 0);
- } else if (in_bottom_left_triangle) {
- ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 0 : 1);
- }
- break;
- case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
- ret = Vector2(ret.x / 2 - ret.y, ret.y * 2).floor();
- if (in_top_left_triangle) {
- ret += Vector2i(0, -1);
- } else if (in_bottom_left_triangle) {
- ret += Vector2i(-1, 1);
- }
- break;
- case TileSet::TILE_LAYOUT_STAIRS_DOWN:
- ret = Vector2(ret.x, ret.y - ret.x / 2).floor();
- if (in_top_left_triangle) {
- ret += Vector2i(-1, 0);
- } else if (in_bottom_left_triangle) {
- ret += Vector2i(-1, 1);
- }
- break;
- case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
- ret = Vector2(ret.x / 2 - ret.y, ret.y + ret.x / 2).floor();
- if (in_top_left_triangle) {
- ret += Vector2i(0, -1);
- } else if (in_bottom_left_triangle) {
- ret += Vector2i(-1, 0);
- }
- break;
- case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
- ret = Vector2(ret.x / 2 + ret.y, ret.y - ret.x / 2).floor();
- if (in_top_left_triangle) {
- ret += Vector2i(-1, 0);
- } else if (in_bottom_left_triangle) {
- ret += Vector2i(0, 1);
- }
- break;
- }
- }
- } else {
- ret = (ret + Vector2(0.00005, 0.00005)).floor();
- }
- return Vector2i(ret);
+ return tile_set->local_to_map(p_pos);
}
bool TileMap::is_existing_neighbor(TileSet::CellNeighbor p_cell_neighbor) const {
ERR_FAIL_COND_V(!tile_set.is_valid(), false);
-
- TileSet::TileShape shape = tile_set->get_tile_shape();
- if (shape == TileSet::TILE_SHAPE_SQUARE) {
- return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER;
-
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
- } else {
- if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
- } else {
- return p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE ||
- p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
- }
- }
+ return tile_set->is_existing_neighbor(p_cell_neighbor);
}
Vector2i TileMap::get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const {
- ERR_FAIL_COND_V(!tile_set.is_valid(), p_coords);
-
- TileSet::TileShape shape = tile_set->get_tile_shape();
- if (shape == TileSet::TILE_SHAPE_SQUARE) {
- switch (p_cell_neighbor) {
- case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
- return p_coords + Vector2i(1, 0);
- case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
- return p_coords + Vector2i(1, 1);
- case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
- return p_coords + Vector2i(0, 1);
- case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
- return p_coords + Vector2i(-1, 1);
- case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
- return p_coords + Vector2i(-1, 0);
- case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
- return p_coords + Vector2i(-1, -1);
- case TileSet::CELL_NEIGHBOR_TOP_SIDE:
- return p_coords + Vector2i(0, -1);
- case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
- return p_coords + Vector2i(1, -1);
- default:
- ERR_FAIL_V(p_coords);
- }
- } else { // Half-offset shapes (square and hexagon).
- switch (tile_set->get_tile_layout()) {
- case TileSet::TILE_LAYOUT_STACKED: {
- if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- bool is_offset = p_coords.y % 2;
- if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
- return p_coords + Vector2i(1, 0);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
- return p_coords + Vector2i(is_offset ? 1 : 0, 1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
- return p_coords + Vector2i(0, 2);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
- return p_coords + Vector2i(is_offset ? 0 : -1, 1);
- } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
- return p_coords + Vector2i(-1, 0);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
- return p_coords + Vector2i(is_offset ? 0 : -1, -1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
- return p_coords + Vector2i(0, -2);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
- return p_coords + Vector2i(is_offset ? 1 : 0, -1);
- } else {
- ERR_FAIL_V(p_coords);
- }
- } else {
- bool is_offset = p_coords.x % 2;
-
- if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
- return p_coords + Vector2i(0, 1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
- return p_coords + Vector2i(1, is_offset ? 1 : 0);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
- return p_coords + Vector2i(2, 0);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
- return p_coords + Vector2i(1, is_offset ? 0 : -1);
- } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
- return p_coords + Vector2i(0, -1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
- return p_coords + Vector2i(-1, is_offset ? 0 : -1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
- return p_coords + Vector2i(-2, 0);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
- return p_coords + Vector2i(-1, is_offset ? 1 : 0);
- } else {
- ERR_FAIL_V(p_coords);
- }
- }
- } break;
- case TileSet::TILE_LAYOUT_STACKED_OFFSET: {
- if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- bool is_offset = p_coords.y % 2;
-
- if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
- return p_coords + Vector2i(1, 0);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
- return p_coords + Vector2i(is_offset ? 0 : 1, 1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
- return p_coords + Vector2i(0, 2);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
- return p_coords + Vector2i(is_offset ? -1 : 0, 1);
- } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
- return p_coords + Vector2i(-1, 0);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
- return p_coords + Vector2i(is_offset ? -1 : 0, -1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
- return p_coords + Vector2i(0, -2);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
- return p_coords + Vector2i(is_offset ? 0 : 1, -1);
- } else {
- ERR_FAIL_V(p_coords);
- }
- } else {
- bool is_offset = p_coords.x % 2;
-
- if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
- return p_coords + Vector2i(0, 1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
- return p_coords + Vector2i(1, is_offset ? 0 : 1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
- return p_coords + Vector2i(2, 0);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
- return p_coords + Vector2i(1, is_offset ? -1 : 0);
- } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
- return p_coords + Vector2i(0, -1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
- return p_coords + Vector2i(-1, is_offset ? -1 : 0);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
- return p_coords + Vector2i(-2, 0);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
- return p_coords + Vector2i(-1, is_offset ? 0 : 1);
- } else {
- ERR_FAIL_V(p_coords);
- }
- }
- } break;
- case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
- case TileSet::TILE_LAYOUT_STAIRS_DOWN: {
- if ((tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STAIRS_RIGHT) ^ (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
- if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
- return p_coords + Vector2i(1, 0);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
- return p_coords + Vector2i(0, 1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
- return p_coords + Vector2i(-1, 2);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
- return p_coords + Vector2i(-1, 1);
- } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
- return p_coords + Vector2i(-1, 0);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
- return p_coords + Vector2i(0, -1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
- return p_coords + Vector2i(1, -2);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
- return p_coords + Vector2i(1, -1);
- } else {
- ERR_FAIL_V(p_coords);
- }
-
- } else {
- if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
- return p_coords + Vector2i(0, 1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
- return p_coords + Vector2i(1, 0);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
- return p_coords + Vector2i(2, -1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
- return p_coords + Vector2i(1, -1);
- } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
- return p_coords + Vector2i(0, -1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
- return p_coords + Vector2i(-1, 0);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
- return p_coords + Vector2i(-2, 1);
-
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
- return p_coords + Vector2i(-1, 1);
- } else {
- ERR_FAIL_V(p_coords);
- }
- }
- } else {
- if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
- return p_coords + Vector2i(2, -1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
- return p_coords + Vector2i(1, 0);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
- return p_coords + Vector2i(0, 1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
- return p_coords + Vector2i(-1, 1);
- } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
- return p_coords + Vector2i(-2, 1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
- return p_coords + Vector2i(-1, 0);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
- return p_coords + Vector2i(0, -1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
- return p_coords + Vector2i(1, -1);
- } else {
- ERR_FAIL_V(p_coords);
- }
-
- } else {
- if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
- return p_coords + Vector2i(-1, 2);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
- return p_coords + Vector2i(0, 1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
- return p_coords + Vector2i(1, 0);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
- return p_coords + Vector2i(1, -1);
- } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
- return p_coords + Vector2i(1, -2);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
- return p_coords + Vector2i(0, -1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
- return p_coords + Vector2i(-1, 0);
-
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
- return p_coords + Vector2i(-1, 1);
- } else {
- ERR_FAIL_V(p_coords);
- }
- }
- }
- } break;
- case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
- case TileSet::TILE_LAYOUT_DIAMOND_DOWN: {
- if ((tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_DIAMOND_RIGHT) ^ (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
- if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
- return p_coords + Vector2i(1, 1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
- return p_coords + Vector2i(0, 1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
- return p_coords + Vector2i(-1, 1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
- return p_coords + Vector2i(-1, 0);
- } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
- return p_coords + Vector2i(-1, -1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
- return p_coords + Vector2i(0, -1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
- return p_coords + Vector2i(1, -1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
- return p_coords + Vector2i(1, 0);
- } else {
- ERR_FAIL_V(p_coords);
- }
-
- } else {
- if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
- return p_coords + Vector2i(1, 1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
- return p_coords + Vector2i(1, 0);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
- return p_coords + Vector2i(1, -1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
- return p_coords + Vector2i(0, -1);
- } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
- return p_coords + Vector2i(-1, -1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
- return p_coords + Vector2i(-1, 0);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
- return p_coords + Vector2i(-1, 1);
-
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
- return p_coords + Vector2i(0, 1);
- } else {
- ERR_FAIL_V(p_coords);
- }
- }
- } else {
- if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
- return p_coords + Vector2i(1, -1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
- return p_coords + Vector2i(1, 0);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
- return p_coords + Vector2i(1, 1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
- return p_coords + Vector2i(0, 1);
- } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
- return p_coords + Vector2i(-1, 1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
- return p_coords + Vector2i(-1, 0);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
- return p_coords + Vector2i(-1, -1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
- return p_coords + Vector2i(0, -1);
- } else {
- ERR_FAIL_V(p_coords);
- }
-
- } else {
- if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
- return p_coords + Vector2i(-1, 1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
- return p_coords + Vector2i(0, 1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
- return p_coords + Vector2i(1, 1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
- return p_coords + Vector2i(1, 0);
- } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
- (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
- return p_coords + Vector2i(1, -1);
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
- return p_coords + Vector2i(0, -1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
- return p_coords + Vector2i(-1, -1);
-
- } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
- return p_coords + Vector2i(-1, 0);
- } else {
- ERR_FAIL_V(p_coords);
- }
- }
- }
- } break;
- default:
- ERR_FAIL_V(p_coords);
- }
- }
+ ERR_FAIL_COND_V(!tile_set.is_valid(), Vector2i());
+ return tile_set->get_neighbor_cell(p_coords, p_cell_neighbor);
}
TypedArray<Vector2i> TileMap::get_used_cells(int p_layer) const {
@@ -1616,7 +953,7 @@ Rect2i TileMap::get_used_rect() const {
// Return the visible rect of the tilemap.
bool first = true;
Rect2i rect = Rect2i();
- for (const Ref<TileMapLayer> &layer : layers) {
+ for (const TileMapLayer *layer : layers) {
Rect2i layer_rect = layer->get_used_rect();
if (layer_rect == Rect2i()) {
continue;
@@ -1636,7 +973,7 @@ Rect2i TileMap::get_used_rect() const {
void TileMap::set_light_mask(int p_light_mask) {
// Occlusion: set light mask.
CanvasItem::set_light_mask(p_light_mask);
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_LIGHT_MASK);
}
}
@@ -1646,7 +983,7 @@ void TileMap::set_material(const Ref<Material> &p_material) {
CanvasItem::set_material(p_material);
// Update material for the whole tilemap.
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_MATERIAL);
}
}
@@ -1656,7 +993,7 @@ void TileMap::set_use_parent_material(bool p_use_parent_material) {
CanvasItem::set_use_parent_material(p_use_parent_material);
// Update use_parent_material for the whole tilemap.
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_USE_PARENT_MATERIAL);
}
}
@@ -1664,7 +1001,7 @@ void TileMap::set_use_parent_material(bool p_use_parent_material) {
void TileMap::set_texture_filter(TextureFilter p_texture_filter) {
// Set a default texture filter for the whole tilemap.
CanvasItem::set_texture_filter(p_texture_filter);
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_TEXTURE_FILTER);
}
}
@@ -1672,7 +1009,7 @@ void TileMap::set_texture_filter(TextureFilter p_texture_filter) {
void TileMap::set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) {
// Set a default texture repeat for the whole tilemap.
CanvasItem::set_texture_repeat(p_texture_repeat);
- for (Ref<TileMapLayer> &layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT);
}
}
@@ -1771,14 +1108,14 @@ PackedStringArray TileMap::get_configuration_warnings() const {
// Retrieve the set of Z index values with a Y-sorted layer.
RBSet<int> y_sorted_z_index;
- for (const Ref<TileMapLayer> &layer : layers) {
+ for (const TileMapLayer *layer : layers) {
if (layer->is_y_sort_enabled()) {
y_sorted_z_index.insert(layer->get_z_index());
}
}
// Check if we have a non-sorted layer in a Z-index with a Y-sorted layer.
- for (const Ref<TileMapLayer> &layer : layers) {
+ for (const TileMapLayer *layer : layers) {
if (!layer->is_y_sort_enabled() && y_sorted_z_index.has(layer->get_z_index())) {
warnings.push_back(RTR("A Y-sorted layer has the same Z-index value as a not Y-sorted layer.\nThis may lead to unwanted behaviors, as a layer that is not Y-sorted will be Y-sorted as a whole with tiles from Y-sorted layers."));
break;
@@ -1787,7 +1124,7 @@ PackedStringArray TileMap::get_configuration_warnings() const {
if (!is_y_sort_enabled()) {
// Check if Y-sort is enabled on a layer but not on the node.
- for (const Ref<TileMapLayer> &layer : layers) {
+ for (const TileMapLayer *layer : layers) {
if (layer->is_y_sort_enabled()) {
warnings.push_back(RTR("A TileMap layer is set as Y-sorted, but Y-sort is not enabled on the TileMap node itself."));
break;
@@ -1796,7 +1133,7 @@ PackedStringArray TileMap::get_configuration_warnings() const {
} else {
// Check if Y-sort is enabled on the node, but not on any of the layers.
bool need_warning = true;
- for (const Ref<TileMapLayer> &layer : layers) {
+ for (const TileMapLayer *layer : layers) {
if (layer->is_y_sort_enabled()) {
need_warning = false;
break;
@@ -1811,7 +1148,7 @@ PackedStringArray TileMap::get_configuration_warnings() const {
if (tile_set.is_valid() && tile_set->get_tile_shape() == TileSet::TILE_SHAPE_ISOMETRIC) {
bool warn = !is_y_sort_enabled();
if (!warn) {
- for (const Ref<TileMapLayer> &layer : layers) {
+ for (const TileMapLayer *layer : layers) {
if (!layer->is_y_sort_enabled()) {
warn = true;
break;
@@ -1926,42 +1263,27 @@ void TileMap::_bind_methods() {
void TileMap::_tile_set_changed() {
emit_signal(CoreStringNames::get_singleton()->changed);
- for (Ref<TileMapLayer> layer : layers) {
+ for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_TILE_SET);
}
update_configuration_warnings();
}
-void TileMap::_update_notify_local_transform() {
- bool notify = collision_animatable || is_y_sort_enabled();
- if (!notify) {
- for (const Ref<TileMapLayer> &layer : layers) {
- if (layer->is_y_sort_enabled()) {
- notify = true;
- break;
- }
- }
- }
- set_notify_local_transform(notify);
-}
-
TileMap::TileMap() {
- set_notify_transform(true);
- _update_notify_local_transform();
-
- Ref<TileMapLayer> new_layer;
- new_layer.instantiate();
- new_layer->set_tile_map(this);
+ TileMapLayer *new_layer = memnew(TileMapLayer);
+ add_child(new_layer);
+ new_layer->set_name("Layer0");
new_layer->set_layer_index_in_tile_map_node(0);
layers.push_back(new_layer);
- default_layer.instantiate();
+ default_layer = memnew(TileMapLayer);
}
TileMap::~TileMap() {
if (tile_set.is_valid()) {
tile_set->disconnect_changed(callable_mp(this, &TileMap::_tile_set_changed));
}
+ memdelete(default_layer);
}
#undef TILEMAP_CALL_FOR_LAYER
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 29af0ad2b1..f2b481cdd1 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -71,18 +71,17 @@ private:
VisibilityMode navigation_visibility_mode = VISIBILITY_MODE_DEFAULT;
// Layers.
- LocalVector<Ref<TileMapLayer>> layers;
- Ref<TileMapLayer> default_layer; // Dummy layer to fetch default values.
+ LocalVector<TileMapLayer *> layers;
+ TileMapLayer *default_layer; // Dummy layer to fetch default values.
int selected_layer = -1;
bool pending_update = false;
+ // Transforms for collision_animatable.
Transform2D last_valid_transform;
Transform2D new_transform;
void _tile_set_changed();
- void _update_notify_local_transform();
-
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
@@ -97,6 +96,8 @@ protected:
Rect2i _get_used_rect_bind_compat_78328();
void _set_quadrant_size_compat_81070(int p_quadrant_size);
int _get_quadrant_size_compat_81070() const;
+ VisibilityMode _get_collision_visibility_mode_bind_compat_87115();
+ VisibilityMode _get_navigation_visibility_mode_bind_compat_87115();
static void _bind_compatibility_methods();
#endif
@@ -150,15 +151,15 @@ public:
void set_selected_layer(int p_layer_id); // For editor use.
int get_selected_layer() const;
- void set_collision_animatable(bool p_enabled);
+ void set_collision_animatable(bool p_collision_animatable);
bool is_collision_animatable() const;
// Debug visibility modes.
void set_collision_visibility_mode(VisibilityMode p_show_collision);
- VisibilityMode get_collision_visibility_mode();
+ VisibilityMode get_collision_visibility_mode() const;
void set_navigation_visibility_mode(VisibilityMode p_show_navigation);
- VisibilityMode get_navigation_visibility_mode();
+ VisibilityMode get_navigation_visibility_mode() const;
// Cells accessors.
void set_cell(int p_layer, const Vector2i &p_coords, int p_source_id = TileSet::INVALID_SOURCE, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = 0);
@@ -192,7 +193,6 @@ public:
Vector2 map_to_local(const Vector2i &p_pos) const;
Vector2i local_to_map(const Vector2 &p_pos) const;
-
bool is_existing_neighbor(TileSet::CellNeighbor p_cell_neighbor) const;
Vector2i get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const;
diff --git a/scene/2d/tile_map_layer.cpp b/scene/2d/tile_map_layer.cpp
index ed93b8d051..df79b3fee6 100644
--- a/scene/2d/tile_map_layer.cpp
+++ b/scene/2d/tile_map_layer.cpp
@@ -40,6 +40,18 @@
#include "servers/navigation_server_3d.h"
#endif // DEBUG_ENABLED
+TileMap *TileMapLayer::_fetch_tilemap() const {
+ return TileMap::cast_to<TileMap>(get_parent());
+}
+
+Ref<TileSet> TileMapLayer::_fetch_tileset() const {
+ TileMap *tile_map_node = _fetch_tilemap();
+ if (!tile_map_node) {
+ return Ref<TileSet>();
+ }
+ return tile_map_node->get_tileset();
+}
+
#ifdef DEBUG_ENABLED
/////////////////////////////// Debug //////////////////////////////////////////
constexpr int TILE_MAP_DEBUG_QUADRANT_SIZE = 16;
@@ -51,11 +63,11 @@ Vector2i TileMapLayer::_coords_to_debug_quadrant_coords(const Vector2i &p_coords
}
void TileMapLayer::_debug_update() {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
RenderingServer *rs = RenderingServer::get_singleton();
// Check if we should cleanup everything.
- bool forced_cleanup = in_destructor || !enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid() || !tile_map_node->is_visible_in_tree();
+ bool forced_cleanup = in_destructor || !enabled || !tile_set.is_valid() || !is_visible_in_tree();
if (forced_cleanup) {
for (KeyValue<Vector2i, Ref<DebugQuadrant>> &kv : debug_quadrant_map) {
@@ -120,10 +132,10 @@ void TileMapLayer::_debug_update() {
} else {
ci = rs->canvas_item_create();
rs->canvas_item_set_z_index(ci, RS::CANVAS_ITEM_Z_MAX - 1);
- rs->canvas_item_set_parent(ci, tile_map_node->get_canvas_item());
+ rs->canvas_item_set_parent(ci, get_canvas_item());
}
- const Vector2 quadrant_pos = tile_map_node->map_to_local(debug_quadrant.quadrant_coords * TILE_MAP_DEBUG_QUADRANT_SIZE);
+ const Vector2 quadrant_pos = tile_set->map_to_local(debug_quadrant.quadrant_coords * TILE_MAP_DEBUG_QUADRANT_SIZE);
Transform2D xform(0, quadrant_pos);
rs->canvas_item_set_transform(ci, xform);
@@ -179,48 +191,33 @@ void TileMapLayer::_debug_quadrants_update_cell(CellData &r_cell_data, SelfList<
/////////////////////////////// Rendering //////////////////////////////////////
void TileMapLayer::_rendering_update() {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const TileMap *tile_map_node = _fetch_tilemap();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
RenderingServer *rs = RenderingServer::get_singleton();
// Check if we should cleanup everything.
- bool forced_cleanup = in_destructor || !enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid() || !tile_map_node->is_visible_in_tree();
+ bool forced_cleanup = in_destructor || !enabled || !tile_set.is_valid() || !is_visible_in_tree();
// ----------- Layer level processing -----------
- if (forced_cleanup) {
- // Cleanup.
- if (canvas_item.is_valid()) {
- rs->free(canvas_item);
- canvas_item = RID();
- }
- } else {
- // Create/Update the layer's CanvasItem.
- if (!canvas_item.is_valid()) {
- RID ci = rs->canvas_item_create();
- rs->canvas_item_set_parent(ci, tile_map_node->get_canvas_item());
- canvas_item = ci;
- }
- RID &ci = canvas_item;
- rs->canvas_item_set_draw_index(ci, layer_index_in_tile_map_node - (int64_t)0x80000000);
- rs->canvas_item_set_sort_children_by_y(ci, y_sort_enabled);
- rs->canvas_item_set_use_parent_material(ci, tile_map_node->get_use_parent_material() || tile_map_node->get_material().is_valid());
- rs->canvas_item_set_z_index(ci, z_index);
- rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(tile_map_node->get_texture_filter_in_tree()));
- rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(tile_map_node->get_texture_repeat_in_tree()));
- rs->canvas_item_set_light_mask(ci, tile_map_node->get_light_mask());
+ if (!forced_cleanup) {
+ // Update the layer's CanvasItem.
+ set_use_parent_material(true);
+ set_light_mask(tile_map_node->get_light_mask());
// Modulate the layer.
- Color layer_modulate = modulate;
+ Color layer_modulate = get_modulate();
int selected_layer = tile_map_node->get_selected_layer();
if (selected_layer >= 0 && layer_index_in_tile_map_node != selected_layer) {
int z_selected = tile_map_node->get_layer_z_index(selected_layer);
- if (z_index < z_selected || (z_index == z_selected && layer_index_in_tile_map_node < selected_layer)) {
+ int layer_z_index = get_z_index();
+ if (layer_z_index < z_selected || (layer_z_index == z_selected && layer_index_in_tile_map_node < selected_layer)) {
layer_modulate = layer_modulate.darkened(0.5);
- } else if (z_index > z_selected || (z_index == z_selected && layer_index_in_tile_map_node > selected_layer)) {
+ } else if (layer_z_index > z_selected || (layer_z_index == z_selected && layer_index_in_tile_map_node > selected_layer)) {
layer_modulate = layer_modulate.darkened(0.5);
layer_modulate.a *= 0.3;
}
}
- rs->canvas_item_set_modulate(ci, layer_modulate);
+ rs->canvas_item_set_modulate(get_canvas_item(), layer_modulate);
}
// ----------- Quadrants processing -----------
@@ -231,7 +228,7 @@ void TileMapLayer::_rendering_update() {
// Check if anything changed that might change the quadrant shape.
// If so, recreate everything.
bool quandrant_shape_changed = dirty.flags[DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE] ||
- (tile_map_node->is_y_sort_enabled() && y_sort_enabled && (dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] || dirty.flags[DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_TILE_MAP_LOCAL_XFORM] || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]));
+ (is_y_sort_enabled() && (dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] || dirty.flags[DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_LOCAL_TRANSFORM] || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]));
// Free all quadrants.
if (forced_cleanup || quandrant_shape_changed) {
@@ -250,7 +247,7 @@ void TileMapLayer::_rendering_update() {
if (!forced_cleanup) {
// List all quadrants to update, recreating them if needed.
- if (dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || _rendering_was_cleaned_up) {
+ if (dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] || _rendering_was_cleaned_up) {
// Update all cells.
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
CellData &cell_data = kv.value;
@@ -290,7 +287,7 @@ void TileMapLayer::_rendering_update() {
rendering_quadrant->canvas_items.clear();
// Sort the quadrant cells.
- if (tile_map_node->is_y_sort_enabled() && is_y_sort_enabled()) {
+ if (is_y_sort_enabled()) {
// For compatibility reasons, we use another comparator for Y-sorted layers.
rendering_quadrant->cells.sort_custom<CellDataYSortedComparator>();
} else {
@@ -330,8 +327,8 @@ void TileMapLayer::_rendering_update() {
if (mat.is_valid()) {
rs->canvas_item_set_material(ci, mat->get_rid());
}
- rs->canvas_item_set_parent(ci, canvas_item);
- rs->canvas_item_set_use_parent_material(ci, tile_map_node->get_use_parent_material() || tile_map_node->get_material().is_valid());
+ rs->canvas_item_set_parent(ci, get_canvas_item());
+ rs->canvas_item_set_use_parent_material(ci, true);
Transform2D xform(0, rendering_quadrant->canvas_items_position);
rs->canvas_item_set_transform(ci, xform);
@@ -340,8 +337,8 @@ void TileMapLayer::_rendering_update() {
rs->canvas_item_set_z_as_relative_to_parent(ci, true);
rs->canvas_item_set_z_index(ci, tile_z_index);
- rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(tile_map_node->get_texture_filter_in_tree()));
- rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(tile_map_node->get_texture_repeat_in_tree()));
+ rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(get_texture_filter_in_tree()));
+ rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(get_texture_repeat_in_tree()));
rendering_quadrant->canvas_items.push_back(ci);
@@ -354,7 +351,7 @@ void TileMapLayer::_rendering_update() {
ci = prev_ci;
}
- const Vector2 local_tile_pos = tile_map_node->map_to_local(cell_data.coords);
+ const Vector2 local_tile_pos = tile_set->map_to_local(cell_data.coords);
// Random animation offset.
real_t random_animation_offset = 0.0;
@@ -366,7 +363,7 @@ void TileMapLayer::_rendering_update() {
}
// Drawing the tile in the canvas item.
- tile_map_node->draw_tile(ci, local_tile_pos - rendering_quadrant->canvas_items_position, tile_set, cell_data.cell.source_id, cell_data.cell.get_atlas_coords(), cell_data.cell.alternative_tile, -1, tile_map_node->get_self_modulate(), tile_data, random_animation_offset);
+ TileMap::draw_tile(ci, local_tile_pos - rendering_quadrant->canvas_items_position, tile_set, cell_data.cell.source_id, cell_data.cell.get_atlas_coords(), cell_data.cell.alternative_tile, -1, get_self_modulate(), tile_data, random_animation_offset);
}
} else {
// Free the quadrant.
@@ -393,7 +390,7 @@ void TileMapLayer::_rendering_update() {
RBMap<Vector2, Ref<RenderingQuadrant>, RenderingQuadrant::CoordsWorldComparator> local_to_map;
for (KeyValue<Vector2i, Ref<RenderingQuadrant>> &kv : rendering_quadrant_map) {
Ref<RenderingQuadrant> &rendering_quadrant = kv.value;
- local_to_map[tile_map_node->map_to_local(rendering_quadrant->quadrant_coords)] = rendering_quadrant;
+ local_to_map[tile_set->map_to_local(rendering_quadrant->quadrant_coords)] = rendering_quadrant;
}
// Sort the quadrants.
@@ -409,14 +406,15 @@ void TileMapLayer::_rendering_update() {
dirty.flags[DIRTY_FLAGS_TILE_MAP_USE_PARENT_MATERIAL] ||
dirty.flags[DIRTY_FLAGS_TILE_MAP_MATERIAL] ||
dirty.flags[DIRTY_FLAGS_TILE_MAP_TEXTURE_FILTER] ||
- dirty.flags[DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT]) {
+ dirty.flags[DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT] ||
+ dirty.flags[DIRTY_FLAGS_LAYER_SELF_MODULATE]) {
for (KeyValue<Vector2i, Ref<RenderingQuadrant>> &kv : rendering_quadrant_map) {
Ref<RenderingQuadrant> &rendering_quadrant = kv.value;
for (const RID &ci : rendering_quadrant->canvas_items) {
rs->canvas_item_set_light_mask(ci, tile_map_node->get_light_mask());
- rs->canvas_item_set_use_parent_material(ci, tile_map_node->get_use_parent_material() || tile_map_node->get_material().is_valid());
- rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(tile_map_node->get_texture_filter_in_tree()));
- rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(tile_map_node->get_texture_repeat_in_tree()));
+ rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(get_texture_filter_in_tree()));
+ rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(get_texture_repeat_in_tree()));
+ rs->canvas_item_set_self_modulate(ci, get_self_modulate());
}
}
}
@@ -441,30 +439,37 @@ void TileMapLayer::_rendering_update() {
_rendering_occluders_update_cell(cell_data);
}
}
+ }
- // Updates on TileMap changes.
- if (dirty.flags[DIRTY_FLAGS_TILE_MAP_IN_CANVAS] || dirty.flags[DIRTY_FLAGS_TILE_MAP_VISIBILITY]) {
+ // -----------
+ // Mark the rendering state as up to date.
+ _rendering_was_cleaned_up = forced_cleanup;
+}
+
+void TileMapLayer::_rendering_notification(int p_what) {
+ RenderingServer *rs = RenderingServer::get_singleton();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
+ if (p_what == NOTIFICATION_TRANSFORM_CHANGED || p_what == NOTIFICATION_ENTER_CANVAS || p_what == NOTIFICATION_VISIBILITY_CHANGED) {
+ if (tile_set.is_valid()) {
+ Transform2D tilemap_xform = get_global_transform();
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
- CellData &cell_data = kv.value;
+ const CellData &cell_data = kv.value;
for (const RID &occluder : cell_data.occluders) {
if (occluder.is_null()) {
continue;
}
- Transform2D xform(0, tile_map_node->map_to_local(kv.key));
- rs->canvas_light_occluder_attach_to_canvas(occluder, tile_map_node->get_canvas());
- rs->canvas_light_occluder_set_transform(occluder, tile_map_node->get_global_transform() * xform);
+ Transform2D xform(0, tile_set->map_to_local(kv.key));
+ rs->canvas_light_occluder_attach_to_canvas(occluder, get_canvas());
+ rs->canvas_light_occluder_set_transform(occluder, tilemap_xform * xform);
}
}
}
}
-
- // -----------
- // Mark the rendering state as up to date.
- _rendering_was_cleaned_up = forced_cleanup;
}
void TileMapLayer::_rendering_quadrants_update_cell(CellData &r_cell_data, SelfList<RenderingQuadrant>::List &r_dirty_rendering_quadrant_list) {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const TileMap *tile_map_node = _fetch_tilemap();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
// Check if the cell is valid and retrieve its y_sort_origin.
bool is_valid = false;
@@ -489,8 +494,8 @@ void TileMapLayer::_rendering_quadrants_update_cell(CellData &r_cell_data, SelfL
// Get the quadrant coords.
Vector2 canvas_items_position;
Vector2i quadrant_coords;
- if (tile_map_node->is_y_sort_enabled() && is_y_sort_enabled()) {
- canvas_items_position = Vector2(0, tile_map_node->map_to_local(r_cell_data.coords).y + tile_y_sort_origin + y_sort_origin);
+ if (is_y_sort_enabled()) {
+ canvas_items_position = Vector2(0, tile_set->map_to_local(r_cell_data.coords).y + tile_y_sort_origin + y_sort_origin);
quadrant_coords = canvas_items_position * 100;
} else {
int quad_size = tile_map_node->get_rendering_quadrant_size();
@@ -500,7 +505,7 @@ void TileMapLayer::_rendering_quadrants_update_cell(CellData &r_cell_data, SelfL
quadrant_coords = Vector2i(
coords.x > 0 ? coords.x / quad_size : (coords.x - (quad_size - 1)) / quad_size,
coords.y > 0 ? coords.y / quad_size : (coords.y - (quad_size - 1)) / quad_size);
- canvas_items_position = tile_map_node->map_to_local(quad_size * quadrant_coords);
+ canvas_items_position = tile_set->map_to_local(quad_size * quadrant_coords);
}
Ref<RenderingQuadrant> rendering_quadrant;
@@ -564,8 +569,7 @@ void TileMapLayer::_rendering_occluders_clear_cell(CellData &r_cell_data) {
}
void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
- bool node_visible = tile_map_node->is_visible_in_tree();
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
RenderingServer *rs = RenderingServer::get_singleton();
// Free unused occluders then resize the occluders array.
@@ -606,14 +610,13 @@ void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
if (occluder_polygon.is_valid()) {
// Create or update occluder.
Transform2D xform;
- xform.set_origin(tile_map_node->map_to_local(r_cell_data.coords));
+ xform.set_origin(tile_set->map_to_local(r_cell_data.coords));
if (!occluder.is_valid()) {
occluder = rs->canvas_light_occluder_create();
}
- rs->canvas_light_occluder_set_enabled(occluder, node_visible);
- rs->canvas_light_occluder_set_transform(occluder, tile_map_node->get_global_transform() * xform);
+ rs->canvas_light_occluder_set_transform(occluder, get_global_transform() * xform);
rs->canvas_light_occluder_set_polygon(occluder, tile_data->get_occluder(occlusion_layer_index, flip_h, flip_v, transpose)->get_rid());
- rs->canvas_light_occluder_attach_to_canvas(occluder, tile_map_node->get_canvas());
+ rs->canvas_light_occluder_attach_to_canvas(occluder, get_canvas());
rs->canvas_light_occluder_set_light_mask(occluder, tile_set->get_occlusion_layer_light_mask(occlusion_layer_index));
} else {
// Clear occluder.
@@ -635,7 +638,7 @@ void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
#ifdef DEBUG_ENABLED
void TileMapLayer::_rendering_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
ERR_FAIL_COND(!tile_set.is_valid());
if (!Engine::get_singleton()->is_editor_hint()) {
@@ -671,7 +674,7 @@ void TileMapLayer::_rendering_draw_cell_debug(const RID &p_canvas_item, const Ve
// Draw a placeholder tile.
Transform2D cell_to_quadrant;
- cell_to_quadrant.set_origin(tile_map_node->map_to_local(r_cell_data.coords) - p_quadrant_pos);
+ cell_to_quadrant.set_origin(tile_set->map_to_local(r_cell_data.coords) - p_quadrant_pos);
rs->canvas_item_add_set_transform(p_canvas_item, cell_to_quadrant);
rs->canvas_item_add_circle(p_canvas_item, Vector2(), MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 4.0, color);
}
@@ -684,17 +687,17 @@ void TileMapLayer::_rendering_draw_cell_debug(const RID &p_canvas_item, const Ve
/////////////////////////////// Physics //////////////////////////////////////
void TileMapLayer::_physics_update() {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
// Check if we should cleanup everything.
- bool forced_cleanup = in_destructor || !enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid();
+ bool forced_cleanup = in_destructor || !enabled || !is_inside_tree() || !tile_set.is_valid();
if (forced_cleanup) {
// Clean everything.
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
_physics_clear_cell(kv.value);
}
} else {
- if (_physics_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_TILE_MAP_COLLISION_ANIMATABLE]) {
+ if (_physics_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
// Update all cells.
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
_physics_update_cell(kv.value);
@@ -713,60 +716,43 @@ void TileMapLayer::_physics_update() {
_physics_was_cleaned_up = forced_cleanup;
}
-void TileMapLayer::_physics_notify_tilemap_change(TileMapLayer::DirtyFlags p_what) {
- Transform2D gl_transform = tile_map_node->get_global_transform();
+void TileMapLayer::_physics_notification(int p_what) {
+ const Ref<TileSet> &tile_set = _fetch_tileset();
+ Transform2D gl_transform = get_global_transform();
PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
- bool in_editor = false;
-#ifdef TOOLS_ENABLED
- in_editor = Engine::get_singleton()->is_editor_hint();
-#endif
-
- if (p_what == DIRTY_FLAGS_TILE_MAP_XFORM) {
- if (tile_map_node->is_inside_tree() && (!tile_map_node->is_collision_animatable() || in_editor)) {
+ switch (p_what) {
+ case NOTIFICATION_TRANSFORM_CHANGED:
// Move the collisison shapes along with the TileMap.
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
- const CellData &cell_data = kv.value;
+ if (is_inside_tree() && tile_set.is_valid()) {
+ for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ const CellData &cell_data = kv.value;
- for (RID body : cell_data.bodies) {
- if (body.is_valid()) {
- Transform2D xform(0, tile_map_node->map_to_local(bodies_coords[body]));
- xform = gl_transform * xform;
- ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
- }
- }
- }
- }
- } else if (p_what == DIRTY_FLAGS_TILE_MAP_LOCAL_XFORM) {
- // With collisions animatable, move the collisison shapes along with the TileMap only on local xform change (they are synchornized on physics tick instead).
- if (tile_map_node->is_inside_tree() && tile_map_node->is_collision_animatable() && !in_editor) {
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
- const CellData &cell_data = kv.value;
-
- for (RID body : cell_data.bodies) {
- if (body.is_valid()) {
- Transform2D xform(0, tile_map_node->map_to_local(bodies_coords[body]));
- xform = gl_transform * xform;
- ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
+ for (RID body : cell_data.bodies) {
+ if (body.is_valid()) {
+ Transform2D xform(0, tile_set->map_to_local(kv.key));
+ xform = gl_transform * xform;
+ ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
+ }
}
}
}
- }
- } else if (p_what == DIRTY_FLAGS_TILE_MAP_IN_TREE) {
- // Changes in the tree may cause the space to change (e.g. when reparenting to a SubViewport).
- if (tile_map_node->is_inside_tree()) {
- RID space = tile_map_node->get_world_2d()->get_space();
+ break;
+ case NOTIFICATION_ENTER_TREE:
+ // Changes in the tree may cause the space to change (e.g. when reparenting to a SubViewport).
+ if (is_inside_tree()) {
+ RID space = get_world_2d()->get_space();
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
- const CellData &cell_data = kv.value;
+ for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ const CellData &cell_data = kv.value;
- for (RID body : cell_data.bodies) {
- if (body.is_valid()) {
- ps->body_set_space(body, space);
+ for (RID body : cell_data.bodies) {
+ if (body.is_valid()) {
+ ps->body_set_space(body, space);
+ }
}
}
}
- }
}
}
@@ -784,9 +770,10 @@ void TileMapLayer::_physics_clear_cell(CellData &r_cell_data) {
}
void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
- Transform2D gl_transform = tile_map_node->get_global_transform();
- RID space = tile_map_node->get_world_2d()->get_space();
+ const TileMap *tile_map_node = _fetch_tilemap();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
+ Transform2D gl_transform = get_global_transform();
+ RID space = get_world_2d()->get_space();
PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
// Recreate bodies and shapes.
@@ -813,10 +800,11 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
// Free unused bodies then resize the bodies array.
for (uint32_t i = tile_set->get_physics_layers_count(); i < r_cell_data.bodies.size(); i++) {
- RID body = r_cell_data.bodies[i];
+ RID &body = r_cell_data.bodies[i];
if (body.is_valid()) {
bodies_coords.erase(body);
ps->free(body);
+ body = RID();
}
}
r_cell_data.bodies.resize(tile_set->get_physics_layers_count());
@@ -844,7 +832,7 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
ps->body_set_space(body, space);
Transform2D xform;
- xform.set_origin(tile_map_node->map_to_local(r_cell_data.coords));
+ xform.set_origin(tile_set->map_to_local(r_cell_data.coords));
xform = gl_transform * xform;
ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
@@ -900,17 +888,18 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
#ifdef DEBUG_ENABLED
void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) {
// Draw the debug collision shapes.
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ TileMap *tile_map_node = _fetch_tilemap();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
ERR_FAIL_COND(!tile_set.is_valid());
- if (!tile_map_node->get_tree()) {
+ if (!get_tree()) {
return;
}
bool show_collision = false;
switch (tile_map_node->get_collision_visibility_mode()) {
case TileMap::VISIBILITY_MODE_DEFAULT:
- show_collision = !Engine::get_singleton()->is_editor_hint() && tile_map_node->get_tree()->is_debugging_collisions_hint();
+ show_collision = !Engine::get_singleton()->is_editor_hint() && get_tree()->is_debugging_collisions_hint();
break;
case TileMap::VISIBILITY_MODE_FORCE_HIDE:
show_collision = false;
@@ -926,12 +915,12 @@ void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vect
RenderingServer *rs = RenderingServer::get_singleton();
PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
- Color debug_collision_color = tile_map_node->get_tree()->get_debug_collisions_color();
+ Color debug_collision_color = get_tree()->get_debug_collisions_color();
Vector<Color> color;
color.push_back(debug_collision_color);
Transform2D quadrant_to_local(0, p_quadrant_pos);
- Transform2D global_to_quadrant = (tile_map_node->get_global_transform() * quadrant_to_local).affine_inverse();
+ Transform2D global_to_quadrant = (get_global_transform() * quadrant_to_local).affine_inverse();
for (RID body : r_cell_data.bodies) {
if (body.is_valid()) {
@@ -956,11 +945,11 @@ void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vect
void TileMapLayer::_navigation_update() {
ERR_FAIL_NULL(NavigationServer2D::get_singleton());
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
NavigationServer2D *ns = NavigationServer2D::get_singleton();
// Check if we should cleanup everything.
- bool forced_cleanup = in_destructor || !enabled || !navigation_enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid();
+ bool forced_cleanup = in_destructor || !enabled || !navigation_enabled || !is_inside_tree() || !tile_set.is_valid();
// ----------- Layer level processing -----------
if (forced_cleanup) {
@@ -973,7 +962,7 @@ void TileMapLayer::_navigation_update() {
if (!navigation_map.is_valid()) {
if (layer_index_in_tile_map_node == 0) {
// Use the default World2D navigation map for the first layer when empty.
- navigation_map = tile_map_node->get_world_2d()->get_navigation_map();
+ navigation_map = get_world_2d()->get_navigation_map();
uses_world_navigation_map = true;
} else {
RID new_layer_map = ns->map_create();
@@ -993,7 +982,7 @@ void TileMapLayer::_navigation_update() {
_navigation_clear_cell(kv.value);
}
} else {
- if (_navigation_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]) {
+ if (_navigation_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
// Update all cells.
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
_navigation_update_cell(kv.value);
@@ -1005,9 +994,18 @@ void TileMapLayer::_navigation_update() {
_navigation_update_cell(cell_data);
}
}
+ }
+
+ // -----------
+ // Mark the navigation state as up to date.
+ _navigation_was_cleaned_up = forced_cleanup;
+}
- if (dirty.flags[DIRTY_FLAGS_TILE_MAP_XFORM]) {
- Transform2D tilemap_xform = tile_map_node->get_global_transform();
+void TileMapLayer::_navigation_notification(int p_what) {
+ const Ref<TileSet> &tile_set = _fetch_tileset();
+ if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
+ if (tile_set.is_valid()) {
+ Transform2D tilemap_xform = get_global_transform();
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
const CellData &cell_data = kv.value;
// Update navigation regions transform.
@@ -1016,16 +1014,12 @@ void TileMapLayer::_navigation_update() {
continue;
}
Transform2D tile_transform;
- tile_transform.set_origin(tile_map_node->map_to_local(kv.key));
+ tile_transform.set_origin(tile_set->map_to_local(kv.key));
NavigationServer2D::get_singleton()->region_set_transform(region, tilemap_xform * tile_transform);
}
}
}
}
-
- // -----------
- // Mark the navigation state as up to date.
- _navigation_was_cleaned_up = forced_cleanup;
}
void TileMapLayer::_navigation_clear_cell(CellData &r_cell_data) {
@@ -1042,9 +1036,10 @@ void TileMapLayer::_navigation_clear_cell(CellData &r_cell_data) {
}
void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const TileMap *tile_map_node = _fetch_tilemap();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
NavigationServer2D *ns = NavigationServer2D::get_singleton();
- Transform2D tilemap_xform = tile_map_node->get_global_transform();
+ Transform2D gl_xform = get_global_transform();
// Get the navigation polygons and create regions.
TileMapCell &c = r_cell_data.cell;
@@ -1088,13 +1083,13 @@ void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) {
if (navigation_polygon.is_valid() && (navigation_polygon->get_polygon_count() > 0 || navigation_polygon->get_outline_count() > 0)) {
// Create or update regions.
Transform2D tile_transform;
- tile_transform.set_origin(tile_map_node->map_to_local(r_cell_data.coords));
+ tile_transform.set_origin(tile_set->map_to_local(r_cell_data.coords));
if (!region.is_valid()) {
region = ns->region_create();
}
ns->region_set_owner_id(region, tile_map_node->get_instance_id());
ns->region_set_map(region, navigation_map);
- ns->region_set_transform(region, tilemap_xform * tile_transform);
+ ns->region_set_transform(region, gl_xform * tile_transform);
ns->region_set_navigation_layers(region, tile_set->get_navigation_layer_layers(navigation_layer_index));
ns->region_set_navigation_polygon(region, navigation_polygon);
} else {
@@ -1119,10 +1114,11 @@ void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) {
#ifdef DEBUG_ENABLED
void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) {
// Draw the debug collision shapes.
+ const TileMap *tile_map_node = _fetch_tilemap();
bool show_navigation = false;
switch (tile_map_node->get_navigation_visibility_mode()) {
case TileMap::VISIBILITY_MODE_DEFAULT:
- show_navigation = !Engine::get_singleton()->is_editor_hint() && tile_map_node->get_tree()->is_debugging_navigation_hint();
+ show_navigation = !Engine::get_singleton()->is_editor_hint() && get_tree()->is_debugging_navigation_hint();
break;
case TileMap::VISIBILITY_MODE_FORCE_HIDE:
show_navigation = false;
@@ -1140,7 +1136,7 @@ void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const V
return;
}
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
RenderingServer *rs = RenderingServer::get_singleton();
const NavigationServer2D *ns2d = NavigationServer2D::get_singleton();
@@ -1170,7 +1166,7 @@ void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const V
}
Transform2D cell_to_quadrant;
- cell_to_quadrant.set_origin(tile_map_node->map_to_local(r_cell_data.coords) - p_quadrant_pos);
+ cell_to_quadrant.set_origin(tile_set->map_to_local(r_cell_data.coords) - p_quadrant_pos);
rs->canvas_item_add_set_transform(p_canvas_item, cell_to_quadrant);
for (int layer_index = 0; layer_index < tile_set->get_navigation_layers_count(); layer_index++) {
@@ -1226,10 +1222,10 @@ void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const V
/////////////////////////////// Scenes //////////////////////////////////////
void TileMapLayer::_scenes_update() {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
// Check if we should cleanup everything.
- bool forced_cleanup = in_destructor || !enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid();
+ bool forced_cleanup = in_destructor || !enabled || !is_inside_tree() || !tile_set.is_valid();
if (forced_cleanup) {
// Clean everything.
@@ -1237,7 +1233,7 @@ void TileMapLayer::_scenes_update() {
_scenes_clear_cell(kv.value);
}
} else {
- if (_scenes_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]) {
+ if (_scenes_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
// Update all cells.
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
_scenes_update_cell(kv.value);
@@ -1257,6 +1253,11 @@ void TileMapLayer::_scenes_update() {
}
void TileMapLayer::_scenes_clear_cell(CellData &r_cell_data) {
+ const TileMap *tile_map_node = _fetch_tilemap();
+ if (!tile_map_node) {
+ return;
+ }
+
// Cleanup existing scene.
Node *node = tile_map_node->get_node_or_null(r_cell_data.scene);
if (node) {
@@ -1266,7 +1267,8 @@ void TileMapLayer::_scenes_clear_cell(CellData &r_cell_data) {
}
void TileMapLayer::_scenes_update_cell(CellData &r_cell_data) {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ TileMap *tile_map_node = _fetch_tilemap();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
// Clear the scene in any case.
_scenes_clear_cell(r_cell_data);
@@ -1287,10 +1289,10 @@ void TileMapLayer::_scenes_update_cell(CellData &r_cell_data) {
Control *scene_as_control = Object::cast_to<Control>(scene);
Node2D *scene_as_node2d = Object::cast_to<Node2D>(scene);
if (scene_as_control) {
- scene_as_control->set_position(tile_map_node->map_to_local(r_cell_data.coords) + scene_as_control->get_position());
+ scene_as_control->set_position(tile_set->map_to_local(r_cell_data.coords) + scene_as_control->get_position());
} else if (scene_as_node2d) {
Transform2D xform;
- xform.set_origin(tile_map_node->map_to_local(r_cell_data.coords));
+ xform.set_origin(tile_set->map_to_local(r_cell_data.coords));
scene_as_node2d->set_transform(xform * scene_as_node2d->get_transform());
}
tile_map_node->add_child(scene);
@@ -1303,7 +1305,7 @@ void TileMapLayer::_scenes_update_cell(CellData &r_cell_data) {
#ifdef DEBUG_ENABLED
void TileMapLayer::_scenes_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
ERR_FAIL_COND(!tile_set.is_valid());
if (!Engine::get_singleton()->is_editor_hint()) {
@@ -1341,7 +1343,7 @@ void TileMapLayer::_scenes_draw_cell_debug(const RID &p_canvas_item, const Vecto
// Draw a placeholder tile.
Transform2D cell_to_quadrant;
- cell_to_quadrant.set_origin(tile_map_node->map_to_local(r_cell_data.coords) - p_quadrant_pos);
+ cell_to_quadrant.set_origin(tile_set->map_to_local(r_cell_data.coords) - p_quadrant_pos);
rs->canvas_item_add_set_transform(p_canvas_item, cell_to_quadrant);
rs->canvas_item_add_circle(p_canvas_item, Vector2(), MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 4.0, color);
}
@@ -1353,10 +1355,11 @@ void TileMapLayer::_scenes_draw_cell_debug(const RID &p_canvas_item, const Vecto
/////////////////////////////////////////////////////////////////////
void TileMapLayer::_build_runtime_update_tile_data() {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const TileMap *tile_map_node = _fetch_tilemap();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
// Check if we should cleanup everything.
- bool forced_cleanup = in_destructor || !enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid() || !tile_map_node->is_visible_in_tree();
+ bool forced_cleanup = in_destructor || !enabled || !tile_set.is_valid() || !is_visible_in_tree();
if (!forced_cleanup) {
if (tile_map_node->GDVIRTUAL_IS_OVERRIDDEN(_use_tile_data_runtime_update) && tile_map_node->GDVIRTUAL_IS_OVERRIDDEN(_tile_data_runtime_update)) {
if (_runtime_update_tile_data_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]) {
@@ -1382,7 +1385,8 @@ void TileMapLayer::_build_runtime_update_tile_data() {
}
void TileMapLayer::_build_runtime_update_tile_data_for_cell(CellData &r_cell_data, bool p_auto_add_to_dirty_list) {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ TileMap *tile_map_node = _fetch_tilemap();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
TileMapCell &c = r_cell_data.cell;
TileSetSource *source;
@@ -1425,7 +1429,7 @@ void TileMapLayer::_clear_runtime_update_tile_data() {
}
TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern) {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
if (!tile_set.is_valid()) {
return TileSet::TerrainsPattern();
}
@@ -1437,7 +1441,7 @@ TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints
int score = 0;
// Check the center bit constraint.
- TerrainConstraint terrain_constraint = TerrainConstraint(tile_map_node, p_position, terrain_pattern.get_terrain());
+ TerrainConstraint terrain_constraint = TerrainConstraint(tile_set, p_position, terrain_pattern.get_terrain());
const RBSet<TerrainConstraint>::Element *in_set_constraint_element = p_constraints.find(terrain_constraint);
if (in_set_constraint_element) {
if (in_set_constraint_element->get().get_terrain() != terrain_constraint.get_terrain()) {
@@ -1453,7 +1457,7 @@ TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) {
// Check if the bit is compatible with the constraints.
- TerrainConstraint terrain_bit_constraint = TerrainConstraint(tile_map_node, p_position, bit, terrain_pattern.get_terrain_peering_bit(bit));
+ TerrainConstraint terrain_bit_constraint = TerrainConstraint(tile_set, p_position, bit, terrain_pattern.get_terrain_peering_bit(bit));
in_set_constraint_element = p_constraints.find(terrain_bit_constraint);
if (in_set_constraint_element) {
if (in_set_constraint_element->get().get_terrain() != terrain_bit_constraint.get_terrain()) {
@@ -1486,19 +1490,19 @@ TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints
}
RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
if (!tile_set.is_valid()) {
return RBSet<TerrainConstraint>();
}
// Compute the constraints needed from the surrounding tiles.
RBSet<TerrainConstraint> output;
- output.insert(TerrainConstraint(tile_map_node, p_position, p_terrains_pattern.get_terrain()));
+ output.insert(TerrainConstraint(tile_set, p_position, p_terrains_pattern.get_terrain()));
for (uint32_t i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor side = TileSet::CellNeighbor(i);
if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, side)) {
- TerrainConstraint c = TerrainConstraint(tile_map_node, p_position, side, p_terrains_pattern.get_terrain_peering_bit(side));
+ TerrainConstraint c = TerrainConstraint(tile_set, p_position, side, p_terrains_pattern.get_terrain_peering_bit(side));
output.insert(c);
}
}
@@ -1507,7 +1511,7 @@ RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_added_patte
}
RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_painted_cells_list(const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
if (!tile_set.is_valid()) {
return RBSet<TerrainConstraint>();
}
@@ -1520,7 +1524,7 @@ RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_painted_cel
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { // Iterates over neighbor bits.
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) {
- dummy_constraints.insert(TerrainConstraint(tile_map_node, E, bit, -1));
+ dummy_constraints.insert(TerrainConstraint(tile_set, E, bit, -1));
}
}
}
@@ -1587,27 +1591,89 @@ RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_painted_cel
int terrain = (tile_data && tile_data->get_terrain_set() == p_terrain_set) ? tile_data->get_terrain() : -1;
if (!p_ignore_empty_terrains || terrain >= 0) {
- constraints.insert(TerrainConstraint(tile_map_node, E_coords, terrain));
+ constraints.insert(TerrainConstraint(tile_set, E_coords, terrain));
}
}
return constraints;
}
-void TileMapLayer::set_tile_map(TileMap *p_tile_map) {
- tile_map_node = p_tile_map;
+void TileMapLayer::_renamed() {
+ TileMap *tile_map_node = _fetch_tilemap();
+ tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
+}
+
+void TileMapLayer::_update_notify_local_transform() {
+ TileMap *tile_map_node = _fetch_tilemap();
+ bool notify = tile_map_node->is_collision_animatable() || is_y_sort_enabled();
+ if (!notify) {
+ if (is_y_sort_enabled()) {
+ notify = true;
+ }
+ }
+ set_notify_local_transform(notify);
+}
+
+void TileMapLayer::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_POSTINITIALIZE: {
+ connect(SNAME("renamed"), callable_mp(this, &TileMapLayer::_renamed));
+ break;
+ }
+ case NOTIFICATION_ENTER_TREE: {
+ _update_notify_local_transform();
+ dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] = true;
+ TileMap *tile_map_node = _fetch_tilemap();
+ tile_map_node->queue_internal_update();
+ } break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] = true;
+ TileMap *tile_map_node = _fetch_tilemap();
+ tile_map_node->queue_internal_update();
+ } break;
+
+ case TileMap::NOTIFICATION_ENTER_CANVAS: {
+ dirty.flags[DIRTY_FLAGS_LAYER_IN_CANVAS] = true;
+ TileMap *tile_map_node = _fetch_tilemap();
+ tile_map_node->queue_internal_update();
+ } break;
+
+ case TileMap::NOTIFICATION_EXIT_CANVAS: {
+ dirty.flags[DIRTY_FLAGS_LAYER_IN_CANVAS] = true;
+ TileMap *tile_map_node = _fetch_tilemap();
+ tile_map_node->queue_internal_update();
+ } break;
+
+ case TileMap::NOTIFICATION_VISIBILITY_CHANGED: {
+ dirty.flags[DIRTY_FLAGS_LAYER_VISIBILITY] = true;
+ TileMap *tile_map_node = _fetch_tilemap();
+ tile_map_node->queue_internal_update();
+ } break;
+ }
+
+ _rendering_notification(p_what);
+ _physics_notification(p_what);
+ _navigation_notification(p_what);
}
void TileMapLayer::set_layer_index_in_tile_map_node(int p_index) {
if (p_index == layer_index_in_tile_map_node) {
return;
}
+ TileMap *tile_map_node = _fetch_tilemap();
layer_index_in_tile_map_node = p_index;
dirty.flags[DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE] = true;
tile_map_node->queue_internal_update();
}
Rect2 TileMapLayer::get_rect(bool &r_changed) const {
+ const Ref<TileSet> &tile_set = _fetch_tileset();
+ if (tile_set.is_null()) {
+ r_changed = rect_cache != Rect2();
+ return Rect2();
+ }
+
// Compute the displayed area of the tilemap.
r_changed = false;
#ifdef DEBUG_ENABLED
@@ -1617,7 +1683,7 @@ Rect2 TileMapLayer::get_rect(bool &r_changed) const {
bool first = true;
for (const KeyValue<Vector2i, CellData> &E : tile_map) {
Rect2 r;
- r.position = tile_map_node->map_to_local(E.key);
+ r.position = tile_set->map_to_local(E.key);
r.size = Size2();
if (first) {
r_total = r;
@@ -1637,7 +1703,7 @@ Rect2 TileMapLayer::get_rect(bool &r_changed) const {
}
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints) {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
if (!tile_set.is_valid()) {
return HashMap<Vector2i, TileSet::TerrainsPattern>();
}
@@ -1686,7 +1752,7 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_constrain
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
HashMap<Vector2i, TileSet::TerrainsPattern> output;
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
ERR_FAIL_COND_V(!tile_set.is_valid(), output);
ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
@@ -1704,8 +1770,8 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(c
// Find the adequate neighbor.
for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
- if (tile_map_node->is_existing_neighbor(bit)) {
- Vector2i neighbor = tile_map_node->get_neighbor_cell(coords, bit);
+ if (tile_set->is_existing_neighbor(bit)) {
+ Vector2i neighbor = tile_set->get_neighbor_cell(coords, bit);
if (!can_modify_set.has(neighbor)) {
can_modify_list.push_back(neighbor);
can_modify_set.insert(neighbor);
@@ -1746,7 +1812,7 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(c
// Add new constraints from the path drawn.
for (Vector2i coords : p_coords_array) {
// Constraints on the center bit.
- TerrainConstraint c = TerrainConstraint(tile_map_node, coords, p_terrain);
+ TerrainConstraint c = TerrainConstraint(tile_set, coords, p_terrain);
c.set_priority(10);
constraints.insert(c);
@@ -1754,11 +1820,11 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(c
for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) {
- c = TerrainConstraint(tile_map_node, coords, bit, p_terrain);
+ c = TerrainConstraint(tile_set, coords, bit, p_terrain);
c.set_priority(10);
if ((int(bit) % 2) == 0) {
// Side peering bits: add the constraint if the center is of the same terrain.
- Vector2i neighbor = tile_map_node->get_neighbor_cell(coords, bit);
+ Vector2i neighbor = tile_set->get_neighbor_cell(coords, bit);
if (cells_with_terrain_center_bit.has(neighbor)) {
constraints.insert(c);
}
@@ -1792,7 +1858,7 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(c
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
HashMap<Vector2i, TileSet::TerrainsPattern> output;
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
ERR_FAIL_COND_V(!tile_set.is_valid(), output);
ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
@@ -1803,8 +1869,8 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(cons
TileSet::CellNeighbor found_bit = TileSet::CELL_NEIGHBOR_MAX;
for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
- if (tile_map_node->is_existing_neighbor(bit)) {
- if (tile_map_node->get_neighbor_cell(p_coords_array[i], bit) == p_coords_array[i + 1]) {
+ if (tile_set->is_existing_neighbor(bit)) {
+ if (tile_set->get_neighbor_cell(p_coords_array[i], bit) == p_coords_array[i + 1]) {
found_bit = bit;
break;
}
@@ -1829,7 +1895,7 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(cons
for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) {
- Vector2i neighbor = tile_map_node->get_neighbor_cell(coords, bit);
+ Vector2i neighbor = tile_set->get_neighbor_cell(coords, bit);
if (!can_modify_set.has(neighbor)) {
can_modify_list.push_back(neighbor);
can_modify_set.insert(neighbor);
@@ -1843,13 +1909,13 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(cons
// Add new constraints from the path drawn.
for (Vector2i coords : p_coords_array) {
// Constraints on the center bit.
- TerrainConstraint c = TerrainConstraint(tile_map_node, coords, p_terrain);
+ TerrainConstraint c = TerrainConstraint(tile_set, coords, p_terrain);
c.set_priority(10);
constraints.insert(c);
}
for (int i = 0; i < p_coords_array.size() - 1; i++) {
// Constraints on the peering bits.
- TerrainConstraint c = TerrainConstraint(tile_map_node, p_coords_array[i], neighbor_list[i], p_terrain);
+ TerrainConstraint c = TerrainConstraint(tile_set, p_coords_array[i], neighbor_list[i], p_terrain);
c.set_priority(10);
constraints.insert(c);
}
@@ -1866,7 +1932,7 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(cons
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_pattern(const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains) {
HashMap<Vector2i, TileSet::TerrainsPattern> output;
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
ERR_FAIL_COND_V(!tile_set.is_valid(), output);
ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
@@ -1885,7 +1951,7 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_pattern(c
for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(j);
if (tile_set->is_valid_terrain_peering_bit(p_terrain_set, bit)) {
- Vector2i neighbor = tile_map_node->get_neighbor_cell(coords, bit);
+ Vector2i neighbor = tile_set->get_neighbor_cell(coords, bit);
if (!can_modify_set.has(neighbor)) {
can_modify_list.push_back(neighbor);
can_modify_set.insert(neighbor);
@@ -1922,7 +1988,7 @@ TileMapCell TileMapLayer::get_cell(const Vector2i &p_coords, bool p_use_proxies)
return TileMapCell();
} else {
TileMapCell c = tile_map.find(p_coords)->value.cell;
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
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];
@@ -1998,7 +2064,7 @@ void TileMapLayer::set_tile_data(TileMapDataFormat p_format, const Vector<int> &
coord_y = decode_uint16(&local[10]);
}
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
if (tile_set.is_valid()) {
Array a = tile_set->compatibility_tilemap_map(v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose);
if (a.size() == 3) {
@@ -2039,9 +2105,9 @@ Vector<int> TileMapLayer::get_tile_data() const {
}
void TileMapLayer::notify_tile_map_change(DirtyFlags p_what) {
+ TileMap *tile_map_node = _fetch_tilemap();
dirty.flags[p_what] = true;
tile_map_node->queue_internal_update();
- _physics_notify_tilemap_change(p_what);
}
void TileMapLayer::internal_update() {
@@ -2124,7 +2190,10 @@ void TileMapLayer::set_cell(const Vector2i &p_coords, int p_source_id, const Vec
if (!E->value.dirty_list_element.in_list()) {
dirty.cell_list.add(&(E->value.dirty_list_element));
}
- tile_map_node->queue_internal_update();
+ TileMap *tile_map_node = _fetch_tilemap();
+ if (tile_map_node) { // Needed to avoid crashes in destructor.
+ tile_map_node->queue_internal_update();
+ }
used_rect_cache_dirty = true;
}
@@ -2141,7 +2210,7 @@ int TileMapLayer::get_cell_source_id(const Vector2i &p_coords, bool p_use_proxie
return TileSet::INVALID_SOURCE;
}
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
if (p_use_proxies && tile_set.is_valid()) {
Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile);
return proxyed[0];
@@ -2158,7 +2227,7 @@ Vector2i TileMapLayer::get_cell_atlas_coords(const Vector2i &p_coords, bool p_us
return TileSetSource::INVALID_ATLAS_COORDS;
}
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
if (p_use_proxies && tile_set.is_valid()) {
Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile);
return proxyed[1];
@@ -2175,7 +2244,7 @@ int TileMapLayer::get_cell_alternative_tile(const Vector2i &p_coords, bool p_use
return TileSetSource::INVALID_TILE_ALTERNATIVE;
}
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
if (p_use_proxies && tile_set.is_valid()) {
Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile);
return proxyed[2];
@@ -2190,7 +2259,7 @@ TileData *TileMapLayer::get_cell_tile_data(const Vector2i &p_coords, bool p_use_
return nullptr;
}
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
Ref<TileSetAtlasSource> source = tile_set->get_source(source_id);
if (source.is_valid()) {
return source->get_tile_data(get_cell_atlas_coords(p_coords, p_use_proxies), get_cell_alternative_tile(p_coords, p_use_proxies));
@@ -2208,7 +2277,7 @@ void TileMapLayer::clear() {
}
Ref<TileMapPattern> TileMapLayer::get_pattern(TypedArray<Vector2i> p_coords_array) {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
ERR_FAIL_COND_V(!tile_set.is_valid(), nullptr);
Ref<TileMapPattern> output;
@@ -2262,19 +2331,19 @@ Ref<TileMapPattern> TileMapLayer::get_pattern(TypedArray<Vector2i> p_coords_arra
}
void TileMapLayer::set_pattern(const Vector2i &p_position, const Ref<TileMapPattern> p_pattern) {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
ERR_FAIL_COND(tile_set.is_null());
ERR_FAIL_COND(p_pattern.is_null());
TypedArray<Vector2i> used_cells = p_pattern->get_used_cells();
for (int i = 0; i < used_cells.size(); i++) {
- Vector2i coords = tile_map_node->map_pattern(p_position, used_cells[i], p_pattern);
+ Vector2i coords = tile_set->map_pattern(p_position, used_cells[i], p_pattern);
set_cell(coords, p_pattern->get_cell_source_id(used_cells[i]), p_pattern->get_cell_atlas_coords(used_cells[i]), p_pattern->get_cell_alternative_tile(used_cells[i]));
}
}
void TileMapLayer::set_cells_terrain_connect(TypedArray<Vector2i> p_cells, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
ERR_FAIL_COND(!tile_set.is_valid());
ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count());
@@ -2314,7 +2383,7 @@ void TileMapLayer::set_cells_terrain_connect(TypedArray<Vector2i> p_cells, int p
}
void TileMapLayer::set_cells_terrain_path(TypedArray<Vector2i> p_path, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
- const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
+ const Ref<TileSet> &tile_set = _fetch_tileset();
ERR_FAIL_COND(!tile_set.is_valid());
ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count());
@@ -2415,24 +2484,13 @@ Rect2i TileMapLayer::get_used_rect() const {
return used_rect_cache;
}
-void TileMapLayer::set_name(String p_name) {
- if (name == p_name) {
- return;
- }
- name = p_name;
- tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
-}
-
-String TileMapLayer::get_name() const {
- return name;
-}
-
void TileMapLayer::set_enabled(bool p_enabled) {
if (enabled == p_enabled) {
return;
}
enabled = p_enabled;
dirty.flags[DIRTY_FLAGS_LAYER_ENABLED] = true;
+ TileMap *tile_map_node = _fetch_tilemap();
tile_map_node->queue_internal_update();
tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
@@ -2443,34 +2501,29 @@ bool TileMapLayer::is_enabled() const {
return enabled;
}
-void TileMapLayer::set_modulate(Color p_modulate) {
- if (modulate == p_modulate) {
+void TileMapLayer::set_self_modulate(const Color &p_self_modulate) {
+ if (get_self_modulate() == p_self_modulate) {
return;
}
- modulate = p_modulate;
- dirty.flags[DIRTY_FLAGS_LAYER_MODULATE] = true;
+ CanvasItem::set_self_modulate(p_self_modulate);
+ dirty.flags[DIRTY_FLAGS_LAYER_SELF_MODULATE] = true;
+ TileMap *tile_map_node = _fetch_tilemap();
tile_map_node->queue_internal_update();
tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
}
-Color TileMapLayer::get_modulate() const {
- return modulate;
-}
-
void TileMapLayer::set_y_sort_enabled(bool p_y_sort_enabled) {
- if (y_sort_enabled == p_y_sort_enabled) {
+ if (is_y_sort_enabled() == p_y_sort_enabled) {
return;
}
- y_sort_enabled = p_y_sort_enabled;
+ CanvasItem::set_y_sort_enabled(p_y_sort_enabled);
dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] = true;
+ TileMap *tile_map_node = _fetch_tilemap();
tile_map_node->queue_internal_update();
tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
tile_map_node->update_configuration_warnings();
-}
-
-bool TileMapLayer::is_y_sort_enabled() const {
- return y_sort_enabled;
+ _update_notify_local_transform();
}
void TileMapLayer::set_y_sort_origin(int p_y_sort_origin) {
@@ -2479,6 +2532,7 @@ void TileMapLayer::set_y_sort_origin(int p_y_sort_origin) {
}
y_sort_origin = p_y_sort_origin;
dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] = true;
+ TileMap *tile_map_node = _fetch_tilemap();
tile_map_node->queue_internal_update();
tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
}
@@ -2488,19 +2542,28 @@ int TileMapLayer::get_y_sort_origin() const {
}
void TileMapLayer::set_z_index(int p_z_index) {
- if (z_index == p_z_index) {
+ if (get_z_index() == p_z_index) {
return;
}
- z_index = p_z_index;
+ CanvasItem::set_z_index(p_z_index);
dirty.flags[DIRTY_FLAGS_LAYER_Z_INDEX] = true;
+ TileMap *tile_map_node = _fetch_tilemap();
tile_map_node->queue_internal_update();
tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
tile_map_node->update_configuration_warnings();
}
-int TileMapLayer::get_z_index() const {
- return z_index;
+void TileMapLayer::set_use_kinematic_bodies(bool p_use_kinematic_bodies) {
+ use_kinematic_bodies = p_use_kinematic_bodies;
+ dirty.flags[DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES] = p_use_kinematic_bodies;
+ TileMap *tile_map_node = _fetch_tilemap();
+ tile_map_node->queue_internal_update();
+ tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
+}
+
+bool TileMapLayer::is_using_kinematic_bodies() const {
+ return use_kinematic_bodies;
}
void TileMapLayer::set_navigation_enabled(bool p_enabled) {
@@ -2509,6 +2572,7 @@ void TileMapLayer::set_navigation_enabled(bool p_enabled) {
}
navigation_enabled = p_enabled;
dirty.flags[DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED] = true;
+ TileMap *tile_map_node = _fetch_tilemap();
tile_map_node->queue_internal_update();
tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
}
@@ -2518,9 +2582,9 @@ bool TileMapLayer::is_navigation_enabled() const {
}
void TileMapLayer::set_navigation_map(RID p_map) {
- ERR_FAIL_COND_MSG(!tile_map_node->is_inside_tree(), "A TileMap navigation map can only be changed while inside the SceneTree.");
+ ERR_FAIL_COND_MSG(!is_inside_tree(), "A TileMap navigation map can only be changed while inside the SceneTree.");
navigation_map = p_map;
- uses_world_navigation_map = p_map == tile_map_node->get_world_2d()->get_navigation_map();
+ uses_world_navigation_map = p_map == get_world_2d()->get_navigation_map();
}
RID TileMapLayer::get_navigation_map() const {
@@ -2531,7 +2595,7 @@ RID TileMapLayer::get_navigation_map() const {
}
void TileMapLayer::fix_invalid_tiles() {
- Ref<TileSet> tileset = tile_map_node->get_tileset();
+ Ref<TileSet> tileset = _fetch_tileset();
ERR_FAIL_COND_MSG(tileset.is_null(), "Cannot call fix_invalid_tiles() on a TileMap without a valid TileSet.");
RBSet<Vector2i> coords;
@@ -2554,12 +2618,11 @@ Vector2i TileMapLayer::get_coords_for_body_rid(RID p_physics_body) const {
return bodies_coords[p_physics_body];
}
-TileMapLayer::~TileMapLayer() {
- if (!tile_map_node) {
- // Temporary layer.
- return;
- }
+TileMapLayer::TileMapLayer() {
+ set_notify_transform(true);
+}
+TileMapLayer::~TileMapLayer() {
in_destructor = true;
clear();
internal_update();
@@ -2569,26 +2632,24 @@ HashMap<Vector2i, TileSet::CellNeighbor> TerrainConstraint::get_overlapping_coor
HashMap<Vector2i, TileSet::CellNeighbor> output;
ERR_FAIL_COND_V(is_center_bit(), output);
+ ERR_FAIL_COND_V(!tile_set.is_valid(), output);
- Ref<TileSet> ts = tile_map->get_tileset();
- ERR_FAIL_COND_V(!ts.is_valid(), output);
-
- TileSet::TileShape shape = ts->get_tile_shape();
+ TileSet::TileShape shape = tile_set->get_tile_shape();
if (shape == TileSet::TILE_SHAPE_SQUARE) {
switch (bit) {
case 1:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_RIGHT_SIDE;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_SIDE;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_SIDE;
break;
case 2:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER;
break;
case 3:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_SIDE;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_SIDE;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_SIDE;
break;
default:
ERR_FAIL_V(output);
@@ -2597,47 +2658,47 @@ HashMap<Vector2i, TileSet::CellNeighbor> TerrainConstraint::get_overlapping_coor
switch (bit) {
case 1:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE;
break;
case 2:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_CORNER)] = TileSet::CELL_NEIGHBOR_TOP_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_RIGHT_CORNER;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_CORNER;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_CORNER)] = TileSet::CELL_NEIGHBOR_TOP_CORNER;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_RIGHT_CORNER;
break;
case 3:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
break;
default:
ERR_FAIL_V(output);
}
} else {
// Half offset shapes.
- TileSet::TileOffsetAxis offset_axis = ts->get_tile_offset_axis();
+ TileSet::TileOffsetAxis offset_axis = tile_set->get_tile_offset_axis();
if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
switch (bit) {
case 1:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_RIGHT_SIDE;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_SIDE;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_SIDE;
break;
case 2:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_CORNER;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_CORNER;
break;
case 3:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE;
break;
case 4:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER;
break;
case 5:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
break;
default:
ERR_FAIL_V(output);
@@ -2646,25 +2707,25 @@ HashMap<Vector2i, TileSet::CellNeighbor> TerrainConstraint::get_overlapping_coor
switch (bit) {
case 1:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_RIGHT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER;
break;
case 2:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE;
break;
case 3:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_CORNER;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)] = TileSet::CELL_NEIGHBOR_LEFT_CORNER;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER;
break;
case 4:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_SIDE;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_SIDE;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_SIDE;
break;
case 5:
output[base_cell_coords] = TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE;
- output[tile_map->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
+ output[tile_set->get_neighbor_cell(base_cell_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)] = TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
break;
default:
ERR_FAIL_V(output);
@@ -2674,25 +2735,20 @@ HashMap<Vector2i, TileSet::CellNeighbor> TerrainConstraint::get_overlapping_coor
return output;
}
-TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, int p_terrain) {
- tile_map = p_tile_map;
-
- Ref<TileSet> ts = tile_map->get_tileset();
- ERR_FAIL_COND(!ts.is_valid());
-
+TerrainConstraint::TerrainConstraint(Ref<TileSet> p_tile_set, const Vector2i &p_position, int p_terrain) {
+ ERR_FAIL_COND(!p_tile_set.is_valid());
+ tile_set = p_tile_set;
bit = 0;
base_cell_coords = p_position;
terrain = p_terrain;
}
-TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, const TileSet::CellNeighbor &p_bit, int p_terrain) {
+TerrainConstraint::TerrainConstraint(Ref<TileSet> p_tile_set, const Vector2i &p_position, const TileSet::CellNeighbor &p_bit, int p_terrain) {
// The way we build the constraint make it easy to detect conflicting constraints.
- tile_map = p_tile_map;
-
- Ref<TileSet> ts = tile_map->get_tileset();
- ERR_FAIL_COND(!ts.is_valid());
+ ERR_FAIL_COND(!p_tile_set.is_valid());
+ tile_set = p_tile_set;
- TileSet::TileShape shape = ts->get_tile_shape();
+ TileSet::TileShape shape = tile_set->get_tile_shape();
if (shape == TileSet::TILE_SHAPE_SQUARE) {
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
@@ -2709,23 +2765,23 @@ TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const Vector2i &
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
bit = 2;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
bit = 1;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
bit = 2;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER);
break;
case TileSet::CELL_NEIGHBOR_TOP_SIDE:
bit = 3;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
bit = 2;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE);
break;
default:
ERR_FAIL();
@@ -2735,7 +2791,7 @@ TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const Vector2i &
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
bit = 2;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
bit = 1;
@@ -2751,19 +2807,19 @@ TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const Vector2i &
break;
case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
bit = 2;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
bit = 1;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_CORNER:
bit = 2;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_CORNER);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_CORNER);
break;
case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
bit = 3;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
break;
default:
ERR_FAIL();
@@ -2771,7 +2827,7 @@ TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const Vector2i &
}
} else {
// Half-offset shapes.
- TileSet::TileOffsetAxis offset_axis = ts->get_tile_offset_axis();
+ TileSet::TileOffsetAxis offset_axis = tile_set->get_tile_offset_axis();
if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
@@ -2796,31 +2852,31 @@ TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const Vector2i &
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
bit = 2;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
bit = 1;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
bit = 4;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
bit = 3;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_CORNER:
bit = 2;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
bit = 5;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
bit = 4;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
break;
default:
ERR_FAIL();
@@ -2846,7 +2902,7 @@ TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const Vector2i &
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
bit = 1;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
bit = 5;
@@ -2854,27 +2910,27 @@ TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const Vector2i &
break;
case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
bit = 3;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
bit = 2;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
bit = 1;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_SIDE:
bit = 4;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
bit = 3;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_SIDE);
break;
case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
bit = 5;
- base_cell_coords = p_tile_map->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
+ base_cell_coords = tile_set->get_neighbor_cell(p_position, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
break;
default:
ERR_FAIL();
diff --git a/scene/2d/tile_map_layer.h b/scene/2d/tile_map_layer.h
index f31c5406a4..2cc57f50d1 100644
--- a/scene/2d/tile_map_layer.h
+++ b/scene/2d/tile_map_layer.h
@@ -38,7 +38,7 @@ class TileSetAtlasSource;
class TerrainConstraint {
private:
- const TileMap *tile_map = nullptr;
+ Ref<TileSet> tile_set;
Vector2i base_cell_coords;
int bit = -1;
int terrain = -1;
@@ -83,8 +83,8 @@ public:
return priority;
}
- TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, int p_terrain); // For the center terrain bit
- TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, const TileSet::CellNeighbor &p_bit, int p_terrain); // For peering bits
+ TerrainConstraint(Ref<TileSet> p_tile_set, const Vector2i &p_position, int p_terrain); // For the center terrain bit
+ TerrainConstraint(Ref<TileSet> p_tile_set, const Vector2i &p_position, const TileSet::CellNeighbor &p_bit, int p_terrain); // For peering bits
TerrainConstraint(){};
};
@@ -214,23 +214,24 @@ public:
}
};
-class TileMapLayer : public RefCounted {
- GDCLASS(TileMapLayer, RefCounted);
+class TileMapLayer : public Node2D {
+ GDCLASS(TileMapLayer, Node2D);
public:
enum DirtyFlags {
DIRTY_FLAGS_LAYER_ENABLED = 0,
- DIRTY_FLAGS_LAYER_MODULATE,
+ DIRTY_FLAGS_LAYER_IN_TREE,
+ DIRTY_FLAGS_LAYER_IN_CANVAS,
+ DIRTY_FLAGS_LAYER_LOCAL_TRANSFORM,
+ DIRTY_FLAGS_LAYER_VISIBILITY,
+ DIRTY_FLAGS_LAYER_SELF_MODULATE,
DIRTY_FLAGS_LAYER_Y_SORT_ENABLED,
DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN,
DIRTY_FLAGS_LAYER_Z_INDEX,
+ DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES,
DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED,
DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE,
- DIRTY_FLAGS_TILE_MAP_IN_TREE,
- DIRTY_FLAGS_TILE_MAP_IN_CANVAS,
- DIRTY_FLAGS_TILE_MAP_VISIBILITY,
- DIRTY_FLAGS_TILE_MAP_XFORM,
- DIRTY_FLAGS_TILE_MAP_LOCAL_XFORM,
+
DIRTY_FLAGS_TILE_MAP_SELECTED_LAYER,
DIRTY_FLAGS_TILE_MAP_LIGHT_MASK,
DIRTY_FLAGS_TILE_MAP_MATERIAL,
@@ -239,7 +240,6 @@ public:
DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT,
DIRTY_FLAGS_TILE_MAP_TILE_SET,
DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE,
- DIRTY_FLAGS_TILE_MAP_COLLISION_ANIMATABLE,
DIRTY_FLAGS_TILE_MAP_COLLISION_VISIBILITY_MODE,
DIRTY_FLAGS_TILE_MAP_NAVIGATION_VISIBILITY_MODE,
DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED,
@@ -249,20 +249,15 @@ public:
private:
// Exposed properties.
- String name;
bool enabled = true;
- Color modulate = Color(1, 1, 1, 1);
- bool y_sort_enabled = false;
int y_sort_origin = 0;
- int z_index = 0;
+ bool use_kinematic_bodies = false;
bool navigation_enabled = true;
RID navigation_map;
bool uses_world_navigation_map = false;
// Internal.
- TileMap *tile_map_node = nullptr;
int layer_index_in_tile_map_node = -1;
- RID canvas_item;
HashMap<Vector2i, CellData> tile_map;
// Dirty flag. Allows knowing what was modified since the last update.
@@ -278,6 +273,10 @@ private:
mutable Rect2i used_rect_cache;
mutable bool used_rect_cache_dirty = true;
+ // Method to fetch the TileSet to use
+ TileMap *_fetch_tilemap() const;
+ Ref<TileSet> _fetch_tileset() const;
+
// Runtime tile data.
bool _runtime_update_tile_data_was_cleaned_up = false;
void _build_runtime_update_tile_data();
@@ -296,6 +295,7 @@ private:
HashMap<Vector2i, Ref<RenderingQuadrant>> rendering_quadrant_map;
bool _rendering_was_cleaned_up = false;
void _rendering_update();
+ void _rendering_notification(int p_what);
void _rendering_quadrants_update_cell(CellData &r_cell_data, SelfList<RenderingQuadrant>::List &r_dirty_rendering_quadrant_list);
void _rendering_occluders_clear_cell(CellData &r_cell_data);
void _rendering_occluders_update_cell(CellData &r_cell_data);
@@ -306,7 +306,7 @@ private:
HashMap<RID, Vector2i> bodies_coords; // Mapping for RID to coords.
bool _physics_was_cleaned_up = false;
void _physics_update();
- void _physics_notify_tilemap_change(DirtyFlags p_what);
+ void _physics_notification(int p_what);
void _physics_clear_cell(CellData &r_cell_data);
void _physics_update_cell(CellData &r_cell_data);
#ifdef DEBUG_ENABLED
@@ -315,6 +315,7 @@ private:
bool _navigation_was_cleaned_up = false;
void _navigation_update();
+ void _navigation_notification(int p_what);
void _navigation_clear_cell(CellData &r_cell_data);
void _navigation_update_cell(CellData &r_cell_data);
#ifdef DEBUG_ENABLED
@@ -334,9 +335,14 @@ private:
RBSet<TerrainConstraint> _get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const;
RBSet<TerrainConstraint> _get_terrain_constraints_from_painted_cells_list(const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const;
+ void _renamed();
+ void _update_notify_local_transform();
+
+protected:
+ void _notification(int p_what);
+
public:
// TileMap node.
- void set_tile_map(TileMap *p_tile_map);
void set_layer_index_in_tile_map_node(int p_index);
// Rect caching.
@@ -383,18 +389,15 @@ public:
Rect2i get_used_rect() const;
// Layer properties.
- void set_name(String p_name);
- String get_name() const;
void set_enabled(bool p_enabled);
bool is_enabled() const;
- void set_modulate(Color p_modulate);
- Color get_modulate() const;
- void set_y_sort_enabled(bool p_y_sort_enabled);
- bool is_y_sort_enabled() const;
+ virtual void set_self_modulate(const Color &p_self_modulate) override;
+ virtual void set_y_sort_enabled(bool p_y_sort_enabled) override;
void set_y_sort_origin(int p_y_sort_origin);
int get_y_sort_origin() const;
- void set_z_index(int p_z_index);
- int get_z_index() const;
+ virtual void set_z_index(int p_z_index) override;
+ void set_use_kinematic_bodies(bool p_use_kinematic_bodies);
+ bool is_using_kinematic_bodies() const;
void set_navigation_enabled(bool p_enabled);
bool is_navigation_enabled() const;
void set_navigation_map(RID p_map);
@@ -407,6 +410,7 @@ public:
bool has_body_rid(RID p_physics_body) const;
Vector2i get_coords_for_body_rid(RID p_physics_body) const; // For finding tiles from collision.
+ TileMapLayer();
~TileMapLayer();
};
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index a35ee17868..0dbbbf7fd6 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -277,6 +277,8 @@ void CanvasItem::_notification(int p_what) {
ERR_MAIN_THREAD_GUARD;
ERR_FAIL_COND(!is_inside_tree());
+ _set_global_invalid(true);
+
Node *parent = get_parent();
if (parent) {
CanvasItem *ci = Object::cast_to<CanvasItem>(parent);
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index 36f0e17924..ce1dbce6c3 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -237,7 +237,7 @@ public:
Color get_modulate() const;
Color get_modulate_in_tree() const;
- void set_self_modulate(const Color &p_self_modulate);
+ virtual void set_self_modulate(const Color &p_self_modulate);
Color get_self_modulate() const;
void set_visibility_layer(uint32_t p_visibility_layer);
@@ -248,7 +248,7 @@ public:
/* ORDERING */
- void set_z_index(int p_z);
+ virtual void set_z_index(int p_z);
int get_z_index() const;
int get_effective_z_index() const;
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index a99102e847..66e1b7bcf9 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -1563,6 +1563,632 @@ void TileSet::draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform
}
}
+Vector2 TileSet::map_to_local(const Vector2i &p_pos) const {
+ // SHOULD RETURN THE CENTER OF THE CELL.
+ Vector2 ret = p_pos;
+
+ if (tile_shape == TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE || tile_shape == TileSet::TILE_SHAPE_HEXAGON || tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ // Technically, those 3 shapes are equivalent, as they are basically half-offset, but with different levels or overlap.
+ // square = no overlap, hexagon = 0.25 overlap, isometric = 0.5 overlap.
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ switch (tile_layout) {
+ case TileSet::TILE_LAYOUT_STACKED:
+ ret = Vector2(ret.x + (Math::posmod(ret.y, 2) == 0 ? 0.0 : 0.5), ret.y);
+ break;
+ case TileSet::TILE_LAYOUT_STACKED_OFFSET:
+ ret = Vector2(ret.x + (Math::posmod(ret.y, 2) == 1 ? 0.0 : 0.5), ret.y);
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
+ ret = Vector2(ret.x + ret.y / 2, ret.y);
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_DOWN:
+ ret = Vector2(ret.x / 2, ret.y * 2 + ret.x);
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
+ ret = Vector2((ret.x + ret.y) / 2, ret.y - ret.x);
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
+ ret = Vector2((ret.x - ret.y) / 2, ret.y + ret.x);
+ break;
+ }
+ } else { // TILE_OFFSET_AXIS_VERTICAL.
+ switch (tile_layout) {
+ case TileSet::TILE_LAYOUT_STACKED:
+ ret = Vector2(ret.x, ret.y + (Math::posmod(ret.x, 2) == 0 ? 0.0 : 0.5));
+ break;
+ case TileSet::TILE_LAYOUT_STACKED_OFFSET:
+ ret = Vector2(ret.x, ret.y + (Math::posmod(ret.x, 2) == 1 ? 0.0 : 0.5));
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
+ ret = Vector2(ret.x * 2 + ret.y, ret.y / 2);
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_DOWN:
+ ret = Vector2(ret.x, ret.y + ret.x / 2);
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
+ ret = Vector2(ret.x + ret.y, (ret.y - ret.x) / 2);
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
+ ret = Vector2(ret.x - ret.y, (ret.y + ret.x) / 2);
+ break;
+ }
+ }
+ }
+
+ // Multiply by the overlapping ratio.
+ double overlapping_ratio = 1.0;
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ overlapping_ratio = 0.5;
+ } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) {
+ overlapping_ratio = 0.75;
+ }
+ ret.y *= overlapping_ratio;
+ } else { // TILE_OFFSET_AXIS_VERTICAL.
+ if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ overlapping_ratio = 0.5;
+ } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) {
+ overlapping_ratio = 0.75;
+ }
+ ret.x *= overlapping_ratio;
+ }
+
+ return (ret + Vector2(0.5, 0.5)) * tile_size;
+}
+
+Vector2i TileSet::local_to_map(const Vector2 &p_local_position) const {
+ Vector2 ret = p_local_position;
+ ret /= tile_size;
+
+ // Divide by the overlapping ratio.
+ double overlapping_ratio = 1.0;
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ overlapping_ratio = 0.5;
+ } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) {
+ overlapping_ratio = 0.75;
+ }
+ ret.y /= overlapping_ratio;
+ } else { // TILE_OFFSET_AXIS_VERTICAL.
+ if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ overlapping_ratio = 0.5;
+ } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) {
+ overlapping_ratio = 0.75;
+ }
+ ret.x /= overlapping_ratio;
+ }
+
+ // For each half-offset shape, we check if we are in the corner of the tile, and thus should correct the local position accordingly.
+ if (tile_shape == TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE || tile_shape == TileSet::TILE_SHAPE_HEXAGON || tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ // Technically, those 3 shapes are equivalent, as they are basically half-offset, but with different levels or overlap.
+ // square = no overlap, hexagon = 0.25 overlap, isometric = 0.5 overlap.
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ // Smart floor of the position
+ Vector2 raw_pos = ret;
+ if (Math::posmod(Math::floor(ret.y), 2) ^ (tile_layout == TileSet::TILE_LAYOUT_STACKED_OFFSET)) {
+ ret = Vector2(Math::floor(ret.x + 0.5) - 0.5, Math::floor(ret.y));
+ } else {
+ ret = ret.floor();
+ }
+
+ // Compute the tile offset, and if we might the output for a neighbor top tile.
+ Vector2 in_tile_pos = raw_pos - ret;
+ bool in_top_left_triangle = (in_tile_pos - Vector2(0.5, 0.0)).cross(Vector2(-0.5, 1.0 / overlapping_ratio - 1)) <= 0;
+ bool in_top_right_triangle = (in_tile_pos - Vector2(0.5, 0.0)).cross(Vector2(0.5, 1.0 / overlapping_ratio - 1)) > 0;
+
+ switch (tile_layout) {
+ case TileSet::TILE_LAYOUT_STACKED:
+ ret = ret.floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 0 : -1, -1);
+ } else if (in_top_right_triangle) {
+ ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 1 : 0, -1);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STACKED_OFFSET:
+ ret = ret.floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? -1 : 0, -1);
+ } else if (in_top_right_triangle) {
+ ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 0 : 1, -1);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
+ ret = Vector2(ret.x - ret.y / 2, ret.y).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(0, -1);
+ } else if (in_top_right_triangle) {
+ ret += Vector2i(1, -1);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_DOWN:
+ ret = Vector2(ret.x * 2, ret.y / 2 - ret.x).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(-1, 0);
+ } else if (in_top_right_triangle) {
+ ret += Vector2i(1, -1);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
+ ret = Vector2(ret.x - ret.y / 2, ret.y / 2 + ret.x).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(0, -1);
+ } else if (in_top_right_triangle) {
+ ret += Vector2i(1, 0);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
+ ret = Vector2(ret.x + ret.y / 2, ret.y / 2 - ret.x).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(-1, 0);
+ } else if (in_top_right_triangle) {
+ ret += Vector2i(0, -1);
+ }
+ break;
+ }
+ } else { // TILE_OFFSET_AXIS_VERTICAL.
+ // Smart floor of the position.
+ Vector2 raw_pos = ret;
+ if (Math::posmod(Math::floor(ret.x), 2) ^ (tile_layout == TileSet::TILE_LAYOUT_STACKED_OFFSET)) {
+ ret = Vector2(Math::floor(ret.x), Math::floor(ret.y + 0.5) - 0.5);
+ } else {
+ ret = ret.floor();
+ }
+
+ // Compute the tile offset, and if we might the output for a neighbor top tile.
+ Vector2 in_tile_pos = raw_pos - ret;
+ bool in_top_left_triangle = (in_tile_pos - Vector2(0.0, 0.5)).cross(Vector2(1.0 / overlapping_ratio - 1, -0.5)) > 0;
+ bool in_bottom_left_triangle = (in_tile_pos - Vector2(0.0, 0.5)).cross(Vector2(1.0 / overlapping_ratio - 1, 0.5)) <= 0;
+
+ switch (tile_layout) {
+ case TileSet::TILE_LAYOUT_STACKED:
+ ret = ret.floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 0 : -1);
+ } else if (in_bottom_left_triangle) {
+ ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 1 : 0);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STACKED_OFFSET:
+ ret = ret.floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? -1 : 0);
+ } else if (in_bottom_left_triangle) {
+ ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 0 : 1);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
+ ret = Vector2(ret.x / 2 - ret.y, ret.y * 2).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(0, -1);
+ } else if (in_bottom_left_triangle) {
+ ret += Vector2i(-1, 1);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_DOWN:
+ ret = Vector2(ret.x, ret.y - ret.x / 2).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(-1, 0);
+ } else if (in_bottom_left_triangle) {
+ ret += Vector2i(-1, 1);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
+ ret = Vector2(ret.x / 2 - ret.y, ret.y + ret.x / 2).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(0, -1);
+ } else if (in_bottom_left_triangle) {
+ ret += Vector2i(-1, 0);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
+ ret = Vector2(ret.x / 2 + ret.y, ret.y - ret.x / 2).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(-1, 0);
+ } else if (in_bottom_left_triangle) {
+ ret += Vector2i(0, 1);
+ }
+ break;
+ }
+ }
+ } else {
+ ret = (ret + Vector2(0.00005, 0.00005)).floor();
+ }
+ return Vector2i(ret);
+}
+
+bool TileSet::is_existing_neighbor(TileSet::CellNeighbor p_cell_neighbor) const {
+ if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
+ return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER;
+
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
+ } else {
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
+ } else {
+ return p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
+ }
+ }
+}
+
+Vector2i TileSet::get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const {
+ if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
+ switch (p_cell_neighbor) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
+ return p_coords + Vector2i(1, 0);
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
+ return p_coords + Vector2i(1, 1);
+ case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
+ return p_coords + Vector2i(0, 1);
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
+ return p_coords + Vector2i(-1, 1);
+ case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
+ return p_coords + Vector2i(-1, 0);
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
+ return p_coords + Vector2i(-1, -1);
+ case TileSet::CELL_NEIGHBOR_TOP_SIDE:
+ return p_coords + Vector2i(0, -1);
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
+ return p_coords + Vector2i(1, -1);
+ default:
+ ERR_FAIL_V(p_coords);
+ }
+ } else { // Half-offset shapes (square and hexagon).
+ switch (tile_layout) {
+ case TileSet::TILE_LAYOUT_STACKED: {
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ bool is_offset = p_coords.y % 2;
+ if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
+ return p_coords + Vector2i(1, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(is_offset ? 1 : 0, 1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
+ return p_coords + Vector2i(0, 2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(is_offset ? 0 : -1, 1);
+ } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
+ return p_coords + Vector2i(-1, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(is_offset ? 0 : -1, -1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
+ return p_coords + Vector2i(0, -2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(is_offset ? 1 : 0, -1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ } else {
+ bool is_offset = p_coords.x % 2;
+
+ if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
+ return p_coords + Vector2i(0, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, is_offset ? 1 : 0);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
+ return p_coords + Vector2i(2, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, is_offset ? 0 : -1);
+ } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
+ return p_coords + Vector2i(0, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, is_offset ? 0 : -1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
+ return p_coords + Vector2i(-2, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, is_offset ? 1 : 0);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ }
+ } break;
+ case TileSet::TILE_LAYOUT_STACKED_OFFSET: {
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ bool is_offset = p_coords.y % 2;
+
+ if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
+ return p_coords + Vector2i(1, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(is_offset ? 0 : 1, 1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
+ return p_coords + Vector2i(0, 2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(is_offset ? -1 : 0, 1);
+ } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
+ return p_coords + Vector2i(-1, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(is_offset ? -1 : 0, -1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
+ return p_coords + Vector2i(0, -2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(is_offset ? 0 : 1, -1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ } else {
+ bool is_offset = p_coords.x % 2;
+
+ if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
+ return p_coords + Vector2i(0, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, is_offset ? 0 : 1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
+ return p_coords + Vector2i(2, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, is_offset ? -1 : 0);
+ } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
+ return p_coords + Vector2i(0, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, is_offset ? -1 : 0);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
+ return p_coords + Vector2i(-2, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, is_offset ? 0 : 1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ }
+ } break;
+ case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
+ case TileSet::TILE_LAYOUT_STAIRS_DOWN: {
+ if ((tile_layout == TileSet::TILE_LAYOUT_STAIRS_RIGHT) ^ (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
+ return p_coords + Vector2i(1, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(0, 1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
+ return p_coords + Vector2i(-1, 2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 1);
+ } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
+ return p_coords + Vector2i(-1, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(0, -1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
+ return p_coords + Vector2i(1, -2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, -1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+
+ } else {
+ if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
+ return p_coords + Vector2i(0, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, 0);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
+ return p_coords + Vector2i(2, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, -1);
+ } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
+ return p_coords + Vector2i(0, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 0);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
+ return p_coords + Vector2i(-2, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ }
+ } else {
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
+ return p_coords + Vector2i(2, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, 0);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
+ return p_coords + Vector2i(0, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 1);
+ } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
+ return p_coords + Vector2i(-2, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 0);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
+ return p_coords + Vector2i(0, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, -1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+
+ } else {
+ if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
+ return p_coords + Vector2i(-1, 2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(0, 1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
+ return p_coords + Vector2i(1, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, -1);
+ } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
+ return p_coords + Vector2i(1, -2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(0, -1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
+ return p_coords + Vector2i(-1, 0);
+
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ }
+ }
+ } break;
+ case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
+ case TileSet::TILE_LAYOUT_DIAMOND_DOWN: {
+ if ((tile_layout == TileSet::TILE_LAYOUT_DIAMOND_RIGHT) ^ (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
+ return p_coords + Vector2i(1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(0, 1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
+ return p_coords + Vector2i(-1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 0);
+ } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
+ return p_coords + Vector2i(-1, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(0, -1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
+ return p_coords + Vector2i(1, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, 0);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+
+ } else {
+ if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
+ return p_coords + Vector2i(1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, 0);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
+ return p_coords + Vector2i(1, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(0, -1);
+ } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
+ return p_coords + Vector2i(-1, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 0);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
+ return p_coords + Vector2i(-1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(0, 1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ }
+ } else {
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
+ return p_coords + Vector2i(1, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, 0);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
+ return p_coords + Vector2i(1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(0, 1);
+ } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
+ return p_coords + Vector2i(-1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 0);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
+ return p_coords + Vector2i(-1, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(0, -1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+
+ } else {
+ if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
+ return p_coords + Vector2i(-1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(0, 1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
+ return p_coords + Vector2i(1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, 0);
+ } else if ((tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
+ (tile_shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
+ return p_coords + Vector2i(1, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(0, -1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
+ return p_coords + Vector2i(-1, -1);
+
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 0);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ }
+ }
+ } break;
+ default:
+ ERR_FAIL_V(p_coords);
+ }
+ }
+}
+
+Vector2i TileSet::map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern) {
+ ERR_FAIL_COND_V(p_pattern.is_null(), Vector2i());
+ ERR_FAIL_COND_V(!p_pattern->has_cell(p_coords_in_pattern), Vector2i());
+
+ Vector2i output = p_position_in_tilemap + p_coords_in_pattern;
+ if (tile_shape != TileSet::TILE_SHAPE_SQUARE) {
+ if (tile_layout == TileSet::TILE_LAYOUT_STACKED) {
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(p_position_in_tilemap.y % 2) && bool(p_coords_in_pattern.y % 2)) {
+ output.x += 1;
+ } else if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(p_position_in_tilemap.x % 2) && bool(p_coords_in_pattern.x % 2)) {
+ output.y += 1;
+ }
+ } else if (tile_layout == TileSet::TILE_LAYOUT_STACKED_OFFSET) {
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(p_position_in_tilemap.y % 2) && bool(p_coords_in_pattern.y % 2)) {
+ output.x -= 1;
+ } else if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(p_position_in_tilemap.x % 2) && bool(p_coords_in_pattern.x % 2)) {
+ output.y -= 1;
+ }
+ }
+ }
+
+ return output;
+}
+
Vector<Point2> TileSet::get_terrain_polygon(int p_terrain_set) {
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
return _get_square_terrain_polygon(tile_size);
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index a71982cd56..0a6d879047 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -530,6 +530,13 @@ public:
Vector<Vector2> get_tile_shape_polygon();
void draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform, Color p_color, bool p_filled = false, Ref<Texture2D> p_texture = Ref<Texture2D>());
+ // Used by TileMap/TileMapLayer
+ Vector2 map_to_local(const Vector2i &p_pos) const;
+ Vector2i local_to_map(const Vector2 &p_pos) const;
+ bool is_existing_neighbor(TileSet::CellNeighbor p_cell_neighbor) const;
+ Vector2i get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const;
+ Vector2i map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern);
+
Vector<Point2> get_terrain_polygon(int p_terrain_set);
Vector<Point2> get_terrain_peering_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit);
void draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, const TileData *p_tile_data);