Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move tile transforms handling cache to TileData #84660

Merged
merged 1 commit into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/classes/TileData.xml
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,23 @@
<method name="get_navigation_polygon" qualifiers="const">
<return type="NavigationPolygon" />
<param index="0" name="layer_id" type="int" />
<param index="1" name="flip_h" type="bool" default="false" />
<param index="2" name="flip_v" type="bool" default="false" />
<param index="3" name="transpose" type="bool" default="false" />
<description>
Returns the navigation polygon of the tile for the TileSet navigation layer with index [param layer_id].
[param flip_h], [param flip_v], and [param transpose] allow transforming the returned polygon.
</description>
</method>
<method name="get_occluder" qualifiers="const">
<return type="OccluderPolygon2D" />
<param index="0" name="layer_id" type="int" />
<param index="1" name="flip_h" type="bool" default="false" />
<param index="2" name="flip_v" type="bool" default="false" />
<param index="3" name="transpose" type="bool" default="false" />
<description>
Returns the occluder polygon of the tile for the TileSet occlusion layer with index [param layer_id].
[param flip_h], [param flip_v], and [param transpose] allow transforming the returned polygon.
</description>
</method>
<method name="get_terrain_peering_bit" qualifiers="const">
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/tiles/tile_data_editors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1421,8 +1421,8 @@ void TileDataOcclusionShapeEditor::draw_over_tile(CanvasItem *p_canvas_item, Tra

Variant TileDataOcclusionShapeEditor::_get_painted_value() {
Ref<OccluderPolygon2D> occluder_polygon;
occluder_polygon.instantiate();
if (polygon_editor->get_polygon_count() >= 1) {
occluder_polygon.instantiate();
occluder_polygon->set_polygon(polygon_editor->get_polygon(0));
}
return occluder_polygon;
Expand Down
7 changes: 7 additions & 0 deletions misc/extension_api_validation/4.2-stable.expected
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@ should instead be used to justify these changes and describe how users should wo
Add new entries at the end of the file.

## Changes between 4.2-stable and 4.3-stable

GH-84660
--------
Validate extension JSON: Error: Field 'classes/TileData/methods/get_navigation_polygon/arguments': size changed value in new API, from 1 to 4.
Validate extension JSON: Error: Field 'classes/TileData/methods/get_occluder/arguments': size changed value in new API, from 1 to 4.

Added optional argument to get_navigation_polygon and get_occluder to specify a polygon transform.
14 changes: 12 additions & 2 deletions modules/navigation/nav_mesh_generator_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,13 +591,19 @@ void NavMeshGenerator2D::generator_parse_tilemap_node(const Ref<NavigationPolygo
continue;
}

// Transform flags.
const int alternative_id = tilemap->get_cell_alternative_tile(tilemap_layer, cell, false);
bool flip_h = (alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_H);
bool flip_v = (alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_V);
bool transpose = (alternative_id & TileSetAtlasSource::TRANSFORM_TRANSPOSE);

Transform2D tile_transform;
tile_transform.set_origin(tilemap->map_to_local(cell));

const Transform2D tile_transform_offset = tilemap_xform * tile_transform;

if (navigation_layers_count > 0) {
Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(tilemap_layer);
Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(tilemap_layer, flip_h, flip_v, transpose);
if (navigation_polygon.is_valid()) {
for (int outline_index = 0; outline_index < navigation_polygon->get_outline_count(); outline_index++) {
const Vector<Vector2> &navigation_polygon_outline = navigation_polygon->get_outline(outline_index);
Expand All @@ -622,11 +628,15 @@ void NavMeshGenerator2D::generator_parse_tilemap_node(const Ref<NavigationPolygo

if (physics_layers_count > 0 && (parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_STATIC_COLLIDERS || parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_BOTH) && (tile_set->get_physics_layer_collision_layer(tilemap_layer) & parsed_collision_mask)) {
for (int collision_polygon_index = 0; collision_polygon_index < tile_data->get_collision_polygons_count(tilemap_layer); collision_polygon_index++) {
const Vector<Vector2> &collision_polygon_points = tile_data->get_collision_polygon_points(tilemap_layer, collision_polygon_index);
PackedVector2Array collision_polygon_points = tile_data->get_collision_polygon_points(tilemap_layer, collision_polygon_index);
if (collision_polygon_points.size() == 0) {
continue;
}

if (flip_h || flip_v || transpose) {
collision_polygon_points = TileData::get_transformed_vertices(collision_polygon_points, flip_h, flip_v, transpose);
}

Vector<Vector2> obstruction_outline;
obstruction_outline.resize(collision_polygon_points.size());

Expand Down
126 changes: 27 additions & 99 deletions scene/2d/tile_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,11 +447,12 @@ void TileMapLayer::_rendering_update() {
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
CellData &cell_data = kv.value;
for (const RID &occluder : cell_data.occluders) {
if (occluder.is_valid()) {
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);
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);
}
}
}
Expand Down Expand Up @@ -591,6 +592,11 @@ void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
tile_data = atlas_source->get_tile_data(r_cell_data.cell.get_atlas_coords(), r_cell_data.cell.alternative_tile);
}

// Transform flags.
bool flip_h = (r_cell_data.cell.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H);
bool flip_v = (r_cell_data.cell.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V);
bool transpose = (r_cell_data.cell.alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE);

// Create, update or clear occluders.
for (uint32_t occlusion_layer_index = 0; occlusion_layer_index < r_cell_data.occluders.size(); occlusion_layer_index++) {
Ref<OccluderPolygon2D> occluder_polygon = tile_data->get_occluder(occlusion_layer_index);
Expand All @@ -606,7 +612,7 @@ void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
}
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_polygon(occluder, tile_map_node->get_transformed_polygon(Ref<Resource>(tile_data->get_occluder(occlusion_layer_index)), r_cell_data.cell.alternative_tile)->get_rid());
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_set_light_mask(occluder, tile_set->get_occlusion_layer_light_mask(occlusion_layer_index));
} else {
Expand Down Expand Up @@ -800,6 +806,11 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
tile_data = atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile);
}

// Transform flags.
bool flip_h = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H);
bool flip_v = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V);
bool transpose = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE);

