Browse Source

Fixes TileMap occluders

(cherry picked from commit fcb8d19de0c2155384b629a7cd5dcf84401e3409)
Gilles Roudière 1 year ago
parent
commit
6e043b80f6
2 changed files with 50 additions and 27 deletions
  1. 49 26
      scene/2d/tile_map.cpp
  2. 1 1
      scene/2d/tile_map.h

+ 49 - 26
scene/2d/tile_map.cpp

@@ -447,9 +447,11 @@ void TileMapLayer::_rendering_update() {
 			for (KeyValue<Vector2i, CellData> &kv : tile_map) {
 			for (KeyValue<Vector2i, CellData> &kv : tile_map) {
 				CellData &cell_data = kv.value;
 				CellData &cell_data = kv.value;
 				for (const RID &occluder : cell_data.occluders) {
 				for (const RID &occluder : cell_data.occluders) {
-					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_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);
+					}
 				}
 				}
 			}
 			}
 		}
 		}
@@ -565,6 +567,15 @@ void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
 	const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
 	const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
 	RenderingServer *rs = RenderingServer::get_singleton();
 	RenderingServer *rs = RenderingServer::get_singleton();
 
 
+	// Free unused occluders then resize the occluders array.
+	for (uint32_t i = tile_set->get_occlusion_layers_count(); i < r_cell_data.occluders.size(); i++) {
+		RID occluder_id = r_cell_data.occluders[i];
+		if (occluder_id.is_valid()) {
+			rs->free(occluder_id);
+		}
+	}
+	r_cell_data.occluders.resize(tile_set->get_occlusion_layers_count());
+
 	TileSetSource *source;
 	TileSetSource *source;
 	if (tile_set->has_source(r_cell_data.cell.source_id)) {
 	if (tile_set->has_source(r_cell_data.cell.source_id)) {
 		source = *tile_set->get_source(r_cell_data.cell.source_id);
 		source = *tile_set->get_source(r_cell_data.cell.source_id);
@@ -580,18 +591,30 @@ 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);
 					tile_data = atlas_source->get_tile_data(r_cell_data.cell.get_atlas_coords(), r_cell_data.cell.alternative_tile);
 				}
 				}
 
 
-				// Update/create occluders.
-				for (int i = 0; i < tile_set->get_occlusion_layers_count(); i++) {
-					Transform2D xform;
-					xform.set_origin(tile_map_node->map_to_local(r_cell_data.coords));
-					if (tile_data->get_occluder(i).is_valid()) {
-						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_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);
+				// 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);
+
+					RID &occluder = r_cell_data.occluders[occlusion_layer_index];
+
+					if (occluder_polygon.is_valid()) {
+						// Create or update occluder.
+						Transform2D xform;
+						xform.set_origin(tile_map_node->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_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_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 {
+						// Clear occluder.
+						if (occluder.is_valid()) {
+							rs->free(occluder);
+							occluder = RID();
+						}
 					}
 					}
 				}
 				}
 
 
@@ -778,7 +801,7 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
 				}
 				}
 
 
 				// Free unused bodies then resize the bodies array.
 				// Free unused bodies then resize the bodies array.
-				for (unsigned int i = tile_set->get_physics_layers_count(); i < r_cell_data.bodies.size(); i++) {
+				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()) {
 					if (body.is_valid()) {
 						bodies_coords.erase(body);
 						bodies_coords.erase(body);
@@ -787,7 +810,7 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
 				}
 				}
 				r_cell_data.bodies.resize(tile_set->get_physics_layers_count());
 				r_cell_data.bodies.resize(tile_set->get_physics_layers_count());
 
 
