|
@@ -3444,7 +3444,8 @@ void TileSet::_compatibility_conversion() {
|
|
|
polygon.write[index] = xform.xform(polygon[index] - ctd->region.get_size() / 2.0);
|
|
|
}
|
|
|
occluder->set_polygon(polygon);
|
|
|
- tile_data->set_occluder(0, occluder);
|
|
|
+ tile_data->add_occluder_polygon(0);
|
|
|
+ tile_data->set_occluder_polygon(0, 0, occluder);
|
|
|
}
|
|
|
if (ctd->navigation.is_valid()) {
|
|
|
if (get_navigation_layers_count() < 1) {
|
|
@@ -3558,7 +3559,8 @@ void TileSet::_compatibility_conversion() {
|
|
|
polygon.write[index] = xform.xform(polygon[index] - ctd->region.get_size() / 2.0);
|
|
|
}
|
|
|
occluder->set_polygon(polygon);
|
|
|
- tile_data->set_occluder(0, occluder);
|
|
|
+ tile_data->add_occluder_polygon(0);
|
|
|
+ tile_data->set_occluder_polygon(0, 0, occluder);
|
|
|
}
|
|
|
if (ctd->autotile_navpoly_map.has(coords)) {
|
|
|
if (get_navigation_layers_count() < 1) {
|
|
@@ -6220,33 +6222,86 @@ int TileData::get_y_sort_origin() const {
|
|
|
return y_sort_origin;
|
|
|
}
|
|
|
|
|
|
+#ifndef DISABLE_DEPRECATED
|
|
|
void TileData::set_occluder(int p_layer_id, Ref<OccluderPolygon2D> p_occluder_polygon) {
|
|
|
ERR_FAIL_INDEX(p_layer_id, occluders.size());
|
|
|
- occluders.write[p_layer_id].occluder = p_occluder_polygon;
|
|
|
- occluders.write[p_layer_id].transformed_occluders.clear();
|
|
|
+ if (get_occluder_polygons_count(p_layer_id) == 0) {
|
|
|
+ add_occluder_polygon(p_layer_id);
|
|
|
+ }
|
|
|
+ set_occluder_polygon(p_layer_id, 0, p_occluder_polygon);
|
|
|
emit_signal(CoreStringName(changed));
|
|
|
}
|
|
|
|
|
|
Ref<OccluderPolygon2D> TileData::get_occluder(int p_layer_id, bool p_flip_h, bool p_flip_v, bool p_transpose) const {
|
|
|
ERR_FAIL_INDEX_V(p_layer_id, occluders.size(), Ref<OccluderPolygon2D>());
|
|
|
+ if (get_occluder_polygons_count(p_layer_id) == 0) {
|
|
|
+ return Ref<OccluderPolygon2D>();
|
|
|
+ }
|
|
|
+ return get_occluder_polygon(p_layer_id, 0, p_flip_h, p_flip_v, p_transpose);
|
|
|
+}
|
|
|
+#endif // DISABLE_DEPRECATED
|
|
|
+
|
|
|
+void TileData::set_occluder_polygons_count(int p_layer_id, int p_polygons_count) {
|
|
|
+ ERR_FAIL_INDEX(p_layer_id, occluders.size());
|
|
|
+ ERR_FAIL_COND(p_polygons_count < 0);
|
|
|
+ if (p_polygons_count == occluders.write[p_layer_id].polygons.size()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ occluders.write[p_layer_id].polygons.resize(p_polygons_count);
|
|
|
+ notify_property_list_changed();
|
|
|
+ emit_signal(CoreStringName(changed));
|
|
|
+}
|
|
|
+
|
|
|
+int TileData::get_occluder_polygons_count(int p_layer_id) const {
|
|
|
+ ERR_FAIL_INDEX_V(p_layer_id, occluders.size(), 0);
|
|
|
+ return occluders[p_layer_id].polygons.size();
|
|
|
+}
|
|
|
+
|
|
|
+void TileData::add_occluder_polygon(int p_layer_id) {
|
|
|
+ ERR_FAIL_INDEX(p_layer_id, occluders.size());
|
|
|
+ occluders.write[p_layer_id].polygons.push_back(OcclusionLayerTileData::PolygonOccluderTileData());
|
|
|
+ emit_signal(CoreStringName(changed));
|
|
|
+}
|
|
|
+
|
|
|
+void TileData::remove_occluder_polygon(int p_layer_id, int p_polygon_index) {
|
|
|
+ ERR_FAIL_INDEX(p_layer_id, occluders.size());
|
|
|
+ ERR_FAIL_INDEX(p_polygon_index, occluders[p_layer_id].polygons.size());
|
|
|
+ occluders.write[p_layer_id].polygons.remove_at(p_polygon_index);
|
|
|
+ emit_signal(CoreStringName(changed));
|
|
|
+}
|
|
|
+
|
|
|
+void TileData::set_occluder_polygon(int p_layer_id, int p_polygon_index, const Ref<OccluderPolygon2D> &p_occluder_polygon) {
|
|
|
+ ERR_FAIL_INDEX(p_layer_id, occluders.size());
|
|
|
+ ERR_FAIL_INDEX(p_polygon_index, occluders[p_layer_id].polygons.size());
|
|
|
+
|
|
|
+ OcclusionLayerTileData::PolygonOccluderTileData &polygon_occluder_tile_data = occluders.write[p_layer_id].polygons.write[p_polygon_index];
|
|
|
+ polygon_occluder_tile_data.occluder_polygon = p_occluder_polygon;
|
|
|
+ polygon_occluder_tile_data.transformed_polygon_occluders.clear();
|
|
|
+ emit_signal(CoreStringName(changed));
|
|
|
+}
|
|
|
+
|
|
|
+Ref<OccluderPolygon2D> TileData::get_occluder_polygon(int p_layer_id, int p_polygon_index, bool p_flip_h, bool p_flip_v, bool p_transpose) const {
|
|
|
+ ERR_FAIL_INDEX_V(p_layer_id, occluders.size(), Ref<OccluderPolygon2D>());
|
|
|
+ ERR_FAIL_INDEX_V(p_polygon_index, occluders[p_layer_id].polygons.size(), Ref<OccluderPolygon2D>());
|
|
|
|
|
|
const OcclusionLayerTileData &layer_tile_data = occluders[p_layer_id];
|
|
|
+ const Ref<OccluderPolygon2D> &occluder_polygon = layer_tile_data.polygons[p_polygon_index].occluder_polygon;
|
|
|
|
|
|
int key = int(p_flip_h) | int(p_flip_v) << 1 | int(p_transpose) << 2;
|
|
|
if (key == 0) {
|
|
|
- return layer_tile_data.occluder;
|
|
|
+ return occluder_polygon;
|
|
|
}
|
|
|
|
|
|
- if (layer_tile_data.occluder.is_null()) {
|
|
|
+ if (occluder_polygon.is_null()) {
|
|
|
return Ref<OccluderPolygon2D>();
|
|
|
}
|
|
|
|
|
|
- HashMap<int, Ref<OccluderPolygon2D>>::Iterator I = layer_tile_data.transformed_occluders.find(key);
|
|
|
+ HashMap<int, Ref<OccluderPolygon2D>>::Iterator I = layer_tile_data.polygons[p_polygon_index].transformed_polygon_occluders.find(key);
|
|
|
if (!I) {
|
|
|
Ref<OccluderPolygon2D> transformed_polygon;
|
|
|
transformed_polygon.instantiate();
|
|
|
- transformed_polygon->set_polygon(get_transformed_vertices(layer_tile_data.occluder->get_polygon(), p_flip_h, p_flip_v, p_transpose));
|
|
|
- layer_tile_data.transformed_occluders[key] = transformed_polygon;
|
|
|
+ transformed_polygon->set_polygon(get_transformed_vertices(occluder_polygon->get_polygon(), p_flip_h, p_flip_v, p_transpose));
|
|
|
+ layer_tile_data.polygons[p_polygon_index].transformed_polygon_occluders[key] = transformed_polygon;
|
|
|
return transformed_polygon;
|
|
|
} else {
|
|
|
return I->value;
|
|
@@ -6594,13 +6649,37 @@ bool TileData::_set(const StringName &p_name, const Variant &p_value) {
|
|
|
#endif
|
|
|
|
|
|
Vector<String> components = String(p_name).split("/", true, 2);
|
|
|
-
|
|
|
- if (components.size() == 2 && components[0].begins_with("occlusion_layer_") && components[0].trim_prefix("occlusion_layer_").is_valid_int()) {
|
|
|
+ if (components.size() >= 2 && components[0].begins_with("occlusion_layer_") && components[0].trim_prefix("occlusion_layer_").is_valid_int()) {
|
|
|
// Occlusion layers.
|
|
|
int layer_index = components[0].trim_prefix("occlusion_layer_").to_int();
|
|
|
ERR_FAIL_COND_V(layer_index < 0, false);
|
|
|
- if (components[1] == "polygon") {
|
|
|
- Ref<OccluderPolygon2D> polygon = p_value;
|
|
|
+ if (components.size() == 2) {
|
|
|
+ if (components[1] == "polygon") {
|
|
|
+ // Kept for compatibility.
|
|
|
+ Ref<OccluderPolygon2D> polygon = p_value;
|
|
|
+ if (layer_index >= occluders.size()) {
|
|
|
+ if (tile_set) {
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+ occluders.resize(layer_index + 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (get_occluder_polygons_count(layer_index) == 0) {
|
|
|
+ add_occluder_polygon(layer_index);
|
|
|
+ }
|
|
|
+ set_occluder_polygon(layer_index, 0, polygon);
|
|
|
+ return true;
|
|
|
+ } else if (components[1] == "polygons_count") {
|
|
|
+ if (p_value.get_type() != Variant::INT) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ set_occluder_polygons_count(layer_index, p_value);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ } else if (components.size() == 3 && components[1].begins_with("polygon_") && components[1].trim_prefix("polygon_").is_valid_int()) {
|
|
|
+ // Polygons.
|
|
|
+ int polygon_index = components[1].trim_prefix("polygon_").to_int();
|
|
|
+ ERR_FAIL_COND_V(polygon_index < 0, false);
|
|
|
|
|
|
if (layer_index >= occluders.size()) {
|
|
|
if (tile_set) {
|
|
@@ -6609,8 +6688,16 @@ bool TileData::_set(const StringName &p_name, const Variant &p_value) {
|
|
|
occluders.resize(layer_index + 1);
|
|
|
}
|
|
|
}
|
|
|
- set_occluder(layer_index, polygon);
|
|
|
- return true;
|
|
|
+
|
|
|
+ if (polygon_index >= occluders[layer_index].polygons.size()) {
|
|
|
+ occluders.write[layer_index].polygons.resize(polygon_index + 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (components[2] == "polygon") {
|
|
|
+ Ref<OccluderPolygon2D> polygon = p_value;
|
|
|
+ set_occluder_polygon(layer_index, polygon_index, polygon);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
}
|
|
|
} else if (components.size() >= 2 && components[0].begins_with("physics_layer_") && components[0].trim_prefix("physics_layer_").is_valid_int()) {
|
|
|
// Physics layers.
|
|
@@ -6638,6 +6725,7 @@ bool TileData::_set(const StringName &p_name, const Variant &p_value) {
|
|
|
return true;
|
|
|
}
|
|
|
} else if (components.size() == 3 && components[1].begins_with("polygon_") && components[1].trim_prefix("polygon_").is_valid_int()) {
|
|
|
+ // Polygons.
|
|
|
int polygon_index = components[1].trim_prefix("polygon_").to_int();
|
|
|
ERR_FAIL_COND_V(polygon_index < 0, false);
|
|
|
|
|
@@ -6724,16 +6812,36 @@ bool TileData::_get(const StringName &p_name, Variant &r_ret) const {
|
|
|
Vector<String> components = String(p_name).split("/", true, 2);
|
|
|
|
|
|
if (tile_set) {
|
|
|
- if (components.size() == 2 && components[0].begins_with("occlusion_layer") && components[0].trim_prefix("occlusion_layer_").is_valid_int()) {
|
|
|
+ if (components.size() >= 2 && components[0].begins_with("occlusion_layer") && components[0].trim_prefix("occlusion_layer_").is_valid_int()) {
|
|
|
// Occlusion layers.
|
|
|
int layer_index = components[0].trim_prefix("occlusion_layer_").to_int();
|
|
|
ERR_FAIL_COND_V(layer_index < 0, false);
|
|
|
if (layer_index >= occluders.size()) {
|
|
|
return false;
|
|
|
}
|
|
|
- if (components[1] == "polygon") {
|
|
|
- r_ret = get_occluder(layer_index);
|
|
|
- return true;
|
|
|
+ if (components.size() == 2) {
|
|
|
+ if (components[1] == "polygon") {
|
|
|
+ // Kept for compatibility.
|
|
|
+ if (occluders[layer_index].polygons.is_empty()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ r_ret = get_occluder_polygon(layer_index, 0);
|
|
|
+ return true;
|
|
|
+ } else if (components[1] == "polygons_count") {
|
|
|
+ r_ret = get_occluder_polygons_count(layer_index);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ } else if (components.size() == 3 && components[1].begins_with("polygon_") && components[1].trim_prefix("polygon_").is_valid_int()) {
|
|
|
+ // Polygons.
|
|
|
+ int polygon_index = components[1].trim_prefix("polygon_").to_int();
|
|
|
+ ERR_FAIL_COND_V(polygon_index < 0, false);
|
|
|
+ if (polygon_index >= occluders[layer_index].polygons.size()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (components[2] == "polygon") {
|
|
|
+ r_ret = get_occluder_polygon(layer_index, polygon_index);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
}
|
|
|
} else if (components.size() >= 2 && components[0].begins_with("physics_layer_") && components[0].trim_prefix("physics_layer_").is_valid_int()) {
|
|
|
// Physics layers.
|
|
@@ -6813,12 +6921,15 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const {
|
|
|
// Occlusion layers.
|
|
|
p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Rendering", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
|
|
|
for (int i = 0; i < occluders.size(); i++) {
|
|
|
- // occlusion_layer_%d/polygon
|
|
|
- property_info = PropertyInfo(Variant::OBJECT, vformat("occlusion_layer_%d/%s", i, PNAME("polygon")), PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_DEFAULT);
|
|
|
- if (occluders[i].occluder.is_null()) {
|
|
|
- property_info.usage ^= PROPERTY_USAGE_STORAGE;
|
|
|
+ p_list->push_back(PropertyInfo(Variant::INT, vformat("occlusion_layer_%d/%s", i, PNAME("polygons_count")), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
|
|
|
+ for (int j = 0; j < occluders[i].polygons.size(); j++) {
|
|
|
+ // occlusion_layer_%d/polygon_%d/polygon
|
|
|
+ property_info = PropertyInfo(Variant::OBJECT, vformat("occlusion_layer_%d/polygon_%d/%s", i, j, PNAME("polygon")), PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_DEFAULT);
|
|
|
+ if (occluders[i].polygons[j].occluder_polygon.is_null()) {
|
|
|
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
|
|
|
+ }
|
|
|
+ p_list->push_back(property_info);
|
|
|
}
|
|
|
- p_list->push_back(property_info);
|
|
|
}
|
|
|
|
|
|
// Physics layers.
|
|
@@ -6923,8 +7034,17 @@ void TileData::_bind_methods() {
|
|
|
ClassDB::bind_method(D_METHOD("set_y_sort_origin", "y_sort_origin"), &TileData::set_y_sort_origin);
|
|
|
ClassDB::bind_method(D_METHOD("get_y_sort_origin"), &TileData::get_y_sort_origin);
|
|
|
|
|
|
+ ClassDB::bind_method(D_METHOD("set_occluder_polygons_count", "layer_id", "polygons_count"), &TileData::set_occluder_polygons_count);
|
|
|
+ ClassDB::bind_method(D_METHOD("get_occluder_polygons_count", "layer_id"), &TileData::get_occluder_polygons_count);
|
|
|
+ ClassDB::bind_method(D_METHOD("add_occluder_polygon", "layer_id"), &TileData::add_occluder_polygon);
|
|
|
+ ClassDB::bind_method(D_METHOD("remove_occluder_polygon", "layer_id", "polygon_index"), &TileData::remove_occluder_polygon);
|
|
|
+ ClassDB::bind_method(D_METHOD("set_occluder_polygon", "layer_id", "polygon_index", "polygon"), &TileData::set_occluder_polygon);
|
|
|
+ ClassDB::bind_method(D_METHOD("get_occluder_polygon", "layer_id", "polygon_index", "flip_h", "flip_v", "transpose"), &TileData::get_occluder_polygon, DEFVAL(false), DEFVAL(false), DEFVAL(false));
|
|
|
+
|
|
|
+#ifndef DISABLE_DEPRECATED
|
|
|
ClassDB::bind_method(D_METHOD("set_occluder", "layer_id", "occluder_polygon"), &TileData::set_occluder);
|
|
|
ClassDB::bind_method(D_METHOD("get_occluder", "layer_id", "flip_h", "flip_v", "transpose"), &TileData::get_occluder, DEFVAL(false), DEFVAL(false), DEFVAL(false));
|
|
|
+#endif // DISABLE_DEPRECATED
|
|
|
|
|
|
// Physics.
|
|
|
ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "layer_id", "velocity"), &TileData::set_constant_linear_velocity);
|