Add per-tile flipping and transposing
This commit is contained in:
+90
-4
@@ -548,7 +548,7 @@ void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
|
||||
RID occluder_id = rs->canvas_light_occluder_create();
|
||||
rs->canvas_light_occluder_set_enabled(occluder_id, node_visible);
|
||||
rs->canvas_light_occluder_set_transform(occluder_id, tile_map_node->get_global_transform() * xform);
|
||||
rs->canvas_light_occluder_set_polygon(occluder_id, tile_data->get_occluder(i)->get_rid());
|
||||
rs->canvas_light_occluder_set_polygon(occluder_id, tile_map_node->get_transformed_polygon(Ref<Resource>(tile_data->get_occluder(i)), r_cell_data.cell.alternative_tile)->get_rid());
|
||||
rs->canvas_light_occluder_attach_to_canvas(occluder_id, tile_map_node->get_canvas());
|
||||
rs->canvas_light_occluder_set_light_mask(occluder_id, tile_set->get_occlusion_layer_light_mask(i));
|
||||
r_cell_data.occluders.push_back(occluder_id);
|
||||
@@ -783,6 +783,7 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
|
||||
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);
|
||||
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);
|
||||
|
||||
@@ -985,6 +986,7 @@ void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) {
|
||||
for (unsigned int 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);
|
||||
|
||||
RID ®ion = r_cell_data.navigation_regions[navigation_layer_index];
|
||||
|
||||
@@ -1074,6 +1076,7 @@ void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const V
|
||||
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);
|
||||
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;
|
||||
@@ -3012,6 +3015,7 @@ void TileMap::_internal_update() {
|
||||
}
|
||||
|
||||
// Update dirty quadrants on layers.
|
||||
polygon_cache.clear();
|
||||
for (Ref<TileMapLayer> &layer : layers) {
|
||||
layer->internal_update();
|
||||
}
|
||||
@@ -3100,18 +3104,18 @@ void TileMap::draw_tile(RID p_canvas_item, const Vector2 &p_position, const Ref<
|
||||
dest_rect.size.x += FP_ADJUST;
|
||||
dest_rect.size.y += FP_ADJUST;
|
||||
|
||||
bool transpose = tile_data->get_transpose();
|
||||
bool transpose = tile_data->get_transpose() ^ bool(p_alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE);
|
||||
if (transpose) {
|
||||
dest_rect.position = (p_position - Vector2(dest_rect.size.y, dest_rect.size.x) / 2 - tile_offset);
|
||||
} else {
|
||||
dest_rect.position = (p_position - dest_rect.size / 2 - tile_offset);
|
||||
}
|
||||
|
||||
if (tile_data->get_flip_h()) {
|
||||
if (tile_data->get_flip_h() ^ bool(p_alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H)) {
|
||||
dest_rect.size.x = -dest_rect.size.x;
|
||||
}
|
||||
|
||||
if (tile_data->get_flip_v()) {
|
||||
if (tile_data->get_flip_v() ^ bool(p_alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V)) {
|
||||
dest_rect.size.y = -dest_rect.size.y;
|
||||
}
|
||||
|
||||
@@ -3482,6 +3486,37 @@ 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") {
|
||||
@@ -4384,6 +4419,57 @@ 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();
|
||||
|
||||
|
||||
@@ -455,6 +455,10 @@ private:
|
||||
|
||||
void _tile_set_changed();
|
||||
|
||||
// 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;
|
||||
@@ -595,6 +599,7 @@ public:
|
||||
// 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);
|
||||
|
||||
Reference in New Issue
Block a user