// 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];
Expand Down Expand Up @@ -864,8 +875,7 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
int shapes_count = tile_data->get_collision_polygon_shapes_count(tile_set_physics_layer, polygon_index);
for (int shape_index = 0; shape_index < shapes_count; shape_index++) {
// Add decomposed convex shapes.
Ref<ConvexPolygonShape2D> shape = tile_data->get_collision_polygon_shape(tile_set_physics_layer, polygon_index, shape_index);
shape = tile_map_node->get_transformed_polygon(Ref<Resource>(shape), c.alternative_tile);
Ref<ConvexPolygonShape2D> shape = tile_data->get_collision_polygon_shape(tile_set_physics_layer, polygon_index, shape_index, flip_h, flip_v, transpose);
ps->body_add_shape(body, shape->get_rid());
ps->body_set_shape_as_one_way_collision(body, body_shape_index, one_way_collision, one_way_collision_margin);

Expand Down Expand Up @@ -1053,6 +1063,11 @@ void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) {
tile_data = atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile);
}

// Transform flags.
bool flip_h = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H);
bool flip_v = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V);
bool transpose = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE);

// Free unused regions then resize the regions array.
for (uint32_t i = tile_set->get_navigation_layers_count(); i < r_cell_data.navigation_regions.size(); i++) {
RID &region = r_cell_data.navigation_regions[i];
Expand All @@ -1066,9 +1081,7 @@ void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) {

// Create, update or clear regions.
for (uint32_t navigation_layer_index = 0; navigation_layer_index < r_cell_data.navigation_regions.size(); navigation_layer_index++) {
Ref<NavigationPolygon> navigation_polygon;
navigation_polygon = tile_data->get_navigation_polygon(navigation_layer_index);
navigation_polygon = tile_map_node->get_transformed_polygon(Ref<Resource>(navigation_polygon), c.alternative_tile);
Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(navigation_layer_index, flip_h, flip_v, transpose);

RID &region = r_cell_data.navigation_regions[navigation_layer_index];

Expand Down Expand Up @@ -1161,9 +1174,11 @@ void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const V
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++) {
Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(layer_index);
bool flip_h = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H);
bool flip_v = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V);
bool transpose = (c.alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE);
Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(layer_index, flip_h, flip_v, transpose);
if (navigation_polygon.is_valid()) {
navigation_polygon = tile_map_node->get_transformed_polygon(Ref<Resource>(navigation_polygon), c.alternative_tile);
Vector<Vector2> navigation_polygon_vertices = navigation_polygon->get_vertices();
if (navigation_polygon_vertices.size() < 3) {
continue;
Expand Down Expand Up @@ -3119,11 +3134,6 @@ void TileMap::_internal_update() {
return;
}

// FIXME: This should only clear polygons that are no longer going to be used, but since it's difficult to determine,
// the cache is never cleared at runtime to prevent invalidating used polygons.
if (Engine::get_singleton()->is_editor_hint()) {
polygon_cache.clear();
}
// Update dirty quadrants on layers.
for (Ref<TileMapLayer> &layer : layers) {
layer->internal_update();
Expand Down Expand Up @@ -3608,37 +3618,6 @@ Rect2 TileMap::_edit_get_rect() const {
}
#endif

PackedVector2Array TileMap::_get_transformed_vertices(const PackedVector2Array &p_vertices, int p_alternative_id) {
const Vector2 *r = p_vertices.ptr();
int size = p_vertices.size();

PackedVector2Array new_points;
new_points.resize(size);
Vector2 *w = new_points.ptrw();

bool flip_h = (p_alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_H);
bool flip_v = (p_alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_V);
bool transpose = (p_alternative_id & TileSetAtlasSource::TRANSFORM_TRANSPOSE);

for (int i = 0; i < size; i++) {
Vector2 v;
if (transpose) {
v = Vector2(r[i].y, r[i].x);
} else {
v = r[i];
}

if (flip_h) {
v.x *= -1;
}
if (flip_v) {
v.y *= -1;
}
w[i] = v;
}
return new_points;
}

bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
Vector<String> components = String(p_name).split("/", true, 2);
if (p_name == "format") {
Expand Down Expand Up @@ -4637,57 +4616,6 @@ void TileMap::draw_cells_outline(Control *p_control, const RBSet<Vector2i> &p_ce
#undef DRAW_SIDE_IF_NEEDED
}

Ref<Resource> TileMap::get_transformed_polygon(Ref<Resource> p_polygon, int p_alternative_id) {
if (!bool(p_alternative_id & (TileSetAtlasSource::TRANSFORM_FLIP_H | TileSetAtlasSource::TRANSFORM_FLIP_V | TileSetAtlasSource::TRANSFORM_TRANSPOSE))) {
return p_polygon;
}

{
HashMap<Pair<Ref<Resource>, int>, Ref<Resource>, PairHash<Ref<Resource>, int>>::Iterator E = polygon_cache.find(Pair<Ref<Resource>, int>(p_polygon, p_alternative_id));
if (E) {
return E->value;
}
}

Ref<ConvexPolygonShape2D> col = p_polygon;
if (col.is_valid()) {
Ref<ConvexPolygonShape2D> ret;
ret.instantiate();
ret->set_points(_get_transformed_vertices(col->get_points(), p_alternative_id));
polygon_cache[Pair<Ref<Resource>, int>(p_polygon, p_alternative_id)] = ret;
return ret;
}

Ref<NavigationPolygon> nav = p_polygon;
if (nav.is_valid()) {
PackedVector2Array new_points = _get_transformed_vertices(nav->get_vertices(), p_alternative_id);
Ref<NavigationPolygon> ret;
ret.instantiate();
ret->set_vertices(new_points);

PackedInt32Array indices;
indices.resize(new_points.size());
int *w = indices.ptrw();
for (int i = 0; i < new_points.size(); i++) {
w[i] = i;
}
ret->add_polygon(indices);
polygon_cache[Pair<Ref<Resource>, int>(p_polygon, p_alternative_id)] = ret;
return ret;
}

Ref<OccluderPolygon2D> ocd = p_polygon;
if (ocd.is_valid()) {
Ref<OccluderPolygon2D> ret;
ret.instantiate();
ret->set_polygon(_get_transformed_vertices(ocd->get_polygon(), p_alternative_id));
polygon_cache[Pair<Ref<Resource>, int>(p_polygon, p_alternative_id)] = ret;
return ret;
}

return p_polygon;
}

PackedStringArray TileMap::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();

Expand Down
5 changes: 0 additions & 5 deletions scene/2d/tile_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -472,10 +472,6 @@ class TileMap : public Node2D {

void _update_notify_local_transform();

// Polygons.
HashMap<Pair<Ref<Resource>, int>, Ref<Resource>, PairHash<Ref<Resource>, int>> polygon_cache;
PackedVector2Array _get_transformed_vertices(const PackedVector2Array &p_vertices, int p_alternative_id);

protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
Expand Down Expand Up @@ -619,7 +615,6 @@ class TileMap : public Node2D {
// Helpers?
TypedArray<Vector2i> get_surrounding_cells(const Vector2i &coords);
void draw_cells_outline(Control *p_control, const RBSet<Vector2i> &p_cells, Color p_color, Transform2D p_transform = Transform2D());
Ref<Resource> get_transformed_polygon(Ref<Resource> p_polygon, int p_alternative_id);

// Virtual function to modify the TileData at runtime.
GDVIRTUAL2R(bool, _use_tile_data_runtime_update, int, Vector2i);
Expand Down
48 changes: 48 additions & 0 deletions scene/resources/tile_set.compat.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**************************************************************************/
/* tile_set.compat.inc */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#ifndef DISABLE_DEPRECATED

#include "tile_set.h"

Ref<NavigationPolygon> TileData::_get_navigation_polygon_bind_compat_84660(int p_layer_id) const {
return get_navigation_polygon(p_layer_id, false, false, false);
}

Ref<OccluderPolygon2D> TileData::_get_occluder_bind_compat_84660(int p_layer_id) const {
return get_occluder(p_layer_id, false, false, false);
}

void TileData::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("get_navigation_polygon"), &TileData::_get_navigation_polygon_bind_compat_84660);
ClassDB::bind_compatibility_method(D_METHOD("get_occluder"), &TileData::_get_occluder_bind_compat_84660);
}

#endif
Loading
Loading