-				for (int tile_set_physics_layer = 0; tile_set_physics_layer < tile_set->get_physics_layers_count(); tile_set_physics_layer++) {
+				for (uint32_t tile_set_physics_layer = 0; tile_set_physics_layer < (uint32_t)tile_set->get_physics_layers_count(); tile_set_physics_layer++) {
 					Ref<PhysicsMaterial> physics_material = tile_set->get_physics_layer_physics_material(tile_set_physics_layer);
 					Ref<PhysicsMaterial> physics_material = tile_set->get_physics_layer_physics_material(tile_set_physics_layer);
 					uint32_t physics_layer = tile_set->get_physics_layer_collision_layer(tile_set_physics_layer);
 					uint32_t physics_layer = tile_set->get_physics_layer_collision_layer(tile_set_physics_layer);
 					uint32_t physics_mask = tile_set->get_physics_layer_collision_mask(tile_set_physics_layer);
 					uint32_t physics_mask = tile_set->get_physics_layer_collision_mask(tile_set_physics_layer);
@@ -998,7 +1021,7 @@ void TileMapLayer::_navigation_update() {
 void TileMapLayer::_navigation_clear_cell(CellData &r_cell_data) {
 void TileMapLayer::_navigation_clear_cell(CellData &r_cell_data) {
 	NavigationServer2D *ns = NavigationServer2D::get_singleton();
 	NavigationServer2D *ns = NavigationServer2D::get_singleton();
 	// Clear navigation shapes.
 	// Clear navigation shapes.
-	for (unsigned int i = 0; i < r_cell_data.navigation_regions.size(); i++) {
+	for (uint32_t i = 0; i < r_cell_data.navigation_regions.size(); i++) {
 		const RID &region = r_cell_data.navigation_regions[i];
 		const RID &region = r_cell_data.navigation_regions[i];
 		if (region.is_valid()) {
 		if (region.is_valid()) {
 			ns->region_set_map(region, RID());
 			ns->region_set_map(region, RID());
@@ -1031,7 +1054,7 @@ void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) {
 				}
 				}
 
 
 				// Free unused regions then resize the regions array.
 				// Free unused regions then resize the regions array.
-				for (unsigned int i = tile_set->get_navigation_layers_count(); i < r_cell_data.navigation_regions.size(); i++) {
+				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];
 					RID &region = r_cell_data.navigation_regions[i];
 					if (region.is_valid()) {
 					if (region.is_valid()) {
 						ns->region_set_map(region, RID());
 						ns->region_set_map(region, RID());
@@ -1042,7 +1065,7 @@ void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) {
 				r_cell_data.navigation_regions.resize(tile_set->get_navigation_layers_count());
 				r_cell_data.navigation_regions.resize(tile_set->get_navigation_layers_count());
 
 
 				// Create, update or clear regions.
 				// Create, update or clear regions.
-				for (unsigned int navigation_layer_index = 0; navigation_layer_index < r_cell_data.navigation_regions.size(); navigation_layer_index++) {
+				for (uint32_t navigation_layer_index = 0; navigation_layer_index < r_cell_data.navigation_regions.size(); navigation_layer_index++) {
 					Ref<NavigationPolygon> navigation_polygon;
 					Ref<NavigationPolygon> navigation_polygon;
 					navigation_polygon = tile_data->get_navigation_polygon(navigation_layer_index);
 					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);
 					navigation_polygon = tile_map_node->get_transformed_polygon(Ref<Resource>(navigation_polygon), c.alternative_tile);
@@ -3250,7 +3273,7 @@ void TileMap::add_layer(int p_to_pos) {
 	new_layer.instantiate();
 	new_layer.instantiate();
 	new_layer->set_tile_map(this);
 	new_layer->set_tile_map(this);
 	layers.insert(p_to_pos, new_layer);
 	layers.insert(p_to_pos, new_layer);
-	for (unsigned int i = 0; i < layers.size(); i++) {
+	for (uint32_t i = 0; i < layers.size(); i++) {
 		layers[i]->set_layer_index_in_tile_map_node(i);
 		layers[i]->set_layer_index_in_tile_map_node(i);
 	}
 	}
 	queue_internal_update();
 	queue_internal_update();
@@ -3269,7 +3292,7 @@ void TileMap::move_layer(int p_layer, int p_to_pos) {
 	Ref<TileMapLayer> layer = layers[p_layer];
 	Ref<TileMapLayer> layer = layers[p_layer];
 	layers.insert(p_to_pos, layer);
 	layers.insert(p_to_pos, layer);
 	layers.remove_at(p_to_pos < p_layer ? p_layer + 1 : p_layer);
 	layers.remove_at(p_to_pos < p_layer ? p_layer + 1 : p_layer);
-	for (unsigned int i = 0; i < layers.size(); i++) {
+	for (uint32_t i = 0; i < layers.size(); i++) {
 		layers[i]->set_layer_index_in_tile_map_node(i);
 		layers[i]->set_layer_index_in_tile_map_node(i);
 	}
 	}
 	queue_internal_update();
 	queue_internal_update();
@@ -3289,7 +3312,7 @@ void TileMap::remove_layer(int p_layer) {
 
 
 	// Clear before removing the layer.
 	// Clear before removing the layer.
 	layers.remove_at(p_layer);
 	layers.remove_at(p_layer);
-	for (unsigned int i = 0; i < layers.size(); i++) {
+	for (uint32_t i = 0; i < layers.size(); i++) {
 		layers[i]->set_layer_index_in_tile_map_node(i);
 		layers[i]->set_layer_index_in_tile_map_node(i);
 	}
 	}
 	queue_internal_update();
 	queue_internal_update();
@@ -3526,7 +3549,7 @@ Vector2i TileMap::get_coords_for_body_rid(RID p_physics_body) {
 }
 }
 
 
 int TileMap::get_layer_for_body_rid(RID p_physics_body) {
 int TileMap::get_layer_for_body_rid(RID p_physics_body) {
-	for (unsigned int i = 0; i < layers.size(); i++) {
+	for (uint32_t i = 0; i < layers.size(); i++) {
 		if (layers[i]->has_body_rid(p_physics_body)) {
 		if (layers[i]->has_body_rid(p_physics_body)) {
 			return i;
 			return i;
 		}
 		}
@@ -3576,7 +3599,7 @@ Rect2 TileMap::_edit_get_rect() const {
 	bool changed = false;
 	bool changed = false;
 	Rect2 rect = layers[0]->get_rect(changed);
 	Rect2 rect = layers[0]->get_rect(changed);
 	any_changed |= changed;
 	any_changed |= changed;
-	for (unsigned int i = 1; i < layers.size(); i++) {
+	for (uint32_t i = 1; i < layers.size(); i++) {
 		rect = rect.merge(layers[i]->get_rect(changed));
 		rect = rect.merge(layers[i]->get_rect(changed));
 		any_changed |= changed;
 		any_changed |= changed;
 	}
 	}
@@ -3755,7 +3778,7 @@ void TileMap::_get_property_list(List<PropertyInfo> *p_list) const {
 		p_list->push_back(PropertyInfo(m_type, property_name, PROPERTY_HINT_NONE, m_hint, (get(property_name) == property_get_revert(property_name)) ? PROPERTY_USAGE_EDITOR : PROPERTY_USAGE_DEFAULT)); \
 		p_list->push_back(PropertyInfo(m_type, property_name, PROPERTY_HINT_NONE, m_hint, (get(property_name) == property_get_revert(property_name)) ? PROPERTY_USAGE_EDITOR : PROPERTY_USAGE_DEFAULT)); \
 	}
 	}
 
 
-	for (unsigned int i = 0; i < layers.size(); i++) {
+	for (uint32_t i = 0; i < layers.size(); i++) {
 		MAKE_LAYER_PROPERTY(Variant::STRING, "name", "");
 		MAKE_LAYER_PROPERTY(Variant::STRING, "name", "");
 		MAKE_LAYER_PROPERTY(Variant::BOOL, "enabled", "");
 		MAKE_LAYER_PROPERTY(Variant::BOOL, "enabled", "");
 		MAKE_LAYER_PROPERTY(Variant::COLOR, "modulate", "");
 		MAKE_LAYER_PROPERTY(Variant::COLOR, "modulate", "");

+ 1 - 1
scene/2d/tile_map.h

@@ -104,7 +104,7 @@ struct CellData {
 	// Rendering.
 	// Rendering.
 	Ref<RenderingQuadrant> rendering_quadrant;
 	Ref<RenderingQuadrant> rendering_quadrant;
 	SelfList<CellData> rendering_quadrant_list_element;
 	SelfList<CellData> rendering_quadrant_list_element;
-	List<RID> occluders;
+	LocalVector<RID> occluders;
 
 
 	// Physics.
 	// Physics.
 	LocalVector<RID> bodies;
 	LocalVector<RID> bodies;