summaryrefslogtreecommitdiff
path: root/scene/resources/tile_set.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/resources/tile_set.cpp')
-rw-r--r--scene/resources/tile_set.cpp169
1 files changed, 139 insertions, 30 deletions
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 4ddfc0331b..16a95e65a8 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -148,15 +148,45 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
}
}
} else if (what == "shape")
- tile_set_shape(id, 0, p_value);
+ if (tile_get_shape_count(id) > 0) {
+ for (int i = 0; i < tile_get_shape_count(id); i++) {
+ tile_set_shape(id, i, p_value);
+ }
+ } else {
+ tile_set_shape(id, 0, p_value);
+ }
else if (what == "shape_offset")
- tile_set_shape_offset(id, 0, p_value);
+ if (tile_get_shape_count(id) > 0) {
+ for (int i = 0; i < tile_get_shape_count(id); i++) {
+ tile_set_shape_offset(id, i, p_value);
+ }
+ } else {
+ tile_set_shape_offset(id, 0, p_value);
+ }
else if (what == "shape_transform")
- tile_set_shape_transform(id, 0, p_value);
+ if (tile_get_shape_count(id) > 0) {
+ for (int i = 0; i < tile_get_shape_count(id); i++) {
+ tile_set_shape_transform(id, i, p_value);
+ }
+ } else {
+ tile_set_shape_transform(id, 0, p_value);
+ }
else if (what == "shape_one_way")
- tile_set_shape_one_way(id, 0, p_value);
+ if (tile_get_shape_count(id) > 0) {
+ for (int i = 0; i < tile_get_shape_count(id); i++) {
+ tile_set_shape_one_way(id, i, p_value);
+ }
+ } else {
+ tile_set_shape_one_way(id, 0, p_value);
+ }
else if (what == "shape_one_way_margin")
- tile_set_shape_one_way_margin(id, 0, p_value);
+ if (tile_get_shape_count(id) > 0) {
+ for (int i = 0; i < tile_get_shape_count(id); i++) {
+ tile_set_shape_one_way_margin(id, i, p_value);
+ }
+ } else {
+ tile_set_shape_one_way_margin(id, 0, p_value);
+ }
else if (what == "shapes")
_tile_set_shapes(id, p_value);
else if (what == "occluder")
@@ -215,7 +245,7 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = autotile_get_spacing(id);
else if (what == "bitmask_flags") {
Array p;
- for (Map<Vector2, uint16_t>::Element *E = tile_map[id].autotile_data.flags.front(); E; E = E->next()) {
+ for (Map<Vector2, uint32_t>::Element *E = tile_map[id].autotile_data.flags.front(); E; E = E->next()) {
p.push_back(E->key());
p.push_back(E->value());
}
@@ -319,6 +349,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::INT, pre + "autotile/spacing", PROPERTY_HINT_RANGE, "0,256,1", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/occluder_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/navpoly_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/priority_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/z_index_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
}
p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "occluder_offset"));
@@ -544,7 +575,7 @@ const Map<Vector2, int> &TileSet::autotile_get_z_index_map(int p_id) const {
return tile_map[p_id].autotile_data.z_index_map;
}
-void TileSet::autotile_set_bitmask(int p_id, Vector2 p_coord, uint16_t p_flag) {
+void TileSet::autotile_set_bitmask(int p_id, Vector2 p_coord, uint32_t p_flag) {
ERR_FAIL_COND(!tile_map.has(p_id));
if (p_flag == 0) {
@@ -555,7 +586,7 @@ void TileSet::autotile_set_bitmask(int p_id, Vector2 p_coord, uint16_t p_flag) {
}
}
-uint16_t TileSet::autotile_get_bitmask(int p_id, Vector2 p_coord) {
+uint32_t TileSet::autotile_get_bitmask(int p_id, Vector2 p_coord) {
ERR_FAIL_COND_V(!tile_map.has(p_id), 0);
if (!tile_map[p_id].autotile_data.flags.has(p_coord)) {
@@ -564,13 +595,13 @@ uint16_t TileSet::autotile_get_bitmask(int p_id, Vector2 p_coord) {
return tile_map[p_id].autotile_data.flags[p_coord];
}
-const Map<Vector2, uint16_t> &TileSet::autotile_get_bitmask_map(int p_id) {
+const Map<Vector2, uint32_t> &TileSet::autotile_get_bitmask_map(int p_id) {
- static Map<Vector2, uint16_t> dummy;
- static Map<Vector2, uint16_t> dummy_atlas;
+ static Map<Vector2, uint32_t> dummy;
+ static Map<Vector2, uint32_t> dummy_atlas;
ERR_FAIL_COND_V(!tile_map.has(p_id), dummy);
if (tile_get_tile_mode(p_id) == ATLAS_TILE) {
- dummy_atlas = Map<Vector2, uint16_t>();
+ dummy_atlas = Map<Vector2, uint32_t>();
Rect2 region = tile_get_region(p_id);
Size2 size = autotile_get_size(p_id);
float spacing = autotile_get_spacing(p_id);
@@ -600,22 +631,79 @@ Vector2 TileSet::autotile_get_subtile_for_bitmask(int p_id, uint16_t p_bitmask,
}
List<Vector2> coords;
- uint16_t mask;
- for (Map<Vector2, uint16_t>::Element *E = tile_map[p_id].autotile_data.flags.front(); E; E = E->next()) {
+ List<uint32_t> priorities;
+ uint32_t priority_sum = 0;
+ uint32_t mask;
+ uint16_t mask_;
+ uint16_t mask_ignore;
+ for (Map<Vector2, uint32_t>::Element *E = tile_map[p_id].autotile_data.flags.front(); E; E = E->next()) {
mask = E->get();
if (tile_map[p_id].autotile_data.bitmask_mode == BITMASK_2X2) {
- mask &= (BIND_BOTTOMLEFT | BIND_BOTTOMRIGHT | BIND_TOPLEFT | BIND_TOPRIGHT);
+ mask |= (BIND_IGNORE_TOP | BIND_IGNORE_LEFT | BIND_IGNORE_CENTER | BIND_IGNORE_RIGHT | BIND_IGNORE_BOTTOM);
}
- if (mask == p_bitmask) {
- for (int i = 0; i < autotile_get_subtile_priority(p_id, E->key()); i++) {
- coords.push_back(E->key());
+
+ mask_ = mask & 0xFFFF;
+ mask_ignore = mask >> 16;
+
+ if (((mask_ & (~mask_ignore)) == (p_bitmask & (~mask_ignore))) && (((~mask_) | mask_ignore) == ((~p_bitmask) | mask_ignore))) {
+ uint32_t priority = autotile_get_subtile_priority(p_id, E->key());
+ priority_sum += priority;
+ priorities.push_back(priority);
+ coords.push_back(E->key());
+ }
+ }
+
+ if (coords.size() == 0) {
+ return autotile_get_icon_coordinate(p_id);
+ } else {
+ uint32_t picked_value = Math::rand() % priority_sum;
+ uint32_t upper_bound;
+ uint32_t lower_bound = 0;
+ Vector2 result = coords.front()->get();
+ List<Vector2>::Element *coords_E = coords.front();
+ List<uint32_t>::Element *priorities_E = priorities.front();
+ while (priorities_E) {
+ upper_bound = lower_bound + priorities_E->get();
+ if (lower_bound <= picked_value && picked_value < upper_bound) {
+ result = coords_E->get();
+ break;
+ }
+ lower_bound = upper_bound;
+ priorities_E = priorities_E->next();
+ coords_E = coords_E->next();
+ }
+
+ return result;
+ }
+}
+
+Vector2 TileSet::atlastile_get_subtile_by_priority(int p_id, const Node *p_tilemap_node, const Vector2 &p_tile_location) {
+
+ ERR_FAIL_COND_V(!tile_map.has(p_id), Vector2());
+ //First try to forward selection to script
+ if (get_script_instance() != NULL) {
+ if (get_script_instance()->has_method("_forward_atlas_subtile_selection")) {
+ Variant ret = get_script_instance()->call("_forward_atlas_subtile_selection", p_id, p_tilemap_node, p_tile_location);
+ if (ret.get_type() == Variant::VECTOR2) {
+ return ret;
+ }
+ }
+ }
+
+ Vector2 coord = tile_get_region(p_id).size / autotile_get_size(p_id);
+
+ List<Vector2> coords;
+ for (int x = 0; x < coord.x; x++) {
+ for (int y = 0; y < coord.y; y++) {
+ for (int i = 0; i < autotile_get_subtile_priority(p_id, Vector2(x, y)); i++) {
+ coords.push_back(Vector2(x, y));
}
}
}
if (coords.size() == 0) {
return autotile_get_icon_coordinate(p_id);
} else {
- return coords[Math::rand() % coords.size()];
+ return coords[Math::random(0, (int)coords.size())];
}
}
@@ -634,6 +722,8 @@ String TileSet::tile_get_name(int p_id) const {
}
void TileSet::tile_clear_shapes(int p_id) {
+
+ ERR_FAIL_COND(!tile_map.has(p_id));
tile_map[p_id].shapes_data.clear();
}
@@ -653,14 +743,15 @@ void TileSet::tile_add_shape(int p_id, const Ref<Shape2D> &p_shape, const Transf
int TileSet::tile_get_shape_count(int p_id) const {
ERR_FAIL_COND_V(!tile_map.has(p_id), 0);
-
return tile_map[p_id].shapes_data.size();
}
void TileSet::tile_set_shape(int p_id, int p_shape_id, const Ref<Shape2D> &p_shape) {
ERR_FAIL_COND(!tile_map.has(p_id));
- if (tile_map[p_id].shapes_data.size() <= p_shape_id)
+ ERR_FAIL_COND(p_shape_id < 0);
+
+ if (p_shape_id >= tile_map[p_id].shapes_data.size())
tile_map[p_id].shapes_data.resize(p_shape_id + 1);
tile_map[p_id].shapes_data.write[p_shape_id].shape = p_shape;
_decompose_convex_shape(p_shape);
@@ -670,7 +761,9 @@ void TileSet::tile_set_shape(int p_id, int p_shape_id, const Ref<Shape2D> &p_sha
Ref<Shape2D> TileSet::tile_get_shape(int p_id, int p_shape_id) const {
ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<Shape2D>());
- if (tile_map[p_id].shapes_data.size() > p_shape_id)
+ ERR_FAIL_COND_V(p_shape_id < 0, Ref<Shape2D>());
+
+ if (p_shape_id < tile_map[p_id].shapes_data.size())
return tile_map[p_id].shapes_data[p_shape_id].shape;
return Ref<Shape2D>();
@@ -679,7 +772,9 @@ Ref<Shape2D> TileSet::tile_get_shape(int p_id, int p_shape_id) const {
void TileSet::tile_set_shape_transform(int p_id, int p_shape_id, const Transform2D &p_offset) {
ERR_FAIL_COND(!tile_map.has(p_id));
- if (tile_map[p_id].shapes_data.size() <= p_shape_id)
+ ERR_FAIL_COND(p_shape_id < 0);
+
+ if (p_shape_id >= tile_map[p_id].shapes_data.size())
tile_map[p_id].shapes_data.resize(p_shape_id + 1);
tile_map[p_id].shapes_data.write[p_shape_id].shape_transform = p_offset;
emit_changed();
@@ -688,7 +783,9 @@ void TileSet::tile_set_shape_transform(int p_id, int p_shape_id, const Transform
Transform2D TileSet::tile_get_shape_transform(int p_id, int p_shape_id) const {
ERR_FAIL_COND_V(!tile_map.has(p_id), Transform2D());
- if (tile_map[p_id].shapes_data.size() > p_shape_id)
+ ERR_FAIL_COND_V(p_shape_id < 0, Transform2D());
+
+ if (p_shape_id < tile_map[p_id].shapes_data.size())
return tile_map[p_id].shapes_data[p_shape_id].shape_transform;
return Transform2D();
@@ -707,7 +804,9 @@ Vector2 TileSet::tile_get_shape_offset(int p_id, int p_shape_id) const {
void TileSet::tile_set_shape_one_way(int p_id, int p_shape_id, const bool p_one_way) {
ERR_FAIL_COND(!tile_map.has(p_id));
- if (tile_map[p_id].shapes_data.size() <= p_shape_id)
+ ERR_FAIL_COND(p_shape_id < 0);
+
+ if (p_shape_id >= tile_map[p_id].shapes_data.size())
tile_map[p_id].shapes_data.resize(p_shape_id + 1);
tile_map[p_id].shapes_data.write[p_shape_id].one_way_collision = p_one_way;
emit_changed();
@@ -716,23 +815,31 @@ void TileSet::tile_set_shape_one_way(int p_id, int p_shape_id, const bool p_one_
bool TileSet::tile_get_shape_one_way(int p_id, int p_shape_id) const {
ERR_FAIL_COND_V(!tile_map.has(p_id), false);
- if (tile_map[p_id].shapes_data.size() > p_shape_id)
+ ERR_FAIL_COND_V(p_shape_id < 0, false);
+
+ if (p_shape_id < tile_map[p_id].shapes_data.size())
return tile_map[p_id].shapes_data[p_shape_id].one_way_collision;
return false;
}
void TileSet::tile_set_shape_one_way_margin(int p_id, int p_shape_id, float p_margin) {
+
ERR_FAIL_COND(!tile_map.has(p_id));
- if (tile_map[p_id].shapes_data.size() <= p_shape_id)
+ ERR_FAIL_COND(p_shape_id < 0);
+
+ if (p_shape_id >= tile_map[p_id].shapes_data.size())
tile_map[p_id].shapes_data.resize(p_shape_id + 1);
tile_map[p_id].shapes_data.write[p_shape_id].one_way_collision_margin = p_margin;
emit_changed();
}
float TileSet::tile_get_shape_one_way_margin(int p_id, int p_shape_id) const {
+
ERR_FAIL_COND_V(!tile_map.has(p_id), 0);
- if (tile_map[p_id].shapes_data.size() > p_shape_id)
+ ERR_FAIL_COND_V(p_shape_id < 0, 0);
+
+ if (p_shape_id < tile_map[p_id].shapes_data.size())
return tile_map[p_id].shapes_data[p_shape_id].one_way_collision_margin;
return 0;
@@ -762,7 +869,9 @@ void TileSet::autotile_set_light_occluder(int p_id, const Ref<OccluderPolygon2D>
}
Ref<OccluderPolygon2D> TileSet::autotile_get_light_occluder(int p_id, const Vector2 &p_coord) const {
+
ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<OccluderPolygon2D>());
+
if (!tile_map[p_id].autotile_data.occluder_map.has(p_coord)) {
return Ref<OccluderPolygon2D>();
} else {
@@ -922,8 +1031,7 @@ void TileSet::_tile_set_shapes(int p_id, const Array &p_shapes) {
s.autotile_coord = default_autotile_coord;
} else {
- ERR_EXPLAIN("Expected an array of objects or dictionaries for tile_set_shapes");
- ERR_CONTINUE(true);
+ ERR_CONTINUE_MSG(true, "Expected an array of objects or dictionaries for tile_set_shapes.");
}
shapes_data.push_back(s);
@@ -1114,6 +1222,7 @@ void TileSet::_bind_methods() {
BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_tile_bound", PropertyInfo(Variant::INT, "drawn_id"), PropertyInfo(Variant::INT, "neighbor_id")));
BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_forward_subtile_selection", PropertyInfo(Variant::INT, "autotile_id"), PropertyInfo(Variant::INT, "bitmask"), PropertyInfo(Variant::OBJECT, "tilemap", PROPERTY_HINT_NONE, "TileMap"), PropertyInfo(Variant::VECTOR2, "tile_location")));
+ BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_forward_atlas_subtile_selection", PropertyInfo(Variant::INT, "atlastile_id"), PropertyInfo(Variant::OBJECT, "tilemap", PROPERTY_HINT_NONE, "TileMap"), PropertyInfo(Variant::VECTOR2, "tile_location")));
BIND_ENUM_CONSTANT(BITMASK_2X2);
BIND_ENUM_CONSTANT(BITMASK_3X3_MINIMAL);