summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/gpu_particles_2d.cpp1
-rw-r--r--scene/2d/polygon_2d.cpp48
-rw-r--r--scene/2d/polygon_2d.h3
-rw-r--r--scene/2d/tile_map.cpp2661
-rw-r--r--scene/2d/tile_map.h413
-rw-r--r--scene/3d/collision_object_3d.cpp125
-rw-r--r--scene/3d/collision_object_3d.h15
-rw-r--r--scene/3d/collision_shape_3d.cpp14
-rw-r--r--scene/3d/collision_shape_3d.h2
-rw-r--r--scene/3d/gi_probe.cpp2
-rw-r--r--scene/3d/gpu_particles_3d.cpp9
-rw-r--r--scene/3d/mesh_instance_3d.cpp2
-rw-r--r--scene/3d/physics_body_3d.cpp2
-rw-r--r--scene/3d/ray_cast_3d.cpp2
-rw-r--r--scene/3d/skeleton_3d.cpp87
-rw-r--r--scene/3d/skeleton_3d.h2
-rw-r--r--scene/3d/skeleton_ik_3d.cpp69
-rw-r--r--scene/animation/animation_tree.cpp4
-rw-r--r--scene/gui/base_button.cpp7
-rw-r--r--scene/gui/color_picker.cpp128
-rw-r--r--scene/gui/color_picker.h14
-rw-r--r--scene/gui/control.cpp36
-rw-r--r--scene/gui/file_dialog.cpp2
-rw-r--r--scene/gui/gradient_edit.cpp10
-rw-r--r--scene/gui/graph_edit.cpp14
-rw-r--r--scene/gui/graph_node.cpp74
-rw-r--r--scene/gui/graph_node.h12
-rw-r--r--scene/gui/item_list.cpp13
-rw-r--r--scene/gui/line_edit.cpp28
-rw-r--r--scene/gui/line_edit.h2
-rw-r--r--scene/gui/popup_menu.cpp8
-rw-r--r--scene/gui/rich_text_label.cpp25
-rw-r--r--scene/gui/rich_text_label.h2
-rw-r--r--scene/gui/scroll_container.cpp119
-rw-r--r--scene/gui/scroll_container.h22
-rw-r--r--scene/gui/tab_container.cpp1
-rw-r--r--scene/gui/tabs.cpp4
-rw-r--r--scene/gui/text_edit.cpp56
-rw-r--r--scene/gui/tree.cpp49
-rw-r--r--scene/gui/tree.h3
-rw-r--r--scene/main/canvas_item.cpp2
-rw-r--r--scene/main/http_request.cpp37
-rw-r--r--scene/main/node.cpp8
-rw-r--r--scene/main/viewport.cpp67
-rw-r--r--scene/main/viewport.h8
-rw-r--r--scene/register_scene_types.cpp5
-rw-r--r--scene/resources/bit_map.cpp2
-rw-r--r--scene/resources/default_theme/SCsub12
-rw-r--r--scene/resources/default_theme/default_theme.cpp66
-rw-r--r--scene/resources/default_theme/default_theme_builders.py40
-rw-r--r--scene/resources/default_theme/font_hidpi.inc25463
-rw-r--r--scene/resources/default_theme/font_lodpi.inc13117
-rw-r--r--scene/resources/material.cpp7
-rw-r--r--scene/resources/mesh.cpp134
-rw-r--r--scene/resources/mesh.h2
-rw-r--r--scene/resources/physics_material.cpp4
-rw-r--r--scene/resources/primitive_meshes.cpp10
-rw-r--r--scene/resources/resource_format_text.cpp14
-rw-r--r--scene/resources/shape_3d.cpp2
-rw-r--r--scene/resources/surface_tool.cpp8
-rw-r--r--scene/resources/text_file.cpp4
-rw-r--r--scene/resources/texture.cpp2
-rw-r--r--scene/resources/tile_set.cpp4797
-rw-r--r--scene/resources/tile_set.h686
-rw-r--r--scene/resources/visual_shader.cpp4
-rw-r--r--scene/resources/visual_shader.h4
66 files changed, 6841 insertions, 41754 deletions
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index 8a0631a614..774a194e39 100644
--- a/scene/2d/gpu_particles_2d.cpp
+++ b/scene/2d/gpu_particles_2d.cpp
@@ -369,6 +369,7 @@ void GPUParticles2D::_bind_methods() {
GPUParticles2D::GPUParticles2D() {
particles = RS::get_singleton()->particles_create();
+ RS::get_singleton()->particles_set_mode(particles, RS::PARTICLES_MODE_2D);
one_shot = false; // Needed so that set_emitting doesn't access uninitialized values
set_emitting(true);
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 1a7038bb80..21083e6a4b 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -302,17 +302,18 @@ void Polygon2D::_notification(int p_what) {
colors.write[i] = color_r[i];
}
} else {
- colors.push_back(color);
+ colors.resize(len);
+ for (int i = 0; i < len; i++) {
+ colors.write[i] = color;
+ }
}
+ Vector<int> index_array;
+
if (invert || polygons.size() == 0) {
- Vector<int> indices = Geometry2D::triangulate_polygon(points);
- if (indices.size()) {
- RS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID(), -1);
- }
+ index_array = Geometry2D::triangulate_polygon(points);
} else {
//draw individual polygons
- Vector<int> total_indices;
for (int i = 0; i < polygons.size(); i++) {
Vector<int> src_indices = polygons[i];
int ic = src_indices.size();
@@ -333,18 +334,38 @@ void Polygon2D::_notification(int p_what) {
int ic2 = indices.size();
const int *r2 = indices.ptr();
- int bic = total_indices.size();
- total_indices.resize(bic + ic2);
- int *w2 = total_indices.ptrw();
+ int bic = index_array.size();
+ index_array.resize(bic + ic2);
+ int *w2 = index_array.ptrw();
for (int j = 0; j < ic2; j++) {
w2[j + bic] = r[r2[j]];
}
}
+ }
+
+ RS::get_singleton()->mesh_clear(mesh);
+
+ if (index_array.size()) {
+ Array arr;
+ arr.resize(RS::ARRAY_MAX);
+ arr[RS::ARRAY_VERTEX] = points;
+ if (uvs.size() == points.size()) {
+ arr[RS::ARRAY_TEX_UV] = uvs;
+ }
+ if (colors.size() == points.size()) {
+ arr[RS::ARRAY_COLOR] = colors;
+ }
- if (total_indices.size()) {
- RS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), total_indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID());
+ if (bones.size() == points.size() * 4) {
+ arr[RS::ARRAY_BONES] = bones;
+ arr[RS::ARRAY_WEIGHTS] = weights;
}
+
+ arr[RS::ARRAY_INDEX] = index_array;
+
+ RS::get_singleton()->mesh_add_surface_from_arrays(mesh, RS::PRIMITIVE_TRIANGLES, arr, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
+ RS::get_singleton()->canvas_item_add_mesh(get_canvas_item(), mesh, Transform2D(), Color(), texture.is_valid() ? texture->get_rid() : RID());
}
} break;
@@ -655,4 +676,9 @@ void Polygon2D::_bind_methods() {
}
Polygon2D::Polygon2D() {
+ mesh = RS::get_singleton()->mesh_create();
+}
+
+Polygon2D::~Polygon2D() {
+ RS::get_singleton()->free(mesh);
}
diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h
index c207024a53..f9f36ff9a2 100644
--- a/scene/2d/polygon_2d.h
+++ b/scene/2d/polygon_2d.h
@@ -72,6 +72,8 @@ class Polygon2D : public Node2D {
void _skeleton_bone_setup_changed();
+ RID mesh;
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -149,6 +151,7 @@ public:
NodePath get_skeleton() const;
Polygon2D();
+ ~Polygon2D();
};
#endif // POLYGON_2D_H
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 4565543ec3..0afead0863 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -30,260 +30,323 @@
#include "tile_map.h"
-#include "collision_object_2d.h"
#include "core/io/marshalls.h"
+#include "core/math/geometry_2d.h"
#include "core/os/os.h"
-#include "scene/2d/area_2d.h"
-#include "servers/navigation_server_2d.h"
-#include "servers/physics_server_2d.h"
-int TileMap::_get_quadrant_size() const {
- if (use_y_sort) {
- return 1;
- } else {
- return quadrant_size;
- }
+void TileMapPattern::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile) {
+ ERR_FAIL_COND_MSG(p_coords.x < 0 || p_coords.y < 0, vformat("Cannot set cell with negative coords in a TileMapPattern. Wrong coords: %s", p_coords));
+
+ size = size.max(p_coords + Vector2i(1, 1));
+ pattern[p_coords] = TileMapCell(p_source_id, p_atlas_coords, p_alternative_tile);
}
-void TileMap::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- if (use_parent) {
- _clear_quadrants();
- collision_parent = Object::cast_to<CollisionObject2D>(get_parent());
- }
+bool TileMapPattern::has_cell(const Vector2i &p_coords) const {
+ return pattern.has(p_coords);
+}
- pending_update = true;
- _recreate_quadrants();
- update_dirty_quadrants();
- RID space = get_world_2d()->get_space();
- _update_quadrant_transform();
- _update_quadrant_space(space);
- update_configuration_warnings();
+void TileMapPattern::remove_cell(const Vector2i &p_coords, bool p_update_size) {
+ ERR_FAIL_COND(!pattern.has(p_coords));
- } break;
+ pattern.erase(p_coords);
+ if (p_update_size) {
+ size = Vector2i();
+ for (Map<Vector2i, TileMapCell>::Element *E = pattern.front(); E; E = E->next()) {
+ size = size.max(E->key() + Vector2i(1, 1));
+ }
+ }
+}
- case NOTIFICATION_EXIT_TREE: {
- _update_quadrant_space(RID());
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- Quadrant &q = E->get();
- for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) {
- NavigationServer2D::get_singleton()->region_set_map(F->get().region, RID());
- }
- q.navpoly_ids.clear();
+int TileMapPattern::get_cell_source_id(const Vector2i &p_coords) const {
+ ERR_FAIL_COND_V(!pattern.has(p_coords), -1);
- if (collision_parent) {
- collision_parent->remove_shape_owner(q.shape_owner_id);
- q.shape_owner_id = -1;
- }
+ return pattern[p_coords].source_id;
+}
- for (Map<PosKey, Quadrant::Occluder>::Element *F = q.occluder_instances.front(); F; F = F->next()) {
- RS::get_singleton()->free(F->get().id);
- }
- q.occluder_instances.clear();
- }
+Vector2i TileMapPattern::get_cell_atlas_coords(const Vector2i &p_coords) const {
+ ERR_FAIL_COND_V(!pattern.has(p_coords), TileSetAtlasSource::INVALID_ATLAS_COORDS);
- collision_parent = nullptr;
- } break;
+ return pattern[p_coords].get_atlas_coords();
+}
- case NOTIFICATION_TRANSFORM_CHANGED: {
- //move stuff
- _update_quadrant_transform();
+int TileMapPattern::get_cell_alternative_tile(const Vector2i &p_coords) const {
+ ERR_FAIL_COND_V(!pattern.has(p_coords), TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
- } break;
- case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
- if (use_parent) {
- _recreate_quadrants();
- }
+ return pattern[p_coords].alternative_tile;
+}
- } break;
+TypedArray<Vector2i> TileMapPattern::get_used_cells() const {
+ // Returns the cells used in the tilemap.
+ TypedArray<Vector2i> a;
+ a.resize(pattern.size());
+ int i = 0;
+ for (Map<Vector2i, TileMapCell>::Element *E = pattern.front(); E; E = E->next()) {
+ Vector2i p(E->key().x, E->key().y);
+ a[i++] = p;
}
+
+ return a;
}
-void TileMap::_update_quadrant_space(const RID &p_space) {
- if (!use_parent) {
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- Quadrant &q = E->get();
- PhysicsServer2D::get_singleton()->body_set_space(q.body, p_space);
- }
- }
+Vector2i TileMapPattern::get_size() const {
+ return size;
}
-void TileMap::_update_quadrant_transform() {
- if (!is_inside_tree()) {
- return;
+void TileMapPattern::set_size(const Vector2i &p_size) {
+ for (Map<Vector2i, TileMapCell>::Element *E = pattern.front(); E; E = E->next()) {
+ Vector2i coords = E->key();
+ if (p_size.x <= coords.x || p_size.y <= coords.y) {
+ ERR_FAIL_MSG(vformat("Cannot set pattern size to %s, it contains a tile at %s. Size can only be increased.", p_size, coords));
+ };
}
- Transform2D global_transform = get_global_transform();
+ size = p_size;
+}
- Transform2D local_transform;
- if (collision_parent) {
- local_transform = get_transform();
- }
+bool TileMapPattern::is_empty() const {
+ return pattern.is_empty();
+};
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- Quadrant &q = E->get();
- Transform2D xform;
- xform.set_origin(q.pos);
+void TileMapPattern::clear() {
+ size = Vector2i();
+ pattern.clear();
+};
- if (!use_parent) {
- xform = global_transform * xform;
- PhysicsServer2D::get_singleton()->body_set_state(q.body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
- }
+void TileMapPattern::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapPattern::set_cell, DEFVAL(-1), DEFVAL(TileSetAtlasSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetAtlasSource::INVALID_TILE_ALTERNATIVE));
+ ClassDB::bind_method(D_METHOD("has_cell", "coords"), &TileMapPattern::has_cell);
+ ClassDB::bind_method(D_METHOD("remove_cell", "coords"), &TileMapPattern::remove_cell);
+ ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords"), &TileMapPattern::get_cell_source_id);
+ ClassDB::bind_method(D_METHOD("get_cell_atlas_coords", "coords"), &TileMapPattern::get_cell_atlas_coords);
+ ClassDB::bind_method(D_METHOD("get_cell_alternative_tile", "coords"), &TileMapPattern::get_cell_alternative_tile);
- if (bake_navigation) {
- for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) {
- NavigationServer2D::get_singleton()->region_set_transform(F->get().region, F->get().xform);
+ ClassDB::bind_method(D_METHOD("get_used_cells"), &TileMapPattern::get_used_cells);
+ ClassDB::bind_method(D_METHOD("get_size"), &TileMapPattern::get_size);
+ ClassDB::bind_method(D_METHOD("set_size", "size"), &TileMapPattern::set_size);
+ ClassDB::bind_method(D_METHOD("is_empty"), &TileMapPattern::is_empty);
+}
+
+Vector2i TileMap::transform_coords_layout(Vector2i p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout) {
+ // Transform to stacked layout.
+ Vector2i output = p_coords;
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
+ SWAP(output.x, output.y);
+ }
+ switch (p_from_layout) {
+ case TileSet::TILE_LAYOUT_STACKED:
+ break;
+ case TileSet::TILE_LAYOUT_STACKED_OFFSET:
+ if (output.y % 2) {
+ output.x -= 1;
}
- }
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
+ case TileSet::TILE_LAYOUT_STAIRS_DOWN:
+ if ((p_from_layout == TileSet::TILE_LAYOUT_STAIRS_RIGHT) ^ (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
+ if (output.y < 0 && bool(output.y % 2)) {
+ output = Vector2i(output.x + output.y / 2 - 1, output.y);
+ } else {
+ output = Vector2i(output.x + output.y / 2, output.y);
+ }
+ } else {
+ if (output.x < 0 && bool(output.x % 2)) {
+ output = Vector2i(output.x / 2 - 1, output.x + output.y * 2);
+ } else {
+ output = Vector2i(output.x / 2, output.x + output.y * 2);
+ }
+ }
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
+ case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
+ if ((p_from_layout == TileSet::TILE_LAYOUT_DIAMOND_RIGHT) ^ (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
+ if ((output.x + output.y) < 0 && (output.x - output.y) % 2) {
+ output = Vector2i((output.x + output.y) / 2 - 1, output.y - output.x);
+ } else {
+ output = Vector2i((output.x + output.y) / 2, -output.x + output.y);
+ }
+ } else {
+ if ((output.x - output.y) < 0 && (output.x + output.y) % 2) {
+ output = Vector2i((output.x - output.y) / 2 - 1, output.x + output.y);
+ } else {
+ output = Vector2i((output.x - output.y) / 2, output.x + output.y);
+ }
+ }
+ break;
+ }
- for (Map<PosKey, Quadrant::Occluder>::Element *F = q.occluder_instances.front(); F; F = F->next()) {
- RS::get_singleton()->canvas_light_occluder_set_transform(F->get().id, global_transform * F->get().xform);
- }
+ switch (p_to_layout) {
+ case TileSet::TILE_LAYOUT_STACKED:
+ break;
+ case TileSet::TILE_LAYOUT_STACKED_OFFSET:
+ if (output.y % 2) {
+ output.x += 1;
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
+ case TileSet::TILE_LAYOUT_STAIRS_DOWN:
+ if ((p_to_layout == TileSet::TILE_LAYOUT_STAIRS_RIGHT) ^ (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
+ if (output.y < 0 && (output.y % 2)) {
+ output = Vector2i(output.x - output.y / 2 + 1, output.y);
+ } else {
+ output = Vector2i(output.x - output.y / 2, output.y);
+ }
+ } else {
+ if (output.y % 2) {
+ if (output.y < 0) {
+ output = Vector2i(2 * output.x + 1, -output.x + output.y / 2 - 1);
+ } else {
+ output = Vector2i(2 * output.x + 1, -output.x + output.y / 2);
+ }
+ } else {
+ output = Vector2i(2 * output.x, -output.x + output.y / 2);
+ }
+ }
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
+ case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
+ if ((p_to_layout == TileSet::TILE_LAYOUT_DIAMOND_RIGHT) ^ (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
+ if (output.y % 2) {
+ if (output.y > 0) {
+ output = Vector2i(output.x - output.y / 2, output.x + output.y / 2 + 1);
+ } else {
+ output = Vector2i(output.x - output.y / 2 + 1, output.x + output.y / 2);
+ }
+ } else {
+ output = Vector2i(output.x - output.y / 2, output.x + output.y / 2);
+ }
+ } else {
+ if (output.y % 2) {
+ if (output.y < 0) {
+ output = Vector2i(output.x + output.y / 2, -output.x + output.y / 2 - 1);
+ } else {
+ output = Vector2i(output.x + output.y / 2 + 1, -output.x + output.y / 2);
+ }
+ } else {
+ output = Vector2i(output.x + output.y / 2, -output.x + output.y / 2);
+ }
+ }
+ break;
}
-}
-void TileMap::set_tileset(const Ref<TileSet> &p_tileset) {
- if (tile_set.is_valid()) {
- tile_set->disconnect("changed", callable_mp(this, &TileMap::_recreate_quadrants));
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
+ SWAP(output.x, output.y);
}
- _clear_quadrants();
- tile_set = p_tileset;
+ return output;
+}
- if (tile_set.is_valid()) {
- tile_set->connect("changed", callable_mp(this, &TileMap::_recreate_quadrants));
+int TileMap::get_effective_quadrant_size() const {
+ // When using YSort, the quadrant size is reduced to 1 to have one CanvasItem per quadrant
+ if (tile_set.is_valid() && tile_set->is_y_sorting()) {
+ return 1;
} else {
- clear();
+ return quadrant_size;
}
+}
- _recreate_quadrants();
- emit_signal("settings_changed");
+Vector2i TileMap::_coords_to_quadrant_coords(const Vector2i &p_coords) const {
+ int quadrant_size = get_effective_quadrant_size();
+
+ // Rounding down, instead of simply rounding towards zero (truncating)
+ return Vector2i(
+ p_coords.x > 0 ? p_coords.x / quadrant_size : (p_coords.x - (quadrant_size - 1)) / quadrant_size,
+ p_coords.y > 0 ? p_coords.y / quadrant_size : (p_coords.y - (quadrant_size - 1)) / quadrant_size);
+}
+
+void TileMap::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ pending_update = true;
+ _recreate_quadrants();
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ _clear_quadrants();
+ } break;
+ }
+
+ // Transfers the notification to tileset plugins.
+ if (tile_set.is_valid()) {
+ for (int i = 0; i < tile_set->get_tile_set_atlas_plugins().size(); i++) {
+ tile_set->get_tile_set_atlas_plugins()[i]->tilemap_notification(this, p_what);
+ }
+ }
}
Ref<TileSet> TileMap::get_tileset() const {
return tile_set;
}
-void TileMap::set_cell_size(Size2 p_size) {
- ERR_FAIL_COND(p_size.x < 1 || p_size.y < 1);
+void TileMap::set_tileset(const Ref<TileSet> &p_tileset) {
+ if (p_tileset == tile_set) {
+ return;
+ }
- _clear_quadrants();
- cell_size = p_size;
- _recreate_quadrants();
- emit_signal("settings_changed");
+ // Set the tileset, registering to its changes.
+ if (tile_set.is_valid()) {
+ tile_set->disconnect("changed", callable_mp(this, &TileMap::_make_all_quadrants_dirty));
+ tile_set->disconnect("changed", callable_mp(this, &TileMap::_tile_set_changed));
+ }
+
+ if (!p_tileset.is_valid()) {
+ _clear_quadrants();
+ }
+
+ tile_set = p_tileset;
+
+ if (tile_set.is_valid()) {
+ tile_set->connect("changed", callable_mp(this, &TileMap::_make_all_quadrants_dirty), varray(true));
+ tile_set->connect("changed", callable_mp(this, &TileMap::_tile_set_changed));
+ _recreate_quadrants();
+ }
+
+ emit_signal("changed");
}
-Size2 TileMap::get_cell_size() const {
- return cell_size;
+int TileMap::get_quadrant_size() const {
+ return quadrant_size;
}
void TileMap::set_quadrant_size(int p_size) {
- ERR_FAIL_COND_MSG(p_size < 1, "Quadrant size cannot be smaller than 1.");
+ ERR_FAIL_COND_MSG(p_size < 1, "TileMapQuadrant size cannot be smaller than 1.");
- _clear_quadrants();
quadrant_size = p_size;
_recreate_quadrants();
- emit_signal("settings_changed");
-}
-
-int TileMap::get_quadrant_size() const {
- return quadrant_size;
+ emit_signal("changed");
}
-void TileMap::_fix_cell_transform(Transform2D &xform, const Cell &p_cell, const Vector2 &p_offset, const Size2 &p_sc) {
+void TileMap::_fix_cell_transform(Transform2D &xform, const TileMapCell &p_cell, const Vector2 &p_offset, const Size2 &p_sc) {
Size2 s = p_sc;
Vector2 offset = p_offset;
- if (compatibility_mode && !centered_textures) {
- if (tile_origin == TILE_ORIGIN_BOTTOM_LEFT) {
- offset.y += cell_size.y;
- } else if (tile_origin == TILE_ORIGIN_CENTER) {
- offset += cell_size / 2;
- }
-
- if (s.y > s.x) {
- if ((p_cell.flip_h && (p_cell.flip_v || p_cell.transpose)) || (p_cell.flip_v && !p_cell.transpose)) {
- offset.y += s.y - s.x;
- }
- } else if (s.y < s.x) {
- if ((p_cell.flip_v && (p_cell.flip_h || p_cell.transpose)) || (p_cell.flip_h && !p_cell.transpose)) {
- offset.x += s.x - s.y;
- }
- }
+ // Flip/transpose: update the tile transform.
+ TileSetSource *source = *tile_set->get_source(p_cell.source_id);
+ TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ if (!atlas_source) {
+ return;
}
-
- if (p_cell.transpose) {
+ TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(p_cell.get_atlas_coords(), p_cell.alternative_tile));
+ if (tile_data->get_transpose()) {
SWAP(xform.elements[0].x, xform.elements[0].y);
SWAP(xform.elements[1].x, xform.elements[1].y);
SWAP(offset.x, offset.y);
SWAP(s.x, s.y);
}
- if (p_cell.flip_h) {
+ if (tile_data->get_flip_h()) {
xform.elements[0].x = -xform.elements[0].x;
xform.elements[1].x = -xform.elements[1].x;
- if (compatibility_mode && !centered_textures) {
- if (tile_origin == TILE_ORIGIN_TOP_LEFT || tile_origin == TILE_ORIGIN_BOTTOM_LEFT) {
- offset.x = s.x - offset.x;
- } else if (tile_origin == TILE_ORIGIN_CENTER) {
- offset.x = s.x - offset.x / 2;
- }
- } else {
- offset.x = s.x - offset.x;
- }
+ offset.x = s.x - offset.x;
}
- if (p_cell.flip_v) {
+ if (tile_data->get_flip_v()) {
xform.elements[0].y = -xform.elements[0].y;
xform.elements[1].y = -xform.elements[1].y;
- if (compatibility_mode && !centered_textures) {
- if (tile_origin == TILE_ORIGIN_TOP_LEFT) {
- offset.y = s.y - offset.y;
- } else if (tile_origin == TILE_ORIGIN_BOTTOM_LEFT) {
- offset.y += s.y;
- } else if (tile_origin == TILE_ORIGIN_CENTER) {
- offset.y += s.y;
- }
- } else {
- offset.y = s.y - offset.y;
- }
+ offset.y = s.y - offset.y;
}
- if (centered_textures) {
- offset += cell_size / 2 - s / 2;
- }
xform.elements[2] += offset;
}
-void TileMap::_add_shape(int &shape_idx, const Quadrant &p_q, const Ref<Shape2D> &p_shape, const TileSet::ShapeData &p_shape_data, const Transform2D &p_xform, const Vector2 &p_metadata) {
- PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
-
- if (!use_parent) {
- ps->body_add_shape(p_q.body, p_shape->get_rid(), p_xform);
- ps->body_set_shape_metadata(p_q.body, shape_idx, p_metadata);
- ps->body_set_shape_as_one_way_collision(p_q.body, shape_idx, p_shape_data.one_way_collision, p_shape_data.one_way_collision_margin);
-
- } else if (collision_parent) {
- Transform2D xform = p_xform;
- xform.set_origin(xform.get_origin() + p_q.pos);
-
- collision_parent->shape_owner_add_shape(p_q.shape_owner_id, p_shape);
-
- int real_index = collision_parent->shape_owner_get_shape_index(p_q.shape_owner_id, shape_idx);
- RID rid = collision_parent->get_rid();
-
- if (Object::cast_to<Area2D>(collision_parent) != nullptr) {
- ps->area_set_shape_transform(rid, real_index, get_transform() * xform);
- } else {
- ps->body_set_shape_transform(rid, real_index, get_transform() * xform);
- ps->body_set_shape_metadata(rid, real_index, p_metadata);
- ps->body_set_shape_as_one_way_collision(rid, real_index, p_shape_data.one_way_collision, p_shape_data.one_way_collision_margin);
- }
- }
- shape_idx++;
-}
-
void TileMap::update_dirty_quadrants() {
if (!pending_update) {
return;
@@ -293,387 +356,47 @@ void TileMap::update_dirty_quadrants() {
return;
}
- RenderingServer *vs = RenderingServer::get_singleton();
- PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
- Vector2 tofs = get_cell_draw_offset();
- Vector2 qofs;
-
- SceneTree *st = SceneTree::get_singleton();
- Color debug_collision_color;
- Color debug_navigation_color;
-
- bool debug_shapes = st && st->is_debugging_collisions_hint();
- if (debug_shapes) {
- debug_collision_color = st->get_debug_collisions_color();
+ // Update the coords cache.
+ for (SelfList<TileMapQuadrant> *q = dirty_quadrant_list.first(); q; q = q->next()) {
+ q->self()->map_to_world.clear();
+ q->self()->world_to_map.clear();
+ for (Set<Vector2i>::Element *E = q->self()->cells.front(); E; E = E->next()) {
+ Vector2i pk = E->get();
+ Vector2i pk_world_coords = map_to_world(pk);
+ q->self()->map_to_world[pk] = pk_world_coords;
+ q->self()->world_to_map[pk_world_coords] = pk;
+ }
}
- bool debug_navigation = st && st->is_debugging_navigation_hint();
- if (debug_navigation) {
- debug_navigation_color = st->get_debug_navigation_color();
+ // Call the update_dirty_quadrant method on plugins.
+ for (int i = 0; i < tile_set->get_tile_set_atlas_plugins().size(); i++) {
+ tile_set->get_tile_set_atlas_plugins()[i]->update_dirty_quadrants(this, dirty_quadrant_list);
}
- while (dirty_quadrant_list.first()) {
- Quadrant &q = *dirty_quadrant_list.first()->self();
-
- for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) {
- vs->free(E->get());
- }
-
- q.canvas_items.clear();
-
- if (!use_parent) {
- ps->body_clear_shapes(q.body);
- } else if (collision_parent) {
- collision_parent->shape_owner_clear_shapes(q.shape_owner_id);
- }
- int shape_idx = 0;
-
- for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) {
- NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID());
- }
- q.navpoly_ids.clear();
-
- for (Map<PosKey, Quadrant::Occluder>::Element *E = q.occluder_instances.front(); E; E = E->next()) {
- RS::get_singleton()->free(E->get().id);
- }
- q.occluder_instances.clear();
- Ref<ShaderMaterial> prev_material;
- int prev_z_index = 0;
- RID prev_canvas_item;
- RID prev_debug_canvas_item;
-
- for (int i = 0; i < q.cells.size(); i++) {
- Map<PosKey, Cell>::Element *E = tile_map.find(q.cells[i]);
- Cell &c = E->get();
- //moment of truth
- if (!tile_set->has_tile(c.id)) {
- continue;
- }
- Ref<Texture2D> tex = tile_set->tile_get_texture(c.id);
- Vector2 tile_ofs = tile_set->tile_get_texture_offset(c.id);
-
- Vector2 wofs = _map_to_world(E->key().x, E->key().y);
- Vector2 offset = wofs - q.pos + tofs;
-
- if (!tex.is_valid()) {
- continue;
- }
-
- Ref<ShaderMaterial> mat = tile_set->tile_get_material(c.id);
- int z_index = tile_set->tile_get_z_index(c.id);
-
- if (tile_set->tile_get_tile_mode(c.id) == TileSet::AUTO_TILE ||
- tile_set->tile_get_tile_mode(c.id) == TileSet::ATLAS_TILE) {
- z_index += tile_set->autotile_get_z_index(c.id, Vector2(c.autotile_coord_x, c.autotile_coord_y));
- }
-
- RID canvas_item;
- RID debug_canvas_item;
-
- if (prev_canvas_item == RID() || prev_material != mat || prev_z_index != z_index) {
- canvas_item = vs->canvas_item_create();
- if (mat.is_valid()) {
- vs->canvas_item_set_material(canvas_item, mat->get_rid());
- }
- vs->canvas_item_set_parent(canvas_item, get_canvas_item());
- _update_item_material_state(canvas_item);
- Transform2D xform;
- xform.set_origin(q.pos);
- vs->canvas_item_set_transform(canvas_item, xform);
- vs->canvas_item_set_light_mask(canvas_item, get_light_mask());
- vs->canvas_item_set_z_index(canvas_item, z_index);
-
- vs->canvas_item_set_default_texture_filter(canvas_item, RS::CanvasItemTextureFilter(CanvasItem::get_texture_filter()));
- vs->canvas_item_set_default_texture_repeat(canvas_item, RS::CanvasItemTextureRepeat(CanvasItem::get_texture_repeat()));
-
- q.canvas_items.push_back(canvas_item);
-
- if (debug_shapes) {
- debug_canvas_item = vs->canvas_item_create();
- vs->canvas_item_set_parent(debug_canvas_item, canvas_item);
- vs->canvas_item_set_z_as_relative_to_parent(debug_canvas_item, false);
- vs->canvas_item_set_z_index(debug_canvas_item, RS::CANVAS_ITEM_Z_MAX - 1);
- q.canvas_items.push_back(debug_canvas_item);
- prev_debug_canvas_item = debug_canvas_item;
- }
-
- prev_canvas_item = canvas_item;
- prev_material = mat;
- prev_z_index = z_index;
-
- } else {
- canvas_item = prev_canvas_item;
- if (debug_shapes) {
- debug_canvas_item = prev_debug_canvas_item;
- }
- }
-
- Rect2 r = tile_set->tile_get_region(c.id);
- if (tile_set->tile_get_tile_mode(c.id) == TileSet::AUTO_TILE || tile_set->tile_get_tile_mode(c.id) == TileSet::ATLAS_TILE) {
- int spacing = tile_set->autotile_get_spacing(c.id);
- r.size = tile_set->autotile_get_size(c.id);
- r.position += (r.size + Vector2(spacing, spacing)) * Vector2(c.autotile_coord_x, c.autotile_coord_y);
- }
-
- Size2 s;
- if (r == Rect2()) {
- s = tex->get_size();
- } else {
- s = r.size;
- }
-
- Rect2 rect;
- rect.position = offset.floor();
- rect.size = s;
- rect.size.x += fp_adjust;
- rect.size.y += fp_adjust;
-
- if (compatibility_mode && !centered_textures) {
- if (rect.size.y > rect.size.x) {
- if ((c.flip_h && (c.flip_v || c.transpose)) || (c.flip_v && !c.transpose)) {
- tile_ofs.y += rect.size.y - rect.size.x;
- }
- } else if (rect.size.y < rect.size.x) {
- if ((c.flip_v && (c.flip_h || c.transpose)) || (c.flip_h && !c.transpose)) {
- tile_ofs.x += rect.size.x - rect.size.y;
- }
- }
- }
-
- if (c.transpose) {
- SWAP(tile_ofs.x, tile_ofs.y);
- if (centered_textures) {
- rect.position.x += cell_size.x / 2 - rect.size.y / 2;
- rect.position.y += cell_size.y / 2 - rect.size.x / 2;
- }
- } else if (centered_textures) {
- rect.position += cell_size / 2 - rect.size / 2;
- }
-
- if (c.flip_h) {
- rect.size.x = -rect.size.x;
- tile_ofs.x = -tile_ofs.x;
- }
-
- if (c.flip_v) {
- rect.size.y = -rect.size.y;
- tile_ofs.y = -tile_ofs.y;
- }
-
- if (compatibility_mode && !centered_textures) {
- if (tile_origin == TILE_ORIGIN_TOP_LEFT) {
- rect.position += tile_ofs;
-
- } else if (tile_origin == TILE_ORIGIN_BOTTOM_LEFT) {
- rect.position += tile_ofs;
-
- if (c.transpose) {
- if (c.flip_h) {
- rect.position.x -= cell_size.x;
- } else {
- rect.position.x += cell_size.x;
- }
- } else {
- if (c.flip_v) {
- rect.position.y -= cell_size.y;
- } else {
- rect.position.y += cell_size.y;
- }
- }
-
- } else if (tile_origin == TILE_ORIGIN_CENTER) {
- rect.position += tile_ofs;
-
- if (c.flip_h) {
- rect.position.x -= cell_size.x / 2;
- } else {
- rect.position.x += cell_size.x / 2;
- }
-
- if (c.flip_v) {
- rect.position.y -= cell_size.y / 2;
- } else {
- rect.position.y += cell_size.y / 2;
- }
- }
- } else {
- rect.position += tile_ofs;
- }
-
- Color modulate = tile_set->tile_get_modulate(c.id);
- Color self_modulate = get_self_modulate();
- modulate = Color(modulate.r * self_modulate.r, modulate.g * self_modulate.g,
- modulate.b * self_modulate.b, modulate.a * self_modulate.a);
- if (r == Rect2()) {
- tex->draw_rect(canvas_item, rect, false, modulate, c.transpose);
- } else {
- tex->draw_rect_region(canvas_item, rect, r, modulate, c.transpose, clip_uv);
- }
-
- Vector<TileSet::ShapeData> shapes = tile_set->tile_get_shapes(c.id);
-
- for (int j = 0; j < shapes.size(); j++) {
- Ref<Shape2D> shape = shapes[j].shape;
- if (shape.is_valid()) {
- if (tile_set->tile_get_tile_mode(c.id) == TileSet::SINGLE_TILE || (shapes[j].autotile_coord.x == c.autotile_coord_x && shapes[j].autotile_coord.y == c.autotile_coord_y)) {
- Transform2D xform;
- xform.set_origin(offset.floor());
-
- Vector2 shape_ofs = shapes[j].shape_transform.get_origin();
-
- _fix_cell_transform(xform, c, shape_ofs, s);
-
- xform *= shapes[j].shape_transform.untranslated();
-
- if (debug_canvas_item.is_valid()) {
- vs->canvas_item_add_set_transform(debug_canvas_item, xform);
- shape->draw(debug_canvas_item, debug_collision_color);
- }
-
- if (shape->has_meta("decomposed")) {
- Array _shapes = shape->get_meta("decomposed");
- for (int k = 0; k < _shapes.size(); k++) {
- Ref<ConvexPolygonShape2D> convex = _shapes[k];
- if (convex.is_valid()) {
- _add_shape(shape_idx, q, convex, shapes[j], xform, Vector2(E->key().x, E->key().y));
-#ifdef DEBUG_ENABLED
- } else {
- print_error("The TileSet assigned to the TileMap " + get_name() + " has an invalid convex shape.");
-#endif
- }
- }
- } else {
- _add_shape(shape_idx, q, shape, shapes[j], xform, Vector2(E->key().x, E->key().y));
- }
- }
- }
- }
-
- if (debug_canvas_item.is_valid()) {
- vs->canvas_item_add_set_transform(debug_canvas_item, Transform2D());
- }
-
- if (bake_navigation) {
- Ref<NavigationPolygon> navpoly;
- Vector2 npoly_ofs;
- if (tile_set->tile_get_tile_mode(c.id) == TileSet::AUTO_TILE || tile_set->tile_get_tile_mode(c.id) == TileSet::ATLAS_TILE) {
- navpoly = tile_set->autotile_get_navigation_polygon(c.id, Vector2(c.autotile_coord_x, c.autotile_coord_y));
- npoly_ofs = Vector2();
- } else {
- navpoly = tile_set->tile_get_navigation_polygon(c.id);
- npoly_ofs = tile_set->tile_get_navigation_polygon_offset(c.id);
- }
-
- if (navpoly.is_valid()) {
- Transform2D xform;
- xform.set_origin(offset.floor() + q.pos);
- _fix_cell_transform(xform, c, npoly_ofs, s);
-
- RID region = NavigationServer2D::get_singleton()->region_create();
- NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
- NavigationServer2D::get_singleton()->region_set_transform(region, xform);
- NavigationServer2D::get_singleton()->region_set_navpoly(region, navpoly);
-
- Quadrant::NavPoly np;
- np.region = region;
- np.xform = xform;
- q.navpoly_ids[E->key()] = np;
-
- if (debug_navigation) {
- RID debug_navigation_item = vs->canvas_item_create();
- vs->canvas_item_set_parent(debug_navigation_item, canvas_item);
- vs->canvas_item_set_z_as_relative_to_parent(debug_navigation_item, false);
- vs->canvas_item_set_z_index(debug_navigation_item, RS::CANVAS_ITEM_Z_MAX - 2); // Display one below collision debug
-
- if (debug_navigation_item.is_valid()) {
- Vector<Vector2> navigation_polygon_vertices = navpoly->get_vertices();
- int vsize = navigation_polygon_vertices.size();
-
- if (vsize > 2) {
- Vector<Color> colors;
- Vector<Vector2> vertices;
- vertices.resize(vsize);
- colors.resize(vsize);
- {
- const Vector2 *vr = navigation_polygon_vertices.ptr();
- for (int j = 0; j < vsize; j++) {
- vertices.write[j] = vr[j];
- colors.write[j] = debug_navigation_color;
- }
- }
-
- Vector<int> indices;
-
- for (int j = 0; j < navpoly->get_polygon_count(); j++) {
- Vector<int> polygon = navpoly->get_polygon(j);
-
- for (int k = 2; k < polygon.size(); k++) {
- int kofs[3] = { 0, k - 1, k };
- for (int l = 0; l < 3; l++) {
- int idx = polygon[kofs[l]];
- ERR_FAIL_INDEX(idx, vsize);
- indices.push_back(idx);
- }
- }
- }
- Transform2D navxform;
- navxform.set_origin(offset.floor());
- _fix_cell_transform(navxform, c, npoly_ofs, s);
-
- vs->canvas_item_set_transform(debug_navigation_item, navxform);
- vs->canvas_item_add_triangle_array(debug_navigation_item, indices, vertices, colors);
- }
- }
- }
- }
- }
-
- Ref<OccluderPolygon2D> occluder;
- if (tile_set->tile_get_tile_mode(c.id) == TileSet::AUTO_TILE || tile_set->tile_get_tile_mode(c.id) == TileSet::ATLAS_TILE) {
- occluder = tile_set->autotile_get_light_occluder(c.id, Vector2(c.autotile_coord_x, c.autotile_coord_y));
- } else {
- occluder = tile_set->tile_get_light_occluder(c.id);
- }
- if (occluder.is_valid()) {
- Vector2 occluder_ofs = tile_set->tile_get_occluder_offset(c.id);
- Transform2D xform;
- xform.set_origin(offset.floor() + q.pos);
- _fix_cell_transform(xform, c, occluder_ofs, s);
-
- RID orid = RS::get_singleton()->canvas_light_occluder_create();
- RS::get_singleton()->canvas_light_occluder_set_transform(orid, get_global_transform() * xform);
- RS::get_singleton()->canvas_light_occluder_set_polygon(orid, occluder->get_rid());
- RS::get_singleton()->canvas_light_occluder_attach_to_canvas(orid, get_canvas());
- RS::get_singleton()->canvas_light_occluder_set_light_mask(orid, occluder_light_mask);
- Quadrant::Occluder oc;
- oc.xform = xform;
- oc.id = orid;
- q.occluder_instances[E->key()] = oc;
- }
+ // Redraw the debug canvas_items.
+ RenderingServer *rs = RenderingServer::get_singleton();
+ for (SelfList<TileMapQuadrant> *q = dirty_quadrant_list.first(); q; q = q->next()) {
+ rs->canvas_item_clear(q->self()->debug_canvas_item);
+ Transform2D xform;
+ xform.set_origin(map_to_world(q->self()->coords * get_effective_quadrant_size()));
+ rs->canvas_item_set_transform(q->self()->debug_canvas_item, xform);
+ for (int i = 0; i < tile_set->get_tile_set_atlas_plugins().size(); i++) {
+ tile_set->get_tile_set_atlas_plugins()[i]->draw_quadrant_debug(this, q->self());
}
+ }
+ // Clear the list
+ while (dirty_quadrant_list.first()) {
dirty_quadrant_list.remove(dirty_quadrant_list.first());
- quadrant_order_dirty = true;
}
pending_update = false;
- if (quadrant_order_dirty) {
- int index = -(int64_t)0x80000000; //always must be drawn below children
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- Quadrant &q = E->get();
- for (List<RID>::Element *F = q.canvas_items.front(); F; F = F->next()) {
- RS::get_singleton()->canvas_item_set_draw_index(F->get(), index++);
- }
- }
-
- quadrant_order_dirty = false;
- }
-
_recompute_rect_cache();
}
void TileMap::_recompute_rect_cache() {
+ // Compute the displayed area of the tilemap.
#ifdef DEBUG_ENABLED
if (!rect_cache_dirty) {
@@ -681,12 +404,12 @@ void TileMap::_recompute_rect_cache() {
}
Rect2 r_total;
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
+ for (Map<Vector2i, TileMapQuadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
Rect2 r;
- r.position = _map_to_world(E->key().x * _get_quadrant_size(), E->key().y * _get_quadrant_size());
- r.expand_to(_map_to_world(E->key().x * _get_quadrant_size() + _get_quadrant_size(), E->key().y * _get_quadrant_size()));
- r.expand_to(_map_to_world(E->key().x * _get_quadrant_size() + _get_quadrant_size(), E->key().y * _get_quadrant_size() + _get_quadrant_size()));
- r.expand_to(_map_to_world(E->key().x * _get_quadrant_size(), E->key().y * _get_quadrant_size() + _get_quadrant_size()));
+ r.position = map_to_world(E->key() * get_effective_quadrant_size());
+ r.expand_to(map_to_world((E->key() + Vector2i(1, 0)) * get_effective_quadrant_size()));
+ r.expand_to(map_to_world((E->key() + Vector2i(1, 1)) * get_effective_quadrant_size()));
+ r.expand_to(map_to_world((E->key() + Vector2i(0, 1)) * get_effective_quadrant_size()));
if (E == quadrant_map.front()) {
r_total = r;
} else {
@@ -702,83 +425,58 @@ void TileMap::_recompute_rect_cache() {
#endif
}
-Map<TileMap::PosKey, TileMap::Quadrant>::Element *TileMap::_create_quadrant(const PosKey &p_qk) {
- Transform2D xform;
- //xform.set_origin(Point2(p_qk.x,p_qk.y)*cell_size*quadrant_size);
- Quadrant q;
- q.pos = _map_to_world(p_qk.x * _get_quadrant_size(), p_qk.y * _get_quadrant_size());
- q.pos += get_cell_draw_offset();
- if (tile_origin == TILE_ORIGIN_CENTER) {
- q.pos += cell_size / 2;
- } else if (tile_origin == TILE_ORIGIN_BOTTOM_LEFT) {
- q.pos.y += cell_size.y;
- }
-
- xform.set_origin(q.pos);
- //q.canvas_item = RenderingServer::get_singleton()->canvas_item_create();
- if (!use_parent) {
- q.body = PhysicsServer2D::get_singleton()->body_create();
- PhysicsServer2D::get_singleton()->body_set_mode(q.body, use_kinematic ? PhysicsServer2D::BODY_MODE_KINEMATIC : PhysicsServer2D::BODY_MODE_STATIC);
-
- PhysicsServer2D::get_singleton()->body_attach_object_instance_id(q.body, get_instance_id());
- PhysicsServer2D::get_singleton()->body_set_collision_layer(q.body, collision_layer);
- PhysicsServer2D::get_singleton()->body_set_collision_mask(q.body, collision_mask);
- PhysicsServer2D::get_singleton()->body_set_param(q.body, PhysicsServer2D::BODY_PARAM_FRICTION, friction);
- PhysicsServer2D::get_singleton()->body_set_param(q.body, PhysicsServer2D::BODY_PARAM_BOUNCE, bounce);
-
- if (is_inside_tree()) {
- xform = get_global_transform() * xform;
- RID space = get_world_2d()->get_space();
- PhysicsServer2D::get_singleton()->body_set_space(q.body, space);
- }
+Map<Vector2i, TileMapQuadrant>::Element *TileMap::_create_quadrant(const Vector2i &p_qk) {
+ TileMapQuadrant q;
+ q.coords = p_qk;
- PhysicsServer2D::get_singleton()->body_set_state(q.body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
- } else if (collision_parent) {
- xform = get_transform() * xform;
- q.shape_owner_id = collision_parent->create_shape_owner(this);
- } else {
- q.shape_owner_id = -1;
+ rect_cache_dirty = true;
+
+ // Create the debug canvas item.
+ RenderingServer *rs = RenderingServer::get_singleton();
+ q.debug_canvas_item = rs->canvas_item_create();
+ rs->canvas_item_set_z_index(q.debug_canvas_item, RS::CANVAS_ITEM_Z_MAX - 1);
+ rs->canvas_item_set_parent(q.debug_canvas_item, get_canvas_item());
+
+ // Call the create_quadrant method on plugins
+ if (tile_set.is_valid()) {
+ for (int i = 0; i < tile_set->get_tile_set_atlas_plugins().size(); i++) {
+ tile_set->get_tile_set_atlas_plugins()[i]->create_quadrant(this, &q);
+ }
}
- rect_cache_dirty = true;
- quadrant_order_dirty = true;
return quadrant_map.insert(p_qk, q);
}
-void TileMap::_erase_quadrant(Map<PosKey, Quadrant>::Element *Q) {
- Quadrant &q = Q->get();
- if (!use_parent) {
- PhysicsServer2D::get_singleton()->free(q.body);
- } else if (collision_parent) {
- collision_parent->remove_shape_owner(q.shape_owner_id);
- }
+void TileMap::_erase_quadrant(Map<Vector2i, TileMapQuadrant>::Element *Q) {
+ // Remove a quadrant.
+ TileMapQuadrant *q = &(Q->get());
- for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) {
- RenderingServer::get_singleton()->free(E->get());
- }
- q.canvas_items.clear();
- if (q.dirty_list.in_list()) {
- dirty_quadrant_list.remove(&q.dirty_list);
+ // Call the cleanup_quadrant method on plugins.
+ if (tile_set.is_valid()) {
+ for (int i = 0; i < tile_set->get_tile_set_atlas_plugins().size(); i++) {
+ tile_set->get_tile_set_atlas_plugins()[i]->cleanup_quadrant(this, q);
+ }
}
- for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) {
- NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID());
+ // Remove the quadrant from the dirty_list if it is there.
+ if (q->dirty_list_element.in_list()) {
+ dirty_quadrant_list.remove(&(q->dirty_list_element));
}
- q.navpoly_ids.clear();
- for (Map<PosKey, Quadrant::Occluder>::Element *E = q.occluder_instances.front(); E; E = E->next()) {
- RS::get_singleton()->free(E->get().id);
- }
- q.occluder_instances.clear();
+ // Free the debug canvas item.
+ RenderingServer *rs = RenderingServer::get_singleton();
+ rs->free(q->debug_canvas_item);
quadrant_map.erase(Q);
rect_cache_dirty = true;
}
-void TileMap::_make_quadrant_dirty(Map<PosKey, Quadrant>::Element *Q, bool update) {
- Quadrant &q = Q->get();
- if (!q.dirty_list.in_list()) {
- dirty_quadrant_list.add(&q.dirty_list);
+void TileMap::_make_all_quadrants_dirty(bool p_update) {
+ // Make all quandrants dirty, then trigger an update later.
+ for (Map<Vector2i, TileMapQuadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
+ if (!E->value().dirty_list_element.in_list()) {
+ dirty_quadrant_list.add(&E->value().dirty_list_element);
+ }
}
if (pending_update) {
@@ -788,39 +486,68 @@ void TileMap::_make_quadrant_dirty(Map<PosKey, Quadrant>::Element *Q, bool updat
if (!is_inside_tree()) {
return;
}
-
- if (update) {
+ if (p_update) {
call_deferred("update_dirty_quadrants");
}
}
-void TileMap::set_cellv(const Vector2 &p_pos, int p_tile, bool p_flip_x, bool p_flip_y, bool p_transpose) {
- set_cell(p_pos.x, p_pos.y, p_tile, p_flip_x, p_flip_y, p_transpose);
-}
+void TileMap::_make_quadrant_dirty(Map<Vector2i, TileMapQuadrant>::Element *Q, bool p_update) {
+ // Make the given quadrant dirty, then trigger an update later.
+ TileMapQuadrant &q = Q->get();
+ if (!q.dirty_list_element.in_list()) {
+ dirty_quadrant_list.add(&q.dirty_list_element);
+ }
+
+ if (pending_update) {
+ return;
+ }
+ pending_update = true;
+ if (!is_inside_tree()) {
+ return;
+ }
-void TileMap::_set_celld(const Vector2 &p_pos, const Dictionary &p_data) {
- Variant v_pos_x = p_pos.x, v_pos_y = p_pos.y, v_tile = p_data["id"], v_flip_h = p_data["flip_h"], v_flip_v = p_data["flip_y"], v_transpose = p_data["transpose"], v_autotile_coord = p_data["auto_coord"];
- const Variant *args[7] = { &v_pos_x, &v_pos_y, &v_tile, &v_flip_h, &v_flip_v, &v_transpose, &v_autotile_coord };
- Callable::CallError ce;
- call("set_cell", args, 7, ce);
+ if (p_update) {
+ call_deferred("update_dirty_quadrants");
+ }
}
-void TileMap::set_cell(int p_x, int p_y, int p_tile, bool p_flip_x, bool p_flip_y, bool p_transpose, Vector2 p_autotile_coord) {
- PosKey pk(p_x, p_y);
+void TileMap::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile) {
+ // Set the current cell tile (using integer position).
+ Vector2i pk(p_coords);
+ Map<Vector2i, TileMapCell>::Element *E = tile_map.find(pk);
+
+ int source_id = p_source_id;
+ Vector2i atlas_coords = p_atlas_coords;
+ int alternative_tile = p_alternative_tile;
+
+ if ((source_id == -1 || atlas_coords == TileSetAtlasSource::INVALID_ATLAS_COORDS || alternative_tile == TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) &&
+ (source_id != -1 || atlas_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS || alternative_tile != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE)) {
+ WARN_PRINT("Setting a cell a cell as empty requires both source_id, atlas_coord and alternative_tile to be set to their respective \"invalid\" values. Values were thus changes accordingly.");
+ source_id = -1;
+ atlas_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS;
+ alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ }
- Map<PosKey, Cell>::Element *E = tile_map.find(pk);
- if (!E && p_tile == INVALID_CELL) {
- return; //nothing to do
+ if (!E && source_id == -1) {
+ return; // Nothing to do, the tile is already empty.
}
- PosKey qk = pk.to_quadrant(_get_quadrant_size());
- if (p_tile == INVALID_CELL) {
- //erase existing
+ // Get the quadrant
+ Vector2i qk = _coords_to_quadrant_coords(pk);
+
+ Map<Vector2i, TileMapQuadrant>::Element *Q = quadrant_map.find(qk);
+
+ if (source_id == -1) {
+ // Erase existing cell in the tile map.
tile_map.erase(pk);
- Map<PosKey, Quadrant>::Element *Q = quadrant_map.find(qk);
+
+ // Erase existing cell in the quadrant.
ERR_FAIL_COND(!Q);
- Quadrant &q = Q->get();
+ TileMapQuadrant &q = Q->get();
+
q.cells.erase(pk);
+
+ // Remove or make the quadrant dirty.
if (q.cells.size() == 0) {
_erase_quadrant(Q);
} else {
@@ -828,331 +555,232 @@ void TileMap::set_cell(int p_x, int p_y, int p_tile, bool p_flip_x, bool p_flip_
}
used_size_cache_dirty = true;
- return;
- }
-
- Map<PosKey, Quadrant>::Element *Q = quadrant_map.find(qk);
-
- if (!E) {
- E = tile_map.insert(pk, Cell());
- if (!Q) {
- Q = _create_quadrant(qk);
- }
- Quadrant &q = Q->get();
- q.cells.insert(pk);
} else {
- ERR_FAIL_COND(!Q); // quadrant should exist...
-
- if (E->get().id == p_tile && E->get().flip_h == p_flip_x && E->get().flip_v == p_flip_y && E->get().transpose == p_transpose && E->get().autotile_coord_x == (uint16_t)p_autotile_coord.x && E->get().autotile_coord_y == (uint16_t)p_autotile_coord.y) {
- return; //nothing changed
- }
- }
-
- Cell &c = E->get();
-
- c.id = p_tile;
- c.flip_h = p_flip_x;
- c.flip_v = p_flip_y;
- c.transpose = p_transpose;
- c.autotile_coord_x = (uint16_t)p_autotile_coord.x;
- c.autotile_coord_y = (uint16_t)p_autotile_coord.y;
-
- _make_quadrant_dirty(Q);
- used_size_cache_dirty = true;
-}
+ if (!E) {
+ // Insert a new cell in the tile map.
+ E = tile_map.insert(pk, TileMapCell());
-int TileMap::get_cellv(const Vector2 &p_pos) const {
- return get_cell(p_pos.x, p_pos.y);
-}
-
-void TileMap::make_bitmask_area_dirty(const Vector2 &p_pos) {
- for (int x = p_pos.x - 1; x <= p_pos.x + 1; x++) {
- for (int y = p_pos.y - 1; y <= p_pos.y + 1; y++) {
- PosKey p(x, y);
- if (dirty_bitmask.find(p) == nullptr) {
- dirty_bitmask.push_back(p);
- }
- }
- }
-}
-
-void TileMap::update_bitmask_area(const Vector2 &p_pos) {
- for (int x = p_pos.x - 1; x <= p_pos.x + 1; x++) {
- for (int y = p_pos.y - 1; y <= p_pos.y + 1; y++) {
- update_cell_bitmask(x, y);
- }
- }
-}
-
-void TileMap::update_bitmask_region(const Vector2 &p_start, const Vector2 &p_end) {
- if ((p_end.x < p_start.x || p_end.y < p_start.y) || (p_end.x == p_start.x && p_end.y == p_start.y)) {
- Array a = get_used_cells();
- for (int i = 0; i < a.size(); i++) {
- Vector2 vector = (Vector2)a[i];
- update_cell_bitmask(vector.x, vector.y);
- }
- return;
- }
- for (int x = p_start.x - 1; x <= p_end.x + 1; x++) {
- for (int y = p_start.y - 1; y <= p_end.y + 1; y++) {
- update_cell_bitmask(x, y);
- }
- }
-}
-
-void TileMap::update_cell_bitmask(int p_x, int p_y) {
- ERR_FAIL_COND_MSG(tile_set.is_null(), "Cannot update cell bitmask if Tileset is not open.");
- PosKey p(p_x, p_y);
- Map<PosKey, Cell>::Element *E = tile_map.find(p);
- if (E != nullptr) {
- int id = get_cell(p_x, p_y);
- if (tile_set->tile_get_tile_mode(id) == TileSet::AUTO_TILE) {
- uint16_t mask = 0;
- if (tile_set->autotile_get_bitmask_mode(id) == TileSet::BITMASK_2X2) {
- if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y))) {
- mask |= TileSet::BIND_TOPLEFT;
- }
- if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y))) {
- mask |= TileSet::BIND_TOPRIGHT;
- }
- if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y))) {
- mask |= TileSet::BIND_BOTTOMLEFT;
- }
- if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y))) {
- mask |= TileSet::BIND_BOTTOMRIGHT;
- }
- } else {
- if (tile_set->autotile_get_bitmask_mode(id) == TileSet::BITMASK_3X3_MINIMAL) {
- if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y))) {
- mask |= TileSet::BIND_TOPLEFT;
- }
- if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y))) {
- mask |= TileSet::BIND_TOPRIGHT;
- }
- if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y))) {
- mask |= TileSet::BIND_BOTTOMLEFT;
- }
- if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y))) {
- mask |= TileSet::BIND_BOTTOMRIGHT;
- }
- } else {
- if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y - 1))) {
- mask |= TileSet::BIND_TOPLEFT;
- }
- if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y - 1))) {
- mask |= TileSet::BIND_TOPRIGHT;
- }
- if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y + 1))) {
- mask |= TileSet::BIND_BOTTOMLEFT;
- }
- if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y + 1))) {
- mask |= TileSet::BIND_BOTTOMRIGHT;
- }
- }
- if (tile_set->is_tile_bound(id, get_cell(p_x, p_y - 1))) {
- mask |= TileSet::BIND_TOP;
- }
- if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y))) {
- mask |= TileSet::BIND_LEFT;
- }
- mask |= TileSet::BIND_CENTER;
- if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y))) {
- mask |= TileSet::BIND_RIGHT;
- }
- if (tile_set->is_tile_bound(id, get_cell(p_x, p_y + 1))) {
- mask |= TileSet::BIND_BOTTOM;
- }
+ // Create a new quadrant if needed, then insert the cell if needed.
+ if (!Q) {
+ Q = _create_quadrant(qk);
}
- Vector2 coord = tile_set->autotile_get_subtile_for_bitmask(id, mask, this, Vector2(p_x, p_y));
- E->get().autotile_coord_x = (int)coord.x;
- E->get().autotile_coord_y = (int)coord.y;
-
- PosKey qk = p.to_quadrant(_get_quadrant_size());
- Map<PosKey, Quadrant>::Element *Q = quadrant_map.find(qk);
- _make_quadrant_dirty(Q);
+ TileMapQuadrant &q = Q->get();
+ q.cells.insert(pk);
- } else if (tile_set->tile_get_tile_mode(id) == TileSet::SINGLE_TILE) {
- E->get().autotile_coord_x = 0;
- E->get().autotile_coord_y = 0;
- } else if (tile_set->tile_get_tile_mode(id) == TileSet::ATLAS_TILE) {
- if (tile_set->autotile_get_bitmask(id, Vector2(p_x, p_y)) == TileSet::BIND_CENTER) {
- Vector2 coord = tile_set->atlastile_get_subtile_by_priority(id, this, Vector2(p_x, p_y));
+ } else {
+ ERR_FAIL_COND(!Q); // TileMapQuadrant should exist...
- E->get().autotile_coord_x = (int)coord.x;
- E->get().autotile_coord_y = (int)coord.y;
+ if (E->get().source_id == source_id && E->get().get_atlas_coords() == atlas_coords && E->get().alternative_tile == alternative_tile) {
+ return; // Nothing changed.
}
}
- }
-}
-void TileMap::update_dirty_bitmask() {
- while (dirty_bitmask.size() > 0) {
- update_cell_bitmask(dirty_bitmask[0].x, dirty_bitmask[0].y);
- dirty_bitmask.pop_front();
- }
-}
+ TileMapCell &c = E->get();
-void TileMap::fix_invalid_tiles() {
- ERR_FAIL_COND_MSG(tile_set.is_null(), "Cannot fix invalid tiles if Tileset is not open.");
+ c.source_id = source_id;
+ c.set_atlas_coords(atlas_coords);
+ c.alternative_tile = alternative_tile;
- Map<PosKey, Cell> temp_tile_map = tile_map;
- for (Map<PosKey, Cell>::Element *E = temp_tile_map.front(); E; E = E->next()) {
- if (!tile_set->has_tile(get_cell(E->key().x, E->key().y))) {
- set_cell(E->key().x, E->key().y, INVALID_CELL);
- }
+ _make_quadrant_dirty(Q);
+ used_size_cache_dirty = true;
}
}
-int TileMap::get_cell(int p_x, int p_y) const {
- PosKey pk(p_x, p_y);
-
- const Map<PosKey, Cell>::Element *E = tile_map.find(pk);
+int TileMap::get_cell_source_id(const Vector2i &p_coords) const {
+ // Get a cell source id from position
+ const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords);
if (!E) {
- return INVALID_CELL;
+ return -1;
}
- return E->get().id;
+ return E->get().source_id;
}
-bool TileMap::is_cell_x_flipped(int p_x, int p_y) const {
- PosKey pk(p_x, p_y);
-
- const Map<PosKey, Cell>::Element *E = tile_map.find(pk);
+Vector2i TileMap::get_cell_atlas_coords(const Vector2i &p_coords) const {
+ // Get a cell source id from position
+ const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords);
if (!E) {
- return false;
+ return TileSetAtlasSource::INVALID_ATLAS_COORDS;
}
- return E->get().flip_h;
+ return E->get().get_atlas_coords();
}
-bool TileMap::is_cell_y_flipped(int p_x, int p_y) const {
- PosKey pk(p_x, p_y);
-
- const Map<PosKey, Cell>::Element *E = tile_map.find(pk);
+int TileMap::get_cell_alternative_tile(const Vector2i &p_coords) const {
+ // Get a cell source id from position
+ const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords);
if (!E) {
- return false;
+ return TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
}
- return E->get().flip_v;
+ return E->get().alternative_tile;
}
-bool TileMap::is_cell_transposed(int p_x, int p_y) const {
- PosKey pk(p_x, p_y);
+TileMapPattern *TileMap::get_pattern(TypedArray<Vector2i> p_coords_array) {
+ ERR_FAIL_COND_V(!tile_set.is_valid(), nullptr);
- const Map<PosKey, Cell>::Element *E = tile_map.find(pk);
-
- if (!E) {
- return false;
+ TileMapPattern *output = memnew(TileMapPattern);
+ if (p_coords_array.is_empty()) {
+ return output;
}
- return E->get().transpose;
-}
-
-void TileMap::set_cell_autotile_coord(int p_x, int p_y, const Vector2 &p_coord) {
- PosKey pk(p_x, p_y);
+ Vector2i min = Vector2i(p_coords_array[0]);
+ for (int i = 1; i < p_coords_array.size(); i++) {
+ min = min.min(p_coords_array[i]);
+ }
- const Map<PosKey, Cell>::Element *E = tile_map.find(pk);
+ Vector<Vector2i> coords_in_pattern_array;
+ coords_in_pattern_array.resize(p_coords_array.size());
+ Vector2i ensure_positive_offset;
+ for (int i = 0; i < p_coords_array.size(); i++) {
+ Vector2i coords = p_coords_array[i];
+ Vector2i coords_in_pattern = coords - min;
+ if (tile_set->get_tile_shape() != TileSet::TILE_SHAPE_SQUARE) {
+ if (tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STACKED) {
+ if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(min.y % 2) && bool(coords_in_pattern.y % 2)) {
+ coords_in_pattern.x -= 1;
+ if (coords_in_pattern.x < 0) {
+ ensure_positive_offset.x = 1;
+ }
+ } else if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(min.x % 2) && bool(coords_in_pattern.x % 2)) {
+ coords_in_pattern.y -= 1;
+ if (coords_in_pattern.y < 0) {
+ ensure_positive_offset.y = 1;
+ }
+ }
+ } else if (tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STACKED_OFFSET) {
+ if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(min.y % 2) && bool(coords_in_pattern.y % 2)) {
+ coords_in_pattern.x += 1;
+ } else if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(min.x % 2) && bool(coords_in_pattern.x % 2)) {
+ coords_in_pattern.y += 1;
+ }
+ }
+ }
+ coords_in_pattern_array.write[i] = coords_in_pattern;
+ }
- if (!E) {
- return;
+ for (int i = 0; i < coords_in_pattern_array.size(); i++) {
+ Vector2i coords = p_coords_array[i];
+ Vector2i coords_in_pattern = coords_in_pattern_array[i];
+ output->set_cell(coords_in_pattern + ensure_positive_offset, get_cell_source_id(coords), get_cell_atlas_coords(coords), get_cell_alternative_tile(coords));
}
- Cell c = E->get();
- c.autotile_coord_x = p_coord.x;
- c.autotile_coord_y = p_coord.y;
- tile_map[pk] = c;
+ return output;
+}
- PosKey qk = pk.to_quadrant(_get_quadrant_size());
- Map<PosKey, Quadrant>::Element *Q = quadrant_map.find(qk);
+Vector2i TileMap::map_pattern(Vector2i p_position_in_tilemap, Vector2i p_coords_in_pattern, const TileMapPattern *p_pattern) {
+ ERR_FAIL_COND_V(!p_pattern->has_cell(p_coords_in_pattern), Vector2i());
- if (!Q) {
- return;
+ Vector2i output = p_position_in_tilemap + p_coords_in_pattern;
+ if (tile_set->get_tile_shape() != TileSet::TILE_SHAPE_SQUARE) {
+ if (tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STACKED) {
+ if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(p_position_in_tilemap.y % 2) && bool(p_coords_in_pattern.y % 2)) {
+ output.x += 1;
+ } else if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(p_position_in_tilemap.x % 2) && bool(p_coords_in_pattern.x % 2)) {
+ output.y += 1;
+ }
+ } else if (tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STACKED_OFFSET) {
+ if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL && bool(p_position_in_tilemap.y % 2) && bool(p_coords_in_pattern.y % 2)) {
+ output.x -= 1;
+ } else if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL && bool(p_position_in_tilemap.x % 2) && bool(p_coords_in_pattern.x % 2)) {
+ output.y -= 1;
+ }
+ }
}
- _make_quadrant_dirty(Q);
+ return output;
}
-Vector2 TileMap::get_cell_autotile_coord(int p_x, int p_y) const {
- PosKey pk(p_x, p_y);
+void TileMap::set_pattern(Vector2i p_position, const TileMapPattern *p_pattern) {
+ ERR_FAIL_COND(!tile_set.is_valid());
- const Map<PosKey, Cell>::Element *E = tile_map.find(pk);
+ TypedArray<Vector2i> used_cells = p_pattern->get_used_cells();
+ for (int i = 0; i < used_cells.size(); i++) {
+ Vector2i coords = map_pattern(p_position, used_cells[i], p_pattern);
+ set_cell(coords, p_pattern->get_cell_source_id(coords), p_pattern->get_cell_atlas_coords(coords), p_pattern->get_cell_alternative_tile(coords));
+ }
+}
- if (!E) {
- return Vector2();
+TileMapCell TileMap::get_cell(const Vector2i &p_coords) const {
+ if (!tile_map.has(p_coords)) {
+ return TileMapCell();
+ } else {
+ return tile_map.find(p_coords)->get();
}
+}
- return Vector2(E->get().autotile_coord_x, E->get().autotile_coord_y);
+Map<Vector2i, TileMapQuadrant> &TileMap::get_quadrant_map() {
+ return quadrant_map;
+}
+
+void TileMap::fix_invalid_tiles() {
+ ERR_FAIL_COND_MSG(tile_set.is_null(), "Cannot fix invalid tiles if Tileset is not open.");
+ for (Map<Vector2i, TileMapCell>::Element *E = tile_map.front(); E; E = E->next()) {
+ TileSetSource *source = *tile_set->get_source(E->get().source_id);
+ if (!source || !source->has_tile(E->get().get_atlas_coords()) || !source->has_alternative_tile(E->get().get_atlas_coords(), E->get().alternative_tile)) {
+ set_cell(E->key(), -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ }
+ }
}
void TileMap::_recreate_quadrants() {
+ // Clear then recreate all quadrants.
_clear_quadrants();
- for (Map<PosKey, Cell>::Element *E = tile_map.front(); E; E = E->next()) {
- PosKey qk = PosKey(E->key().x, E->key().y).to_quadrant(_get_quadrant_size());
+ for (Map<Vector2i, TileMapCell>::Element *E = tile_map.front(); E; E = E->next()) {
+ Vector2i qk = _coords_to_quadrant_coords(Vector2i(E->key().x, E->key().y));
- Map<PosKey, Quadrant>::Element *Q = quadrant_map.find(qk);
+ Map<Vector2i, TileMapQuadrant>::Element *Q = quadrant_map.find(qk);
if (!Q) {
Q = _create_quadrant(qk);
- dirty_quadrant_list.add(&Q->get().dirty_list);
+ dirty_quadrant_list.add(&Q->get().dirty_list_element);
}
- Q->get().cells.insert(E->key());
+ Vector2i pk = E->key();
+ Q->get().cells.insert(pk);
+
_make_quadrant_dirty(Q, false);
}
+
update_dirty_quadrants();
}
void TileMap::_clear_quadrants() {
+ // Clear quadrants.
while (quadrant_map.size()) {
_erase_quadrant(quadrant_map.front());
}
-}
-void TileMap::set_material(const Ref<Material> &p_material) {
- CanvasItem::set_material(p_material);
- _update_all_items_material_state();
-}
-
-void TileMap::set_use_parent_material(bool p_use_parent_material) {
- CanvasItem::set_use_parent_material(p_use_parent_material);
- _update_all_items_material_state();
-}
-
-void TileMap::_update_all_items_material_state() {
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- Quadrant &q = E->get();
- for (List<RID>::Element *F = q.canvas_items.front(); F; F = F->next()) {
- _update_item_material_state(F->get());
- }
+ // Clear the dirty quadrants list.
+ while (dirty_quadrant_list.first()) {
+ dirty_quadrant_list.remove(dirty_quadrant_list.first());
}
}
-void TileMap::_update_item_material_state(const RID &p_canvas_item) {
- RS::get_singleton()->canvas_item_set_use_parent_material(p_canvas_item, get_use_parent_material() || get_material().is_valid());
-}
-
void TileMap::clear() {
+ // Remove all tiles.
_clear_quadrants();
tile_map.clear();
used_size_cache_dirty = true;
}
void TileMap::_set_tile_data(const Vector<int> &p_data) {
- ERR_FAIL_COND(format > FORMAT_2);
+ // Set data for a given tile from raw data.
+ ERR_FAIL_COND(format > FORMAT_3);
int c = p_data.size();
const int *r = p_data.ptr();
- int offset = (format == FORMAT_2) ? 3 : 2;
+ int offset = (format >= FORMAT_2) ? 3 : 2;
clear();
for (int i = 0; i < c; i += offset) {
const uint8_t *ptr = (const uint8_t *)&r[i];
uint8_t local[12];
- for (int j = 0; j < ((format == FORMAT_2) ? 12 : 8); j++) {
+ for (int j = 0; j < ((format >= FORMAT_2) ? 12 : 8); j++) {
local[j] = ptr[j];
}
@@ -1163,31 +791,49 @@ void TileMap::_set_tile_data(const Vector<int> &p_data) {
SWAP(local[4], local[7]);
SWAP(local[5], local[6]);
//TODO: ask someone to check this...
- if (FORMAT == FORMAT_2) {
+ if (FORMAT >= FORMAT_2) {
SWAP(local[8], local[11]);
SWAP(local[9], local[10]);
}
#endif
+ int16_t x = decode_uint16(&local[0]);
+ int16_t y = decode_uint16(&local[2]);
+
+ if (format == FORMAT_3) {
+ uint16_t source_id = decode_uint16(&local[4]);
+ uint16_t atlas_coords_x = decode_uint16(&local[6]);
+ uint16_t atlas_coords_y = decode_uint32(&local[8]);
+ uint16_t alternative_tile = decode_uint16(&local[10]);
+ set_cell(Vector2i(x, y), source_id, Vector2i(atlas_coords_x, atlas_coords_y), alternative_tile);
+ } else {
+ uint32_t v = decode_uint32(&local[4]);
+ v &= (1 << 29) - 1;
+
+ // We generate an alternative tile number out of the the flags
+ // An option should create the alternative in the tileset for compatibility
+ bool flip_h = v & (1 << 29);
+ bool flip_v = v & (1 << 30);
+ bool transpose = v & (1 << 31);
+ int16_t coord_x = 0;
+ int16_t coord_y = 0;
+ if (format == FORMAT_2) {
+ coord_x = decode_uint16(&local[8]);
+ coord_y = decode_uint16(&local[10]);
+ }
- uint16_t x = decode_uint16(&local[0]);
- uint16_t y = decode_uint16(&local[2]);
- uint32_t v = decode_uint32(&local[4]);
- bool flip_h = v & (1 << 29);
- bool flip_v = v & (1 << 30);
- bool transpose = v & (1 << 31);
- v &= (1 << 29) - 1;
- int16_t coord_x = 0;
- int16_t coord_y = 0;
- if (format == FORMAT_2) {
- coord_x = decode_uint16(&local[8]);
- coord_y = decode_uint16(&local[10]);
- }
+ int compatibility_alternative_tile = ((int)flip_h) + ((int)flip_v << 1) + ((int)transpose << 2);
+
+ if (tile_set.is_valid()) {
+ v = tile_set->compatibility_get_source_for_tile_id(v);
+ }
- set_cell(x, y, v, flip_h, flip_v, transpose, Vector2(coord_x, coord_y));
+ set_cell(Vector2i(x, y), v, Vector2i(coord_x, coord_y), compatibility_alternative_tile);
+ }
}
}
Vector<int> TileMap::_get_tile_data() const {
+ // Export tile data to raw format
Vector<int> data;
data.resize(tile_map.size() * 3);
int *w = data.ptrw();
@@ -1195,23 +841,14 @@ Vector<int> TileMap::_get_tile_data() const {
// Save in highest format
int idx = 0;
- for (const Map<PosKey, Cell>::Element *E = tile_map.front(); E; E = E->next()) {
+ for (const Map<Vector2i, TileMapCell>::Element *E = tile_map.front(); E; E = E->next()) {
uint8_t *ptr = (uint8_t *)&w[idx];
- encode_uint16(E->key().x, &ptr[0]);
- encode_uint16(E->key().y, &ptr[2]);
- uint32_t val = E->get().id;
- if (E->get().flip_h) {
- val |= (1 << 29);
- }
- if (E->get().flip_v) {
- val |= (1 << 30);
- }
- if (E->get().transpose) {
- val |= (1 << 31);
- }
- encode_uint32(val, &ptr[4]);
- encode_uint16(E->get().autotile_coord_x, &ptr[8]);
- encode_uint16(E->get().autotile_coord_y, &ptr[10]);
+ encode_uint16((int16_t)(E->key().x), &ptr[0]);
+ encode_uint16((int16_t)(E->key().y), &ptr[2]);
+ encode_uint16(E->get().source_id, &ptr[4]);
+ encode_uint16(E->get().coord_x, &ptr[6]);
+ encode_uint16(E->get().coord_y, &ptr[8]);
+ encode_uint16(E->get().alternative_tile, &ptr[10]);
idx += 3;
}
@@ -1220,6 +857,7 @@ Vector<int> TileMap::_get_tile_data() const {
#ifdef TOOLS_ENABLED
Rect2 TileMap::_edit_get_rect() const {
+ // Return the visible rect of the tilemap
if (pending_update) {
const_cast<TileMap *>(this)->update_dirty_quadrants();
} else {
@@ -1229,255 +867,6 @@ Rect2 TileMap::_edit_get_rect() const {
}
#endif
-void TileMap::set_collision_layer(uint32_t p_layer) {
- collision_layer = p_layer;
- if (!use_parent) {
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- Quadrant &q = E->get();
- PhysicsServer2D::get_singleton()->body_set_collision_layer(q.body, collision_layer);
- }
- }
-}
-
-void TileMap::set_collision_mask(uint32_t p_mask) {
- collision_mask = p_mask;
- if (!use_parent) {
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- Quadrant &q = E->get();
- PhysicsServer2D::get_singleton()->body_set_collision_mask(q.body, collision_mask);
- }
- }
-}
-
-void TileMap::set_collision_layer_bit(int p_bit, bool p_value) {
- ERR_FAIL_INDEX_MSG(p_bit, 32, "Collision layer bit must be between 0 and 31 inclusive.");
- uint32_t layer = get_collision_layer();
- if (p_value) {
- layer |= 1 << p_bit;
- } else {
- layer &= ~(1 << p_bit);
- }
- set_collision_layer(layer);
-}
-
-void TileMap::set_collision_mask_bit(int p_bit, bool p_value) {
- ERR_FAIL_INDEX_MSG(p_bit, 32, "Collision mask bit must be between 0 and 31 inclusive.");
- uint32_t mask = get_collision_mask();
- if (p_value) {
- mask |= 1 << p_bit;
- } else {
- mask &= ~(1 << p_bit);
- }
- set_collision_mask(mask);
-}
-
-bool TileMap::get_collision_use_kinematic() const {
- return use_kinematic;
-}
-
-void TileMap::set_collision_use_kinematic(bool p_use_kinematic) {
- _clear_quadrants();
- use_kinematic = p_use_kinematic;
- _recreate_quadrants();
-}
-
-bool TileMap::get_collision_use_parent() const {
- return use_parent;
-}
-
-void TileMap::set_collision_use_parent(bool p_use_parent) {
- if (use_parent == p_use_parent) {
- return;
- }
-
- _clear_quadrants();
-
- use_parent = p_use_parent;
- set_notify_local_transform(use_parent);
-
- if (use_parent && is_inside_tree()) {
- collision_parent = Object::cast_to<CollisionObject2D>(get_parent());
- } else {
- collision_parent = nullptr;
- }
-
- _recreate_quadrants();
- notify_property_list_changed();
- update_configuration_warnings();
-}
-
-void TileMap::set_collision_friction(float p_friction) {
- friction = p_friction;
- if (!use_parent) {
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- Quadrant &q = E->get();
- PhysicsServer2D::get_singleton()->body_set_param(q.body, PhysicsServer2D::BODY_PARAM_FRICTION, p_friction);
- }
- }
-}
-
-float TileMap::get_collision_friction() const {
- return friction;
-}
-
-void TileMap::set_collision_bounce(float p_bounce) {
- bounce = p_bounce;
- if (!use_parent) {
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- Quadrant &q = E->get();
- PhysicsServer2D::get_singleton()->body_set_param(q.body, PhysicsServer2D::BODY_PARAM_BOUNCE, p_bounce);
- }
- }
-}
-
-float TileMap::get_collision_bounce() const {
- return bounce;
-}
-
-void TileMap::set_bake_navigation(bool p_bake_navigation) {
- bake_navigation = p_bake_navigation;
- for (Map<PosKey, Quadrant>::Element *F = quadrant_map.front(); F; F = F->next()) {
- _make_quadrant_dirty(F);
- }
-}
-
-bool TileMap::is_baking_navigation() {
- return bake_navigation;
-}
-
-uint32_t TileMap::get_collision_layer() const {
- return collision_layer;
-}
-
-uint32_t TileMap::get_collision_mask() const {
- return collision_mask;
-}
-
-bool TileMap::get_collision_layer_bit(int p_bit) const {
- ERR_FAIL_INDEX_V_MSG(p_bit, 32, false, "Collision layer bit must be between 0 and 31 inclusive.");
- return get_collision_layer() & (1 << p_bit);
-}
-
-bool TileMap::get_collision_mask_bit(int p_bit) const {
- ERR_FAIL_INDEX_V_MSG(p_bit, 32, false, "Collision mask bit must be between 0 and 31 inclusive.");
- return get_collision_mask() & (1 << p_bit);
-}
-
-void TileMap::set_mode(Mode p_mode) {
- _clear_quadrants();
- mode = p_mode;
- _recreate_quadrants();
- emit_signal("settings_changed");
-}
-
-TileMap::Mode TileMap::get_mode() const {
- return mode;
-}
-
-void TileMap::set_half_offset(HalfOffset p_half_offset) {
- _clear_quadrants();
- half_offset = p_half_offset;
- _recreate_quadrants();
- emit_signal("settings_changed");
-}
-
-void TileMap::set_tile_origin(TileOrigin p_tile_origin) {
- _clear_quadrants();
- tile_origin = p_tile_origin;
- _recreate_quadrants();
- emit_signal("settings_changed");
-}
-
-TileMap::TileOrigin TileMap::get_tile_origin() const {
- return tile_origin;
-}
-
-Vector2 TileMap::get_cell_draw_offset() const {
- switch (mode) {
- case MODE_SQUARE: {
- return Vector2();
- } break;
- case MODE_ISOMETRIC: {
- return Vector2(-cell_size.x * 0.5, 0);
-
- } break;
- case MODE_CUSTOM: {
- Vector2 min;
- min.x = MIN(custom_transform[0].x, min.x);
- min.y = MIN(custom_transform[0].y, min.y);
- min.x = MIN(custom_transform[1].x, min.x);
- min.y = MIN(custom_transform[1].y, min.y);
- return min;
- } break;
- }
-
- return Vector2();
-}
-
-TileMap::HalfOffset TileMap::get_half_offset() const {
- return half_offset;
-}
-
-Transform2D TileMap::get_cell_transform() const {
- switch (mode) {
- case MODE_SQUARE: {
- Transform2D m;
- m[0] *= cell_size.x;
- m[1] *= cell_size.y;
- return m;
- } break;
- case MODE_ISOMETRIC: {
- //isometric only makes sense when y is positive in both x and y vectors, otherwise
- //the drawing of tiles will overlap
- Transform2D m;
- m[0] = Vector2(cell_size.x * 0.5, cell_size.y * 0.5);
- m[1] = Vector2(-cell_size.x * 0.5, cell_size.y * 0.5);
- return m;
-
- } break;
- case MODE_CUSTOM: {
- return custom_transform;
- } break;
- }
-
- return Transform2D();
-}
-
-void TileMap::set_custom_transform(const Transform2D &p_xform) {
- _clear_quadrants();
- custom_transform = p_xform;
- _recreate_quadrants();
- emit_signal("settings_changed");
-}
-
-Transform2D TileMap::get_custom_transform() const {
- return custom_transform;
-}
-
-Vector2 TileMap::_map_to_world(int p_x, int p_y, bool p_ignore_ofs) const {
- Vector2 ret = get_cell_transform().xform(Vector2(p_x, p_y));
- if (!p_ignore_ofs) {
- switch (half_offset) {
- case HALF_OFFSET_X:
- case HALF_OFFSET_NEGATIVE_X: {
- if (ABS(p_y) & 1) {
- ret += get_cell_transform()[0] * (half_offset == HALF_OFFSET_X ? 0.5 : -0.5);
- }
- } break;
- case HALF_OFFSET_Y:
- case HALF_OFFSET_NEGATIVE_Y: {
- if (ABS(p_x) & 1) {
- ret += get_cell_transform()[1] * (half_offset == HALF_OFFSET_Y ? 0.5 : -0.5);
- }
- } break;
- case HALF_OFFSET_DISABLED: {
- // Nothing to do.
- }
- }
- }
- return ret;
-}
-
bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
if (p_name == "format") {
if (p_value.get_type() == Variant::INT) {
@@ -1496,7 +885,7 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
bool TileMap::_get(const StringName &p_name, Variant &r_ret) const {
if (p_name == "format") {
- r_ret = FORMAT_2; // When saving, always save highest format
+ r_ret = FORMAT_3; // When saving, always save highest format
return true;
} else if (p_name == "tile_data") {
r_ret = _get_tile_data();
@@ -1513,92 +902,632 @@ void TileMap::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(p);
}
-void TileMap::_validate_property(PropertyInfo &property) const {
- if (use_parent && property.name != "collision_use_parent" && property.name.begins_with("collision_")) {
- property.usage = PROPERTY_USAGE_NOEDITOR;
+Vector2 TileMap::map_to_world(const Vector2i &p_pos) const {
+ // SHOULD RETURN THE CENTER OF THE TILE
+ ERR_FAIL_COND_V(!tile_set.is_valid(), Vector2());
+
+ Vector2 ret = p_pos;
+ TileSet::TileShape tile_shape = tile_set->get_tile_shape();
+ TileSet::TileOffsetAxis tile_offset_axis = tile_set->get_tile_offset_axis();
+
+ if (tile_shape == TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE || tile_shape == TileSet::TILE_SHAPE_HEXAGON || tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ // Technically, those 3 shapes are equivalent, as they are basically half-offset, but with different levels or overlap.
+ // square = no overlap, hexagon = 0.25 overlap, isometric = 0.5 overlap
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ switch (tile_set->get_tile_layout()) {
+ case TileSet::TILE_LAYOUT_STACKED:
+ ret = Vector2(ret.x + (Math::posmod(ret.y, 2) == 0 ? 0.0 : 0.5), ret.y);
+ break;
+ case TileSet::TILE_LAYOUT_STACKED_OFFSET:
+ ret = Vector2(ret.x + (Math::posmod(ret.y, 2) == 1 ? 0.0 : 0.5), ret.y);
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
+ ret = Vector2(ret.x + ret.y / 2, ret.y);
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_DOWN:
+ ret = Vector2(ret.x / 2, ret.y * 2 + ret.x);
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
+ ret = Vector2((ret.x + ret.y) / 2, ret.y - ret.x);
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
+ ret = Vector2((ret.x - ret.y) / 2, ret.y + ret.x);
+ break;
+ }
+ } else { // TILE_OFFSET_AXIS_VERTICAL
+ switch (tile_set->get_tile_layout()) {
+ case TileSet::TILE_LAYOUT_STACKED:
+ ret = Vector2(ret.x, ret.y + (Math::posmod(ret.x, 2) == 0 ? 0.0 : 0.5));
+ break;
+ case TileSet::TILE_LAYOUT_STACKED_OFFSET:
+ ret = Vector2(ret.x, ret.y + (Math::posmod(ret.x, 2) == 1 ? 0.0 : 0.5));
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
+ ret = Vector2(ret.x * 2 + ret.y, ret.y / 2);
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_DOWN:
+ ret = Vector2(ret.x, ret.y + ret.x / 2);
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
+ ret = Vector2(ret.x + ret.y, (ret.y - ret.x) / 2);
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
+ ret = Vector2(ret.x - ret.y, (ret.y + ret.x) / 2);
+ break;
+ }
+ }
}
-}
-Vector2 TileMap::map_to_world(const Vector2 &p_pos, bool p_ignore_ofs) const {
- return _map_to_world(p_pos.x, p_pos.y, p_ignore_ofs);
+ // Multiply by the overlapping ratio
+ double overlapping_ratio = 1.0;
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ overlapping_ratio = 0.5;
+ } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) {
+ overlapping_ratio = 0.75;
+ }
+ ret.y *= overlapping_ratio;
+ } else { // TILE_OFFSET_AXIS_VERTICAL
+ if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ overlapping_ratio = 0.5;
+ } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) {
+ overlapping_ratio = 0.75;
+ }
+ ret.x *= overlapping_ratio;
+ }
+
+ return (ret + Vector2(0.5, 0.5)) * tile_set->get_tile_size();
}
-Vector2 TileMap::world_to_map(const Vector2 &p_pos) const {
- Vector2 ret = get_cell_transform().affine_inverse().xform(p_pos);
+Vector2i TileMap::world_to_map(const Vector2 &p_pos) const {
+ ERR_FAIL_COND_V(!tile_set.is_valid(), Vector2i());
+
+ Vector2 ret = p_pos;
+ ret /= tile_set->get_tile_size();
+
+ TileSet::TileShape tile_shape = tile_set->get_tile_shape();
+ TileSet::TileOffsetAxis tile_offset_axis = tile_set->get_tile_offset_axis();
+ TileSet::TileLayout tile_layout = tile_set->get_tile_layout();
- switch (half_offset) {
- case HALF_OFFSET_X: {
- if (int(floor(ret.y)) & 1) {
- ret.x -= 0.5;
+ // Divide by the overlapping ratio
+ double overlapping_ratio = 1.0;
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ overlapping_ratio = 0.5;
+ } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) {
+ overlapping_ratio = 0.75;
+ }
+ ret.y /= overlapping_ratio;
+ } else { // TILE_OFFSET_AXIS_VERTICAL
+ if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ overlapping_ratio = 0.5;
+ } else if (tile_shape == TileSet::TILE_SHAPE_HEXAGON) {
+ overlapping_ratio = 0.75;
+ }
+ ret.x /= overlapping_ratio;
+ }
+
+ // For each half-offset shape, we check if we are in the corner of the tile, and thus should correct the world position accordingly.
+ if (tile_shape == TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE || tile_shape == TileSet::TILE_SHAPE_HEXAGON || tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ // Technically, those 3 shapes are equivalent, as they are basically half-offset, but with different levels or overlap.
+ // square = no overlap, hexagon = 0.25 overlap, isometric = 0.5 overlap
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ // Smart floor of the position
+ Vector2 raw_pos = ret;
+ if (Math::posmod(Math::floor(ret.y), 2) ^ (tile_layout == TileSet::TILE_LAYOUT_STACKED_OFFSET)) {
+ ret = Vector2(Math::floor(ret.x + 0.5) - 0.5, Math::floor(ret.y));
+ } else {
+ ret = ret.floor();
}
- } break;
- case HALF_OFFSET_NEGATIVE_X: {
- if (int(floor(ret.y)) & 1) {
- ret.x += 0.5;
+
+ // Compute the tile offset, and if we might the output for a neighbour top tile
+ Vector2 in_tile_pos = raw_pos - ret;
+ bool in_top_left_triangle = (in_tile_pos - Vector2(0.5, 0.0)).cross(Vector2(-0.5, 1.0 / overlapping_ratio - 1)) <= 0;
+ bool in_top_right_triangle = (in_tile_pos - Vector2(0.5, 0.0)).cross(Vector2(0.5, 1.0 / overlapping_ratio - 1)) > 0;
+
+ switch (tile_layout) {
+ case TileSet::TILE_LAYOUT_STACKED:
+ ret = ret.floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 0 : -1, -1);
+ } else if (in_top_right_triangle) {
+ ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 1 : 0, -1);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STACKED_OFFSET:
+ ret = ret.floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? -1 : 0, -1);
+ } else if (in_top_right_triangle) {
+ ret += Vector2i(Math::posmod(Math::floor(ret.y), 2) ? 0 : 1, -1);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
+ ret = Vector2(ret.x - ret.y / 2, ret.y).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(0, -1);
+ } else if (in_top_right_triangle) {
+ ret += Vector2i(1, -1);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_DOWN:
+ ret = Vector2(ret.x * 2, ret.y / 2 - ret.x).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(-1, 0);
+ } else if (in_top_right_triangle) {
+ ret += Vector2i(1, -1);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
+ ret = Vector2(ret.x - ret.y / 2, ret.y / 2 + ret.x).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(0, -1);
+ } else if (in_top_right_triangle) {
+ ret += Vector2i(1, 0);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
+ ret = Vector2(ret.x + ret.y / 2, ret.y / 2 - ret.x).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(-1, 0);
+ } else if (in_top_right_triangle) {
+ ret += Vector2i(0, -1);
+ }
+ break;
}
- } break;
- case HALF_OFFSET_Y: {
- if (int(floor(ret.x)) & 1) {
- ret.y -= 0.5;
+ } else { // TILE_OFFSET_AXIS_VERTICAL
+ // Smart floor of the position
+ Vector2 raw_pos = ret;
+ if (Math::posmod(Math::floor(ret.x), 2) ^ (tile_layout == TileSet::TILE_LAYOUT_STACKED_OFFSET)) {
+ ret = Vector2(Math::floor(ret.x), Math::floor(ret.y + 0.5) - 0.5);
+ } else {
+ ret = ret.floor();
}
- } break;
- case HALF_OFFSET_NEGATIVE_Y: {
- if (int(floor(ret.x)) & 1) {
- ret.y += 0.5;
+
+ // Compute the tile offset, and if we might the output for a neighbour top tile
+ Vector2 in_tile_pos = raw_pos - ret;
+ bool in_top_left_triangle = (in_tile_pos - Vector2(0.0, 0.5)).cross(Vector2(1.0 / overlapping_ratio - 1, -0.5)) > 0;
+ bool in_bottom_left_triangle = (in_tile_pos - Vector2(0.0, 0.5)).cross(Vector2(1.0 / overlapping_ratio - 1, 0.5)) <= 0;
+
+ switch (tile_layout) {
+ case TileSet::TILE_LAYOUT_STACKED:
+ ret = ret.floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 0 : -1);
+ } else if (in_bottom_left_triangle) {
+ ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 1 : 0);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STACKED_OFFSET:
+ ret = ret.floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? -1 : 0);
+ } else if (in_bottom_left_triangle) {
+ ret += Vector2i(-1, Math::posmod(Math::floor(ret.x), 2) ? 0 : 1);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
+ ret = Vector2(ret.x / 2 - ret.y, ret.y * 2).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(0, -1);
+ } else if (in_bottom_left_triangle) {
+ ret += Vector2i(-1, 1);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_DOWN:
+ ret = Vector2(ret.x, ret.y - ret.x / 2).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(-1, 0);
+ } else if (in_bottom_left_triangle) {
+ ret += Vector2i(-1, 1);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
+ ret = Vector2(ret.x / 2 - ret.y, ret.y + ret.x / 2).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(0, -1);
+ } else if (in_bottom_left_triangle) {
+ ret += Vector2i(-1, 0);
+ }
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
+ ret = Vector2(ret.x / 2 + ret.y, ret.y - ret.x / 2).floor();
+ if (in_top_left_triangle) {
+ ret += Vector2i(-1, 0);
+ } else if (in_bottom_left_triangle) {
+ ret += Vector2i(0, 1);
+ }
+ break;
}
- } break;
- case HALF_OFFSET_DISABLED: {
- // Nothing to do.
+ }
+ } else {
+ ret = (ret + Vector2(0.00005, 0.00005)).floor();
+ }
+ return Vector2i(ret);
+}
+
+bool TileMap::is_existing_neighbor(TileSet::CellNeighbor p_cell_neighbor) const {
+ ERR_FAIL_COND_V(!tile_set.is_valid(), false);
+
+ TileSet::TileShape shape = tile_set->get_tile_shape();
+ if (shape == TileSet::TILE_SHAPE_SQUARE) {
+ return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER;
+
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
+ } else {
+ if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ return p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
+ } else {
+ return p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE ||
+ p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE;
}
}
-
- // Account for precision errors on the border (GH-23250).
- // 0.00005 is 5*CMP_EPSILON, results would start being unpredictable if
- // cell size is > 15,000, but we can hardly have more precision anyway with
- // floating point.
- ret += Vector2(0.00005, 0.00005);
- return ret.floor();
}
-void TileMap::set_y_sort_enabled(bool p_enable) {
- _clear_quadrants();
- use_y_sort = p_enable;
- RS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), use_y_sort);
- _recreate_quadrants();
- emit_signal("settings_changed");
-}
-
-bool TileMap::is_y_sort_enabled() const {
- return use_y_sort;
-}
+Vector2i TileMap::get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const {
+ ERR_FAIL_COND_V(!tile_set.is_valid(), p_coords);
+
+ TileSet::TileShape shape = tile_set->get_tile_shape();
+ if (shape == TileSet::TILE_SHAPE_SQUARE) {
+ switch (p_cell_neighbor) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
+ return p_coords + Vector2i(1, 0);
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
+ return p_coords + Vector2i(1, 1);
+ case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
+ return p_coords + Vector2i(0, 1);
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
+ return p_coords + Vector2i(-1, 1);
+ case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
+ return p_coords + Vector2i(-1, 0);
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
+ return p_coords + Vector2i(-1, -1);
+ case TileSet::CELL_NEIGHBOR_TOP_SIDE:
+ return p_coords + Vector2i(0, -1);
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
+ return p_coords + Vector2i(1, -1);
+ default:
+ ERR_FAIL_V(p_coords);
+ }
+ } else { // Half-offset shapes (square and hexagon)
+ switch (tile_set->get_tile_layout()) {
+ case TileSet::TILE_LAYOUT_STACKED: {
+ if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ bool is_offset = p_coords.y % 2;
+ if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
+ return p_coords + Vector2i(1, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(is_offset ? 1 : 0, 1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
+ return p_coords + Vector2i(0, 2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(is_offset ? 0 : -1, 1);
+ } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
+ return p_coords + Vector2i(-1, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(is_offset ? 0 : -1, -1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
+ return p_coords + Vector2i(0, -2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(is_offset ? 1 : 0, -1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ } else {
+ bool is_offset = p_coords.x % 2;
+
+ if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
+ return p_coords + Vector2i(0, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, is_offset ? 1 : 0);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
+ return p_coords + Vector2i(2, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, is_offset ? 0 : -1);
+ } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
+ return p_coords + Vector2i(0, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, is_offset ? 0 : -1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
+ return p_coords + Vector2i(-2, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, is_offset ? 1 : 0);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ }
+ } break;
+ case TileSet::TILE_LAYOUT_STACKED_OFFSET: {
+ if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ bool is_offset = p_coords.y % 2;
+
+ if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
+ return p_coords + Vector2i(1, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(is_offset ? 0 : 1, 1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
+ return p_coords + Vector2i(0, 2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(is_offset ? -1 : 0, 1);
+ } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
+ return p_coords + Vector2i(-1, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(is_offset ? -1 : 0, -1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
+ return p_coords + Vector2i(0, -2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(is_offset ? 0 : 1, -1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ } else {
+ bool is_offset = p_coords.x % 2;
+
+ if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
+ return p_coords + Vector2i(0, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, is_offset ? 0 : 1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
+ return p_coords + Vector2i(2, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, is_offset ? -1 : 0);
+ } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
+ return p_coords + Vector2i(0, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, is_offset ? -1 : 0);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
+ return p_coords + Vector2i(-2, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, is_offset ? 0 : 1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ }
+ } break;
+ case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
+ case TileSet::TILE_LAYOUT_STAIRS_DOWN: {
+ if ((tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_STAIRS_RIGHT) ^ (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
+ if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
+ return p_coords + Vector2i(1, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(0, 1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
+ return p_coords + Vector2i(-1, 2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 1);
+ } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
+ return p_coords + Vector2i(-1, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(0, -1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
+ return p_coords + Vector2i(1, -2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, -1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
-void TileMap::set_compatibility_mode(bool p_enable) {
- _clear_quadrants();
- compatibility_mode = p_enable;
- _recreate_quadrants();
- emit_signal("settings_changed");
-}
+ } else {
+ if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
+ return p_coords + Vector2i(0, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, 0);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
+ return p_coords + Vector2i(2, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, -1);
+ } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
+ return p_coords + Vector2i(0, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 0);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
+ return p_coords + Vector2i(-2, 1);
+
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ }
+ } else {
+ if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
+ return p_coords + Vector2i(2, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, 0);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
+ return p_coords + Vector2i(0, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 1);
+ } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
+ return p_coords + Vector2i(-2, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 0);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
+ return p_coords + Vector2i(0, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, -1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
-bool TileMap::is_compatibility_mode_enabled() const {
- return compatibility_mode;
-}
+ } else {
+ if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
+ return p_coords + Vector2i(-1, 2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(0, 1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
+ return p_coords + Vector2i(1, 0);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, -1);
+ } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
+ return p_coords + Vector2i(1, -2);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(0, -1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
+ return p_coords + Vector2i(-1, 0);
+
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ }
+ }
+ } break;
+ case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
+ case TileSet::TILE_LAYOUT_DIAMOND_DOWN: {
+ if ((tile_set->get_tile_layout() == TileSet::TILE_LAYOUT_DIAMOND_RIGHT) ^ (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
+ if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
+ return p_coords + Vector2i(1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(0, 1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
+ return p_coords + Vector2i(-1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 0);
+ } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
+ return p_coords + Vector2i(-1, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(0, -1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
+ return p_coords + Vector2i(1, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, 0);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
-void TileMap::set_centered_textures(bool p_enable) {
- _clear_quadrants();
- centered_textures = p_enable;
- _recreate_quadrants();
- emit_signal("settings_changed");
-}
+ } else {
+ if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
+ return p_coords + Vector2i(1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, 0);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
+ return p_coords + Vector2i(1, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(0, -1);
+ } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
+ return p_coords + Vector2i(-1, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 0);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
+ return p_coords + Vector2i(-1, 1);
+
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(0, 1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ }
+ } else {
+ if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
+ return p_coords + Vector2i(1, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, 0);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) {
+ return p_coords + Vector2i(1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(0, 1);
+ } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
+ return p_coords + Vector2i(-1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 0);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
+ return p_coords + Vector2i(-1, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(0, -1);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
-bool TileMap::is_centered_textures_enabled() const {
- return centered_textures;
+ } else {
+ if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
+ return p_coords + Vector2i(-1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) {
+ return p_coords + Vector2i(0, 1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_RIGHT_CORNER) {
+ return p_coords + Vector2i(1, 1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return p_coords + Vector2i(1, 0);
+ } else if ((shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_CORNER) ||
+ (shape != TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
+ return p_coords + Vector2i(1, -1);
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) {
+ return p_coords + Vector2i(0, -1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC && p_cell_neighbor == TileSet::CELL_NEIGHBOR_LEFT_CORNER) {
+ return p_coords + Vector2i(-1, -1);
+
+ } else if (p_cell_neighbor == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) {
+ return p_coords + Vector2i(-1, 0);
+ } else {
+ ERR_FAIL_V(p_coords);
+ }
+ }
+ }
+ } break;
+ default:
+ ERR_FAIL_V(p_coords);
+ }
+ }
}
TypedArray<Vector2i> TileMap::get_used_cells() const {
+ // Returns the cells used in the tilemap.
TypedArray<Vector2i> a;
a.resize(tile_map.size());
int i = 0;
- for (Map<PosKey, Cell>::Element *E = tile_map.front(); E; E = E->next()) {
+ for (Map<Vector2i, TileMapCell>::Element *E = tile_map.front(); E; E = E->next()) {
Vector2i p(E->key().x, E->key().y);
a[i++] = p;
}
@@ -1606,25 +1535,13 @@ TypedArray<Vector2i> TileMap::get_used_cells() const {
return a;
}
-TypedArray<Vector2i> TileMap::get_used_cells_by_index(int p_id) const {
- TypedArray<Vector2i> a;
- for (Map<PosKey, Cell>::Element *E = tile_map.front(); E; E = E->next()) {
- if (E->value().id == p_id) {
- Vector2i p(E->key().x, E->key().y);
- a.push_back(p);
- }
- }
-
- return a;
-}
-
Rect2 TileMap::get_used_rect() { // Not const because of cache
-
+ // Return the rect of the currently used area
if (used_size_cache_dirty) {
if (tile_map.size() > 0) {
used_size_cache = Rect2(tile_map.front()->key().x, tile_map.front()->key().y, 0, 0);
- for (Map<PosKey, Cell>::Element *E = tile_map.front(); E; E = E->next()) {
+ for (Map<Vector2i, TileMapCell>::Element *E = tile_map.front(); E; E = E->next()) {
used_size_cache.expand_to(Vector2(E->key().x, E->key().y));
}
@@ -1639,46 +1556,49 @@ Rect2 TileMap::get_used_rect() { // Not const because of cache
return used_size_cache;
}
-void TileMap::set_occluder_light_mask(int p_mask) {
- occluder_light_mask = p_mask;
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- for (Map<PosKey, Quadrant::Occluder>::Element *F = E->get().occluder_instances.front(); F; F = F->next()) {
- RenderingServer::get_singleton()->canvas_light_occluder_set_light_mask(F->get().id, occluder_light_mask);
- }
- }
-}
-
-int TileMap::get_occluder_light_mask() const {
- return occluder_light_mask;
-}
+// --- Override some methods of the CanvasItem class to pass the changes to the quadrants CanvasItems ---
void TileMap::set_light_mask(int p_light_mask) {
+ // Occlusion: set light mask.
CanvasItem::set_light_mask(p_light_mask);
- for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
+ for (Map<Vector2i, TileMapQuadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
for (List<RID>::Element *F = E->get().canvas_items.front(); F; F = F->next()) {
RenderingServer::get_singleton()->canvas_item_set_light_mask(F->get(), get_light_mask());
}
}
}
-void TileMap::set_clip_uv(bool p_enable) {
- if (clip_uv == p_enable) {
- return;
- }
+void TileMap::set_material(const Ref<Material> &p_material) {
+ // Set material for the whole tilemap.
+ CanvasItem::set_material(p_material);
- _clear_quadrants();
- clip_uv = p_enable;
- _recreate_quadrants();
+ // Update material for the whole tilemap.
+ for (Map<Vector2i, TileMapQuadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
+ TileMapQuadrant &q = E->get();
+ for (List<RID>::Element *F = q.canvas_items.front(); F; F = F->next()) {
+ RS::get_singleton()->canvas_item_set_use_parent_material(F->get(), get_use_parent_material() || get_material().is_valid());
+ }
+ }
}
-bool TileMap::get_clip_uv() const {
- return clip_uv;
+void TileMap::set_use_parent_material(bool p_use_parent_material) {
+ // Set use_parent_material for the whole tilemap.
+ CanvasItem::set_use_parent_material(p_use_parent_material);
+
+ // Update use_parent_material for the whole tilemap.
+ for (Map<Vector2i, TileMapQuadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
+ TileMapQuadrant &q = E->get();
+ for (List<RID>::Element *F = q.canvas_items.front(); F; F = F->next()) {
+ RS::get_singleton()->canvas_item_set_use_parent_material(F->get(), get_use_parent_material() || get_material().is_valid());
+ }
+ }
}
void TileMap::set_texture_filter(TextureFilter p_texture_filter) {
+ // Set a default texture filter for the whole tilemap
CanvasItem::set_texture_filter(p_texture_filter);
- for (Map<PosKey, Quadrant>::Element *F = quadrant_map.front(); F; F = F->next()) {
- Quadrant &q = F->get();
+ for (Map<Vector2i, TileMapQuadrant>::Element *F = quadrant_map.front(); F; F = F->next()) {
+ TileMapQuadrant &q = F->get();
for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) {
RenderingServer::get_singleton()->canvas_item_set_default_texture_filter(E->get(), RS::CanvasItemTextureFilter(p_texture_filter));
_make_quadrant_dirty(F);
@@ -1687,9 +1607,10 @@ void TileMap::set_texture_filter(TextureFilter p_texture_filter) {
}
void TileMap::set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) {
+ // Set a default texture repeat for the whole tilemap
CanvasItem::set_texture_repeat(p_texture_repeat);
- for (Map<PosKey, Quadrant>::Element *F = quadrant_map.front(); F; F = F->next()) {
- Quadrant &q = F->get();
+ for (Map<Vector2i, TileMapQuadrant>::Element *F = quadrant_map.front(); F; F = F->next()) {
+ TileMapQuadrant &q = F->get();
for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) {
RenderingServer::get_singleton()->canvas_item_set_default_texture_repeat(E->get(), RS::CanvasItemTextureRepeat(p_texture_repeat));
_make_quadrant_dirty(F);
@@ -1697,167 +1618,153 @@ void TileMap::set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) {
}
}
-TypedArray<String> TileMap::get_configuration_warnings() const {
- TypedArray<String> warnings = Node::get_configuration_warnings();
+TypedArray<Vector2i> TileMap::get_surrounding_tiles(Vector2i coords) {
+ if (!tile_set.is_valid()) {
+ return TypedArray<Vector2i>();
+ }
- if (use_parent && !collision_parent) {
- warnings.push_back(TTR("TileMap with Use Parent on needs a parent CollisionObject2D to give shapes to. Please use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."));
+ TypedArray<Vector2i> around;
+ TileSet::TileShape shape = tile_set->get_tile_shape();
+ if (shape == TileSet::TILE_SHAPE_SQUARE) {
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_SIDE));
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE));
+ } else {
+ if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE));
+ } else {
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_SIDE));
+ around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE));
+ }
}
- return warnings;
+ return around;
}
-void TileMap::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_tileset", "tileset"), &TileMap::set_tileset);
- ClassDB::bind_method(D_METHOD("get_tileset"), &TileMap::get_tileset);
-
- ClassDB::bind_method(D_METHOD("set_mode", "mode"), &TileMap::set_mode);
- ClassDB::bind_method(D_METHOD("get_mode"), &TileMap::get_mode);
+void TileMap::draw_cells_outline(Control *p_control, Set<Vector2i> p_cells, Color p_color, Transform2D p_transform) {
+ if (!tile_set.is_valid()) {
+ return;
+ }
- ClassDB::bind_method(D_METHOD("set_half_offset", "half_offset"), &TileMap::set_half_offset);
- ClassDB::bind_method(D_METHOD("get_half_offset"), &TileMap::get_half_offset);
+ // Create a set.
+ Vector2i tile_size = tile_set->get_tile_size();
+ Vector<Vector2> uvs;
- ClassDB::bind_method(D_METHOD("set_custom_transform", "custom_transform"), &TileMap::set_custom_transform);
- ClassDB::bind_method(D_METHOD("get_custom_transform"), &TileMap::get_custom_transform);
+ if (tile_set->get_tile_shape() == TileSet::TILE_SHAPE_SQUARE) {
+ uvs.append(Vector2(1.0, 0.0));
+ uvs.append(Vector2(1.0, 1.0));
+ uvs.append(Vector2(0.0, 1.0));
+ uvs.append(Vector2(0.0, 0.0));
+ } else {
+ float overlap = 0.0;
+ switch (tile_set->get_tile_shape()) {
+ case TileSet::TILE_SHAPE_ISOMETRIC:
+ overlap = 0.5;
+ break;
+ case TileSet::TILE_SHAPE_HEXAGON:
+ overlap = 0.25;
+ break;
+ case TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE:
+ overlap = 0.0;
+ break;
+ default:
+ break;
+ }
+ uvs.append(Vector2(1.0, overlap));
+ uvs.append(Vector2(1.0, 1.0 - overlap));
+ uvs.append(Vector2(0.5, 1.0));
+ uvs.append(Vector2(0.0, 1.0 - overlap));
+ uvs.append(Vector2(0.0, overlap));
+ uvs.append(Vector2(0.5, 0.0));
+ if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
+ for (int i = 0; i < uvs.size(); i++) {
+ uvs.write[i] = Vector2(uvs[i].y, uvs[i].x);
+ }
+ }
+ }
- ClassDB::bind_method(D_METHOD("set_cell_size", "size"), &TileMap::set_cell_size);
- ClassDB::bind_method(D_METHOD("get_cell_size"), &TileMap::get_cell_size);
+ for (Set<Vector2i>::Element *E = p_cells.front(); E; E = E->next()) {
+ Vector2 top_left = map_to_world(E->get()) - tile_size / 2;
+ TypedArray<Vector2i> surrounding_tiles = get_surrounding_tiles(E->get());
+ for (int i = 0; i < surrounding_tiles.size(); i++) {
+ if (!p_cells.has(surrounding_tiles[i])) {
+ p_control->draw_line(p_transform.xform(top_left + uvs[i] * tile_size), p_transform.xform(top_left + uvs[(i + 1) % uvs.size()] * tile_size), p_color);
+ }
+ }
+ }
+}
- ClassDB::bind_method(D_METHOD("_set_old_cell_size", "size"), &TileMap::_set_old_cell_size);
- ClassDB::bind_method(D_METHOD("_get_old_cell_size"), &TileMap::_get_old_cell_size);
+void TileMap::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_tileset", "tileset"), &TileMap::set_tileset);
+ ClassDB::bind_method(D_METHOD("get_tileset"), &TileMap::get_tileset);
ClassDB::bind_method(D_METHOD("set_quadrant_size", "size"), &TileMap::set_quadrant_size);
ClassDB::bind_method(D_METHOD("get_quadrant_size"), &TileMap::get_quadrant_size);
- ClassDB::bind_method(D_METHOD("set_tile_origin", "origin"), &TileMap::set_tile_origin);
- ClassDB::bind_method(D_METHOD("get_tile_origin"), &TileMap::get_tile_origin);
-
- ClassDB::bind_method(D_METHOD("set_clip_uv", "enable"), &TileMap::set_clip_uv);
- ClassDB::bind_method(D_METHOD("get_clip_uv"), &TileMap::get_clip_uv);
-
- ClassDB::bind_method(D_METHOD("set_y_sort_enabled", "enable"), &TileMap::set_y_sort_enabled);
- ClassDB::bind_method(D_METHOD("is_y_sort_enabled"), &TileMap::is_y_sort_enabled);
-
- ClassDB::bind_method(D_METHOD("set_compatibility_mode", "enable"), &TileMap::set_compatibility_mode);
- ClassDB::bind_method(D_METHOD("is_compatibility_mode_enabled"), &TileMap::is_compatibility_mode_enabled);
-
- ClassDB::bind_method(D_METHOD("set_centered_textures", "enable"), &TileMap::set_centered_textures);
- ClassDB::bind_method(D_METHOD("is_centered_textures_enabled"), &TileMap::is_centered_textures_enabled);
-
- ClassDB::bind_method(D_METHOD("set_collision_use_kinematic", "use_kinematic"), &TileMap::set_collision_use_kinematic);
- ClassDB::bind_method(D_METHOD("get_collision_use_kinematic"), &TileMap::get_collision_use_kinematic);
-
- ClassDB::bind_method(D_METHOD("set_collision_use_parent", "use_parent"), &TileMap::set_collision_use_parent);
- ClassDB::bind_method(D_METHOD("get_collision_use_parent"), &TileMap::get_collision_use_parent);
-
- ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &TileMap::set_collision_layer);
- ClassDB::bind_method(D_METHOD("get_collision_layer"), &TileMap::get_collision_layer);
-
- ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &TileMap::set_collision_mask);
- ClassDB::bind_method(D_METHOD("get_collision_mask"), &TileMap::get_collision_mask);
-
- ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &TileMap::set_collision_layer_bit);
- ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &TileMap::get_collision_layer_bit);
-
- ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &TileMap::set_collision_mask_bit);
- ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &TileMap::get_collision_mask_bit);
-
- ClassDB::bind_method(D_METHOD("set_collision_friction", "value"), &TileMap::set_collision_friction);
- ClassDB::bind_method(D_METHOD("get_collision_friction"), &TileMap::get_collision_friction);
-
- ClassDB::bind_method(D_METHOD("set_collision_bounce", "value"), &TileMap::set_collision_bounce);
- ClassDB::bind_method(D_METHOD("get_collision_bounce"), &TileMap::get_collision_bounce);
-
- ClassDB::bind_method(D_METHOD("set_bake_navigation", "bake_navigation"), &TileMap::set_bake_navigation);
- ClassDB::bind_method(D_METHOD("is_baking_navigation"), &TileMap::is_baking_navigation);
-
- ClassDB::bind_method(D_METHOD("set_occluder_light_mask", "mask"), &TileMap::set_occluder_light_mask);
- ClassDB::bind_method(D_METHOD("get_occluder_light_mask"), &TileMap::get_occluder_light_mask);
-
- ClassDB::bind_method(D_METHOD("set_cell", "x", "y", "tile", "flip_x", "flip_y", "transpose", "autotile_coord"), &TileMap::set_cell, DEFVAL(false), DEFVAL(false), DEFVAL(false), DEFVAL(Vector2()));
- ClassDB::bind_method(D_METHOD("set_cellv", "position", "tile", "flip_x", "flip_y", "transpose"), &TileMap::set_cellv, DEFVAL(false), DEFVAL(false), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("_set_celld", "position", "data"), &TileMap::_set_celld);
- ClassDB::bind_method(D_METHOD("get_cell", "x", "y"), &TileMap::get_cell);
- ClassDB::bind_method(D_METHOD("get_cellv", "position"), &TileMap::get_cellv);
- ClassDB::bind_method(D_METHOD("is_cell_x_flipped", "x", "y"), &TileMap::is_cell_x_flipped);
- ClassDB::bind_method(D_METHOD("is_cell_y_flipped", "x", "y"), &TileMap::is_cell_y_flipped);
- ClassDB::bind_method(D_METHOD("is_cell_transposed", "x", "y"), &TileMap::is_cell_transposed);
-
- ClassDB::bind_method(D_METHOD("get_cell_autotile_coord", "x", "y"), &TileMap::get_cell_autotile_coord);
+ ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMap::set_cell, DEFVAL(-1), DEFVAL(TileSetAtlasSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetAtlasSource::INVALID_TILE_ALTERNATIVE));
+ ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords"), &TileMap::get_cell_source_id);
+ ClassDB::bind_method(D_METHOD("get_cell_atlas_coords", "coords"), &TileMap::get_cell_atlas_coords);
+ ClassDB::bind_method(D_METHOD("get_cell_alternative_tile", "coords"), &TileMap::get_cell_alternative_tile);
ClassDB::bind_method(D_METHOD("fix_invalid_tiles"), &TileMap::fix_invalid_tiles);
+ ClassDB::bind_method(D_METHOD("get_surrounding_tiles", "coords"), &TileMap::get_surrounding_tiles);
ClassDB::bind_method(D_METHOD("clear"), &TileMap::clear);
ClassDB::bind_method(D_METHOD("get_used_cells"), &TileMap::get_used_cells);
- ClassDB::bind_method(D_METHOD("get_used_cells_by_index", "index"), &TileMap::get_used_cells_by_index);
ClassDB::bind_method(D_METHOD("get_used_rect"), &TileMap::get_used_rect);
- ClassDB::bind_method(D_METHOD("map_to_world", "map_position", "ignore_half_ofs"), &TileMap::map_to_world, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("map_to_world", "map_position"), &TileMap::map_to_world);
ClassDB::bind_method(D_METHOD("world_to_map", "world_position"), &TileMap::world_to_map);
- ClassDB::bind_method(D_METHOD("_clear_quadrants"), &TileMap::_clear_quadrants);
- ClassDB::bind_method(D_METHOD("update_dirty_quadrants"), &TileMap::update_dirty_quadrants);
+ ClassDB::bind_method(D_METHOD("get_neighbor_cell", "coords", "neighbor"), &TileMap::get_neighbor_cell);
- ClassDB::bind_method(D_METHOD("update_bitmask_area", "position"), &TileMap::update_bitmask_area);
- ClassDB::bind_method(D_METHOD("update_bitmask_region", "start", "end"), &TileMap::update_bitmask_region, DEFVAL(Vector2()), DEFVAL(Vector2()));
+ ClassDB::bind_method(D_METHOD("update_dirty_quadrants"), &TileMap::update_dirty_quadrants);
ClassDB::bind_method(D_METHOD("_set_tile_data"), &TileMap::_set_tile_data);
ClassDB::bind_method(D_METHOD("_get_tile_data"), &TileMap::_get_tile_data);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Square,Isometric,Custom"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tile_set", PROPERTY_HINT_RESOURCE_TYPE, "TileSet"), "set_tileset", "get_tileset");
-
- ADD_GROUP("Cell", "cell_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "cell_size", PROPERTY_HINT_RANGE, "1,8192,1"), "set_cell_size", "get_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_quadrant_size", PROPERTY_HINT_RANGE, "1,128,1"), "set_quadrant_size", "get_quadrant_size");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "cell_custom_transform"), "set_custom_transform", "get_custom_transform");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_half_offset", PROPERTY_HINT_ENUM, "Offset X,Offset Y,Disabled,Offset Negative X,Offset Negative Y"), "set_half_offset", "get_half_offset");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_tile_origin", PROPERTY_HINT_ENUM, "Top Left,Center,Bottom Left"), "set_tile_origin", "get_tile_origin");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cell_y_sort"), "set_y_sort_enabled", "is_y_sort_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "compatibility_mode"), "set_compatibility_mode", "is_compatibility_mode_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "centered_textures"), "set_centered_textures", "is_centered_textures_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cell_clip_uv"), "set_clip_uv", "get_clip_uv");
-
- ADD_GROUP("Collision", "collision_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_parent", PROPERTY_HINT_NONE, ""), "set_collision_use_parent", "get_collision_use_parent");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_kinematic", PROPERTY_HINT_NONE, ""), "set_collision_use_kinematic", "get_collision_use_kinematic");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_friction", "get_collision_friction");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_bounce", "get_collision_bounce");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask");
-
- ADD_GROUP("Occluder", "occluder_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "occluder_light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_occluder_light_mask", "get_occluder_light_mask");
-
- ADD_GROUP("Navigation", "");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_navigation"), "set_bake_navigation", "is_baking_navigation");
ADD_PROPERTY_DEFAULT("format", FORMAT_1);
- ADD_SIGNAL(MethodInfo("settings_changed"));
-
- BIND_CONSTANT(INVALID_CELL);
-
- BIND_ENUM_CONSTANT(MODE_SQUARE);
- BIND_ENUM_CONSTANT(MODE_ISOMETRIC);
- BIND_ENUM_CONSTANT(MODE_CUSTOM);
-
- BIND_ENUM_CONSTANT(HALF_OFFSET_X);
- BIND_ENUM_CONSTANT(HALF_OFFSET_Y);
- BIND_ENUM_CONSTANT(HALF_OFFSET_DISABLED);
- BIND_ENUM_CONSTANT(HALF_OFFSET_NEGATIVE_X);
- BIND_ENUM_CONSTANT(HALF_OFFSET_NEGATIVE_Y);
+ ADD_SIGNAL(MethodInfo("changed"));
+}
- BIND_ENUM_CONSTANT(TILE_ORIGIN_TOP_LEFT);
- BIND_ENUM_CONSTANT(TILE_ORIGIN_CENTER);
- BIND_ENUM_CONSTANT(TILE_ORIGIN_BOTTOM_LEFT);
+void TileMap::_tile_set_changed() {
+ emit_signal("changed");
+ _make_all_quadrants_dirty(true);
}
TileMap::TileMap() {
+ rect_cache_dirty = true;
+ used_size_cache_dirty = true;
+ pending_update = false;
+ quadrant_size = 16;
+ format = FORMAT_1; // Assume lowest possible format if none is present
+
set_notify_transform(true);
set_notify_local_transform(false);
}
TileMap::~TileMap() {
- clear();
+ if (tile_set.is_valid()) {
+ tile_set->disconnect("changed", callable_mp(this, &TileMap::_tile_set_changed));
+ }
+ _clear_quadrants();
}
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 9d27053fee..e9dbccbdb9 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -34,193 +34,194 @@
#include "core/templates/self_list.h"
#include "core/templates/vset.h"
#include "scene/2d/node_2d.h"
+#include "scene/gui/control.h"
#include "scene/resources/tile_set.h"
-class CollisionObject2D;
+class TileSetAtlasSource;
-class TileMap : public Node2D {
- GDCLASS(TileMap, Node2D);
-
-public:
- enum Mode {
- MODE_SQUARE,
- MODE_ISOMETRIC,
- MODE_CUSTOM
+union TileMapCell {
+ struct {
+ int32_t source_id : 16;
+ int16_t coord_x : 16;
+ int16_t coord_y : 16;
+ int32_t alternative_tile : 16;
};
- enum HalfOffset {
- HALF_OFFSET_X,
- HALF_OFFSET_Y,
- HALF_OFFSET_DISABLED,
- HALF_OFFSET_NEGATIVE_X,
- HALF_OFFSET_NEGATIVE_Y,
- };
+ uint64_t _u64t;
+ TileMapCell(int p_source_id = -1, Vector2i p_atlas_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
+ source_id = p_source_id;
+ set_atlas_coords(p_atlas_coords);
+ alternative_tile = p_alternative_tile;
+ }
+
+ Vector2i get_atlas_coords() const {
+ return Vector2i(coord_x, coord_y);
+ }
+
+ void set_atlas_coords(const Vector2i &r_coords) {
+ coord_x = r_coords.x;
+ coord_y = r_coords.y;
+ }
+
+ bool operator<(const TileMapCell &p_other) const {
+ if (source_id == p_other.source_id) {
+ if (coord_x == p_other.coord_x) {
+ if (coord_y == p_other.coord_y) {
+ return alternative_tile < p_other.alternative_tile;
+ } else {
+ return coord_y < p_other.coord_y;
+ }
+ } else {
+ return coord_x < p_other.coord_x;
+ }
+ } else {
+ return source_id < p_other.source_id;
+ }
+ }
- enum TileOrigin {
- TILE_ORIGIN_TOP_LEFT,
- TILE_ORIGIN_CENTER,
- TILE_ORIGIN_BOTTOM_LEFT
- };
+ bool operator!=(const TileMapCell &p_other) const {
+ return !(source_id == p_other.source_id && coord_x == p_other.coord_x && coord_y == p_other.coord_y && alternative_tile == p_other.alternative_tile);
+ }
+};
-private:
- enum DataFormat {
- FORMAT_1 = 0,
- FORMAT_2
+struct TileMapQuadrant {
+ struct CoordsWorldComparator {
+ _ALWAYS_INLINE_ bool operator()(const Vector2i &p_a, const Vector2i &p_b) const {
+ // We sort the cells by their world coords, as it is needed by rendering.
+ if (p_a.y == p_b.y) {
+ return p_a.x > p_b.x;
+ } else {
+ return p_a.y < p_b.y;
+ }
+ }
};
- Ref<TileSet> tile_set;
- Size2i cell_size = Size2(64, 64);
- int quadrant_size = 16;
- Mode mode = MODE_SQUARE;
- Transform2D custom_transform = Transform2D(64, 0, 0, 64, 0, 0);
- HalfOffset half_offset = HALF_OFFSET_DISABLED;
- bool use_parent = false;
- CollisionObject2D *collision_parent = nullptr;
- bool use_kinematic = false;
- bool bake_navigation = false;
-
- union PosKey {
- struct {
- int16_t x;
- int16_t y;
- };
- uint32_t key = 0;
-
- //using a more precise comparison so the regions can be sorted later
- bool operator<(const PosKey &p_k) const { return (y == p_k.y) ? x < p_k.x : y < p_k.y; }
-
- bool operator==(const PosKey &p_k) const { return (y == p_k.y && x == p_k.x); }
-
- PosKey to_quadrant(const int &p_quadrant_size) const {
- // rounding down, instead of simply rounding towards zero (truncating)
- return PosKey(
- x > 0 ? x / p_quadrant_size : (x - (p_quadrant_size - 1)) / p_quadrant_size,
- y > 0 ? y / p_quadrant_size : (y - (p_quadrant_size - 1)) / p_quadrant_size);
- }
+ // Dirty list element
+ SelfList<TileMapQuadrant> dirty_list_element;
+
+ // Quadrant coords.
+ Vector2i coords;
+
+ // TileMapCells
+ Set<Vector2i> cells;
+ // We need those two maps to sort by world position for rendering
+ // This is kind of workaround, it would be better to sort the cells directly in the "cells" set instead.
+ Map<Vector2i, Vector2i> map_to_world;
+ Map<Vector2i, Vector2i, CoordsWorldComparator> world_to_map;
+
+ // Debug.
+ RID debug_canvas_item;
+
+ // Rendering
+ List<RID> canvas_items;
+ List<RID> occluders;
+
+ // Physics.
+ List<RID> bodies;
+
+ // Navigation
+ Map<Vector2i, Vector<RID>> navigation_regions;
+
+ void operator=(const TileMapQuadrant &q) {
+ coords = q.coords;
+ debug_canvas_item = q.debug_canvas_item;
+ canvas_items = q.canvas_items;
+ occluders = q.occluders;
+ bodies = q.bodies;
+ navigation_regions = q.navigation_regions;
+ }
+
+ TileMapQuadrant(const TileMapQuadrant &q) :
+ dirty_list_element(this) {
+ coords = q.coords;
+ debug_canvas_item = q.debug_canvas_item;
+ canvas_items = q.canvas_items;
+ occluders = q.occluders;
+ bodies = q.bodies;
+ navigation_regions = q.navigation_regions;
+ }
+
+ TileMapQuadrant() :
+ dirty_list_element(this) {
+ }
+};
- PosKey(int16_t p_x, int16_t p_y) {
- x = p_x;
- y = p_y;
- }
- PosKey() {
- x = 0;
- y = 0;
- }
- };
+class TileMapPattern : public Object {
+ GDCLASS(TileMapPattern, Object);
- union Cell {
- struct {
- int32_t id : 24;
- bool flip_h : 1;
- bool flip_v : 1;
- bool transpose : 1;
- int16_t autotile_coord_x : 16;
- int16_t autotile_coord_y : 16;
- };
-
- uint64_t _u64t = 0;
- };
+ Vector2i size;
+ Map<Vector2i, TileMapCell> pattern;
- Map<PosKey, Cell> tile_map;
- List<PosKey> dirty_bitmask;
+protected:
+ static void _bind_methods();
- struct Quadrant {
- Vector2 pos;
- List<RID> canvas_items;
- RID body;
- uint32_t shape_owner_id = 0;
+public:
+ void set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile = 0);
+ bool has_cell(const Vector2i &p_coords) const;
+ void remove_cell(const Vector2i &p_coords, bool p_update_size = true);
+ int get_cell_source_id(const Vector2i &p_coords) const;
+ Vector2i get_cell_atlas_coords(const Vector2i &p_coords) const;
+ int get_cell_alternative_tile(const Vector2i &p_coords) const;
- SelfList<Quadrant> dirty_list;
+ TypedArray<Vector2i> get_used_cells() const;
- struct NavPoly {
- RID region;
- Transform2D xform;
- };
+ Vector2i get_size() const;
+ void set_size(const Vector2i &p_size);
+ bool is_empty() const;
- struct Occluder {
- RID id;
- Transform2D xform;
- };
+ void clear();
+};
- Map<PosKey, NavPoly> navpoly_ids;
- Map<PosKey, Occluder> occluder_instances;
+class TileMap : public Node2D {
+ GDCLASS(TileMap, Node2D);
- VSet<PosKey> cells;
+public:
+private:
+ friend class TileSetPlugin;
- void operator=(const Quadrant &q) {
- pos = q.pos;
- canvas_items = q.canvas_items;
- body = q.body;
- shape_owner_id = q.shape_owner_id;
- cells = q.cells;
- navpoly_ids = q.navpoly_ids;
- occluder_instances = q.occluder_instances;
- }
- Quadrant(const Quadrant &q) :
- dirty_list(this) {
- pos = q.pos;
- canvas_items = q.canvas_items;
- body = q.body;
- shape_owner_id = q.shape_owner_id;
- cells = q.cells;
- occluder_instances = q.occluder_instances;
- navpoly_ids = q.navpoly_ids;
- }
- Quadrant() :
- dirty_list(this) {}
+ enum DataFormat {
+ FORMAT_1 = 0,
+ FORMAT_2,
+ FORMAT_3
};
- Map<PosKey, Quadrant> quadrant_map;
+ Ref<TileSet> tile_set;
+ int quadrant_size;
+ Transform2D custom_transform;
+
+ // Map of cells
+ Map<Vector2i, TileMapCell> tile_map;
- SelfList<Quadrant>::List dirty_quadrant_list;
+ Vector2i _coords_to_quadrant_coords(const Vector2i &p_coords) const;
+
+ Map<Vector2i, TileMapQuadrant> quadrant_map;
+
+ SelfList<TileMapQuadrant>::List dirty_quadrant_list;
bool pending_update = false;
Rect2 rect_cache;
bool rect_cache_dirty = true;
Rect2 used_size_cache;
- bool used_size_cache_dirty = true;
- bool quadrant_order_dirty = false;
- bool use_y_sort = false;
- bool compatibility_mode = false;
- bool centered_textures = false;
- bool clip_uv = false;
- float fp_adjust = 0.00001;
- float friction = 1.0;
- float bounce = 0.0;
- uint32_t collision_layer = 1;
- uint32_t collision_mask = 1;
- mutable DataFormat format = FORMAT_1; // Assume lowest possible format if none is present
-
- TileOrigin tile_origin = TILE_ORIGIN_TOP_LEFT;
-
- int occluder_light_mask = 1;
-
- void _fix_cell_transform(Transform2D &xform, const Cell &p_cell, const Vector2 &p_offset, const Size2 &p_sc);
-
- void _add_shape(int &shape_idx, const Quadrant &p_q, const Ref<Shape2D> &p_shape, const TileSet::ShapeData &p_shape_data, const Transform2D &p_xform, const Vector2 &p_metadata);
-
- Map<PosKey, Quadrant>::Element *_create_quadrant(const PosKey &p_qk);
- void _erase_quadrant(Map<PosKey, Quadrant>::Element *Q);
- void _make_quadrant_dirty(Map<PosKey, Quadrant>::Element *Q, bool update = true);
+ bool used_size_cache_dirty;
+ mutable DataFormat format;
+
+ void _fix_cell_transform(Transform2D &xform, const TileMapCell &p_cell, const Vector2 &p_offset, const Size2 &p_sc);
+
+ Map<Vector2i, TileMapQuadrant>::Element *_create_quadrant(const Vector2i &p_qk);
+ void _erase_quadrant(Map<Vector2i, TileMapQuadrant>::Element *Q);
+ void _make_all_quadrants_dirty(bool p_update = true);
+ void _make_quadrant_dirty(Map<Vector2i, TileMapQuadrant>::Element *Q, bool p_update = true);
void _recreate_quadrants();
void _clear_quadrants();
- void _update_quadrant_space(const RID &p_space);
- void _update_quadrant_transform();
void _recompute_rect_cache();
void _update_all_items_material_state();
- _FORCE_INLINE_ void _update_item_material_state(const RID &p_canvas_item);
-
- _FORCE_INLINE_ int _get_quadrant_size() const;
void _set_tile_data(const Vector<int> &p_data);
Vector<int> _get_tile_data() const;
- void _set_old_cell_size(int p_size) { set_cell_size(Size2(p_size, p_size)); }
- int _get_old_cell_size() const { return cell_size.x; }
-
- _FORCE_INLINE_ Vector2 _map_to_world(int p_x, int p_y, bool p_ignore_ofs = false) const;
+ void _tile_set_changed();
protected:
bool _set(const StringName &p_name, const Variant &p_value);
@@ -230,9 +231,9 @@ protected:
void _notification(int p_what);
static void _bind_methods();
- virtual void _validate_property(PropertyInfo &property) const override;
-
public:
+ static Vector2i transform_coords_layout(Vector2i p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout);
+
enum {
INVALID_CELL = -1
};
@@ -244,117 +245,49 @@ public:
void set_tileset(const Ref<TileSet> &p_tileset);
Ref<TileSet> get_tileset() const;
- void set_cell_size(Size2 p_size);
- Size2 get_cell_size() const;
-
void set_quadrant_size(int p_size);
int get_quadrant_size() const;
- void set_cell(int p_x, int p_y, int p_tile, bool p_flip_x = false, bool p_flip_y = false, bool p_transpose = false, Vector2 p_autotile_coord = Vector2());
- int get_cell(int p_x, int p_y) const;
- bool is_cell_x_flipped(int p_x, int p_y) const;
- bool is_cell_y_flipped(int p_x, int p_y) const;
- bool is_cell_transposed(int p_x, int p_y) const;
- void set_cell_autotile_coord(int p_x, int p_y, const Vector2 &p_coord);
- Vector2 get_cell_autotile_coord(int p_x, int p_y) const;
+ void set_cell(const Vector2i &p_coords, int p_source_id = -1, const Vector2i p_atlas_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ int get_cell_source_id(const Vector2i &p_coords) const;
+ Vector2i get_cell_atlas_coords(const Vector2i &p_coords) const;
+ int get_cell_alternative_tile(const Vector2i &p_coords) const;
- void _set_celld(const Vector2 &p_pos, const Dictionary &p_data);
- void set_cellv(const Vector2 &p_pos, int p_tile, bool p_flip_x = false, bool p_flip_y = false, bool p_transpose = false);
- int get_cellv(const Vector2 &p_pos) const;
+ TileMapPattern *get_pattern(TypedArray<Vector2i> p_coords_array);
+ Vector2i map_pattern(Vector2i p_position_in_tilemap, Vector2i p_coords_in_pattern, const TileMapPattern *p_pattern);
+ void set_pattern(Vector2i p_position, const TileMapPattern *p_pattern);
- void make_bitmask_area_dirty(const Vector2 &p_pos);
- void update_bitmask_area(const Vector2 &p_pos);
- void update_bitmask_region(const Vector2 &p_start = Vector2(), const Vector2 &p_end = Vector2());
- void update_cell_bitmask(int p_x, int p_y);
- void update_dirty_bitmask();
+ // Not exposed to users
+ TileMapCell get_cell(const Vector2i &p_coords) const;
+ Map<Vector2i, TileMapQuadrant> &get_quadrant_map();
+ int get_effective_quadrant_size() const;
void update_dirty_quadrants();
- void set_collision_layer(uint32_t p_layer);
- uint32_t get_collision_layer() const;
-
- void set_collision_mask(uint32_t p_mask);
- uint32_t get_collision_mask() const;
-
- void set_collision_layer_bit(int p_bit, bool p_value);
- bool get_collision_layer_bit(int p_bit) const;
-
- void set_collision_mask_bit(int p_bit, bool p_value);
- bool get_collision_mask_bit(int p_bit) const;
-
- void set_collision_use_kinematic(bool p_use_kinematic);
- bool get_collision_use_kinematic() const;
-
- void set_collision_use_parent(bool p_use_parent);
- bool get_collision_use_parent() const;
-
- void set_collision_friction(float p_friction);
- float get_collision_friction() const;
-
- void set_collision_bounce(float p_bounce);
- float get_collision_bounce() const;
-
- void set_bake_navigation(bool p_bake_navigation);
- bool is_baking_navigation();
-
- void set_mode(Mode p_mode);
- Mode get_mode() const;
+ Vector2 map_to_world(const Vector2i &p_pos) const;
+ Vector2i world_to_map(const Vector2 &p_pos) const;
- void set_half_offset(HalfOffset p_half_offset);
- HalfOffset get_half_offset() const;
-
- void set_tile_origin(TileOrigin p_tile_origin);
- TileOrigin get_tile_origin() const;
-
- void set_custom_transform(const Transform2D &p_xform);
- Transform2D get_custom_transform() const;
-
- Transform2D get_cell_transform() const;
- Vector2 get_cell_draw_offset() const;
-
- Vector2 map_to_world(const Vector2 &p_pos, bool p_ignore_ofs = false) const;
- Vector2 world_to_map(const Vector2 &p_pos) const;
-
- void set_y_sort_enabled(bool p_enable);
- bool is_y_sort_enabled() const;
-
- void set_compatibility_mode(bool p_enable);
- bool is_compatibility_mode_enabled() const;
-
- void set_centered_textures(bool p_enable);
- bool is_centered_textures_enabled() const;
+ bool is_existing_neighbor(TileSet::CellNeighbor p_cell_neighbor) const;
+ Vector2i get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const;
TypedArray<Vector2i> get_used_cells() const;
- TypedArray<Vector2i> get_used_cells_by_index(int p_index) const;
Rect2 get_used_rect(); // Not const because of cache
- void set_occluder_light_mask(int p_mask);
- int get_occluder_light_mask() const;
-
+ // Override some methods of the CanvasItem class to pass the changes to the quadrants CanvasItems
virtual void set_light_mask(int p_light_mask) override;
-
virtual void set_material(const Ref<Material> &p_material) override;
-
virtual void set_use_parent_material(bool p_use_parent_material) override;
-
- void set_clip_uv(bool p_enable);
- bool get_clip_uv() const;
-
- TypedArray<String> get_configuration_warnings() const override;
-
virtual void set_texture_filter(CanvasItem::TextureFilter p_texture_filter) override;
-
virtual void set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) override;
void fix_invalid_tiles();
void clear();
+ // Helpers
+ TypedArray<Vector2i> get_surrounding_tiles(Vector2i coords);
+ void draw_cells_outline(Control *p_control, Set<Vector2i> p_cells, Color p_color, Transform2D p_transform = Transform2D());
+
TileMap();
~TileMap();
};
-
-VARIANT_ENUM_CAST(TileMap::Mode);
-VARIANT_ENUM_CAST(TileMap::HalfOffset);
-VARIANT_ENUM_CAST(TileMap::TileOrigin);
-
#endif // TILE_MAP_H
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp
index 688509a979..914b3ad816 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/collision_object_3d.cpp
@@ -31,12 +31,27 @@
#include "collision_object_3d.h"
#include "core/config/engine.h"
-#include "mesh_instance_3d.h"
#include "scene/scene_string_names.h"
#include "servers/physics_server_3d.h"
void CollisionObject3D::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ if (_are_collision_shapes_visible()) {
+ debug_shape_old_transform = get_global_transform();
+ for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
+ debug_shapes_to_update.insert(E->key());
+ }
+ _update_debug_shapes();
+ }
+ } break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ if (debug_shapes_count > 0) {
+ _clear_debug_shapes();
+ }
+ } break;
+
case NOTIFICATION_ENTER_WORLD: {
if (area) {
PhysicsServer3D::get_singleton()->area_set_transform(rid, get_global_transform());
@@ -62,6 +77,8 @@ void CollisionObject3D::_notification(int p_what) {
PhysicsServer3D::get_singleton()->body_set_state(rid, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
}
+ _on_transform_changed();
+
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
_update_pickable();
@@ -75,11 +92,6 @@ void CollisionObject3D::_notification(int p_what) {
}
} break;
- case NOTIFICATION_PREDELETE: {
- if (debug_shape_count > 0) {
- _clear_debug_shapes();
- }
- } break;
}
}
@@ -175,6 +187,33 @@ void CollisionObject3D::_update_pickable() {
}
}
+bool CollisionObject3D::_are_collision_shapes_visible() {
+ return is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !Engine::get_singleton()->is_editor_hint();
+}
+
+void CollisionObject3D::_update_shape_data(uint32_t p_owner) {
+ if (_are_collision_shapes_visible()) {
+ if (debug_shapes_to_update.is_empty()) {
+ callable_mp(this, &CollisionObject3D::_update_debug_shapes).call_deferred({}, 0);
+ }
+ debug_shapes_to_update.insert(p_owner);
+ }
+}
+
+void CollisionObject3D::_shape_changed(const Ref<Shape3D> &p_shape) {
+ for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
+ ShapeData &shapedata = E->get();
+ ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw();
+ for (int i = 0; i < shapedata.shapes.size(); i++) {
+ ShapeData::ShapeBase &s = shapes[i];
+ if (s.shape == p_shape && s.debug_shape.is_valid()) {
+ Ref<Mesh> mesh = s.shape->get_debug_mesh();
+ RS::get_singleton()->instance_set_base(s.debug_shape, mesh->get_rid());
+ }
+ }
+ }
+}
+
void CollisionObject3D::_update_debug_shapes() {
for (Set<uint32_t>::Element *shapedata_idx = debug_shapes_to_update.front(); shapedata_idx; shapedata_idx = shapedata_idx->next()) {
if (shapes.has(shapedata_idx->get())) {
@@ -182,23 +221,30 @@ void CollisionObject3D::_update_debug_shapes() {
ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw();
for (int i = 0; i < shapedata.shapes.size(); i++) {
ShapeData::ShapeBase &s = shapes[i];
- if (s.debug_shape) {
- s.debug_shape->queue_delete();
- s.debug_shape = nullptr;
- --debug_shape_count;
- }
if (s.shape.is_null() || shapedata.disabled) {
+ if (s.debug_shape.is_valid()) {
+ RS::get_singleton()->free(s.debug_shape);
+ s.debug_shape = RID();
+ --debug_shapes_count;
+ }
continue;
}
+ if (s.debug_shape.is_null()) {
+ s.debug_shape = RS::get_singleton()->instance_create();
+ RS::get_singleton()->instance_set_scenario(s.debug_shape, get_world_3d()->get_scenario());
+
+ if (!s.shape->is_connected("changed", callable_mp(this, &CollisionObject3D::_shape_changed))) {
+ s.shape->connect("changed", callable_mp(this, &CollisionObject3D::_shape_changed),
+ varray(s.shape), CONNECT_DEFERRED);
+ }
+
+ ++debug_shapes_count;
+ }
+
Ref<Mesh> mesh = s.shape->get_debug_mesh();
- MeshInstance3D *mi = memnew(MeshInstance3D);
- mi->set_transform(shapedata.xform);
- mi->set_mesh(mesh);
- add_child(mi);
- mi->force_update_transform();
- s.debug_shape = mi;
- ++debug_shape_count;
+ RS::get_singleton()->instance_set_base(s.debug_shape, mesh->get_rid());
+ RS::get_singleton()->instance_set_transform(s.debug_shape, get_global_transform() * shapedata.xform);
}
}
}
@@ -211,23 +257,28 @@ void CollisionObject3D::_clear_debug_shapes() {
ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw();
for (int i = 0; i < shapedata.shapes.size(); i++) {
ShapeData::ShapeBase &s = shapes[i];
- if (s.debug_shape) {
- s.debug_shape->queue_delete();
- s.debug_shape = nullptr;
- --debug_shape_count;
+ if (s.debug_shape.is_valid()) {
+ RS::get_singleton()->free(s.debug_shape);
+ s.debug_shape = RID();
+ if (s.shape.is_valid() && s.shape->is_connected("changed", callable_mp(this, &CollisionObject3D::_update_shape_data))) {
+ s.shape->disconnect("changed", callable_mp(this, &CollisionObject3D::_update_shape_data));
+ }
}
}
}
-
- debug_shape_count = 0;
+ debug_shapes_count = 0;
}
-void CollisionObject3D::_update_shape_data(uint32_t p_owner) {
- if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !Engine::get_singleton()->is_editor_hint()) {
- if (debug_shapes_to_update.is_empty()) {
- call_deferred("_update_debug_shapes");
+void CollisionObject3D::_on_transform_changed() {
+ if (debug_shapes_count > 0 && !debug_shape_old_transform.is_equal_approx(get_global_transform())) {
+ debug_shape_old_transform = get_global_transform();
+ for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
+ ShapeData &shapedata = E->get();
+ const ShapeData::ShapeBase *shapes = shapedata.shapes.ptr();
+ for (int i = 0; i < shapedata.shapes.size(); i++) {
+ RS::get_singleton()->instance_set_transform(shapes[i].debug_shape, debug_shape_old_transform * shapedata.xform);
+ }
}
- debug_shapes_to_update.insert(p_owner);
}
}
@@ -270,8 +321,6 @@ void CollisionObject3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject3D::shape_owner_clear_shapes);
ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject3D::shape_find_owner);
- ClassDB::bind_method(D_METHOD("_update_debug_shapes"), &CollisionObject3D::_update_debug_shapes);
-
BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
@@ -316,7 +365,11 @@ void CollisionObject3D::shape_owner_set_disabled(uint32_t p_owner, bool p_disabl
ERR_FAIL_COND(!shapes.has(p_owner));
ShapeData &sd = shapes[p_owner];
+ if (sd.disabled == p_disabled) {
+ return;
+ }
sd.disabled = p_disabled;
+
for (int i = 0; i < sd.shapes.size(); i++) {
if (area) {
PhysicsServer3D::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled);
@@ -421,7 +474,7 @@ void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape)
ERR_FAIL_COND(!shapes.has(p_owner));
ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size());
- const ShapeData::ShapeBase &s = shapes[p_owner].shapes[p_shape];
+ ShapeData::ShapeBase &s = shapes[p_owner].shapes.write[p_shape];
int index_to_remove = s.index;
if (area) {
@@ -430,8 +483,12 @@ void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape)
PhysicsServer3D::get_singleton()->body_remove_shape(rid, index_to_remove);
}
- if (s.debug_shape) {
- s.debug_shape->queue_delete();
+ if (s.debug_shape.is_valid()) {
+ RS::get_singleton()->free(s.debug_shape);
+ if (s.shape.is_valid() && s.shape->is_connected("changed", callable_mp(this, &CollisionObject3D::_shape_changed))) {
+ s.shape->disconnect("changed", callable_mp(this, &CollisionObject3D::_shape_changed));
+ }
+ --debug_shapes_count;
}
shapes[p_owner].shapes.remove(p_shape);
diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h
index e3901979d3..7ff3c5efde 100644
--- a/scene/3d/collision_object_3d.h
+++ b/scene/3d/collision_object_3d.h
@@ -48,7 +48,7 @@ class CollisionObject3D : public Node3D {
Object *owner = nullptr;
Transform xform;
struct ShapeBase {
- Node *debug_shape = nullptr;
+ RID debug_shape;
Ref<Shape3D> shape;
int index = 0;
};
@@ -65,25 +65,30 @@ class CollisionObject3D : public Node3D {
bool ray_pickable = true;
Set<uint32_t> debug_shapes_to_update;
- int debug_shape_count = 0;
+ int debug_shapes_count = 0;
+ Transform debug_shape_old_transform;
void _update_pickable();
+ bool _are_collision_shapes_visible();
void _update_shape_data(uint32_t p_owner);
+ void _shape_changed(const Ref<Shape3D> &p_shape);
+ void _update_debug_shapes();
+ void _clear_debug_shapes();
protected:
CollisionObject3D(RID p_rid, bool p_area);
void _notification(int p_what);
static void _bind_methods();
+
+ void _on_transform_changed();
+
friend class Viewport;
virtual void _input_event(Node *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape);
virtual void _mouse_enter();
virtual void _mouse_exit();
- void _update_debug_shapes();
- void _clear_debug_shapes();
-
public:
void set_collision_layer(uint32_t p_layer);
uint32_t get_collision_layer() const;
diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp
index bec87914c0..70d9cebb83 100644
--- a/scene/3d/collision_shape_3d.cpp
+++ b/scene/3d/collision_shape_3d.cpp
@@ -161,12 +161,10 @@ void CollisionShape3D::set_shape(const Ref<Shape3D> &p_shape) {
}
if (!shape.is_null()) {
shape->unregister_owner(this);
- shape->disconnect("changed", callable_mp(this, &CollisionShape3D::_shape_changed));
}
shape = p_shape;
if (!shape.is_null()) {
shape->register_owner(this);
- shape->connect("changed", callable_mp(this, &CollisionShape3D::_shape_changed));
}
update_gizmo();
if (parent) {
@@ -176,8 +174,9 @@ void CollisionShape3D::set_shape(const Ref<Shape3D> &p_shape) {
}
}
- if (is_inside_tree()) {
- _shape_changed();
+ if (is_inside_tree() && parent) {
+ // If this is a heightfield shape our center may have changed
+ _update_in_shape_owner(true);
}
update_configuration_warnings();
}
@@ -209,10 +208,3 @@ CollisionShape3D::~CollisionShape3D() {
}
//RenderingServer::get_singleton()->free(indicator);
}
-
-void CollisionShape3D::_shape_changed() {
- // If this is a heightfield shape our center may have changed
- if (parent) {
- _update_in_shape_owner(true);
- }
-}
diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/collision_shape_3d.h
index 56a4ae3039..f69c1e38eb 100644
--- a/scene/3d/collision_shape_3d.h
+++ b/scene/3d/collision_shape_3d.h
@@ -47,8 +47,6 @@ class CollisionShape3D : public Node3D {
bool disabled = false;
protected:
- void _shape_changed();
-
void _update_in_shape_owner(bool p_xform_only = false);
protected:
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
index 4d7fc29f15..6505fb1ee8 100644
--- a/scene/3d/gi_probe.cpp
+++ b/scene/3d/gi_probe.cpp
@@ -454,7 +454,7 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
mmi->set_multimesh(baker.create_debug_multimesh());
add_child(mmi);
#ifdef TOOLS_ENABLED
- if (get_tree()->get_edited_scene_root() == this) {
+ if (is_inside_tree() && get_tree()->get_edited_scene_root() == this) {
mmi->set_owner(this);
} else {
mmi->set_owner(get_owner());
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index ab85338f36..50044ddc67 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -605,14 +605,15 @@ void GPUParticles3D::_bind_methods() {
BIND_CONSTANT(MAX_DRAW_PASSES);
- BIND_CONSTANT(TRANSFORM_ALIGN_DISABLED);
- BIND_CONSTANT(TRANSFORM_ALIGN_Z_BILLBOARD);
- BIND_CONSTANT(TRANSFORM_ALIGN_Y_TO_VELOCITY);
- BIND_CONSTANT(TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY);
+ BIND_ENUM_CONSTANT(TRANSFORM_ALIGN_DISABLED);
+ BIND_ENUM_CONSTANT(TRANSFORM_ALIGN_Z_BILLBOARD);
+ BIND_ENUM_CONSTANT(TRANSFORM_ALIGN_Y_TO_VELOCITY);
+ BIND_ENUM_CONSTANT(TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY);
}
GPUParticles3D::GPUParticles3D() {
particles = RS::get_singleton()->particles_create();
+ RS::get_singleton()->particles_set_mode(particles, RS::PARTICLES_MODE_3D);
set_base(particles);
one_shot = false; // Needed so that set_emitting doesn't access uninitialized values
set_emitting(true);
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index 27d5487a1a..c495f68890 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -427,7 +427,7 @@ void MeshInstance3D::create_debug_tangents() {
add_child(mi);
#ifdef TOOLS_ENABLED
- if (this == get_tree()->get_edited_scene_root()) {
+ if (is_inside_tree() && this == get_tree()->get_edited_scene_root()) {
mi->set_owner(this);
} else {
mi->set_owner(get_owner());
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 93d3e946fd..dd1a797568 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -292,6 +292,7 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
get_script_instance()->call("_integrate_forces", state);
}
set_ignore_transform_notification(false);
+ _on_transform_changed();
if (contact_monitor) {
contact_monitor->locked = true;
@@ -1985,6 +1986,7 @@ void PhysicalBone3D::_direct_state_changed(Object *p_state) {
set_ignore_transform_notification(true);
set_global_transform(global_transform);
set_ignore_transform_notification(false);
+ _on_transform_changed();
// Update skeleton
if (parent_skeleton) {
diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp
index 95638ce514..475f8c07fd 100644
--- a/scene/3d/ray_cast_3d.cpp
+++ b/scene/3d/ray_cast_3d.cpp
@@ -428,7 +428,7 @@ void RayCast3D::_update_debug_shape_material(bool p_check_collision) {
color = get_tree()->get_debug_collisions_color();
}
- if (p_check_collision) {
+ if (p_check_collision && collided) {
if ((color.get_h() < 0.055 || color.get_h() > 0.945) && color.get_s() > 0.5 && color.get_v() > 0.5) {
// If base color is already quite reddish, highlight collision with green color
color = Color(0.0, 1.0, 0.0, color.a);
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index ebbb8985c9..59233708f6 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -237,53 +237,57 @@ void Skeleton3D::_notification(int p_what) {
for (int i = 0; i < len; i++) {
Bone &b = bonesptr[order[i]];
- if (b.global_pose_override_amount >= 0.999) {
- b.pose_global = b.global_pose_override;
- } else {
- if (b.disable_rest) {
- if (b.enabled) {
- Transform pose = b.pose;
- if (b.custom_pose_enable) {
- pose = b.custom_pose * pose;
- }
- if (b.parent >= 0) {
- b.pose_global = bonesptr[b.parent].pose_global * pose;
- } else {
- b.pose_global = pose;
- }
+ if (b.disable_rest) {
+ if (b.enabled) {
+ Transform pose = b.pose;
+ if (b.custom_pose_enable) {
+ pose = b.custom_pose * pose;
+ }
+ if (b.parent >= 0) {
+ b.pose_global = bonesptr[b.parent].pose_global * pose;
+ b.pose_global_no_override = bonesptr[b.parent].pose_global * pose;
} else {
- if (b.parent >= 0) {
- b.pose_global = bonesptr[b.parent].pose_global;
- } else {
- b.pose_global = Transform();
- }
+ b.pose_global = pose;
+ b.pose_global_no_override = pose;
}
-
} else {
- if (b.enabled) {
- Transform pose = b.pose;
- if (b.custom_pose_enable) {
- pose = b.custom_pose * pose;
- }
- if (b.parent >= 0) {
- b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose);
- } else {
- b.pose_global = b.rest * pose;
- }
+ if (b.parent >= 0) {
+ b.pose_global = bonesptr[b.parent].pose_global;
+ b.pose_global_no_override = bonesptr[b.parent].pose_global;
} else {
- if (b.parent >= 0) {
- b.pose_global = bonesptr[b.parent].pose_global * b.rest;
- } else {
- b.pose_global = b.rest;
- }
+ b.pose_global = Transform();
+ b.pose_global_no_override = Transform();
}
}
- if (b.global_pose_override_amount >= CMP_EPSILON) {
- b.pose_global = b.pose_global.interpolate_with(b.global_pose_override, b.global_pose_override_amount);
+ } else {
+ if (b.enabled) {
+ Transform pose = b.pose;
+ if (b.custom_pose_enable) {
+ pose = b.custom_pose * pose;
+ }
+ if (b.parent >= 0) {
+ b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose);
+ b.pose_global_no_override = bonesptr[b.parent].pose_global * (b.rest * pose);
+ } else {
+ b.pose_global = b.rest * pose;
+ b.pose_global_no_override = b.rest * pose;
+ }
+ } else {
+ if (b.parent >= 0) {
+ b.pose_global = bonesptr[b.parent].pose_global * b.rest;
+ b.pose_global_no_override = bonesptr[b.parent].pose_global * b.rest;
+ } else {
+ b.pose_global = b.rest;
+ b.pose_global_no_override = b.rest;
+ }
}
}
+ if (b.global_pose_override_amount >= CMP_EPSILON) {
+ b.pose_global = b.pose_global.interpolate_with(b.global_pose_override, b.global_pose_override_amount);
+ }
+
if (b.global_pose_override_reset) {
b.global_pose_override_amount = 0.0;
}
@@ -408,6 +412,14 @@ Transform Skeleton3D::get_bone_global_pose(int p_bone) const {
return bones[p_bone].pose_global;
}
+Transform Skeleton3D::get_bone_global_pose_no_override(int p_bone) const {
+ ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform());
+ if (dirty) {
+ const_cast<Skeleton3D *>(this)->notification(NOTIFICATION_UPDATE_SKELETON);
+ }
+ return bones[p_bone].pose_global_no_override;
+}
+
// skeleton creation api
void Skeleton3D::add_bone(const String &p_name) {
ERR_FAIL_COND(p_name == "" || p_name.find(":") != -1 || p_name.find("/") != -1);
@@ -912,6 +924,7 @@ void Skeleton3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_bones_global_pose_override"), &Skeleton3D::clear_bones_global_pose_override);
ClassDB::bind_method(D_METHOD("set_bone_global_pose_override", "bone_idx", "pose", "amount", "persistent"), &Skeleton3D::set_bone_global_pose_override, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_bone_global_pose", "bone_idx"), &Skeleton3D::get_bone_global_pose);
+ ClassDB::bind_method(D_METHOD("get_bone_global_pose_no_override", "bone_idx"), &Skeleton3D::get_bone_global_pose_no_override);
ClassDB::bind_method(D_METHOD("get_bone_custom_pose", "bone_idx"), &Skeleton3D::get_bone_custom_pose);
ClassDB::bind_method(D_METHOD("set_bone_custom_pose", "bone_idx", "custom_pose"), &Skeleton3D::set_bone_custom_pose);
diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h
index 2941ac2c45..508cd7c329 100644
--- a/scene/3d/skeleton_3d.h
+++ b/scene/3d/skeleton_3d.h
@@ -83,6 +83,7 @@ private:
Transform pose;
Transform pose_global;
+ Transform pose_global_no_override;
bool custom_pose_enable = false;
Transform custom_pose;
@@ -160,6 +161,7 @@ public:
void set_bone_rest(int p_bone, const Transform &p_rest);
Transform get_bone_rest(int p_bone) const;
Transform get_bone_global_pose(int p_bone) const;
+ Transform get_bone_global_pose_no_override(int p_bone) const;
void clear_bones_global_pose_override();
void set_bone_global_pose_override(int p_bone, const Transform &p_pose, float p_amount, bool p_persistent = false);
diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp
index 898f94ccc1..bd1c202205 100644
--- a/scene/3d/skeleton_ik_3d.cpp
+++ b/scene/3d/skeleton_ik_3d.cpp
@@ -246,7 +246,7 @@ void FabrikInverseKinematic::make_goal(Task *p_task, const Transform &p_inverse_
p_task->end_effectors.write[0].goal_transform = p_inverse_transf * p_task->goal_global_transform;
} else {
// End effector in local transform
- const Transform end_effector_pose(p_task->skeleton->get_bone_global_pose(p_task->end_effectors[0].tip_bone));
+ const Transform end_effector_pose(p_task->skeleton->get_bone_global_pose_no_override(p_task->end_effectors[0].tip_bone));
// Update the end_effector (local transform) by blending with current pose
p_task->end_effectors.write[0].goal_transform = end_effector_pose.interpolate_with(p_inverse_transf * p_task->goal_global_transform, blending_delta);
@@ -270,18 +270,7 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove
return; // Skip solving
}
- p_task->skeleton->set_bone_global_pose_override(p_task->chain.chain_root.bone, Transform(), 0.0, true);
-
- if (p_task->chain.middle_chain_item) {
- p_task->skeleton->set_bone_global_pose_override(p_task->chain.middle_chain_item->bone, Transform(), 0.0, true);
- }
-
- for (int i = 0; i < p_task->chain.tips.size(); i += 1) {
- p_task->skeleton->set_bone_global_pose_override(p_task->chain.tips[i].chain_item->bone, Transform(), 0.0, true);
- }
-
- // Update the transforms to their global poses
- // (Needed to sync IK with animation)
+ // Update the initial root transform so its synced with any animation changes
_update_chain(p_task->skeleton, &p_task->chain.chain_root);
make_goal(p_task, p_task->skeleton->get_global_transform().affine_inverse(), blending_delta);
@@ -298,48 +287,22 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove
Transform new_bone_pose(ci->initial_transform);
new_bone_pose.origin = ci->current_pos;
- // The root bone needs to be rotated differently so it isn't frozen in place.
- if (ci == &p_task->chain.chain_root && !ci->children.is_empty()) {
- new_bone_pose = new_bone_pose.looking_at(ci->children[0].current_pos);
- const Vector3 bone_rest_dir = p_task->skeleton->get_bone_rest(ci->children[0].bone).origin.normalized().abs();
- const Vector3 bone_rest_dir_abs = bone_rest_dir.abs();
- if (bone_rest_dir_abs.x > bone_rest_dir_abs.y && bone_rest_dir_abs.x > bone_rest_dir_abs.z) {
- if (bone_rest_dir.x < 0) {
- new_bone_pose.basis.rotate_local(Vector3(0, 1, 0), -Math_PI / 2.0f);
- } else {
- new_bone_pose.basis.rotate_local(Vector3(0, 1, 0), Math_PI / 2.0f);
- }
- } else if (bone_rest_dir_abs.y > bone_rest_dir_abs.x && bone_rest_dir_abs.y > bone_rest_dir_abs.z) {
- if (bone_rest_dir.y < 0) {
- new_bone_pose.basis.rotate_local(Vector3(1, 0, 0), Math_PI / 2.0f);
- } else {
- new_bone_pose.basis.rotate_local(Vector3(1, 0, 0), -Math_PI / 2.0f);
- }
- } else {
- if (bone_rest_dir.z < 0) {
- // Do nothing!
- } else {
- new_bone_pose.basis.rotate_local(Vector3(0, 0, 1), Math_PI);
- }
- }
- } else {
- if (!ci->children.is_empty()) {
- /// Rotate basis
- const Vector3 initial_ori((ci->children[0].initial_transform.origin - ci->initial_transform.origin).normalized());
- const Vector3 rot_axis(initial_ori.cross(ci->current_ori).normalized());
+ if (!ci->children.is_empty()) {
+ /// Rotate basis
+ const Vector3 initial_ori((ci->children[0].initial_transform.origin - ci->initial_transform.origin).normalized());
+ const Vector3 rot_axis(initial_ori.cross(ci->current_ori).normalized());
- if (rot_axis[0] != 0 && rot_axis[1] != 0 && rot_axis[2] != 0) {
- const real_t rot_angle(Math::acos(CLAMP(initial_ori.dot(ci->current_ori), -1, 1)));
- new_bone_pose.basis.rotate(rot_axis, rot_angle);
- }
+ if (rot_axis[0] != 0 && rot_axis[1] != 0 && rot_axis[2] != 0) {
+ const real_t rot_angle(Math::acos(CLAMP(initial_ori.dot(ci->current_ori), -1, 1)));
+ new_bone_pose.basis.rotate(rot_axis, rot_angle);
+ }
+ } else {
+ // Set target orientation to tip
+ if (override_tip_basis) {
+ new_bone_pose.basis = p_task->chain.tips[0].end_effector->goal_transform.basis;
} else {
- // Set target orientation to tip
- if (override_tip_basis) {
- new_bone_pose.basis = p_task->chain.tips[0].end_effector->goal_transform.basis;
- } else {
- new_bone_pose.basis = new_bone_pose.basis * p_task->chain.tips[0].end_effector->goal_transform.basis;
- }
+ new_bone_pose.basis = new_bone_pose.basis * p_task->chain.tips[0].end_effector->goal_transform.basis;
}
}
@@ -362,7 +325,7 @@ void FabrikInverseKinematic::_update_chain(const Skeleton3D *p_sk, ChainItem *p_
return;
}
- p_chain_item->initial_transform = p_sk->get_bone_global_pose(p_chain_item->bone);
+ p_chain_item->initial_transform = p_sk->get_bone_global_pose_no_override(p_chain_item->bone);
p_chain_item->current_pos = p_chain_item->initial_transform.origin;
ChainItem *items = p_chain_item->children.ptrw();
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 44f2d38a84..2ad871ba61 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -597,9 +597,9 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
if (path.get_subname_count() == 1 && Object::cast_to<Skeleton3D>(spatial)) {
Skeleton3D *sk = Object::cast_to<Skeleton3D>(spatial);
+ track_xform->skeleton = sk;
int bone_idx = sk->find_bone(path.get_subname(0));
if (bone_idx != -1) {
- track_xform->skeleton = sk;
track_xform->bone_idx = bone_idx;
}
}
@@ -1205,7 +1205,7 @@ void AnimationTree::_process_graph(float p_delta) {
} else if (t->skeleton && t->bone_idx >= 0) {
t->skeleton->set_bone_pose(t->bone_idx, xform);
- } else {
+ } else if (!t->skeleton) {
t->spatial->set_transform(xform);
}
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 826fd0189b..ac067aa001 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -155,6 +155,9 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) {
}
status.pressed = !status.pressed;
_unpress_group();
+ if (button_group.is_valid()) {
+ button_group->emit_signal("pressed", this);
+ }
_toggled(status.pressed);
_pressed();
}
@@ -218,6 +221,9 @@ void BaseButton::set_pressed(bool p_pressed) {
if (p_pressed) {
_unpress_group();
+ if (button_group.is_valid()) {
+ button_group->emit_signal("pressed", this);
+ }
}
_toggled(status.pressed);
@@ -487,6 +493,7 @@ BaseButton *ButtonGroup::get_pressed_button() {
void ButtonGroup::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_pressed_button"), &ButtonGroup::get_pressed_button);
ClassDB::bind_method(D_METHOD("get_buttons"), &ButtonGroup::_get_buttons);
+ ADD_SIGNAL(MethodInfo("pressed", PropertyInfo(Variant::OBJECT, "button")));
}
ButtonGroup::ButtonGroup() {
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index b78f9cad24..9ccb2886e1 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -84,6 +84,57 @@ void ColorPicker::_notification(int p_what) {
}
}
+Ref<Shader> ColorPicker::wheel_shader;
+Ref<Shader> ColorPicker::circle_shader;
+
+void ColorPicker::init_shaders() {
+ wheel_shader.instance();
+ wheel_shader->set_code(
+ "shader_type canvas_item;"
+ "const float TAU = 6.28318530718;"
+ "void fragment() {"
+ " float x = UV.x - 0.5;"
+ " float y = UV.y - 0.5;"
+ " float a = atan(y, x);"
+ " x += 0.001;"
+ " y += 0.001;"
+ " float b = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);"
+ " x -= 0.002;"
+ " float b2 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);"
+ " y -= 0.002;"
+ " float b3 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);"
+ " x += 0.002;"
+ " float b4 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);"
+ " COLOR = vec4(clamp((abs(fract(((a - TAU) / TAU) + vec3(3.0, 2.0, 1.0) / 3.0) * 6.0 - 3.0) - 1.0), 0.0, 1.0), (b + b2 + b3 + b4) / 4.00);"
+ "}");
+
+ circle_shader.instance();
+ circle_shader->set_code(
+ "shader_type canvas_item;"
+ "const float TAU = 6.28318530718;"
+ "uniform float v = 1.0;"
+ "void fragment() {"
+ " float x = UV.x - 0.5;"
+ " float y = UV.y - 0.5;"
+ " float a = atan(y, x);"
+ " x += 0.001;"
+ " y += 0.001;"
+ " float b = float(sqrt(x * x + y * y) < 0.5);"
+ " x -= 0.002;"
+ " float b2 = float(sqrt(x * x + y * y) < 0.5);"
+ " y -= 0.002;"
+ " float b3 = float(sqrt(x * x + y * y) < 0.5);"
+ " x += 0.002;"
+ " float b4 = float(sqrt(x * x + y * y) < 0.5);"
+ " COLOR = vec4(mix(vec3(1.0), clamp(abs(fract(vec3((a - TAU) / TAU) + vec3(1.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - vec3(3.0)) - vec3(1.0), 0.0, 1.0), ((float(sqrt(x * x + y * y)) * 2.0)) / 1.0) * vec3(v), (b + b2 + b3 + b4) / 4.00);"
+ "}");
+}
+
+void ColorPicker::finish_shaders() {
+ wheel_shader.unref();
+ circle_shader.unref();
+}
+
void ColorPicker::set_focus_on_line_edit() {
c_text->call_deferred("grab_focus");
}
@@ -189,6 +240,18 @@ void ColorPicker::set_pick_color(const Color &p_color) {
_set_pick_color(p_color, true); //because setters can't have more arguments
}
+void ColorPicker::set_old_color(const Color &p_color) {
+ old_color = p_color;
+}
+
+void ColorPicker::set_display_old_color(bool p_enabled) {
+ display_old_color = p_enabled;
+}
+
+bool ColorPicker::is_displaying_old_color() const {
+ return display_old_color;
+}
+
void ColorPicker::set_edit_alpha(bool p_show) {
edit_alpha = p_show;
_update_controls();
@@ -458,18 +521,53 @@ void ColorPicker::_update_text_value() {
c_text->set_visible(visible);
}
+void ColorPicker::_sample_input(const Ref<InputEvent> &p_event) {
+ const Ref<InputEventMouseButton> mb = p_event;
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
+ const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95));
+ if (rect_old.has_point(mb->get_position())) {
+ // Revert to the old color when left-clicking the old color sample.
+ color = old_color;
+ _update_color();
+ emit_signal("color_changed", color);
+ }
+ }
+}
+
void ColorPicker::_sample_draw() {
- const Rect2 r = Rect2(Point2(), Size2(sample->get_size().width, sample->get_size().height * 0.95));
+ // Covers the right half of the sample if the old color is being displayed,
+ // or the whole sample if it's not being displayed.
+ Rect2 rect_new;
+
+ if (display_old_color) {
+ rect_new = Rect2(Point2(sample->get_size().width * 0.5, 0), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95));
+
+ // Draw both old and new colors for easier comparison (only if spawned from a ColorPickerButton).
+ const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95));
+
+ if (display_old_color && old_color.a < 1.0) {
+ sample->draw_texture_rect(get_theme_icon("preset_bg", "ColorPicker"), rect_old, true);
+ }
+
+ sample->draw_rect(rect_old, old_color);
+
+ if (old_color.r > 1 || old_color.g > 1 || old_color.b > 1) {
+ // Draw an indicator to denote that the old color is "overbright" and can't be displayed accurately in the preview.
+ sample->draw_texture(get_theme_icon("overbright_indicator", "ColorPicker"), Point2());
+ }
+ } else {
+ rect_new = Rect2(Point2(), Size2(sample->get_size().width, sample->get_size().height * 0.95));
+ }
if (color.a < 1.0) {
- sample->draw_texture_rect(get_theme_icon("preset_bg", "ColorPicker"), r, true);
+ sample->draw_texture_rect(get_theme_icon("preset_bg", "ColorPicker"), rect_new, true);
}
- sample->draw_rect(r, color);
+ sample->draw_rect(rect_new, color);
if (color.r > 1 || color.g > 1 || color.b > 1) {
- // Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview
- sample->draw_texture(get_theme_icon("overbright_indicator", "ColorPicker"), Point2());
+ // Draw an indicator to denote that the new color is "overbright" and can't be displayed accurately in the preview.
+ sample->draw_texture(get_theme_icon("overbright_indicator", "ColorPicker"), Point2(uv_edit->get_size().width * 0.5, 0));
}
}
@@ -1033,6 +1131,7 @@ ColorPicker::ColorPicker() :
hb_smpl->add_child(sample);
sample->set_h_size_flags(SIZE_EXPAND_FILL);
+ sample->connect("gui_input", callable_mp(this, &ColorPicker::_sample_input));
sample->connect("draw", callable_mp(this, &ColorPicker::_sample_draw));
btn_pick->set_flat(true);
@@ -1117,14 +1216,8 @@ ColorPicker::ColorPicker() :
hb_edit->add_child(wheel_edit);
wheel_mat.instance();
- circle_mat.instance();
-
- Ref<Shader> wheel_shader(memnew(Shader));
- wheel_shader->set_code("shader_type canvas_item;const float TAU=6.28318530718;void fragment(){float x=UV.x-0.5;float y=UV.y-0.5;float a=atan(y,x);x+=0.001;y+=0.001;float b=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);x-=0.002;float b2=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);y-=0.002;float b3=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);x+=0.002;float b4=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);COLOR=vec4(clamp((abs(fract(((a-TAU)/TAU)+vec3(3.0,2.0,1.0)/3.0)*6.0-3.0)-1.0),0.0,1.0),(b+b2+b3+b4)/4.00);}");
wheel_mat->set_shader(wheel_shader);
-
- Ref<Shader> circle_shader(memnew(Shader));
- circle_shader->set_code("shader_type canvas_item;const float TAU=6.28318530718;uniform float v=1.0;void fragment(){float x=UV.x-0.5;float y=UV.y-0.5;float a=atan(y,x);x+=0.001;y+=0.001;float b=float(sqrt(x*x+y*y)<0.5);x-=0.002;float b2=float(sqrt(x*x+y*y)<0.5);y-=0.002;float b3=float(sqrt(x*x+y*y)<0.5);x+=0.002;float b4=float(sqrt(x*x+y*y)<0.5);COLOR=vec4(mix(vec3(1.0),clamp(abs(fract(vec3((a-TAU)/TAU)+vec3(1.0,2.0/3.0,1.0/3.0))*6.0-vec3(3.0))-vec3(1.0),0.0,1.0),((float(sqrt(x*x+y*y))*2.0))/1.0)*vec3(v),(b+b2+b3+b4)/4.00);}");
+ circle_mat.instance();
circle_mat->set_shader(circle_shader);
MarginContainer *wheel_margin(memnew(MarginContainer));
@@ -1174,6 +1267,13 @@ ColorPicker::ColorPicker() :
/////////////////
+void ColorPickerButton::_about_to_popup() {
+ set_pressed(true);
+ if (picker) {
+ picker->set_old_color(color);
+ }
+}
+
void ColorPickerButton::_color_changed(const Color &p_color) {
color = p_color;
update();
@@ -1286,10 +1386,11 @@ void ColorPickerButton::_update_picker() {
popup->add_child(picker);
add_child(popup);
picker->connect("color_changed", callable_mp(this, &ColorPickerButton::_color_changed));
- popup->connect("about_to_popup", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(true));
+ popup->connect("about_to_popup", callable_mp(this, &ColorPickerButton::_about_to_popup));
popup->connect("popup_hide", callable_mp(this, &ColorPickerButton::_modal_closed));
picker->set_pick_color(color);
picker->set_edit_alpha(edit_alpha);
+ picker->set_display_old_color(true);
emit_signal("picker_created");
}
}
@@ -1301,6 +1402,7 @@ void ColorPickerButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_popup"), &ColorPickerButton::get_popup);
ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPickerButton::set_edit_alpha);
ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPickerButton::is_editing_alpha);
+ ClassDB::bind_method(D_METHOD("_about_to_popup"), &ColorPickerButton::_about_to_popup);
ADD_SIGNAL(MethodInfo("color_changed", PropertyInfo(Variant::COLOR, "color")));
ADD_SIGNAL(MethodInfo("popup_closed"));
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index a0d2aa95ca..14113467d0 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -56,6 +56,9 @@ public:
};
private:
+ static Ref<Shader> wheel_shader;
+ static Ref<Shader> circle_shader;
+
Control *screen = nullptr;
Control *uv_edit = memnew(Control);
Control *w_edit = memnew(Control);
@@ -86,6 +89,8 @@ private:
PickerShapeType picker_type = SHAPE_HSV_WHEEL;
Color color;
+ Color old_color;
+ bool display_old_color = false;
bool raw_mode_enabled = false;
bool hsv_mode_enabled = false;
bool deferred_mode_enabled = false;
@@ -106,6 +111,7 @@ private:
void _update_presets();
void _update_text_value();
void _text_type_toggled();
+ void _sample_input(const Ref<InputEvent> &p_event);
void _sample_draw();
void _hsv_draw(int p_which, Control *c);
void _slider_draw(int p_which);
@@ -125,12 +131,19 @@ protected:
static void _bind_methods();
public:
+ static void init_shaders();
+ static void finish_shaders();
+
void set_edit_alpha(bool p_show);
bool is_editing_alpha() const;
void _set_pick_color(const Color &p_color, bool p_update_sliders);
void set_pick_color(const Color &p_color);
Color get_pick_color() const;
+ void set_old_color(const Color &p_color);
+
+ void set_display_old_color(bool p_enabled);
+ bool is_displaying_old_color() const;
void set_picker_shape(PickerShapeType p_picker_type);
PickerShapeType get_picker_shape() const;
@@ -171,6 +184,7 @@ class ColorPickerButton : public Button {
Color color;
bool edit_alpha = true;
+ void _about_to_popup();
void _color_changed(const Color &p_color);
void _modal_closed();
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 191f94b2b8..ce5eef93aa 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -345,72 +345,72 @@ void Control::_get_property_list(List<PropertyInfo> *p_list) const {
List<StringName> names;
theme->get_icon_list(get_class_name(), &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- uint32_t hint = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
+ uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
if (data.icon_override.has(E->get())) {
- hint |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+ usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::OBJECT, "custom_icons/" + E->get(), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", hint));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "custom_icons/" + E->get(), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", usage));
}
}
{
List<StringName> names;
theme->get_stylebox_list(get_class_name(), &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- uint32_t hint = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
+ uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
if (data.style_override.has(E->get())) {
- hint |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+ usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::OBJECT, "custom_styles/" + E->get(), PROPERTY_HINT_RESOURCE_TYPE, "StyleBox", hint));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "custom_styles/" + E->get(), PROPERTY_HINT_RESOURCE_TYPE, "StyleBox", usage));
}
}
{
List<StringName> names;
theme->get_font_list(get_class_name(), &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- uint32_t hint = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
+ uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
if (data.font_override.has(E->get())) {
- hint |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+ usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::OBJECT, "custom_fonts/" + E->get(), PROPERTY_HINT_RESOURCE_TYPE, "Font", hint));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "custom_fonts/" + E->get(), PROPERTY_HINT_RESOURCE_TYPE, "Font", usage));
}
}
{
List<StringName> names;
theme->get_font_size_list(get_class_name(), &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- uint32_t hint = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
+ uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
if (data.font_size_override.has(E->get())) {
- hint |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+ usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::INT, "custom_font_sizes/" + E->get(), PROPERTY_HINT_NONE, "", hint));
+ p_list->push_back(PropertyInfo(Variant::INT, "custom_font_sizes/" + E->get(), PROPERTY_HINT_NONE, "", usage));
}
}
{
List<StringName> names;
theme->get_color_list(get_class_name(), &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- uint32_t hint = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
+ uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
if (data.color_override.has(E->get())) {
- hint |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+ usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::COLOR, "custom_colors/" + E->get(), PROPERTY_HINT_NONE, "", hint));
+ p_list->push_back(PropertyInfo(Variant::COLOR, "custom_colors/" + E->get(), PROPERTY_HINT_NONE, "", usage));
}
}
{
List<StringName> names;
theme->get_constant_list(get_class_name(), &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- uint32_t hint = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
+ uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
if (data.constant_override.has(E->get())) {
- hint |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+ usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::INT, "custom_constants/" + E->get(), PROPERTY_HINT_RANGE, "-16384,16384", hint));
+ p_list->push_back(PropertyInfo(Variant::INT, "custom_constants/" + E->get(), PROPERTY_HINT_RANGE, "-16384,16384", usage));
}
}
}
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 5409b44b9e..350c77039f 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -105,7 +105,7 @@ void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
switch (k->get_keycode()) {
case KEY_H: {
- if (k->get_command()) {
+ if (k->is_command_pressed()) {
set_show_hidden_files(!show_hidden_files);
} else {
handled = false;
diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp
index e72709e847..7278ca6e94 100644
--- a/scene/gui/gradient_edit.cpp
+++ b/scene/gui/gradient_edit.cpp
@@ -107,7 +107,7 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
//Show color picker on double click.
- if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_doubleclick() && mb->is_pressed()) {
+ if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_double_click() && mb->is_pressed()) {
grabbed = _get_point_from_pos(mb->get_position().x);
_show_color_picker();
accept_event();
@@ -127,7 +127,7 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
//Hold alt key to duplicate selected color
- if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed() && mb->get_alt()) {
+ if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed() && mb->is_alt_pressed()) {
int x = mb->get_position().x;
grabbed = _get_point_from_pos(x);
@@ -236,9 +236,9 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) {
// Snap to "round" coordinates if holding Ctrl.
// Be more precise if holding Shift as well
- if (mm->get_control()) {
- newofs = Math::snapped(newofs, mm->get_shift() ? 0.025 : 0.1);
- } else if (mm->get_shift()) {
+ if (mm->is_ctrl_pressed()) {
+ newofs = Math::snapped(newofs, mm->is_shift_pressed() ? 0.025 : 0.1);
+ } else if (mm->is_shift_pressed()) {
// Snap to nearest point if holding just Shift
const float snap_threshold = 0.03;
float smallest_ofs = snap_threshold;
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 06c9cf1b63..5a4dacd897 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -1091,7 +1091,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
// Snapping can be toggled temporarily by holding down Ctrl.
// This is done here as to not toggle the grid when holding down Ctrl.
- if (is_using_snap() ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (is_using_snap() ^ Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
const int snap = get_snap();
pos = pos.snapped(Vector2(snap, snap));
}
@@ -1174,7 +1174,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
}
if (b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed() && dragging) {
- if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
//deselect current node
for (int i = get_child_count() - 1; i >= 0; i--) {
GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
@@ -1238,7 +1238,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
dragging = true;
drag_accum = Vector2();
just_selected = !gn->is_selected();
- if (!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
for (int i = 0; i < get_child_count(); i++) {
GraphNode *o_gn = Object::cast_to<GraphNode>(get_child(i));
if (o_gn) {
@@ -1275,7 +1275,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
box_selecting = true;
box_selecting_from = b->get_position();
- if (b->get_control()) {
+ if (b->is_ctrl_pressed()) {
box_selection_mode_additive = true;
previous_selected.clear();
for (int i = get_child_count() - 1; i >= 0; i--) {
@@ -1286,7 +1286,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
previous_selected.push_back(gn2);
}
- } else if (b->get_shift()) {
+ } else if (b->is_shift_pressed()) {
box_selection_mode_additive = false;
previous_selected.clear();
for (int i = get_child_count() - 1; i >= 0; i--) {
@@ -1322,9 +1322,9 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
minimap->update();
}
- if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
set_zoom_custom(zoom * ZOOM_SCALE, b->get_position());
- } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_CTRL)) {
set_zoom_custom(zoom / ZOOM_SCALE, b->get_position());
} else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8);
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 7d5c53effe..7771970a22 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -459,7 +459,7 @@ void GraphNode::_shape() {
}
void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left, const Ref<Texture2D> &p_custom_right) {
- ERR_FAIL_COND(p_idx < 0);
+ ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set slot with p_idx (%d) lesser than zero.", p_idx));
if (!p_enable_left && p_type_left == 0 && p_color_left == Color(1, 1, 1, 1) &&
!p_enable_right && p_type_right == 0 && p_color_right == Color(1, 1, 1, 1) &&
@@ -503,6 +503,26 @@ bool GraphNode::is_slot_enabled_left(int p_idx) const {
return slot_info[p_idx].enable_left;
}
+void GraphNode::set_slot_enabled_left(int p_idx, bool p_enable_left) {
+ ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set enable_left for the slot with p_idx (%d) lesser than zero.", p_idx));
+
+ slot_info[p_idx].enable_left = p_enable_left;
+ update();
+ connpos_dirty = true;
+
+ emit_signal("slot_updated", p_idx);
+}
+
+void GraphNode::set_slot_type_left(int p_idx, int p_type_left) {
+ ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set type_left for the slot '%d' because it hasn't been enabled.", p_idx));
+
+ slot_info[p_idx].type_left = p_type_left;
+ update();
+ connpos_dirty = true;
+
+ emit_signal("slot_updated", p_idx);
+}
+
int GraphNode::get_slot_type_left(int p_idx) const {
if (!slot_info.has(p_idx)) {
return 0;
@@ -510,6 +530,16 @@ int GraphNode::get_slot_type_left(int p_idx) const {
return slot_info[p_idx].type_left;
}
+void GraphNode::set_slot_color_left(int p_idx, const Color &p_color_left) {
+ ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set color_left for the slot '%d' because it hasn't been enabled.", p_idx));
+
+ slot_info[p_idx].color_left = p_color_left;
+ update();
+ connpos_dirty = true;
+
+ emit_signal("slot_updated", p_idx);
+}
+
Color GraphNode::get_slot_color_left(int p_idx) const {
if (!slot_info.has(p_idx)) {
return Color(1, 1, 1, 1);
@@ -524,6 +554,26 @@ bool GraphNode::is_slot_enabled_right(int p_idx) const {
return slot_info[p_idx].enable_right;
}
+void GraphNode::set_slot_enabled_right(int p_idx, bool p_enable_right) {
+ ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set enable_right for the slot with p_idx (%d) lesser than zero.", p_idx));
+
+ slot_info[p_idx].enable_right = p_enable_right;
+ update();
+ connpos_dirty = true;
+
+ emit_signal("slot_updated", p_idx);
+}
+
+void GraphNode::set_slot_type_right(int p_idx, int p_type_right) {
+ ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set type_right for the slot '%d' because it hasn't been enabled.", p_idx));
+
+ slot_info[p_idx].type_right = p_type_right;
+ update();
+ connpos_dirty = true;
+
+ emit_signal("slot_updated", p_idx);
+}
+
int GraphNode::get_slot_type_right(int p_idx) const {
if (!slot_info.has(p_idx)) {
return 0;
@@ -531,6 +581,16 @@ int GraphNode::get_slot_type_right(int p_idx) const {
return slot_info[p_idx].type_right;
}
+void GraphNode::set_slot_color_right(int p_idx, const Color &p_color_right) {
+ ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set color_right for the slot '%d' because it hasn't been enabled.", p_idx));
+
+ slot_info[p_idx].color_right = p_color_right;
+ update();
+ connpos_dirty = true;
+
+ emit_signal("slot_updated", p_idx);
+}
+
Color GraphNode::get_slot_color_right(int p_idx) const {
if (!slot_info.has(p_idx)) {
return Color(1, 1, 1, 1);
@@ -891,11 +951,23 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_slot", "idx", "enable_left", "type_left", "color_left", "enable_right", "type_right", "color_right", "custom_left", "custom_right"), &GraphNode::set_slot, DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("clear_slot", "idx"), &GraphNode::clear_slot);
ClassDB::bind_method(D_METHOD("clear_all_slots"), &GraphNode::clear_all_slots);
+
ClassDB::bind_method(D_METHOD("is_slot_enabled_left", "idx"), &GraphNode::is_slot_enabled_left);
+ ClassDB::bind_method(D_METHOD("set_slot_enabled_left", "idx", "enable_left"), &GraphNode::set_slot_enabled_left);
+
+ ClassDB::bind_method(D_METHOD("set_slot_type_left", "idx", "type_left"), &GraphNode::set_slot_type_left);
ClassDB::bind_method(D_METHOD("get_slot_type_left", "idx"), &GraphNode::get_slot_type_left);
+
+ ClassDB::bind_method(D_METHOD("set_slot_color_left", "idx", "color_left"), &GraphNode::set_slot_color_left);
ClassDB::bind_method(D_METHOD("get_slot_color_left", "idx"), &GraphNode::get_slot_color_left);
+
ClassDB::bind_method(D_METHOD("is_slot_enabled_right", "idx"), &GraphNode::is_slot_enabled_right);
+ ClassDB::bind_method(D_METHOD("set_slot_enabled_right", "idx", "enable_right"), &GraphNode::set_slot_enabled_right);
+
+ ClassDB::bind_method(D_METHOD("set_slot_type_right", "idx", "type_right"), &GraphNode::set_slot_type_right);
ClassDB::bind_method(D_METHOD("get_slot_type_right", "idx"), &GraphNode::get_slot_type_right);
+
+ ClassDB::bind_method(D_METHOD("set_slot_color_right", "idx", "color_right"), &GraphNode::set_slot_color_right);
ClassDB::bind_method(D_METHOD("get_slot_color_right", "idx"), &GraphNode::get_slot_color_right);
ClassDB::bind_method(D_METHOD("set_position_offset", "offset"), &GraphNode::set_position_offset);
diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h
index 1bc54dddb7..c70f616b47 100644
--- a/scene/gui/graph_node.h
+++ b/scene/gui/graph_node.h
@@ -113,11 +113,23 @@ public:
void set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left = Ref<Texture2D>(), const Ref<Texture2D> &p_custom_right = Ref<Texture2D>());
void clear_slot(int p_idx);
void clear_all_slots();
+
bool is_slot_enabled_left(int p_idx) const;
+ void set_slot_enabled_left(int p_idx, bool p_enable_left);
+
+ void set_slot_type_left(int p_idx, int p_type_left);
int get_slot_type_left(int p_idx) const;
+
+ void set_slot_color_left(int p_idx, const Color &p_color_left);
Color get_slot_color_left(int p_idx) const;
+
bool is_slot_enabled_right(int p_idx) const;
+ void set_slot_enabled_right(int p_idx, bool p_enable_right);
+
+ void set_slot_type_right(int p_idx, int p_type_right);
int get_slot_type_right(int p_idx) const;
+
+ void set_slot_color_right(int p_idx, const Color &p_color_right);
Color get_slot_color_right(int p_idx) const;
void set_title(const String &p_title);
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 86d070f9b1..150980b2e9 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -406,6 +406,9 @@ void ItemList::remove_item(int p_idx) {
ERR_FAIL_INDEX(p_idx, items.size());
items.remove(p_idx);
+ if (current == p_idx) {
+ current = -1;
+ }
update();
shape_changed = true;
defer_select_single = -1;
@@ -578,11 +581,11 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
if (closest != -1) {
int i = closest;
- if (select_mode == SELECT_MULTI && items[i].selected && mb->get_command()) {
+ if (select_mode == SELECT_MULTI && items[i].selected && mb->is_command_pressed()) {
deselect(i);
emit_signal("multi_selected", i, false);
- } else if (select_mode == SELECT_MULTI && mb->get_shift() && current >= 0 && current < items.size() && current != i) {
+ } else if (select_mode == SELECT_MULTI && mb->is_shift_pressed() && current >= 0 && current < items.size() && current != i) {
int from = current;
int to = i;
if (i < current) {
@@ -600,7 +603,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
emit_signal("item_rmb_selected", i, get_local_mouse_position());
}
} else {
- if (!mb->is_doubleclick() && !mb->get_command() && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (!mb->is_double_click() && !mb->is_command_pressed() && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
defer_select_single = i;
return;
}
@@ -610,7 +613,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
} else {
bool selected = items[i].selected;
- select(i, select_mode == SELECT_SINGLE || !mb->get_command());
+ select(i, select_mode == SELECT_SINGLE || !mb->is_command_pressed());
if (!selected || allow_reselect) {
if (select_mode == SELECT_SINGLE) {
@@ -622,7 +625,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
emit_signal("item_rmb_selected", i, get_local_mouse_position());
- } else if (/*select_mode==SELECT_SINGLE &&*/ mb->is_doubleclick()) {
+ } else if (/*select_mode==SELECT_SINGLE &&*/ mb->is_double_click()) {
emit_signal("item_activated", i);
}
}
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 1aff5d5390..98dd9f624b 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -250,25 +250,25 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
return;
}
- shift_selection_check_pre(b->get_shift());
+ shift_selection_check_pre(b->is_shift_pressed());
set_caret_at_pixel_pos(b->get_position().x);
- if (b->get_shift()) {
+ if (b->is_shift_pressed()) {
selection_fill_at_caret();
selection.creating = true;
} else {
if (selecting_enabled) {
- if (!b->is_doubleclick() && (OS::get_singleton()->get_ticks_msec() - selection.last_dblclk) < 600) {
+ if (!b->is_double_click() && (OS::get_singleton()->get_ticks_msec() - selection.last_dblclk) < 600) {
// Triple-click select all.
selection.enabled = true;
selection.begin = 0;
selection.end = text.length();
- selection.doubleclick = true;
+ selection.double_click = true;
selection.last_dblclk = 0;
caret_column = selection.begin;
- } else if (b->is_doubleclick()) {
+ } else if (b->is_double_click()) {
// Double-click select word.
Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
for (int i = 0; i < words.size(); i++) {
@@ -276,7 +276,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
selection.enabled = true;
selection.begin = words[i].x;
selection.end = words[i].y;
- selection.doubleclick = true;
+ selection.double_click = true;
selection.last_dblclk = OS::get_singleton()->get_ticks_msec();
caret_column = selection.end;
break;
@@ -308,11 +308,11 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
}
}
- if ((!selection.creating) && (!selection.doubleclick)) {
+ if ((!selection.creating) && (!selection.double_click)) {
deselect();
}
selection.creating = false;
- selection.doubleclick = false;
+ selection.double_click = false;
show_virtual_keyboard();
}
@@ -442,9 +442,9 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
// Cursor Movement
k = k->duplicate();
- bool shift_pressed = k->get_shift();
+ bool shift_pressed = k->is_shift_pressed();
// Remove shift or else actions will not match. Use above variable for selection.
- k->set_shift(false);
+ k->set_shift_pressed(false);
if (k->is_action("ui_text_caret_word_left", true)) {
_move_caret_left(shift_pressed, true);
@@ -490,7 +490,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
// Allow unicode handling if:
// * No Modifiers are pressed (except shift)
- bool allow_unicode_handling = !(k->get_command() || k->get_control() || k->get_alt() || k->get_metakey());
+ bool allow_unicode_handling = !(k->is_command_pressed() || k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed());
if (allow_unicode_handling && editable && k->get_unicode() >= 32) {
// Handle Unicode (if no modifiers active)
@@ -557,7 +557,7 @@ void LineEdit::drop_data(const Point2 &p_point, const Variant &p_data) {
}
Control::CursorShape LineEdit::get_cursor_shape(const Point2 &p_pos) const {
- if (!text.is_empty() && is_editable() && _is_over_clear_button(p_pos)) {
+ if ((!text.is_empty() && is_editable() && _is_over_clear_button(p_pos)) || (!is_editable() && (!is_selecting_enabled() || text.is_empty()))) {
return CURSOR_ARROW;
}
return Control::get_cursor_shape(p_pos);
@@ -1532,7 +1532,7 @@ void LineEdit::deselect() {
selection.start_column = 0;
selection.enabled = false;
selection.creating = false;
- selection.doubleclick = false;
+ selection.double_click = false;
update();
}
@@ -1659,7 +1659,7 @@ void LineEdit::select(int p_from, int p_to) {
selection.begin = p_from;
selection.end = p_to;
selection.creating = false;
- selection.doubleclick = false;
+ selection.double_click = false;
update();
}
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index f4f0ff0629..12fec2f98b 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -134,7 +134,7 @@ private:
int start_column = 0;
bool enabled = false;
bool creating = false;
- bool doubleclick = false;
+ bool double_click = false;
bool drag_attempt = false;
uint64_t last_dblclk = 0;
} selection;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 44df8eafdc..2100707d2d 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -1282,16 +1282,16 @@ bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_fo
if (code == 0) {
code = k->get_unicode();
}
- if (k->get_control()) {
+ if (k->is_ctrl_pressed()) {
code |= KEY_MASK_CTRL;
}
- if (k->get_alt()) {
+ if (k->is_alt_pressed()) {
code |= KEY_MASK_ALT;
}
- if (k->get_metakey()) {
+ if (k->is_meta_pressed()) {
code |= KEY_MASK_META;
}
- if (k->get_shift()) {
+ if (k->is_shift_pressed()) {
code |= KEY_MASK_SHIFT;
}
}
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index c763ae6bd6..2800ab0442 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1432,10 +1432,11 @@ void RichTextLabel::_notification(int p_what) {
}
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
- float dt = get_process_delta_time();
-
- _update_fx(main, dt);
- update();
+ if (is_visible_in_tree()) {
+ float dt = get_process_delta_time();
+ _update_fx(main, dt);
+ update();
+ }
}
}
}
@@ -1482,7 +1483,7 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
}
if (b->get_button_index() == MOUSE_BUTTON_LEFT) {
- if (b->is_pressed() && !b->is_doubleclick()) {
+ if (b->is_pressed() && !b->is_double_click()) {
scroll_updated = false;
ItemFrame *c_frame = nullptr;
int c_line = 0;
@@ -1514,8 +1515,8 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
}
}
}
- } else if (b->is_pressed() && b->is_doubleclick() && selection.enabled) {
- //doubleclick: select word
+ } else if (b->is_pressed() && b->is_double_click() && selection.enabled) {
+ //double_click: select word
ItemFrame *c_frame = nullptr;
int c_line = 0;
@@ -1549,7 +1550,7 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
} else if (!b->is_pressed()) {
selection.click_item = nullptr;
- if (!b->is_doubleclick() && !scroll_updated) {
+ if (!b->is_double_click() && !scroll_updated) {
Item *c_item = nullptr;
bool outside = true;
@@ -2612,6 +2613,14 @@ void RichTextLabel::pop() {
current = current->parent;
}
+// Creates a new line without adding an ItemNewline to the previous line.
+// Useful when wanting to calling remove_line and add a new line immediately after.
+void RichTextLabel::increment_line_count() {
+ _validate_line_caches(main);
+ current_frame->lines.resize(current_frame->lines.size() + 1);
+ _invalidate_current_line(current_frame);
+}
+
void RichTextLabel::clear() {
main->_clear_children();
current = main;
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index e3e457d1f2..afc88e070a 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -483,6 +483,8 @@ public:
void push_cell();
void pop();
+ void increment_line_count();
+
void clear();
void set_offset(int p_pixel);
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 73c6371658..46db4a3c2f 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -98,7 +98,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb.is_valid()) {
if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) {
// only horizontal is enabled, scroll horizontally
- if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->get_shift())) {
+ if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->is_shift_pressed())) {
h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() / 8 * mb->get_factor());
} else if (v_scroll->is_visible_in_tree()) {
v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() / 8 * mb->get_factor());
@@ -107,7 +107,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) {
// only horizontal is enabled, scroll horizontally
- if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->get_shift())) {
+ if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->is_shift_pressed())) {
h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() / 8 * mb->get_factor());
} else if (v_scroll->is_visible()) {
v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() / 8 * mb->get_factor());
@@ -299,7 +299,7 @@ void ScrollContainer::_update_dimensions() {
child_max_size.x = MAX(child_max_size.x, minsize.x);
child_max_size.y = MAX(child_max_size.y, minsize.y);
- Rect2 r = Rect2(-scroll, minsize);
+ Rect2 r = Rect2(-Size2(get_h_scroll(), get_v_scroll()), minsize);
if (!scroll_h || (!h_scroll->is_visible_in_tree() && c->get_h_size_flags() & SIZE_EXPAND)) {
r.position.x = 0;
if (c->get_h_size_flags() & SIZE_EXPAND) {
@@ -434,40 +434,16 @@ void ScrollContainer::update_scrollbars() {
Size2 min = child_max_size;
- bool hide_scroll_v = !scroll_v || min.height <= size.height;
- bool hide_scroll_h = !scroll_h || min.width <= size.width;
-
- v_scroll->set_max(min.height);
- if (hide_scroll_v) {
- v_scroll->set_page(size.height);
- v_scroll->hide();
- scroll.y = 0;
- } else {
- v_scroll->show();
- if (hide_scroll_h) {
- v_scroll->set_page(size.height);
- } else {
- v_scroll->set_page(size.height - hmin.height);
- }
-
- scroll.y = v_scroll->get_value();
- }
+ bool hide_scroll_h = !scroll_h || min.width <= size.width || !h_scroll_visible;
+ bool hide_scroll_v = !scroll_v || min.height <= size.height || !v_scroll_visible;
h_scroll->set_max(min.width);
- if (hide_scroll_h) {
- h_scroll->set_page(size.width);
- h_scroll->hide();
- scroll.x = 0;
- } else {
- h_scroll->show();
- if (hide_scroll_v) {
- h_scroll->set_page(size.width);
- } else {
- h_scroll->set_page(size.width - vmin.width);
- }
+ h_scroll->set_page(size.width - (hide_scroll_v ? 0 : vmin.width));
+ h_scroll->set_visible(!hide_scroll_h);
- scroll.x = h_scroll->get_value();
- }
+ v_scroll->set_max(min.height);
+ v_scroll->set_page(size.height - (hide_scroll_h ? 0 : hmin.height));
+ v_scroll->set_visible(!hide_scroll_v);
// Avoid scrollbar overlapping.
h_scroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, hide_scroll_v ? 0 : -vmin.width);
@@ -475,13 +451,28 @@ void ScrollContainer::update_scrollbars() {
}
void ScrollContainer::_scroll_moved(float) {
- scroll.x = h_scroll->get_value();
- scroll.y = v_scroll->get_value();
queue_sort();
-
update();
};
+void ScrollContainer::set_h_scroll(int p_pos) {
+ h_scroll->set_value(p_pos);
+ _cancel_drag();
+}
+
+int ScrollContainer::get_h_scroll() const {
+ return h_scroll->get_value();
+}
+
+void ScrollContainer::set_v_scroll(int p_pos) {
+ v_scroll->set_value(p_pos);
+ _cancel_drag();
+}
+
+int ScrollContainer::get_v_scroll() const {
+ return v_scroll->get_value();
+}
+
void ScrollContainer::set_enable_h_scroll(bool p_enable) {
if (scroll_h == p_enable) {
return;
@@ -510,22 +501,30 @@ bool ScrollContainer::is_v_scroll_enabled() const {
return scroll_v;
}
-int ScrollContainer::get_v_scroll() const {
- return v_scroll->get_value();
+void ScrollContainer::set_h_scroll_visible(bool p_visible) {
+ if (h_scroll_visible == p_visible) {
+ return;
+ }
+
+ h_scroll_visible = p_visible;
+ update_scrollbars();
}
-void ScrollContainer::set_v_scroll(int p_pos) {
- v_scroll->set_value(p_pos);
- _cancel_drag();
+bool ScrollContainer::is_h_scroll_visible() const {
+ return h_scroll_visible;
}
-int ScrollContainer::get_h_scroll() const {
- return h_scroll->get_value();
+void ScrollContainer::set_v_scroll_visible(bool p_visible) {
+ if (v_scroll_visible == p_visible) {
+ return;
+ }
+
+ v_scroll_visible = p_visible;
+ update_scrollbars();
}
-void ScrollContainer::set_h_scroll(int p_pos) {
- h_scroll->set_value(p_pos);
- _cancel_drag();
+bool ScrollContainer::is_v_scroll_visible() const {
+ return v_scroll_visible;
}
int ScrollContainer::get_deadzone() const {
@@ -581,17 +580,29 @@ VScrollBar *ScrollContainer::get_v_scrollbar() {
void ScrollContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &ScrollContainer::_gui_input);
- ClassDB::bind_method(D_METHOD("set_enable_h_scroll", "enable"), &ScrollContainer::set_enable_h_scroll);
- ClassDB::bind_method(D_METHOD("is_h_scroll_enabled"), &ScrollContainer::is_h_scroll_enabled);
- ClassDB::bind_method(D_METHOD("set_enable_v_scroll", "enable"), &ScrollContainer::set_enable_v_scroll);
- ClassDB::bind_method(D_METHOD("is_v_scroll_enabled"), &ScrollContainer::is_v_scroll_enabled);
ClassDB::bind_method(D_METHOD("_update_scrollbar_position"), &ScrollContainer::_update_scrollbar_position);
+
ClassDB::bind_method(D_METHOD("set_h_scroll", "value"), &ScrollContainer::set_h_scroll);
ClassDB::bind_method(D_METHOD("get_h_scroll"), &ScrollContainer::get_h_scroll);
+
ClassDB::bind_method(D_METHOD("set_v_scroll", "value"), &ScrollContainer::set_v_scroll);
ClassDB::bind_method(D_METHOD("get_v_scroll"), &ScrollContainer::get_v_scroll);
+
+ ClassDB::bind_method(D_METHOD("set_enable_h_scroll", "enable"), &ScrollContainer::set_enable_h_scroll);
+ ClassDB::bind_method(D_METHOD("is_h_scroll_enabled"), &ScrollContainer::is_h_scroll_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_enable_v_scroll", "enable"), &ScrollContainer::set_enable_v_scroll);
+ ClassDB::bind_method(D_METHOD("is_v_scroll_enabled"), &ScrollContainer::is_v_scroll_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_h_scroll_visible", "visible"), &ScrollContainer::set_h_scroll_visible);
+ ClassDB::bind_method(D_METHOD("is_h_scroll_visible"), &ScrollContainer::is_h_scroll_visible);
+
+ ClassDB::bind_method(D_METHOD("set_v_scroll_visible", "visible"), &ScrollContainer::set_v_scroll_visible);
+ ClassDB::bind_method(D_METHOD("is_v_scroll_visible"), &ScrollContainer::is_v_scroll_visible);
+
ClassDB::bind_method(D_METHOD("set_deadzone", "deadzone"), &ScrollContainer::set_deadzone);
ClassDB::bind_method(D_METHOD("get_deadzone"), &ScrollContainer::get_deadzone);
+
ClassDB::bind_method(D_METHOD("set_follow_focus", "enabled"), &ScrollContainer::set_follow_focus);
ClassDB::bind_method(D_METHOD("is_following_focus"), &ScrollContainer::is_following_focus);
@@ -604,10 +615,12 @@ void ScrollContainer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_focus"), "set_follow_focus", "is_following_focus");
ADD_GROUP("Scroll", "scroll_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_horizontal_enabled"), "set_enable_h_scroll", "is_h_scroll_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal"), "set_h_scroll", "get_h_scroll");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_vertical_enabled"), "set_enable_v_scroll", "is_v_scroll_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_vertical"), "set_v_scroll", "get_v_scroll");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_horizontal_enabled"), "set_enable_h_scroll", "is_h_scroll_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_vertical_enabled"), "set_enable_v_scroll", "is_v_scroll_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_horizontal_visible"), "set_h_scroll_visible", "is_h_scroll_visible");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_vertical_visible"), "set_v_scroll_visible", "is_v_scroll_visible");
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_deadzone"), "set_deadzone", "get_deadzone");
GLOBAL_DEF("gui/common/default_scroll_deadzone", 0);
diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h
index e7d73bab0a..f61df70b85 100644
--- a/scene/gui/scroll_container.h
+++ b/scene/gui/scroll_container.h
@@ -42,7 +42,6 @@ class ScrollContainer : public Container {
VScrollBar *v_scroll;
Size2 child_max_size;
- Size2 scroll;
void update_scrollbars();
@@ -50,16 +49,17 @@ class ScrollContainer : public Container {
Vector2 drag_accum;
Vector2 drag_from;
Vector2 last_drag_accum;
- float last_drag_time = 0.0;
- float time_since_motion = 0.0;
+ float time_since_motion = 0.0f;
bool drag_touching = false;
bool drag_touching_deaccel = false;
- bool click_handled = false;
bool beyond_deadzone = false;
bool scroll_h = true;
bool scroll_v = true;
+ bool h_scroll_visible = true;
+ bool v_scroll_visible = true;
+
int deadzone = 0;
bool follow_focus = false;
@@ -80,11 +80,11 @@ protected:
void _ensure_focused_visible(Control *p_node);
public:
- int get_v_scroll() const;
- void set_v_scroll(int p_pos);
-
- int get_h_scroll() const;
void set_h_scroll(int p_pos);
+ int get_h_scroll() const;
+
+ void set_v_scroll(int p_pos);
+ int get_v_scroll() const;
void set_enable_h_scroll(bool p_enable);
bool is_h_scroll_enabled() const;
@@ -92,6 +92,12 @@ public:
void set_enable_v_scroll(bool p_enable);
bool is_v_scroll_enabled() const;
+ void set_h_scroll_visible(bool p_visible);
+ bool is_h_scroll_visible() const;
+
+ void set_v_scroll_visible(bool p_visible);
+ bool is_v_scroll_visible() const;
+
int get_deadzone() const;
void set_deadzone(int p_deadzone);
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index ff9dafa0f9..acf0641005 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -394,6 +394,7 @@ void TabContainer::_notification(int p_what) {
Vector<int> tab_widths;
for (int i = first_tab_cache; i < tabs.size(); i++) {
if (get_tab_hidden(i)) {
+ tab_widths.push_back(0);
continue;
}
int tab_width = _get_tab_width(i);
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index 6cbc5890ce..471b26be75 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -127,7 +127,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->get_command()) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->is_command_pressed()) {
if (scrolling_enabled && buttons_visible) {
if (offset > 0) {
offset--;
@@ -136,7 +136,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->get_command()) {
+ if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->is_command_pressed()) {
if (scrolling_enabled && buttons_visible) {
if (missing_right) {
offset++;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 4f508423b3..ba98b3c931 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -2054,6 +2054,7 @@ void TextEdit::indent_selected_lines_left() {
if (is_selection_active() && get_selection_to_column() == 0) {
end_line--;
}
+ String first_line_text = get_line(start_line);
String last_line_text = get_line(end_line);
for (int i = start_line; i <= end_line; i++) {
@@ -2078,10 +2079,17 @@ void TextEdit::indent_selected_lines_left() {
}
}
- // Fix selection and cursor being off by one on the last line.
- if (is_selection_active() && last_line_text != get_line(end_line)) {
- select(selection.from_line, selection.from_column - removed_characters,
- selection.to_line, initial_selection_end_column - removed_characters);
+ if (is_selection_active()) {
+ // Fix selection being off by one on the first line.
+ if (first_line_text != get_line(start_line)) {
+ select(selection.from_line, selection.from_column - removed_characters,
+ selection.to_line, initial_selection_end_column);
+ }
+ // Fix selection being off by one on the last line.
+ if (last_line_text != get_line(end_line)) {
+ select(selection.from_line, selection.from_column,
+ selection.to_line, initial_selection_end_column - removed_characters);
+ }
}
cursor_set_column(initial_cursor_column - removed_characters, false);
end_complex_operation();
@@ -2895,7 +2903,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
completion_current = completion_options[completion_index];
update();
- if (mb->is_doubleclick()) {
+ if (mb->is_double_click()) {
_confirm_completion();
}
}
@@ -2906,17 +2914,25 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
if (mb->is_pressed()) {
- if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->get_command()) {
- if (mb->get_shift()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->is_command_pressed()) {
+ if (mb->is_shift_pressed()) {
h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor()));
+ } else if (mb->is_alt_pressed()) {
+ // Scroll 5 times as fast as normal (like in Visual Studio Code).
+ _scroll_up(15 * mb->get_factor());
} else if (v_scroll->is_visible()) {
+ // Scroll 3 lines.
_scroll_up(3 * mb->get_factor());
}
}
- if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->get_command()) {
- if (mb->get_shift()) {
+ if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->is_command_pressed()) {
+ if (mb->is_shift_pressed()) {
h_scroll->set_value(h_scroll->get_value() + (100 * mb->get_factor()));
+ } else if (mb->is_alt_pressed()) {
+ // Scroll 5 times as fast as normal (like in Visual Studio Code).
+ _scroll_down(15 * mb->get_factor());
} else if (v_scroll->is_visible()) {
+ // Scroll 3 lines.
_scroll_down(3 * mb->get_factor());
}
}
@@ -2969,7 +2985,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
cursor_set_line(row, false, false);
cursor_set_column(col);
- if (mb->get_shift() && (cursor.column != prev_col || cursor.line != prev_line)) {
+ if (mb->is_shift_pressed() && (cursor.column != prev_col || cursor.line != prev_line)) {
if (!selection.active) {
selection.active = true;
selection.selecting_mode = SelectionMode::SELECTION_MODE_POINTER;
@@ -3018,12 +3034,12 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
selection.selecting_column = col;
}
- if (!mb->is_doubleclick() && (OS::get_singleton()->get_ticks_msec() - last_dblclk) < 600 && cursor.line == prev_line) {
+ if (!mb->is_double_click() && (OS::get_singleton()->get_ticks_msec() - last_dblclk) < 600 && cursor.line == prev_line) {
// Triple-click select line.
selection.selecting_mode = SelectionMode::SELECTION_MODE_LINE;
_update_selection_mode_line();
last_dblclk = 0;
- } else if (mb->is_doubleclick() && text[cursor.line].length()) {
+ } else if (mb->is_double_click() && text[cursor.line].length()) {
// Double-click select word.
selection.selecting_mode = SelectionMode::SELECTION_MODE_WORD;
_update_selection_mode_word();
@@ -3065,7 +3081,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
} else {
if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
- if (mb->get_command() && highlighted_word != String()) {
+ if (mb->is_command_pressed() && highlighted_word != String()) {
int row, col;
_get_mouse_pos(Point2i(mpos.x, mpos.y), row, col);
@@ -3108,7 +3124,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
mpos.x = get_size().x - mpos.x;
}
if (select_identifiers_enabled) {
- if (!dragging_minimap && !dragging_selection && mm->get_command() && mm->get_button_mask() == 0) {
+ if (!dragging_minimap && !dragging_selection && mm->is_command_pressed() && mm->get_button_mask() == 0) {
String new_word = get_word_at_pos(mpos);
if (new_word != highlighted_word) {
emit_signal("symbol_validate", new_word);
@@ -3157,7 +3173,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
#ifdef OSX_ENABLED
if (k->get_keycode() == KEY_META) {
#else
- if (k->get_keycode() == KEY_CONTROL) {
+ if (k->get_keycode() == KEY_CTRL) {
#endif
if (select_identifiers_enabled) {
if (k->is_pressed() && !dragging_minimap && !dragging_selection) {
@@ -3175,7 +3191,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
// If a modifier has been pressed, and nothing else, return.
- if (k->get_keycode() == KEY_CONTROL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT || k->get_keycode() == KEY_META) {
+ if (k->get_keycode() == KEY_CTRL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT || k->get_keycode() == KEY_META) {
return;
}
@@ -3183,7 +3199,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
// Allow unicode handling if:
// * No Modifiers are pressed (except shift)
- bool allow_unicode_handling = !(k->get_command() || k->get_control() || k->get_alt() || k->get_metakey());
+ bool allow_unicode_handling = !(k->is_command_pressed() || k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed());
// Save here for insert mode, just in case it is cleared in the following section.
bool had_selection = selection.active;
@@ -3428,9 +3444,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
// CURSOR MOVEMENT
k = k->duplicate();
- bool shift_pressed = k->get_shift();
+ bool shift_pressed = k->is_shift_pressed();
// Remove shift or else actions will not match. Use above variable for selection.
- k->set_shift(false);
+ k->set_shift_pressed(false);
// CURSOR MOVEMENT - LEFT, RIGHT.
if (k->is_action("ui_text_caret_word_left", true)) {
@@ -4442,7 +4458,7 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
return CURSOR_POINTING_HAND;
}
- if ((completion_active && completion_rect.has_point(p_pos))) {
+ if ((completion_active && completion_rect.has_point(p_pos)) || (is_readonly() && (!is_selecting_enabled() || text.size() == 0))) {
return CURSOR_ARROW;
}
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 73fd9dbcd7..9e4c73679e 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -1388,7 +1388,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
}
- if ((select_mode == SELECT_ROW && selected_item == p_item) || p_item->cells[i].selected) {
+ if ((select_mode == SELECT_ROW && selected_item == p_item) || p_item->cells[i].selected || !p_item->has_meta("__focus_rect")) {
Rect2i r(cell_rect.position, cell_rect.size);
p_item->set_meta("__focus_rect", Rect2(r.position, r.size));
@@ -1672,7 +1672,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
float line_width = 1.0;
#ifdef TOOLS_ENABLED
- line_width *= EDSCALE;
+ line_width *= Math::round(EDSCALE);
#endif
Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + cache.arrow->get_height() / 2) - cache.offset + p_draw_ofs;
@@ -1866,7 +1866,7 @@ void Tree::_range_click_timeout() {
}
}
-int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_doubleclick, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod) {
+int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod) {
int item_h = compute_item_height(p_item) + cache.vseparation;
bool skip = (p_item == root && hide_root);
@@ -1963,7 +1963,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
if (p_button == MOUSE_BUTTON_LEFT || (p_button == MOUSE_BUTTON_RIGHT && allow_rmb_select)) {
/* process selection */
- if (p_doubleclick && (!c.editable || c.mode == TreeItem::CELL_MODE_CUSTOM || c.mode == TreeItem::CELL_MODE_ICON /*|| c.mode==TreeItem::CELL_MODE_CHECK*/)) { //it's confusing for check
+ if (p_double_click && (!c.editable || c.mode == TreeItem::CELL_MODE_CUSTOM || c.mode == TreeItem::CELL_MODE_ICON /*|| c.mode==TreeItem::CELL_MODE_CHECK*/)) { //it's confusing for check
propagate_mouse_activated = true;
@@ -1971,7 +1971,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
return -1;
}
- if (select_mode == SELECT_MULTI && p_mod->get_command() && c.selectable) {
+ if (select_mode == SELECT_MULTI && p_mod->is_command_pressed() && c.selectable) {
if (!c.selected || p_button == MOUSE_BUTTON_RIGHT) {
p_item->select(col);
emit_signal("multi_selected", p_item, col, true);
@@ -1988,7 +1988,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
} else {
if (c.selectable) {
- if (select_mode == SELECT_MULTI && p_mod->get_shift() && selected_item && selected_item != p_item) {
+ if (select_mode == SELECT_MULTI && p_mod->is_shift_pressed() && selected_item && selected_item != p_item) {
bool inrange = false;
select_single_item(p_item, root, col, selected_item, &inrange);
@@ -2167,7 +2167,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
TreeItem *c = p_item->children;
while (c) {
- int child_h = propagate_mouse_event(new_pos, x_ofs, y_ofs, p_doubleclick, c, p_button, p_mod);
+ int child_h = propagate_mouse_event(new_pos, x_ofs, y_ofs, p_double_click, c, p_button, p_mod);
if (child_h < 0) {
return -1; // break, stop propagating, no need to anymore
@@ -2406,7 +2406,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
Ref<InputEventKey> k = p_event;
- bool is_command = k.is_valid() && k->get_command();
+ bool is_command = k.is_valid() && k->is_command_pressed();
if (p_event->is_action("ui_right") && p_event->is_pressed()) {
if (!cursor_can_exit_tree) {
accept_event();
@@ -2415,7 +2415,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (!selected_item || select_mode == SELECT_ROW || selected_col > (columns.size() - 1)) {
return;
}
- if (k.is_valid() && k->get_alt()) {
+ if (k.is_valid() && k->is_alt_pressed()) {
selected_item->set_collapsed(false);
TreeItem *next = selected_item->get_children();
while (next && next != selected_item->next) {
@@ -2434,7 +2434,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
return;
}
- if (k.is_valid() && k->get_alt()) {
+ if (k.is_valid() && k->is_alt_pressed()) {
selected_item->set_collapsed(true);
TreeItem *next = selected_item->get_children();
while (next && next != selected_item->next) {
@@ -2564,7 +2564,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (!k->is_pressed()) {
return;
}
- if (k->get_command() || (k->get_shift() && k->get_unicode() == 0) || k->get_metakey()) {
+ if (k->is_command_pressed() || (k->is_shift_pressed() && k->get_unicode() == 0) || k->is_meta_pressed()) {
return;
}
if (!root) {
@@ -2846,7 +2846,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
propagate_mouse_activated = false;
blocked++;
- propagate_mouse_event(pos + cache.offset, 0, 0, b->is_doubleclick(), root, b->get_button_index(), b);
+ propagate_mouse_event(pos + cache.offset, 0, 0, b->is_double_click(), root, b->get_button_index(), b);
blocked--;
if (pressing_for_editor) {
@@ -2880,7 +2880,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
if (b->get_button_index() == MOUSE_BUTTON_LEFT) {
- if (get_item_at_position(b->get_position()) == nullptr && !b->get_shift() && !b->get_control() && !b->get_command()) {
+ if (get_item_at_position(b->get_position()) == nullptr && !b->is_shift_pressed() && !b->is_ctrl_pressed() && !b->is_command_pressed()) {
emit_signal("nothing_selected");
}
}
@@ -3013,6 +3013,10 @@ bool Tree::edit_selected() {
return false;
}
+bool Tree::is_editing() {
+ return popup_editor->is_visible();
+}
+
Size2 Tree::get_internal_min_size() const {
Size2i size = cache.bg->get_offset();
if (root) {
@@ -3174,7 +3178,6 @@ void Tree::_notification(int p_what) {
RID ci = get_canvas_item();
Ref<StyleBox> bg = cache.bg;
- Ref<StyleBox> bg_focus = get_theme_stylebox("bg_focus");
Color font_outline_color = get_theme_color("font_outline_color");
int outline_size = get_theme_constant("outline_size");
@@ -3183,11 +3186,6 @@ void Tree::_notification(int p_what) {
Size2 draw_size = get_size() - bg->get_minimum_size();
bg->draw(ci, Rect2(Point2(), get_size()));
- if (has_focus()) {
- RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, true);
- bg_focus->draw(ci, Rect2(Point2(), get_size()));
- RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false);
- }
int tbh = _get_title_button_height();
@@ -3221,6 +3219,15 @@ void Tree::_notification(int p_what) {
columns[i].text_buf->draw(ci, text_pos, cache.title_button_color);
}
}
+
+ // Draw the background focus outline last, so that it is drawn in front of the section headings.
+ // Otherwise, section heading backgrounds can appear to be in front of the focus outline when scrolling.
+ if (has_focus()) {
+ RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, true);
+ const Ref<StyleBox> bg_focus = get_theme_stylebox("bg_focus");
+ bg_focus->draw(ci, Rect2(Point2(), get_size()));
+ RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false);
+ }
}
if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED || p_what == NOTIFICATION_TRANSLATION_CHANGED) {
@@ -4262,7 +4269,7 @@ void Tree::_bind_methods() {
ADD_SIGNAL(MethodInfo("item_custom_button_pressed"));
ADD_SIGNAL(MethodInfo("item_double_clicked"));
ADD_SIGNAL(MethodInfo("item_collapsed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem")));
- //ADD_SIGNAL( MethodInfo("item_doubleclicked" ) );
+ //ADD_SIGNAL( MethodInfo("item_double_clicked" ) );
ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("custom_popup_edited", PropertyInfo(Variant::BOOL, "arrow_clicked")));
ADD_SIGNAL(MethodInfo("item_activated"));
@@ -4327,6 +4334,8 @@ Tree::Tree() {
set_mouse_filter(MOUSE_FILTER_STOP);
set_clip_contents(true);
+
+ update_cache();
}
Tree::~Tree() {
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index d1407e24d4..6d36f0df7f 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -390,7 +390,7 @@ private:
void draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color, int p_ol_size, const Color &p_ol_color);
int draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item);
void select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev = nullptr, bool *r_in_range = nullptr, bool p_force_deselect = false);
- int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_doubleclick, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod);
+ int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod);
void _text_editor_enter(String p_text);
void _text_editor_modal_close();
void value_editor_changed(double p_value);
@@ -604,6 +604,7 @@ public:
int get_item_offset(TreeItem *p_item) const;
Rect2 get_item_rect(TreeItem *p_item, int p_column = -1) const;
bool edit_selected();
+ bool is_editing();
// First item that starts with the text, from the current focused item down and wraps around.
TreeItem *search_item_text(const String &p_find, int *r_col = nullptr, bool p_selectable = false);
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 55529517f1..fa98a10a26 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -1210,7 +1210,7 @@ void CanvasItem::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask");
ADD_GROUP("Texture", "texture_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Inherit,Nearest,Linear,MipmapNearest,MipmapLinear,MipmapNearestAniso,MipmapLinearAniso"), "set_texture_filter", "get_texture_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Inherit,Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Aniso.,Linear Mipmap Aniso."), "set_texture_filter", "get_texture_filter");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "Inherit,Disabled,Enabled,Mirror"), "set_texture_repeat", "get_texture_repeat");
ADD_GROUP("Material", "");
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 08ab71e7fa..884696d58d 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -40,9 +40,7 @@ Error HTTPRequest::_request() {
}
Error HTTPRequest::_parse_url(const String &p_url) {
- url = p_url;
use_ssl = false;
-
request_string = "";
port = 80;
request_sent = false;
@@ -52,35 +50,20 @@ Error HTTPRequest::_parse_url(const String &p_url) {
downloaded.set(0);
redirections = 0;
- String url_lower = url.to_lower();
- if (url_lower.begins_with("http://")) {
- url = url.substr(7, url.length() - 7);
- } else if (url_lower.begins_with("https://")) {
- url = url.substr(8, url.length() - 8);
+ String scheme;
+ Error err = p_url.parse_url(scheme, url, port, request_string);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Error parsing URL: " + p_url + ".");
+ if (scheme == "https://") {
use_ssl = true;
- port = 443;
- } else {
- ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Malformed URL: " + url + ".");
+ } else if (scheme != "http://") {
+ ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Invalid URL scheme: " + scheme + ".");
}
-
- ERR_FAIL_COND_V_MSG(url.length() < 1, ERR_INVALID_PARAMETER, "URL too short: " + url + ".");
-
- int slash_pos = url.find("/");
-
- if (slash_pos != -1) {
- request_string = url.substr(slash_pos, url.length());
- url = url.substr(0, slash_pos);
- } else {
- request_string = "/";
+ if (port == 0) {
+ port = use_ssl ? 443 : 80;
}
-
- int colon_pos = url.find(":");
- if (colon_pos != -1) {
- port = url.substr(colon_pos + 1, url.length()).to_int();
- url = url.substr(0, colon_pos);
- ERR_FAIL_COND_V(port < 1 || port > 65535, ERR_INVALID_PARAMETER);
+ if (request_string.is_empty()) {
+ request_string = "/";
}
-
return OK;
}
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index b7313749d6..c90d3e4a32 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -591,7 +591,7 @@ Variant Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallEr
if (p_args[0]->get_type() != Variant::STRING_NAME) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
- r_error.expected = Variant::STRING;
+ r_error.expected = Variant::STRING_NAME;
return Variant();
}
@@ -620,7 +620,7 @@ Variant Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::Cal
if (p_args[1]->get_type() != Variant::STRING_NAME) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
- r_error.expected = Variant::STRING;
+ r_error.expected = Variant::STRING_NAME;
return Variant();
}
@@ -643,7 +643,7 @@ Variant Node::_rpc_unreliable_bind(const Variant **p_args, int p_argcount, Calla
if (p_args[0]->get_type() != Variant::STRING_NAME) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
- r_error.expected = Variant::STRING;
+ r_error.expected = Variant::STRING_NAME;
return Variant();
}
@@ -672,7 +672,7 @@ Variant Node::_rpc_unreliable_id_bind(const Variant **p_args, int p_argcount, Ca
if (p_args[1]->get_type() != Variant::STRING_NAME) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
- r_error.expected = Variant::STRING;
+ r_error.expected = Variant::STRING_NAME;
return Variant();
}
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index f1613f2fe5..62e1223fb0 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -617,10 +617,10 @@ void Viewport::_process_picking() {
mm->set_device(InputEvent::DEVICE_ID_INTERNAL);
mm->set_global_position(physics_last_mousepos);
mm->set_position(physics_last_mousepos);
- mm->set_alt(physics_last_mouse_state.alt);
- mm->set_shift(physics_last_mouse_state.shift);
- mm->set_control(physics_last_mouse_state.control);
- mm->set_metakey(physics_last_mouse_state.meta);
+ mm->set_alt_pressed(physics_last_mouse_state.alt);
+ mm->set_shift_pressed(physics_last_mouse_state.shift);
+ mm->set_ctrl_pressed(physics_last_mouse_state.control);
+ mm->set_meta_pressed(physics_last_mouse_state.meta);
mm->set_button_mask(physics_last_mouse_state.mouse_mask);
physics_picking_events.push_back(mm);
}
@@ -641,10 +641,10 @@ void Viewport::_process_picking() {
physics_has_last_mousepos = true;
physics_last_mousepos = pos;
- physics_last_mouse_state.alt = mm->get_alt();
- physics_last_mouse_state.shift = mm->get_shift();
- physics_last_mouse_state.control = mm->get_control();
- physics_last_mouse_state.meta = mm->get_metakey();
+ physics_last_mouse_state.alt = mm->is_alt_pressed();
+ physics_last_mouse_state.shift = mm->is_shift_pressed();
+ physics_last_mouse_state.control = mm->is_ctrl_pressed();
+ physics_last_mouse_state.meta = mm->is_meta_pressed();
physics_last_mouse_state.mouse_mask = mm->get_button_mask();
}
@@ -656,10 +656,10 @@ void Viewport::_process_picking() {
physics_has_last_mousepos = true;
physics_last_mousepos = pos;
- physics_last_mouse_state.alt = mb->get_alt();
- physics_last_mouse_state.shift = mb->get_shift();
- physics_last_mouse_state.control = mb->get_control();
- physics_last_mouse_state.meta = mb->get_metakey();
+ physics_last_mouse_state.alt = mb->is_alt_pressed();
+ physics_last_mouse_state.shift = mb->is_shift_pressed();
+ physics_last_mouse_state.control = mb->is_ctrl_pressed();
+ physics_last_mouse_state.meta = mb->is_meta_pressed();
if (mb->is_pressed()) {
physics_last_mouse_state.mouse_mask |= (1 << (mb->get_button_index() - 1));
@@ -676,10 +676,10 @@ void Viewport::_process_picking() {
Ref<InputEventKey> k = ev;
if (k.is_valid()) {
//only for mask
- physics_last_mouse_state.alt = k->get_alt();
- physics_last_mouse_state.shift = k->get_shift();
- physics_last_mouse_state.control = k->get_control();
- physics_last_mouse_state.meta = k->get_metakey();
+ physics_last_mouse_state.alt = k->is_alt_pressed();
+ physics_last_mouse_state.shift = k->is_shift_pressed();
+ physics_last_mouse_state.control = k->is_ctrl_pressed();
+ physics_last_mouse_state.meta = k->is_meta_pressed();
continue;
}
@@ -1412,6 +1412,16 @@ void Viewport::_update_canvas_items(Node *p_node) {
}
}
+void Viewport::set_use_xr(bool p_use_xr) {
+ use_xr = p_use_xr;
+
+ RS::get_singleton()->viewport_set_use_xr(viewport, use_xr);
+}
+
+bool Viewport::is_using_xr() {
+ return use_xr;
+}
+
Ref<ViewportTexture> Viewport::get_texture() const {
return default_texture;
}
@@ -1830,6 +1840,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Control *over = nullptr;
Point2 mpos = mb->get_position();
+ gui.last_mouse_pos = mpos;
if (mb->is_pressed()) {
Size2 pos = mpos;
if (gui.mouse_focus_mask) {
@@ -2391,10 +2402,10 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Control *from = gui.key_focus ? gui.key_focus : nullptr; //hmm
//keyboard focus
- //if (from && p_event->is_pressed() && !p_event->get_alt() && !p_event->get_metakey() && !p_event->key->get_command()) {
+ //if (from && p_event->is_pressed() && !p_event->is_alt_pressed() && !p_event->is_meta_pressed() && !p_event->key->is_command_pressed()) {
Ref<InputEventKey> k = p_event;
//need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/right/etc> is handled here when it shouldn't be.
- bool mods = k.is_valid() && (k->get_control() || k->get_alt() || k->get_shift() || k->get_metakey());
+ bool mods = k.is_valid() && (k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_shift_pressed() || k->is_meta_pressed());
if (from && p_event->is_pressed()) {
Control *next = nullptr;
@@ -3498,6 +3509,9 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_render_info", "info"), &Viewport::get_render_info);
+ ClassDB::bind_method(D_METHOD("set_use_xr", "use"), &Viewport::set_use_xr);
+ ClassDB::bind_method(D_METHOD("is_using_xr"), &Viewport::is_using_xr);
+
ClassDB::bind_method(D_METHOD("get_texture"), &Viewport::get_texture);
ClassDB::bind_method(D_METHOD("set_physics_object_picking", "enable"), &Viewport::set_physics_object_picking);
@@ -3578,6 +3592,7 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("_process_picking"), &Viewport::_process_picking);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_3d", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", 0), "set_world_2d", "get_world_2d");
@@ -3593,7 +3608,7 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_lod_threshold", "get_lod_threshold");
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
ADD_GROUP("Canvas Items", "canvas_item_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,MipmapLinear,MipmapNearest"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter");
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirror"), "set_default_canvas_item_texture_repeat", "get_default_canvas_item_texture_repeat");
ADD_GROUP("Audio Listener", "audio_listener_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_2d"), "set_as_audio_listener_2d", "is_audio_listener_2d");
@@ -3746,16 +3761,6 @@ Viewport::~Viewport() {
/////////////////////////////////
-void SubViewport::set_use_xr(bool p_use_xr) {
- xr = p_use_xr;
-
- RS::get_singleton()->viewport_set_use_xr(get_viewport_rid(), xr);
-}
-
-bool SubViewport::is_using_xr() {
- return xr;
-}
-
void SubViewport::set_size(const Size2i &p_size) {
_set_size(p_size, _get_size_2d_override(), Rect2i(), _stretch_transform(), true);
}
@@ -3828,9 +3833,6 @@ void SubViewport::_notification(int p_what) {
}
void SubViewport::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_use_xr", "use"), &SubViewport::set_use_xr);
- ClassDB::bind_method(D_METHOD("is_using_xr"), &SubViewport::is_using_xr);
-
ClassDB::bind_method(D_METHOD("set_size", "size"), &SubViewport::set_size);
ClassDB::bind_method(D_METHOD("get_size"), &SubViewport::get_size);
@@ -3846,7 +3848,6 @@ void SubViewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_clear_mode", "mode"), &SubViewport::set_clear_mode);
ClassDB::bind_method(D_METHOD("get_clear_mode"), &SubViewport::get_clear_mode);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "xr"), "set_use_xr", "is_using_xr");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size_2d_override"), "set_size_2d_override", "get_size_2d_override");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "size_2d_override_stretch"), "set_size_2d_override_stretch", "is_size_2d_override_stretch_enabled");
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 6786b70a6b..2e88e1251d 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -234,6 +234,7 @@ private:
Size2i size;
Size2i size_2d_override;
bool size_allocated = false;
+ bool use_xr = false;
RID contact_2d_debug;
RID contact_3d_debug_multimesh;
@@ -534,6 +535,9 @@ public:
void set_transparent_background(bool p_enable);
bool has_transparent_background() const;
+ void set_use_xr(bool p_use_xr);
+ bool is_using_xr();
+
Ref<ViewportTexture> get_texture() const;
void set_shadow_atlas_size(int p_size);
@@ -656,7 +660,6 @@ public:
private:
UpdateMode update_mode = UPDATE_WHEN_VISIBLE;
ClearMode clear_mode = CLEAR_MODE_ALWAYS;
- bool xr = false;
bool size_2d_override_stretch = false;
protected:
@@ -672,9 +675,6 @@ public:
void set_size_2d_override(const Size2i &p_size);
Size2i get_size_2d_override() const;
- void set_use_xr(bool p_use_xr);
- bool is_using_xr();
-
void set_size_2d_override_stretch(bool p_enable);
bool is_size_2d_override_stretch_enabled() const;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index b16532676f..f24ea7e39b 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -655,6 +655,9 @@ void register_scene_types() {
ClassDB::register_class<GrooveJoint2D>();
ClassDB::register_class<DampedSpringJoint2D>();
ClassDB::register_class<TileSet>();
+ ClassDB::register_virtual_class<TileSetSource>();
+ ClassDB::register_class<TileSetAtlasSource>();
+ ClassDB::register_class<TileData>();
ClassDB::register_class<TileMap>();
ClassDB::register_class<ParallaxBackground>();
ClassDB::register_class<ParallaxLayer>();
@@ -976,6 +979,7 @@ void register_scene_types() {
// Always make the default theme to avoid invalid default font/icon/style in the given theme.
if (RenderingServer::get_singleton()) {
make_default_theme(default_theme_hidpi, font);
+ ColorPicker::init_shaders(); // RenderingServer needs to exist for this to succeed.
}
if (theme_path != String()) {
@@ -1032,5 +1036,6 @@ void unregister_scene_types() {
ParticlesMaterial::finish_shaders();
CanvasItemMaterial::finish_shaders();
+ ColorPicker::finish_shaders();
SceneStringNames::free();
}
diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp
index e9bfac3653..0ffeb8a5bf 100644
--- a/scene/resources/bit_map.cpp
+++ b/scene/resources/bit_map.cpp
@@ -38,7 +38,7 @@ void BitMap::create(const Size2 &p_size) {
width = p_size.width;
height = p_size.height;
- bitmask.resize(((width * height) / 8) + 1);
+ bitmask.resize((((width * height) - 1) / 8) + 1);
memset(bitmask.ptrw(), 0, bitmask.size());
}
diff --git a/scene/resources/default_theme/SCsub b/scene/resources/default_theme/SCsub
index fc61250247..0fb6bb2c62 100644
--- a/scene/resources/default_theme/SCsub
+++ b/scene/resources/default_theme/SCsub
@@ -2,4 +2,16 @@
Import("env")
+import os
+import os.path
+from platform_methods import run_in_subprocess
+import default_theme_builders
+
env.add_source_files(env.scene_sources, "*.cpp")
+
+env.Depends("#scene/resources/default_theme/default_font.gen.h", "#thirdparty/fonts/OpenSans_SemiBold.ttf")
+env.CommandNoCache(
+ "#scene/resources/default_theme/default_font.gen.h",
+ "#thirdparty/fonts/OpenSans_SemiBold.ttf",
+ run_in_subprocess(default_theme_builders.make_fonts_header),
+)
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 7c00c6d146..b671ee4644 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -30,15 +30,12 @@
#include "default_theme.h"
-#include "scene/resources/theme.h"
-
#include "core/os/os.h"
-#include "theme_data.h"
-
-#include "font_hidpi.inc"
-#include "font_lodpi.inc"
-
+#include "default_font.gen.h"
+#include "scene/resources/font.h"
+#include "scene/resources/theme.h"
#include "servers/text_server.h"
+#include "theme_data.h"
typedef Map<const void *, Ref<ImageTexture>> TexCacheMap;
@@ -128,38 +125,6 @@ static Ref<Texture2D> flip_icon(Ref<Texture2D> p_texture, bool p_flip_y = false,
return texture;
}
-static Ref<FontData> make_font(int p_height, int p_ascent, int p_charcount, const int *p_char_rects, int p_kerning_count, const int *p_kernings, int p_w, int p_h, const unsigned char *p_img) {
- Ref<FontData> font(memnew(FontData));
- font->new_bitmap(p_height, p_ascent, p_height);
-
- Ref<Image> image = memnew(Image(p_img));
- Ref<ImageTexture> tex = memnew(ImageTexture);
- tex->create_from_image(image);
-
- font->bitmap_add_texture(tex);
-
- for (int i = 0; i < p_charcount; i++) {
- const int *c = &p_char_rects[i * 8];
-
- int chr = c[0];
- Rect2 frect;
- frect.position.x = c[1];
- frect.position.y = c[2];
- frect.size.x = c[3];
- frect.size.y = c[4];
- Point2 align(c[6], c[5]);
- int advance = c[7];
-
- font->bitmap_add_char(chr, 0, frect, align, advance);
- }
-
- for (int i = 0; i < p_kerning_count; i++) {
- font->bitmap_add_kerning_pair(p_kernings[i * 3 + 0], p_kernings[i * 3 + 1], p_kernings[i * 3 + 2]);
- }
-
- return font;
-}
-
static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) {
Ref<StyleBox> style(memnew(StyleBoxEmpty));
@@ -1024,18 +989,25 @@ void make_default_theme(bool p_hidpi, Ref<Font> p_font) {
Ref<StyleBox> default_style;
Ref<Texture2D> default_icon;
Ref<Font> default_font;
- int default_font_size = 14;
+ int default_font_size = 16;
if (p_font.is_valid()) {
+ // Use the custom font defined in the Project Settings.
default_font = p_font;
- } else if (p_hidpi) {
- Ref<FontData> font_data = make_font(_hidpi_font_height, _hidpi_font_ascent, _hidpi_font_charcount, &_hidpi_font_charrects[0][0], _hidpi_font_kerning_pair_count, &_hidpi_font_kerning_pairs[0][0], _hidpi_font_img_width, _hidpi_font_img_height, _hidpi_font_img_data);
- default_font.instance();
- default_font->add_data(font_data);
} else {
- Ref<FontData> font_data = make_font(_lodpi_font_height, _lodpi_font_ascent, _lodpi_font_charcount, &_lodpi_font_charrects[0][0], _lodpi_font_kerning_pair_count, &_lodpi_font_kerning_pairs[0][0], _lodpi_font_img_width, _lodpi_font_img_height, _lodpi_font_img_data);
- default_font.instance();
- default_font->add_data(font_data);
+ // Use the default DynamicFont (separate from the editor font).
+ // The default DynamicFont is chosen to have a small file size since it's
+ // embedded in both editor and export template binaries.
+ Ref<Font> dynamic_font;
+ dynamic_font.instance();
+
+ Ref<FontData> dynamic_font_data;
+ dynamic_font_data.instance();
+ dynamic_font_data->load_memory(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size, "ttf", default_font_size);
+ dynamic_font->add_data(dynamic_font_data);
+
+ default_font = dynamic_font;
}
+
Ref<Font> large_font = default_font;
fill_default_theme(t, default_font, large_font, default_icon, default_style, p_hidpi ? 2.0 : 1.0);
diff --git a/scene/resources/default_theme/default_theme_builders.py b/scene/resources/default_theme/default_theme_builders.py
new file mode 100644
index 0000000000..0455d6d246
--- /dev/null
+++ b/scene/resources/default_theme/default_theme_builders.py
@@ -0,0 +1,40 @@
+"""Functions used to generate source files during build time
+
+All such functions are invoked in a subprocess on Windows to prevent build flakiness.
+
+"""
+import os
+import os.path
+from platform_methods import subprocess_main
+
+
+def make_fonts_header(target, source, env):
+ dst = target[0]
+
+ g = open(dst, "w", encoding="utf-8")
+
+ g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
+ g.write("#ifndef _DEFAULT_FONTS_H\n")
+ g.write("#define _DEFAULT_FONTS_H\n")
+
+ # Saving uncompressed, since FreeType will reference from memory pointer.
+ for i in range(len(source)):
+ with open(source[i], "rb") as f:
+ buf = f.read()
+
+ name = os.path.splitext(os.path.basename(source[i]))[0]
+
+ g.write("static const int _font_" + name + "_size = " + str(len(buf)) + ";\n")
+ g.write("static const unsigned char _font_" + name + "[] = {\n")
+ for j in range(len(buf)):
+ g.write("\t" + str(buf[j]) + ",\n")
+
+ g.write("};\n")
+
+ g.write("#endif")
+
+ g.close()
+
+
+if __name__ == "__main__":
+ subprocess_main(globals())
diff --git a/scene/resources/default_theme/font_hidpi.inc b/scene/resources/default_theme/font_hidpi.inc
deleted file mode 100644
index 4860149e6b..0000000000
--- a/scene/resources/default_theme/font_hidpi.inc
+++ /dev/null
@@ -1,25463 +0,0 @@
-/* clang-format off */
-static const int _hidpi_font_height=25;
-static const int _hidpi_font_ascent=19;
-static const int _hidpi_font_charcount=191;
-static const int _hidpi_font_charrects[191][8]={
-/* charidx , ofs_x, ofs_y, size_x, size_y, valign, halign, advance */
-{192,63,23,16,23,-4,-1,15},
-{224,184,182,10,19,0,1,13},
-{64,98,2,18,19,2,1,21},
-{96,159,234,5,4,0,5,14},
-{160,0,0,0,0,19,0,6},
-{32,0,0,0,0,19,0,6},
-{33,2,249,3,17,2,2,6},
-{193,83,25,16,23,-4,-1,15},
-{225,92,160,10,19,0,1,13},
-{65,163,23,16,17,2,-1,15},
-{161,246,236,3,17,6,2,6},
-{97,142,190,10,13,6,1,13},
-{162,67,214,9,17,2,2,13},
-{98,242,136,11,18,1,2,14},
-{194,103,25,16,23,-4,-1,15},
-{226,106,160,10,19,0,1,13},
-{66,122,146,11,17,2,2,15},
-{34,226,203,8,6,2,1,10},
-{35,189,44,14,17,2,1,16},
-{163,62,166,11,17,2,1,13},
-{195,123,23,16,23,-4,-1,15},
-{227,134,167,10,19,0,1,13},
-{67,209,65,12,17,2,1,14},
-{99,225,186,9,13,6,1,11},
-{228,170,182,10,18,1,1,13},
-{100,227,143,11,18,1,1,14},
-{196,23,23,16,22,-3,-1,15},
-{36,2,179,10,20,1,2,13},
-{68,193,65,12,17,2,2,16},
-{164,176,65,13,12,5,0,13},
-{37,120,2,18,17,2,1,20},
-{69,41,222,9,17,2,2,13},
-{165,98,99,12,17,2,1,13},
-{197,43,23,16,21,-2,-1,15},
-{229,16,179,10,20,-1,1,13},
-{101,189,109,11,13,6,1,13},
-{38,183,23,16,17,2,1,17},
-{70,54,222,9,17,2,2,12},
-{198,75,2,19,17,2,-1,20},
-{102,202,212,8,18,1,1,8},
-{166,44,268,2,24,1,6,13},
-{230,142,2,18,13,6,1,20},
-{71,2,71,14,17,2,1,17},
-{167,176,160,10,18,1,0,12},
-{199,146,94,12,23,2,1,14},
-{103,159,67,13,19,6,0,13},
-{231,212,189,9,19,6,1,11},
-{39,30,271,3,6,2,1,5},
-{72,130,99,12,17,2,2,17},
-{104,162,160,10,18,1,2,14},
-{200,238,186,9,23,-4,2,13},
-{40,46,243,7,21,2,1,7},
-{232,2,156,11,19,0,1,13},
-{168,68,235,7,3,1,4,14},
-{73,106,209,8,17,2,0,9},
-{169,230,2,17,17,2,1,20},
-{105,222,232,4,18,1,1,6},
-{201,28,222,9,23,-4,2,13},
-{41,130,238,6,21,2,0,7},
-{233,197,126,11,19,0,1,13},
-{202,93,209,9,23,-4,2,13},
-{74,13,225,7,22,2,-2,7},
-{234,167,137,11,19,0,1,13},
-{42,82,120,12,11,1,0,13},
-{170,100,236,6,8,2,1,8},
-{106,110,237,6,24,1,-1,6},
-{171,144,121,11,10,8,0,12},
-{43,2,119,12,12,5,1,13},
-{203,80,209,9,22,-3,2,13},
-{107,32,177,11,18,1,2,12},
-{235,77,166,11,18,1,1,13},
-{75,74,77,13,17,2,2,14},
-{44,230,213,4,6,16,1,6},
-{172,204,109,11,7,10,1,13},
-{236,204,234,5,19,0,0,6},
-{204,130,211,8,23,-4,0,9},
-{108,23,271,3,18,1,2,6},
-{76,86,188,10,17,2,2,12},
-{173,140,238,6,2,12,1,8},
-{45,120,237,6,2,12,1,8},
-{109,208,2,18,13,6,2,22},
-{205,178,205,8,23,-4,0,9},
-{237,213,234,5,19,0,2,6},
-{77,143,19,16,17,2,2,21},
-{46,9,251,3,3,16,2,6},
-{110,100,183,10,13,6,2,14},
-{206,154,207,8,23,-4,0,9},
-{238,238,213,8,19,0,-1,6},
-{174,2,23,17,17,2,1,20},
-{78,91,78,13,17,2,2,18},
-{175,18,125,12,2,-1,0,12},
-{111,162,90,12,13,6,1,14},
-{207,118,211,8,22,-3,0,9},
-{239,24,249,7,18,1,0,6},
-{79,203,23,15,17,2,1,18},
-{47,120,167,10,17,2,-1,9},
-{176,166,207,8,8,2,1,10},
-{112,212,143,11,19,6,2,14},
-{240,18,103,12,18,1,1,14},
-{208,171,44,14,17,2,0,16},
-{80,128,190,10,17,2,2,14},
-{48,234,115,11,17,2,1,13},
-{177,66,127,12,14,5,1,13},
-{113,182,126,11,19,6,1,14},
-{241,30,199,10,19,0,2,14},
-{81,97,52,15,22,2,1,18},
-{209,142,67,13,23,-4,2,18},
-{49,57,243,7,17,2,2,13},
-{178,190,206,8,10,2,0,8},
-{114,142,207,8,13,6,2,10},
-{242,242,87,12,19,0,1,14},
-{210,59,50,15,23,-4,1,18},
-{82,82,99,12,17,2,2,14},
-{50,2,135,11,17,2,1,13},
-{179,35,249,7,10,2,0,8},
-{115,72,188,10,13,6,0,11},
-{243,226,92,12,19,0,1,14},
-{211,40,49,15,23,-4,1,18},
-{83,129,125,11,17,2,0,13},
-{51,17,135,11,17,2,1,13},
-{180,168,219,5,4,0,5,14},
-{116,214,212,8,16,3,0,8},
-{244,194,86,12,19,0,1,14},
-{212,21,49,15,23,-4,1,18},
-{84,66,106,12,17,2,0,13},
-{52,125,78,13,17,2,0,13},
-{53,32,156,11,17,2,1,13},
-{85,50,106,12,17,2,2,17},
-{181,204,166,10,19,6,2,14},
-{117,198,189,10,13,6,2,14},
-{245,178,86,12,19,0,1,14},
-{213,2,44,15,23,-4,1,18},
-{54,47,156,11,17,2,1,13},
-{86,222,23,15,17,2,-1,14},
-{246,241,65,12,18,1,1,14},
-{214,116,52,15,22,-3,1,18},
-{182,34,131,12,21,1,1,16},
-{118,135,50,14,13,6,-1,12},
-{55,62,145,11,17,2,1,13},
-{87,2,2,22,17,2,-1,21},
-{119,28,2,20,13,6,-1,18},
-{215,114,125,11,11,5,1,13},
-{247,210,92,12,10,6,0,13},
-{183,16,251,3,3,9,2,6},
-{56,77,145,11,17,2,1,13},
-{88,225,44,14,17,2,-1,13},
-{216,78,52,15,19,1,1,18},
-{248,98,120,12,15,5,1,14},
-{120,50,127,12,13,6,0,12},
-{184,150,234,5,6,19,0,5},
-{89,207,44,14,17,2,-1,13},
-{121,153,44,14,19,6,-1,12},
-{217,225,65,12,23,-4,2,17},
-{249,44,199,10,19,0,2,14},
-{57,92,139,11,17,2,1,13},
-{185,177,232,5,10,2,0,8},
-{218,2,92,12,23,-4,2,17},
-{250,156,184,10,19,0,2,14},
-{90,232,165,10,17,2,1,13},
-{122,148,167,10,13,6,1,11},
-{58,37,263,3,13,6,2,6},
-{186,90,236,6,8,2,1,8},
-{219,34,104,12,23,-4,2,17},
-{123,2,224,7,21,2,1,9},
-{91,186,232,5,21,2,2,7},
-{251,58,191,10,19,0,2,14},
-{59,238,236,4,16,6,1,6},
-{187,47,177,11,10,8,1,12},
-{188,164,2,18,17,2,0,18},
-{252,190,149,10,18,1,2,14},
-{124,50,268,2,24,1,6,13},
-{220,114,99,12,22,-3,2,17},
-{92,137,146,11,17,2,-1,9},
-{60,159,121,11,12,5,1,13},
-{189,186,2,18,17,2,0,18},
-{253,56,77,14,25,0,-1,12},
-{221,20,76,14,23,-4,-1,13},
-{125,79,235,7,21,2,1,9},
-{93,195,234,5,21,2,0,7},
-{61,152,137,11,6,8,1,13},
-{190,52,2,19,17,2,0,18},
-{222,114,188,10,17,2,2,14},
-{254,219,115,11,24,1,2,14},
-{62,174,109,11,12,5,1,13},
-{94,108,78,13,11,2,0,13},
-{126,107,140,11,5,8,1,13},
-{223,17,156,11,18,1,2,14},
-{191,15,203,9,18,6,0,10},
-{255,38,76,14,24,1,-1,12},
-{63,2,203,9,17,2,0,10},
-{95,218,166,10,2,21,0,10},
-};
-static const int _hidpi_font_kerning_pair_count=0;
-static const int _hidpi_font_kerning_pairs[1][3]={
-{0,0,0}
-};
-static const int _hidpi_font_img_width=256;
-static const int _hidpi_font_img_height=512;
-static const int _hidpi_font_img_data_size=25255;
-static const unsigned char _hidpi_font_img_data[25255]={
-137,
-80,
-78,
-71,
-13,
-10,
-26,
-10,
-0,
-0,
-0,
-13,
-73,
-72,
-68,
-82,
-0,
-0,
-1,
-0,
-0,
-0,
-2,
-0,
-8,
-6,
-0,
-0,
-0,
-109,
-154,
-178,
-251,
-0,
-0,
-32,
-0,
-73,
-68,
-65,
-84,
-120,
-156,
-236,
-157,
-119,
-184,
-38,
-53,
-245,
-199,
-51,
-84,
-165,
-55,
-1,
-21,
-16,
-41,
-34,
-42,
-130,
-98,
-23,
-1,
-21,
-20,
-84,
-108,
-40,
-138,
-138,
-10,
-34,
-40,
-86,
-148,
-159,
-216,
-11,
-34,
-138,
-130,
-162,
-40,
-32,
-160,
-128,
-160,
-2,
-162,
-32,
-162,
-34,
-34,
-29,
-145,
-142,
-235,
-210,
-219,
-210,
-151,
-14,
-219,
-251,
-231,
-247,
-199,
-57,
-97,
-114,
-231,
-205,
-204,
-100,
-102,
-50,
-239,
-189,
-119,
-111,
-190,
-207,
-179,
-207,
-221,
-55,
-57,
-57,
-147,
-153,
-73,
-206,
-36,
-39,
-167,
-24,
-147,
-144,
-144,
-144,
-144,
-144,
-144,
-48,
-129,
-1,
-172,
-75,
-142,
-45,
-74,
-104,
-158,
-231,
-208,
-188,
-176,
-132,
-230,
-85,
-14,
-205,
-58,
-158,
-250,
-245,
-156,
-250,
-103,
-121,
-234,
-95,
-237,
-212,
-239,
-225,
-169,
-95,
-25,
-88,
-160,
-245,
-235,
-122,
-234,
-55,
-5,
-78,
-0,
-238,
-5,
-230,
-2,
-83,
-128,
-95,
-2,
-107,
-149,
-244,
-119,
-105,
-224,
-22,
-224,
-65,
-96,
-37,
-31,
-77,
-8,
-128,
-143,
-211,
-0,
-129,
-60,
-215,
-1,
-190,
-8,
-156,
-15,
-220,
-13,
-204,
-1,
-30,
-7,
-38,
-1,
-63,
-3,
-182,
-12,
-228,
-243,
-33,
-224,
-102,
-109,
-255,
-63,
-224,
-109,
-21,
-180,
-235,
-3,
-179,
-244,
-249,
-173,
-88,
-195,
-119,
-109,
-224,
-43,
-192,
-101,
-192,
-19,
-250,
-188,
-239,
-5,
-126,
-3,
-108,
-160,
-52,
-27,
-0,
-191,
-7,
-30,
-86,
-190,
-215,
-0,
-159,
-0,
-150,
-168,
-224,
-187,
-42,
-112,
-172,
-62,
-170,
-211,
-42,
-232,
-26,
-189,
-187,
-62,
-248,
-42,
-175,
-235,
-244,
-255,
-239,
-211,
-103,
-49,
-67,
-223,
-211,
-133,
-246,
-89,
-3,
-75,
-0,
-159,
-5,
-174,
-211,
-231,
-240,
-36,
-240,
-79,
-224,
-117,
-117,
-253,
-214,
-246,
-43,
-105,
-251,
-127,
-1,
-143,
-0,
-243,
-245,
-239,
-185,
-192,
-103,
-234,
-222,
-85,
-16,
-128,
-27,
-244,
-134,
-246,
-45,
-169,
-255,
-164,
-51,
-134,
-247,
-41,
-161,
-249,
-138,
-214,
-79,
-174,
-184,
-206,
-205,
-74,
-243,
-126,
-79,
-221,
-33,
-206,
-53,
-78,
-247,
-212,
-239,
-164,
-117,
-55,
-150,
-240,
-254,
-43,
-48,
-93,
-7,
-225,
-87,
-129,
-95,
-1,
-139,
-128,
-127,
-149,
-208,
-127,
-65,
-249,
-125,
-188,
-172,
-191,
-33,
-0,
-174,
-5,
-22,
-2,
-151,
-56,
-253,
-191,
-86,
-127,
-15,
-252,
-171,
-225,
-245,
-52,
-224,
-251,
-192,
-108,
-229,
-115,
-43,
-112,
-6,
-112,
-52,
-112,
-18,
-112,
-149,
-94,
-11,
-224,
-52,
-96,
-149,
-10,
-94,
-175,
-215,
-251,
-183,
-130,
-240,
-126,
-29,
-60,
-94,
-225,
-1,
-156,
-165,
-124,
-119,
-14,
-184,
-231,
-43,
-149,
-118,
-1,
-112,
-35,
-112,
-5,
-50,
-209,
-1,
-30,
-211,
-107,
-63,
-166,
-191,
-239,
-214,
-241,
-101,
-251,
-125,
-98,
-9,
-207,
-247,
-2,
-83,
-129,
-187,
-128,
-153,
-84,
-79,
-212,
-224,
-119,
-215,
-35,
-95,
-144,
-9,
-253,
-85,
-253,
-255,
-125,
-250,
-126,
-158,
-212,
-223,
-139,
-128,
-157,
-245,
-61,
-161,
-215,
-191,
-70,
-251,
-128,
-190,
-139,
-87,
-215,
-92,
-99,
-39,
-224,
-81,
-100,
-194,
-31,
-13,
-236,
-14,
-188,
-93,
-255,
-30,
-173,
-229,
-143,
-80,
-33,
-216,
-131,
-0,
-28,
-166,
-157,
-250,
-75,
-73,
-253,
-105,
-136,
-148,
-159,
-11,
-156,
-82,
-66,
-115,
-142,
-242,
-56,
-164,
-226,
-58,
-63,
-87,
-154,
-35,
-60,
-117,
-183,
-235,
-96,
-189,
-18,
-145,
-164,
-79,
-43,
-212,
-31,
-170,
-109,
-127,
-90,
-194,
-123,
-85,
-96,
-181,
-66,
-217,
-121,
-192,
-116,
-15,
-237,
-26,
-136,
-164,
-254,
-47,
-21,
-95,
-164,
-58,
-0,
-175,
-209,
-62,
-253,
-85,
-127,
-91,
-120,
-87,
-82,
-53,
-188,
-214,
-0,
-254,
-173,
-237,
-79,
-1,
-94,
-80,
-66,
-183,
-46,
-240,
-107,
-165,
-187,
-17,
-88,
-181,
-132,
-238,
-79,
-74,
-179,
-137,
-254,
-126,
-169,
-254,
-62,
-201,
-67,
-251,
-110,
-247,
-62,
-2,
-250,
-250,
-38,
-224,
-115,
-238,
-243,
-70,
-190,
-158,
-71,
-58,
-131,
-127,
-33,
-176,
-139,
-83,
-255,
-34,
-100,
-34,
-2,
-188,
-215,
-195,
-243,
-64,
-224,
-183,
-192,
-234,
-84,
-76,
-212,
-166,
-239,
-174,
-71,
-190,
-22,
-243,
-129,
-15,
-58,
-229,
-203,
-33,
-31,
-35,
-128,
-121,
-200,
-234,
-235,
-237,
-133,
-235,
-92,
-163,
-245,
-103,
-84,
-240,
-255,
-178,
-62,
-195,
-31,
-0,
-43,
-148,
-208,
-172,
-0,
-28,
-172,
-116,
-95,
-174,
-235,
-115,
-213,
-205,
-236,
-168,
-29,
-122,
-18,
-88,
-178,
-80,
-183,
-4,
-34,
-133,
-174,
-212,
-127,
-15,
-120,
-218,
-47,
-67,
-46,
-217,
-182,
-171,
-184,
-206,
-59,
-148,
-102,
-114,
-161,
-124,
-11,
-45,
-63,
-94,
-111,
-24,
-224,
-45,
-5,
-154,
-171,
-181,
-188,
-86,
-218,
-33,
-95,
-210,
-215,
-35,
-203,
-211,
-223,
-122,
-234,
-127,
-161,
-188,
-222,
-80,
-199,
-171,
-230,
-58,
-191,
-85,
-62,
-239,
-208,
-223,
-22,
-141,
-4,
-0,
-176,
-20,
-178,
-66,
-152,
-15,
-236,
-22,
-216,
-102,
-95,
-189,
-214,
-159,
-75,
-234,
-239,
-5,
-110,
-45,
-148,
-221,
-9,
-220,
-89,
-40,
-91,
-1,
-184,
-7,
-249,
-154,
-61,
-183,
-73,
-191,
-61,
-215,
-92,
-203,
-121,
-6,
-199,
-121,
-234,
-247,
-215,
-186,
-127,
-212,
-240,
-129,
-242,
-137,
-218,
-250,
-221,
-197,
-228,
-235,
-220,
-231,
-209,
-158,
-186,
-45,
-156,
-250,
-67,
-61,
-245,
-239,
-209,
-186,
-7,
-75,
-120,
-239,
-132,
-76,
-234,
-93,
-245,
-247,
-18,
-192,
-222,
-200,
-252,
-155,
-137,
-204,
-199,
-75,
-128,
-79,
-107,
-253,
-110,
-74,
-223,
-110,
-37,
-128,
-72,
-173,
-57,
-218,
-169,
-87,
-20,
-234,
-236,
-151,
-227,
-112,
-231,
-33,
-109,
-82,
-160,
-217,
-74,
-203,
-103,
-0,
-203,
-86,
-92,
-103,
-37,
-29,
-228,
-139,
-128,
-213,
-157,
-242,
-3,
-180,
-253,
-135,
-145,
-175,
-11,
-192,
-145,
-78,
-253,
-202,
-122,
-131,
-243,
-40,
-145,
-134,
-14,
-173,
-139,
-127,
-22,
-251,
-3,
-188,
-0,
-89,
-186,
-122,
-39,
-78,
-40,
-128,
-103,
-32,
-43,
-162,
-251,
-80,
-161,
-233,
-92,
-183,
-169,
-0,
-248,
-134,
-182,
-251,
-124,
-195,
-118,
-118,
-121,
-249,
-90,
-79,
-221,
-60,
-224,
-226,
-66,
-217,
-165,
-192,
-220,
-66,
-217,
-143,
-149,
-199,
-87,
-155,
-92,
-187,
-162,
-79,
-115,
-149,
-223,
-174,
-158,
-186,
-55,
-106,
-221,
-35,
-53,
-60,
-192,
-51,
-81,
-187,
-190,
-187,
-152,
-124,
-157,
-119,
-61,
-48,
-233,
-128,
-167,
-59,
-245,
-59,
-120,
-234,
-55,
-211,
-186,
-5,
-37,
-109,
-31,
-6,
-14,
-114,
-202,
-78,
-82,
-250,
-169,
-250,
-255,
-211,
-149,
-230,
-215,
-14,
-205,
-193,
-200,
-118,
-160,
-157,
-78,
-0,
-81,
-42,
-0,
-236,
-95,
-40,
-255,
-63,
-251,
-66,
-129,
-15,
-234,
-255,
-247,
-46,
-208,
-216,
-1,
-124,
-86,
-192,
-117,
-46,
-85,
-218,
-119,
-56,
-101,
-215,
-35,
-66,
-97,
-45,
-125,
-0,
-179,
-129,
-123,
-157,
-122,
-187,
-255,
-191,
-48,
-128,
-255,
-14,
-200,
-222,
-235,
-8,
-109,
-115,
-80,
-161,
-254,
-108,
-100,
-114,
-108,
-92,
-199,
-171,
-230,
-58,
-86,
-231,
-241,
-93,
-167,
-204,
-34,
-88,
-0,
-32,
-66,
-241,
-9,
-100,
-133,
-147,
-57,
-229,
-203,
-34,
-203,
-192,
-201,
-136,
-112,
-158,
-141,
-124,
-193,
-207,
-36,
-95,
-214,
-219,
-47,
-141,
-111,
-75,
-53,
-157,
-130,
-206,
-1,
-217,
-98,
-76,
-115,
-126,
-111,
-142,
-12,
-252,
-27,
-128,
-165,
-27,
-244,
-121,
-73,
-68,
-241,
-117,
-18,
-162,
-220,
-186,
-31,
-152,
-166,
-207,
-53,
-4,
-11,
-107,
-248,
-131,
-127,
-162,
-118,
-122,
-119,
-49,
-249,
-58,
-247,
-178,
-89,
-77,
-253,
-139,
-61,
-117,
-27,
-217,
-74,
-79,
-221,
-199,
-16,
-37,
-228,
-242,
-250,
-251,
-189,
-74,
-122,
-5,
-35,
-63,
-154,
-203,
-0,
-43,
-59,
-191,
-87,
-64,
-4,
-192,
-103,
-66,
-239,
-161,
-120,
-97,
-59,
-209,
-255,
-81,
-40,
-63,
-91,
-203,
-159,
-173,
-255,
-0,
-126,
-87,
-160,
-57,
-79,
-203,
-63,
-29,
-112,
-157,
-111,
-43,
-237,
-161,
-250,
-219,
-158,
-48,
-92,
-234,
-208,
-252,
-93,
-203,
-94,
-170,
-191,
-237,
-254,
-255,
-107,
-13,
-239,
-233,
-66,
-224,
-9,
-231,
-183,
-221,
-234,
-252,
-184,
-9,
-31,
-15,
-223,
-37,
-16,
-125,
-197,
-66,
-224,
-57,
-78,
-185,
-69,
-19,
-1,
-176,
-151,
-182,
-249,
-136,
-83,
-182,
-52,
-114,
-2,
-0,
-162,
-80,
-60,
-4,
-89,
-129,
-221,
-173,
-101,
-175,
-117,
-104,
-239,
-3,
-174,
-247,
-240,
-189,
-137,
-193,
-45,
-192,
-20,
-84,
-137,
-10,
-100,
-228,
-58,
-135,
-109,
-27,
-244,
-119,
-13,
-70,
-42,
-1,
-255,
-131,
-40,
-94,
-127,
-10,
-28,
-228,
-60,
-131,
-235,
-40,
-81,
-132,
-82,
-175,
-12,
-133,
-194,
-68,
-141,
-241,
-238,
-98,
-242,
-117,
-238,
-115,
-163,
-166,
-245,
-84,
-11,
-128,
-243,
-25,
-185,
-250,
-253,
-135,
-146,
-110,
-19,
-208,
-167,
-163,
-129,
-115,
-155,
-220,
-135,
-219,
-120,
-115,
-189,
-208,
-12,
-244,
-107,
-64,
-190,
-183,
-191,
-201,
-161,
-187,
-13,
-184,
-207,
-249,
-189,
-44,
-185,
-214,
-218,
-251,
-48,
-10,
-215,
-121,
-173,
-210,
-94,
-166,
-191,
-191,
-172,
-191,
-247,
-115,
-104,
-62,
-165,
-101,
-223,
-208,
-223,
-118,
-192,
-189,
-162,
-130,
-239,
-42,
-133,
-223,
-75,
-34,
-95,
-182,
-71,
-244,
-247,
-82,
-246,
-183,
-75,
-11,
-124,
-196,
-55,
-48,
-106,
-238,
-225,
-237,
-218,
-230,
-239,
-133,
-242,
-90,
-120,
-120,
-157,
-170,
-85,
-207,
-112,
-202,
-172,
-48,
-62,
-13,
-88,
-202,
-41,
-63,
-89,
-203,
-95,
-228,
-148,
-93,
-12,
-60,
-238,
-225,
-251,
-59,
-165,
-45,
-42,
-1,
-79,
-214,
-223,
-123,
-235,
-239,
-19,
-244,
-119,
-208,
-145,
-33,
-162,
-167,
-1,
-81,
-150,
-61,
-167,
-80,
-151,
-57,
-183,
-218,
-90,
-191,
-82,
-124,
-31,
-177,
-222,
-93,
-13,
-223,
-117,
-17,
-1,
-118,
-135,
-62,
-131,
-59,
-145,
-15,
-79,
-153,
-2,
-206,
-34,
-182,
-0,
-120,
-20,
-248,
-168,
-243,
-219,
-30,
-253,
-45,
-89,
-164,
-245,
-180,
-221,
-157,
-154,
-237,
-85,
-85,
-227,
-12,
-120,
-64,
-251,
-181,
-149,
-150,
-109,
-173,
-191,
-143,
-112,
-232,
-236,
-121,
-234,
-70,
-250,
-123,
-91,
-253,
-125,
-91,
-224,
-117,
-150,
-66,
-148,
-141,
-115,
-144,
-47,
-157,
-61,
-62,
-219,
-208,
-161,
-89,
-95,
-203,
-46,
-66,
-20,
-122,
-243,
-245,
-193,
-84,
-157,
-33,
-207,
-65,
-142,
-204,
-190,
-11,
-124,
-29,
-153,
-24,
-0,
-7,
-107,
-253,
-167,
-245,
-247,
-167,
-156,
-54,
-175,
-64,
-246,
-85,
-115,
-66,
-7,
-145,
-182,
-179,
-171,
-162,
-119,
-21,
-202,
-45,
-130,
-143,
-1,
-145,
-163,
-190,
-187,
-10,
-101,
-147,
-148,
-207,
-250,
-37,
-215,
-93,
-199,
-41,
-59,
-135,
-194,
-190,
-94,
-203,
-95,
-137,
-124,
-161,
-167,
-144,
-31,
-3,
-46,
-68,
-236,
-45,
-158,
-129,
-28,
-211,
-61,
-166,
-255,
-15,
-62,
-50,
-212,
-247,
-0,
-126,
-77,
-254,
-218,
-206,
-51,
-104,
-183,
-20,
-53,
-222,
-137,
-26,
-229,
-221,
-85,
-241,
-5,
-254,
-172,
-207,
-224,
-12,
-228,
-163,
-100,
-79,
-90,
-6,
-148,
-200,
-14,
-47,
-136,
-47,
-0,
-22,
-48,
-242,
-212,
-96,
-62,
-30,
-197,
-123,
-201,
-53,
-223,
-14,
-204,
-15,
-161,
-45,
-99,
-240,
-27,
-237,
-151,
-253,
-242,
-126,
-71,
-127,
-191,
-199,
-161,
-249,
-144,
-150,
-125,
-76,
-127,
-219,
-37,
-253,
-207,
-27,
-92,
-231,
-207,
-218,
-230,
-213,
-200,
-222,
-107,
-146,
-135,
-102,
-178,
-214,
-109,
-163,
-180,
-127,
-168,
-225,
-121,
-16,
-114,
-44,
-54,
-83,
-7,
-197,
-100,
-196,
-152,
-102,
-73,
-228,
-136,
-240,
-17,
-68,
-215,
-176,
-148,
-210,
-175,
-141,
-104,
-202,
-247,
-68,
-20,
-87,
-161,
-131,
-104,
-35,
-29,
-40,
-247,
-227,
-124,
-157,
-181,
-206,
-162,
-201,
-22,
-224,
-73,
-224,
-170,
-66,
-217,
-108,
-224,
-81,
-15,
-237,
-85,
-202,
-127,
-69,
-167,
-236,
-106,
-28,
-125,
-73,
-129,
-254,
-29,
-200,
-23,
-110,
-174,
-254,
-221,
-89,
-203,
-237,
-123,
-222,
-75,
-127,
-255,
-81,
-127,
-23,
-87,
-11,
-3,
-103,
-246,
-228,
-202,
-226,
-55,
-122,
-234,
-236,
-106,
-14,
-224,
-114,
-28,
-157,
-70,
-19,
-104,
-251,
-211,
-244,
-255,
-49,
-223,
-93,
-41,
-95,
-96,
-53,
-224,
-85,
-5,
-250,
-243,
-128,
-89,
-21,
-188,
-160,
-255,
-21,
-192,
-195,
-200,
-60,
-8,
-57,
-154,
-108,
-191,
-2,
-80,
-6,
-86,
-201,
-247,
-47,
-253,
-125,
-1,
-131,
-26,
-251,
-117,
-148,
-230,
-4,
-135,
-6,
-26,
-28,
-65,
-144,
-75,
-222,
-163,
-245,
-239,
-119,
-60,
-52,
-7,
-219,
-235,
-232,
-223,
-214,
-6,
-59,
-192,
-79,
-148,
-199,
-14,
-250,
-123,
-25,
-68,
-25,
-249,
-91,
-253,
-253,
-212,
-192,
-8,
-224,
-101,
-245,
-17,
-85,
-104,
-34,
-0,
-230,
-1,
-255,
-46,
-148,
-61,
-12,
-60,
-89,
-40,
-179,
-43,
-39,
-236,
-96,
-32,
-63,
-189,
-105,
-162,
-189,
-182,
-43,
-182,
-127,
-163,
-19,
-20,
-255,
-145,
-225,
-20,
-10,
-71,
-134,
-90,
-110,
-183,
-99,
-167,
-0,
-203,
-104,
-89,
-134,
-28,
-69,
-205,
-70,
-116,
-2,
-183,
-43,
-205,
-177,
-192,
-154,
-78,
-219,
-117,
-16,
-163,
-178,
-183,
-54,
-232,
-111,
-180,
-119,
-87,
-197,
-183,
-132,
-230,
-122,
-60,
-31,
-39,
-231,
-186,
-16,
-95,
-0,
-92,
-200,
-72,
-29,
-128,
-213,
-135,
-189,
-38,
-224,
-158,
-142,
-166,
-196,
-240,
-45,
-8,
-192,
-154,
-200,
-132,
-159,
-142,
-44,
-207,
-103,
-162,
-230,
-142,
-5,
-186,
-219,
-144,
-189,
-210,
-82,
-250,
-210,
-231,
-160,
-90,
-203,
-192,
-235,
-108,
-162,
-55,
-53,
-189,
-108,
-194,
-0,
-175,
-211,
-186,
-25,
-250,
-119,
-253,
-150,
-247,
-180,
-49,
-50,
-201,
-254,
-238,
-148,
-253,
-18,
-217,
-195,
-46,
-167,
-191,
-131,
-6,
-17,
-114,
-66,
-241,
-168,
-62,
-35,
-223,
-18,
-223,
-162,
-137,
-0,
-152,
-138,
-163,
-99,
-209,
-178,
-127,
-41,
-159,
-173,
-156,
-178,
-143,
-146,
-91,
-211,
-109,
-168,
-101,
-86,
-87,
-50,
-112,
-228,
-86,
-114,
-173,
-101,
-144,
-85,
-210,
-124,
-28,
-237,
-180,
-62,
-31,
-223,
-137,
-129,
-111,
-107,
-177,
-141,
-211,
-143,
-135,
-145,
-21,
-136,
-181,
-250,
-187,
-9,
-153,
-228,
-47,
-39,
-223,
-42,
-44,
-210,
-255,
-91,
-59,
-17,
-8,
-80,
-22,
-235,
-181,
-162,
-189,
-187,
-58,
-190,
-30,
-154,
-207,
-107,
-223,
-119,
-42,
-169,
-183,
-136,
-45,
-0,
-246,
-98,
-228,
-41,
-128,
-181,
-25,
-248,
-15,
-176,
-70,
-129,
-118,
-25,
-231,
-255,
-246,
-20,
-224,
-115,
-229,
-119,
-30,
-0,
-114,
-43,
-165,
-119,
-234,
-95,
-159,
-33,
-131,
-213,
-3,
-216,
-115,
-221,
-198,
-154,
-71,
-114,
-141,
-246,
-192,
-87,
-70,
-235,
-151,
-116,
-6,
-214,
-45,
-109,
-238,
-69,
-249,
-156,
-137,
-12,
-248,
-23,
-232,
-239,
-79,
-40,
-223,
-13,
-28,
-154,
-160,
-65,
-4,
-236,
-81,
-117,
-191,
-206,
-75,
-111,
-34,
-0,
-46,
-213,
-254,
-173,
-224,
-148,
-189,
-81,
-7,
-223,
-147,
-136,
-117,
-221,
-73,
-58,
-96,
-63,
-141,
-28,
-25,
-94,
-139,
-216,
-100,
-204,
-210,
-246,
-75,
-85,
-93,
-195,
-225,
-251,
-53,
-223,
-59,
-37,
-224,
-200,
-176,
-80,
-183,
-53,
-114,
-108,
-252,
-48,
-50,
-177,
-111,
-68,
-108,
-57,
-220,
-99,
-169,
-231,
-32,
-71,
-177,
-119,
-34,
-203,
-244,
-25,
-218,
-239,
-131,
-128,
-181,
-3,
-251,
-27,
-237,
-221,
-85,
-241,
-245,
-212,
-127,
-82,
-235,
-247,
-172,
-224,
-97,
-17,
-91,
-0,
-44,
-135,
-8,
-204,
-239,
-57,
-101,
-118,
-203,
-246,
-16,
-162,
-8,
-62,
-22,
-177,
-113,
-113,
-143,
-116,
-127,
-160,
-207,
-102,
-229,
-34,
-207,
-70,
-64,
-108,
-209,
-33,
-215,
-56,
-15,
-44,
-215,
-200,
-245,
-0,
-182,
-99,
-251,
-249,
-120,
-141,
-54,
-200,
-5,
-212,
-207,
-157,
-178,
-186,
-179,
-234,
-245,
-43,
-248,
-217,
-229,
-239,
-46,
-37,
-245,
-22,
-77,
-4,
-192,
-129,
-218,
-230,
-125,
-133,
-242,
-183,
-34,
-75,
-208,
-185,
-136,
-118,
-126,
-119,
-45,
-223,
-17,
-89,
-98,
-63,
-170,
-207,
-127,
-117,
-63,
-231,
-129,
-235,
-108,
-128,
-8,
-140,
-187,
-41,
-104,
-182,
-41,
-63,
-50,
-108,
-45,
-120,
-187,
-34,
-246,
-187,
-171,
-226,
-91,
-168,
-255,
-54,
-34,
-120,
-223,
-226,
-171,
-31,
-6,
-128,
-119,
-225,
-152,
-82,
-35,
-91,
-172,
-61,
-80,
-161,
-140,
-163,
-220,
-213,
-250,
-15,
-40,
-253,
-59,
-99,
-92,
-252,
-245,
-250,
-128,
-158,
-64,
-164,
-224,
-128,
-101,
-17,
-185,
-30,
-224,
-113,
-253,
-251,
-34,
-31,
-175,
-209,
-4,
-178,
-130,
-248,
-175,
-246,
-209,
-213,
-97,
-124,
-222,
-243,
-15,
-228,
-220,
-250,
-243,
-148,
-120,
-129,
-33,
-90,
-103,
-144,
-229,
-153,
-215,
-104,
-198,
-25,
-136,
-77,
-4,
-192,
-198,
-250,
-66,
-175,
-43,
-227,
-27,
-3,
-192,
-223,
-180,
-111,
-239,
-242,
-212,
-149,
-29,
-25,
-54,
-222,
-91,
-199,
-64,
-236,
-119,
-87,
-199,
-215,
-169,
-251,
-37,
-34,
-12,
-159,
-223,
-215,
-189,
-133,
-2,
-57,
-201,
-90,
-8,
-124,
-143,
-146,
-237,
-53,
-176,
-60,
-242,
-193,
-94,
-8,
-124,
-61,
-214,
-133,
-151,
-33,
-223,
-119,
-95,
-86,
-65,
-119,
-155,
-210,
-220,
-19,
-229,
-194,
-145,
-65,
-110,
-96,
-227,
-245,
-112,
-44,
-208,
-214,
-14,
-118,
-114,
-101,
-228,
-193,
-53,
-124,
-160,
-161,
-55,
-32,
-185,
-213,
-226,
-81,
-116,
-112,
-78,
-170,
-232,
-151,
-221,
-71,
-122,
-45,
-53,
-41,
-63,
-50,
-12,
-114,
-89,
-141,
-141,
-216,
-239,
-46,
-132,
-47,
-114,
-252,
-55,
-19,
-248,
-166,
-71,
-200,
-120,
-173,
-253,
-250,
-6,
-178,
-18,
-120,
-28,
-249,
-232,
-28,
-137,
-232,
-129,
-222,
-174,
-127,
-143,
-212,
-242,
-199,
-136,
-241,
-229,
-47,
-92,
-248,
-47,
-250,
-160,
-190,
-87,
-65,
-99,
-245,
-0,
-199,
-70,
-189,
-120,
-4,
-32,
-230,
-181,
-15,
-34,
-190,
-221,
-181,
-95,
-213,
-186,
-65,
-132,
-120,
-146,
-205,
-70,
-246,
-229,
-165,
-198,
-78,
-4,
-160,
-164,
-221,
-178,
-228,
-74,
-196,
-243,
-241,
-216,
-246,
-59,
-180,
-27,
-0,
-95,
-168,
-187,
-39,
-135,
-126,
-69,
-68,
-203,
-63,
-139,
-234,
-237,
-205,
-187,
-144,
-189,
-252,
-92,
-253,
-235,
-221,
-230,
-244,
-141,
-216,
-239,
-46,
-148,
-111,
-205,
-107,
-251,
-68,
-219,
-251,
-233,
-10,
-96,
-21,
-228,
-56,
-251,
-2,
-100,
-219,
-183,
-64,
-255,
-94,
-128,
-184,
-47,
-119,
-219,
-243,
-39,
-140,
-13,
-168,
-16,
-248,
-57,
-178,
-237,
-2,
-57,
-29,
-248,
-27,
-112,
-34,
-162,
-4,
-252,
-7,
-98,
-246,
-91,
-42,
-72,
-134,
-216,
-87,
-23,
-63,
-11,
-160,
-255,
-180,
-219,
-96,
-24,
-125,
-76,
-72,
-24,
-151,
-0,
-158,
-139,
-24,
-96,
-93,
-128,
-44,
-197,
-231,
-32,
-202,
-175,
-135,
-16,
-37,
-208,
-143,
-40,
-24,
-172,
-140,
-66,
-31,
-93,
-220,
-75,
-141,
-193,
-15,
-35,
-143,
-72,
-147,
-0,
-72,
-72,
-24,
-207,
-208,
-121,
-188,
-8,
-177,
-182,
-132,
-10,
-35,
-21,
-68,
-97,
-188,
-8,
-81,
-212,
-37,
-1,
-48,
-70,
-16,
-93,
-209,
-148,
-48,
-225,
-144,
-25,
-99,
-206,
-214,
-255,
-191,
-167,
-130,
-238,
-125,
-74,
-219,
-41,
-254,
-66,
-194,
-144,
-64,
-79,
-65,
-8,
-17,
-207,
-182,
-219,
-172,
-210,
-2,
-177,
-197,
-190,
-3,
-245,
-78,
-107,
-201,
-115,
-51,
-196,
-230,
-124,
-134,
-46,
-153,
-91,
-251,
-248,
-147,
-219,
-217,
-79,
-199,
-241,
-204,
-155,
-104,
-32,
-204,
-235,
-204,
-194,
-6,
-111,
-185,
-171,
-130,
-246,
-74,
-29,
-67,
-79,
-5,
-141,
-109,
-208,
-151,
-23,
-58,
-215,
-218,
-60,
-180,
-93,
-129,
-199,
-43,
-16,
-95,
-135,
-169,
-228,
-78,
-101,
-127,
-35,
-192,
-189,
-182,
-132,
-223,
-106,
-72,
-28,
-192,
-75,
-17,
-165,
-226,
-60,
-253,
-123,
-9,
-240,
-37,
-234,
-143,
-34,
-215,
-38,
-183,
-164,
-172,
-220,
-202,
-57,
-207,
-108,
-33,
-129,
-198,
-83,
-157,
-64,
-143,
-65,
-8,
-201,
-157,
-72,
-94,
-171,
-191,
-109,
-20,
-161,
-217,
-29,
-250,
-123,
-57,
-162,
-28,
-219,
-6,
-241,
-138,
-187,
-168,
-3,
-175,
-231,
-234,
-139,
-4,
-79,
-128,
-141,
-197,
-9,
-58,
-8,
-207,
-67,
-142,
-152,
-78,
-67,
-237,
-22,
-16,
-123,
-254,
-251,
-2,
-218,
-91,
-108,
-130,
-24,
-43,
-129,
-199,
-85,
-27,
-57,
-177,
-0,
-241,
-98,
-124,
-81,
-11,
-1,
-240,
-67,
-231,
-90,
-3,
-22,
-169,
-1,
-237,
-183,
-39,
-87,
-170,
-62,
-138,
-152,
-45,
-91,
-19,
-229,
-133,
-148,
-152,
-249,
-86,
-240,
-123,
-55,
-185,
-237,
-11,
-136,
-149,
-227,
-21,
-228,
-71,
-226,
-232,
-24,
-26,
-112,
-148,
-42,
-240,
-185,
-64,
-105,
-75,
-143,
-148,
-149,
-206,
-250,
-195,
-92,
-208,
-164,
-159,
-173,
-64,
-207,
-65,
-8,
-25,
-92,
-1,
-172,
-130,
-172,
-0,
-188,
-65,
-70,
-3,
-121,
-206,
-68,
-221,
-82,
-129,
-93,
-240,
-4,
-0,
-109,
-200,
-111,
-75,
-196,
-0,
-106,
-33,
-240,
-242,
-46,
-188,
-10,
-124,
-215,
-36,
-183,
-173,
-184,
-162,
-3,
-31,
-87,
-155,
-30,
-100,
-79,
-95,
-194,
-231,
-56,
-228,
-88,
-112,
-50,
-178,
-63,
-183,
-251,
-249,
-89,
-192,
-49,
-1,
-237,
-45,
-54,
-35,
-247,
-24,
-253,
-145,
-135,
-206,
-70,
-204,
-253,
-8,
-121,
-188,
-137,
-208,
-208,
-232,
-75,
-34,
-167,
-30,
-211,
-244,
-223,
-3,
-4,
-172,
-78,
-10,
-60,
-236,
-170,
-238,
-120,
-52,
-52,
-28,
-114,
-218,
-98,
-45,
-88,
-7,
-252,
-92,
-42,
-120,
-237,
-72,
-30,
-150,
-254,
-116,
-10,
-199,
-193,
-136,
-233,
-243,
-239,
-181,
-126,
-14,
-21,
-95,
-119,
-114,
-31,
-142,
-74,
-75,
-75,
-228,
-200,
-18,
-28,
-55,
-232,
-94,
-192,
-96,
-16,
-66,
-23,
-179,
-16,
-5,
-206,
-103,
-28,
-250,
-110,
-65,
-8,
-35,
-1,
-89,
-94,
-158,
-133,
-216,
-166,
-159,
-67,
-64,
-200,
-176,
-0,
-158,
-91,
-234,
-96,
-187,
-33,
-70,
-31,
-149,
-231,
-81,
-250,
-44,
-31,
-160,
-16,
-68,
-163,
-1,
-143,
-23,
-33,
-66,
-196,
-78,
-136,
-25,
-148,
-216,
-178,
-7,
-240,
-154,
-10,
-124,
-64,
-255,
-255,
-98,
-68,
-56,
-63,
-137,
-172,
-10,
-188,
-121,
-20,
-10,
-237,
-45,
-182,
-32,
-143,
-111,
-119,
-135,
-135,
-110,
-146,
-78,
-134,
-149,
-112,
-2,
-101,
-6,
-246,
-241,
-205,
-74,
-126,
-166,
-254,
-3,
-216,
-177,
-225,
-125,
-218,
-85,
-231,
-75,
-10,
-229,
-91,
-218,
-137,
-26,
-200,
-231,
-105,
-200,
-105,
-7,
-72,
-0,
-151,
-210,
-83,
-15,
-228,
-216,
-22,
-196,
-124,
-219,
-43,
-176,
-24,
-185,
-13,
-240,
-90,
-209,
-146,
-111,
-127,
-250,
-93,
-254,
-227,
-15,
-66,
-8,
-178,
-23,
-62,
-10,
-248,
-3,
-185,
-27,
-234,
-199,
-28,
-154,
-110,
-65,
-8,
-35,
-0,
-177,
-129,
-182,
-152,
-6,
-60,
-111,
-180,
-250,
-82,
-6,
-196,
-51,
-110,
-33,
-178,
-116,
-108,
-28,
-46,
-92,
-121,
-172,
-133,
-44,
-55,
-167,
-33,
-49,
-20,
-94,
-167,
-2,
-224,
-142,
-144,
-9,
-235,
-225,
-23,
-228,
-60,
-84,
-209,
-254,
-41,
-1,
-160,
-191,
-109,
-190,
-135,
-45,
-29,
-154,
-77,
-181,
-236,
-116,
-253,
-221,
-84,
-0,
-216,
-136,
-203,
-123,
-34,
-113,
-242,
-0,
-126,
-223,
-176,
-159,
-214,
-225,
-236,
-205,
-133,
-114,
-203,
-47,
-200,
-215,
-129,
-220,
-77,
-126,
-54,
-142,
-123,
-115,
-9,
-173,
-13,
-63,
-14,
-78,
-220,
-75,
-15,
-221,
-133,
-74,
-243,
-141,
-146,
-250,
-175,
-107,
-125,
-231,
-143,
-90,
-37,
-40,
-4,
-33,
-212,
-50,
-128,
-41,
-206,
-239,
-151,
-105,
-217,
-121,
-78,
-89,
-227,
-32,
-132,
-68,
-80,
-234,
-20,
-248,
-117,
-218,
-35,
-14,
-3,
-136,
-85,
-221,
-84,
-2,
-179,
-249,
-148,
-240,
-184,
-10,
-49,
-211,
-117,
-93,
-120,
-95,
-138,
-36,
-155,
-184,
-170,
-170,
-109,
-31,
-240,
-8,
-0,
-235,
-208,
-244,
-125,
-135,
-198,
-110,
-13,
-172,
-67,
-75,
-176,
-0,
-64,
-172,
-23,
-103,
-34,
-75,
-238,
-103,
-32,
-138,
-183,
-121,
-200,
-106,
-52,
-56,
-139,
-19,
-121,
-20,
-235,
-243,
-200,
-99,
-31,
-108,
-71,
-190,
-143,
-31,
-240,
-139,
-40,
-225,
-99,
-151,
-246,
-65,
-39,
-25,
-228,
-1,
-86,
-142,
-175,
-160,
-177,
-219,
-185,
-107,
-75,
-234,
-109,
-24,
-252,
-214,
-91,
-189,
-32,
-80,
-8,
-66,
-168,
-101,
-69,
-1,
-176,
-162,
-150,
-253,
-175,
-64,
-215,
-40,
-8,
-97,
-204,
-9,
-75,
-132,
-61,
-162,
-135,
-103,
-84,
-1,
-53,
-214,
-209,
-246,
-126,
-61,
-2,
-192,
-78,
-238,
-91,
-28,
-154,
-155,
-144,
-85,
-202,
-114,
-5,
-154,
-16,
-1,
-96,
-221,
-174,
-255,
-233,
-148,
-89,
-103,
-166,
-143,
-85,
-181,
-45,
-240,
-121,
-22,
-185,
-75,
-249,
-49,
-200,
-170,
-98,
-17,
-34,
-76,
-62,
-217,
-128,
-143,
-93,
-225,
-4,
-133,
-78,
-39,
-143,
-140,
-52,
-16,
-172,
-213,
-161,
-113,
-183,
-1,
-235,
-23,
-234,
-108,
-26,
-189,
-133,
-192,
-51,
-67,
-251,
-217,
-10,
-20,
-66,
-16,
-105,
-217,
-83,
-2,
-0,
-241,
-79,
-182,
-46,
-194,
-71,
-20,
-232,
-130,
-67,
-16,
-197,
-158,
-176,
-68,
-216,
-35,
-122,
-120,
-142,
-249,
-21,
-69,
-76,
-180,
-189,
-223,
-162,
-0,
-208,
-178,
-91,
-181,
-108,
-115,
-103,
-178,
-255,
-214,
-169,
-111,
-34,
-0,
-172,
-150,
-124,
-79,
-167,
-236,
-35,
-90,
-214,
-104,
-73,
-76,
-158,
-245,
-200,
-226,
-82,
-52,
-218,
-116,
-3,
-30,
-118,
-11,
-252,
-161,
-64,
-250,
-221,
-148,
-254,
-177,
-26,
-58,
-187,
-13,
-216,
-183,
-80,
-254,
-89,
-45,
-111,
-125,
-170,
-21,
-12,
-10,
-65,
-8,
-181,
-12,
-68,
-82,
-90,
-205,
-181,
-125,
-112,
-69,
-23,
-202,
-224,
-32,
-132,
-68,
-158,
-176,
-68,
-216,
-35,
-22,
-248,
-141,
-249,
-21,
-69,
-76,
-126,
-93,
-238,
-215,
-233,
-131,
-43,
-0,
-108,
-70,
-167,
-3,
-157,
-255,
-239,
-228,
-212,
-7,
-9,
-0,
-68,
-155,
-110,
-191,
-210,
-110,
-234,
-177,
-149,
-17,
-165,
-222,
-34,
-2,
-163,
-67,
-33,
-43,
-9,
-155,
-142,
-204,
-226,
-7,
-33,
-109,
-11,
-124,
-172,
-246,
-191,
-54,
-111,
-162,
-210,
-239,
-172,
-244,
-149,
-115,
-131,
-124,
-27,
-80,
-76,
-224,
-114,
-190,
-150,
-183,
-14,
-172,
-26,
-12,
-202,
-87,
-0,
-51,
-16,
-39,
-148,
-187,
-245,
-1,
-108,
-224,
-105,
-219,
-100,
-5,
-16,
-109,
-194,
-18,
-105,
-143,
-88,
-224,
-57,
-230,
-87,
-20,
-49,
-249,
-117,
-185,
-95,
-167,
-15,
-174,
-0,
-176,
-154,
-245,
-155,
-17,
-229,
-228,
-99,
-140,
-12,
-89,
-21,
-42,
-0,
-108,
-146,
-153,
-129,
-112,
-93,
-136,
-203,
-46,
-192,
-55,
-107,
-120,
-44,
-137,
-28,
-117,
-218,
-113,
-252,
-85,
-36,
-145,
-137,
-205,
-90,
-244,
-253,
-2,
-189,
-53,
-104,
-242,
-70,
-182,
-70,
-142,
-134,
-33,
-60,
-109,
-91,
-232,
-10,
-224,
-153,
-200,
-50,
-127,
-33,
-170,
-92,
-68,
-242,
-46,
-44,
-64,
-4,
-221,
-64,
-22,
-237,
-232,
-160,
-16,
-132,
-80,
-203,
-32,
-223,
-2,
-216,
-24,
-248,
-190,
-140,
-42,
-65,
-65,
-8,
-137,
-60,
-97,
-137,
-180,
-71,
-44,
-240,
-28,
-211,
-43,
-138,
-30,
-248,
-181,
-190,
-95,
-114,
-108,
-81,
-40,
-191,
-195,
-169,
-59,
-182,
-80,
-23,
-42,
-0,
-110,
-161,
-30,
-183,
-214,
-240,
-176,
-123,
-240,
-135,
-113,
-210,
-217,
-35,
-81,
-150,
-236,
-209,
-160,
-171,
-176,
-252,
-165,
-150,
-121,
-147,
-131,
-32,
-138,
-92,
-8,
-215,
-1,
-212,
-102,
-202,
-118,
-104,
-47,
-82,
-218,
-143,
-235,
-239,
-143,
-234,
-239,
-139,
-235,
-218,
-70,
-1,
-133,
-32,
-132,
-90,
-6,
-35,
-149,
-128,
-231,
-107,
-217,
-235,
-157,
-178,
-224,
-32,
-132,
-68,
-158,
-176,
-68,
-220,
-35,
-106,
-219,
-49,
-191,
-162,
-136,
-201,
-175,
-235,
-253,
-146,
-163,
-40,
-0,
-126,
-228,
-212,
-109,
-87,
-168,
-171,
-21,
-0,
-200,
-17,
-39,
-200,
-87,
-187,
-44,
-171,
-144,
-13,
-36,
-91,
-229,
-128,
-100,
-163,
-18,
-15,
-164,
-178,
-71,
-12,
-122,
-158,
-18,
-2,
-72,
-102,
-170,
-57,
-136,
-197,
-160,
-215,
-148,
-156,
-60,
-55,
-95,
-232,
-41,
-128,
-205,
-204,
-60,
-144,
-32,
-213,
-67,
-251,
-25,
-165,
-61,
-189,
-208,
-246,
-179,
-33,
-215,
-234,
-12,
-252,
-65,
-8,
-97,
-164,
-0,
-216,
-18,
-89,
-146,
-92,
-75,
-30,
-146,
-58,
-56,
-8,
-33,
-113,
-149,
-58,
-207,
-33,
-210,
-30,
-209,
-105,
-59,
-30,
-86,
-20,
-49,
-183,
-80,
-157,
-238,
-151,
-28,
-69,
-1,
-96,
-195,
-166,
-77,
-101,
-48,
-203,
-116,
-136,
-0,
-176,
-6,
-83,
-135,
-87,
-208,
-252,
-76,
-105,
-142,
-170,
-160,
-177,
-177,
-3,
-183,
-45,
-169,
-127,
-51,
-121,
-54,
-43,
-123,
-74,
-240,
-195,
-10,
-126,
-239,
-83,
-154,
-57,
-52,
-179,
-3,
-120,
-123,
-21,
-173,
-210,
-219,
-109,
-192,
-147,
-200,
-92,
-156,
-174,
-99,
-248,
-217,
-117,
-109,
-163,
-129,
-193,
-32,
-132,
-224,
-8,
-0,
-45,
-179,
-22,
-78,
-31,
-163,
-65,
-16,
-66,
-34,
-79,
-88,
-34,
-236,
-17,
-61,
-237,
-198,
-244,
-138,
-162,
-7,
-126,
-81,
-239,
-55,
-6,
-16,
-19,
-93,
-59,
-25,
-95,
-89,
-65,
-103,
-29,
-100,
-30,
-163,
-36,
-19,
-53,
-146,
-238,
-28,
-224,
-43,
-21,
-124,
-118,
-37,
-199,
-29,
-84,
-68,
-31,
-210,
-190,
-221,
-165,
-180,
-191,
-43,
-163,
-83,
-90,
-107,
-102,
-124,
-19,
-225,
-74,
-85,
-187,
-13,
-248,
-162,
-254,
-173,
-204,
-157,
-216,
-11,
-232,
-41,
-8,
-97,
-236,
-9,
-75,
-132,
-61,
-98,
-129,
-223,
-115,
-24,
-227,
-43,
-138,
-152,
-252,
-250,
-184,
-223,
-24,
-32,
-143,
-91,
-88,
-107,
-157,
-71,
-190,
-196,
-247,
-186,
-33,
-147,
-39,
-253,
-152,
-173,
-207,
-206,
-205,
-175,
-184,
-30,
-146,
-123,
-241,
-225,
-194,
-152,
-57,
-160,
-230,
-154,
-111,
-34,
-63,
-13,
-56,
-133,
-193,
-188,
-136,
-235,
-145,
-7,
-87,
-157,
-67,
-133,
-16,
-243,
-240,
-182,
-219,
-128,
-251,
-245,
-111,
-183,
-216,
-254,
-109,
-65,
-15,
-65,
-8,
-137,
-56,
-97,
-137,
-180,
-71,
-44,
-240,
-28,
-15,
-43,
-138,
-152,
-91,
-168,
-232,
-247,
-27,
-3,
-228,
-113,
-40,
-107,
-175,
-77,
-110,
-121,
-120,
-102,
-73,
-253,
-74,
-136,
-167,
-168,
-197,
-124,
-228,
-52,
-203,
-245,
-228,
-91,
-136,
-108,
-57,
-118,
-116,
-198,
-204,
-64,
-134,
-170,
-2,
-223,
-119,
-21,
-120,
-220,
-166,
-215,
-113,
-189,
-1,
-167,
-226,
-232,
-202,
-2,
-239,
-253,
-89,
-136,
-224,
-69,
-255,
-174,
-83,
-223,
-170,
-39,
-16,
-49,
-8,
-33,
-145,
-39,
-44,
-145,
-246,
-136,
-5,
-250,
-49,
-189,
-162,
-232,
-129,
-95,
-212,
-251,
-141,
-1,
-100,
-91,
-99,
-221,
-118,
-7,
-142,
-155,
-61,
-244,
-214,
-207,
-96,
-30,
-37,
-177,
-27,
-144,
-204,
-86,
-159,
-68,
-20,
-216,
-54,
-174,
-197,
-99,
-136,
-99,
-219,
-161,
-56,
-161,
-191,
-145,
-109,
-133,
-61,
-234,
-251,
-118,
-205,
-181,
-215,
-64,
-132,
-232,
-101,
-72,
-152,
-54,
-27,
-174,
-237,
-98,
-100,
-101,
-209,
-54,
-94,
-134,
-77,
-102,
-251,
-239,
-122,
-234,
-113,
-2,
-34,
-78,
-88,
-34,
-238,
-17,
-29,
-218,
-49,
-191,
-162,
-136,
-201,
-175,
-143,
-251,
-77,
-72,
-240,
-34,
-246,
-132,
-37,
-226,
-30,
-209,
-161,
-27,
-15,
-43,
-138,
-152,
-91,
-168,
-232,
-247,
-155,
-144,
-224,
-69,
-236,
-9,
-75,
-196,
-61,
-162,
-210,
-140,
-249,
-21,
-69,
-76,
-126,
-125,
-220,
-111,
-66,
-66,
-41,
-98,
-78,
-88,
-250,
-217,
-35,
-142,
-249,
-21,
-69,
-76,
-126,
-125,
-220,
-111,
-194,
-4,
-3,
-225,
-231,
-154,
-209,
-39,
-108,
-108,
-196,
-20,
-80,
-74,
-19,
-123,
-203,
-19,
-155,
-95,
-212,
-251,
-13,
-1,
-162,
-48,
-179,
-86,
-119,
-165,
-249,
-246,
-144,
-252,
-136,
-32,
-182,
-250,
-107,
-84,
-208,
-21,
-177,
-16,
-57,
-206,
-187,
-4,
-177,
-247,
-95,
-181,
-97,
-255,
-214,
-82,
-62,
-39,
-20,
-202,
-47,
-3,
-30,
-172,
-104,
-183,
-10,
-185,
-210,
-240,
-131,
-21,
-116,
-239,
-82,
-154,
-39,
-129,
-85,
-60,
-245,
-43,
-146,
-219,
-44,
-236,
-81,
-193,
-103,
-71,
-165,
-185,
-135,
-190,
-3,
-240,
-208,
-49,
-96,
-228,
-120,
-0,
-227,
-96,
-69,
-17,
-147,
-95,
-31,
-247,
-27,
-10,
-242,
-179,
-241,
-42,
-75,
-187,
-131,
-148,
-230,
-212,
-26,
-94,
-22,
-54,
-247,
-226,
-127,
-200,
-163,
-254,
-160,
-99,
-118,
-32,
-155,
-117,
-5,
-191,
-237,
-181,
-221,
-23,
-157,
-178,
-12,
-217,
-86,
-253,
-179,
-166,
-237,
-183,
-181,
-109,
-105,
-92,
-65,
-114,
-205,
-254,
-129,
-21,
-52,
-86,
-72,
-60,
-130,
-39,
-211,
-51,
-18,
-142,
-204,
-190,
-223,
-119,
-135,
-222,
-91,
-107,
-208,
-49,
-96,
-228,
-68,
-5,
-241,
-87,
-20,
-67,
-255,
-98,
-247,
-1,
-36,
-98,
-51,
-136,
-243,
-210,
-64,
-40,
-50,
-96,
-9,
-242,
-120,
-123,
-111,
-170,
-225,
-101,
-81,
-52,
-65,
-222,
-20,
-248,
-179,
-214,
-45,
-160,
-196,
-4,
-216,
-195,
-239,
-11,
-218,
-102,
-123,
-167,
-204,
-70,
-50,
-174,
-244,
-182,
-100,
-228,
-42,
-224,
-205,
-158,
-122,
-27,
-69,
-107,
-186,
-111,
-98,
-23,
-104,
-109,
-223,
-127,
-229,
-169,
-179,
-130,
-198,
-155,
-216,
-53,
-58,
-232,
-24,
-48,
-114,
-34,
-130,
-200,
-95,
-216,
-216,
-252,
-70,
-27,
-136,
-89,
-44,
-120,
-108,
-227,
-129,
-29,
-180,
-110,
-10,
-53,
-153,
-145,
-203,
-4,
-128,
-214,
-101,
-192,
-201,
-90,
-127,
-23,
-97,
-137,
-69,
-143,
-87,
-250,
-181,
-157,
-178,
-119,
-106,
-217,
-71,
-3,
-218,
-219,
-201,
-57,
-224,
-17,
-75,
-190,
-242,
-25,
-136,
-150,
-236,
-161,
-93,
-151,
-220,
-7,
-96,
-43,
-167,
-124,
-67,
-196,
-154,
-113,
-38,
-195,
-178,
-206,
-164,
-99,
-192,
-200,
-132,
-132,
-34,
-200,
-191,
-180,
-103,
-120,
-234,
-78,
-209,
-186,
-111,
-5,
-240,
-41,
-21,
-0,
-90,
-191,
-6,
-185,
-147,
-207,
-7,
-2,
-248,
-93,
-13,
-60,
-84,
-40,
-179,
-118,
-23,
-181,
-81,
-131,
-24,
-185,
-10,
-112,
-3,
-162,
-174,
-163,
-2,
-124,
-22,
-129,
-31,
-77,
-96,
-95,
-229,
-243,
-63,
-59,
-7,
-201,
-205,
-189,
-27,
-133,
-224,
-31,
-115,
-32,
-82,
-60,
-123,
-135,
-95,
-148,
-56,
-251,
-9,
-195,
-1,
-226,
-33,
-103,
-93,
-110,
-215,
-116,
-202,
-87,
-213,
-242,
-133,
-192,
-122,
-1,
-124,
-42,
-5,
-128,
-210,
-216,
-128,
-156,
-94,
-167,
-29,
-90,
-160,
-166,
-79,
-118,
-21,
-112,
-170,
-83,
-102,
-19,
-122,
-252,
-180,
-238,
-158,
-156,
-54,
-75,
-2,
-215,
-104,
-187,
-47,
-145,
-235,
-6,
-38,
-19,
-176,
-154,
-137,
-2,
-58,
-166,
-61,
-42,
-225,
-25,
-45,
-158,
-189,
-195,
-179,
-83,
-156,
-125,
-82,
-26,
-176,
-74,
-32,
-91,
-16,
-235,
-82,
-91,
-186,
-5,
-1,
-54,
-82,
-154,
-218,
-173,
-7,
-185,
-59,
-243,
-126,
-78,
-153,
-77,
-144,
-113,
-118,
-85,
-91,
-135,
-222,
-162,
-74,
-0,
-236,
-175,
-52,
-94,
-227,
-40,
-224,
-88,
-253,
-119,
-186,
-210,
-93,
-227,
-148,
-29,
-139,
-172,
-32,
-30,
-118,
-203,
-106,
-250,
-100,
-87,
-1,
-11,
-144,
-37,
-251,
-242,
-200,
-137,
-204,
-28,
-26,
-186,
-244,
-34,
-122,
-131,
-133,
-58,
-71,
-238,
-69,
-182,
-4,
-175,
-107,
-194,
-163,
-53,
-136,
-148,
-246,
-168,
-192,
-51,
-106,
-60,
-123,
-229,
-25,
-35,
-206,
-254,
-132,
-73,
-3,
-214,
-22,
-228,
-138,
-169,
-82,
-37,
-36,
-240,
-93,
-165,
-249,
-99,
-0,
-191,
-173,
-149,
-246,
-122,
-167,
-204,
-10,
-226,
-247,
-214,
-180,
-173,
-68,
-129,
-214,
-134,
-227,
-122,
-162,
-134,
-167,
-141,
-219,
-183,
-135,
-83,
-182,
-188,
-142,
-173,
-63,
-212,
-221,
-79,
-129,
-151,
-93,
-5,
-28,
-65,
-190,
-218,
-109,
-101,
-73,
-73,
-110,
-215,
-1,
-240,
-235,
-54,
-60,
-218,
-92,
-52,
-90,
-218,
-163,
-66,
-187,
-232,
-241,
-236,
-137,
-16,
-103,
-95,
-249,
-244,
-146,
-6,
-172,
-112,
-141,
-12,
-9,
-38,
-81,
-171,
-87,
-33,
-242,
-234,
-139,
-142,
-201,
-88,
-201,
-163,
-233,
-122,
-143,
-33,
-245,
-222,
-166,
-40,
-77,
-80,
-134,
-40,
-242,
-208,
-90,
-47,
-37,
-87,
-92,
-62,
-140,
-19,
-59,
-176,
-164,
-157,
-181,
-122,
-180,
-184,
-214,
-41,
-187,
-164,
-64,
-107,
-39,
-246,
-188,
-26,
-158,
-7,
-40,
-157,
-187,
-119,
-183,
-1,
-77,
-188,
-201,
-58,
-42,
-120,
-217,
-85,
-192,
-44,
-125,
-38,
-243,
-105,
-169,
-180,
-3,
-246,
-113,
-238,
-179,
-113,
-0,
-211,
-54,
-23,
-140,
-154,
-246,
-104,
-60,
-129,
-142,
-105,
-192,
-60,
-147,
-118,
-46,
-98,
-172,
-113,
-1,
-226,
-137,
-182,
-159,
-62,
-175,
-223,
-214,
-240,
-9,
-89,
-125,
-61,
-68,
-33,
-204,
-86,
-13,
-207,
-78,
-201,
-88,
-129,
-101,
-144,
-179,
-105,
-240,
-8,
-124,
-224,
-245,
-90,
-231,
-61,
-222,
-43,
-225,
-249,
-121,
-109,
-115,
-32,
-185,
-178,
-205,
-27,
-135,
-175,
-164,
-189,
-69,
-213,
-22,
-224,
-163,
-74,
-83,
-25,
-172,
-22,
-9,
-171,
-182,
-0,
-120,
-154,
-83,
-182,
-167,
-182,
-13,
-118,
-119,
-119,
-218,
-126,
-219,
-233,
-95,
-171,
-47,
-55,
-226,
-225,
-249,
-48,
-162,
-245,
-159,
-133,
-108,
-71,
-106,
-117,
-35,
-157,
-64,
-15,
-105,
-143,
-38,
-2,
-60,
-147,
-246,
-14,
-157,
-180,
-247,
-144,
-251,
-118,
-131,
-124,
-201,
-189,
-249,
-223,
-148,
-79,
-211,
-213,
-87,
-168,
-87,
-98,
-231,
-100,
-172,
-192,
-225,
-122,
-221,
-95,
-120,
-234,
-236,
-17,
-90,
-169,
-129,
-143,
-167,
-205,
-106,
-58,
-206,
-46,
-35,
-95,
-254,
-7,
-235,
-131,
-2,
-5,
-128,
-205,
-72,
-52,
-201,
-83,
-231,
-238,
-245,
-31,
-211,
-177,
-236,
-150,
-93,
-171,
-109,
-255,
-68,
-192,
-254,
-191,
-192,
-123,
-21,
-167,
-127,
-175,
-14,
-109,
-87,
-224,
-113,
-168,
-182,
-255,
-46,
-121,
-124,
-197,
-147,
-218,
-240,
-106,
-114,
-209,
-232,
-105,
-143,
-148,
-46,
-218,
-146,
-54,
-38,
-175,
-24,
-40,
-76,
-218,
-211,
-128,
-13,
-11,
-245,
-27,
-147,
-235,
-24,
-230,
-80,
-72,
-78,
-233,
-208,
-181,
-89,
-125,
-221,
-194,
-144,
-142,
-106,
-201,
-141,
-89,
-30,
-193,
-209,
-68,
-35,
-123,
-101,
-235,
-132,
-84,
-106,
-226,
-91,
-194,
-243,
-68,
-125,
-127,
-139,
-128,
-203,
-26,
-182,
-181,
-168,
-18,
-0,
-231,
-42,
-205,
-128,
-209,
-26,
-45,
-16,
-187,
-127,
-21,
-109,
-55,
-66,
-86,
-144,
-15,
-34,
-38,
-194,
-107,
-144,
-219,
-6,
-116,
-218,
-238,
-214,
-93,
-184,
-143,
-180,
-71,
-209,
-20,
-138,
-49,
-121,
-41,
-191,
-78,
-194,
-132,
-145,
-147,
-246,
-119,
-120,
-38,
-45,
-240,
-33,
-173,
-183,
-198,
-60,
-215,
-151,
-208,
-181,
-93,
-125,
-5,
-229,
-180,
-139,
-1,
-228,
-24,
-10,
-156,
-21,
-31,
-240,
-97,
-45,
-107,
-52,
-129,
-181,
-173,
-221,
-138,
-64,
-243,
-112,
-102,
-22,
-101,
-118,
-0,
-27,
-147,
-167,
-219,
-42,
-53,
-9,
-38,
-87,
-72,
-126,
-163,
-80,
-254,
-16,
-112,
-121,
-147,
-62,
-53,
-233,
-95,
-77,
-91,
-27,
-219,
-97,
-31,
-167,
-236,
-123,
-90,
-118,
-126,
-219,
-62,
-133,
-92,
-56,
-106,
-218,
-35,
-226,
-230,
-81,
-143,
-170,
-156,
-36,
-130,
-48,
-33,
-159,
-180,
-179,
-240,
-56,
-174,
-32,
-146,
-251,
-97,
-29,
-136,
-111,
-35,
-159,
-180,
-3,
-138,
-50,
-198,
-199,
-234,
-235,
-255,
-244,
-154,
-238,
-57,
-183,
-253,
-202,
-238,
-21,
-202,
-199,
-105,
-187,
-190,
-182,
-157,
-14,
-172,
-208,
-176,
-173,
-133,
-207,
-18,
-240,
-233,
-228,
-138,
-194,
-201,
-84,
-175,
-166,
-62,
-169,
-116,
-174,
-80,
-123,
-166,
-150,
-5,
-47,
-251,
-155,
-244,
-175,
-166,
-157,
-213,
-167,
-220,
-204,
-200,
-248,
-133,
-171,
-146,
-27,
-26,
-213,
-70,
-24,
-110,
-5,
-34,
-166,
-61,
-34,
-162,
-66,
-49,
-38,
-47,
-165,
-137,
-34,
-76,
-28,
-26,
-239,
-209,
-23,
-121,
-84,
-216,
-159,
-233,
-111,
-27,
-231,
-221,
-183,
-36,
-109,
-187,
-250,
-42,
-85,
-90,
-18,
-127,
-197,
-244,
-76,
-125,
-110,
-51,
-145,
-176,
-213,
-107,
-33,
-194,
-173,
-109,
-68,
-98,
-155,
-246,
-186,
-241,
-68,
-115,
-250,
-239,
-102,
-36,
-90,
-2,
-216,
-22,
-184,
-82,
-235,
-102,
-81,
-51,
-1,
-129,
-159,
-43,
-237,
-115,
-157,
-50,
-155,
-29,
-168,
-117,
-64,
-78,
-95,
-255,
-2,
-218,
-44,
-129,
-132,
-41,
-3,
-143,
-179,
-15,
-240,
-45,
-173,
-187,
-145,
-62,
-182,
-126,
-68,
-76,
-123,
-68,
-68,
-133,
-98,
-100,
-94,
-49,
-5,
-147,
-157,
-180,
-251,
-123,
-234,
-172,
-119,
-217,
-221,
-232,
-215,
-141,
-138,
-44,
-49,
-180,
-95,
-125,
-61,
-94,
-82,
-223,
-215,
-113,
-174,
-53,
-73,
-221,
-25,
-216,
-91,
-255,
-127,
-98,
-72,
-219,
-2,
-159,
-165,
-16,
-129,
-4,
-240,
-178,
-22,
-237,
-45,
-236,
-49,
-224,
-181,
-228,
-46,
-211,
-32,
-199,
-203,
-175,
-8,
-224,
-115,
-62,
-98,
-155,
-146,
-57,
-101,
-246,
-196,
-230,
-13,
-77,
-251,
-229,
-233,
-95,
-19,
-1,
-176,
-151,
-182,
-185,
-180,
-164,
-126,
-37,
-36,
-38,
-39,
-120,
-18,
-157,
-116,
-6,
-17,
-211,
-30,
-17,
-113,
-73,
-27,
-153,
-87,
-76,
-97,
-226,
-157,
-180,
-200,
-215,
-209,
-166,
-198,
-122,
-171,
-83,
-110,
-245,
-1,
-143,
-122,
-120,
-181,
-93,
-125,
-45,
-240,
-212,
-245,
-118,
-156,
-75,
-158,
-24,
-227,
-120,
-224,
-239,
-250,
-255,
-70,
-19,
-5,
-57,
-86,
-180,
-167,
-10,
-23,
-52,
-105,
-235,
-240,
-40,
-98,
-54,
-114,
-234,
-114,
-38,
-240,
-113,
-2,
-35,
-24,
-33,
-123,
-253,
-127,
-23,
-202,
-78,
-80,
-158,
-149,
-227,
-35,
-176,
-127,
-65,
-2,
-0,
-153,
-220,
-86,
-89,
-92,
-149,
-233,
-200,
-206,
-185,
-135,
-136,
-173,
-240,
-38,
-98,
-218,
-35,
-34,
-42,
-20,
-35,
-243,
-138,
-41,
-76,
-188,
-147,
-150,
-252,
-216,
-230,
-228,
-66,
-121,
-213,
-150,
-169,
-237,
-234,
-107,
-154,
-167,
-174,
-183,
-227,
-92,
-68,
-184,
-216,
-112,
-241,
-179,
-144,
-175,
-120,
-169,
-128,
-113,
-218,
-173,
-132,
-40,
-64,
-175,
-32,
-183,
-41,
-120,
-130,
-0,
-15,
-199,
-132,
-126,
-225,
-186,
-93,
-254,
-69,
-255,
-190,
-57,
-100,
-224,
-24,
-99,
-172,
-239,
-243,
-233,
-30,
-18,
-235,
-86,
-121,
-119,
-96,
-63,
-108,
-128,
-145,
-103,
-246,
-204,
-203,
-122,
-118,
-133,
-106,
-120,
-175,
-212,
-191,
-62,
-11,
-193,
-233,
-250,
-247,
-233,
-182,
-0,
-241,
-28,
-219,
-215,
-24,
-243,
-152,
-49,
-166,
-184,
-135,
-92,
-174,
-208,
-206,
-197,
-3,
-250,
-119,
-221,
-192,
-126,
-217,
-120,
-241,
-119,
-121,
-234,
-172,
-146,
-241,
-156,
-44,
-203,
-30,
-242,
-212,
-63,
-133,
-44,
-203,
-30,
-53,
-198,
-88,
-251,
-251,
-218,
-19,
-133,
-44,
-203,
-230,
-24,
-99,
-78,
-49,
-198,
-172,
-105,
-228,
-190,
-79,
-200,
-178,
-44,
-228,
-136,
-108,
-145,
-49,
-102,
-101,
-99,
-204,
-22,
-198,
-152,
-101,
-140,
-140,
-181,
-151,
-100,
-89,
-118,
-71,
-64,
-219,
-132,
-30,
-225,
-10,
-128,
-51,
-140,
-76,
-178,
-101,
-141,
-49,
-135,
-213,
-180,
-251,
-137,
-145,
-1,
-125,
-179,
-49,
-230,
-175,
-158,
-122,
-155,
-81,
-40,
-200,
-218,
-204,
-24,
-51,
-75,
-255,
-250,
-194,
-28,
-197,
-228,
-21,
-83,
-152,
-216,
-201,
-181,
-142,
-49,
-198,
-32,
-75,
-232,
-99,
-140,
-49,
-75,
-26,
-99,
-246,
-203,
-178,
-172,
-24,
-74,
-202,
-78,
-218,
-251,
-61,
-188,
-174,
-214,
-191,
-161,
-89,
-100,
-172,
-64,
-242,
-153,
-81,
-199,
-20,
-114,
-3,
-200,
-178,
-236,
-19,
-89,
-142,
-111,
-7,
-182,
-153,
-145,
-101,
-217,
-58,
-89,
-150,
-45,
-147,
-101,
-217,
-74,
-89,
-150,
-189,
-61,
-203,
-178,
-59,
-3,
-251,
-151,
-208,
-35,
-158,
-18,
-0,
-89,
-150,
-205,
-53,
-198,
-124,
-220,
-24,
-179,
-208,
-24,
-179,
-43,
-21,
-105,
-143,
-140,
-49,
-187,
-25,
-99,
-230,
-26,
-99,
-62,
-146,
-101,
-217,
-66,
-15,
-223,
-25,
-250,
-119,
-57,
-79,
-157,
-15,
-85,
-95,
-199,
-152,
-188,
-98,
-10,
-19,
-59,
-249,
-236,
-196,
-217,
-215,
-200,
-228,
-59,
-47,
-203,
-50,
-95,
-54,
-88,
-75,
-119,
-165,
-167,
-174,
-237,
-234,
-107,
-192,
-175,
-222,
-196,
-21,
-114,
-9,
-139,
-57,
-70,
-68,
-94,
-201,
-178,
-236,
-28,
-99,
-204,
-123,
-141,
-49,
-79,
-24,
-99,
-118,
-49,
-198,
-76,
-193,
-73,
-123,
-100,
-100,
-201,
-185,
-171,
-49,
-230,
-65,
-99,
-204,
-142,
-89,
-150,
-149,
-125,
-101,
-218,
-46,
-105,
-125,
-95,
-199,
-152,
-188,
-98,
-10,
-147,
-127,
-232,
-223,
-29,
-16,
-141,
-243,
-119,
-140,
-8,
-150,
-189,
-139,
-132,
-1,
-91,
-166,
-54,
-171,
-175,
-27,
-77,
-46,
-56,
-92,
-196,
-20,
-114,
-227,
-2,
-136,
-157,
-197,
-41,
-148,
-28,
-143,
-33,
-217,
-129,
-254,
-136,
-39,
-100,
-151,
-214,
-23,
-209,
-58,
-200,
-40,
-18,
-196,
-117,
-111,
-224,
-31,
-192,
-125,
-136,
-237,
-197,
-52,
-228,
-136,
-239,
-135,
-56,
-14,
-113,
-37,
-237,
-59,
-185,
-168,
-211,
-209,
-249,
-203,
-50,
-233,
-148,
-246,
-136,
-184,
-10,
-197,
-152,
-188,
-98,
-158,
-116,
-44,
-67,
-158,
-196,
-209,
-42,
-210,
-6,
-142,
-4,
-149,
-182,
-54,
-83,
-44,
-205,
-146,
-78,
-206,
-162,
-228,
-152,
-139,
-136,
-199,
-185,
-227,
-5,
-58,
-232,
-209,
-231,
-252,
-101,
-224,
-6,
-125,
-39,
-147,
-145,
-99,
-189,
-83,
-181,
-222,
-39,
-48,
-125,
-199,
-138,
-173,
-130,
-140,
-34,
-169,
-207,
-111,
-119,
-218,
-77,
-69,
-20,
-159,
-55,
-146,
-91,
-38,
-86,
-230,
-112,
-164,
-163,
-139,
-58,
-29,
-157,
-191,
-162,
-128,
-136,
-121,
-212,
-35,
-243,
-138,
-38,
-76,
-180,
-126,
-123,
-231,
-197,
-78,
-7,
-54,
-45,
-212,
-55,
-202,
-20,
-75,
-120,
-210,
-201,
-109,
-43,
-120,
-68,
-19,
-114,
-49,
-64,
-216,
-241,
-226,
-234,
-192,
-33,
-136,
-127,
-195,
-92,
-202,
-225,
-245,
-55,
-64,
-162,
-232,
-252,
-202,
-161,
-187,
-29,
-17,
-162,
-147,
-157,
-178,
-83,
-40,
-113,
-55,
-118,
-104,
-90,
-7,
-25,
-5,
-94,
-64,
-46,
-124,
-255,
-11,
-108,
-83,
-168,
-95,
-11,
-137,
-16,
-84,
-155,
-48,
-148,
-14,
-46,
-234,
-68,
-112,
-254,
-234,
-12,
-34,
-230,
-81,
-143,
-204,
-43,
-154,
-48,
-81,
-154,
-103,
-146,
-219,
-3,
-128,
-56,
-108,
-220,
-197,
-160,
-197,
-93,
-112,
-166,
-88,
-6,
-87,
-95,
-11,
-201,
-133,
-204,
-69,
-212,
-251,
-40,
-68,
-21,
-114,
-129,
-60,
-90,
-135,
-144,
-215,
-251,
-181,
-95,
-205,
-219,
-129,
-99,
-128,
-163,
-129,
-91,
-157,
-231,
-119,
-55,
-226,
-33,
-87,
-122,
-239,
-228,
-246,
-242,
-199,
-49,
-210,
-97,
-201,
-90,
-28,
-126,
-161,
-162,
-173,
-69,
-171,
-32,
-163,
-74,
-99,
-45,
-16,
-175,
-37,
-66,
-204,
-126,
-58,
-186,
-168,
-143,
-58,
-136,
-152,
-71,
-61,
-22,
-47,
-34,
-10,
-19,
-165,
-57,
-70,
-105,
-14,
-71,
-246,
-138,
-255,
-209,
-151,
-22,
-37,
-83,
-172,
-115,
-29,
-43,
-184,
-102,
-2,
-149,
-186,
-16,
-34,
-11,
-185,
-192,
-254,
-29,
-71,
-203,
-16,
-242,
-192,
-79,
-245,
-250,
-255,
-194,
-49,
-224,
-65,
-246,
-237,
-103,
-107,
-93,
-109,
-48,
-76,
-100,
-245,
-48,
-3,
-88,
-190,
-80,
-158,
-33,
-1,
-54,
-7,
-220,
-130,
-29,
-26,
-139,
-86,
-65,
-70,
-201,
-45,
-63,
-33,
-32,
-136,
-232,
-132,
-1,
-17,
-243,
-168,
-199,
-226,
-69,
-92,
-193,
-180,
-2,
-146,
-66,
-189,
-215,
-220,
-121,
-200,
-18,
-215,
-46,
-103,
-47,
-5,
-158,
-94,
-65,
-27,
-85,
-200,
-5,
-246,
-175,
-117,
-8,
-121,
-114,
-147,
-224,
-29,
-61,
-117,
-111,
-214,
-186,
-255,
-5,
-244,
-97,
-54,
-37,
-201,
-57,
-144,
-85,
-209,
-204,
-138,
-182,
-22,
-173,
-130,
-140,
-34,
-43,
-22,
-40,
-49,
-227,
-29,
-22,
-144,
-109,
-198,
-65,
-136,
-192,
-155,
-129,
-8,
-247,
-255,
-34,
-65,
-74,
-26,
-101,
-75,
-50,
-192,
-243,
-145,
-101,
-213,
-165,
-200,
-87,
-109,
-46,
-98,
-111,
-125,
-35,
-98,
-6,
-250,
-57,
-28,
-39,
-138,
-10,
-62,
-209,
-242,
-168,
-199,
-226,
-69,
-68,
-193,
-52,
-44,
-32,
-49,
-16,
-173,
-91,
-241,
-5,
-84,
-36,
-153,
-32,
-162,
-144,
-11,
-236,
-91,
-107,
-231,
-20,
-242,
-61,
-255,
-102,
-158,
-186,
-205,
-180,
-110,
-150,
-175,
-109,
-129,
-246,
-118,
-68,
-219,
-62,
-32,
-28,
-17,
-13,
-252,
-109,
-21,
-109,
-67,
-4,
-64,
-105,
-144,
-81,
-157,
-112,
-0,
-223,
-173,
-235,
-103,
-9,
-239,
-5,
-250,
-111,
-243,
-10,
-154,
-45,
-108,
-39,
-75,
-234,
-95,
-69,
-110,
-101,
-57,
-11,
-9,
-117,
-126,
-13,
-249,
-202,
-229,
-30,
-42,
-2,
-210,
-184,
-140,
-150,
-71,
-150,
-116,
-118,
-223,
-185,
-0,
-89,
-94,
-93,
-142,
-104,
-87,
-109,
-148,
-88,
-232,
-224,
-49,
-53,
-218,
-32,
-162,
-96,
-26,
-22,
-16,
-51,
-95,
-27,
-101,
-168,
-50,
-172,
-58,
-227,
-68,
-200,
-145,
-231,
-196,
-27,
-176,
-68,
-36,
-79,
-206,
-225,
-59,
-210,
-45,
-210,
-218,
-40,
-58,
-199,
-48,
-210,
-149,
-214,
-78,
-220,
-210,
-12,
-63,
-206,
-243,
-168,
-18,
-0,
-165,
-65,
-70,
-157,
-231,
-252,
-209,
-186,
-126,
-118,
-184,
-126,
-169,
-0,
-64,
-20,
-125,
-246,
-68,
-234,
-199,
-56,
-66,
-16,
-153,
-207,
-214,
-235,
-241,
-14,
-10,
-91,
-164,
-34,
-163,
-21,
-201,
-195,
-33,
-61,
-12,
-124,
-134,
-194,
-210,
-1,
-89,
-98,
-110,
-143,
-68,
-62,
-45,
-93,
-138,
-38,
-244,
-3,
-96,
-23,
-2,
-61,
-240,
-232,
-81,
-200,
-21,
-132,
-72,
-41,
-159,
-170,
-129,
-171,
-245,
-214,
-49,
-104,
-50,
-78,
-0,
-77,
-36,
-169,
-198,
-127,
-237,
-164,
-174,
-233,
-75,
-230,
-240,
-1,
-249,
-96,
-157,
-236,
-180,
-135,
-138,
-175,
-115,
-224,
-4,
-44,
-13,
-50,
-74,
-67,
-103,
-174,
-150,
-215,
-175,
-18,
-0,
-214,
-255,
-165,
-204,
-147,
-48,
-67,
-20,
-211,
-0,
-159,
-173,
-234,
-136,
-117,
-150,
-185,
-135,
-228,
-168,
-145,
-80,
-1,
-70,
-162,
-42,
-225,
-103,
-157,
-0,
-88,
-93,
-39,
-44,
-136,
-128,
-186,
-65,
-133,
-129,
-221,
-26,
-76,
-193,
-73,
-217,
-85,
-194,
-227,
-56,
-165,
-253,
-13,
-162,
-140,
-189,
-17,
-89,
-6,
-223,
-164,
-191,
-109,
-236,
-127,
-239,
-185,
-122,
-224,
-4,
-252,
-168,
-210,
-12,
-4,
-25,
-37,
-63,
-254,
-251,
-112,
-85,
-63,
-43,
-120,
-119,
-21,
-0,
-151,
-106,
-213,
-167,
-42,
-218,
-127,
-86,
-105,
-46,
-40,
-35,
-120,
-137,
-211,
-145,
-237,
-189,
-68,
-9,
-9,
-10,
-29,
-39,
-139,
-16,
-101,
-211,
-92,
-10,
-49,
-7,
-28,
-186,
-74,
-1,
-160,
-52,
-171,
-146,
-123,
-125,
-46,
-64,
-244,
-18,
-55,
-35,
-231,
-230,
-171,
-5,
-244,
-229,
-173,
-192,
-31,
-40,
-183,
-4,
-92,
-22,
-73,
-178,
-234,
-141,
-242,
-27,
-56,
-1,
-171,
-130,
-140,
-90,
-219,
-139,
-218,
-4,
-174,
-29,
-174,
-95,
-37,
-0,
-108,
-44,
-132,
-82,
-215,
-108,
-224,
-141,
-101,
-2,
-204,
-18,
-28,
-166,
-4,
-215,
-182,
-185,
-137,
-16,
-208,
-33,
-149,
-23,
-49,
-76,
-28,
-19,
-162,
-193,
-25,
-180,
-223,
-210,
-191,
-139,
-86,
-90,
-155,
-0,
-0,
-32,
-0,
-73,
-68,
-65,
-84,
-222,
-140,
-196,
-129,
-2,
-224,
-215,
-136,
-206,
-105,
-167,
-254,
-122,
-92,
-142,
-192,
-9,
-88,
-21,
-100,
-212,
-218,
-94,
-84,
-166,
-18,
-239,
-120,
-253,
-42,
-1,
-96,
-149,
-195,
-85,
-39,
-86,
-175,
-84,
-154,
-1,
-119,
-116,
-75,
-96,
-247,
-254,
-223,
-111,
-115,
-19,
-33,
-160,
-67,
-42,
-47,
-122,
-48,
-113,
-108,
-34,
-144,
-234,
-94,
-18,
-178,
-207,
-178,
-3,
-225,
-34,
-156,
-56,
-243,
-139,
-35,
-156,
-231,
-241,
-108,
-242,
-0,
-40,
-3,
-105,
-189,
-3,
-5,
-192,
-44,
-228,
-200,
-106,
-83,
-106,
-50,
-3,
-247,
-129,
-128,
-119,
-91,
-25,
-100,
-20,
-120,
-175,
-214,
-45,
-4,
-158,
-23,
-251,
-250,
-74,
-83,
-37,
-0,
-108,
-164,
-160,
-170,
-24,
-150,
-219,
-41,
-205,
-64,
-64,
-154,
-34,
-147,
-221,
-155,
-222,
-64,
-8,
-232,
-152,
-202,
-139,
-30,
-76,
-28,
-105,
-32,
-144,
-2,
-6,
-137,
-53,
-104,
-249,
-175,
-237,
-99,
-5,
-143,
-78,
-138,
-51,
-15,
-253,
-174,
-74,
-94,
-155,
-89,
-55,
-128,
-215,
-55,
-156,
-126,
-174,
-82,
-65,
-103,
-177,
-62,
-185,
-130,
-236,
-6,
-10,
-203,
-240,
-144,
-123,
-97,
-164,
-25,
-175,
-139,
-25,
-136,
-113,
-85,
-109,
-134,
-223,
-46,
-168,
-122,
-183,
-4,
-4,
-25,
-69,
-140,
-150,
-172,
-53,
-227,
-165,
-64,
-168,
-179,
-89,
-237,
-245,
-29,
-154,
-42,
-1,
-112,
-145,
-86,
-149,
-42,
-248,
-144,
-99,
-123,
-128,
-139,
-203,
-8,
-236,
-50,
-194,
-171,
-201,
-44,
-121,
-65,
-193,
-241,
-210,
-137,
-148,
-202,
-43,
-22,
-104,
-40,
-144,
-106,
-6,
-137,
-53,
-55,
-189,
-3,
-40,
-117,
-171,
-45,
-60,
-186,
-214,
-138,
-179,
-2,
-173,
-59,
-248,
-158,
-164,
-194,
-62,
-32,
-128,
-151,
-107,
-107,
-0,
-97,
-2,
-96,
-83,
-253,
-125,
-158,
-254,
-254,
-92,
-129,
-174,
-78,
-9,
-248,
-2,
-68,
-121,
-103,
-147,
-97,
-62,
-162,
-255,
-30,
-103,
-100,
-98,
-149,
-248,
-113,
-240,
-6,
-239,
-165,
-117,
-144,
-81,
-36,
-196,
-184,
-85,
-92,
-94,
-173,
-109,
-151,
-40,
-208,
-108,
-4,
-236,
-27,
-114,
-125,
-15,
-77,
-149,
-0,
-176,
-153,
-150,
-188,
-222,
-185,
-140,
-60,
-5,
-248,
-82,
-217,
-5,
-172,
-34,
-225,
-35,
-37,
-245,
-151,
-56,
-255,
-174,
-45,
-235,
-204,
-120,
-1,
-13,
-5,
-82,
-217,
-75,
-34,
-15,
-142,
-249,
-32,
-37,
-138,
-176,
-2,
-143,
-40,
-138,
-51,
-135,
-246,
-51,
-74,
-106,
-99,
-244,
-253,
-40,
-228,
-126,
-60,
-124,
-150,
-67,
-180,
-230,
-247,
-146,
-159,
-41,
-135,
-8,
-128,
-23,
-235,
-239,
-23,
-35,
-10,
-188,
-199,
-113,
-194,
-164,
-215,
-12,
-220,
-237,
-17,
-205,
-255,
-21,
-192,
-11,
-61,
-245,
-43,
-146,
-39,
-30,
-237,
-197,
-89,
-169,
-112,
-47,
-93,
-131,
-140,
-190,
-9,
-57,
-102,
-181,
-120,
-20,
-49,
-198,
-185,
-66,
-199,
-90,
-217,
-115,
-240,
-142,
-173,
-2,
-77,
-213,
-115,
-92,
-158,
-252,
-35,
-240,
-115,
-156,
-179,
-126,
-125,
-175,
-246,
-136,
-244,
-94,
-74,
-86,
-167,
-6,
-152,
-164,
-68,
-7,
-4,
-220,
-104,
-163,
-37,
-106,
-27,
-32,
-103,
-216,
-118,
-223,
-95,
-154,
-117,
-6,
-217,
-159,
-129,
-76,
-168,
-129,
-248,
-252,
-17,
-251,
-51,
-240,
-146,
-144,
-189,
-223,
-66,
-228,
-203,
-235,
-205,
-250,
-83,
-194,
-227,
-91,
-250,
-183,
-181,
-226,
-76,
-233,
-86,
-68,
-4,
-207,
-253,
-200,
-82,
-245,
-106,
-228,
-75,
-245,
-172,
-22,
-247,
-247,
-11,
-189,
-228,
-62,
-206,
-96,
-13,
-17,
-0,
-238,
-243,
-56,
-82,
-203,
-142,
-114,
-202,
-170,
-6,
-174,
-61,
-254,
-219,
-164,
-226,
-58,
-171,
-42,
-77,
-111,
-238,
-172,
-12,
-162,
-85,
-144,
-81,
-229,
-181,
-18,
-226,
-130,
-124,
-62,
-178,
-181,
-156,
-175,
-255,
-30,
-68,
-44,
-56,
-7,
-188,
-52,
-125,
-207,
-210,
-67,
-83,
-183,
-146,
-122,
-33,
-185,
-11,
-243,
-108,
-68,
-240,
-216,
-241,
-128,
-94,
-191,
-60,
-2,
-51,
-249,
-126,
-216,
-191,
-71,
-8,
-236,
-12,
-121,
-134,
-84,
-128,
-15,
-86,
-240,
-120,
-151,
-210,
-60,
-89,
-54,
-208,
-200,
-205,
-85,
-171,
-150,
-203,
-7,
-41,
-205,
-169,
-101,
-52,
-49,
-80,
-124,
-73,
-136,
-82,
-101,
-46,
-34,
-164,
-182,
-109,
-200,
-163,
-179,
-226,
-76,
-233,
-236,
-209,
-212,
-167,
-244,
-247,
-219,
-245,
-247,
-145,
-13,
-239,
-109,
-7,
-109,
-247,
-111,
-196,
-239,
-192,
-42,
-70,
-155,
-10,
-128,
-53,
-144,
-21,
-192,
-83,
-102,
-173,
-53,
-99,
-197,
-46,
-153,
-253,
-95,
-37,
-243,
-212,
-22,
-1,
-96,
-177,
-141,
-31,
-232,
-60,
-239,
-82,
-171,
-76,
-224,
-13,
-74,
-227,
-11,
-78,
-99,
-105,
-86,
-65,
-236,
-254,
-255,
-139,
-40,
-85,
-103,
-34,
-102,
-202,
-223,
-163,
-238,
-227,
-232,
-92,
-0,
-106,
-150,
-197,
-117,
-3,
-148,
-60,
-67,
-170,
-215,
-57,
-67,
-105,
-46,
-86,
-154,
-3,
-43,
-104,
-182,
-81,
-26,
-111,
-230,
-89,
-100,
-159,
-102,
-67,
-96,
-15,
-76,
-36,
-165,
-137,
-178,
-146,
-112,
-7,
-60,
-226,
-170,
-57,
-29,
-249,
-250,
-15,
-36,
-113,
-168,
-184,
-134,
-69,
-12,
-197,
-217,
-154,
-218,
-135,
-187,
-112,
-252,
-220,
-17,
-201,
-63,
-143,
-64,
-67,
-46,
-196,
-16,
-231,
-126,
-229,
-181,
-161,
-150,
-89,
-115,
-239,
-70,
-2,
-64,
-203,
-173,
-178,
-233,
-124,
-253,
-253,
-162,
-178,
-123,
-33,
-223,
-95,
-123,
-93,
-117,
-145,
-252,
-5,
-151,
-43,
-205,
-183,
-67,
-238,
-103,
-60,
-130,
-124,
-245,
-253,
-241,
-10,
-26,
-155,
-197,
-168,
-116,
-78,
-197,
-232,
-200,
-191,
-157,
-65,
-89,
-234,
-74,
-90,
-55,
-64,
-25,
-185,
-10,
-24,
-8,
-195,
-68,
-158,
-108,
-114,
-58,
-53,
-74,
-43,
-100,
-95,
-10,
-254,
-0,
-31,
-246,
-203,
-53,
-133,
-138,
-227,
-35,
-34,
-172,
-36,
-156,
-1,
-191,
-3,
-185,
-208,
-241,
-133,
-247,
-170,
-186,
-23,
-139,
-78,
-138,
-51,
-165,
-177,
-246,
-221,
-123,
-22,
-202,
-173,
-253,
-124,
-80,
-54,
-89,
-114,
-47,
-183,
-61,
-156,
-50,
-171,
-124,
-107,
-35,
-0,
-150,
-210,
-241,
-3,
-240,
-30,
-36,
-194,
-141,
-247,
-94,
-16,
-197,
-153,
-93,
-162,
-254,
-27,
-217,
-171,
-254,
-16,
-248,
-37,
-162,
-217,
-182,
-10,
-201,
-83,
-41,
-9,
-230,
-177,
-56,
-128,
-60,
-148,
-252,
-85,
-248,
-79,
-25,
-50,
-242,
-172,
-65,
-223,
-235,
-179,
-35,
-27,
-146,
-31,
-7,
-222,
-141,
-56,
-64,
-12,
-228,
-109,
-67,
-60,
-143,
-234,
-6,
-168,
-93,
-5,
-252,
-203,
-83,
-103,
-39,
-100,
-173,
-194,
-10,
-248,
-130,
-210,
-14,
-4,
-192,
-68,
-60,
-221,
-160,
-230,
-248,
-139,
-56,
-43,
-9,
-139,
-251,
-116,
-130,
-44,
-212,
-191,
-193,
-137,
-49,
-28,
-30,
-173,
-21,
-103,
-90,
-191,
-33,
-242,
-149,
-190,
-181,
-120,
-63,
-206,
-96,
-89,
-72,
-141,
-247,
-23,
-185,
-121,
-235,
-31,
-11,
-229,
-22,
-141,
-5,
-128,
-214,
-89,
-55,
-222,
-41,
-228,
-57,
-0,
-203,
-238,
-101,
-19,
-100,
-251,
-121,
-51,
-34,
-12,
-22,
-32,
-219,
-194,
-73,
-136,
-99,
-207,
-152,
-241,
-200,
-236,
-11,
-136,
-223,
-131,
-13,
-44,
-115,
-56,
-206,
-156,
-67,
-244,
-60,
-86,
-183,
-242,
-8,
-53,
-102,
-209,
-49,
-58,
-243,
-60,
-242,
-37,
-9,
-58,
-208,
-110,
-38,
-207,
-229,
-126,
-47,
-206,
-241,
-76,
-5,
-31,
-119,
-21,
-176,
-165,
-83,
-190,
-14,
-34,
-217,
-103,
-81,
-227,
-43,
-174,
-244,
-171,
-35,
-75,
-248,
-249,
-56,
-171,
-18,
-68,
-57,
-52,
-71,
-7,
-250,
-122,
-1,
-124,
-58,
-173,
-36,
-156,
-231,
-49,
-21,
-73,
-189,
-101,
-87,
-12,
-247,
-16,
-232,
-107,
-237,
-155,
-52,
-52,
-84,
-156,
-105,
-189,
-141,
-80,
-227,
-77,
-37,
-134,
-228,
-5,
-4,
-143,
-208,
-116,
-104,
-214,
-215,
-65,
-119,
-63,
-133,
-85,
-152,
-211,
-207,
-86,
-2,
-64,
-235,
-255,
-162,
-245,
-7,
-215,
-141,
-149,
-97,
-129,
-6,
-49,
-15,
-128,
-79,
-59,
-247,
-88,
-233,
-121,
-25,
-3,
-58,
-166,
-108,
-112,
-22,
-87,
-137,
-103,
-221,
-121,
-31,
-167,
-16,
-102,
-172,
-207,
-206,
-44,
-1,
-188,
-31,
-89,
-122,
-77,
-33,
-151,
-204,
-51,
-144,
-227,
-134,
-115,
-244,
-197,
-122,
-163,
-172,
-58,
-124,
-236,
-42,
-192,
-205,
-40,
-107,
-7,
-196,
-79,
-27,
-244,
-231,
-183,
-218,
-102,
-63,
-167,
-236,
-83,
-90,
-118,
-118,
-85,
-91,
-135,
-190,
-211,
-74,
-194,
-25,
-12,
-175,
-210,
-223,
-75,
-147,
-71,
-112,
-13,
-50,
-70,
-242,
-77,
-26,
-154,
-43,
-206,
-182,
-68,
-4,
-240,
-13,
-148,
-11,
-171,
-140,
-92,
-136,
-15,
-28,
-95,
-233,
-251,
-189,
-72,
-249,
-248,
-148,
-144,
-22,
-93,
-4,
-192,
-198,
-228,
-74,
-82,
-239,
-189,
-244,
-1,
-58,
-132,
-39,
-115,
-120,
-188,
-72,
-199,
-250,
-52,
-253,
-55,
-3,
-120,
-65,
-191,
-61,
-55,
-6,
-217,
-46,
-253,
-28,
-57,
-29,
-153,
-173,
-215,
-189,
-30,
-217,
-34,
-4,
-127,
-249,
-233,
-24,
-89,
-56,
-26,
-200,
-87,
-1,
-11,
-144,
-101,
-235,
-242,
-200,
-249,
-234,
-28,
-224,
-217,
-13,
-248,
-216,
-60,
-238,
-215,
-59,
-101,
-246,
-38,
-223,
-27,
-200,
-163,
-211,
-74,
-162,
-100,
-242,
-110,
-66,
-46,
-181,
-107,
-61,
-193,
-202,
-38,
-13,
-205,
-20,
-103,
-255,
-12,
-185,
-111,
-100,
-255,
-13,
-112,
-174,
-167,
-206,
-250,
-200,
-123,
-67,
-144,
-59,
-253,
-108,
-45,
-0,
-148,
-230,
-71,
-14,
-221,
-176,
-4,
-192,
-113,
-180,
-12,
-79,
-166,
-237,
-215,
-66,
-162,
-20,
-77,
-3,
-94,
-13,
-188,
-14,
-153,
-136,
-119,
-16,
-176,
-98,
-29,
-11,
-160,
-99,
-100,
-225,
-216,
-157,
-177,
-171,
-128,
-35,
-200,
-151,
-85,
-71,
-213,
-183,
-28,
-224,
-99,
-61,
-174,
-94,
-138,
-216,
-140,
-131,
-196,
-44,
-8,
-86,
-14,
-209,
-97,
-37,
-81,
-54,
-224,
-201,
-181,
-179,
-79,
-226,
-248,
-179,
-55,
-228,
-17,
-172,
-56,
-139,
-1,
-242,
-227,
-183,
-91,
-116,
-114,
-20,
-255,
-89,
-88,
-215,
-92,
-95,
-88,
-116,
-239,
-189,
-20,
-104,
-86,
-162,
-194,
-0,
-166,
-15,
-208,
-33,
-60,
-153,
-182,
-185,
-10,
-89,
-245,
-190,
-216,
-41,
-123,
-41,
-114,
-218,
-226,
-203,
-196,
-52,
-38,
-65,
-135,
-200,
-194,
-177,
-59,
-98,
-87,
-1,
-179,
-244,
-193,
-206,
-175,
-155,
-40,
-37,
-124,
-172,
-185,
-227,
-129,
-228,
-246,
-234,
-63,
-110,
-200,
-163,
-245,
-74,
-162,
-106,
-192,
-3,
-103,
-105,
-221,
-37,
-84,
-236,
-51,
-107,
-120,
-4,
-43,
-206,
-186,
-130,
-22,
-232,
-163,
-31,
-37,
-125,
-235,
-20,
-215,
-142,
-14,
-225,
-201,
-22,
-55,
-48,
-86,
-34,
-11,
-147,
-175,
-2,
-0,
-126,
-221,
-146,
-199,
-106,
-200,
-190,
-200,
-42,
-35,
-161,
-197,
-190,
-140,
-150,
-43,
-137,
-154,
-201,
-187,
-38,
-249,
-146,
-235,
-235,
-109,
-120,
-104,
-253,
-152,
-80,
-156,
-57,
-253,
-44,
-221,
-2,
-244,
-116,
-221,
-56,
-113,
-237,
-18,
-226,
-129,
-14,
-62,
-252,
-14,
-143,
-85,
-156,
-65,
-245,
-234,
-14,
-125,
-57,
-17,
-57,
-149,
-88,
-4,
-92,
-214,
-146,
-71,
-171,
-149,
-68,
-192,
-228,
-125,
-155,
-214,
-207,
-167,
-100,
-201,
-21,
-192,
-99,
-84,
-20,
-103,
-158,
-126,
-12,
-93,
-0,
-16,
-41,
-174,
-29,
-221,
-87,
-16,
-209,
-34,
-235,
-34,
-167,
-103,
-181,
-122,
-135,
-26,
-30,
-157,
-231,
-95,
-39,
-208,
-193,
-135,
-191,
-192,
-167,
-114,
-240,
-7,
-242,
-216,
-202,
-225,
-243,
-177,
-150,
-60,
-90,
-173,
-36,
-66,
-250,
-143,
-232,
-57,
-64,
-246,
-214,
-3,
-131,
-52,
-144,
-199,
-208,
-21,
-103,
-158,
-62,
-140,
-134,
-0,
-232,
-28,
-215,
-142,
-142,
-43,
-136,
-174,
-237,
-61,
-252,
-126,
-5,
-124,
-38,
-148,
-190,
-132,
-71,
-163,
-249,
-71,
-228,
-208,
-224,
-157,
-124,
-248,
-11,
-188,
-106,
-7,
-127,
-0,
-15,
-187,
-55,
-158,
-142,
-199,
-64,
-169,
-1,
-159,
-206,
-43,
-137,
-150,
-215,
-13,
-17,
-0,
-67,
-87,
-156,
-121,
-250,
-208,
-73,
-0,
-208,
-34,
-65,
-38,
-29,
-227,
-218,
-209,
-113,
-5,
-209,
-181,
-125,
-31,
-104,
-58,
-255,
-136,
-189,
-133,
-34,
-162,
-15,
-127,
-36,
-1,
-96,
-253,
-238,
-143,
-237,
-216,
-151,
-206,
-43,
-137,
-4,
-63,
-104,
-153,
-32,
-147,
-142,
-113,
-237,
-232,
-184,
-130,
-232,
-218,
-190,
-15,
-52,
-153,
-127,
-99,
-81,
-128,
-21,
-59,
-216,
-73,
-0,
-32,
-71,
-101,
-119,
-42,
-143,
-114,
-183,
-198,
-48,
-94,
-81,
-86,
-18,
-9,
-35,
-65,
-135,
-4,
-153,
-116,
-140,
-107,
-71,
-247,
-21,
-68,
-140,
-21,
-72,
-40,
-46,
-41,
-187,
-70,
-91,
-208,
-82,
-128,
-141,
-139,
-35,
-19,
-68,
-67,
-127,
-168,
-49,
-102,
-125,
-99,
-204,
-133,
-89,
-150,
-117,
-61,
-143,
-181,
-38,
-180,
-167,
-100,
-89,
-54,
-163,
-35,
-175,
-4,
-35,
-3,
-204,
-24,
-115,
-130,
-49,
-102,
-101,
-99,
-204,
-117,
-198,
-152,
-173,
-179,
-44,
-27,
-225,
-186,
-154,
-101,
-217,
-131,
-198,
-24,
-111,
-10,
-117,
-99,
-204,
-52,
-99,
-204,
-106,
-198,
-152,
-42,
-129,
-188,
-162,
-67,
-91,
-132,
-205,
-204,
-124,
-99,
-69,
-123,
-123,
-252,
-235,
-91,
-6,
-119,
-109,
-191,
-192,
-24,
-19,
-154,
-26,
-172,
-52,
-79,
-97,
-7,
-216,
-128,
-170,
-222,
-116,
-112,
-89,
-150,
-129,
-56,
-136,
-189,
-220,
-24,
-243,
-110,
-99,
-204,
-207,
-70,
-16,
-16,
-33,
-61,
-81,
-21,
-28,
-233,
-23,
-180,
-2,
-64,
-246,
-194,
-215,
-171,
-212,
-178,
-251,
-154,
-39,
-232,
-152,
-175,
-128,
-136,
-43,
-137,
-132,
-28,
-116,
-76,
-144,
-73,
-199,
-184,
-118,
-116,
-95,
-65,
-116,
-143,
-172,
-27,
-1,
-180,
-84,
-226,
-209,
-53,
-52,
-120,
-200,
-4,
-237,
-34,
-0,
-154,
-2,
-73,
-188,
-121,
-47,
-185,
-2,
-233,
-76,
-2,
-114,
-17,
-214,
-240,
-92,
-134,
-60,
-60,
-210,
-5,
-145,
-186,
-106,
-121,
-23,
-49,
-23,
-217,
-147,
-253,
-3,
-248,
-24,
-53,
-6,
-42,
-228,
-129,
-39,
-75,
-51,
-225,
-146,
-251,
-51,
-84,
-126,
-105,
-104,
-17,
-66,
-189,
-235,
-251,
-167,
-99,
-130,
-76,
-58,
-198,
-181,
-163,
-99,
-100,
-220,
-174,
-237,
-99,
-128,
-14,
-74,
-60,
-186,
-10,
-176,
-174,
-3,
-96,
-172,
-130,
-158,
-86,
-18,
-158,
-235,
-88,
-216,
-184,
-114,
-87,
-58,
-215,
-3,
-9,
-128,
-82,
-26,
-45,
-150,
-220,
-142,
-224,
-94,
-252,
-57,
-232,
-151,
-32,
-87,
-174,
-13,
-228,
-209,
-43,
-208,
-54,
-14,
-161,
-222,
-245,
-253,
-211,
-61,
-65,
-102,
-167,
-184,
-118,
-116,
-95,
-65,
-116,
-143,
-172,
-59,
-72,
-255,
-107,
-2,
-143,
-1,
-233,
-126,
-138,
-209,
-77,
-128,
-117,
-29,
-0,
-99,
-21,
-244,
-176,
-146,
-40,
-185,
-206,
-192,
-243,
-67,
-38,
-237,
-174,
-228,
-19,
-242,
-59,
-21,
-237,
-109,
-30,
-123,
-240,
-231,
-160,
-183,
-2,
-226,
-22,
-106,
-98,
-231,
-211,
-34,
-132,
-122,
-215,
-247,
-79,
-199,
-4,
-153,
-202,
-163,
-117,
-92,
-59,
-186,
-175,
-32,
-186,
-71,
-214,
-29,
-108,
-115,
-51,
-112,
-116,
-32,
-109,
-215,
-83,
-140,
-110,
-2,
-172,
-235,
-0,
-152,
-232,
-168,
-122,
-126,
-192,
-207,
-180,
-174,
-74,
-193,
-100,
-128,
-15,
-41,
-221,
-149,
-158,
-186,
-127,
-104,
-221,
-39,
-98,
-246,
-219,
-225,
-223,
-233,
-253,
-211,
-49,
-65,
-166,
-195,
-167,
-85,
-92,
-59,
-186,
-175,
-32,
-186,
-71,
-214,
-237,
-118,
-223,
-93,
-79,
-33,
-186,
-9,
-176,
-174,
-3,
-192,
-211,
-153,
-115,
-129,
-29,
-156,
-178,
-231,
-33,
-174,
-154,
-222,
-32,
-22,
-227,
-29,
-85,
-207,
-15,
-137,
-173,
-0,
-48,
-167,
-134,
-135,
-171,
-160,
-220,
-202,
-41,
-223,
-4,
-49,
-90,
-122,
-136,
-158,
-50,
-50,
-119,
-125,
-255,
-116,
-76,
-144,
-25,
-3,
-116,
-140,
-140,
-219,
-181,
-125,
-199,
-190,
-119,
-181,
-131,
-232,
-38,
-192,
-186,
-14,
-128,
-2,
-221,
-1,
-228,
-246,
-203,
-23,
-35,
-89,
-135,
-23,
-34,
-231,
-238,
-223,
-174,
-106,
-235,
-240,
-24,
-106,
-68,
-150,
-174,
-168,
-122,
-126,
-72,
-104,
-105,
-0,
-223,
-241,
-85,
-145,
-214,
-222,
-247,
-31,
-157,
-50,
-251,
-242,
-170,
-2,
-150,
-116,
-58,
-197,
-233,
-250,
-254,
-233,
-152,
-32,
-51,
-22,
-232,
-18,
-25,
-55,
-66,
-251,
-14,
-253,
-238,
-124,
-10,
-65,
-23,
-1,
-214,
-117,
-0,
-120,
-104,
-119,
-33,
-247,
-59,
-7,
-177,
-189,
-175,
-205,
-244,
-170,
-109,
-71,
-37,
-34,
-75,
-23,
-84,
-61,
-63,
-36,
-200,
-37,
-4,
-68,
-47,
-66,
-226,
-251,
-63,
-132,
-8,
-204,
-231,
-34,
-49,
-225,
-166,
-233,
-75,
-172,
-90,
-2,
-119,
-157,
-192,
-93,
-219,
-119,
-74,
-144,
-57,
-209,
-65,
-164,
-83,
-8,
-218,
-10,
-176,
-88,
-2,
-0,
-216,
-131,
-60,
-28,
-213,
-125,
-136,
-115,
-203,
-44,
-100,
-9,
-91,
-27,
-189,
-135,
-150,
-17,
-89,
-136,
-247,
-5,
-12,
-66,
-69,
-251,
-162,
-18,
-112,
-119,
-68,
-186,
-47,
-162,
-66,
-186,
-23,
-120,
-89,
-147,
-231,
-159,
-144,
-103,
-254,
-169,
-140,
-236,
-210,
-245,
-253,
-69,
-184,
-255,
-78,
-9,
-50,
-39,
-58,
-232,
-225,
-20,
-34,
-4,
-125,
-88,
-2,
-46,
-105,
-140,
-153,
-103,
-140,
-217,
-205,
-136,
-165,
-221,
-124,
-36,
-212,
-213,
-89,
-198,
-152,
-223,
-0,
-87,
-102,
-89,
-54,
-165,
-162,
-253,
-95,
-141,
-49,
-153,
-49,
-102,
-171,
-44,
-203,
-38,
-25,
-99,
-12,
-176,
-181,
-49,
-230,
-116,
-173,
-43,
-219,
-131,
-217,
-64,
-28,
-3,
-97,
-149,
-3,
-225,
-211,
-190,
-190,
-86,
-255,
-94,
-103,
-140,
-153,
-25,
-200,
-231,
-56,
-96,
-166,
-49,
-102,
-89,
-99,
-204,
-6,
-70,
-172,
-219,
-102,
-24,
-99,
-246,
-200,
-178,
-204,
-171,
-160,
-241,
-224,
-23,
-198,
-152,
-47,
-25,
-99,
-62,
-102,
-140,
-121,
-208,
-24,
-179,
-200,
-24,
-211,
-40,
-248,
-73,
-7,
-84,
-221,
-235,
-242,
-198,
-152,
-50,
-1,
-115,
-134,
-49,
-230,
-14,
-35,
-247,
-124,
-28,
-176,
-125,
-150,
-101,
-179,
-122,
-232,
-223,
-226,
-138,
-63,
-25,
-99,
-94,
-103,
-140,
-249,
-160,
-41,
-90,
-233,
-25,
-81,
-226,
-105,
-157,
-49,
-198,
-252,
-37,
-250,
-213,
-187,
-126,
-65,
-2,
-248,
-31,
-170,
-77,
-91,
-103,
-243,
-173,
-225,
-31,
-189,
-255,
-33,
-60,
-61,
-180,
-69,
-60,
-66,
-96,
-96,
-70,
-242,
-48,
-221,
-85,
-240,
-234,
-67,
-186,
-222,
-127,
-140,
-231,
-71,
-135,
-4,
-153,
-19,
-29,
-140,
-242,
-41,
-132,
-33,
-82,
-122,
-162,
-138,
-182,
-171,
-144,
-159,
-21,
-15,
-229,
-28,
-222,
-67,
-51,
-12,
-1,
-224,
-110,
-1,
-206,
-215,
-178,
-61,
-170,
-218,
-58,
-244,
-59,
-50,
-50,
-9,
-171,
-197,
-181,
-78,
-153,
-55,
-19,
-81,
-215,
-251,
-143,
-245,
-252,
-104,
-153,
-32,
-179,
-41,
-144,
-60,
-123,
-219,
-118,
-228,
-241,
-44,
-228,
-136,
-246,
-118,
-196,
-86,
-227,
-17,
-36,
-188,
-155,
-55,
-55,
-132,
-182,
-9,
-70,
-139,
-254,
-140,
-218,
-41,
-132,
-33,
-82,
-122,
-34,
-224,
-53,
-136,
-214,
-255,
-110,
-228,
-107,
-48,
-93,
-95,
-254,
-231,
-145,
-68,
-15,
-0,
-159,
-247,
-180,
-27,
-85,
-45,
-118,
-9,
-125,
-45,
-207,
-42,
-90,
-224,
-37,
-200,
-158,
-248,
-65,
-90,
-72,
-237,
-174,
-215,
-247,
-208,
-12,
-229,
-249,
-209,
-34,
-65,
-102,
-83,
-144,
-107,
-205,
-91,
-9,
-2,
-196,
-215,
-222,
-42,
-222,
-166,
-33,
-147,
-237,
-86,
-231,
-57,
-120,
-141,
-182,
-24,
-41,
-160,
-203,
-254,
-61,
-25,
-58,
-198,
-60,
-252,
-71,
-229,
-20,
-194,
-16,
-33,
-61,
-17,
-240,
-85,
-242,
-164,
-33,
-211,
-148,
-151,
-43,
-193,
-30,
-208,
-191,
-255,
-240,
-180,
-29,
-51,
-3,
-184,
-9,
-207,
-58,
-90,
-36,
-42,
-12,
-192,
-192,
-190,
-206,
-195,
-99,
-92,
-111,
-1,
-74,
-218,
-188,
-4,
-249,
-154,
-109,
-90,
-79,
-29,
-14,
-196,
-165,
-251,
-23,
-228,
-99,
-43,
-88,
-16,
-32,
-2,
-234,
-30,
-109,
-247,
-45,
-70,
-230,
-86,
-220,
-1,
-249,
-104,
-65,
-131,
-172,
-79,
-5,
-254,
-151,
-52,
-121,
-70,
-99,
-2,
-116,
-76,
-79,
-68,
-126,
-68,
-177,
-200,
-243,
-80,
-159,
-142,
-8,
-7,
-139,
-123,
-60,
-237,
-199,
-220,
-0,
-14,
-225,
-89,
-71,
-11,
-60,
-83,
-7,
-212,
-2,
-60,
-145,
-112,
-10,
-180,
-227,
-126,
-11,
-224,
-105,
-243,
-7,
-29,
-19,
-231,
-19,
-89,
-8,
-40,
-255,
-53,
-17,
-239,
-57,
-107,
-136,
-84,
-43,
-8,
-128,
-47,
-42,
-173,
-55,
-115,
-18,
-240,
-93,
-173,
-255,
-83,
-203,
-62,
-141,
-63,
-1,
-96,
-204,
-83,
-3,
-176,
-85,
-122,
-34,
-242,
-208,
-216,
-165,
-81,
-127,
-129,
-19,
-44,
-111,
-79,
-221,
-152,
-27,
-192,
-33,
-60,
-67,
-104,
-129,
-175,
-105,
-221,
-69,
-33,
-215,
-141,
-125,
-125,
-135,
-102,
-52,
-4,
-192,
-187,
-17,
-223,
-4,
-128,
-107,
-67,
-219,
-53,
-5,
-242,
-85,
-223,
-159,
-124,
-149,
-89,
-42,
-8,
-128,
-11,
-149,
-198,
-107,
-181,
-136,
-232,
-49,
-0,
-166,
-182,
-236,
-203,
-248,
-20,
-0,
-198,
-24,
-67,
-203,
-244,
-68,
-72,
-104,
-109,
-128,
-247,
-87,
-208,
-188,
-85,
-105,
-230,
-122,
-234,
-198,
-220,
-0,
-142,
-53,
-1,
-145,
-21,
-208,
-93,
-90,
-255,
-65,
-95,
-251,
-62,
-175,
-239,
-208,
-12,
-93,
-0,
-56,
-109,
-47,
-5,
-158,
-104,
-218,
-174,
-197,
-117,
-150,
-5,
-62,
-129,
-56,
-67,
-129,
-223,
-110,
-222,
-245,
-210,
-172,
-194,
-194,
-150,
-125,
-24,
-55,
-2,
-96,
-192,
-14,
-32,
-203,
-178,
-59,
-141,
-49,
-109,
-76,
-111,
-173,
-146,
-235,
-222,
-10,
-154,
-39,
-245,
-239,
-99,
-45,
-248,
-143,
-91,
-100,
-89,
-54,
-27,
-241,
-243,
-255,
-157,
-49,
-230,
-71,
-192,
-153,
-197,
-104,
-57,
-17,
-48,
-211,
-200,
-57,
-125,
-85,
-228,
-87,
-107,
-137,
-57,
-148,
-40,
-72,
-136,
-99,
-16,
-70,
-108,
-7,
-182,
-52,
-198,
-252,
-97,
-24,
-215,
-213,
-107,
-90,
-248,
-140,
-146,
-236,
-88,
-253,
-175,
-233,
-231,
-89,
-124,
-222,
-24,
-51,
-16,
-80,
-213,
-17,
-10,
-27,
-103,
-89,
-118,
-91,
-27,
-198,
-192,
-134,
-198,
-152,
-111,
-24,
-99,
-182,
-55,
-198,
-172,
-110,
-196,
-78,
-228,
-76,
-99,
-204,
-1,
-89,
-150,
-61,
-220,
-174,
-187,
-17,
-64,
-190,
-244,
-218,
-165,
-130,
-230,
-195,
-74,
-243,
-119,
-79,
-221,
-152,
-251,
-130,
-133,
-240,
-28,
-43,
-32,
-210,
-41,
-78,
-228,
-62,
-205,
-64,
-180,
-245,
-83,
-144,
-227,
-182,
-222,
-130,
-81,
-34,
-91,
-128,
-47,
-57,
-227,
-112,
-10,
-176,
-15,
-176,
-172,
-135,
-214,
-58,
-222,
-148,
-154,
-221,
-246,
-212,
-71,
-139,
-141,
-90,
-182,
-127,
-41,
-185,
-158,
-110,
-6,
-146,
-241,
-218,
-42,
-65,
-239,
-35,
-32,
-75,
-118,
-111,
-32,
-79,
-89,
-253,
-199,
-10,
-154,
-191,
-41,
-205,
-94,
-158,
-186,
-174,
-2,
-32,
-186,
-29,
-195,
-56,
-19,
-0,
-157,
-79,
-113,
-198,
-35,
-16,
-37,
-224,
-247,
-200,
-109,
-76,
-110,
-70,
-204,
-175,
-75,
-173,
-92,
-201,
-93,
-111,
-191,
-48,
-228,
-190,
-182,
-22,
-0,
-136,
-89,
-185,
-77,
-113,
-127,
-2,
-42,
-76,
-129,
-149,
-17,
-69,
-43,
-104,
-114,
-217,
-81,
-1,
-114,
-220,
-99,
-207,
-102,
-191,
-138,
-35,
-121,
-145,
-125,
-217,
-119,
-156,
-23,
-52,
-224,
-210,
-26,
-65,
-0,
-68,
-255,
-2,
-142,
-51,
-1,
-208,
-233,
-20,
-103,
-188,
-1,
-57,
-6,
-252,
-57,
-249,
-23,
-112,
-18,
-226,
-118,
-93,
-25,
-44,
-69,
-219,
-238,
-167,
-109,
-174,
-199,
-19,
-125,
-169,
-47,
-116,
-20,
-0,
-111,
-215,
-182,
-247,
-2,
-79,
-43,
-212,
-45,
-79,
-158,
-154,
-238,
-85,
-49,
-59,
-124,
-24,
-13,
-98,
-160,
-3,
-31,
-32,
-63,
-49,
-152,
-129,
-156,
-32,
-92,
-77,
-254,
-117,
-190,
-7,
-120,
-97,
-73,
-219,
-174,
-2,
-32,
-250,
-23,
-112,
-60,
-9,
-0,
-99,
-186,
-157,
-226,
-140,
-55,
-144,
-127,
-108,
-174,
-4,
-222,
-233,
-123,
-231,
-21,
-109,
-87,
-64,
-182,
-8,
-32,
-17,
-162,
-54,
-44,
-212,
-63,
-7,
-81,
-36,
-238,
-80,
-198,
-163,
-101,
-159,
-187,
-8,
-0,
-43,
-192,
-189,
-246,
-36,
-228,
-89,
-169,
-126,
-208,
-189,
-167,
-57,
-83,
-104,
-24,
-195,
-28,
-9,
-252,
-113,
-4,
-249,
-41,
-130,
-141,
-106,
-250,
-29,
-186,
-231,
-155,
-175,
-18,
-0,
-209,
-191,
-128,
-93,
-5,
-0,
-34,
-248,
-162,
-41,
-153,
-144,
-124,
-134,
-223,
-167,
-58,
-55,
-94,
-171,
-83,
-156,
-241,
-6,
-196,
-123,
-238,
-205,
-29,
-218,
-111,
-70,
-126,
-50,
-3,
-242,
-5,
-157,
-66,
-110,
-4,
-4,
-145,
-227,
-80,
-56,
-124,
-159,
-131,
-28,
-143,
-90,
-171,
-65,
-155,
-190,
-252,
-45,
-21,
-109,
-255,
-163,
-109,
-119,
-43,
-169,
-223,
-93,
-235,
-207,
-139,
-221,
-225,
-232,
-73,
-12,
-74,
-174,
-213,
-121,
-15,
-79,
-228,
-47,
-96,
-4,
-1,
-112,
-59,
-208,
-72,
-219,
-203,
-96,
-88,
-232,
-39,
-245,
-30,
-190,
-133,
-44,
-119,
-103,
-0,
-207,
-106,
-211,
-159,
-190,
-129,
-68,
-93,
-62,
-7,
-103,
-27,
-230,
-43,
-107,
-200,
-115,
-91,
-34,
-71,
-112,
-118,
-120,
-175,
-12,
-124,
-5,
-89,
-69,
-76,
-67,
-140,
-181,
-30,
-211,
-201,
-246,
-157,
-216,
-2,
-211,
-25,
-79,
-63,
-212,
-191,
-247,
-1,
-151,
-147,
-7,
-3,
-5,
-143,
-153,
-188,
-182,
-181,
-202,
-77,
-239,
-252,
-32,
-143,
-22,
-52,
-96,
-100,
-215,
-181,
-195,
-195,
-18,
-0,
-177,
-124,
-17,
-162,
-125,
-1,
-35,
-8,
-128,
-127,
-211,
-32,
-76,
-54,
-254,
-176,
-208,
-147,
-28,
-1,
-6,
-112,
-112,
-155,
-190,
-12,
-3,
-120,
-150,
-169,
-190,
-178,
-64,
-94,
-219,
-34,
-198,
-60,
-208,
-99,
-28,
-254,
-97,
-194,
-121,
-135,
-115,
-113,
-98,
-99,
-32,
-219,
-83,
-27,
-247,
-97,
-30,
-158,
-120,
-10,
-228,
-186,
-14,
-111,
-206,
-5,
-224,
-101,
-90,
-31,
-239,
-88,
-115,
-200,
-2,
-96,
-92,
-107,
-177,
-129,
-53,
-144,
-200,
-174,
-155,
-57,
-101,
-167,
-227,
-152,
-147,
-34,
-169,
-179,
-190,
-136,
-39,
-203,
-43,
-213,
-97,
-161,
-63,
-224,
-12,
-158,
-41,
-140,
-193,
-116,
-102,
-228,
-71,
-188,
-215,
-160,
-10,
-96,
-95,
-89,
-0,
-31,
-119,
-226,
-207,
-70,
-236,
-253,
-215,
-239,
-181,
-243,
-67,
-130,
-243,
-14,
-189,
-193,
-93,
-200,
-79,
-201,
-14,
-241,
-212,
-217,
-188,
-138,
-155,
-149,
-180,
-125,
-177,
-214,
-183,
-50,
-94,
-50,
-192,
-15,
-8,
-199,
-59,
-91,
-93,
-164,
-250,
-250,
-227,
-90,
-139,
-141,
-248,
-194,
-91,
-220,
-141,
-164,
-117,
-190,
-88,
-255,
-29,
-73,
-174,
-116,
-2,
-216,
-201,
-211,
-222,
-27,
-22,
-26,
-241,
-37,
-176,
-86,
-150,
-118,
-25,
-232,
-93,
-38,
-142,
-22,
-128,
-205,
-145,
-47,
-212,
-116,
-244,
-235,
-229,
-43,
-171,
-225,
-225,
-78,
-252,
-39,
-16,
-93,
-199,
-154,
-253,
-247,
-126,
-120,
-112,
-222,
-255,
-219,
-74,
-234,
-109,
-236,
-200,
-171,
-61,
-117,
-118,
-107,
-91,
-183,
-2,
-8,
-13,
-92,
-51,
-192,
-224,
-19,
-12,
-186,
-53,
-162,
-147,
-178,
-88,
-254,
-186,
-138,
-155,
-11,
-66,
-73,
-31,
-198,
-173,
-22,
-27,
-17,
-0,
-255,
-208,
-254,
-22,
-149,
-73,
-211,
-181,
-236,
-106,
-100,
-63,
-60,
-224,
-111,
-142,
-39,
-44,
-52,
-178,
-234,
-177,
-225,
-192,
-143,
-5,
-246,
-213,
-255,
-15,
-100,
-215,
-85,
-250,
-205,
-41,
-28,
-17,
-57,
-117,
-75,
-81,
-227,
-75,
-142,
-104,
-199,
-191,
-174,
-207,
-221,
-26,
-241,
-60,
-140,
-8,
-177,
-239,
-80,
-208,
-150,
-107,
-155,
-149,
-200,
-205,
-110,
-63,
-92,
-86,
-86,
-113,
-77,
-119,
-226,
-79,
-69,
-4,
-225,
-74,
-85,
-109,
-198,
-43,
-156,
-241,
-80,
-246,
-21,
-127,
-189,
-214,
-15,
-152,
-76,
-35,
-250,
-2,
-168,
-215,
-1,
-60,
-16,
-187,
-195,
-65,
-91,
-0,
-36,
-40,
-100,
-240,
-191,
-10,
-62,
-139,
-133,
-22,
-27,
-145,
-230,
-243,
-16,
-79,
-184,
-218,
-88,
-254,
-228,
-214,
-105,
-175,
-119,
-202,
-108,
-172,
-247,
-91,
-144,
-179,
-222,
-29,
-244,
-183,
-47,
-44,
-244,
-11,
-17,
-69,
-214,
-63,
-138,
-66,
-0,
-88,
-26,
-217,
-142,
-204,
-161,
-228,
-156,
-24,
-81,
-62,
-222,
-172,
-252,
-23,
-234,
-4,
-190,
-18,
-39,
-136,
-7,
-254,
-132,
-26,
-43,
-147,
-135,
-50,
-255,
-112,
-89,
-89,
-201,
-53,
-237,
-196,
-191,
-3,
-209,
-239,
-120,
-133,
-87,
-23,
-32,
-31,
-149,
-243,
-200,
-181,
-237,
-23,
-163,
-43,
-88,
-116,
-75,
-217,
-128,
-215,
-154,
-228,
-202,
-234,
-43,
-90,
-244,
-197,
-98,
-227,
-146,
-250,
-170,
-220,
-133,
-54,
-102,
-96,
-153,
-3,
-147,
-61,
-5,
-184,
-172,
-105,
-191,
-234,
-58,
-60,
-20,
-29,
-64,
-87,
-32,
-57,
-7,
-64,
-190,
-164,
-3,
-86,
-96,
-200,
-23,
-208,
-126,
-101,
-75,
-61,
-22,
-11,
-109,
-26,
-217,
-65,
-56,
-237,
-94,
-128,
-172,
-100,
-78,
-1,
-206,
-70,
-4,
-153,
-87,
-234,
-59,
-109,
-70,
-132,
-133,
-70,
-142,
-169,
-230,
-32,
-66,
-228,
-101,
-90,
-246,
-170,
-138,
-1,
-178,
-52,
-112,
-134,
-214,
-63,
-37,
-4,
-16,
-45,
-252,
-153,
-90,
-126,
-22,
-37,
-123,
-113,
-224,
-120,
-165,
-185,
-141,
-66,
-4,
-102,
-196,
-200,
-235,
-8,
-74,
-162,
-58,
-35,
-38,
-170,
-179,
-25,
-185,
-5,
-24,
-40,
-243,
-180,
-179,
-58,
-143,
-219,
-145,
-21,
-104,
-84,
-1,
-64,
-158,
-72,
-3,
-100,
-251,
-228,
-70,
-37,
-250,
-50,
-170,
-88,
-107,
-192,
-239,
-40,
-135,
-215,
-128,
-30,
-39,
-160,
-189,
-133,
-55,
-232,
-13,
-249,
-87,
-252,
-113,
-79,
-221,
-33,
-90,
-119,
-120,
-73,
-219,
-95,
-104,
-125,
-101,
-240,
-216,
-54,
-29,
-30,
-47,
-2,
-96,
-57,
-96,
-178,
-246,
-249,
-32,
-79,
-253,
-247,
-181,
-110,
-18,
-129,
-201,
-53,
-218,
-220,
-63,
-226,
-249,
-103,
-83,
-124,
-109,
-79,
-254,
-213,
-190,
-145,
-234,
-243,
-123,
-27,
-157,
-230,
-77,
-192,
-211,
-28,
-30,
-95,
-118,
-104,
-42,
-195,
-66,
-35,
-66,
-224,
-207,
-74,
-115,
-54,
-242,
-37,
-254,
-171,
-254,
-46,
-157,
-252,
-218,
-214,
-158,
-62,
-148,
-250,
-114,
-212,
-220,
-183,
-253,
-2,
-185,
-74,
-192,
-129,
-178,
-66,
-155,
-101,
-17,
-123,
-125,
-171,
-31,
-153,
-138,
-184,
-244,
-118,
-222,
-2,
-0,
-27,
-147,
-199,
-39,
-252,
-63,
-84,
-177,
-140,
-108,
-171,
-62,
-70,
-174,
-84,
-11,
-245,
-11,
-121,
-185,
-182,
-121,
-156,
-246,
-167,
-66,
-22,
-239,
-40,
-169,
-255,
-148,
-214,
-95,
-229,
-169,
-179,
-249,
-29,
-239,
-163,
-218,
-18,
-208,
-171,
-95,
-104,
-5,
-101,
-56,
-46,
-4,
-128,
-49,
-198,
-0,
-155,
-34,
-75,
-180,
-69,
-192,
-118,
-78,
-249,
-246,
-90,
-54,
-29,
-216,
-164,
-1,
-191,
-198,
-247,
-79,
-158,
-6,
-236,
-78,
-29,
-108,
-25,
-112,
-131,
-150,
-253,
-178,
-162,
-221,
-83,
-97,
-161,
-129,
-159,
-234,
-255,
-207,
-199,
-49,
-109,
-37,
-32,
-44,
-52,
-242,
-197,
-183,
-66,
-192,
-218,
-199,
-87,
-78,
-126,
-109,
-103,
-151,
-182,
-91,
-85,
-209,
-213,
-240,
-176,
-249,
-15,
-126,
-86,
-85,
-230,
-105,
-183,
-52,
-34,
-44,
-236,
-22,
-228,
-9,
-196,
-22,
-162,
-181,
-18,
-144,
-60,
-8,
-173,
-215,
-48,
-134,
-60,
-54,
-69,
-168,
-0,
-184,
-17,
-17,
-80,
-91,
-118,
-232,
-147,
-197,
-175,
-74,
-234,
-207,
-211,
-250,
-31,
-150,
-212,
-91,
-189,
-220,
-111,
-200,
-125,
-1,
-86,
-4,
-78,
-213,
-242,
-235,
-9,
-48,
-133,
-110,
-210,
-225,
-237,
-232,
-43,
-8,
-97,
-79,
-0,
-62,
-168,
-15,
-99,
-42,
-178,
-175,
-93,
-139,
-124,
-217,
-87,
-26,
-171,
-160,
-132,
-23,
-52,
-23,
-0,
-107,
-35,
-58,
-140,
-253,
-157,
-178,
-143,
-35,
-91,
-148,
-117,
-42,
-218,
-89,
-5,
-223,
-221,
-136,
-176,
-122,
-12,
-88,
-215,
-169,
-15,
-78,
-78,
-137,
-40,
-243,
-236,
-201,
-193,
-163,
-192,
-138,
-1,
-253,
-182,
-118,
-24,
-165,
-9,
-76,
-3,
-120,
-44,
-139,
-40,
-57,
-247,
-170,
-42,
-171,
-104,
-111,
-147,
-169,
-218,
-213,
-207,
-44,
-125,
-150,
-235,
-183,
-232,
-203,
-53,
-202,
-99,
-159,
-146,
-250,
-157,
-155,
-8,
-128,
-24,
-112,
-4,
-192,
-2,
-36,
-252,
-155,
-187,
-42,
-249,
-63,
-173,
-155,
-75,
-137,
-169,
-48,
-162,
-31,
-179,
-39,
-65,
-51,
-16,
-161,
-100,
-149,
-230,
-143,
-83,
-19,
-113,
-106,
-204,
-67,
-7,
-192,
-62,
-136,
-1,
-141,
-61,
-18,
-244,
-162,
-134,
-143,
-205,
-85,
-127,
-142,
-254,
-131,
-22,
-123,
-35,
-109,
-55,
-44,
-59,
-136,
-21,
-200,
-21,
-103,
-224,
-40,
-123,
-104,
-16,
-22,
-154,
-145,
-219,
-0,
-43,
-4,
-254,
-130,
-19,
-162,
-173,
-164,
-157,
-141,
-90,
-52,
-15,
-89,
-138,
-46,
-89,
-69,
-223,
-39,
-116,
-66,
-188,
-19,
-81,
-66,
-66,
-11,
-67,
-32,
-242,
-16,
-97,
-222,
-184,
-126,
-136,
-94,
-163,
-118,
-44,
-197,
-132,
-243,
-110,
-109,
-170,
-239,
-7,
-24,
-180,
-4,
-172,
-212,
-57,
-33,
-31,
-152,
-35,
-17,
-191,
-154,
-185,
-250,
-247,
-215,
-140,
-119,
-91,
-9,
-125,
-233,
-127,
-28,
-152,
-233,
-57,
-30,
-66,
-20,
-84,
-15,
-213,
-189,
-52,
-100,
-15,
-125,
-157,
-211,
-246,
-42,
-234,
-151,
-192,
-163,
-106,
-7,
-161,
-125,
-248,
-142,
-115,
-141,
-89,
-72,
-44,
-192,
-38,
-201,
-45,
-93,
-69,
-224,
-25,
-200,
-222,
-240,
-116,
-253,
-93,
-41,
-4,
-180,
-173,
-213,
-23,
-128,
-8,
-163,
-175,
-50,
-202,
-103,
-241,
-192,
-155,
-105,
-24,
-74,
-77,
-219,
-217,
-108,
-197,
-175,
-40,
-169,
-223,
-216,
-222,
-104,
-5,
-143,
-198,
-97,
-195,
-107,
-250,
-100,
-241,
-44,
-100,
-165,
-243,
-31,
-100,
-91,
-58,
-29,
-9,
-83,
-22,
-111,
-255,
-62,
-222,
-64,
-158,
-65,
-183,
-12,
-159,
-80,
-186,
-79,
-84,
-189,
-52,
-135,
-159,
-155,
-92,
-116,
-239,
-0,
-250,
-78,
-118,
-16,
-93,
-1,
-60,
-3,
-249,
-106,
-205,
-5,
-14,
-70,
-150,
-228,
-51,
-144,
-37,
-222,
-36,
-234,
-211,
-99,
-219,
-163,
-62,
-244,
-239,
-210,
-78,
-185,
-141,
-201,
-119,
-38,
-213,
-66,
-96,
-9,
-125,
-110,
-246,
-204,
-25,
-29,
-248,
-63,
-165,
-143,
-100,
-20,
-61,
-130,
-124,
-5,
-89,
-22,
-195,
-114,
-51,
-123,
-131,
-37,
-245,
-173,
-194,
-134,
-215,
-244,
-201,
-98,
-192,
-158,
-98,
-194,
-131,
-220,
-12,
-178,
-12,
-193,
-2,
-0,
-241,
-182,
-122,
-2,
-209,
-218,
-46,
-68,
-246,
-211,
-165,
-251,
-239,
-10,
-62,
-48,
-188,
-45,
-192,
-114,
-58,
-201,
-127,
-212,
-178,
-253,
-243,
-145,
-125,
-224,
-83,
-147,
-223,
-169,
-91,
-10,
-9,
-216,
-50,
-147,
-18,
-75,
-50,
-15,
-253,
-206,
-228,
-138,
-73,
-16,
-5,
-221,
-184,
-177,
-204,
-35,
-95,
-1,
-238,
-89,
-82,
-255,
-182,
-50,
-1,
-64,
-79,
-97,
-195,
-157,
-103,
-217,
-42,
-34,
-80,
-239,
-64,
-236,
-217,
-191,
-133,
-72,
-187,
-39,
-145,
-165,
-231,
-36,
-36,
-81,
-65,
-165,
-253,
-57,
-34,
-81,
-15,
-71,
-52,
-222,
-51,
-144,
-51,
-224,
-155,
-144,
-4,
-151,
-181,
-222,
-107,
-228,
-202,
-141,
-78,
-2,
-0,
-88,
-18,
-49,
-246,
-0,
-49,
-30,
-178,
-231,
-167,
-23,
-208,
-80,
-67,
-170,
-237,
-198,
-211,
-41,
-200,
-243,
-139,
-147,
-223,
-169,
-91,
-146,
-22,
-74,
-34,
-36,
-144,
-171,
-221,
-79,
-7,
-217,
-79,
-140,
-5,
-144,
-159,
-164,
-120,
-243,
-232,
-145,
-155,
-150,
-251,
-4,
-64,
-47,
-97,
-195,
-199,
-180,
-0,
-0,
-62,
-68,
-190,
-108,
-90,
-128,
-236,
-123,
-220,
-165,
-224,
-245,
-128,
-55,
-224,
-164,
-78,
-124,
-155,
-16,
-100,
-14,
-98,
-185,
-118,
-143,
-83,
-246,
-48,
-53,
-199,
-111,
-140,
-76,
-37,
-238,
-67,
-168,
-0,
-248,
-166,
-210,
-79,
-66,
-52,
-208,
-203,
-146,
-107,
-184,
-191,
-214,
-240,
-153,
-192,
-56,
-18,
-0,
-125,
-193,
-62,
-115,
-224,
-161,
-209,
-238,
-75,
-40,
-16,
-97,
-104,
-141,
-171,
-246,
-41,
-212,
-189,
-7,
-81,
-118,
-226,
-27,
-75,
-244,
-20,
-54,
-220,
-25,
-203,
-209,
-5,
-64,
-103,
-222,
-58,
-137,
-231,
-81,
-56,
-127,
-5,
-94,
-65,
-254,
-117,
-246,
-102,
-168,
-37,
-143,
-199,
-254,
-49,
-70,
-122,
-177,
-61,
-31,
-57,
-170,
-128,
-18,
-73,
-236,
-208,
-186,
-46,
-175,
-173,
-4,
-0,
-146,
-78,
-124,
-1,
-34,
-76,
-94,
-236,
-148,
-111,
-174,
-101,
-243,
-9,
-76,
-209,
-173,
-237,
-146,
-0,
-48,
-198,
-0,
-175,
-213,
-103,
-49,
-16,
-206,
-61,
-160,
-109,
-48,
-2,
-120,
-185,
-122,
-157,
-218,
-96,
-29,
-228,
-71,
-171,
-144,
-251,
-222,
-219,
-165,
-189,
-253,
-138,
-251,
-4,
-64,
-47,
-97,
-195,
-157,
-118,
-99,
-82,
-0,
-44,
-65,
-121,
-184,
-174,
-189,
-148,
-249,
-93,
-21,
-109,
-189,
-91,
-4,
-224,
-29,
-218,
-182,
-210,
-79,
-153,
-145,
-222,
-114,
-62,
-84,
-10,
-0,
-100,
-223,
-118,
-135,
-210,
-250,
-108,
-214,
-247,
-215,
-186,
-219,
-9,
-56,
-23,
-215,
-54,
-227,
-206,
-14,
-162,
-15,
-56,
-239,
-255,
-198,
-22,
-109,
-67,
-114,
-233,
-93,
-66,
-141,
-160,
-5,
-94,
-132,
-108,
-45,
-167,
-233,
-191,
-25,
-20,
-76,
-150,
-75,
-218,
-189,
-13,
-249,
-162,
-91,
-109,
-251,
-127,
-128,
-247,
-2,
-235,
-218,
-129,
-229,
-105,
-99,
-87,
-14,
-215,
-117,
-233,
-179,
-135,
-111,
-183,
-73,
-58,
-74,
-188,
-173,
-70,
-20,
-96,
-94,
-139,
-182,
-219,
-106,
-219,
-1,
-251,
-230,
-2,
-221,
-239,
-171,
-231,
-127,
-173,
-0,
-56,
-73,
-233,
-46,
-194,
-179,
-215,
-71,
-132,
-148,
-85,
-106,
-157,
-232,
-169,
-247,
-157,
-2,
-148,
-253,
-235,
-124,
-10,
-128,
-8,
-151,
-179,
-144,
-175,
-205,
-28,
-68,
-195,
-124,
-8,
-125,
-38,
-128,
-44,
-239,
-203,
-230,
-200,
-113,
-215,
-43,
-139,
-207,
-14,
-177,
-162,
-180,
-95,
-196,
-74,
-3,
-164,
-30,
-251,
-183,
-22,
-114,
-44,
-57,
-13,
-89,
-229,
-189,
-14,
-17,
-0,
-119,
-0,
-107,
-181,
-228,
-185,
-161,
-29,
-88,
-158,
-186,
-81,
-9,
-27,
-222,
-5,
-125,
-11,
-0,
-187,
-231,
-169,
-74,
-250,
-81,
-214,
-214,
-58,
-41,
-84,
-42,
-144,
-24,
-233,
-79,
-223,
-88,
-0,
-116,
-5,
-67,
-180,
-3,
-32,
-95,
-141,
-128,
-124,
-149,
-110,
-38,
-215,
-129,
-220,
-71,
-3,
-115,
-229,
-24,
-32,
-119,
-50,
-2,
-153,
-100,
-215,
-33,
-138,
-96,
-55,
-205,
-247,
-31,
-168,
-8,
-181,
-221,
-115,
-255,
-174,
-66,
-86,
-136,
-238,
-182,
-238,
-165,
-72,
-76,
-191,
-1,
-187,
-249,
-64,
-158,
-27,
-217,
-27,
-243,
-212,
-141,
-74,
-216,
-240,
-46,
-112,
-222,
-211,
-6,
-125,
-48,
-183,
-17,
-71,
-143,
-9,
-164,
-95,
-6,
-217,
-255,
-255,
-4,
-81,
-4,
-94,
-67,
-137,
-39,
-89,
-161,
-221,
-215,
-201,
-21,
-135,
-69,
-244,
-42,
-0,
-134,
-5,
-228,
-43,
-187,
-72,
-39,
-252,
-7,
-200,
-205,
-65,
-159,
-129,
-216,
-254,
-163,
-19,
-208,
-231,
-209,
-248,
-74,
-224,
-159,
-200,
-215,
-111,
-22,
-98,
-26,
-252,
-85,
-224,
-185,
-14,
-205,
-218,
-192,
-111,
-27,
-246,
-105,
-69,
-36,
-54,
-222,
-121,
-200,
-22,
-105,
-58,
-162,
-15,
-186,
-15,
-49,
-40,
-122,
-87,
-135,
-251,
-13,
-70,
-219,
-107,
-180,
-236,
-87,
-149,
-0,
-24,
-149,
-176,
-225,
-93,
-224,
-60,
-198,
-117,
-128,
-93,
-16,
-33,
-22,
-20,
-112,
-180,
-142,
-241,
-115,
-144,
-37,
-234,
-2,
-2,
-150,
-23,
-133,
-119,
-58,
-9,
-177,
-121,
-14,
-126,
-136,
-136,
-100,
-63,
-88,
-7,
-222,
-223,
-201,
-221,
-124,
-23,
-23,
-1,
-96,
-183,
-42,
-62,
-143,
-197,
-101,
-201,
-245,
-24,
-239,
-241,
-212,
-91,
-69,
-230,
-181,
-140,
-52,
-74,
-1,
-81,
-182,
-94,
-133,
-76,
-220,
-57,
-195,
-185,
-155,
-122,
-16,
-73,
-7,
-208,
-67,
-191,
-170,
-4,
-192,
-168,
-132,
-13,
-239,
-2,
-103,
-28,
-88,
-147,
-241,
-224,
-128,
-163,
-85,
-76,
-151,
-6,
-46,
-211,
-198,
-65,
-241,
-198,
-145,
-175,
-215,
-36,
-196,
-1,
-103,
-33,
-114,
-58,
-112,
-8,
-29,
-44,
-201,
-22,
-51,
-1,
-112,
-183,
-222,
-207,
-75,
-74,
-234,
-109,
-16,
-144,
-147,
-61,
-117,
-39,
-1,
-207,
-116,
-126,
-111,
-4,
-124,
-67,
-5,
-194,
-60,
-196,
-208,
-231,
-92,
-26,
-156,
-116,
-140,
-7,
-16,
-217,
-36,
-87,
-121,
-150,
-10,
-0,
-173,
-111,
-21,
-54,
-92,
-203,
-175,
-211,
-255,
-55,
-10,
-253,
-221,
-165,
-207,
-78,
-159,
-230,
-225,
-56,
-189,
-17,
-16,
-112,
-180,
-234,
-130,
-191,
-210,
-134,
-151,
-208,
-98,
-255,
-135,
-44,
-107,
-191,
-174,
-23,
-190,
-159,
-246,
-57,
-209,
-22,
-39,
-1,
-96,
-207,
-159,
-159,
-81,
-82,
-111,
-143,
-220,
-90,
-37,
-143,
-92,
-220,
-64,
-15,
-38,
-185,
-202,
-183,
-82,
-0,
-40,
-77,
-227,
-176,
-225,
-202,
-114,
-22,
-178,
-53,
-131,
-24,
-95,
-226,
-128,
-62,
-59,
-188,
-27,
-7,
-28,
-45,
-187,
-216,
-193,
-218,
-224,
-150,
-178,
-193,
-218,
-160,
-227,
-214,
-56,
-231,
-172,
-150,
-237,
-163,
-11,
-0,
-26,
-160,
-130,
-199,
-70,
-136,
-95,
-249,
-125,
-200,
-210,
-252,
-126,
-196,
-87,
-187,
-84,
-202,
-234,
-64,
-2,
-120,
-126,
-73,
-253,
-139,
-180,
-62,
-118,
-246,
-224,
-113,
-7,
-122,
-50,
-201,
-237,
-19,
-206,
-176,
-105,
-28,
-250,
-59,
-128,
-119,
-136,
-0,
-104,
-28,
-112,
-212,
-71,
-252,
-37,
-37,
-190,
-31,
-71,
-193,
-212,
-22,
-228,
-199,
-136,
-173,
-34,
-150,
-106,
-219,
-216,
-2,
-96,
-114,
-205,
-191,
-59,
-170,
-250,
-140,
-28,
-157,
-89,
-203,
-201,
-153,
-136,
-38,
-223,
-250,
-102,
-79,
-163,
-124,
-137,
-111,
-51,
-188,
-120,
-29,
-148,
-200,
-5,
-111,
-212,
-88,
-248,
-248,
-49,
-27,
-89,
-214,
-158,
-137,
-196,
-81,
-240,
-154,
-74,
-3,
-171,
-43,
-237,
-28,
-58,
-126,
-12,
-26,
-246,
-185,
-23,
-147,
-220,
-62,
-225,
-60,
-219,
-56,
-95,
-226,
-145,
-109,
-67,
-4,
-128,
-215,
-220,
-155,
-138,
-128,
-163,
-69,
-66,
-43,
-41,
-30,
-2,
-54,
-109,
-218,
-201,
-18,
-158,
-219,
-40,
-207,
-39,
-91,
-182,
-135,
-33,
-111,
-1,
-16,
-255,
-7,
-128,
-95,
-148,
-212,
-159,
-171,
-245,
-167,
-161,
-70,
-80,
-136,
-242,
-200,
-122,
-222,
-157,
-91,
-210,
-110,
-31,
-173,
-191,
-31,
-71,
-72,
-32,
-118,
-10,
-159,
-33,
-15,
-85,
-85,
-105,
-55,
-209,
-226,
-126,
-44,
-174,
-37,
-87,
-188,
-93,
-67,
-110,
-231,
-15,
-162,
-120,
-245,
-230,
-216,
-67,
-124,
-206,
-1,
-190,
-26,
-179,
-95,
-53,
-125,
-238,
-197,
-36,
-183,
-79,
-56,
-207,
-178,
-251,
-151,
-120,
-176,
-109,
-136,
-0,
-40,
-139,
-191,
-88,
-26,
-112,
-212,
-37,
-218,
-133,
-220,
-123,
-46,
-90,
-66,
-76,
-242,
-0,
-8,
-173,
-242,
-150,
-105,
-219,
-161,
-9,
-0,
-196,
-51,
-239,
-17,
-125,
-22,
-94,
-215,
-77,
-114,
-31,
-253,
-77,
-10,
-229,
-207,
-215,
-242,
-178,
-149,
-195,
-146,
-72,
-188,
-62,
-144,
-109,
-195,
-69,
-200,
-23,
-248,
-78,
-189,
-158,
-77,
-144,
-50,
-37,
-242,
-61,
-89,
-108,
-81,
-40,
-95,
-18,
-216,
-155,
-252,
-248,
-213,
-123,
-228,
-135,
-156,
-206,
-128,
-40,
-49,
-135,
-18,
-44,
-132,
-158,
-76,
-114,
-251,
-132,
-211,
-167,
-198,
-161,
-191,
-29,
-154,
-98,
-36,
-227,
-75,
-16,
-235,
-197,
-245,
-44,
-243,
-138,
-235,
-54,
-10,
-56,
-234,
-198,
-155,
-219,
-193,
-24,
-115,
-146,
-49,
-102,
-166,
-49,
-102,
-199,
-44,
-203,
-130,
-82,
-104,
-107,
-219,
-115,
-145,
-44,
-48,
-43,
-23,
-202,
-215,
-0,
-14,
-52,
-198,
-88,
-103,
-12,
-175,
-47,
-193,
-24,
-196,
-158,
-198,
-152,
-213,
-141,
-49,
-103,
-100,
-89,
-118,
-123,
-9,
-205,
-52,
-253,
-187,
-160,
-80,
-190,
-72,
-255,
-122,
-95,
-112,
-150,
-101,
-11,
-141,
-49,
-59,
-25,
-99,
-190,
-96,
-140,
-153,
-108,
-140,
-121,
-153,
-49,
-102,
-107,
-99,
-204,
-29,
-198,
-152,
-237,
-140,
-49,
-147,
-148,
-244,
-250,
-86,
-61,
-111,
-136,
-44,
-203,
-22,
-102,
-89,
-246,
-75,
-99,
-204,
-63,
-181,
-104,
-235,
-18,
-186,
-107,
-140,
-49,
-151,
-25,
-99,
-214,
-53,
-198,
-120,
-131,
-90,
-246,
-0,
-59,
-158,
-254,
-107,
-140,
-185,
-180,
-226,
-95,
-235,
-80,
-216,
-200,
-138,
-237,
-54,
-59,
-118,
-129,
-85,
-145,
-237,
-223,
-192,
-41,
-76,
-67,
-148,
-29,
-197,
-206,
-210,
-191,
-222,
-0,
-177,
-72,
-68,
-160,
-191,
-25,
-99,
-94,
-175,
-180,
-55,
-27,
-99,
-54,
-50,
-198,
-156,
-106,
-140,
-217,
-55,
-224,
-186,
-235,
-151,
-148,
-91,
-157,
-147,
-127,
-60,
-147,
-239,
-95,
-167,
-82,
-189,
-55,
-30,
-152,
-196,
-142,
-244,
-89,
-132,
-40,
-109,
-254,
-135,
-124,
-209,
-236,
-87,
-101,
-1,
-78,
-116,
-219,
-166,
-80,
-30,
-67,
-89,
-1,
-32,
-190,
-240,
-246,
-248,
-231,
-213,
-21,
-116,
-39,
-42,
-205,
-247,
-10,
-229,
-54,
-241,
-99,
-144,
-209,
-148,
-135,
-175,
-221,
-215,
-182,
-142,
-205,
-87,
-194,
-215,
-194,
-187,
-178,
-67,
-18,
-143,
-0,
-28,
-86,
-193,
-99,
-87,
-165,
-137,
-151,
-129,
-182,
-2,
-12,
-193,
-36,
-23,
-209,
-107,
-0,
-188,
-86,
-127,
-219,
-232,
-187,
-179,
-91,
-242,
-179,
-104,
-19,
-250,
-187,
-117,
-36,
-99,
-231,
-186,
-173,
-2,
-142,
-54,
-209,
-138,
-159,
-230,
-105,
-187,
-35,
-162,
-13,
-159,
-132,
-156,
-151,
-206,
-71,
-20,
-97,
-147,
-17,
-43,
-194,
-78,
-193,
-10,
-245,
-186,
-195,
-18,
-0,
-187,
-233,
-245,
-42,
-147,
-122,
-34,
-203,
-49,
-235,
-37,
-249,
-83,
-96,
-3,
-242,
-173,
-206,
-245,
-180,
-8,
-158,
-161,
-47,
-218,
-186,
-46,
-87,
-230,
-17,
-104,
-193,
-219,
-98,
-64,
-0,
-32,
-250,
-7,
-27,
-64,
-99,
-192,
-0,
-201,
-161,
-91,
-218,
-185,
-103,
-175,
-227,
-88,
-76,
-48,
-4,
-147,
-92,
-6,
-87,
-0,
-171,
-32,
-43,
-128,
-83,
-90,
-242,
-179,
-104,
-19,
-250,
-187,
-117,
-36,
-99,
-231,
-186,
-173,
-2,
-142,
-38,
-152,
-167,
-30,
-150,
-141,
-72,
-91,
-107,
-254,
-138,
-72,
-236,
-171,
-25,
-137,
-95,
-2,
-171,
-180,
-188,
-190,
-245,
-186,
-59,
-191,
-77,
-251,
-26,
-222,
-3,
-2,
-0,
-49,
-217,
-222,
-20,
-56,
-70,
-235,
-254,
-76,
-137,
-18,
-208,
-105,
-99,
-227,
-22,
-30,
-25,
-187,
-143,
-158,
-107,
-141,
-103,
-147,
-220,
-198,
-95,
-98,
-58,
-68,
-50,
-214,
-226,
-7,
-201,
-117,
-72,
-141,
-3,
-142,
-78,
-120,
-32,
-209,
-111,
-64,
-108,
-31,
-106,
-163,
-7,
-233,
-132,
-189,
-23,
-145,
-186,
-214,
-113,
-230,
-6,
-26,
-154,
-136,
-34,
-193,
-59,
-191,
-170,
-124,
-102,
-81,
-178,
-124,
-236,
-2,
-170,
-113,
-17,
-162,
-195,
-169,
-156,
-252,
-202,
-231,
-89,
-200,
-57,
-246,
-116,
-122,
-142,
-19,
-200,
-248,
-54,
-201,
-109,
-252,
-37,
-166,
-67,
-36,
-99,
-45,
-254,
-147,
-254,
-63,
-5,
-28,
-109,
-3,
-114,
-119,
-225,
-79,
-214,
-208,
-45,
-1,
-252,
-86,
-105,
-47,
-70,
-52,
-255,
-203,
-34,
-73,
-61,
-158,
-64,
-116,
-31,
-7,
-86,
-180,
-255,
-53,
-146,
-190,
-235,
-207,
-72,
-8,
-116,
-27,
-12,
-229,
-1,
-122,
-74,
-126,
-234,
-12,
-76,
-247,
-24,
-240,
-74,
-36,
-142,
-224,
-2,
-189,
-247,
-215,
-4,
-242,
-58,
-89,
-121,
-125,
-174,
-143,
-190,
-22,
-174,
-213,
-202,
-36,
-55,
-128,
-175,
-133,
-111,
-34,
-214,
-90,
-9,
-6,
-240,
-109,
-28,
-250,
-155,
-8,
-145,
-140,
-19,
-90,
-2,
-241,
-51,
-7,
-9,
-95,
-86,
-153,
-58,
-140,
-220,
-162,
-235,
-66,
-10,
-81,
-118,
-145,
-175,
-210,
-157,
-90,
-255,
-145,
-146,
-246,
-199,
-32,
-147,
-126,
-1,
-114,
-212,
-117,
-33,
-98,
-244,
-210,
-219,
-23,
-213,
-25,
-124,
-190,
-99,
-192,
-143,
-146,
-7,
-80,
-173,
-253,
-154,
-146,
-43,
-202,
-110,
-33,
-96,
-213,
-208,
-21,
-180,
-48,
-201,
-13,
-224,
-217,
-183,
-0,
-104,
-28,
-250,
-155,
-142,
-145,
-140,
-163,
-0,
-241,
-40,
-67,
-59,
-28,
-108,
-245,
-165,
-15,
-237,
-24,
-68,
-241,
-247,
-184,
-182,
-191,
-9,
-113,
-96,
-241,
-90,
-197,
-105,
-187,
-189,
-169,
-135,
-215,
-168,
-166,
-192,
-103,
-101,
-100,
-207,
-120,
-33,
-50,
-169,
-230,
-107,
-31,
-130,
-246,
-170,
-228,
-201,
-52,
-106,
-181,
-239,
-228,
-169,
-175,
-203,
-94,
-148,
-205,
-225,
-55,
-102,
-236,
-249,
-157,
-103,
-89,
-119,
-10,
-16,
-116,
-164,
-134,
-172,
-36,
-96,
-12,
-45,
-191,
-155,
-192,
-121,
-30,
-125,
-9,
-128,
-198,
-161,
-191,
-233,
-16,
-201,
-56,
-26,
-144,
-244,
-67,
-54,
-209,
-96,
-80,
-54,
-29,
-196,
-44,
-214,
-218,
-184,
-207,
-69,
-20,
-105,
-215,
-144,
-47,
-211,
-230,
-1,
-59,
-149,
-180,
-253,
-134,
-210,
-84,
-29,
-63,
-86,
-30,
-169,
-33,
-150,
-134,
-110,
-84,
-225,
-7,
-181,
-221,
-20,
-224,
-204,
-128,
-254,
-111,
-138,
-44,
-219,
-103,
-19,
-32,
-244,
-200,
-29,
-122,
-188,
-209,
-142,
-129,
-103,
-107,
-253,
-88,
-114,
-203,
-173,
-19,
-0,
-31,
-209,
-250,
-89,
-190,
-122,
-15,
-253,
-158,
-74,
-223,
-202,
-191,
-99,
-180,
-49,
-4,
-1,
-208,
-88,
-219,
-78,
-135,
-72,
-198,
-81,
-1,
-108,
-73,
-30,
-87,
-255,
-229,
-1,
-244,
-103,
-105,
-191,
-46,
-99,
-100,
-64,
-209,
-229,
-200,
-143,
-46,
-38,
-151,
-180,
-181,
-254,
-203,
-94,
-205,
-103,
-192,
-181,
-55,
-35,
-183,
-202,
-251,
-13,
-133,
-227,
-41,
-2,
-180,
-199,
-228,
-49,
-7,
-74,
-147,
-119,
-22,
-232,
-173,
-75,
-175,
-247,
-235,
-135,
-88,
-84,
-2,
-220,
-20,
-118,
-23,
-253,
-35,
-64,
-0,
-216,
-19,
-136,
-202,
-216,
-141,
-14,
-253,
-211,
-17,
-47,
-189,
-133,
-244,
-17,
-133,
-166,
-103,
-140,
-81,
-1,
-208,
-58,
-146,
-113,
-116,
-168,
-16,
-120,
-0,
-184,
-33,
-128,
-214,
-106,
-47,
-7,
-98,
-229,
-145,
-155,
-144,
-122,
-191,
-134,
-192,
-41,
-90,
-223,
-202,
-186,
-140,
-252,
-88,
-165,
-84,
-233,
-86,
-211,
-126,
-29,
-125,
-176,
-139,
-8,
-244,
-208,
-34,
-63,
-175,
-189,
-157,
-130,
-177,
-16,
-98,
-19,
-97,
-87,
-80,
-251,
-151,
-241,
-24,
-54,
-2,
-4,
-128,
-117,
-253,
-190,
-188,
-1,
-79,
-123,
-228,
-116,
-104,
-188,
-158,
-14,
-7,
-99,
-81,
-0,
-104,
-251,
-170,
-72,
-198,
-95,
-71,
-21,
-198,
-109,
-120,
-247,
-134,
-154,
-135,
-121,
-144,
-214,
-253,
-179,
-164,
-237,
-249,
-90,
-95,
-187,
-210,
-240,
-180,
-125,
-177,
-182,
-157,
-66,
-77,
-242,
-203,
-10,
-30,
-118,
-50,
-255,
-185,
-65,
-155,
-21,
-201,
-189,
-250,
-64,
-190,
-132,
-55,
-50,
-50,
-161,
-233,
-25,
-4,
-158,
-93,
-3,
-107,
-146,
-167,
-231,
-190,
-34,
-176,
-77,
-211,
-16,
-217,
-22,
-69,
-37,
-96,
-6,
-236,
-65,
-174,
-129,
-174,
-205,
-226,
-235,
-180,
-125,
-46,
-185,
-239,
-200,
-114,
-161,
-237,
-106,
-250,
-215,
-118,
-226,
-108,
-139,
-124,
-76,
-110,
-211,
-73,
-50,
-3,
-49,
-170,
-58,
-20,
-143,
-14,
-170,
-102,
-204,
-142,
-154,
-0,
-80,
-30,
-222,
-72,
-198,
-90,
-119,
-93,
-155,
-228,
-11,
-222,
-105,
-0,
-0,
-32,
-0,
-73,
-68,
-65,
-84,
-126,
-245,
-10,
-223,
-77,
-35,
-103,
-184,
-54,
-55,
-252,
-109,
-192,
-179,
-75,
-218,
-94,
-175,
-52,
-222,
-250,
-154,
-235,
-30,
-168,
-109,
-127,
-210,
-178,
-223,
-171,
-146,
-235,
-41,
-26,
-69,
-250,
-69,
-172,
-226,
-246,
-65,
-142,
-207,
-30,
-211,
-9,
-244,
-40,
-18,
-179,
-239,
-169,
-88,
-127,
-129,
-188,
-142,
-210,
-62,
-60,
-0,
-60,
-39,
-128,
-190,
-113,
-136,
-108,
-231,
-29,
-185,
-199,
-128,
-151,
-147,
-103,
-16,
-6,
-57,
-222,
-107,
-154,
-61,
-233,
-47,
-218,
-246,
-227,
-77,
-218,
-85,
-244,
-175,
-205,
-210,
-217,
-21,
-134,
-183,
-35,
-177,
-18,
-239,
-33,
-55,
-157,
-29,
-88,
-29,
-86,
-93,
-143,
-252,
-195,
-50,
-42,
-2,
-96,
-84,
-65,
-139,
-240,
-75,
-197,
-155,
-70,
-190,
-12,
-54,
-106,
-203,
-239,
-168,
-176,
-140,
-115,
-6,
-224,
-13,
-228,
-122,
-135,
-25,
-136,
-34,
-241,
-48,
-96,
-227,
-138,
-182,
-214,
-183,
-250,
-3,
-136,
-34,
-240,
-92,
-228,
-4,
-194,
-102,
-214,
-221,
-151,
-81,
-138,
-100,
-27,
-10,
-36,
-86,
-194,
-66,
-237,
-119,
-173,
-7,
-38,
-45,
-67,
-100,
-227,
-199,
-34,
-114,
-161,
-181,
-107,
-203,
-254,
-91,
-151,
-220,
-255,
-182,
-105,
-239,
-233,
-95,
-27,
-1,
-96,
-141,
-176,
-182,
-43,
-148,
-175,
-130,
-152,
-118,
-15,
-40,
-107,
-201,
-133,
-195,
-139,
-60,
-117,
-54,
-151,
-197,
-216,
-250,
-210,
-246,
-13,
-90,
-134,
-95,
-42,
-190,
-60,
-242,
-188,
-238,
-181,
-54,
-220,
-192,
-57,
-74,
-251,
-24,
-18,
-84,
-99,
-50,
-249,
-30,
-26,
-68,
-8,
-121,
-191,
-46,
-228,
-86,
-98,
-135,
-32,
-95,
-224,
-123,
-144,
-47,
-210,
-69,
-228,
-10,
-147,
-191,
-50,
-138,
-185,
-238,
-235,
-128,
-108,
-29,
-166,
-2,
-91,
-6,
-210,
-71,
-15,
-145,
-61,
-22,
-208,
-81,
-0,
-216,
-49,
-251,
-170,
-6,
-109,
-236,
-24,
-123,
-183,
-167,
-238,
-232,
-9,
-39,
-0,
-232,
-16,
-126,
-201,
-35,
-0,
-172,
-86,
-62,
-40,
-35,
-47,
-158,
-76,
-61,
-192,
-243,
-200,
-45,
-206,
-22,
-1,
-219,
-122,
-104,
-158,
-112,
-234,
-191,
-228,
-78,
-116,
-196,
-108,
-210,
-30,
-13,
-214,
-166,
-7,
-79,
-24,
-93,
-116,
-20,
-0,
-214,
-131,
-114,
-26,
-18,
-200,
-165,
-54,
-89,
-8,
-185,
-221,
-199,
-21,
-56,
-33,
-235,
-17,
-109,
-187,
-213,
-196,
-79,
-40,
-1,
-208,
-58,
-252,
-146,
-71,
-0,
-156,
-161,
-191,
-255,
-71,
-71,
-175,
-54,
-135,
-215,
-217,
-158,
-58,
-171,
-184,
-250,
-105,
-73,
-91,
-107,
-100,
-84,
-233,
-217,
-151,
-48,
-250,
-112,
-198,
-208,
-250,
-72,
-120,
-178,
-43,
-244,
-67,
-242,
-36,
-178,
-69,
-169,
-212,
-209,
-0,
-7,
-56,
-60,
-230,
-35,
-137,
-76,
-94,
-91,
-65,
-255,
-26,
-103,
-252,
-204,
-64,
-156,
-186,
-172,
-201,
-241,
-183,
-24,
-35,
-218,
-118,
-2,
-17,
-227,
-66,
-173,
-195,
-47,
-57,
-253,
-176,
-2,
-96,
-53,
-196,
-198,
-29,
-100,
-41,
-254,
-77,
-90,
-46,
-195,
-145,
-99,
-53,
-240,
-251,
-79,
-91,
-205,
-185,
-55,
-12,
-54,
-98,
-224,
-3,
-53,
-161,
-200,
-144,
-213,
-198,
-137,
-200,
-82,
-124,
-62,
-178,
-31,
-191,
-4,
-201,
-224,
-227,
-205,
-136,
-172,
-237,
-90,
-5,
-147,
-64,
-146,
-119,
-124,
-13,
-81,
-194,
-77,
-211,
-107,
-78,
-69,
-132,
-221,
-86,
-177,
-219,
-141,
-7,
-56,
-99,
-200,
-166,
-115,
-191,
-27,
-217,
-130,
-218,
-119,
-60,
-159,
-146,
-248,
-12,
-192,
-203,
-144,
-45,
-228,
-99,
-200,
-135,
-234,
-50,
-135,
-223,
-241,
-192,
-178,
-37,
-237,
-222,
-128,
-156,
-66,
-77,
-67,
-38,
-252,
-53,
-168,
-249,
-54,
-37,
-218,
-246,
-226,
-88,
-47,
-212,
-133,
-132,
-236,
-170,
-132,
-167,
-93,
-85,
-46,
-5,
-107,
-143,
-210,
-42,
-212,
-94,
-241,
-66,
-173,
-195,
-47,
-249,
-30,
-10,
-162,
-37,
-255,
-6,
-121,
-128,
-131,
-179,
-129,
-167,
-181,
-232,
-151,
-245,
-128,
-26,
-8,
-208,
-128,
-40,
-42,
-161,
-160,
-252,
-113,
-234,
-159,
-161,
-245,
-165,
-89,
-109,
-17,
-187,
-118,
-235,
-140,
-51,
-23,
-209,
-67,
-184,
-105,
-209,
-75,
-99,
-236,
-211,
-50,
-152,
-4,
-185,
-185,
-245,
-124,
-228,
-20,
-228,
-42,
-242,
-237,
-204,
-2,
-224,
-245,
-49,
-219,
-85,
-244,
-227,
-45,
-218,
-54,
-232,
-232,
-209,
-211,
-126,
-64,
-168,
-35,
-19,
-174,
-18,
-37,
-188,
-44,
-230,
-3,
-187,
-56,
-229,
-171,
-59,
-247,
-93,
-182,
-58,
-181,
-31,
-155,
-55,
-59,
-101,
-219,
-144,
-7,
-118,
-245,
-174,
-16,
-219,
-192,
-233,
-103,
-83,
-1,
-112,
-82,
-200,
-191,
-6,
-253,
-88,
-146,
-252,
-4,
-173,
-117,
-176,
-29,
-151,
-97,
-235,
-140,
-168,
-53,
-15,
-101,
-11,
-114,
-79,
-168,
-160,
-228,
-34,
-133,
-246,
-239,
-212,
-182,
-183,
-122,
-234,
-172,
-17,
-145,
-247,
-1,
-144,
-11,
-143,
-187,
-43,
-248,
-219,
-243,
-252,
-75,
-113,
-204,
-128,
-17,
-171,
-172,
-255,
-171,
-233,
-91,
-171,
-96,
-18,
-136,
-78,
-229,
-211,
-56,
-206,
-63,
-136,
-213,
-164,
-221,
-151,
-150,
-5,
-20,
-109,
-213,
-174,
-162,
-31,
-246,
-20,
-197,
-187,
-234,
-83,
-154,
-181,
-17,
-99,
-171,
-199,
-245,
-126,
-183,
-208,
-242,
-221,
-128,
-251,
-60,
-244,
-239,
-69,
-242,
-44,
-22,
-255,
-253,
-81,
-175,
-229,
-181,
-52,
-116,
-198,
-208,
-81,
-158,
-58,
-235,
-7,
-255,
-96,
-73,
-91,
-43,
-192,
-87,
-45,
-148,
-111,
-169,
-229,
-211,
-124,
-237,
-218,
-160,
-102,
-172,
-183,
-182,
-31,
-104,
-209,
-15,
-107,
-185,
-121,
-55,
-45,
-62,
-172,
-62,
-134,
-173,
-195,
-47,
-85,
-61,
-20,
-173,
-183,
-166,
-177,
-222,
-244,
-226,
-53,
-188,
-173,
-153,
-241,
-64,
-116,
-94,
-29,
-108,
-32,
-202,
-203,
-1,
-15,
-62,
-224,
-251,
-90,
-95,
-154,
-43,
-143,
-124,
-133,
-210,
-58,
-99,
-75,
-44,
-144,
-123,
-36,
-54,
-90,
-210,
-181,
-105,
-135,
-100,
-199,
-93,
-132,
-28,
-161,
-121,
-151,
-200,
-74,
-119,
-28,
-178,
-23,
-159,
-172,
-244,
-139,
-244,
-255,
-179,
-8,
-207,
-21,
-185,
-20,
-249,
-87,
-220,
-235,
-106,
-237,
-140,
-161,
-1,
-111,
-57,
-242,
-92,
-9,
-197,
-248,
-139,
-182,
-222,
-58,
-103,
-125,
-177,
-80,
-190,
-154,
-150,
-63,
-28,
-210,
-207,
-16,
-140,
-5,
-1,
-128,
-196,
-143,
-176,
-10,
-238,
-82,
-225,
-221,
-148,
-105,
-235,
-240,
-75,
-1,
-2,
-96,
-11,
-173,
-247,
-45,
-227,
-255,
-12,
-236,
-4,
-172,
-84,
-40,
-127,
-22,
-185,
-121,
-234,
-116,
-96,
-125,
-79,
-219,
-165,
-200,
-61,
-168,
-46,
-70,
-181,
-191,
-136,
-117,
-219,
-222,
-200,
-228,
-94,
-68,
-197,
-241,
-144,
-211,
-247,
-129,
-243,
-224,
-97,
-131,
-138,
-156,
-245,
-177,
-219,
-1,
-63,
-214,
-38,
-3,
-57,
-10,
-11,
-116,
-83,
-129,
-15,
-232,
-255,
-95,
-140,
-172,
-2,
-108,
-154,
-171,
-160,
-212,
-220,
-136,
-82,
-13,
-224,
-156,
-10,
-26,
-139,
-1,
-165,
-113,
-221,
-196,
-66,
-44,
-231,
-108,
-252,
-201,
-19,
-201,
-117,
-81,
-54,
-191,
-197,
-9,
-33,
-253,
-12,
-188,
-151,
-210,
-177,
-94,
-215,
-207,
-136,
-125,
-248,
-182,
-94,
-230,
-26,
-98,
-185,
-99,
-211,
-33,
-252,
-146,
-251,
-80,
-244,
-101,
-63,
-203,
-169,
-91,
-154,
-220,
-34,
-112,
-96,
-175,
-233,
-180,
-93,
-132,
-68,
-215,
-185,
-158,
-145,
-250,
-136,
-71,
-41,
-217,
-227,
-107,
-251,
-231,
-147,
-239,
-217,
-231,
-33,
-123,
-120,
-55,
-88,
-68,
-229,
-254,
-200,
-161,
-107,
-44,
-0,
-104,
-153,
-179,
-14,
-17,
-92,
-31,
-68,
-142,
-57,
-39,
-33,
-210,
-124,
-58,
-185,
-86,
-186,
-108,
-160,
-183,
-106,
-231,
-225,
-179,
-28,
-121,
-32,
-144,
-245,
-234,
-250,
-26,
-194,
-179,
-162,
-253,
-75,
-245,
-189,
-60,
-65,
-197,
-177,
-176,
-59,
-134,
-60,
-117,
-33,
-105,
-188,
-94,
-67,
-190,
-202,
-88,
-132,
-40,
-74,
-23,
-33,
-218,
-253,
-213,
-187,
-220,
-67,
-204,
-126,
-70,
-184,
-254,
-51,
-201,
-21,
-163,
-241,
-130,
-165,
-210,
-33,
-252,
-146,
-251,
-80,
-156,
-23,
-112,
-51,
-98,
-16,
-100,
-39,
-243,
-130,
-146,
-182,
-111,
-67,
-162,
-235,
-220,
-138,
-44,
-43,
-109,
-176,
-135,
-203,
-144,
-211,
-131,
-218,
-224,
-154,
-136,
-178,
-239,
-80,
-229,
-49,
-87,
-219,
-159,
-77,
-64,
-242,
-72,
-167,
-239,
-141,
-4,
-0,
-237,
-141,
-166,
-214,
-36,
-247,
-165,
-183,
-207,
-197,
-70,
-82,
-182,
-171,
-25,
-159,
-18,
-169,
-85,
-187,
-146,
-62,
-216,
-253,
-227,
-233,
-77,
-238,
-185,
-41,
-144,
-152,
-131,
-54,
-198,
-226,
-110,
-53,
-180,
-79,
-141,
-33,
-79,
-93,
-240,
-196,
-2,
-94,
-133,
-172,
-28,
-109,
-148,
-235,
-203,
-112,
-18,
-170,
-118,
-69,
-172,
-126,
-118,
-184,
-190,
-141,
-223,
-248,
-215,
-62,
-152,
-119,
-201,
-136,
-138,
-62,
-128,
-189,
-244,
-161,
-79,
-67,
-36,
-255,
-20,
-100,
-153,
-223,
-200,
-214,
-190,
-111,
-144,
-107,
-240,
-189,
-168,
-105,
-219,
-197,
-104,
-234,
-55,
-90,
-55,
-21,
-49,
-58,
-121,
-186,
-83,
-87,
-165,
-69,
-110,
-213,
-174,
-164,
-255,
-255,
-85,
-242,
-202,
-47,
-8,
-29,
-143,
-29,
-17,
-229,
-31,
-4,
-164,
-238,
-114,
-199,
-144,
-167,
-174,
-241,
-196,
-66,
-78,
-15,
-78,
-213,
-102,
-165,
-91,
-143,
-166,
-168,
-233,
-103,
-175,
-17,
-123,
-128,
-23,
-34,
-130,
-127,
-1,
-125,
-69,
-101,
-166,
-135,
-240,
-75,
-99,
-17,
-136,
-143,
-194,
-105,
-206,
-11,
-61,
-71,
-127,
-159,
-134,
-39,
-244,
-121,
-161,
-109,
-23,
-163,
-41,
-187,
-106,
-24,
-8,
-23,
-70,
-158,
-67,
-209,
-39,
-0,
-90,
-181,
-243,
-208,
-110,
-173,
-164,
-33,
-110,
-222,
-173,
-143,
-29,
-17,
-197,
-164,
-13,
-150,
-26,
-178,
-138,
-171,
-154,
-88,
-173,
-190,
-172,
-136,
-16,
-128,
-192,
-32,
-39,
-129,
-60,
-45,
-124,
-62,
-4,
-189,
-70,
-236,
-33,
-63,
-181,
-57,
-186,
-15,
-254,
-19,
-18,
-85,
-47,
-180,
-162,
-77,
-23,
-163,
-41,
-123,
-234,
-176,
-173,
-167,
-206,
-38,
-21,
-241,
-9,
-128,
-86,
-237,
-60,
-180,
-246,
-171,
-248,
-169,
-0,
-218,
-182,
-199,
-149,
-79,
-71,
-182,
-128,
-224,
-177,
-181,
-47,
-105,
-211,
-74,
-0,
-32,
-142,
-103,
-251,
-81,
-80,
-18,
-35,
-129,
-91,
-191,
-172,
-205,
-188,
-193,
-104,
-218,
-192,
-233,
-167,
-207,
-135,
-224,
-136,
-190,
-4,
-0,
-121,
-66,
-145,
-25,
-44,
-38,
-31,
-225,
-49,
-129,
-150,
-2,
-160,
-139,
-209,
-148,
-221,
-175,
-31,
-135,
-42,
-216,
-116,
-176,
-238,
-69,
-133,
-50,
-175,
-109,
-187,
-2,
-143,
-103,
-145,
-39,
-109,
-25,
-240,
-191,
-104,
-112,
-255,
-149,
-199,
-142,
-136,
-98,
-20,
-224,
-196,
-6,
-60,
-45,
-154,
-10,
-128,
-45,
-156,
-182,
-83,
-145,
-149,
-235,
-21,
-228,
-43,
-166,
-57,
-56,
-6,
-66,
-93,
-225,
-92,
-171,
-232,
-67,
-240,
-46,
-122,
-138,
-216,
-163,
-239,
-217,
-234,
-127,
-190,
-21,
-147,
-247,
-168,
-163,
-234,
-197,
-7,
-180,
-253,
-56,
-18,
-94,
-123,
-153,
-170,
-178,
-138,
-246,
-75,
-59,
-215,
-127,
-126,
-29,
-189,
-211,
-174,
-139,
-209,
-212,
-78,
-133,
-1,
-123,
-53,
-185,
-13,
-198,
-126,
-168,
-34,
-54,
-86,
-187,
-2,
-15,
-107,
-47,
-255,
-243,
-208,
-123,
-45,
-225,
-83,
-122,
-236,
-136,
-36,
-191,
-180,
-39,
-58,
-193,
-9,
-82,
-170,
-198,
-1,
-213,
-2,
-96,
-57,
-224,
-115,
-250,
-188,
-109,
-92,
-134,
-199,
-16,
-229,
-227,
-49,
-68,
-202,
-112,
-237,
-233,
-39,
-228,
-62,
-4,
-174,
-242,
-124,
-126,
-221,
-123,
-104,
-113,
-205,
-143,
-40,
-255,
-7,
-0,
-111,
-78,
-193,
-113,
-139,
-170,
-23,
-31,
-208,
-214,
-198,
-19,
-60,
-162,
-170,
-172,
-162,
-253,
-122,
-206,
-245,
-87,
-171,
-163,
-119,
-218,
-117,
-202,
-89,
-135,
-248,
-155,
-95,
-142,
-40,
-11,
-167,
-33,
-166,
-172,
-239,
-214,
-186,
-147,
-203,
-6,
-80,
-219,
-118,
-90,
-239,
-166,
-245,
-10,
-18,
-118,
-180,
-56,
-118,
-116,
-38,
-195,
-121,
-248,
-45,
-2,
-127,
-0,
-172,
-27,
-246,
-164,
-198,
-30,
-156,
-241,
-178,
-23,
-114,
-234,
-51,
-15,
-17,
-118,
-135,
-33,
-6,
-58,
-255,
-139,
-41,
-0,
-144,
-237,
-148,
-85,
-56,
-119,
-10,
-186,
-210,
-244,
-194,
-0,
-199,
-55,
-108,
-179,
-153,
-14,
-208,
-25,
-192,
-5,
-84,
-4,
-243,
-40,
-92,
-167,
-173,
-0,
-88,
-150,
-124,
-105,
-180,
-91,
-89,
-89,
-69,
-123,
-155,
-171,
-189,
-209,
-30,
-145,
-33,
-228,
-172,
-139,
-13,
-36,
-104,
-10,
-4,
-154,
-11,
-211,
-254,
-184,
-50,
-4,
-193,
-126,
-251,
-99,
-13,
-206,
-61,
-84,
-218,
-79,
-68,
-188,
-222,
-87,
-236,
-24,
-101,
-152,
-113,
-45,
-90,
-10,
-128,
-203,
-145,
-229,
-247,
-54,
-136,
-86,
-253,
-162,
-192,
-235,
-180,
-18,
-0,
-218,
-254,
-121,
-136,
-192,
-153,
-137,
-6,
-201,
-240,
-149,
-121,
-218,
-109,
-133,
-236,
-229,
-231,
-18,
-96,
-47,
-80,
-104,
-59,
-30,
-115,
-214,
-89,
-135,
-153,
-218,
-156,
-135,
-74,
-31,
-237,
-216,
-113,
-113,
-130,
-51,
-94,
-135,
-18,
-9,
-153,
-60,
-206,
-228,
-221,
-52,
-216,
-106,
-182,
-189,
-216,
-26,
-136,
-59,
-166,
-53,
-222,
-88,
-136,
-44,
-233,
-206,
-69,
-114,
-215,
-85,
-38,
-59,
-208,
-9,
-103,
-131,
-23,
-238,
-2,
-76,
-15,
-184,
-102,
-39,
-1,
-160,
-60,
-62,
-172,
-60,
-110,
-69,
-77,
-138,
-125,
-101,
-37,
-215,
-125,
-130,
-234,
-116,
-232,
-3,
-171,
-3,
-198,
-89,
-206,
-58,
-114,
-167,
-168,
-187,
-8,
-252,
-138,
-16,
-233,
-216,
-113,
-113,
-67,
-140,
-241,
-218,
-242,
-122,
-149,
-136,
-113,
-161,
-13,
-200,
-227,
-243,
-89,
-239,
-170,
-39,
-201,
-205,
-14,
-161,
-102,
-201,
-139,
-104,
-96,
-207,
-66,
-206,
-154,
-207,
-1,
-46,
-108,
-112,
-131,
-27,
-21,
-202,
-215,
-118,
-38,
-217,
-55,
-107,
-120,
-216,
-201,
-126,
-39,
-185,
-103,
-222,
-64,
-89,
-201,
-117,
-91,
-61,
-92,
-122,
-202,
-89,
-215,
-7,
-144,
-92,
-132,
-0,
-95,
-105,
-208,
-38,
-202,
-177,
-99,
-108,
-208,
-62,
-6,
-67,
-171,
-140,
-87,
-30,
-62,
-222,
-241,
-58,
-238,
-1,
-252,
-93,
-111,
-236,
-100,
-228,
-11,
-7,
-226,
-219,
-157,
-33,
-129,
-53,
-190,
-10,
-172,
-80,
-195,
-99,
-115,
-228,
-120,
-100,
-38,
-226,
-156,
-83,
-27,
-103,
-223,
-247,
-64,
-245,
-250,
-54,
-237,
-118,
-93,
-86,
-160,
-231,
-233,
-75,
-157,
-141,
-134,
-127,
-246,
-149,
-245,
-1,
-250,
-203,
-89,
-119,
-157,
-254,
-191,
-113,
-100,
-28,
-15,
-191,
-213,
-180,
-253,
-156,
-38,
-3,
-159,
-8,
-199,
-142,
-125,
-128,
-246,
-49,
-24,
-26,
-103,
-188,
-42,
-225,
-179,
-216,
-10,
-0,
-251,
-213,
-127,
-174,
-254,
-134,
-134,
-58,
-128,
-150,
-215,
-29,
-241,
-64,
-17,
-205,
-179,
-21,
-70,
-103,
-81,
-177,
-100,
-101,
-164,
-194,
-239,
-163,
-101,
-101,
-227,
-9,
-218,
-239,
-89,
-136,
-9,
-46,
-52,
-136,
-140,
-19,
-185,
-31,
-157,
-143,
-29,
-27,
-92,
-43,
-56,
-47,
-2,
-45,
-99,
-48,
-40,
-109,
-163,
-140,
-87,
-37,
-60,
-22,
-91,
-1,
-96,
-131,
-118,
-188,
-64,
-127,
-15,
-91,
-0,
-172,
-171,
-191,
-173,
-179,
-195,
-21,
-212,
-156,
-121,
-146,
-31,
-249,
-29,
-85,
-85,
-54,
-158,
-224,
-60,
-143,
-198,
-145,
-113,
-122,
-232,
-75,
-235,
-99,
-199,
-134,
-215,
-105,
-148,
-23,
-161,
-227,
-181,
-130,
-51,
-94,
-77,
-40,
-144,
-107,
-125,
-207,
-71,
-210,
-101,
-5,
-11,
-0,
-58,
-56,
-141,
-56,
-3,
-126,
-37,
-242,
-175,
-222,
-109,
-132,
-217,
-143,
-239,
-133,
-232,
-26,
-150,
-169,
-42,
-27,
-79,
-112,
-158,
-71,
-227,
-200,
-56,
-227,
-17,
-52,
-204,
-139,
-176,
-56,
-3,
-120,
-1,
-146,
-165,
-249,
-78,
-68,
-7,
-243,
-32,
-178,
-157,
-252,
-70,
-9,
-125,
-20,
-189,
-134,
-101,
-182,
-22,
-185,
-59,
-171,
-53,
-105,
-60,
-139,
-138,
-104,
-49,
-158,
-142,
-180,
-113,
-26,
-65,
-7,
-192,
-251,
-201,
-131,
-58,
-116,
-138,
-36,
-60,
-158,
-225,
-8,
-128,
-198,
-145,
-113,
-198,
-35,
-104,
-144,
-23,
-161,
-203,
-135,
-102,
-172,
-3,
-9,
-125,
-103,
-183,
-225,
-243,
-17,
-155,
-11,
-155,
-113,
-219,
-235,
-250,
-75,
-36,
-189,
-134,
-203,
-112,
-5,
-196,
-189,
-213,
-77,
-181,
-253,
-40,
-146,
-130,
-107,
-224,
-40,
-205,
-105,
-215,
-58,
-86,
-157,
-35,
-0,
-102,
-59,
-215,
-236,
-100,
-170,
-218,
-7,
-144,
-147,
-141,
-63,
-170,
-144,
-156,
-141,
-40,
-58,
-39,
-35,
-22,
-96,
-3,
-251,
-73,
-231,
-94,
-26,
-125,
-213,
-156,
-118,
-141,
-34,
-227,
-180,
-189,
-222,
-120,
-2,
-237,
-131,
-169,
-142,
-105,
-193,
-129,
-164,
-147,
-183,
-167,
-71,
-191,
-64,
-77,
-168,
-17,
-5,
-252,
-22,
-84,
-40,
-178,
-137,
-160,
-215,
-240,
-49,
-93,
-74,
-59,
-243,
-8,
-249,
-106,
-224,
-54,
-26,
-90,
-63,
-17,
-16,
-171,
-206,
-25,
-184,
-23,
-0,
-219,
-59,
-15,
-98,
-224,
-11,
-56,
-90,
-0,
-118,
-37,
-95,
-157,
-216,
-140,
-173,
-55,
-145,
-167,
-151,
-58,
-204,
-211,
-166,
-171,
-0,
-104,
-27,
-118,
-122,
-113,
-22,
-0,
-109,
-189,
-19,
-27,
-11,
-142,
-182,
-239,
-193,
-161,
-9,
-94,
-206,
-147,
-39,
-208,
-253,
-119,
-248,
-211,
-24,
-209,
-62,
-190,
-94,
-67,
-59,
-116,
-60,
-34,
-157,
-172,
-251,
-107,
-35,
-229,
-19,
-1,
-177,
-234,
-138,
-15,
-26,
-201,
-84,
-11,
-226,
-71,
-62,
-38,
-220,
-30,
-201,
-131,
-78,
-126,
-169,
-80,
-190,
-58,
-240,
-73,
-60,
-130,
-177,
-237,
-132,
-108,
-59,
-240,
-34,
-92,
-207,
-98,
-158,
-14,
-166,
-179,
-245,
-93,
-84,
-157,
-194,
-52,
-254,
-178,
-182,
-189,
-191,
-154,
-123,
-168,
-243,
-78,
-108,
-44,
-56,
-186,
-244,
-147,
-134,
-203,
-121,
-68,
-225,
-13,
-99,
-196,
-110,
-196,
-24,
-51,
-242,
-20,
-0,
-216,
-68,
-127,
-151,
-133,
-116,
-110,
-29,
-171,
-206,
-247,
-160,
-201,
-67,
-72,
-159,
-67,
-172,
-160,
-135,
-35,
-175,
-217,
-52,
-181,
-182,
-53,
-138,
-121,
-69,
-131,
-107,
-88,
-12,
-91,
-0,
-88,
-204,
-67,
-38,
-227,
-57,
-192,
-158,
-148,
-196,
-246,
-115,
-232,
-109,
-214,
-224,
-171,
-16,
-133,
-156,
-197,
-69,
-148,
-164,
-254,
-102,
-20,
-190,
-172,
-37,
-253,
-104,
-27,
-76,
-181,
-84,
-112,
-116,
-120,
-15,
-141,
-151,
-243,
-228,
-199,
-171,
-3,
-17,
-164,
-70,
-13,
-218,
-161,
-227,
-245,
-255,
-214,
-231,
-218,
-151,
-157,
-167,
-83,
-172,
-58,
-223,
-131,
-70,
-190,
-172,
-54,
-208,
-231,
-126,
-145,
-239,
-171,
-77,
-106,
-109,
-187,
-2,
-186,
-140,
-26,
-115,
-104,
-167,
-141,
-197,
-176,
-5,
-64,
-217,
-68,
-190,
-20,
-207,
-177,
-170,
-175,
-159,
-72,
-210,
-137,
-221,
-201,
-183,
-56,
-7,
-148,
-244,
-117,
-216,
-95,
-214,
-40,
-65,
-81,
-29,
-126,
-85,
-110,
-205,
-109,
-223,
-67,
-227,
-229,
-60,
-185,
-123,
-121,
-155,
-15,
-76,
-41,
-66,
-121,
-89,
-134,
-199,
-2,
-219,
-162,
-199,
-103,
-202,
-227,
-120,
-36,
-20,
-180,
-205,
-246,
-251,
-27,
-79,
-187,
-78,
-78,
-35,
-101,
-15,
-26,
-209,
-7,
-44,
-66,
-190,
-190,
-47,
-109,
-116,
-51,
-229,
-215,
-106,
-155,
-90,
-251,
-185,
-228,
-89,
-102,
-108,
-222,
-185,
-186,
-120,
-122,
-22,
-163,
-182,
-5,
-96,
-112,
-34,
-127,
-183,
-73,
-63,
-117,
-76,
-0,
-220,
-212,
-240,
-30,
-250,
-248,
-178,
-182,
-254,
-208,
-208,
-206,
-173,
-185,
-109,
-63,
-27,
-47,
-231,
-201,
-87,
-77,
-219,
-54,
-104,
-99,
-97,
-5,
-126,
-55,
-7,
-33,
-135,
-225,
-28,
-242,
-227,
-192,
-69,
-78,
-249,
-36,
-60,
-103,
-243,
-116,
-116,
-26,
-169,
-121,
-208,
-54,
-118,
-253,
-77,
-68,
-8,
-132,
-64,
-135,
-212,
-218,
-200,
-151,
-237,
-235,
-140,
-60,
-33,
-249,
-95,
-217,
-75,
-115,
-104,
-70,
-93,
-7,
-64,
-197,
-68,
-174,
-105,
-183,
-187,
-29,
-19,
-13,
-239,
-161,
-143,
-47,
-107,
-219,
-96,
-170,
-93,
-221,
-154,
-155,
-246,
-179,
-241,
-114,
-30,
-177,
-244,
-132,
-6,
-89,
-172,
-171,
-222,
-91,
-43,
-32,
-190,
-241,
-127,
-67,
-150,
-222,
-118,
-73,
-50,
-13,
-56,
-29,
-217,
-67,
-150,
-37,
-88,
-28,
-147,
-78,
-35,
-125,
-1,
-9,
-172,
-241,
-254,
-194,
-160,
-218,
-217,
-67,
-215,
-234,
-5,
-117,
-24,
-120,
-165,
-215,
-163,
-98,
-34,
-215,
-180,
-219,
-77,
-235,
-158,
-40,
-233,
-235,
-48,
-191,
-172,
-109,
-131,
-169,
-182,
-21,
-28,
-109,
-251,
-217,
-102,
-57,
-127,
-176,
-182,
-57,
-191,
-65,
-155,
-210,
-247,
-22,
-5,
-202,
-252,
-248,
-0,
-186,
-49,
-233,
-52,
-210,
-55,
-244,
-30,
-109,
-16,
-200,
-41,
-158,
-250,
-126,
-95,
-80,
-131,
-235,
-81,
-49,
-145,
-107,
-218,
-157,
-160,
-117,
-255,
-242,
-212,
-13,
-251,
-203,
-218,
-54,
-152,
-106,
-91,
-193,
-81,
-213,
-207,
-23,
-87,
-180,
-107,
-179,
-156,
-95,
-151,
-60,
-143,
-193,
-33,
-56,
-241,
-26,
-145,
-20,
-110,
-187,
-86,
-244,
-111,
-212,
-5,
-192,
-208,
-156,
-70,
-186,
-160,
-237,
-192,
-171,
-225,
-249,
-82,
-109,
-214,
-232,
-203,
-218,
-7,
-170,
-174,
-71,
-245,
-68,
-30,
-104,
-135,
-56,
-84,
-125,
-158,
-92,
-119,
-240,
-78,
-79,
-187,
-62,
-190,
-172,
-85,
-19,
-171,
-109,
-48,
-213,
-182,
-130,
-195,
-222,
-187,
-47,
-252,
-247,
-59,
-42,
-218,
-53,
-94,
-206,
-107,
-187,
-247,
-145,
-219,
-220,
-204,
-67,
-156,
-192,
-102,
-233,
-239,
-255,
-120,
-232,
-75,
-223,
-119,
-20,
-40,
-243,
-227,
-3,
-105,
-135,
-226,
-52,
-210,
-5,
-53,
-3,
-175,
-106,
-192,
-110,
-128,
-132,
-151,
-222,
-160,
-80,
-254,
-52,
-114,
-39,
-150,
-43,
-43,
-174,
-55,
-106,
-2,
-128,
-176,
-137,
-108,
-97,
-149,
-73,
-215,
-49,
-50,
-6,
-196,
-129,
-37,
-215,
-107,
-251,
-101,
-109,
-59,
-177,
-218,
-6,
-83,
-109,
-43,
-56,
-172,
-137,
-173,
-47,
-252,
-247,
-209,
-21,
-237,
-26,
-47,
-231,
-157,
-182,
-155,
-35,
-185,
-13,
-239,
-65,
-182,
-18,
-51,
-144,
-147,
-167,
-15,
-121,
-104,
-7,
-222,
-247,
-98,
-5,
-106,
-34,
-215,
-208,
-208,
-17,
-194,
-121,
-96,
-93,
-194,
-78,
-63,
-128,
-104,
-121,
-175,
-36,
-15,
-213,
-52,
-11,
-216,
-186,
-226,
-122,
-195,
-22,
-0,
-77,
-39,
-114,
-17,
-179,
-144,
-19,
-143,
-147,
-80,
-159,
-251,
-146,
-118,
-109,
-191,
-172,
-173,
-38,
-150,
-214,
-55,
-254,
-208,
-208,
-94,
-112,
-216,
-163,
-204,
-98,
-248,
-239,
-247,
-144,
-239,
-243,
-125,
-237,
-26,
-47,
-231,
-219,
-192,
-243,
-222,
-6,
-16,
-227,
-58,
-189,
-130,
-134,
-185,
-231,
-11,
-109,
-27,
-57,
-66,
-56,
-207,
-165,
-75,
-216,
-233,
-71,
-145,
-175,
-198,
-227,
-136,
-31,
-192,
-49,
-192,
-38,
-53,
-215,
-27,
-182,
-0,
-176,
-8,
-157,
-200,
-173,
-250,
-73,
-251,
-47,
-107,
-171,
-137,
-213,
-5,
-180,
-19,
-28,
-175,
-113,
-238,
-195,
-134,
-255,
-182,
-17,
-160,
-190,
-133,
-90,
-250,
-149,
-92,
-175,
-209,
-114,
-190,
-229,
-61,
-89,
-196,
-57,
-6,
-28,
-13,
-208,
-49,
-247,
-60,
-13,
-28,
-33,
-156,
-7,
-54,
-148,
-164,
-142,
-109,
-39,
-214,
-176,
-175,
-215,
-161,
-93,
-219,
-47,
-107,
-235,
-137,
-53,
-108,
-0,
-111,
-64,
-220,
-227,
-167,
-105,
-191,
-174,
-65,
-183,
-60,
-168,
-0,
-172,
-104,
-27,
-188,
-156,
-111,
-217,
-183,
-161,
-142,
-175,
-94,
-64,
-156,
-220,
-243,
-65,
-142,
-16,
-73,
-0,
-196,
-109,
-167,
-109,
-219,
-230,
-55,
-104,
-61,
-177,
-198,
-27,
-144,
-128,
-172,
-179,
-233,
-47,
-65,
-73,
-52,
-59,
-128,
-149,
-129,
-207,
-34,
-182,
-223,
-143,
-35,
-75,
-151,
-59,
-145,
-163,
-174,
-210,
-188,
-238,
-5,
-30,
-63,
-69,
-246,
-63,
-191,
-8,
-164,
-239,
-148,
-123,
-190,
-9,
-70,
-81,
-0,
-148,
-46,
-209,
-208,
-8,
-202,
-145,
-175,
-55,
-52,
-1,
-144,
-80,
-15,
-196,
-106,
-116,
-145,
-10,
-188,
-82,
-33,
-64,
-190,
-69,
-216,
-190,
-170,
-204,
-169,
-139,
-46,
-0,
-174,
-115,
-152,
-62,
-142,
-132,
-8,
-179,
-150,
-128,
-15,
-17,
-96,
-3,
-79,
-238,
-241,
-52,
-51,
-74,
-167,
-34,
-162,
-70,
-0,
-148,
-30,
-63,
-69,
-184,
-94,
-21,
-62,
-223,
-195,
-245,
-146,
-0,
-24,
-67,
-0,
-222,
-77,
-158,
-133,
-250,
-218,
-10,
-186,
-187,
-138,
-239,
-193,
-87,
-230,
-212,
-69,
-23,
-0,
-123,
-0,
-63,
-193,
-201,
-59,
-142,
-36,
-147,
-188,
-64,
-47,
-116,
-106,
-0,
-143,
-35,
-145,
-229,
-78,
-200,
-254,
-29,
-90,
-68,
-191,
-173,
-153,
-200,
-85,
-202,
-188,
-86,
-199,
-79,
-139,
-59,
-22,
-87,
-1,
-64,
-131,
-64,
-163,
-67,
-234,
-207,
-165,
-148,
-88,
-84,
-106,
-189,
-61,
-213,
-90,
-167,
-170,
-204,
-169,
-27,
-206,
-123,
-3,
-94,
-168,
-23,
-122,
-44,
-50,
-95,
-104,
-17,
-253,
-182,
-131,
-0,
-104,
-125,
-252,
-180,
-56,
-99,
-49,
-22,
-0,
-149,
-129,
-70,
-145,
-232,
-87,
-7,
-33,
-39,
-37,
-115,
-144,
-237,
-238,
-161,
-212,
-132,
-190,
-111,
-216,
-135,
-157,
-145,
-21,
-192,
-1,
-122,
-141,
-210,
-108,
-201,
-72,
-252,
-5,
-112,
-76,
-238,
-125,
-101,
-78,
-221,
-208,
-4,
-192,
-202,
-118,
-178,
-70,
-230,
-107,
-209,
-40,
-250,
-109,
-7,
-1,
-48,
-244,
-227,
-167,
-197,
-25,
-250,
-184,
-46,
-215,
-255,
-175,
-173,
-19,
-238,
-110,
-68,
-195,
-127,
-123,
-69,
-187,
-224,
-88,
-12,
-200,
-10,
-244,
-100,
-100,
-85,
-248,
-36,
-240,
-59,
-2,
-130,
-196,
-16,
-16,
-104,
-84,
-199,
-195,
-34,
-36,
-120,
-201,
-151,
-201,
-147,
-167,
-252,
-182,
-142,
-127,
-40,
-144,
-143,
-217,
-124,
-228,
-68,
-228,
-103,
-84,
-56,
-180,
-33,
-39,
-6,
-211,
-234,
-202,
-156,
-58,
-139,
-126,
-143,
-1,
-17,
-141,
-45,
-212,
-36,
-208,
-68,
-206,
-203,
-33,
-48,
-96,
-165,
-115,
-3,
-141,
-162,
-223,
-118,
-16,
-0,
-227,
-230,
-248,
-105,
-60,
-64,
-159,
-219,
-61,
-72,
-26,
-180,
-41,
-250,
-123,
-33,
-162,
-60,
-190,
-180,
-164,
-77,
-112,
-44,
-6,
-157,
-252,
-54,
-83,
-213,
-249,
-72,
-128,
-218,
-121,
-200,
-74,
-174,
-82,
-8,
-16,
-16,
-104,
-20,
-73,
-152,
-242,
-170,
-66,
-217,
-121,
-68,
-254,
-208,
-133,
-2,
-241,
-124,
-189,
-163,
-174,
-204,
-169,
-171,
-69,
-140,
-78,
-173,
-64,
-238,
-240,
-241,
-165,
-26,
-218,
-87,
-148,
-77,
-218,
-154,
-27,
-104,
-20,
-253,
-214,
-105,
-215,
-38,
-160,
-68,
-47,
-199,
-79,
-180,
-76,
-87,
-165,
-180,
-65,
-95,
-68,
-242,
-56,
-141,
-62,
-188,
-172,
-77,
-191,
-187,
-64,
-175,
-59,
-31,
-17,
-164,
-255,
-3,
-222,
-132,
-38,
-74,
-197,
-241,
-11,
-112,
-232,
-27,
-197,
-98,
-64,
-143,
-17,
-113,
-50,
-60,
-35,
-66,
-124,
-62,
-112,
-82,
-79,
-247,
-116,
-61,
-48,
-169,
-15,
-222,
-227,
-14,
-72,
-162,
-208,
-203,
-245,
-37,
-92,
-74,
-69,
-22,
-92,
-196,
-2,
-236,
-159,
-74,
-91,
-155,
-161,
-69,
-219,
-88,
-180,
-141,
-126,
-59,
-148,
-227,
-188,
-16,
-208,
-62,
-93,
-85,
-163,
-232,
-68,
-72,
-172,
-185,
-67,
-157,
-103,
-240,
-123,
-224,
-67,
-68,
-136,
-149,
-208,
-20,
-78,
-31,
-30,
-194,
-217,
-82,
-85,
-208,
-55,
-138,
-197,
-160,
-207,
-99,
-96,
-43,
-1,
-252,
-133,
-10,
-101,
-90,
-91,
-32,
-62,
-19,
-139,
-128,
-157,
-98,
-243,
-30,
-119,
-64,
-210,
-45,
-93,
-175,
-47,
-248,
-106,
-52,
-174,
-89,
-5,
-189,
-85,
-162,
-205,
-2,
-158,
-31,
-120,
-141,
-86,
-19,
-121,
-140,
-10,
-128,
-198,
-233,
-170,
-104,
-25,
-157,
-72,
-219,
-90,
-84,
-42,
-128,
-60,
-253,
-170,
-92,
-153,
-208,
-192,
-191,
-194,
-233,
-195,
-103,
-171,
-232,
-218,
-66,
-251,
-112,
-139,
-167,
-252,
-12,
-60,
-251,
-98,
-58,
-172,
-144,
-144,
-192,
-174,
-243,
-129,
-61,
-99,
-222,
-195,
-184,
-5,
-18,
-204,
-16,
-224,
-6,
-106,
-164,
-59,
-146,
-4,
-19,
-100,
-73,
-61,
-96,
-176,
-80,
-209,
-174,
-15,
-1,
-16,
-253,
-60,
-191,
-47,
-208,
-45,
-58,
-81,
-168,
-0,
-104,
-180,
-50,
-161,
-129,
-127,
-133,
-211,
-135,
-94,
-146,
-175,
-146,
-7,
-134,
-117,
-21,
-196,
-47,
-71,
-156,
-144,
-188,
-71,
-210,
-180,
-88,
-33,
-1,
-223,
-70,
-20,
-140,
-111,
-9,
-236,
-215,
-146,
-218,
-230,
-38,
-196,
-232,
-237,
-33,
-42,
-182,
-122,
-228,
-130,
-125,
-131,
-50,
-154,
-49,
-7,
-242,
-176,
-87,
-219,
-212,
-208,
-109,
-133,
-44,
-155,
-230,
-1,
-219,
-53,
-188,
-70,
-91,
-1,
-48,
-225,
-207,
-243,
-27,
-8,
-128,
-54,
-43,
-147,
-32,
-255,
-138,
-170,
-247,
-87,
-66,
-223,
-232,
-11,
-13,
-172,
-135,
-248,
-22,
-44,
-2,
-206,
-5,
-206,
-68,
-4,
-218,
-163,
-192,
-179,
-107,
-174,
-85,
-251,
-124,
-116,
-34,
-255,
-82,
-39,
-114,
-208,
-170,
-85,
-219,
-125,
-67,
-121,
-47,
-66,
-244,
-70,
-183,
-0,
-191,
-175,
-160,
-183,
-31,
-211,
-198,
-201,
-68,
-201,
-243,
-100,
-222,
-83,
-65,
-211,
-40,
-194,
-117,
-232,
-133,
-237,
-36,
-27,
-80,
-230,
-20,
-232,
-78,
-87,
-186,
-111,
-182,
-184,
-70,
-233,
-0,
-98,
-140,
-156,
-231,
-59,
-125,
-44,
-53,
-89,
-174,
-24,
-212,
-79,
-33,
-70,
-95,
-74,
-174,
-217,
-203,
-25,
-48,
-1,
-254,
-21,
-85,
-239,
-175,
-162,
-77,
-163,
-47,
-52,
-34,
-4,
-78,
-35,
-215,
-145,
-156,
-74,
-128,
-89,
-122,
-200,
-243,
-65,
-182,
-18,
-51,
-129,
-111,
-34,
-251,
-127,
-247,
-95,
-105,
-106,
-58,
-242,
-120,
-153,
-95,
-112,
-202,
-202,
-66,
-174,
-175,
-134,
-156,
-70,
-52,
-122,
-78,
-78,
-251,
-255,
-105,
-91,
-111,
-162,
-91,
-90,
-68,
-184,
-142,
-10,
-231,
-230,
-26,
-101,
-12,
-210,
-182,
-165,
-3,
-136,
-49,
-114,
-158,
-239,
-244,
-177,
-106,
-9,
-105,
-17,
-124,
-30,
-75,
-0,
-2,
-251,
-53,
-106,
-198,
-59,
-85,
-239,
-175,
-65,
-219,
-190,
-4,
-88,
-45,
-255,
-154,
-199,
-255,
-137,
-138,
-118,
-214,
-205,
-183,
-46,
-148,
-252,
-81,
-228,
-113,
-1,
-138,
-152,
-26,
-112,
-15,
-171,
-146,
-155,
-226,
-15,
-196,
-23,
-164,
-131,
-14,
-201,
-69,
-87,
-103,
-28,
-59,
-1,
-163,
-90,
-9,
-214,
-224,
-96,
-99,
-204,
-91,
-141,
-49,
-47,
-55,
-198,
-220,
-13,
-220,
-108,
-140,
-89,
-195,
-24,
-179,
-158,
-49,
-230,
-219,
-198,
-152,
-47,
-27,
-99,
-158,
-214,
-150,
-57,
-34,
-205,
-247,
-51,
-198,
-236,
-229,
-20,
-79,
-7,
-238,
-50,
-198,
-252,
-57,
-203,
-178,
-50,
-251,
-253,
-221,
-179,
-44,
-187,
-174,
-225,
-229,
-174,
-51,
-198,
-244,
-226,
-55,
-161,
-247,
-49,
-191,
-164,
-250,
-229,
-89,
-150,
-85,
-234,
-25,
-22,
-119,
-100,
-89,
-214,
-56,
-225,
-12,
-146,
-164,
-198,
-158,
-134,
-205,
-171,
-33,
-127,
-194,
-24,
-115,
-184,
-49,
-102,
-127,
-253,
-253,
-75,
-45,
-51,
-198,
-152,
-233,
-1,
-151,
-219,
-198,
-24,
-147,
-25,
-99,
-174,
-206,
-178,
-204,
-103,
-202,
-252,
-87,
-173,
-223,
-42,
-203,
-178,
-73,
-218,
-191,
-173,
-141,
-49,
-167,
-107,
-93,
-187,
-163,
-97,
-100,
-95,
-52,
-27,
-56,
-60,
-128,
-246,
-30,
-149,
-80,
-3,
-38,
-187,
-1,
-109,
-75,
-191,
-32,
-140,
-210,
-121,
-190,
-182,
-63,
-217,
-233,
-219,
-44,
-196,
-168,
-228,
-94,
-253,
-253,
-231,
-138,
-251,
-8,
-254,
-154,
-181,
-105,
-211,
-166,
-61,
-13,
-150,
-220,
-52,
-223,
-163,
-151,
-190,
-191,
-88,
-253,
-111,
-139,
-62,
-248,
-35,
-123,
-255,
-219,
-125,
-15,
-39,
-176,
-47,
-141,
-158,
-19,
-98,
-57,
-8,
-145,
-34,
-8,
-53,
-185,
-176,
-117,
-65,
-172,
-61,
-107,
-69,
-156,
-127,
-64,
-38,
-224,
-250,
-78,
-249,
-166,
-136,
-107,
-240,
-238,
-189,
-118,
-54,
-50,
-144,
-100,
-36,
-22,
-135,
-224,
-164,
-196,
-2,
-214,
-199,
-227,
-206,
-217,
-102,
-176,
-117,
-29,
-160,
-77,
-219,
-135,
-210,
-211,
-76,
-96,
-180,
-26,
-216,
-109,
-250,
-63,
-22,
-248,
-3,
-63,
-208,
-127,
-22,
-71,
-217,
-178,
-192,
-190,
-52,
-21,
-0,
-183,
-234,
-191,
-202,
-208,
-120,
-209,
-65,
-179,
-21,
-192,
-218,
-136,
-253,
-183,
-197,
-253,
-228,
-81,
-97,
-64,
-189,
-253,
-198,
-11,
-200,
-163,
-231,
-94,
-220,
-160,
-77,
-227,
-193,
-214,
-117,
-128,
-54,
-109,
-223,
-7,
-253,
-48,
-5,
-0,
-13,
-61,
-251,
-186,
-62,
-223,
-64,
-222,
-161,
-167,
-31,
-173,
-159,
-83,
-95,
-125,
-114,
-177,
-68,
-177,
-32,
-203,
-178,
-189,
-179,
-44,
-123,
-122,
-150,
-101,
-159,
-169,
-107,
-156,
-101,
-217,
-84,
-35,
-123,
-141,
-195,
-141,
-49,
-83,
-140,
-236,
-197,
-151,
-48,
-198,
-92,
-108,
-140,
-249,
-156,
-49,
-102,
-219,
-166,
-29,
-26,
-101,
-88,
-101,
-75,
-173,
-9,
-239,
-68,
-71,
-150,
-227,
-182,
-33,
-92,
-238,
-0,
-99,
-204,
-242,
-198,
-152,
-169,
-198,
-152,
-104,
-65,
-84,
-18,
-186,
-43,
-1,
-77,
-150,
-101,
-15,
-25,
-99,
-62,
-171,
-255,
-198,
-59,
-236,
-17,
-211,
-141,
-45,
-218,
-94,
-75,
-201,
-118,
-176,
-141,
-194,
-41,
-65,
-128,
-216,
-34,
-124,
-220,
-136,
-2,
-109,
-199,
-44,
-203,
-238,
-26,
-229,
-46,
-45,
-86,
-24,
-90,
-72,
-174,
-50,
-32,
-249,
-6,
-239,
-48,
-34,
-225,
-175,
-204,
-178,
-204,
-119,
-228,
-81,
-171,
-212,
-43,
-78,
-178,
-54,
-109,
-140,
-49,
-118,
-207,
-239,
-77,
-131,
-94,
-131,
-54,
-26,
-253,
-36,
-52,
-234,
-241,
-27,
-99,
-204,
-195,
-198,
-152,
-183,
-182,
-56,
-101,
-73,
-168,
-193,
-168,
-11,
-0,
-211,
-108,
-121,
-215,
-102,
-146,
-53,
-105,
-51,
-199,
-136,
-16,
-88,
-174,
-142,
-208,
-131,
-49,
-117,
-12,
-184,
-184,
-32,
-203,
-178,
-168,
-193,
-52,
-19,
-2,
-129,
-132,
-8,
-251,
-15,
-240,
-120,
-143,
-215,
-168,
-13,
-220,
-160,
-116,
-67,
-81,
-180,
-33,
-102,
-179,
-0,
-123,
-213,
-83,
-15,
-183,
-111,
-218,
-238,
-29,
-12,
-106,
-233,
-63,
-136,
-115,
-90,
-17,
-227,
-122,
-125,
-42,
-209,
-198,
-59,
-255,
-166,
-10,
-55,
-52,
-206,
-4,
-145,
-82,
-220,
-199,
-232,
-147,
-139,
-1,
-37,
-160,
-50,
-220,
-223,
-24,
-243,
-43,
-99,
-204,
-43,
-141,
-49,
-247,
-55,
-232,
-64,
-211,
-7,
-110,
-151,
-119,
-219,
-141,
-145,
-229,
-221,
-213,
-250,
-119,
-151,
-74,
-170,
-81,
-0,
-98,
-216,
-115,
-134,
-49,
-230,
-11,
-78,
-241,
-251,
-141,
-49,
-39,
-25,
-99,
-134,
-103,
-254,
-153,
-208,
-20,
-183,
-234,
-223,
-49,
-55,
-166,
-140,
-41,
-17,
-0,
-198,
-152,
-125,
-245,
-239,
-39,
-178,
-44,
-123,
-97,
-9,
-77,
-103,
-100,
-89,
-182,
-105,
-150,
-101,
-107,
-103,
-89,
-118,
-117,
-61,
-245,
-80,
-96,
-195,
-65,
-189,
-17,
-248,
-46,
-35,
-227,
-179,
-173,
-5,
-188,
-125,
-148,
-250,
-101,
-178,
-44,
-91,
-144,
-149,
-99,
-66,
-91,
-245,
-89,
-216,
-21,
-146,
-83,
-180,
-127,
-200,
-10,
-169,
-103,
-28,
-235,
-244,
-229,
-102,
-196,
-132,
-189,
-214,
-20,
-120,
-84,
-225,
-124,
-209,
-155,
-250,
-246,
-143,
-153,
-37,
-93,
-219,
-62,
-145,
-59,
-56,
-129,
-156,
-61,
-223,
-64,
-30,
-154,
-42,
-74,
-150,
-214,
-190,
-159,
-87,
-215,
-235,
-141,
-197,
-247,
-25,
-192,
-115,
-40,
-17,
-147,
-28,
-158,
-161,
-91,
-128,
-12,
-216,
-95,
-199,
-209,
-108,
-196,
-122,
-213,
-27,
-50,
-109,
-88,
-125,
-114,
-81,
-167,
-4,
-12,
-138,
-239,
-215,
-4,
-208,
-74,
-59,
-63,
-76,
-236,
-98,
-140,
-249,
-146,
-49,
-102,
-79,
-99,
-204,
-250,
-198,
-24,
-171,
-132,
-186,
-195,
-24,
-83,
-26,
-213,
-53,
-161,
-30,
-192,
-59,
-140,
-49,
-110,
-34,
-213,
-253,
-129,
-179,
-140,
-49,
-167,
-103,
-89,
-214,
-41,
-22,
-95,
-150,
-101,
-11,
-140,
-216,
-198,
-143,
-41,
-100,
-89,
-134,
-17,
-255,
-149,
-131,
-71,
-187,
-47,
-62,
-140,
-230,
-41,
-192,
-176,
-142,
-205,
-26,
-181,
-201,
-178,
-108,
-190,
-49,
-230,
-123,
-198,
-152,
-239,
-57,
-194,
-106,
-165,
-44,
-203,
-234,
-28,
-56,
-142,
-163,
-36,
-33,
-74,
-150,
-101,
-91,
-213,
-180,
-93,
-236,
-65,
-174,
-195,
-112,
-241,
-126,
-253,
-247,
-114,
-99,
-76,
-218,
-198,
-140,
-2,
-70,
-83,
-0,
-12,
-235,
-216,
-44,
-198,
-81,
-91,
-101,
-108,
-63,
-69,
-155,
-229,
-236,
-132,
-17,
-26,
-99,
-245,
-11,
-221,
-20,
-139,
-155,
-125,
-198,
-128,
-0,
-96,
-100,
-18,
-133,
-97,
-186,
-249,
-134,
-160,
-141,
-208,
-104,
-211,
-198,
-24,
-19,
-246,
-178,
-59,
-14,
-136,
-94,
-117,
-0,
-125,
-46,
-185,
-19,
-22,
-51,
-0,
-203,
-3,
-47,
-3,
-254,
-165,
-10,
-133,
-191,
-53,
-104,
-27,
-172,
-212,
-25,
-150,
-210,
-172,
-111,
-69,
-214,
-88,
-71,
-27,
-165,
-24,
-45,
-237,
-12,
-198,
-2,
-144,
-0,
-26,
-199,
-106,
-191,
-79,
-243,
-212,
-15,
-96,
-52,
-250,
-233,
-244,
-103,
-105,
-228,
-68,
-224,
-78,
-26,
-4,
-240,
-232,
-179,
-67,
-22,
-55,
-2,
-95,
-1,
-130,
-131,
-106,
-36,
-1,
-48,
-254,
-209,
-70,
-96,
-140,
-21,
-0,
-239,
-69,
-162,
-83,
-221,
-133,
-68,
-225,
-169,
-18,
-0,
-87,
-17,
-51,
-115,
-78,
-75,
-0,
-27,
-58,
-125,
-26,
-181,
-227,
-101,
-215,
-14,
-224,
-127,
-70,
-246,
-202,
-235,
-25,
-99,
-94,
-104,
-196,
-60,
-55,
-97,
-130,
-160,
-15,
-59,
-3,
-224,
-37,
-200,
-209,
-151,
-215,
-156,
-151,
-6,
-97,
-200,
-107,
-176,
-185,
-49,
-230,
-95,
-198,
-152,
-16,
-107,
-187,
-247,
-103,
-89,
-182,
-149,
-79,
-199,
-226,
-147,
-124,
-109,
-251,
-76,
-189,
-11,
-243,
-221,
-198,
-152,
-43,
-141,
-49,
-119,
-26,
-99,
-46,
-15,
-232,
-119,
-255,
-0,
-86,
-68,
-242,
-145,
-1,
-252,
-179,
-65,
-187,
-224,
-175,
-109,
-197,
-87,
-166,
-234,
-161,
-7,
-243,
-239,
-210,
-70,
-219,
-5,
-199,
-210,
-71,
-76,
-152,
-255,
-3,
-236,
-209,
-228,
-26,
-19,
-5,
-192,
-31,
-144,
-184,
-118,
-231,
-251,
-132,
-0,
-13,
-194,
-144,
-55,
-184,
-38,
-84,
-175,
-0,
-74,
-207,
-202,
-201,
-227,
-56,
-218,
-73,
-238,
-27,
-139,
-65,
-125,
-166,
-38,
-57,
-233,
-152,
-5,
-176,
-142,
-243,
-176,
-86,
-10,
-108,
-19,
-60,
-217,
-28,
-218,
-54,
-65,
-52,
-135,
-33,
-0,
-130,
-99,
-233,
-147,
-39,
-79,
-1,
-248,
-98,
-13,
-223,
-37,
-144,
-40,
-67,
-143,
-35,
-65,
-83,
-14,
-68,
-98,
-204,
-21,
-233,
-62,
-15,
-92,
-134,
-132,
-230,
-126,
-20,
-248,
-59,
-240,
-188,
-38,
-247,
-48,
-86,
-128,
-100,
-198,
-61,
-205,
-190,
-239,
-18,
-154,
-160,
-48,
-228,
-13,
-174,
-9,
-45,
-5,
-128,
-67,
-91,
-23,
-146,
-174,
-178,
-207,
-4,
-250,
-184,
-116,
-5,
-18,
-54,
-124,
-54,
-240,
-75,
-79,
-221,
-47,
-144,
-237,
-208,
-79,
-219,
-48,
-182,
-216,
-176,
-33,
-125,
-223,
-58,
-128,
-94,
-133,
-134,
-182,
-107,
-20,
-75,
-31,
-201,
-42,
-3,
-240,
-64,
-13,
-223,
-47,
-34,
-81,
-139,
-191,
-160,
-255,
-230,
-227,
-137,
-62,
-139,
-164,
-146,
-62,
-20,
-120,
-63,
-176,
-59,
-146,
-120,
-226,
-162,
-10,
-190,
-149,
-202,
-36,
-74,
-80,
-255,
-36,
-226,
-1,
-73,
-45,
-87,
-26,
-98,
-142,
-128,
-48,
-228,
-13,
-174,
-5,
-61,
-11,
-128,
-186,
-62,
-19,
-144,
-156,
-180,
-105,
-159,
-74,
-218,
-219,
-240,
-125,
-3,
-238,
-235,
-78,
-221,
-147,
-109,
-24,
-55,
-234,
-88,
-147,
-201,
-214,
-132,
-214,
-211,
-166,
-20,
-49,
-174,
-211,
-6,
-192,
-243,
-235,
-6,
-139,
-210,
-93,
-11,
-252,
-213,
-249,
-253,
-87,
-60,
-166,
-197,
-158,
-118,
-135,
-81,
-145,
-177,
-150,
-26,
-101,
-18,
-178,
-162,
-25,
-248,
-231,
-161,
-179,
-193,
-80,
-127,
-94,
-211,
-159,
-208,
-231,
-191,
-51,
-178,
-2,
-56,
-64,
-175,
-57,
-20,
-43,
-74,
-237,
-78,
-239,
-2,
-32,
-6,
-154,
-244,
-169,
-164,
-253,
-145,
-200,
-10,
-224,
-23,
-158,
-58,
-187,
-58,
-56,
-178,
-247,
-142,
-53,
-153,
-108,
-195,
-154,
-152,
-195,
-66,
-232,
-96,
-65,
-210,
-79,
-29,
-230,
-252,
-62,
-12,
-24,
-176,
-179,
-64,
-146,
-178,
-254,
-12,
-177,
-29,
-159,
-129,
-198,
-134,
-175,
-224,
-107,
-87,
-0,
-141,
-226,
-193,
-123,
-248,
-172,
-6,
-220,
-167,
-183,
-242,
-158,
-10,
-186,
-80,
-129,
-50,
-3,
-89,
-229,
-76,
-209,
-251,
-25,
-138,
-82,
-121,
-34,
-9,
-128,
-24,
-24,
-11,
-1,
-65,
-38,
-10,
-22,
-153,
-145,
-150,
-112,
-101,
-158,
-152,
-191,
-49,
-18,
-19,
-254,
-48,
-99,
-204,
-100,
-99,
-204,
-206,
-250,
-207,
-11,
-53,
-93,
-30,
-136,
-162,
-212,
-20,
-89,
-150,
-61,
-134,
-164,
-150,
-250,
-147,
-49,
-230,
-112,
-224,
-239,
-89,
-150,
-13,
-88,
-41,
-102,
-89,
-22,
-116,
-60,
-156,
-101,
-217,
-10,
-93,
-251,
-52,
-150,
-225,
-8,
-135,
-141,
-139,
-113,
-17,
-171,
-234,
-198,
-26,
-202,
-6,
-161,
-117,
-2,
-170,
-76,
-13,
-150,
-208,
-8,
-183,
-24,
-99,
-54,
-113,
-126,
-63,
-207,
-228,
-190,
-226,
-46,
-182,
-54,
-198,
-28,
-159,
-101,
-217,
-215,
-178,
-44,
-251,
-189,
-49,
-102,
-152,
-97,
-161,
-207,
-48,
-198,
-220,
-100,
-140,
-89,
-219,
-24,
-19,
-39,
-207,
-92,
-194,
-168,
-0,
-248,
-152,
-174,
-46,
-94,
-92,
-69,
-87,
-38,
-0,
-172,
-212,
-122,
-83,
-192,
-133,
-92,
-30,
-115,
-3,
-251,
-183,
-56,
-225,
-169,
-136,
-73,
-192,
-186,
-21,
-116,
-71,
-27,
-99,
-182,
-3,
-246,
-3,
-246,
-51,
-198,
-108,
-103,
-114,
-95,
-113,
-23,
-119,
-24,
-99,
-182,
-69,
-148,
-128,
-223,
-51,
-198,
-188,
-173,
-174,
-3,
-177,
-150,
-146,
-234,
-185,
-102,
-253,
-233,
-247,
-41,
-188,
-219,
-113,
-1,
-181,
-91,
-40,
-221,
-194,
-76,
-32,
-172,
-84,
-248,
-27,
-14,
-196,
-178,
-202,
-226,
-250,
-26,
-218,
-245,
-148,
-110,
-33,
-1,
-199,
-134,
-14,
-223,
-96,
-141,
-126,
-0,
-207,
-159,
-43,
-207,
-63,
-4,
-208,
-238,
-66,
-158,
-179,
-109,
-149,
-166,
-215,
-42,
-225,
-121,
-182,
-242,
-59,
-23,
-209,
-14,
-15,
-152,
-206,
-34,
-126,
-225,
-223,
-36,
-63,
-6,
-252,
-14,
-254,
-99,
-192,
-215,
-144,
-251,
-142,
-159,
-13,
-236,
-90,
-183,
-23,
-141,
-185,
-151,
-68,
-108,
-65,
-108,
-142,
-197,
-215,
-117,
-229,
-55,
-86,
-208,
-228,
-25,
-17,
-118,
-10,
-80,
-202,
-47,
-244,
-90,
-49,
-223,
-155,
-135,
-247,
-55,
-149,
-119,
-80,
-218,
-115,
-31,
-131,
-119,
-2,
-23,
-227,
-81,
-84,
-57,
-52,
-75,
-3,
-39,
-233,
-133,
-74,
-143,
-170,
-10,
-109,
-106,
-209,
-176,
-159,
-59,
-107,
-179,
-251,
-129,
-213,
-43,
-232,
-50,
-68,
-35,
-237,
-34,
-150,
-0,
-120,
-58,
-98,
-62,
-125,
-99,
-155,
-123,
-136,
-112,
-253,
-168,
-3,
-9,
-248,
-183,
-242,
-59,
-48,
-6,
-191,
-177,
-128,
-38,
-207,
-136,
-197,
-67,
-0,
-28,
-162,
-188,
-223,
-87,
-69,
-87,
-170,
-4,
-204,
-178,
-236,
-12,
-51,
-232,
-191,
-109,
-153,
-223,
-103,
-140,
-185,
-215,
-136,
-217,
-240,
-218,
-70,
-162,
-233,
-238,
-23,
-210,
-177,
-152,
-238,
-148,
-72,
-250,
-114,
-155,
-193,
-232,
-179,
-89,
-150,
-61,
-90,
-66,
-183,
-188,
-145,
-96,
-30,
-239,
-50,
-18,
-247,
-111,
-99,
-211,
-102,
-105,
-84,
-142,
-21,
-140,
-49,
-47,
-50,
-242,
-60,
-102,
-26,
-89,
-198,
-143,
-103,
-156,
-103,
-140,
-121,
-181,
-49,
-166,
-242,
-28,
-59,
-97,
-76,
-35,
-104,
-11,
-208,
-118,
-143,
-55,
-199,
-136,
-221,
-245,
-211,
-140,
-49,
-103,
-25,
-99,
-94,
-155,
-249,
-51,
-152,
-246,
-141,
-221,
-141,
-49,
-207,
-52,
-198,
-220,
-108,
-140,
-249,
-99,
-5,
-221,
-95,
-140,
-76,
-254,
-11,
-141,
-236,
-189,
-99,
-251,
-116,
-159,
-98,
-140,
-249,
-128,
-17,
-13,
-250,
-218,
-89,
-150,
-85,
-42,
-94,
-198,
-1,
-172,
-0,
-171,
-210,
-105,
-36,
-140,
-50,
-144,
-179,
-126,
-128,
-123,
-60,
-213,
-43,
-234,
-223,
-74,
-1,
-208,
-234,
-24,
-48,
-203,
-178,
-32,
-11,
-193,
-62,
-129,
-36,
-77,
-180,
-230,
-183,
-135,
-168,
-2,
-171,
-12,
-63,
-54,
-198,
-220,
-99,
-140,
-249,
-120,
-150,
-101,
-243,
-104,
-224,
-233,
-24,
-208,
-143,
-149,
-141,
-49,
-175,
-215,
-159,
-95,
-201,
-178,
-172,
-77,
-82,
-145,
-177,
-134,
-135,
-244,
-239,
-26,
-163,
-218,
-139,
-132,
-58,
-188,
-74,
-255,
-254,
-213,
-83,
-103,
-39,
-254,
-138,
-158,
-186,
-167,
-48,
-158,
-237,
-0,
-94,
-105,
-140,
-217,
-192,
-200,
-145,
-165,
-215,
-76,
-215,
-34,
-203,
-178,
-179,
-140,
-172,
-84,
-44,
-150,
-46,
-163,
-109,
-129,
-167,
-38,
-73,
-150,
-101,
-247,
-70,
-228,
-59,
-154,
-120,
-68,
-255,
-174,
-54,
-170,
-189,
-72,
-40,
-5,
-176,
-170,
-17,
-175,
-93,
-99,
-140,
-249,
-181,
-135,
-164,
-217,
-22,
-0,
-152,
-171,
-203,
-137,
-168,
-174,
-137,
-52,
-243,
-174,
-219,
-20,
-201,
-208,
-123,
-175,
-246,
-103,
-10,
-146,
-173,
-216,
-103,
-225,
-182,
-173,
-254,
-189,
-34,
-32,
-94,
-95,
-159,
-88,
-172,
-66,
-68,
-41,
-150,
-209,
-191,
-211,
-70,
-181,
-23,
-9,
-85,
-216,
-198,
-200,
-216,
-187,
-186,
-100,
-251,
-221,
-120,
-11,
-48,
-221,
-24,
-179,
-186,
-137,
-255,
-210,
-223,
-102,
-140,
-89,
-214,
-136,
-146,
-236,
-82,
-35,
-82,
-235,
-185,
-70,
-246,
-238,
-69,
-28,
-98,
-196,
-16,
-230,
-116,
-35,
-6,
-41,
-27,
-26,
-73,
-12,
-185,
-145,
-49,
-230,
-141,
-5,
-218,
-109,
-244,
-239,
-121,
-145,
-251,
-155,
-144,
-191,
-155,
-135,
-71,
-181,
-23,
-139,
-57,
-58,
-42,
-196,
-223,
-160,
-127,
-15,
-45,
-169,
-111,
-188,
-5,
-152,
-102,
-74,
-4,
-0,
-226,
-110,
-248,
-97,
-99,
-204,
-113,
-89,
-150,
-237,
-19,
-90,
-167,
-56,
-203,
-72,
-236,
-187,
-201,
-250,
-123,
-178,
-145,
-32,
-8,
-87,
-122,
-104,
-63,
-100,
-228,
-185,
-60,
-117,
-244,
-8,
-60,
-215,
-248,
-77,
-93,
-173,
-143,
-245,
-120,
-215,
-184,
-143,
-69,
-88,
-247,
-227,
-74,
-15,
-199,
-113,
-138,
-147,
-81,
-223,
-133,
-113,
-30,
-120,
-117,
-71,
-35,
-6,
-123,
-167,
-150,
-212,
-55,
-51,
-4,
-2,
-174,
-211,
-45,
-192,
-241,
-158,
-186,
-16,
-183,
-195,
-168,
-202,
-47,
-224,
-105,
-192,
-235,
-17,
-191,
-235,
-223,
-122,
-234,
-109,
-178,
-142,
-183,
-182,
-224,
-109,
-209,
-217,
-14,
-0,
-216,
-76,
-121,
-205,
-235,
-202,
-171,
-67,
-31,
-162,
-158,
-39,
-3,
-103,
-41,
-191,
-178,
-175,
-203,
-184,
-3,
-30,
-84,
-208,
-14,
-197,
-14,
-160,
-79,
-56,
-91,
-250,
-202,
-36,
-36,
-197,
-45,
-128,
-49,
-254,
-45,
-192,
-137,
-70,
-190,
-242,
-191,
-241,
-212,
-157,
-96,
-140,
-249,
-168,
-254,
-141,
-130,
-194,
-131,
-63,
-215,
-24,
-227,
-139,
-184,
-99,
-39,
-175,
-247,
-236,
-127,
-136,
-216,
-65,
-255,
-250,
-236,
-250,
-199,
-29,
-144,
-19,
-146,
-109,
-245,
-231,
-57,
-163,
-216,
-149,
-168,
-8,
-89,
-110,
-147,
-91,
-161,
-214,
-158,
-18,
-85,
-241,
-27,
-11,
-161,
-195,
-179,
-44,
-91,
-182,
-158,
-202,
-1,
-226,
-159,
-14,
-61,
-89,
-127,
-53,
-145,
-138,
-192,
-14,
-136,
-133,
-223,
-17,
-218,
-230,
-32,
-15,
-205,
-227,
-90,
-183,
-181,
-143,
-71,
-96,
-95,
-58,
-173,
-0,
-16,
-147,
-93,
-139,
-82,
-143,
-189,
-190,
-17,
-243,
-139,
-131,
-248,
-32,
-128,
-132,
-189,
-90,
-166,
-190,
-197,
-226,
-131,
-38,
-171,
-132,
-197,
-14,
-72,
-8,
-104,
-144,
-204,
-192,
-125,
-240,
-111,
-53,
-72,
-129,
-11,
-241,
-68,
-147,
-1,
-110,
-85,
-126,
-141,
-179,
-174,
-70,
-20,
-0,
-143,
-33,
-230,
-210,
-239,
-236,
-194,
-167,
-43,
-34,
-11,
-128,
-75,
-149,
-215,
-119,
-99,
-244,
-45,
-97,
-108,
-35,
-116,
-11,
-48,
-20,
-0,
-171,
-100,
-89,
-246,
-132,
-243,
-123,
-73,
-99,
-204,
-51,
-140,
-63,
-71,
-225,
-253,
-70,
-78,
-7,
-188,
-17,
-103,
-135,
-129,
-44,
-203,
-22,
-171,
-115,
-114,
-196,
-113,
-228,
-53,
-70,
-18,
-194,
-44,
-54,
-251,
-255,
-132,
-114,
-184,
-166,
-192,
-211,
-10,
-127,
-71,
-3,
-83,
-129,
-51,
-144,
-212,
-220,
-95,
-55,
-198,
-92,
-96,
-100,
-130,
-255,
-202,
-67,
-107,
-247,
-107,
-111,
-240,
-212,
-77,
-24,
-48,
-210,
-243,
-176,
-52,
-238,
-94,
-0,
-159,
-149,
-141,
-49,
-71,
-233,
-207,
-207,
-186,
-130,
-56,
-97,
-2,
-128,
-220,
-125,
-176,
-151,
-36,
-5,
-33,
-203,
-84,
-224,
-32,
-196,
-163,
-110,
-38,
-18,
-106,
-106,
-50,
-18,
-76,
-115,
-32,
-40,
-6,
-240,
-70,
-229,
-55,
-151,
-134,
-153,
-107,
-98,
-109,
-1,
-198,
-2,
-128,
-183,
-235,
-189,
-60,
-94,
-79,
-93,
-201,
-199,
-134,
-131,
-111,
-30,
-67,
-46,
-97,
-252,
-3,
-216,
-87,
-7,
-192,
-182,
-61,
-241,
-143,
-182,
-79,
-85,
-126,
-203,
-34,
-145,
-87,
-1,
-118,
-107,
-217,
-151,
-113,
-43,
-0,
-128,
-187,
-145,
-248,
-245,
-243,
-244,
-94,
-14,
-24,
-237,
-62,
-37,
-140,
-99,
-144,
-135,
-16,
-10,
-201,
-174,
-210,
-134,
-127,
-84,
-1,
-160,
-60,
-247,
-87,
-158,
-147,
-98,
-241,
-28,
-47,
-64,
-148,
-160,
-243,
-144,
-64,
-158,
-95,
-247,
-173,
-146,
-18,
-18,
-198,
-12,
-122,
-18,
-0,
-43,
-34,
-201,
-51,
-0,
-106,
-67,
-103,
-37,
-36,
-36,
-140,
-18,
-250,
-16,
-0,
-202,
-247,
-67,
-202,
-247,
-238,
-241,
-188,
-164,
-79,
-72,
-24,
-85,
-32,
-94,
-119,
-179,
-129,
-195,
-235,
-169,
-91,
-241,
-15,
-22,
-0,
-84,
-164,
-60,
-42,
-161,
-63,
-82,
-121,
-255,
-174,
-123,
-79,
-19,
-18,
-38,
-32,
-200,
-109,
-250,
-123,
-57,
-254,
-105,
-40,
-0,
-122,
-241,
-47,
-72,
-72,
-72,
-24,
-9,
-215,
-14,
-224,
-68,
-35,
-161,
-190,
-134,
-146,
-194,
-169,
-6,
-39,
-24,
-233,
-75,
-52,
-255,
-130,
-132,
-132,
-132,
-81,
-68,
-95,
-58,
-128,
-132,
-132,
-132,
-132,
-132,
-132,
-132,
-137,
-0,
-93,
-69,
-148,
-165,
-3,
-111,
-156,
-84,
-36,
-33,
-97,
-34,
-99,
-220,
-165,
-126,
-74,
-72,
-72,
-136,
-135,
-36,
-0,
-18,
-18,
-38,
-48,
-122,
-21,
-0,
-85,
-138,
-63,
-231,
-168,
-111,
-251,
-62,
-251,
-144,
-144,
-144,
-80,
-142,
-209,
-92,
-1,
-60,
-92,
-248,
-155,
-144,
-144,
-48,
-100,
-140,
-5,
-1,
-240,
-72,
-177,
-194,
-177,
-74,
-60,
-98,
-200,
-125,
-74,
-72,
-152,
-80,
-24,
-77,
-1,
-96,
-39,
-190,
-111,
-5,
-176,
-155,
-145,
-192,
-140,
-31,
-30,
-94,
-119,
-18,
-18,
-38,
-30,
-70,
-123,
-5,
-48,
-61,
-203,
-178,
-185,
-158,
-58,
-107,
-149,
-232,
-139,
-66,
-156,
-144,
-144,
-16,
-9,
-163,
-153,
-27,
-240,
-97,
-227,
-89,
-254,
-27,
-99,
-76,
-150,
-101,
-123,
-27,
-99,
-246,
-30,
-110,
-119,
-18,
-18,
-18,
-162,
-98,
-152,
-230,
-191,
-201,
-16,
-40,
-33,
-161,
-57,
-146,
-29,
-64,
-66,
-194,
-4,
-70,
-18,
-0,
-9,
-9,
-19,
-24,
-73,
-0,
-36,
-36,
-76,
-96,
-36,
-1,
-144,
-144,
-48,
-129,
-145,
-4,
-64,
-66,
-194,
-4,
-198,
-184,
-19,
-0,
-73,
-219,
-159,
-144,
-16,
-15,
-227,
-78,
-0,
-36,
-36,
-36,
-196,
-67,
-18,
-0,
-9,
-9,
-19,
-24,
-73,
-0,
-36,
-36,
-76,
-96,
-36,
-1,
-144,
-144,
-48,
-117,
-14,
-169,
-49,
-0,
-0,
-2,
-74,
-73,
-68,
-65,
-84,
-129,
-145,
-4,
-64,
-66,
-194,
-4,
-70,
-175,
-206,
-64,
-89,
-150,
-101,
-125,
-242,
-79,
-72,
-72,
-232,
-134,
-180,
-2,
-72,
-72,
-152,
-192,
-72,
-2,
-32,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-33,
-225,
-255,
-219,
-131,
-3,
-2,
-0,
-0,
-0,
-0,
-33,
-253,
-95,
-221,
-17,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-0,
-208,
-17,
-112,
-180,
-144,
-16,
-164,
-2,
-78,
-0,
-0,
-0,
-0,
-73,
-69,
-78,
-68,
-174,
-66,
-96,
-130,
-};
-/* clang-format on */
diff --git a/scene/resources/default_theme/font_lodpi.inc b/scene/resources/default_theme/font_lodpi.inc
deleted file mode 100644
index d2f5851224..0000000000
--- a/scene/resources/default_theme/font_lodpi.inc
+++ /dev/null
@@ -1,13117 +0,0 @@
-/* clang-format off */
-static const int _lodpi_font_height=14;
-static const int _lodpi_font_ascent=11;
-static const int _lodpi_font_charcount=191;
-static const int _lodpi_font_charrects[191][8]={
-/* charidx , ofs_x, ofs_y, size_x, size_y, valign, halign, advance */
-{64,72,34,10,11,1,1,12},
-{224,85,180,5,11,0,1,7},
-{192,32,16,11,13,-2,-1,9},
-{96,2,216,3,2,0,3,8},
-{160,0,0,0,0,11,0,4},
-{32,0,0,0,0,11,0,4},
-{33,65,234,2,10,1,1,4},
-{225,112,169,5,11,0,1,7},
-{193,17,16,11,13,-2,-1,9},
-{161,2,222,2,11,3,1,4},
-{65,2,16,11,10,1,-1,9},
-{97,76,188,5,8,3,1,7},
-{98,102,165,6,11,0,1,8},
-{226,72,143,6,11,0,1,7},
-{194,113,2,11,13,-2,-1,9},
-{66,46,109,7,10,1,1,9},
-{162,12,136,6,10,1,1,8},
-{34,49,187,5,4,1,1,6},
-{35,78,66,8,10,1,0,9},
-{163,22,167,6,10,1,1,8},
-{195,53,2,11,14,-3,-1,9},
-{227,2,155,6,12,-1,1,7},
-{67,68,115,7,10,1,1,8},
-{99,40,179,5,8,3,1,7},
-{228,121,169,5,11,0,1,7},
-{196,98,2,11,13,-2,-1,9},
-{36,102,137,6,12,0,1,8},
-{100,82,150,6,11,0,1,8},
-{68,90,66,8,10,1,1,10},
-{164,14,79,8,7,3,0,8},
-{37,2,30,10,10,1,1,12},
-{69,29,191,5,10,1,1,7},
-{165,79,98,7,10,1,0,8},
-{229,20,196,5,12,-1,1,7},
-{197,83,2,11,12,-1,-1,9},
-{101,32,124,6,8,3,1,8},
-{38,67,49,9,10,1,1,10},
-{70,101,105,6,10,1,1,7},
-{198,21,2,12,10,1,-1,12},
-{166,95,228,2,14,0,3,7},
-{102,2,201,5,11,0,0,4},
-{230,58,34,10,8,3,1,12},
-{71,66,65,8,10,1,1,10},
-{231,2,186,5,11,3,1,7},
-{199,57,97,7,13,1,1,8},
-{103,13,107,7,11,3,1,7},
-{167,112,131,6,11,0,0,7},
-{39,119,219,2,4,1,1,3},
-{72,54,65,8,10,1,1,10},
-{232,62,143,6,11,0,1,8},
-{200,47,195,5,13,-2,1,7},
-{40,93,212,4,12,1,1,4},
-{104,72,158,6,11,0,1,8},
-{168,77,217,4,2,0,2,8},
-{73,38,191,5,10,1,0,5},
-{169,44,34,10,10,1,1,12},
-{233,52,142,6,11,0,1,8},
-{201,56,197,5,13,-2,1,7},
-{41,51,226,3,12,1,0,4},
-{105,109,213,3,11,0,0,4},
-{106,101,213,4,14,0,-1,4},
-{74,92,195,5,13,1,-2,3},
-{202,65,202,5,13,-2,1,7},
-{42,108,80,7,6,0,0,8},
-{170,29,205,4,5,1,0,5},
-{234,12,181,6,11,0,1,8},
-{171,22,181,5,6,4,1,7},
-{43,101,94,7,7,3,0,8},
-{107,112,92,7,11,0,1,7},
-{203,83,200,5,13,-2,1,7},
-{235,2,171,6,11,0,1,8},
-{75,102,66,8,10,1,1,8},
-{44,107,231,2,3,9,1,4},
-{172,2,104,7,4,6,0,8},
-{108,113,228,2,11,0,1,4},
-{204,101,196,5,13,-2,0,5},
-{236,30,214,3,11,0,0,4},
-{76,22,124,6,10,1,1,7},
-{173,16,229,3,2,7,1,5},
-{45,123,201,3,2,7,1,5},
-{109,68,2,11,8,3,1,13},
-{205,11,211,5,13,-2,0,5},
-{237,37,214,3,11,0,1,4},
-{77,62,20,10,10,1,1,12},
-{46,101,231,2,2,9,1,4},
-{110,111,107,6,8,3,1,8},
-{206,20,212,5,13,-2,0,5},
-{238,11,196,5,11,0,-1,4},
-{174,30,33,10,10,1,1,12},
-{78,2,79,8,10,1,1,10},
-{175,35,111,7,1,-1,0,7},
-{111,102,153,6,8,3,1,8},
-{207,119,184,5,13,-2,0,5},
-{239,69,219,4,11,0,0,4},
-{79,41,66,9,10,1,1,11},
-{47,90,105,7,10,1,-1,5},
-{176,61,219,4,4,1,1,6},
-{112,32,150,6,11,3,1,8},
-{240,82,165,6,11,0,1,8},
-{208,86,33,9,10,1,0,10},
-{80,52,128,6,10,1,1,8},
-{48,42,135,6,10,1,1,8},
-{177,46,97,7,8,3,0,8},
-{113,22,152,6,11,3,1,8},
-{241,2,112,6,12,-1,1,8},
-{81,15,59,9,13,1,1,11},
-{209,74,80,8,14,-3,1,10},
-{49,45,212,4,10,1,2,8},
-{178,58,187,5,6,1,0,5},
-{114,85,217,4,8,3,1,5},
-{210,2,62,9,13,-2,1,11},
-{242,62,165,6,11,0,1,8},
-{82,35,97,7,10,1,1,8},
-{50,57,114,7,10,1,1,8},
-{179,53,214,4,6,1,0,5},
-{115,112,146,6,8,3,0,7},
-{211,106,49,9,13,-2,1,11},
-{243,52,172,6,11,0,1,8},
-{83,24,96,7,10,1,0,7},
-{51,22,138,6,10,1,1,8},
-{180,9,228,3,2,0,3,8},
-{116,67,188,5,10,1,0,5},
-{212,93,49,9,13,-2,1,11},
-{244,42,164,6,11,0,1,8},
-{84,13,93,7,10,1,0,7},
-{52,24,110,7,10,1,1,8},
-{53,92,119,6,10,1,1,8},
-{85,114,66,8,10,1,1,10},
-{213,2,44,9,14,-3,1,11},
-{117,42,123,6,8,3,1,8},
-{181,2,140,6,11,3,1,8},
-{245,12,165,6,12,-1,1,8},
-{54,82,121,6,10,1,1,8},
-{86,76,18,10,10,1,-1,8},
-{246,72,173,6,11,0,1,8},
-{214,80,49,9,13,-2,1,11},
-{182,68,98,7,13,0,1,9},
-{118,15,47,9,8,3,-1,7},
-{55,72,129,6,10,1,1,8},
-{87,2,2,15,10,1,-1,13},
-{119,37,2,12,8,3,-1,10},
-{247,90,94,7,7,3,0,8},
-{215,2,93,7,7,3,0,8},
-{183,77,223,2,2,5,1,4},
-{56,62,129,6,10,1,1,8},
-{88,90,19,10,10,1,-1,8},
-{216,99,33,9,12,0,1,11},
-{248,2,128,6,8,3,1,8},
-{120,119,80,7,8,3,0,7},
-{184,116,212,3,3,11,0,3},
-{89,28,65,9,10,1,-1,7},
-{217,38,80,8,13,-2,1,10},
-{249,52,157,6,11,0,1,8},
-{121,112,33,9,11,3,-1,7},
-{57,12,122,6,10,1,1,8},
-{185,23,229,3,6,1,0,5},
-{218,26,79,8,13,-2,1,10},
-{250,42,149,6,11,0,1,8},
-{90,32,136,6,10,1,1,8},
-{122,112,119,6,8,3,1,7},
-{58,89,229,2,8,3,1,4},
-{186,37,205,4,5,1,0,5},
-{219,50,80,8,13,-2,1,10},
-{91,58,227,3,12,1,1,4},
-{123,103,180,5,12,1,0,5},
-{251,12,150,6,11,0,1,8},
-{59,71,234,2,9,3,1,4},
-{187,31,181,5,6,4,1,7},
-{188,16,33,10,10,1,0,10},
-{124,83,229,2,14,0,3,7},
-{220,62,79,8,13,-2,1,10},
-{252,92,133,6,11,0,1,8},
-{92,97,80,7,10,1,-1,5},
-{60,92,153,6,7,3,1,8},
-{189,47,20,11,10,1,0,10},
-{253,28,47,9,14,0,-1,7},
-{221,54,48,9,13,-2,-1,7},
-{93,44,226,3,12,1,0,4},
-{125,110,196,5,12,1,0,5},
-{61,79,112,7,5,4,0,8},
-{190,104,19,10,10,1,0,10},
-{222,32,165,6,10,1,1,8},
-{254,102,119,6,14,0,1,8},
-{62,112,158,6,7,3,1,8},
-{94,86,80,7,6,1,0,7},
-{126,62,158,6,3,5,1,8},
-{223,82,135,6,11,0,1,8},
-{255,41,48,9,14,0,-1,7},
-{191,94,180,5,11,3,0,6},
-{63,74,202,5,10,1,0,6},
-{95,92,148,6,1,12,0,6},
-};
-static const int _lodpi_font_kerning_pair_count=0;
-static const int _lodpi_font_kerning_pairs[1][3]={
-{0,0,0},
-};
-static const int _lodpi_font_img_width=128;
-static const int _lodpi_font_img_height=256;
-static const int _lodpi_font_img_data_size=12909;
-static const unsigned char _lodpi_font_img_data[12909]={
-137,
-80,
-78,
-71,
-13,
-10,
-26,
-10,
-0,
-0,
-0,
-13,
-73,
-72,
-68,
-82,
-0,
-0,
-0,
-128,
-0,
-0,
-1,
-0,
-8,
-6,
-0,
-0,
-0,
-123,
-249,
-126,
-167,
-0,
-0,
-32,
-0,
-73,
-68,
-65,
-84,
-120,
-156,
-237,
-157,
-119,
-184,
-30,
-85,
-181,
-255,
-191,
-59,
-128,
-8,
-210,
-155,
-82,
-77,
-232,
-221,
-2,
-210,
-164,
-132,
-26,
-154,
-5,
-164,
-131,
-63,
-224,
-98,
-65,
-4,
-68,
-46,
-8,
-42,
-23,
-84,
-80,
-41,
-94,
-16,
-21,
-17,
-197,
-10,
-22,
-80,
-17,
-21,
-4,
-5,
-65,
-16,
-41,
-42,
-185,
-116,
-19,
-106,
-128,
-80,
-46,
-32,
-33,
-148,
-208,
-18,
-62,
-191,
-63,
-214,
-122,
-115,
-230,
-204,
-217,
-51,
-179,
-103,
-222,
-121,
-223,
-115,
-146,
-123,
-190,
-207,
-115,
-158,
-51,
-101,
-237,
-50,
-243,
-174,
-217,
-123,
-237,
-213,
-182,
-52,
-138,
-81,
-140,
-98,
-20,
-2,
-150,
-3,
-222,
-0,
-54,
-207,
-93,
-255,
-32,
-134,
-247,
-231,
-174,
-111,
-237,
-244,
-203,
-38,
-212,
-61,
-31,
-48,
-149,
-2,
-68,
-232,
-87,
-242,
-91,
-107,
-102,
-174,
-253,
-28,
-184,
-58,
-115,
-190,
-178,
-211,
-172,
-88,
-243,
-57,
-199,
-84,
-220,
-7,
-216,
-17,
-184,
-21,
-120,
-21,
-184,
-23,
-216,
-9,
-56,
-192,
-143,
-103,
-0,
-55,
-1,
-235,
-36,
-180,
-245,
-117,
-224,
-122,
-224,
-244,
-58,
-125,
-244,
-178,
-247,
-0,
-239,
-4,
-222,
-13,
-220,
-85,
-179,
-236,
-55,
-253,
-57,
-190,
-89,
-69,
-59,
-251,
-101,
-132,
-16,
-30,
-151,
-116,
-171,
-164,
-157,
-114,
-52,
-59,
-74,
-186,
-94,
-210,
-118,
-185,
-235,
-59,
-73,
-250,
-123,
-8,
-225,
-137,
-132,
-62,
-237,
-39,
-233,
-113,
-73,
-11,
-248,
-249,
-206,
-126,
-188,
-64,
-230,
-218,
-108,
-132,
-16,
-30,
-145,
-116,
-175,
-164,
-205,
-252,
-129,
-230,
-149,
-180,
-161,
-164,
-21,
-129,
-133,
-156,
-108,
-115,
-73,
-147,
-67,
-8,
-143,
-150,
-53,
-12,
-28,
-9,
-76,
-3,
-206,
-4,
-198,
-74,
-186,
-49,
-161,
-191,
-103,
-75,
-58,
-76,
-210,
-242,
-178,
-103,
-191,
-88,
-210,
-17,
-146,
-118,
-151,
-52,
-78,
-210,
-51,
-146,
-190,
-157,
-80,
-207,
-102,
-33,
-132,
-45,
-37,
-109,
-157,
-64,
-155,
-199,
-204,
-204,
-241,
-172,
-212,
-66,
-192,
-119,
-37,
-45,
-41,
-105,
-13,
-73,
-75,
-251,
-121,
-114,
-225,
-19,
-128,
-137,
-185,
-107,
-15,
-1,
-59,
-3,
-255,
-202,
-93,
-191,
-11,
-248,
-108,
-98,
-189,
-119,
-2,
-251,
-250,
-49,
-64,
-158,
-153,
-98,
-101,
-206,
-1,
-206,
-247,
-227,
-109,
-128,
-75,
-129,
-31,
-117,
-70,
-34,
-224,
-188,
-20,
-14,
-7,
-110,
-241,
-209,
-226,
-76,
-224,
-57,
-224,
-136,
-10,
-122,
-128,
-79,
-100,
-206,
-215,
-205,
-247,
-217,
-71,
-136,
-23,
-18,
-218,
-190,
-223,
-203,
-222,
-93,
-69,
-59,
-34,
-0,
-172,
-159,
-29,
-214,
-129,
-53,
-128,
-71,
-252,
-120,
-42,
-176,
-188,
-31,
-175,
-232,
-15,
-182,
-118,
-66,
-157,
-59,
-1,
-143,
-250,
-87,
-92,
-135,
-1,
-62,
-216,
-121,
-113,
-192,
-89,
-192,
-97,
-192,
-65,
-192,
-185,
-126,
-237,
-110,
-114,
-211,
-82,
-65,
-61,
-165,
-67,
-126,
-132,
-30,
-96,
-219,
-204,
-249,
-88,
-191,
-54,
-54,
-115,
-109,
-115,
-24,
-58,
-117,
-69,
-234,
-186,
-12,
-248,
-53,
-240,
-251,
-58,
-125,
-240,
-178,
-59,
-121,
-187,
-249,
-17,
-185,
-167,
-101,
-59,
-95,
-252,
-193,
-126,
-124,
-100,
-230,
-43,
-252,
-17,
-112,
-144,
-31,
-127,
-28,
-184,
-47,
-177,
-190,
-107,
-128,
-207,
-100,
-206,
-135,
-160,
-160,
-220,
-162,
-192,
-107,
-254,
-255,
-62,
-76,
-46,
-88,
-14,
-120,
-16,
-88,
-204,
-239,
-45,
-146,
-216,
-135,
-228,
-23,
-226,
-116,
-155,
-103,
-206,
-59,
-12,
-176,
-66,
-230,
-90,
-37,
-3,
-0,
-227,
-128,
-151,
-252,
-99,
-121,
-41,
-203,
-64,
-137,
-125,
-238,
-134,
-121,
-26,
-151,
-21,
-112,
-54,
-112,
-177,
-31,
-255,
-1,
-216,
-211,
-143,
-247,
-7,
-46,
-244,
-227,
-75,
-129,
-175,
-37,
-212,
-245,
-110,
-224,
-5,
-96,
-177,
-204,
-53,
-252,
-7,
-121,
-115,
-231,
-175,
-164,
-252,
-77,
-192,
-129,
-192,
-29,
-153,
-107,
-119,
-0,
-7,
-3,
-55,
-212,
-120,
-166,
-228,
-23,
-210,
-34,
-3,
-156,
-14,
-252,
-218,
-143,
-47,
-1,
-78,
-171,
-209,
-223,
-198,
-204,
-211,
-45,
-227,
-9,
-216,
-22,
-19,
-154,
-22,
-0,
-158,
-7,
-22,
-247,
-235,
-111,
-5,
-30,
-199,
-36,
-250,
-231,
-201,
-173,
-22,
-10,
-234,
-250,
-121,
-236,
-139,
-39,
-97,
-10,
-240,
-242,
-39,
-3,
-55,
-0,
-95,
-201,
-92,
-59,
-195,
-25,
-227,
-164,
-196,
-58,
-106,
-189,
-144,
-54,
-24,
-192,
-25,
-251,
-25,
-96,
-15,
-63,
-223,
-195,
-207,
-11,
-153,
-61,
-87,
-190,
-27,
-230,
-105,
-92,
-182,
-83,
-193,
-188,
-206,
-0,
-31,
-7,
-110,
-206,
-221,
-187,
-29,
-27,
-9,
-158,
-162,
-122,
-57,
-53,
-22,
-27,
-166,
-215,
-206,
-126,
-237,
-53,
-25,
-96,
-75,
-167,
-223,
-44,
-115,
-109,
-187,
-252,
-181,
-138,
-58,
-106,
-189,
-144,
-150,
-24,
-224,
-64,
-255,
-72,
-22,
-240,
-243,
-55,
-3,
-211,
-129,
-3,
-19,
-250,
-219,
-152,
-121,
-186,
-101,
-188,
-108,
-69,
-63,
-195,
-164,
-231,
-47,
-230,
-174,
-127,
-205,
-191,
-190,
-31,
-36,
-212,
-113,
-54,
-240,
-219,
-200,
-117,
-72,
-156,
-2,
-186,
-69,
-107,
-47,
-164,
-126,
-187,
-127,
-39,
-142,
-91,
-18,
-202,
-118,
-195,
-60,
-141,
-203,
-230,
-43,
-218,
-219,
-59,
-252,
-222,
-220,
-245,
-9,
-126,
-253,
-3,
-21,
-229,
-23,
-7,
-94,
-4,
-198,
-71,
-238,
-13,
-65,
-173,
-206,
-213,
-64,
-107,
-47,
-164,
-94,
-155,
-239,
-1,
-102,
-97,
-43,
-168,
-236,
-200,
-183,
-154,
-95,
-223,
-176,
-162,
-124,
-55,
-204,
-211,
-184,
-236,
-92,
-137,
-225,
-120,
-33,
-216,
-106,
-233,
-55,
-5,
-247,
-46,
-5,
-126,
-88,
-82,
-182,
-49,
-243,
-116,
-203,
-120,
-115,
-29,
-134,
-227,
-133,
-0,
-75,
-2,
-47,
-3,
-91,
-21,
-220,
-223,
-214,
-239,
-47,
-89,
-112,
-191,
-27,
-230,
-105,
-92,
-118,
-174,
-196,
-156,
-246,
-66,
-186,
-97,
-158,
-110,
-25,
-111,
-174,
-195,
-232,
-11,
-105,
-1,
-116,
-163,
-78,
-180,
-242,
-75,
-1,
-255,
-11,
-252,
-180,
-102,
-185,
-159,
-123,
-185,
-165,
-154,
-180,
-59,
-138,
-150,
-64,
-55,
-234,
-68,
-43,
-127,
-5,
-166,
-195,
-175,
-171,
-139,
-159,
-7,
-51,
-163,
-254,
-161,
-73,
-187,
-163,
-104,
-1,
-116,
-171,
-78,
-156,
-139,
-1,
-44,
-3,
-188,
-14,
-108,
-19,
-185,
-183,
-131,
-223,
-91,
-102,
-56,
-250,
-214,
-4,
-69,
-95,
-231,
-39,
-36,
-93,
-233,
-182,
-246,
-63,
-250,
-121,
-50,
-186,
-153,
-62,
-186,
-157,
-122,
-122,
-141,
-16,
-194,
-83,
-146,
-174,
-146,
-180,
-103,
-228,
-246,
-158,
-146,
-254,
-228,
-52,
-131,
-0,
-44,
-136,
-57,
-121,
-124,
-46,
-114,
-239,
-72,
-191,
-183,
-96,
-228,
-222,
-217,
-152,
-129,
-238,
-62,
-224,
-204,
-204,
-245,
-177,
-152,
-133,
-54,
-201,
-32,
-150,
-12,
-90,
-208,
-158,
-117,
-51,
-125,
-212,
-41,
-235,
-194,
-222,
-143,
-129,
-215,
-114,
-215,
-43,
-95,
-142,
-51,
-217,
-171,
-184,
-173,
-35,
-119,
-239,
-77,
-192,
-211,
-80,
-104,
-169,
-220,
-215,
-229,
-148,
-121,
-50,
-215,
-230,
-245,
-50,
-251,
-148,
-180,
-185,
-30,
-102,
-28,
-219,
-58,
-115,
-109,
-99,
-204,
-79,
-97,
-221,
-130,
-50,
-107,
-250,
-180,
-184,
-46,
-240,
-104,
-230,
-250,
-133,
-192,
-167,
-138,
-218,
-106,
-12,
-186,
-212,
-158,
-117,
-51,
-125,
-212,
-45,
-11,
-252,
-2,
-179,
-77,
-204,
-200,
-93,
-175,
-124,
-57,
-206,
-0,
-55,
-147,
-113,
-254,
-200,
-220,
-219,
-3,
-184,
-177,
-132,
-1,
-22,
-244,
-119,
-180,
-77,
-230,
-218,
-118,
-217,
-247,
-86,
-210,
-238,
-199,
-128,
-39,
-129,
-101,
-157,
-129,
-31,
-6,
-62,
-86,
-81,
-230,
-58,
-103,
-174,
-143,
-248,
-249,
-187,
-48,
-103,
-147,
-55,
-149,
-149,
-107,
-4,
-186,
-212,
-158,
-49,
-12,
-150,
-44,
-96,
-102,
-230,
-56,
-233,
-229,
-248,
-51,
-29,
-79,
-206,
-224,
-229,
-247,
-254,
-0,
-28,
-81,
-196,
-0,
-78,
-243,
-35,
-220,
-57,
-197,
-207,
-207,
-3,
-126,
-148,
-216,
-223,
-95,
-96,
-190,
-130,
-127,
-0,
-126,
-145,
-88,
-102,
-89,
-224,
-223,
-126,
-252,
-39,
-220,
-195,
-170,
-85,
-208,
-189,
-30,
-123,
-88,
-44,
-89,
-57,
-6,
-72,
-122,
-57,
-206,
-0,
-219,
-98,
-243,
-235,
-26,
-153,
-235,
-203,
-3,
-255,
-196,
-220,
-208,
-202,
-24,
-96,
-59,
-124,
-26,
-240,
-191,
-167,
-200,
-120,
-18,
-85,
-180,
-189,
-48,
-54,
-69,
-61,
-69,
-197,
-28,
-142,
-59,
-189,
-2,
-107,
-97,
-158,
-85,
-219,
-99,
-14,
-171,
-1,
-27,
-253,
-94,
-43,
-43,
-95,
-11,
-116,
-169,
-61,
-99,
-152,
-44,
-89,
-29,
-6,
-200,
-188,
-156,
-147,
-128,
-73,
-216,
-240,
-26,
-157,
-10,
-156,
-1,
-182,
-195,
-124,
-14,
-190,
-156,
-185,
-254,
-121,
-224,
-112,
-191,
-87,
-198,
-0,
-99,
-128,
-199,
-156,
-81,
-182,
-246,
-31,
-52,
-105,
-201,
-235,
-31,
-218,
-116,
-108,
-154,
-27,
-178,
-154,
-200,
-209,
-222,
-130,
-9,
-128,
-119,
-2,
-239,
-243,
-231,
-219,
-14,
-88,
-221,
-127,
-175,
-25,
-101,
-229,
-147,
-65,
-11,
-218,
-51,
-134,
-201,
-146,
-5,
-204,
-244,
-47,
-162,
-243,
-114,
-54,
-197,
-28,
-90,
-22,
-3,
-166,
-23,
-148,
-233,
-48,
-192,
-106,
-206,
-40,
-99,
-188,
-142,
-187,
-49,
-107,
-102,
-41,
-3,
-120,
-29,
-103,
-96,
-186,
-142,
-179,
-73,
-116,
-253,
-118,
-198,
-254,
-23,
-240,
-73,
-224,
-88,
-108,
-4,
-90,
-168,
-186,
-164,
-4,
-236,
-7,
-252,
-17,
-152,
-31,
-184,
-26,
-120,
-27,
-240,
-122,
-74,
-217,
-158,
-131,
-97,
-182,
-100,
-117,
-94,
-78,
-238,
-218,
-4,
-224,
-138,
-2,
-122,
-112,
-199,
-20,
-76,
-224,
-219,
-22,
-24,
-143,
-207,
-201,
-137,
-12,
-240,
-14,
-108,
-249,
-54,
-25,
-88,
-191,
-170,
-143,
-94,
-230,
-76,
-224,
-42,
-103,
-182,
-121,
-128,
-127,
-0,
-149,
-46,
-230,
-216,
-202,
-228,
-126,
-44,
-86,
-224,
-28,
-6,
-166,
-202,
-153,
-85,
-101,
-251,
-2,
-134,
-209,
-146,
-149,
-125,
-57,
-153,
-107,
-155,
-2,
-215,
-82,
-108,
-121,
-203,
-50,
-192,
-161,
-216,
-114,
-242,
-2,
-96,
-123,
-191,
-86,
-201,
-0,
-78,
-119,
-59,
-112,
-123,
-21,
-157,
-211,
-110,
-9,
-60,
-75,
-38,
-152,
-5,
-243,
-196,
-126,
-149,
-204,
-210,
-176,
-160,
-236,
-81,
-192,
-5,
-126,
-252,
-47,
-108,
-138,
-155,
-228,
-207,
-49,
-188,
-90,
-83,
-134,
-217,
-146,
-149,
-125,
-57,
-126,
-190,
-13,
-112,
-17,
-176,
-112,
-73,
-153,
-44,
-3,
-44,
-14,
-252,
-219,
-95,
-236,
-24,
-191,
-150,
-196,
-0,
-169,
-0,
-222,
-2,
-60,
-64,
-68,
-166,
-193,
-228,
-144,
-7,
-129,
-183,
-20,
-148,
-93,
-4,
-147,
-55,
-198,
-70,
-238,
-141,
-140,
-17,
-96,
-184,
-16,
-123,
-57,
-206,
-48,
-247,
-101,
-190,
-146,
-141,
-34,
-229,
-102,
-51,
-128,
-159,
-255,
-146,
-140,
-11,
-92,
-219,
-12,
-48,
-226,
-1,
-108,
-229,
-28,
-122,
-47,
-176,
-113,
-230,
-250,
-242,
-152,
-144,
-212,
-174,
-202,
-113,
-20,
-35,
-11,
-152,
-20,
-190,
-13,
-166,
-139,
-191,
-46,
-115,
-253,
-7,
-192,
-145,
-195,
-217,
-183,
-81,
-244,
-1,
-216,
-154,
-244,
-45,
-192,
-66,
-248,
-210,
-9,
-211,
-63,
-223,
-75,
-47,
-84,
-142,
-163,
-24,
-89,
-192,
-140,
-20,
-29,
-6,
-120,
-222,
-175,
-93,
-78,
-137,
-113,
-195,
-105,
-26,
-27,
-100,
-156,
-110,
-39,
-204,
-0,
-116,
-149,
-255,
-93,
-6,
-76,
-232,
-254,
-137,
-134,
-31,
-12,
-198,
-12,
-44,
-170,
-233,
-68,
-42,
-236,
-5,
-5,
-117,
-189,
-189,
-224,
-250,
-82,
-190,
-138,
-200,
-135,
-245,
-111,
-130,
-197,
-101,
-44,
-157,
-218,
-192,
-13,
-153,
-41,
-224,
-111,
-216,
-154,
-248,
-159,
-152,
-150,
-107,
-136,
-108,
-144,
-41,
-215,
-141,
-65,
-230,
-100,
-224,
-123,
-89,
-9,
-31,
-88,
-218,
-175,
-149,
-70,
-254,
-212,
-101,
-28,
-111,
-107,
-50,
-240,
-138,
-255,
-159,
-0,
-124,
-26,
-51,
-204,
-60,
-5,
-156,
-75,
-196,
-28,
-155,
-41,
-191,
-14,
-240,
-83,
-23,
-56,
-159,
-198,
-150,
-157,
-167,
-149,
-49,
-184,
-255,
-240,
-157,
-24,
-136,
-177,
-192,
-7,
-48,
-101,
-213,
-223,
-139,
-218,
-194,
-116,
-254,
-223,
-243,
-118,
-94,
-5,
-166,
-248,
-52,
-252,
-34,
-176,
-92,
-65,
-153,
-139,
-240,
-24,
-206,
-204,
-181,
-115,
-113,
-187,
-74,
-18,
-128,
-205,
-48,
-201,
-249,
-126,
-96,
-139,
-140,
-76,
-16,
-149,
-13,
-34,
-229,
-107,
-25,
-100,
-128,
-93,
-24,
-80,
-186,
-128,
-169,
-70,
-31,
-7,
-142,
-245,
-107,
-223,
-43,
-250,
-65,
-155,
-48,
-14,
-102,
-194,
-125,
-15,
-182,
-228,
-251,
-152,
-127,
-145,
-147,
-176,
-105,
-110,
-37,
-255,
-0,
-162,
-241,
-142,
-192,
-110,
-254,
-110,
-246,
-194,
-109,
-19,
-152,
-99,
-200,
-119,
-252,
-171,
-142,
-46,
-55,
-253,
-185,
-182,
-203,
-93,
-91,
-8,
-91,
-242,
-157,
-16,
-161,
-95,
-10,
-19,
-184,
-127,
-131,
-41,
-153,
-22,
-1,
-54,
-192,
-84,
-228,
-143,
-20,
-49,
-27,
-3,
-150,
-200,
-5,
-253,
-124,
-126,
-44,
-186,
-107,
-151,
-24,
-125,
-37,
-128,
-125,
-112,
-229,
-2,
-17,
-217,
-160,
-160,
-76,
-45,
-131,
-12,
-230,
-50,
-182,
-148,
-31,
-131,
-169,
-53,
-87,
-195,
-194,
-211,
-23,
-244,
-31,
-244,
-178,
-72,
-185,
-44,
-227,
-172,
-4,
-252,
-197,
-31,
-246,
-119,
-126,
-173,
-144,
-113,
-50,
-117,
-204,
-139,
-105,
-24,
-63,
-150,
-185,
-182,
-7,
-240,
-112,
-132,
-118,
-172,
-191,
-252,
-149,
-10,
-234,
-186,
-144,
-140,
-45,
-33,
-119,
-111,
-8,
-3,
-248,
-245,
-207,
-17,
-201,
-250,
-1,
-252,
-183,
-51,
-229,
-152,
-28,
-237,
-3,
-152,
-138,
-250,
-11,
-5,
-237,
-4,
-103,
-170,
-255,
-231,
-231,
-123,
-249,
-199,
-52,
-79,
-140,
-190,
-20,
-152,
-86,
-237,
-94,
-92,
-181,
-73,
-68,
-54,
-40,
-40,
-151,
-55,
-200,
-148,
-90,
-171,
-24,
-156,
-238,
-5,
-224,
-67,
-192,
-113,
-152,
-110,
-188,
-163,
-140,
-185,
-42,
-82,
-46,
-203,
-56,
-191,
-195,
-244,
-241,
-99,
-112,
-61,
-64,
-9,
-227,
-172,
-128,
-133,
-188,
-61,
-236,
-127,
-49,
-188,
-17,
-41,
-247,
-117,
-224,
-56,
-63,
-94,
-13,
-83,
-27,
-79,
-197,
-134,
-230,
-21,
-48,
-245,
-245,
-189,
-145,
-114,
-67,
-144,
-185,
-247,
-65,
-224,
-229,
-72,
-153,
-201,
-157,
-182,
-252,
-124,
-93,
-76,
-167,
-177,
-165,
-191,
-155,
-59,
-242,
-101,
-50,
-180,
-159,
-7,
-174,
-241,
-227,
-203,
-129,
-83,
-139,
-104,
-75,
-1,
-124,
-138,
-140,
-93,
-27,
-147,
-7,
-182,
-198,
-101,
-131,
-146,
-114,
-121,
-131,
-76,
-169,
-181,
-42,
-194,
-0,
-87,
-96,
-115,
-241,
-58,
-153,
-235,
-49,
-6,
-200,
-150,
-123,
-14,
-88,
-61,
-66,
-19,
-43,
-247,
-103,
-204,
-211,
-104,
-17,
-103,
-24,
-176,
-16,
-184,
-172,
-237,
-97,
-136,
-233,
-25,
-251,
-34,
-215,
-246,
-227,
-107,
-128,
-195,
-252,
-248,
-85,
-44,
-98,
-122,
-12,
-240,
-74,
-164,
-92,
-39,
-16,
-118,
-167,
-124,
-221,
-192,
-238,
-192,
-139,
-145,
-50,
-175,
-0,
-123,
-249,
-241,
-188,
-152,
-12,
-118,
-150,
-159,
-239,
-89,
-244,
-46,
-253,
-254,
-114,
-152,
-208,
-183,
-14,
-230,
-151,
-184,
-70,
-17,
-109,
-33,
-252,
-229,
-60,
-202,
-96,
-93,
-245,
-32,
-217,
-160,
-162,
-124,
-178,
-181,
-202,
-127,
-240,
-37,
-253,
-24,
-167,
-61,
-16,
-56,
-207,
-175,
-45,
-69,
-252,
-75,
-206,
-51,
-192,
-106,
-17,
-154,
-24,
-3,
-188,
-4,
-236,
-234,
-199,
-227,
-188,
-205,
-83,
-202,
-158,
-199,
-105,
-95,
-102,
-96,
-110,
-125,
-9,
-120,
-59,
-54,
-26,
-130,
-141,
-150,
-139,
-3,
-79,
-23,
-148,
-133,
-248,
-20,
-240,
-37,
-224,
-214,
-200,
-245,
-87,
-24,
-200,
-199,
-112,
-2,
-54,
-34,
-116,
-204,
-227,
-123,
-17,
-25,
-53,
-114,
-229,
-127,
-135,
-77,
-191,
-133,
-31,
-106,
-207,
-64,
-77,
-107,
-21,
-102,
-219,
-254,
-185,
-31,
-119,
-24,
-32,
-96,
-158,
-50,
-155,
-96,
-115,
-249,
-16,
-199,
-208,
-28,
-227,
-252,
-22,
-243,
-34,
-26,
-195,
-192,
-180,
-80,
-196,
-56,
-147,
-176,
-233,
-226,
-173,
-216,
-84,
-112,
-163,
-51,
-208,
-222,
-206,
-16,
-239,
-5,
-118,
-143,
-148,
-123,
-9,
-88,
-212,
-143,
-31,
-194,
-134,
-227,
-29,
-176,
-17,
-96,
-25,
-44,
-140,
-254,
-226,
-130,
-103,
-28,
-194,
-0,
-94,
-230,
-73,
-224,
-63,
-35,
-244,
-147,
-49,
-47,
-165,
-245,
-48,
-33,
-117,
-211,
-204,
-189,
-227,
-129,
-59,
-99,
-237,
-228,
-222,
-41,
-184,
-235,
-88,
-95,
-65,
-3,
-107,
-21,
-240,
-85,
-44,
-16,
-36,
-43,
-205,
-47,
-133,
-45,
-45,
-79,
-46,
-40,
-147,
-101,
-156,
-149,
-176,
-37,
-224,
-52,
-60,
-137,
-85,
-9,
-227,
-108,
-143,
-205,
-253,
-211,
-129,
-111,
-97,
-67,
-236,
-209,
-126,
-237,
-117,
-108,
-78,
-143,
-249,
-7,
-78,
-196,
-163,
-156,
-177,
-161,
-123,
-138,
-63,
-215,
-4,
-224,
-127,
-48,
-225,
-108,
-229,
-130,
-190,
-130,
-77,
-1,
-11,
-96,
-242,
-194,
-1,
-152,
-176,
-118,
-13,
-145,
-21,
-18,
-230,
-91,
-112,
-15,
-54,
-141,
-158,
-150,
-185,
-62,
-143,
-51,
-71,
-244,
-157,
-100,
-232,
-118,
-114,
-134,
-45,
-52,
-130,
-245,
-4,
-116,
-97,
-173,
-242,
-31,
-244,
-10,
-108,
-202,
-184,
-218,
-143,
-75,
-151,
-47,
-77,
-24,
-167,
-41,
-128,
-255,
-44,
-98,
-224,
-132,
-178,
-89,
-60,
-143,
-45,
-169,
-143,
-2,
-230,
-43,
-160,
-95,
-6,
-147,
-222,
-95,
-198,
-150,
-172,
-11,
-99,
-115,
-250,
-149,
-206,
-116,
-67,
-150,
-129,
-206,
-28,
-11,
-97,
-194,
-232,
-93,
-192,
-25,
-77,
-250,
-58,
-199,
-161,
-9,
-227,
-52,
-108,
-103,
-62,
-255,
-98,
-127,
-69,
-198,
-117,
-219,
-127,
-172,
-86,
-29,
-51,
-177,
-21,
-204,
-115,
-152,
-101,
-242,
-49,
-76,
-168,
-155,
-234,
-35,
-86,
-52,
-84,
-206,
-71,
-150,
-87,
-188,
-220,
-15,
-128,
-249,
-219,
-236,
-147,
-168,
-25,
-218,
-53,
-55,
-194,
-153,
-224,
-211,
-152,
-84,
-62,
-13,
-243,
-29,
-120,
-0,
-23,
-88,
-91,
-110,
-43,
-26,
-31,
-208,
-55,
-144,
-203,
-172,
-73,
-196,
-109,
-122,
-20,
-115,
-15,
-98,
-95,
-247,
-254,
-146,
-54,
-240,
-227,
-219,
-36,
-213,
-138,
-238,
-29,
-197,
-28,
-142,
-58,
-67,
-190,
-207,
-89,
-175,
-145,
-243,
-184,
-193,
-194,
-157,
-94,
-45,
-154,
-183,
-114,
-180,
-141,
-194,
-200,
-71,
-209,
-3,
-48,
-216,
-18,
-213,
-17,
-64,
-190,
-77,
-137,
-73,
-17,
-211,
-174,
-125,
-35,
-119,
-237,
-219,
-20,
-172,
-141,
-35,
-229,
-107,
-133,
-145,
-211,
-48,
-139,
-246,
-40,
-163,
-85,
-128,
-1,
-75,
-212,
-165,
-12,
-88,
-162,
-214,
-243,
-31,
-248,
-62,
-92,
-25,
-18,
-41,
-183,
-11,
-166,
-194,
-237,
-228,
-2,
-126,
-147,
-11,
-73,
-61,
-177,
-233,
-99,
-214,
-183,
-14,
-3,
-36,
-121,
-227,
-122,
-185,
-36,
-70,
-195,
-20,
-66,
-19,
-49,
-69,
-204,
-237,
-84,
-104,
-63,
-115,
-101,
-107,
-51,
-39,
-53,
-82,
-187,
-231,
-202,
-181,
-203,
-208,
-152,
-37,
-234,
-94,
-114,
-22,
-36,
-76,
-203,
-54,
-153,
-98,
-139,
-215,
-60,
-62,
-98,
-236,
-226,
-231,
-187,
-59,
-35,
-69,
-95,
-52,
-109,
-57,
-48,
-244,
-8,
-152,
-54,
-243,
-84,
-96,
-9,
-76,
-115,
-152,
-148,
-19,
-217,
-203,
-214,
-98,
-78,
-224,
-187,
-152,
-86,
-114,
-117,
-76,
-135,
-145,
-156,
-218,
-189,
-238,
-200,
-153,
-82,
-225,
-32,
-75,
-84,
-238,
-222,
-241,
-101,
-28,
-141,
-41,
-102,
-126,
-230,
-199,
-191,
-161,
-192,
-108,
-153,
-161,
-175,
-229,
-192,
-208,
-132,
-105,
-176,
-168,
-160,
-105,
-228,
-220,
-176,
-49,
-83,
-247,
-179,
-37,
-35,
-218,
-11,
-25,
-102,
-222,
-139,
-2,
-61,
-255,
-92,
-7,
-50,
-150,
-168,
-200,
-189,
-82,
-67,
-4,
-102,
-38,
-157,
-142,
-185,
-135,
-205,
-160,
-192,
-118,
-158,
-161,
-175,
-237,
-192,
-80,
-151,
-105,
-252,
-254,
-137,
-152,
-118,
-44,
-100,
-174,
-221,
-70,
-196,
-25,
-35,
-115,
-255,
-39,
-152,
-61,
-98,
-2,
-166,
-149,
-59,
-172,
-236,
-89,
-188,
-76,
-19,
-217,
-169,
-47,
-101,
-146,
-209,
-13,
-3,
-56,
-205,
-95,
-49,
-15,
-153,
-63,
-150,
-209,
-57,
-109,
-109,
-7,
-134,
-134,
-76,
-179,
-136,
-127,
-237,
-239,
-243,
-243,
-157,
-177,
-136,
-227,
-178,
-128,
-145,
-245,
-48,
-211,
-246,
-27,
-192,
-222,
-9,
-207,
-82,
-91,
-118,
-234,
-87,
-153,
-90,
-192,
-116,
-205,
-199,
-23,
-220,
-75,
-177,
-68,
-29,
-236,
-47,
-46,
-150,
-58,
-37,
-70,
-95,
-203,
-129,
-161,
-9,
-211,
-100,
-218,
-185,
-193,
-143,
-255,
-74,
-193,
-52,
-231,
-247,
-223,
-235,
-12,
-115,
-54,
-166,
-233,
-251,
-25,
-3,
-206,
-41,
-135,
-19,
-113,
-200,
-160,
-129,
-236,
-212,
-175,
-50,
-181,
-128,
-37,
-130,
-190,
-47,
-210,
-64,
-146,
-37,
-170,
-65,
-123,
-181,
-29,
-24,
-234,
-50,
-141,
-211,
-45,
-236,
-95,
-253,
-103,
-49,
-169,
-57,
-26,
-126,
-229,
-180,
-119,
-0,
-95,
-242,
-227,
-149,
-24,
-112,
-200,
-92,
-206,
-153,
-237,
-195,
-145,
-50,
-181,
-101,
-167,
-126,
-149,
-169,
-133,
-204,
-16,
-115,
-21,
-230,
-138,
-148,
-181,
-68,
-117,
-63,
-196,
-196,
-219,
-172,
-229,
-192,
-208,
-132,
-105,
-188,
-220,
-113,
-24,
-134,
-216,
-224,
-115,
-116,
-47,
-2,
-187,
-101,
-206,
-87,
-198,
-28,
-100,
-94,
-0,
-190,
-95,
-80,
-166,
-246,
-212,
-217,
-175,
-50,
-41,
-200,
-238,
-26,
-246,
-140,
-164,
-77,
-36,
-77,
-145,
-244,
-39,
-73,
-255,
-150,
-101,
-8,
-123,
-80,
-182,
-251,
-85,
-161,
-67,
-104,
-23,
-248,
-158,
-164,
-237,
-37,
-37,
-165,
-109,
-245,
-157,
-205,
-174,
-148,
-116,
-150,
-108,
-199,
-178,
-201,
-137,
-237,
-116,
-148,
-82,
-67,
-210,
-215,
-231,
-112,
-163,
-164,
-227,
-176,
-101,
-220,
-56,
-73,
-155,
-202,
-118,
-239,
-154,
-79,
-210,
-180,
-196,
-182,
-230,
-40,
-204,
-155,
-61,
-241,
-45,
-224,
-62,
-218,
-199,
-246,
-103,
-74,
-154,
-33,
-233,
-162,
-26,
-101,
-190,
-39,
-233,
-119,
-170,
-215,
-207,
-212,
-32,
-207,
-131,
-36,
-125,
-93,
-198,
-248,
-11,
-73,
-154,
-36,
-233,
-11,
-146,
-110,
-146,
-116,
-45,
-240,
-74,
-8,
-33,
-191,
-130,
-152,
-34,
-41,
-234,
-16,
-226,
-215,
-239,
-143,
-92,
-239,
-87,
-153,
-222,
-131,
-226,
-165,
-73,
-52,
-89,
-34,
-93,
-58,
-48,
-208,
-192,
-235,
-133,
-129,
-93,
-63,
-86,
-173,
-211,
-86,
-98,
-221,
-181,
-101,
-167,
-126,
-149,
-233,
-57,
-40,
-95,
-154,
-60,
-64,
-102,
-179,
-168,
-76,
-153,
-218,
-14,
-12,
-45,
-48,
-77,
-47,
-25,
-160,
-182,
-236,
-212,
-175,
-50,
-61,
-7,
-189,
-94,
-154,
-12,
-212,
-215,
-91,
-175,
-151,
-46,
-145,
-25,
-5,
-31,
-167,
-190,
-82,
-167,
-167,
-101,
-154,
-62,
-80,
-82,
-198,
-110,
-122,
-189,
-52,
-25,
-197,
-240,
-128,
-196,
-140,
-221,
-244,
-104,
-105,
-50,
-138,
-254,
-97,
-222,
-216,
-197,
-16,
-194,
-44,
-73,
-71,
-181,
-80,
-127,
-123,
-73,
-12,
-71,
-209,
-19,
-12,
-50,
-37,
-82,
-223,
-216,
-48,
-69,
-229,
-75,
-147,
-41,
-249,
-139,
-52,
-180,
-210,
-213,
-133,
-11,
-125,
-177,
-168,
-156,
-194,
-220,
-63,
-152,
-47,
-195,
-49,
-152,
-63,
-192,
-75,
-152,
-98,
-232,
-110,
-160,
-141,
-143,
-97,
-100,
-163,
-66,
-162,
-47,
-146,
-76,
-171,
-150,
-38,
-255,
-85,
-208,
-86,
-19,
-43,
-93,
-45,
-230,
-172,
-203,
-0,
-254,
-227,
-95,
-135,
-5,
-101,
-236,
-224,
-140,
-250,
-86,
-224,
-253,
-177,
-122,
-114,
-253,
-122,
-202,
-143,
-151,
-6,
-30,
-47,
-233,
-79,
-7,
-149,
-201,
-34,
-98,
-253,
-199,
-98,
-45,
-175,
-35,
-30,
-195,
-56,
-147,
-248,
-30,
-6,
-105,
-201,
-174,
-104,
-102,
-160,
-40,
-91,
-154,
-220,
-73,
-65,
-6,
-76,
-106,
-90,
-233,
-26,
-50,
-103,
-93,
-6,
-56,
-14,
-75,
-252,
-80,
-107,
-4,
-2,
-118,
-197,
-147,
-81,
-98,
-219,
-202,
-71,
-211,
-220,
-123,
-127,
-146,
-147,
-69,
-228,
-251,
-15,
-124,
-25,
-27,
-153,
-138,
-114,
-4,
-212,
-122,
-222,
-14,
-178,
-83,
-192,
-174,
-146,
-190,
-239,
-243,
-255,
-108,
-132,
-16,
-222,
-144,
-169,
-106,
-135,
-108,
-22,
-25,
-81,
-31,
-79,
-147,
-116,
-151,
-164,
-151,
-36,
-109,
-17,
-66,
-24,
-18,
-1,
-235,
-229,
-158,
-151,
-244,
-223,
-146,
-58,
-43,
-136,
-207,
-74,
-58,
-35,
-132,
-240,
-66,
-65,
-63,
-63,
-43,
-233,
-85,
-73,
-31,
-10,
-33,
-220,
-30,
-66,
-120,
-62,
-132,
-112,
-167,
-108,
-131,
-134,
-55,
-36,
-125,
-166,
-160,
-92,
-29,
-236,
-39,
-233,
-188,
-6,
-42,
-239,
-13,
-36,
-77,
-140,
-28,
-199,
-240,
-122,
-8,
-225,
-149,
-16,
-194,
-148,
-16,
-194,
-111,
-37,
-109,
-37,
-105,
-41,
-73,
-71,
-151,
-53,
-0,
-28,
-42,
-105,
-15,
-73,
-59,
-250,
-187,
-107,
-31,
-180,
-36,
-209,
-99,
-86,
-186,
-137,
-249,
-145,
-36,
-66,
-87,
-199,
-74,
-215,
-196,
-122,
-86,
-138,
-8,
-253,
-12,
-96,
-191,
-148,
-103,
-116,
-250,
-231,
-252,
-111,
-38,
-102,
-44,
-26,
-116,
-92,
-208,
-159,
-58,
-201,
-34,
-240,
-175,
-247,
-3,
-62,
-250,
-69,
-115,
-4,
-37,
-212,
-159,
-60,
-2,
-180,
-133,
-79,
-75,
-90,
-69,
-210,
-37,
-148,
-36,
-67,
-242,
-175,
-253,
-12,
-73,
-95,
-145,
-116,
-122,
-8,
-225,
-165,
-146,
-58,
-223,
-46,
-233,
-161,
-130,
-123,
-15,
-122,
-123,
-49,
-236,
-44,
-105,
-129,
-220,
-223,
-206,
-69,
-93,
-146,
-217,
-38,
-102,
-163,
-140,
-97,
-66,
-8,
-139,
-133,
-16,
-22,
-147,
-244,
-164,
-164,
-181,
-252,
-248,
-127,
-37,
-173,
-238,
-199,
-169,
-184,
-167,
-164,
-255,
-235,
-75,
-250,
-153,
-108,
-116,
-28,
-146,
-189,
-164,
-13,
-100,
-25,
-96,
-138,
-90,
-48,
-54,
-132,
-16,
-238,
-149,
-89,
-248,
-222,
-144,
-84,
-149,
-201,
-58,
-213,
-74,
-215,
-20,
-157,
-33,
-119,
-246,
-95,
-73,
-159,
-30,
-148,
-148,
-207,
-53,
-80,
-198,
-48,
-194,
-118,
-20,
-39,
-132,
-48,
-21,
-75,
-224,
-52,
-203,
-13,
-106,
-117,
-48,
-70,
-210,
-172,
-130,
-123,
-235,
-203,
-166,
-166,
-147,
-128,
-229,
-107,
-214,
-155,
-220,
-120,
-7,
-151,
-73,
-58,
-36,
-63,
-116,
-251,
-249,
-193,
-146,
-46,
-77,
-173,
-52,
-132,
-240,
-247,
-16,
-194,
-110,
-33,
-132,
-170,
-60,
-182,
-169,
-86,
-186,
-41,
-234,
-189,
-37,
-236,
-18,
-73,
-135,
-146,
-145,
-176,
-203,
-24,
-198,
-135,
-249,
-127,
-73,
-90,
-214,
-143,
-39,
-75,
-90,
-174,
-51,
-53,
-212,
-104,
-247,
-157,
-94,
-54,
-134,
-11,
-93,
-86,
-184,
-72,
-210,
-79,
-200,
-172,
-154,
-34,
-152,
-37,
-51,
-91,
-231,
-241,
-38,
-229,
-70,
-182,
-44,
-178,
-12,
-112,
-170,
-19,
-95,
-73,
-70,
-162,
-151,
-116,
-185,
-211,
-69,
-51,
-104,
-245,
-9,
-173,
-49,
-103,
-9,
-206,
-144,
-9,
-175,
-127,
-194,
-178,
-164,
-45,
-138,
-173,
-74,
-162,
-95,
-158,
-15,
-243,
-231,
-72,
-58,
-209,
-143,
-207,
-148,
-116,
-82,
-102,
-106,
-168,
-4,
-102,
-49,
-253,
-152,
-108,
-152,
-47,
-195,
-103,
-36,
-173,
-36,
-233,
-216,
-18,
-154,
-123,
-37,
-189,
-59,
-114,
-125,
-35,
-191,
-151,
-212,
-161,
-254,
-24,
-27,
-6,
-218,
-75,
-178,
-210,
-209,
-204,
-122,
-86,
-91,
-40,
-194,
-188,
-154,
-191,
-137,
-101,
-5,
-155,
-233,
-130,
-225,
-189,
-20,
-236,
-235,
-227,
-237,
-79,
-240,
-227,
-203,
-40,
-217,
-234,
-206,
-251,
-83,
-39,
-89,
-196,
-160,
-254,
-99,
-233,
-239,
-95,
-6,
-54,
-200,
-211,
-250,
-253,
-61,
-48,
-167,
-217,
-3,
-253,
-119,
-124,
-27,
-112,
-144,
-11,
-165,
-251,
-23,
-245,
-107,
-142,
-65,
-191,
-153,
-51,
-177,
-79,
-79,
-116,
-218,
-247,
-227,
-183,
-149,
-208,
-102,
-145,
-146,
-44,
-98,
-8,
-3,
-99,
-241,
-23,
-147,
-41,
-78,
-43,
-255,
-62,
-44,
-132,
-253,
-101,
-103,
-222,
-155,
-129,
-15,
-117,
-243,
-140,
-163,
-24,
-197,
-40,
-70,
-49,
-138,
-185,
-31,
-62,
-231,
-220,
-157,
-159,
-147,
-42,
-132,
-166,
-43,
-124,
-94,
-126,
-210,
-231,
-230,
-239,
-2,
-151,
-39,
-180,
-53,
-98,
-66,
-181,
-105,
-24,
-110,
-62,
-183,
-32,
-175,
-9,
-92,
-84,
-210,
-49,
-53,
-202,
-63,
-41,
-105,
-89,
-73,
-107,
-75,
-90,
-75,
-210,
-91,
-252,
-90,
-21,
-46,
-144,
-45,
-125,
-134,
-4,
-90,
-228,
-65,
-162,
-119,
-82,
-174,
-76,
-157,
-144,
-235,
-236,
-26,
-185,
-72,
-33,
-83,
-214,
-86,
-85,
-184,
-249,
-10,
-152,
-89,
-121,
-205,
-18,
-154,
-206,
-190,
-73,
-235,
-213,
-108,
-187,
-52,
-112,
-21,
-203,
-99,
-124,
-117,
-238,
-218,
-159,
-201,
-236,
-175,
-148,
-189,
-1,
-240,
-31,
-46,
-161,
-142,
-203,
-92,
-47,
-27,
-1,
-30,
-3,
-86,
-201,
-156,
-47,
-82,
-213,
-169,
-186,
-32,
-209,
-59,
-41,
-67,
-223,
-56,
-228,
-58,
-177,
-254,
-90,
-57,
-148,
-128,
-243,
-49,
-251,
-72,
-105,
-194,
-12,
-108,
-207,
-133,
-115,
-203,
-104,
-156,
-110,
-33,
-6,
-194,
-213,
-254,
-234,
-255,
-3,
-17,
-203,
-171,
-255,
-30,
-15,
-2,
-255,
-225,
-231,
-135,
-96,
-206,
-186,
-67,
-173,
-174,
-206,
-0,
-91,
-250,
-131,
-93,
-158,
-185,
-94,
-198,
-0,
-79,
-144,
-73,
-146,
-136,
-173,
-207,
-163,
-241,
-244,
-116,
-107,
-175,
-110,
-25,
-77,
-251,
-131,
-237,
-228,
-185,
-178,
-191,
-167,
-231,
-128,
-35,
-74,
-104,
-215,
-240,
-23,
-62,
-63,
-102,
-30,
-127,
-103,
-9,
-237,
-70,
-216,
-154,
-189,
-106,
-131,
-141,
-19,
-48,
-179,
-245,
-79,
-49,
-31,
-138,
-159,
-98,
-9,
-58,
-190,
-88,
-64,
-191,
-137,
-223,
-127,
-167,
-255,
-31,
-178,
-231,
-67,
-135,
-16,
-108,
-139,
-182,
-133,
-176,
-112,
-168,
-78,
-170,
-215,
-50,
-6,
-248,
-1,
-150,
-174,
-117,
-49,
-255,
-241,
-127,
-82,
-244,
-197,
-121,
-253,
-117,
-236,
-243,
-181,
-126,
-160,
-6,
-244,
-181,
-250,
-147,
-185,
-95,
-39,
-135,
-210,
-175,
-128,
-143,
-250,
-241,
-190,
-68,
-82,
-216,
-230,
-232,
-255,
-9,
-28,
-94,
-65,
-179,
-8,
-182,
-165,
-252,
-49,
-216,
-212,
-114,
-180,
-159,
-23,
-250,
-49,
-96,
-142,
-39,
-51,
-136,
-56,
-232,
-228,
-31,
-38,
-184,
-13,
-255,
-40,
-73,
-103,
-71,
-135,
-138,
-193,
-120,
-171,
-164,
-103,
-100,
-170,
-198,
-251,
-100,
-115,
-104,
-105,
-110,
-128,
-26,
-152,
-39,
-210,
-191,
-54,
-233,
-107,
-193,
-25,
-230,
-110,
-111,
-39,
-123,
-189,
-136,
-193,
-54,
-148,
-244,
-46,
-13,
-132,
-189,
-93,
-36,
-105,
-53,
-96,
-147,
-146,
-102,
-206,
-145,
-52,
-36,
-93,
-109,
-22,
-238,
-15,
-48,
-77,
-246,
-27,
-29,
-44,
-179,
-190,
-78,
-171,
-240,
-99,
-24,
-39,
-233,
-89,
-255,
-63,
-8,
-209,
-23,
-22,
-66,
-248,
-181,
-44,
-69,
-220,
-41,
-42,
-49,
-36,
-132,
-16,
-118,
-9,
-33,
-28,
-18,
-66,
-88,
-38,
-132,
-240,
-182,
-16,
-194,
-193,
-33,
-132,
-29,
-203,
-30,
-96,
-14,
-71,
-29,
-33,
-249,
-84,
-73,
-167,
-116,
-12,
-98,
-238,
-88,
-243,
-21,
-73,
-101,
-177,
-18,
-191,
-144,
-244,
-54,
-42,
-118,
-17,
-149,
-180,
-177,
-164,
-137,
-33,
-132,
-95,
-74,
-186,
-69,
-210,
-123,
-139,
-8,
-49,
-175,
-171,
-237,
-36,
-189,
-71,
-210,
-14,
-120,
-198,
-244,
-24,
-225,
-160,
-33,
-17,
-203,
-160,
-253,
-60,
-182,
-189,
-74,
-215,
-115,
-116,
-131,
-41,
-96,
-36,
-210,
-215,
-18,
-146,
-155,
-0,
-115,
-205,
-251,
-101,
-75,
-117,
-45,
-137,
-201,
-105,
-157,
-233,
-124,
-79,
-63,
-95,
-162,
-67,
-83,
-56,
-100,
-134,
-16,
-30,
-146,
-244,
-85,
-73,
-95,
-106,
-163,
-51,
-115,
-9,
-238,
-151,
-116,
-190,
-164,
-111,
-245,
-176,
-141,
-115,
-37,
-189,
-159,
-130,
-13,
-162,
-106,
-226,
-219,
-146,
-238,
-8,
-33,
-252,
-74,
-146,
-124,
-196,
-184,
-211,
-175,
-75,
-170,
-158,
-51,
-191,
-38,
-11,
-19,
-111,
-3,
-141,
-236,
-213,
-61,
-68,
-147,
-254,
-204,
-39,
-233,
-68,
-73,
-235,
-119,
-190,
-170,
-182,
-17,
-66,
-184,
-95,
-210,
-181,
-50,
-51,
-113,
-183,
-117,
-237,
-29,
-66,
-152,
-144,
-187,
-182,
-67,
-8,
-97,
-246,
-86,
-128,
-217,
-252,
-0,
-33,
-132,
-112,
-117,
-142,
-248,
-245,
-16,
-194,
-58,
-33,
-132,
-50,
-71,
-132,
-84,
-212,
-181,
-87,
-215,
-253,
-129,
-234,
-210,
-55,
-177,
-159,
-215,
-21,
-146,
-155,
-226,
-28,
-73,
-31,
-197,
-115,
-47,
-206,
-21,
-160,
-166,
-189,
-26,
-83,
-209,
-126,
-62,
-114,
-253,
-11,
-46,
-141,
-119,
-75,
-95,
-183,
-63,
-121,
-25,
-233,
-114,
-44,
-151,
-208,
-248,
-54,
-101,
-128,
-185,
-26,
-212,
-176,
-87,
-55,
-248,
-129,
-106,
-59,
-68,
-212,
-236,
-79,
-158,
-1,
-90,
-21,
-146,
-71,
-17,
-65,
-157,
-31,
-168,
-9,
-125,
-205,
-190,
-12,
-89,
-53,
-96,
-46,
-237,
-79,
-14,
-39,
-3,
-120,
-191,
-54,
-175,
-166,
-76,
-171,
-108,
-173,
-252,
-57,
-17,
-71,
-68,
-74,
-208,
-74,
-71,
-70,
-32,
-10,
-24,
-96,
-62,
-204,
-130,
-58,
-231,
-51,
-0,
-176,
-10,
-166,
-99,
-222,
-193,
-207,
-183,
-33,
-183,
-143,
-95,
-134,
-182,
-179,
-207,
-222,
-26,
-222,
-129,
-181,
-41,
-216,
-119,
-111,
-20,
-67,
-129,
-109,
-170,
-149,
-36,
-88,
-99,
-6,
-173,
-168,
-219,
-152,
-223,
-111,
-117,
-4,
-216,
-210,
-153,
-224,
-243,
-254,
-127,
-124,
-5,
-253,
-88,
-239,
-64,
-235,
-169,
-87,
-230,
-102,
-164,
-254,
-248,
-78,
-75,
-217,
-135,
-149,
-101,
-0,
-204,
-225,
-244,
-38,
-114,
-41,
-117,
-235,
-118,
-238,
-24,
-175,
-52,
-154,
-53,
-52,
-71,
-155,
-196,
-0,
-88,
-46,
-225,
-171,
-49,
-227,
-197,
-19,
-152,
-141,
-255,
-255,
-252,
-94,
-68,
-41,
-72,
-101,
-0,
-44,
-136,
-247,
-55,
-192,
-239,
-105,
-178,
-103,
-176,
-87,
-182,
-149,
-127,
-249,
-157,
-72,
-217,
-237,
-43,
-232,
-83,
-25,
-224,
-70,
-44,
-217,
-243,
-50,
-152,
-229,
-234,
-160,
-146,
-135,
-129,
-129,
-125,
-252,
-206,
-1,
-22,
-79,
-232,
-119,
-233,
-48,
-233,
-52,
-75,
-97,
-142,
-34,
-83,
-177,
-56,
-200,
-135,
-40,
-216,
-45,
-188,
-23,
-192,
-220,
-192,
-99,
-136,
-109,
-33,
-123,
-97,
-1,
-237,
-175,
-34,
-180,
-96,
-91,
-204,
-125,
-195,
-191,
-254,
-232,
-182,
-244,
-41,
-29,
-28,
-135,
-205,
-249,
-219,
-248,
-249,
-22,
-126,
-190,
-86,
-73,
-153,
-84,
-6,
-120,
-153,
-34,
-35,
-196,
-96,
-58,
-48,
-223,
-249,
-133,
-49,
-251,
-248,
-157,
-120,
-26,
-250,
-132,
-114,
-101,
-95,
-201,
-34,
-152,
-59,
-245,
-213,
-152,
-235,
-215,
-226,
-254,
-124,
-177,
-212,
-175,
-11,
-3,
-23,
-224,
-210,
-125,
-22,
-17,
-218,
-107,
-129,
-255,
-206,
-93,
-59,
-25,
-207,
-77,
-156,
-187,
-62,
-134,
-220,
-62,
-197,
-254,
-55,
-36,
-225,
-21,
-38,
-92,
-118,
-238,
-131,
-5,
-169,
-188,
-153,
-8,
-147,
-251,
-253,
-142,
-7,
-212,
-16,
-121,
-173,
-22,
-200,
-24,
-57,
-252,
-188,
-40,
-104,
-177,
-115,
-63,
-149,
-1,
-238,
-33,
-205,
-219,
-5,
-6,
-175,
-181,
-247,
-7,
-42,
-85,
-209,
-9,
-12,
-112,
-10,
-230,
-189,
-84,
-24,
-172,
-154,
-161,
-61,
-39,
-247,
-187,
-79,
-194,
-116,
-10,
-147,
-34,
-180,
-91,
-96,
-211,
-90,
-103,
-43,
-219,
-249,
-253,
-163,
-121,
-127,
-69,
-27,
-109,
-203,
-0,
-191,
-194,
-188,
-160,
-174,
-168,
-83,
-119,
-215,
-168,
-193,
-0,
-59,
-99,
-27,
-62,
-92,
-71,
-137,
-61,
-60,
-194,
-0,
-31,
-6,
-162,
-193,
-150,
-212,
-27,
-38,
-239,
-166,
-98,
-19,
-139,
-12,
-237,
-99,
-185,
-250,
-238,
-242,
-235,
-81,
-135,
-81,
-44,
-215,
-241,
-201,
-126,
-124,
-176,
-51,
-123,
-233,
-143,
-64,
-15,
-86,
-1,
-216,
-200,
-245,
-16,
-240,
-233,
-148,
-122,
-91,
-65,
-42,
-3,
-56,
-237,
-234,
-152,
-144,
-50,
-139,
-200,
-208,
-235,
-52,
-48,
-48,
-5,
-108,
-140,
-165,
-145,
-249,
-66,
-1,
-109,
-157,
-97,
-242,
-21,
-96,
-159,
-88,
-61,
-17,
-218,
-153,
-53,
-25,
-96,
-19,
-204,
-71,
-112,
-17,
-108,
-47,
-225,
-131,
-83,
-218,
-105,
-11,
-29,
-6,
-240,
-227,
-205,
-49,
-5,
-216,
-187,
-250,
-213,
-120,
-237,
-101,
-32,
-182,
-15,
-79,
-52,
-214,
-63,
-242,
-53,
-31,
-153,
-88,
-39,
-148,
-15,
-147,
-175,
-144,
-176,
-249,
-131,
-211,
-78,
-175,
-195,
-0,
-126,
-239,
-114,
-76,
-250,
-158,
-74,
-36,
-206,
-175,
-151,
-200,
-50,
-128,
-159,
-127,
-5,
-155,
-182,
-10,
-19,
-110,
-12,
-43,
-176,
-164,
-75,
-209,
-52,
-39,
-254,
-48,
-219,
-249,
-241,
-223,
-129,
-66,
-239,
-155,
-220,
-8,
-112,
-169,
-143,
-26,
-69,
-35,
-192,
-36,
-224,
-115,
-137,
-253,
-251,
-83,
-42,
-3,
-48,
-48,
-250,
-228,
-177,
-66,
-74,
-91,
-35,
-10,
-184,
-85,
-43,
-134,
-46,
-235,
-93,
-10,
-51,
-208,
-44,
-141,
-249,
-200,
-95,
-6,
-252,
-174,
-128,
-54,
-203,
-0,
-187,
-97,
-75,
-209,
-162,
-68,
-83,
-117,
-100,
-128,
-51,
-177,
-249,
-177,
-242,
-235,
-196,
-146,
-80,
-61,
-156,
-194,
-0,
-126,
-61,
-59,
-13,
-237,
-196,
-156,
-170,
-13,
-37,
-190,
-76,
-89,
-180,
-5,
-6,
-88,
-28,
-219,
-170,
-165,
-147,
-71,
-231,
-18,
-10,
-162,
-104,
-115,
-12,
-16,
-48,
-225,
-45,
-233,
-203,
-173,
-232,
-195,
-210,
-152,
-167,
-243,
-223,
-176,
-53,
-243,
-34,
-216,
-178,
-183,
-72,
-22,
-121,
-51,
-176,
-1,
-176,
-97,
-25,
-3,
-208,
-197,
-8,
-224,
-12,
-254,
-40,
-17,
-165,
-77,
-65,
-157,
-253,
-183,
-55,
-116,
-30,
-176,
-143,
-237,
-205,
-102,
-0,
-63,
-255,
-48,
-45,
-37,
-143,
-4,
-150,
-7,
-190,
-143,
-133,
-176,
-205,
-194,
-76,
-185,
-215,
-38,
-148,
-235,
-201,
-8,
-128,
-229,
-58,
-40,
-202,
-163,
-56,
-187,
-174,
-236,
-95,
-74,
-189,
-173,
-2,
-155,
-103,
-135,
-36,
-71,
-192,
-180,
-121,
-127,
-241,
-151,
-217,
-193,
-227,
-100,
-156,
-13,
-71,
-50,
-128,
-139,
-129,
-75,
-18,
-105,
-43,
-133,
-64,
-191,
-63,
-136,
-121,
-43,
-104,
-87,
-199,
-150,
-197,
-149,
-35,
-97,
-66,
-155,
-187,
-96,
-59,
-156,
-206,
-192,
-130,
-86,
-214,
-79,
-233,
-67,
-87,
-192,
-134,
-244,
-147,
-252,
-248,
-68,
-224,
-250,
-158,
-55,
-218,
-34,
-176,
-41,
-33,
-41,
-223,
-94,
-42,
-3,
-212,
-108,
-255,
-44,
-160,
-112,
-151,
-148,
-154,
-12,
-48,
-25,
-155,
-170,
-150,
-193,
-132,
-225,
-222,
-255,
-22,
-206,
-109,
-219,
-250,
-241,
-182,
-68,
-244,
-217,
-125,
-232,
-67,
-22,
-47,
-99,
-243,
-233,
-197,
-84,
-107,
-47,
-255,
-138,
-173,
-48,
-62,
-153,
-216,
-78,
-171,
-12,
-128,
-89,
-236,
-166,
-1,
-91,
-149,
-208,
-68,
-81,
-64,
-247,
-137,
-204,
-249,
-142,
-64,
-81,
-178,
-205,
-40,
-154,
-90,
-228,
-238,
-151,
-244,
-65,
-31,
-242,
-63,
-168,
-226,
-44,
-87,
-131,
-128,
-205,
-233,
-80,
-18,
-35,
-87,
-19,
-157,
-60,
-128,
-111,
-147,
-101,
-50,
-93,
-82,
-210,
-144,
-85,
-64,
-22,
-33,
-132,
-45,
-66,
-8,
-27,
-133,
-16,
-206,
-105,
-169,
-15,
-117,
-177,
-159,
-164,
-199,
-66,
-8,
-215,
-85,
-208,
-197,
-114,
-28,
-198,
-144,
-117,
-96,
-125,
-81,
-182,
-215,
-81,
-111,
-225,
-67,
-206,
-52,
-204,
-106,
-55,
-145,
-4,
-205,
-19,
-176,
-32,
-166,
-217,
-123,
-190,
-136,
-1,
-48,
-189,
-122,
-244,
-47,
-66,
-59,
-100,
-152,
-196,
-36,
-235,
-178,
-132,
-147,
-195,
-14,
-204,
-101,
-173,
-116,
-244,
-169,
-57,
-5,
-100,
-149,
-64,
-155,
-199,
-70,
-138,
-50,
-148,
-186,
-29,
-3,
-99,
-60,
-164,
-105,
-16,
-66,
-8,
-255,
-196,
-214,
-212,
-107,
-132,
-16,
-30,
-76,
-108,
-235,
-51,
-178,
-221,
-184,
-10,
-99,
-223,
-66,
-8,
-141,
-184,
-23,
-83,
-254,
-140,
-149,
-237,
-36,
-86,
-103,
-7,
-178,
-174,
-128,
-57,
-204,
-68,
-87,
-18,
-49,
-87,
-122,
-44,
-50,
-119,
-13,
-73,
-63,
-233,
-109,
-207,
-26,
-130,
-26,
-177,
-239,
-88,
-122,
-179,
-14,
-158,
-164,
-68,
-213,
-138,
-45,
-193,
-158,
-192,
-148,
-66,
-111,
-180,
-49,
-5,
-20,
-76,
-147,
-23,
-208,
-212,
-25,
-162,
-89,
-31,
-138,
-76,
-188,
-209,
-37,
-27,
-233,
-57,
-0,
-250,
-54,
-2,
-228,
-101,
-128,
-253,
-101,
-25,
-175,
-37,
-11,
-14,
-141,
-166,
-112,
-1,
-206,
-145,
-101,
-239,
-92,
-213,
-255,
-206,
-85,
-121,
-34,
-201,
-175,
-74,
-58,
-199,
-179,
-139,
-183,
-105,
-174,
-236,
-204,
-147,
-11,
-75,
-26,
-47,
-11,
-234,
-248,
-122,
-164,
-191,
-27,
-98,
-186,
-250,
-233,
-88,
-130,
-234,
-139,
-40,
-73,
-233,
-150,
-138,
-16,
-194,
-27,
-249,
-84,
-180,
-153,
-148,
-180,
-249,
-62,
-44,
-41,
-105,
-47,
-101,
-194,
-178,
-70,
-28,
-72,
-116,
-211,
-242,
-121,
-121,
-163,
-204,
-249,
-38,
-20,
-164,
-71,
-197,
-52,
-111,
-143,
-227,
-198,
-9,
-231,
-218,
-182,
-70,
-128,
-188,
-12,
-176,
-63,
-240,
-108,
-132,
-246,
-66,
-204,
-81,
-99,
-101,
-108,
-13,
-126,
-45,
-5,
-121,
-253,
-157,
-62,
-201,
-123,
-136,
-30,
-169,
-207,
-135,
-5,
-222,
-239,
-36,
-165,
-2,
-102,
-207,
-62,
-210,
-143,
-23,
-244,
-23,
-28,
-141,
-104,
-5,
-110,
-192,
-44,
-84,
-171,
-250,
-31,
-152,
-255,
-126,
-87,
-201,
-143,
-11,
-24,
-224,
-96,
-224,
-177,
-132,
-178,
-239,
-163,
-216,
-32,
-85,
-199,
-123,
-168,
-214,
-20,
-48,
-162,
-225,
-47,
-52,
-73,
-169,
-224,
-95,
-252,
-173,
-152,
-243,
-196,
-67,
-88,
-166,
-176,
-168,
-22,
-176,
-232,
-11,
-1,
-254,
-210,
-66,
-127,
-59,
-234,
-210,
-69,
-49,
-143,
-230,
-251,
-129,
-51,
-19,
-202,
-126,
-130,
-72,
-184,
-152,
-223,
-75,
-246,
-30,
-154,
-171,
-224,
-47,
-180,
-43,
-165,
-66,
-141,
-118,
-218,
-22,
-2,
-103,
-98,
-185,
-120,
-78,
-166,
-98,
-83,
-73,
-44,
-5,
-206,
-125,
-192,
-199,
-11,
-238,
-39,
-123,
-15,
-205,
-85,
-240,
-23,
-185,
-109,
-230,
-188,
-182,
-68,
-89,
-163,
-157,
-182,
-20,
-65,
-117,
-219,
-158,
-199,
-71,
-182,
-223,
-80,
-224,
-146,
-69,
-13,
-239,
-161,
-134,
-125,
-56,
-44,
-50,
-26,
-198,
-18,
-85,
-64,
-66,
-192,
-7,
-240,
-59,
-76,
-86,
-153,
-138,
-9,
-184,
-93,
-233,
-1,
-94,
-173,
-83,
-184,
-9,
-90,
-10,
-53,
-175,
-13,
-76,
-192,
-253,
-129,
-164,
-197,
-101,
-123,
-239,
-148,
-189,
-168,
-94,
-10,
-113,
-75,
-73,
-186,
-66,
-82,
-214,
-219,
-169,
-82,
-110,
-41,
-66,
-8,
-97,
-182,
-3,
-42,
-240,
-99,
-21,
-107,
-12,
-163,
-152,
-123,
-226,
-207,
-75,
-224,
-95,
-251,
-119,
-100,
-75,
-214,
-9,
-33,
-132,
-178,
-253,
-143,
-166,
-168,
-120,
-11,
-151,
-170,
-118,
-86,
-150,
-229,
-1,
-218,
-82,
-166,
-150,
-30,
-31,
-66,
-184,
-41,
-71,
-182,
-148,
-164,
-7,
-61,
-17,
-68,
-107,
-0,
-54,
-147,
-244,
-33,
-89,
-194,
-206,
-100,
-212,
-182,
-5,
-96,
-82,
-242,
-143,
-128,
-127,
-99,
-10,
-160,
-202,
-8,
-162,
-17,
-128,
-111,
-200,
-244,
-4,
-71,
-200,
-146,
-48,
-117,
-86,
-36,
-177,
-156,
-124,
-127,
-144,
-37,
-103,
-168,
-229,
-219,
-135,
-101,
-50,
-189,
-78,
-54,
-122,
-76,
-144,
-237,
-115,
-116,
-103,
-132,
-116,
-41,
-217,
-222,
-66,
-41,
-216,
-4,
-19,
-204,
-103,
-96,
-249,
-0,
-163,
-242,
-141,
-143,
-110,
-223,
-146,
-244,
-213,
-16,
-194,
-163,
-117,
-250,
-157,
-173,
-100,
-208,
-156,
-83,
-36,
-3,
-0,
-223,
-193,
-44,
-106,
-171,
-57,
-205,
-35,
-192,
-1,
-141,
-26,
-237,
-65,
-255,
-74,
-202,
-198,
-240,
-145,
-8,
-109,
-45,
-239,
-161,
-76,
-185,
-255,
-194,
-54,
-131,
-172,
-218,
-45,
-237,
-50,
-204,
-59,
-234,
-53,
-76,
-63,
-242,
-109,
-34,
-153,
-70,
-188,
-127,
-183,
-97,
-190,
-23,
-107,
-98,
-130,
-235,
-23,
-10,
-234,
-60,
-212,
-239,
-247,
-126,
-87,
-117,
-239,
-244,
-142,
-153,
-243,
-143,
-18,
-89,
-46,
-22,
-9,
-55,
-5,
-117,
-158,
-128,
-229,
-3,
-126,
-26,
-56,
-151,
-226,
-141,
-20,
-187,
-82,
-123,
-166,
-130,
-6,
-222,
-67,
-88,
-46,
-130,
-74,
-247,
-53,
-44,
-115,
-215,
-170,
-216,
-82,
-123,
-107,
-204,
-97,
-245,
-194,
-8,
-29,
-120,
-138,
-87,
-63,
-255,
-52,
-241,
-76,
-39,
-75,
-98,
-163,
-241,
-46,
-169,
-207,
-215,
-21,
-48,
-117,
-234,
-123,
-51,
-231,
-59,
-0,
-67,
-146,
-20,
-166,
-50,
-0,
-176,
-31,
-166,
-88,
-90,
-23,
-88,
-9,
-83,
-28,
-197,
-180,
-110,
-125,
-99,
-128,
-38,
-192,
-252,
-29,
-191,
-136,
-133,
-179,
-189,
-128,
-69,
-233,
-84,
-42,
-187,
-176,
-61,
-25,
-103,
-68,
-174,
-67,
-38,
-95,
-32,
-166,
-188,
-26,
-34,
-164,
-99,
-35,
-114,
-105,
-6,
-210,
-50,
-52,
-241,
-7,
-184,
-94,
-210,
-17,
-62,
-52,
-190,
-93,
-182,
-251,
-103,
-179,
-128,
-68,
-195,
-17,
-146,
-190,
-22,
-66,
-184,
-43,
-132,
-240,
-136,
-76,
-151,
-191,
-103,
-23,
-245,
-13,
-23,
-22,
-146,
-180,
-181,
-164,
-221,
-36,
-173,
-40,
-233,
-101,
-153,
-141,
-164,
-10,
-243,
-73,
-122,
-170,
-224,
-222,
-152,
-220,
-113,
-140,
-225,
-63,
-42,
-105,
-51,
-6,
-150,
-130,
-83,
-233,
-165,
-91,
-186,
-127,
-165,
-87,
-98,
-246,
-128,
-59,
-157,
-235,
-159,
-137,
-208,
-165,
-142,
-0,
-207,
-50,
-20,
-67,
-76,
-208,
-145,
-17,
-96,
-251,
-17,
-54,
-2,
-188,
-64,
-38,
-0,
-22,
-83,
-31,
-199,
-70,
-198,
-227,
-125,
-180,
-91,
-26,
-139,
-198,
-190,
-15,
-56,
-37,
-66,
-7,
-158,
-103,
-216,
-207,
-143,
-161,
-7,
-251,
-25,
-204,
-230,
-48,
-76,
-175,
-125,
-134,
-255,
-32,
-79,
-99,
-33,
-221,
-135,
-228,
-11,
-132,
-16,
-30,
-9,
-33,
-236,
-24,
-66,
-88,
-40,
-132,
-176,
-158,
-164,
-87,
-148,
-186,
-45,
-89,
-113,
-31,
-246,
-209,
-96,
-207,
-151,
-216,
-136,
-242,
-146,
-6,
-123,
-187,
-172,
-17,
-171,
-44,
-195,
-68,
-179,
-48,
-19,
-244,
-55,
-72,
-8,
-49,
-111,
-1,
-119,
-201,
-190,
-252,
-14,
-22,
-146,
-121,
-232,
-228,
-241,
-30,
-217,
-40,
-58,
-85,
-210,
-121,
-146,
-126,
-36,
-41,
-154,
-233,
-91,
-210,
-145,
-152,
-0,
-184,
-150,
-164,
-195,
-212,
-75,
-63,
-2,
-224,
-63,
-157,
-27,
-215,
-198,
-50,
-91,
-19,
-99,
-128,
-72,
-185,
-137,
-192,
-137,
-145,
-235,
-169,
-35,
-192,
-45,
-120,
-112,
-101,
-5,
-221,
-13,
-152,
-6,
-111,
-25,
-76,
-58,
-159,
-28,
-27,
-1,
-188,
-221,
-78,
-124,
-225,
-38,
-152,
-106,
-247,
-231,
-17,
-186,
-113,
-88,
-166,
-243,
-206,
-30,
-192,
-151,
-18,
-217,
-159,
-55,
-50,
-58,
-81,
-208,
-238,
-129,
-152,
-13,
-97,
-75,
-108,
-133,
-116,
-3,
-240,
-157,
-170,
-231,
-42,
-121,
-94,
-128,
-207,
-96,
-246,
-141,
-151,
-177,
-125,
-7,
-122,
-23,
-118,
-134,
-5,
-54,
-30,
-229,
-199,
-215,
-96,
-214,
-176,
-91,
-34,
-116,
-243,
-99,
-238,
-226,
-75,
-98,
-142,
-35,
-83,
-137,
-108,
-221,
-86,
-131,
-1,
-246,
-194,
-156,
-80,
-62,
-4,
-172,
-136,
-229,
-5,
-216,
-45,
-66,
-247,
-78,
-103,
-182,
-87,
-48,
-139,
-229,
-174,
-37,
-12,
-144,
-141,
-45,
-56,
-0,
-152,
-22,
-161,
-187,
-25,
-11,
-169,
-30,
-135,
-229,
-71,
-250,
-5,
-112,
-107,
-132,
-110,
-213,
-220,
-223,
-215,
-40,
-112,
-148,
-193,
-150,
-130,
-79,
-97,
-82,
-249,
-15,
-169,
-200,
-253,
-95,
-6,
-127,
-142,
-118,
-114,
-255,
-36,
-54,
-56,
-29,
-147,
-52,
-183,
-193,
-252,
-214,
-118,
-45,
-120,
-113,
-27,
-97,
-107,
-216,
-255,
-197,
-162,
-124,
-242,
-251,
-237,
-118,
-232,
-146,
-24,
-192,
-105,
-63,
-130,
-133,
-99,
-205,
-116,
-134,
-250,
-84,
-23,
-207,
-145,
-103,
-128,
-168,
-137,
-24,
-155,
-179,
-179,
-50,
-197,
-150,
-84,
-24,
-191,
-48,
-91,
-194,
-20,
-122,
-104,
-43,
-200,
-180,
-149,
-204,
-0,
-152,
-60,
-52,
-209,
-71,
-138,
-169,
-36,
-140,
-168,
-177,
-74,
-166,
-97,
-67,
-231,
-141,
-152,
-37,
-240,
-3,
-68,
-156,
-43,
-106,
-212,
-7,
-67,
-163,
-91,
-74,
-211,
-184,
-180,
-129,
-76,
-187,
-139,
-49,
-32,
-100,
-157,
-29,
-161,
-251,
-33,
-240,
-107,
-204,
-58,
-184,
-16,
-230,
-49,
-84,
-234,
-41,
-12,
-236,
-141,
-41,
-137,
-122,
-174,
-66,
-175,
-201,
-0,
-79,
-98,
-250,
-152,
-69,
-177,
-216,
-198,
-241,
-77,
-26,
-252,
-7,
-22,
-230,
-220,
-217,
-135,
-230,
-104,
-224,
-239,
-181,
-43,
-26,
-168,
-47,
-134,
-82,
-151,
-237,
-54,
-144,
-105,
-107,
-38,
-230,
-171,
-112,
-10,
-241,
-173,
-89,
-231,
-199,
-194,
-179,
-158,
-197,
-134,
-236,
-243,
-168,
-222,
-0,
-234,
-22,
-224,
-179,
-45,
-244,
-177,
-213,
-157,
-202,
-188,
-190,
-243,
-233,
-38,
-132,
-14,
-248,
-148,
-191,
-184,
-253,
-49,
-65,
-240,
-1,
-224,
-208,
-110,
-59,
-215,
-111,
-248,
-51,
-164,
-200,
-30,
-187,
-251,
-151,
-179,
-157,
-63,
-251,
-179,
-148,
-7,
-107,
-116,
-146,
-47,
-44,
-217,
-66,
-31,
-239,
-200,
-48,
-192,
-237,
-45,
-212,
-55,
-30,
-115,
-209,
-159,
-142,
-109,
-47,
-91,
-223,
-153,
-5,
-203,
-171,
-251,
-15,
-127,
-17,
-211,
-128,
-47,
-85,
-125,
-17,
-253,
-4,
-22,
-45,
-124,
-154,
-247,
-237,
-25,
-34,
-137,
-161,
-157,
-46,
-149,
-1,
-38,
-147,
-209,
-239,
-99,
-94,
-66,
-49,
-227,
-77,
-231,
-254,
-111,
-40,
-217,
-129,
-12,
-203,
-104,
-50,
-209,
-153,
-228,
-206,
-70,
-195,
-112,
-67,
-120,
-123,
-7,
-249,
-135,
-123,
-11,
-240,
-219,
-126,
-53,
-12,
-53,
-247,
-186,
-43,
-168,
-99,
-8,
-34,
-116,
-7,
-99,
-235,
-250,
-119,
-97,
-110,
-107,
-79,
-1,
-187,
-23,
-212,
-151,
-194,
-0,
-47,
-98,
-38,
-212,
-206,
-249,
-86,
-68,
-20,
-55,
-126,
-111,
-21,
-159,
-82,
-10,
-179,
-112,
-249,
-87,
-253,
-77,
-204,
-135,
-240,
-43,
-64,
-212,
-220,
-235,
-253,
-107,
-85,
-165,
-141,
-9,
-180,
-59,
-249,
-241,
-102,
-244,
-58,
-56,
-6,
-56,
-28,
-19,
-174,
-240,
-161,
-39,
-105,
-79,
-191,
-130,
-186,
-242,
-14,
-149,
-151,
-17,
-9,
-156,
-196,
-150,
-166,
-95,
-204,
-156,
-159,
-76,
-68,
-7,
-94,
-131,
-1,
-174,
-196,
-214,
-254,
-227,
-176,
-117,
-251,
-31,
-129,
-95,
-23,
-208,
-126,
-11,
-184,
-170,
-162,
-190,
-89,
-157,
-175,
-30,
-19,
-66,
-135,
-232,
-247,
-51,
-253,
-171,
-197,
-0,
-20,
-120,
-92,
-103,
-238,
-159,
-238,
-31,
-196,
-193,
-192,
-73,
-192,
-53,
-101,
-244,
-93,
-193,
-27,
-121,
-209,
-135,
-156,
-21,
-176,
-124,
-193,
-155,
-69,
-232,
-222,
-135,
-101,
-5,
-123,
-17,
-27,
-182,
-47,
-7,
-86,
-175,
-168,
-123,
-107,
-108,
-41,
-51,
-54,
-114,
-111,
-42,
-153,
-204,
-223,
-152,
-222,
-160,
-177,
-39,
-141,
-247,
-253,
-82,
-6,
-166,
-148,
-11,
-137,
-236,
-78,
-234,
-95,
-244,
-139,
-84,
-88,
-219,
-178,
-63,
-44,
-230,
-36,
-251,
-199,
-42,
-58,
-63,
-239,
-154,
-1,
-156,
-102,
-87,
-76,
-249,
-4,
-137,
-249,
-144,
-26,
-1,
-83,
-194,
-156,
-154,
-64,
-247,
-117,
-224,
-8,
-76,
-149,
-185,
-10,
-54,
-135,
-22,
-174,
-42,
-48,
-85,
-244,
-109,
-192,
-87,
-10,
-238,
-191,
-204,
-96,
-159,
-197,
-109,
-129,
-215,
-154,
-61,
-69,
-79,
-60,
-184,
-94,
-0,
-0,
-18,
-40,
-73,
-68,
-65,
-84,
-251,
-200,
-49,
-192,
-115,
-192,
-7,
-170,
-232,
-252,
-188,
-200,
-239,
-98,
-69,
-76,
-178,
-159,
-226,
-101,
-30,
-163,
-64,
-238,
-201,
-149,
-251,
-36,
-53,
-118,
-111,
-205,
-218,
-2,
-82,
-57,
-115,
-13,
-73,
-149,
-203,
-195,
-16,
-194,
-81,
-33,
-132,
-111,
-134,
-16,
-38,
-133,
-16,
-30,
-144,
-237,
-23,
-92,
-54,
-2,
-252,
-135,
-108,
-31,
-194,
-175,
-22,
-220,
-207,
-247,
-101,
-94,
-73,
-175,
-87,
-245,
-99,
-152,
-48,
-70,
-233,
-190,
-121,
-69,
-116,
-157,
-60,
-74,
-239,
-147,
-244,
-188,
-164,
-93,
-36,
-253,
-45,
-79,
-132,
-173,
-253,
-247,
-195,
-54,
-201,
-88,
-92,
-182,
-181,
-221,
-16,
-5,
-94,
-17,
-154,
-40,
-52,
-130,
-226,
-102,
-201,
-40,
-48,
-231,
-142,
-119,
-201,
-12,
-30,
-81,
-243,
-40,
-230,
-17,
-115,
-138,
-164,
-207,
-135,
-16,
-138,
-180,
-113,
-79,
-203,
-28,
-58,
-59,
-88,
-212,
-175,
-141,
-68,
-156,
-45,
-233,
-187,
-192,
-191,
-66,
-8,
-249,
-101,
-94,
-146,
-81,
-75,
-182,
-41,
-247,
-255,
-132,
-16,
-238,
-4,
-8,
-33,
-220,
-86,
-210,
-222,
-161,
-50,
-195,
-82,
-144,
-52,
-81,
-210,
-190,
-181,
-123,
-92,
-99,
-104,
-186,
-139,
-136,
-249,
-178,
-164,
-78,
-48,
-1,
-233,
-28,
-10,
-220,
-165,
-176,
-181,
-235,
-109,
-148,
-44,
-59,
-49,
-161,
-237,
-212,
-204,
-249,
-233,
-84,
-11,
-102,
-125,
-219,
-166,
-62,
-55,
-5,
-4,
-151,
-47,
-254,
-26,
-161,
-75,
-53,
-106,
-77,
-192,
-220,
-237,
-30,
-197,
-150,
-150,
-221,
-229,
-1,
-174,
-243,
-0,
-126,
-94,
-196,
-0,
-31,
-193,
-92,
-164,
-14,
-192,
-92,
-167,
-86,
-195,
-118,
-167,
-140,
-213,
-185,
-152,
-207,
-101,
-31,
-196,
-116,
-253,
-223,
-143,
-208,
-140,
-245,
-249,
-189,
-116,
-183,
-76,
-204,
-104,
-244,
-12,
-166,
-60,
-121,
-47,
-166,
-175,
-56,
-168,
-162,
-204,
-21,
-88,
-58,
-150,
-40,
-99,
-81,
-99,
-107,
-122,
-42,
-182,
-164,
-143,
-188,
-191,
-9,
-192,
-16,
-239,
-99,
-18,
-141,
-90,
-78,
-59,
-47,
-102,
-163,
-152,
-137,
-41,
-121,
-26,
-219,
-72,
-42,
-17,
-121,
-128,
-66,
-135,
-11,
-44,
-140,
-60,
-187,
-12,
-188,
-60,
-70,
-151,
-43,
-179,
-47,
-145,
-120,
-60,
-44,
-173,
-203,
-101,
-164,
-133,
-87,
-127,
-145,
-1,
-69,
-213,
-233,
-116,
-153,
-24,
-153,
-196,
-173,
-233,
-73,
-216,
-146,
-62,
-55,
-2,
-108,
-134,
-105,
-23,
-155,
-121,
-232,
-14,
-173,
-251,
-57,
-10,
-140,
-115,
-173,
-193,
-31,
-32,
-235,
-236,
-121,
-120,
-17,
-3,
-228,
-202,
-36,
-41,
-130,
-176,
-244,
-48,
-49,
-171,
-92,
-20,
-245,
-159,
-96,
-80,
-157,
-149,
-78,
-166,
-109,
-35,
-199,
-0,
-19,
-177,
-81,
-114,
-136,
-215,
-113,
-141,
-250,
-254,
-11,
-27,
-233,
-222,
-234,
-117,
-157,
-69,
-36,
-99,
-121,
-107,
-240,
-7,
-200,
-206,
-77,
-15,
-116,
-243,
-67,
-248,
-215,
-250,
-78,
-44,
-213,
-250,
-54,
-36,
-6,
-110,
-118,
-11,
-18,
-157,
-76,
-157,
-54,
-197,
-27,
-121,
-127,
-76,
-203,
-247,
-146,
-255,
-47,
-220,
-168,
-185,
-77,
-96,
-166,
-246,
-71,
-49,
-211,
-251,
-27,
-254,
-28,
-27,
-20,
-208,
-110,
-129,
-5,
-235,
-118,
-204,
-193,
-73,
-50,
-90,
-190,
-18,
-48,
-109,
-219,
-11,
-192,
-189,
-152,
-121,
-177,
-27,
-6,
-184,
-16,
-211,
-78,
-189,
-234,
-204,
-244,
-101,
-250,
-16,
-54,
-141,
-237,
-154,
-113,
-72,
-230,
-124,
-15,
-224,
-225,
-8,
-93,
-170,
-55,
-242,
-54,
-152,
-60,
-180,
-4,
-182,
-81,
-228,
-255,
-244,
-250,
-25,
-34,
-125,
-168,
-210,
-4,
-62,
-132,
-237,
-243,
-180,
-24,
-150,
-225,
-116,
-124,
-147,
-70,
-160,
-124,
-111,
-251,
-57,
-2,
-164,
-59,
-153,
-38,
-49,
-74,
-174,
-204,
-22,
-68,
-92,
-179,
-107,
-246,
-47,
-41,
-9,
-86,
-174,
-76,
-21,
-3,
-60,
-5,
-28,
-219,
-77,
-191,
-134,
-8,
-129,
-35,
-21,
-84,
-44,
-237,
-48,
-129,
-105,
-111,
-42,
-132,
-202,
-26,
-140,
-50,
-214,
-135,
-227,
-39,
-241,
-189,
-4,
-122,
-241,
-92,
-221,
-0,
-19,
-176,
-103,
-0,
-127,
-198,
-183,
-252,
-105,
-82,
-73,
-45,
-6,
-160,
-98,
-89,
-84,
-179,
-221,
-221,
-72,
-136,
-129,
-115,
-250,
-170,
-165,
-93,
-170,
-147,
-105,
-42,
-163,
-252,
-5,
-243,
-143,
-92,
-15,
-91,
-218,
-165,
-134,
-163,
-245,
-53,
-112,
-5,
-147,
-181,
-78,
-195,
-150,
-151,
-69,
-94,
-198,
-173,
-53,
-86,
-185,
-44,
-170,
-81,
-23,
-152,
-67,
-106,
-101,
-12,
-92,
-98,
-125,
-169,
-78,
-166,
-169,
-140,
-50,
-3,
-247,
-247,
-119,
-134,
-25,
-145,
-12,
-144,
-105,
-247,
-195,
-20,
-152,
-181,
-251,
-221,
-145,
-249,
-177,
-180,
-104,
-51,
-48,
-97,
-235,
-253,
-177,
-23,
-226,
-12,
-144,
-18,
-3,
-55,
-104,
-132,
-42,
-123,
-193,
-36,
-56,
-153,
-214,
-96,
-148,
-251,
-49,
-211,
-243,
-242,
-62,
-26,
-140,
-40,
-6,
-192,
-4,
-191,
-15,
-99,
-182,
-128,
-37,
-48,
-79,
-237,
-59,
-122,
-217,
-96,
-210,
-15,
-129,
-217,
-165,
-31,
-194,
-188,
-84,
-214,
-197,
-252,
-214,
-138,
-24,
-32,
-37,
-6,
-46,
-153,
-1,
-106,
-60,
-75,
-10,
-163,
-124,
-8,
-243,
-25,
-124,
-12,
-83,
-198,
-12,
-73,
-1,
-231,
-116,
-89,
-134,
-159,
-236,
-140,
-92,
-217,
-63,
-204,
-185,
-101,
-136,
-74,
-155,
-193,
-129,
-58,
-207,
-98,
-190,
-141,
-177,
-228,
-147,
-139,
-98,
-102,
-247,
-23,
-48,
-129,
-242,
-58,
-224,
-29,
-169,
-239,
-160,
-54,
-106,
-48,
-192,
-36,
-50,
-91,
-190,
-224,
-169,
-81,
-10,
-234,
-203,
-154,
-121,
-63,
-16,
-123,
-201,
-189,
-96,
-128,
-54,
-17,
-97,
-248,
-127,
-149,
-245,
-15,
-155,
-62,
-47,
-246,
-15,
-99,
-136,
-241,
-134,
-193,
-129,
-58,
-107,
-251,
-113,
-235,
-62,
-154,
-85,
-94,
-176,
-221,
-248,
-4,
-142,
-211,
-224,
-144,
-177,
-178,
-140,
-24,
-43,
-103,
-142,
-87,
-171,
-160,
-29,
-169,
-216,
-87,
-150,
-12,
-243,
-158,
-16,
-194,
-93,
-146,
-138,
-108,
-6,
-203,
-97,
-17,
-67,
-151,
-72,
-250,
-173,
-164,
-117,
-67,
-8,
-67,
-34,
-151,
-36,
-29,
-144,
-169,
-239,
-30,
-89,
-130,
-201,
-131,
-218,
-238,
-244,
-160,
-31,
-152,
-92,
-170,
-88,
-73,
-55,
-118,
-81,
-247,
-171,
-210,
-32,
-179,
-241,
-204,
-18,
-218,
-38,
-49,
-112,
-35,
-45,
-141,
-91,
-42,
-195,
-79,
-150,
-180,
-130,
-164,
-119,
-135,
-16,
-126,
-26,
-203,
-197,
-236,
-88,
-89,
-210,
-3,
-185,
-250,
-74,
-61,
-170,
-154,
-160,
-81,
-170,
-216,
-28,
-138,
-126,
-136,
-71,
-52,
-248,
-203,
-46,
-203,
-187,
-115,
-129,
-164,
-203,
-100,
-182,
-236,
-107,
-20,
-73,
-247,
-170,
-116,
-59,
-122,
-45,
-43,
-95,
-139,
-72,
-101,
-248,
-141,
-100,
-161,
-227,
-119,
-96,
-22,
-213,
-162,
-140,
-34,
-111,
-104,
-112,
-90,
-221,
-222,
-123,
-104,
-167,
-12,
-249,
-46,
-104,
-84,
-26,
-141,
-128,
-207,
-97,
-42,
-229,
-53,
-49,
-147,
-241,
-173,
-37,
-50,
-64,
-74,
-58,
-180,
-36,
-59,
-186,
-211,
-86,
-90,
-249,
-48,
-255,
-132,
-231,
-177,
-37,
-232,
-62,
-152,
-4,
-253,
-229,
-46,
-250,
-119,
-87,
-86,
-136,
-164,
-66,
-149,
-142,
-121,
-55,
-95,
-238,
-178,
-210,
-144,
-20,
-59,
-216,
-166,
-22,
-71,
-103,
-206,
-163,
-129,
-58,
-88,
-112,
-75,
-212,
-70,
-80,
-11,
-36,
-26,
-61,
-82,
-127,
-8,
-76,
-177,
-242,
-83,
-204,
-64,
-113,
-63,
-190,
-45,
-125,
-132,
-46,
-245,
-5,
-39,
-219,
-209,
-83,
-0,
-156,
-138,
-5,
-184,
-238,
-131,
-249,
-213,
-191,
-72,
-36,
-147,
-119,
-141,
-254,
-229,
-25,
-126,
-98,
-74,
-255,
-128,
-77,
-137,
-120,
-241,
-2,
-135,
-248,
-123,
-235,
-8,
-129,
-209,
-64,
-29,
-76,
-11,
-120,
-15,
-150,
-0,
-59,
-26,
-167,
-153,
-4,
-18,
-141,
-30,
-77,
-127,
-8,
-138,
-87,
-11,
-73,
-47,
-56,
-21,
-249,
-250,
-138,
-218,
-109,
-90,
-95,
-9,
-93,
-158,
-225,
-119,
-239,
-178,
-221,
-128,
-237,
-199,
-52,
-141,
-138,
-64,
-29,
-108,
-201,
-184,
-191,
-51,
-242,
-119,
-128,
-101,
-155,
-182,
-219,
-169,
-176,
-107,
-163,
-71,
-164,
-206,
-126,
-41,
-70,
-122,
-193,
-0,
-71,
-210,
-239,
-157,
-185,
-26,
-0,
-120,
-19,
-150,
-243,
-32,
-57,
-197,
-111,
-214,
-43,
-120,
-182,
-209,
-67,
-182,
-11,
-70,
-95,
-247,
-192,
-29,
-225,
-56,
-92,
-210,
-33,
-178,
-93,
-73,
-158,
-144,
-229,
-228,
-27,
-49,
-192,
-100,
-158,
-3,
-36,
-221,
-46,
-233,
-53,
-153,
-160,
-89,
-187,
-146,
-70,
-70,
-143,
-145,
-134,
-30,
-141,
-0,
-61,
-79,
-162,
-221,
-20,
-216,
-74,
-98,
-18,
-230,
-86,
-215,
-60,
-7,
-51,
-13,
-141,
-30,
-253,
-6,
-245,
-157,
-51,
-187,
-74,
-38,
-229,
-245,
-245,
-60,
-137,
-118,
-83,
-96,
-78,
-60,
-155,
-54,
-45,
-159,
-21,
-42,
-30,
-151,
-180,
-49,
-150,
-219,
-174,
-112,
-99,
-167,
-130,
-78,
-52,
-94,
-163,
-250,
-11,
-78,
-205,
-36,
-242,
-93,
-89,
-14,
-222,
-53,
-36,
-45,
-77,
-220,
-10,
-217,
-11,
-125,
-65,
-146,
-60,
-132,
-37,
-153,
-56,
-20,
-216,
-147,
-72,
-242,
-199,
-58,
-72,
-21,
-62,
-67,
-8,
-219,
-68,
-242,
-17,
-55,
-106,
-48,
-201,
-232,
-225,
-180,
-201,
-155,
-75,
-37,
-180,
-155,
-204,
-0,
-137,
-245,
-181,
-173,
-47,
-72,
-158,
-82,
-176,
-112,
-181,
-89,
-152,
-175,
-193,
-184,
-46,
-159,
-35,
-137,
-1,
-134,
-5,
-46,
-9,
-175,
-236,
-12,
-240,
-28,
-112,
-68,
-1,
-221,
-170,
-192,
-245,
-152,
-110,
-225,
-62,
-96,
-255,
-8,
-77,
-7,
-165,
-105,
-221,
-72,
-183,
-142,
-181,
-173,
-47,
-168,
-195,
-0,
-151,
-96,
-145,
-193,
-151,
-23,
-140,
-78,
-117,
-219,
-237,
-139,
-3,
-106,
-109,
-164,
-14,
-249,
-152,
-139,
-210,
-165,
-88,
-36,
-238,
-22,
-192,
-187,
-35,
-52,
-144,
-150,
-214,
-173,
-85,
-235,
-88,
-13,
-134,
-74,
-102,
-128,
-12,
-205,
-130,
-152,
-71,
-111,
-227,
-47,
-216,
-219,
-61,
-154,
-68,
-79,
-169,
-190,
-33,
-245,
-197,
-57,
-237,
-12,
-96,
-231,
-138,
-250,
-96,
-112,
-86,
-175,
-253,
-137,
-103,
-39,
-155,
-157,
-198,
-206,
-207,
-63,
-77,
-119,
-83,
-79,
-219,
-12,
-181,
-16,
-230,
-15,
-240,
-44,
-166,
-8,
-186,
-22,
-248,
-65,
-23,
-245,
-65,
-13,
-79,
-41,
-170,
-125,
-37,
-219,
-201,
-75,
-84,
-231,
-197,
-249,
-67,
-140,
-175,
-168,
-47,
-207,
-0,
-69,
-105,
-221,
-166,
-147,
-9,
-65,
-195,
-28,
-71,
-186,
-201,
-98,
-214,
-54,
-67,
-157,
-137,
-169,
-208,
-215,
-240,
-247,
-114,
-15,
-5,
-89,
-66,
-18,
-235,
-131,
-4,
-79,
-169,
-204,
-253,
-42,
-95,
-201,
-234,
-188,
-68,
-41,
-92,
-82,
-231,
-197,
-213,
-96,
-128,
-148,
-180,
-110,
-211,
-128,
-236,
-246,
-40,
-221,
-166,
-177,
-107,
-155,
-161,
-166,
-228,
-126,
-176,
-131,
-40,
-200,
-18,
-146,
-88,
-31,
-12,
-94,
-126,
-70,
-61,
-165,
-186,
-69,
-158,
-91,
-178,
-38,
-204,
-89,
-5,
-101,
-146,
-236,
-212,
-12,
-172,
-34,
-254,
-140,
-185,
-92,
-149,
-249,
-3,
-252,
-65,
-210,
-51,
-178,
-188,
-185,
-23,
-73,
-138,
-249,
-184,
-223,
-39,
-219,
-242,
-165,
-131,
-85,
-84,
-226,
-56,
-82,
-53,
-36,
-170,
-125,
-115,
-235,
-91,
-101,
-90,
-194,
-14,
-158,
-145,
-45,
-73,
-219,
-66,
-52,
-91,
-56,
-9,
-70,
-188,
-50,
-154,
-65,
-15,
-29,
-66,
-88,
-63,
-132,
-112,
-91,
-8,
-97,
-98,
-8,
-161,
-200,
-175,
-44,
-233,
-197,
-133,
-16,
-58,
-46,
-214,
-219,
-134,
-16,
-230,
-13,
-33,
-148,
-229,
-34,
-216,
-222,
-105,
-198,
-133,
-16,
-78,
-8,
-33,
-196,
-50,
-127,
-156,
-39,
-233,
-176,
-206,
-212,
-35,
-233,
-147,
-178,
-77,
-160,
-138,
-112,
-129,
-164,
-159,
-73,
-42,
-218,
-233,
-35,
-153,
-161,
-18,
-231,
-207,
-71,
-37,
-45,
-151,
-57,
-31,
-39,
-115,
-254,
-232,
-6,
-41,
-158,
-82,
-79,
-200,
-156,
-104,
-86,
-148,
-169,
-240,
-99,
-106,
-234,
-20,
-26,
-137,
-180,
-88,
-185,
-84,
-59,
-245,
-252,
-62,
-140,
-149,
-234,
-165,
-243,
-50,
-64,
-9,
-93,
-178,
-117,
-44,
-5,
-36,
-154,
-91,
-157,
-182,
-114,
-254,
-4,
-190,
-128,
-173,
-96,
-58,
-66,
-219,
-100,
-42,
-194,
-215,
-43,
-250,
-135,
-183,
-187,
-38,
-176,
-22,
-240,
-32,
-240,
-153,
-138,
-50,
-149,
-70,
-188,
-66,
-26,
-210,
-99,
-229,
-82,
-237,
-212,
-251,
-49,
-32,
-20,
-205,
-78,
-182,
-156,
-240,
-236,
-93,
-129,
-244,
-229,
-93,
-219,
-12,
-53,
-63,
-38,
-8,
-62,
-225,
-245,
-157,
-22,
-107,
-183,
-70,
-125,
-175,
-99,
-91,
-249,
-150,
-102,
-11,
-39,
-33,
-114,
-41,
-133,
-70,
-164,
-7,
-85,
-38,
-189,
-56,
-10,
-208,
-232,
-109,
-212,
-0,
-195,
-164,
-47,
-24,
-46,
-144,
-96,
-196,
-75,
-161,
-17,
-137,
-177,
-114,
-35,
-29,
-140,
-112,
-125,
-65,
-219,
-32,
-193,
-136,
-87,
-70,
-147,
-223,
-147,
-38,
-101,
-231,
-142,
-145,
-142,
-182,
-189,
-105,
-251,
-226,
-158,
-221,
-5,
-82,
-140,
-120,
-213,
-52,
-36,
-198,
-202,
-245,
-27,
-62,
-4,
-127,
-25,
-91,
-103,
-191,
-72,
-197,
-14,
-89,
-140,
-112,
-125,
-65,
-219,
-32,
-193,
-136,
-151,
-66,
-35,
-18,
-99,
-229,
-250,
-13,
-224,
-40,
-108,
-101,
-50,
-1,
-75,
-56,
-89,
-149,
-76,
-42,
-105,
-149,
-82,
-163,
-253,
-70,
-12,
-69,
-130,
-169,
-25,
-115,
-72,
-189,
-39,
-161,
-174,
-9,
-254,
-129,
-150,
-230,
-17,
-232,
-26,
-212,
-216,
-185,
-131,
-132,
-240,
-112,
-224,
-91,
-153,
-227,
-111,
-84,
-220,
-31,
-162,
-253,
-243,
-235,
-183,
-147,
-176,
-33,
-99,
-134,
-62,
-121,
-121,
-151,
-88,
-95,
-35,
-134,
-34,
-205,
-212,
-188,
-31,
-80,
-169,
-43,
-192,
-18,
-64,
-156,
-76,
-127,
-54,
-191,
-170,
-6,
-105,
-89,
-179,
-182,
-0,
-206,
-247,
-227,
-205,
-128,
-239,
-69,
-104,
-190,
-207,
-64,
-98,
-165,
-243,
-137,
-120,
-182,
-96,
-75,
-160,
-104,
-218,
-213,
-130,
-190,
-13,
-155,
-190,
-160,
-87,
-240,
-15,
-109,
-124,
-63,
-219,
-236,
-26,
-152,
-143,
-218,
-134,
-249,
-227,
-28,
-205,
-134,
-157,
-57,
-221,
-143,
-127,
-31,
-161,
-121,
-53,
-59,
-4,
-247,
-27,
-77,
-24,
-138,
-244,
-24,
-139,
-13,
-128,
-202,
-116,
-183,
-206,
-0,
-133,
-155,
-89,
-116,
-131,
-70,
-95,
-6,
-105,
-105,
-216,
-230,
-41,
-56,
-46,
-163,
-139,
-169,
-139,
-31,
-80,
-205,
-45,
-209,
-219,
-68,
-8,
-129,
-16,
-194,
-151,
-66,
-8,
-139,
-251,
-223,
-137,
-37,
-241,
-124,
-29,
-164,
-169,
-94,
-165,
-93,
-53,
-120,
-197,
-50,
-8,
-152,
-95,
-193,
-129,
-50,
-27,
-77,
-105,
-254,
-162,
-146,
-58,
-90,
-221,
-158,
-166,
-142,
-198,
-112,
-171,
-204,
-20,
-48,
-123,
-58,
-200,
-209,
-124,
-31,
-216,
-210,
-143,
-207,
-39,
-226,
-64,
-129,
-69,
-20,
-61,
-142,
-185,
-91,
-173,
-74,
-65,
-86,
-210,
-145,
-10,
-10,
-84,
-175,
-192,
-58,
-152,
-215,
-210,
-129,
-37,
-101,
-193,
-164,
-247,
-198,
-35,
-32,
-169,
-219,
-211,
-144,
-184,
-220,
-162,
-70,
-118,
-45,
-50,
-187,
-112,
-17,
-17,
-22,
-169,
-16,
-18,
-253,
-250,
-60,
-152,
-38,
-110,
-42,
-166,
-208,
-24,
-178,
-153,
-196,
-72,
-3,
-105,
-234,
-217,
-75,
-171,
-158,
-5,
-179,
-104,
-30,
-139,
-41,
-233,
-150,
-232,
-93,
-143,
-149,
-190,
-220,
-98,
-4,
-106,
-12,
-201,
-8,
-138,
-20,
-8,
-141,
-62,
-143,
-79,
-194,
-86,
-57,
-189,
-203,
-185,
-171,
-100,
-245,
-236,
-244,
-148,
-121,
-29,
-203,
-23,
-12,
-176,
-69,
-131,
-126,
-108,
-130,
-173,
-253,
-241,
-81,
-180,
-216,
-199,
-144,
-196,
-229,
-22,
-137,
-217,
-181,
-250,
-9,
-127,
-200,
-45,
-242,
-199,
-57,
-154,
-77,
-129,
-5,
-48,
-199,
-147,
-194,
-36,
-74,
-88,
-142,
-223,
-117,
-75,
-238,
-167,
-216,
-223,
-83,
-212,
-179,
-47,
-146,
-152,
-151,
-209,
-127,
-192,
-241,
-41,
-180,
-145,
-178,
-99,
-189,
-124,
-212,
-16,
-151,
-21,
-2,
-87,
-151,
-84,
-232,
-114,
-148,
-193,
-100,
-89,
-86,
-139,
-87,
-178,
-127,
-77,
-58,
-215,
-34,
-158,
-245,
-191,
-252,
-241,
-108,
-132,
-16,
-110,
-10,
-33,
-188,
-44,
-105,
-99,
-21,
-36,
-190,
-192,
-172,
-109,
-71,
-75,
-90,
-172,
-164,
-173,
-20,
-1,
-47,
-69,
-61,
-123,
-147,
-164,
-99,
-48,
-185,
-102,
-107,
-224,
-240,
-146,
-54,
-123,
-15,
-18,
-151,
-91,
-140,
-64,
-141,
-33,
-150,
-24,
-105,
-217,
-252,
-113,
-132,
-110,
-83,
-204,
-89,
-51,
-186,
-247,
-31,
-3,
-123,
-238,
-60,
-133,
-201,
-28,
-165,
-31,
-4,
-197,
-2,
-94,
-138,
-122,
-118,
-101,
-44,
-170,
-231,
-37,
-76,
-183,
-80,
-168,
-134,
-247,
-169,
-235,
-44,
-26,
-200,
-1,
-85,
-35,
-64,
-150,
-240,
-30,
-224,
-184,
-196,
-74,
-187,
-218,
-235,
-151,
-8,
-34,
-52,
-233,
-243,
-87,
-90,
-155,
-219,
-96,
-49,
-244,
-11,
-39,
-244,
-173,
-208,
-157,
-155,
-97,
-200,
-28,
-138,
-233,
-11,
-254,
-66,
-131,
-152,
-196,
-58,
-12,
-208,
-183,
-229,
-150,
-119,
-104,
-208,
-190,
-194,
-5,
-116,
-105,
-157,
-79,
-107,
-243,
-101,
-204,
-148,
-59,
-201,
-255,
-162,
-158,
-74,
-9,
-12,
-80,
-41,
-224,
-141,
-36,
-84,
-189,
-195,
-172,
-226,
-229,
-44,
-153,
-99,
-227,
-143,
-37,
-45,
-33,
-233,
-247,
-254,
-215,
-43,
-188,
-222,
-79,
-217,
-33,
-132,
-208,
-86,
-82,
-169,
-141,
-36,
-237,
-229,
-123,
-249,
-172,
-221,
-82,
-157,
-195,
-134,
-217,
-66,
-96,
-8,
-97,
-86,
-8,
-225,
-216,
-16,
-194,
-10,
-178,
-132,
-77,
-61,
-223,
-233,
-123,
-14,
-69,
-227,
-32,
-218,
-57,
-6,
-192,
-210,
-68,
-182,
-119,
-105,
-177,
-254,
-74,
-25,
-192,
-233,
-42,
-167,
-0,
-90,
-206,
-8,
-134,
-109,
-206,
-176,
-101,
-201,
-253,
-228,
-32,
-218,
-132,
-182,
-160,
-197,
-192,
-216,
-130,
-54,
-234,
-77,
-163,
-192,
-95,
-49,
-19,
-232,
-39,
-11,
-238,
-39,
-101,
-9,
-199,
-76,
-161,
-215,
-3,
-167,
-71,
-238,
-181,
-38,
-3,
-144,
-184,
-239,
-79,
-42,
-48,
-111,
-222,
-51,
-129,
-69,
-128,
-229,
-170,
-75,
-116,
-213,
-86,
-33,
-3,
-84,
-49,
-54,
-166,
-71,
-184,
-25,
-216,
-190,
-164,
-254,
-77,
-48,
-33,
-29,
-103,
-216,
-238,
-130,
-77,
-169,
-145,
-37,
-28,
-183,
-153,
-3,
-255,
-136,
-220,
-75,
-226,
-252,
-218,
-220,
-91,
-94,
-87,
-210,
-22,
-114,
-152,
-13,
-99,
-18,
-230,
-149,
-219,
-120,
-107,
-218,
-196,
-62,
-149,
-49,
-64,
-41,
-99,
-99,
-91,
-218,
-126,
-25,
-75,
-233,
-51,
-242,
-224,
-35,
-197,
-117,
-196,
-13,
-69,
-173,
-48,
-0,
-17,
-148,
-212,
-85,
-26,
-59,
-55,
-28,
-72,
-125,
-15,
-37,
-229,
-199,
-151,
-61,
-115,
-207,
-224,
-29,
-239,
-54,
-244,
-185,
-235,
-41,
-32,
-181,
-158,
-145,
-138,
-34,
-6,
-32,
-81,
-7,
-50,
-34,
-25,
-128,
-52,
-93,
-121,
-229,
-151,
-75,
-194,
-252,
-149,
-242,
-5,
-213,
-25,
-37,
-218,
-0,
-53,
-236,
-239,
-101,
-253,
-175,
-98,
-254,
-12,
-205,
-235,
-192,
-129,
-64,
-163,
-101,
-110,
-62,
-89,
-244,
-78,
-88,
-182,
-203,
-87,
-129,
-235,
-155,
-84,
-168,
-4,
-93,
-121,
-136,
-32,
-66,
-115,
-115,
-8,
-97,
-5,
-191,
-189,
-124,
-8,
-97,
-200,
-198,
-201,
-53,
-176,
-179,
-6,
-187,
-187,
-247,
-18,
-41,
-1,
-182,
-173,
-32,
-132,
-48,
-69,
-210,
-30,
-50,
-29,
-78,
-101,
-36,
-114,
-229,
-71,
-128,
-237,
-85,
-123,
-18,
-182,
-9,
-65,
-97,
-182,
-201,
-178,
-17,
-32,
-71,
-215,
-122,
-194,
-201,
-72,
-63,
-170,
-70,
-146,
-202,
-81,
-194,
-233,
-170,
-178,
-143,
-125,
-17,
-91,
-33,
-188,
-132,
-173,
-148,
-186,
-86,
-2,
-181,
-48,
-2,
-44,
-129,
-153,
-231,
-143,
-37,
-109,
-251,
-219,
-78,
-220,
-226,
-154,
-157,
-107,
-121,
-129,
-104,
-5,
-73,
-215,
-132,
-16,
-166,
-135,
-16,
-158,
-80,
-3,
-208,
-255,
-132,
-147,
-93,
-127,
-221,
-164,
-101,
-31,
-123,
-70,
-22,
-145,
-252,
-14,
-89,
-100,
-241,
-144,
-200,
-228,
-126,
-79,
-55,
-146,
-214,
-145,
-237,
-168,
-126,
-86,
-8,
-225,
-153,
-42,
-226,
-16,
-194,
-164,
-206,
-223,
-144,
-155,
-88,
-98,
-35,
-112,
-75,
-88,
-89,
-69,
-101,
-35,
-0,
-125,
-212,
-149,
-167,
-124,
-221,
-189,
-248,
-81,
-48,
-7,
-214,
-162,
-93,
-77,
-146,
-133,
-210,
-22,
-70,
-128,
-174,
-133,
-192,
-172,
-42,
-120,
-23,
-63,
-220,
-221,
-213,
-193,
-77,
-177,
-145,
-164,
-175,
-135,
-16,
-238,
-84,
-129,
-93,
-29,
-248,
-33,
-112,
-35,
-22,
-199,
-119,
-66,
-228,
-254,
-246,
-126,
-255,
-111,
-180,
-227,
-14,
-93,
-58,
-74,
-52,
-96,
-146,
-247,
-72,
-122,
-168,
-224,
-222,
-235,
-41,
-126,
-18,
-12,
-56,
-210,
-118,
-19,
-101,
-212,
-110,
-144,
-106,
-217,
-151,
-157,
-74,
-71,
-194,
-46,
-91,
-192,
-124,
-254,
-127,
-94,
-226,
-249,
-128,
-110,
-195,
-20,
-29,
-75,
-2,
-255,
-172,
-232,
-71,
-233,
-23,
-87,
-99,
-148,
-72,
-250,
-114,
-125,
-100,
-123,
-30,
-216,
-175,
-97,
-91,
-203,
-96,
-94,
-73,
-39,
-97,
-171,
-155,
-104,
-230,
-175,
-170,
-17,
-0,
-155,
-255,
-191,
-65,
-133,
-207,
-66,
-45,
-164,
-50,
-64,
-69,
-29,
-41,
-206,
-16,
-159,
-192,
-66,
-157,
-174,
-35,
-238,
-80,
-49,
-37,
-118,
-92,
-208,
-223,
-210,
-47,
-183,
-6,
-3,
-164,
-102,
-43,
-189,
-25,
-248,
-97,
-23,
-253,
-153,
-142,
-169,
-113,
-175,
-39,
-18,
-43,
-145,
-161,
-171,
-98,
-128,
-23,
-48,
-231,
-150,
-230,
-249,
-129,
-11,
-30,
-160,
-231,
-217,
-41,
-49,
-149,
-236,
-155,
-253,
-75,
-24,
-178,
-124,
-193,
-166,
-134,
-37,
-48,
-245,
-237,
-109,
-93,
-182,
-85,
-249,
-117,
-215,
-100,
-128,
-153,
-148,
-251,
-18,
-116,
-173,
-152,
-162,
-109,
-29,
-126,
-141,
-134,
-251,
-197,
-0,
-231,
-96,
-6,
-167,
-223,
-19,
-223,
-36,
-114,
-107,
-76,
-6,
-184,
-145,
-76,
-166,
-172,
-134,
-109,
-165,
-142,
-18,
-165,
-52,
-53,
-218,
-234,
-169,
-117,
-175,
-167,
-232,
-23,
-3,
-140,
-52,
-212,
-249,
-114,
-49,
-69,
-217,
-222,
-37,
-245,
-204,
-81,
-12,
-208,
-52,
-52,
-44,
-201,
-178,
-54,
-135,
-33,
-73,
-122,
-87,
-181,
-228,
-61,
-95,
-183,
-83,
-192,
-136,
-7,
-213,
-89,
-41,
-91,
-217,
-89,
-188,
-162,
-15,
-251,
-249,
-124,
-220,
-181,
-16,
-212,
-214,
-151,
-91,
-103,
-42,
-1,
-62,
-6,
-252,
-185,
-219,
-54,
-11,
-234,
-190,
-24,
-184,
-164,
-23,
-117,
-167,
-52,
-222,
-218,
-206,
-226,
-37,
-109,
-28,
-136,
-45,
-55,
-95,
-109,
-145,
-1,
-250,
-102,
-85,
-196,
-18,
-99,
-79,
-163,
-100,
-163,
-7,
-239,
-199,
-195,
-192,
-123,
-234,
-220,
-243,
-251,
-189,
-241,
-232,
-162,
-69,
-87,
-109,
-74,
-60,
-94,
-170,
-166,
-24,
-103,
-176,
-85,
-48,
-75,
-216,
-16,
-6,
-192,
-118,
-61,
-123,
-8,
-243,
-2,
-62,
-51,
-161,
-47,
-201,
-95,
-110,
-27,
-240,
-175,
-191,
-52,
-49,
-68,
-83,
-6,
-160,
-194,
-163,
-171,
-107,
-80,
-189,
-62,
-77,
-181,
-101,
-23,
-122,
-188,
-144,
-232,
-188,
-225,
-109,
-196,
-24,
-96,
-77,
-175,
-127,
-93,
-224,
-209,
-212,
-103,
-235,
-23,
-176,
-192,
-208,
-115,
-170,
-41,
-251,
-136,
-178,
-47,
-50,
-71,
-151,
-106,
-167,
-46,
-165,
-105,
-3,
-69,
-12,
-224,
-247,
-174,
-195,
-242,
-23,
-124,
-164,
-151,
-125,
-104,
-2,
-204,
-234,
-250,
-209,
-4,
-58,
-40,
-214,
-184,
-22,
-222,
-171,
-131,
-236,
-23,
-118,
-128,
-164,
-159,
-43,
-109,
-227,
-230,
-86,
-80,
-244,
-16,
-109,
-60,
-92,
-8,
-97,
-43,
-73,
-235,
-75,
-58,
-173,
-155,
-122,
-98,
-160,
-194,
-233,
-195,
-251,
-191,
-62,
-166,
-210,
-126,
-58,
-82,
-197,
-210,
-50,
-235,
-226,
-176,
-99,
-118,
-96,
-72,
-8,
-97,
-150,
-164,
-163,
-74,
-104,
-231,
-24,
-0,
-43,
-134,
-16,
-30,
-149,
-25,
-163,
-26,
-167,
-108,
-47,
-65,
-138,
-211,
-199,
-143,
-37,
-157,
-44,
-41,
-230,
-21,
-20,
-100,
-73,
-183,
-135,
-29,
-35,
-198,
-65,
-178,
-101,
-252,
-10,
-184,
-79,
-210,
-197,
-138,
-4,
-111,
-96,
-18,
-255,
-195,
-46,
-40,
-78,
-136,
-220,
-47,
-253,
-194,
-19,
-179,
-170,
-255,
-44,
-132,
-240,
-235,
-16,
-66,
-76,
-216,
-251,
-183,
-164,
-158,
-239,
-108,
-78,
-66,
-130,
-173,
-178,
-20,
-238,
-115,
-44,
-66,
-8,
-27,
-87,
-144,
-156,
-39,
-105,
-127,
-73,
-79,
-75,
-186,
-66,
-150,
-218,
-61,
-139,
-54,
-220,
-186,
-162,
-123,
-47,
-59,
-110,
-147,
-57,
-150,
-244,
-26,
-209,
-80,
-249,
-44,
-230,
-74,
-6,
-72,
-192,
-24,
-217,
-143,
-60,
-83,
-17,
-205,
-94,
-8,
-33,
-187,
-55,
-112,
-211,
-31,
-170,
-76,
-155,
-120,
-165,
-164,
-126,
-164,
-154,
-171,
-100,
-128,
-236,
-222,
-193,
-147,
-128,
-189,
-122,
-222,
-165,
-22,
-225,
-14,
-163,
-77,
-172,
-133,
-31,
-151,
-244,
-11,
-73,
-87,
-169,
-32,
-190,
-175,
-45,
-41,
-187,
-0,
-23,
-72,
-90,
-145,
-18,
-115,
-112,
-75,
-72,
-103,
-0,
-89,
-186,
-182,
-170,
-117,
-247,
-38,
-146,
-110,
-240,
-211,
-235,
-138,
-214,
-248,
-35,
-29,
-33,
-132,
-203,
-67,
-8,
-111,
-247,
-29,
-74,
-174,
-168,
-91,
-30,
-184,
-149,
-72,
-196,
-83,
-141,
-246,
-159,
-147,
-116,
-156,
-164,
-83,
-154,
-214,
-145,
-216,
-206,
-86,
-77,
-125,
-59,
-27,
-131,
-26,
-182,
-236,
-94,
-46,
-3,
-187,
-69,
-197,
-26,
-124,
-34,
-112,
-107,
-147,
-178,
-13,
-250,
-176,
-89,
-183,
-245,
-164,
-54,
-54,
-29,
-88,
-186,
-47,
-141,
-205,
-1,
-24,
-78,
-38,
-196,
-92,
-225,
-198,
-99,
-187,
-169,
-22,
-186,
-231,
-183,
-129,
-172,
-16,
-56,
-70,
-115,
-192,
-254,
-0,
-48,
-160,
-167,
-207,
-7,
-148,
-0,
-127,
-146,
-116,
-73,
-8,
-225,
-59,
-125,
-239,
-88,
-187,
-120,
-80,
-210,
-235,
-146,
-142,
-239,
-219,
-16,
-142,
-5,
-60,
-12,
-91,
-74,
-214,
-84,
-96,
-134,
-144,
-29,
-178,
-140,
-144,
-185,
-183,
-9,
-102,
-101,
-91,
-40,
-114,
-111,
-54,
-18,
-219,
-25,
-246,
-105,
-168,
-31,
-200,
-239,
-24,
-18,
-29,
-1,
-24,
-65,
-14,
-32,
-238,
-172,
-17,
-219,
-86,
-78,
-33,
-132,
-155,
-37,
-61,
-37,
-105,
-136,
-199,
-174,
-99,
-130,
-122,
-31,
-26,
-150,
-12,
-103,
-178,
-174,
-77,
-207,
-221,
-48,
-107,
-18,
-3,
-168,
-100,
-15,
-190,
-178,
-47,
-203,
-231,
-178,
-31,
-3,
-209,
-31,
-172,
-71,
-248,
-179,
-236,
-135,
-142,
-225,
-181,
-94,
-230,
-37,
-42,
-250,
-65,
-49,
-155,
-192,
-196,
-94,
-181,
-219,
-13,
-146,
-100,
-128,
-16,
-194,
-78,
-37,
-117,
-148,
-77,
-27,
-231,
-200,
-18,
-77,
-237,
-89,
-191,
-107,
-141,
-113,
-155,
-164,
-227,
-187,
-173,
-36,
-22,
-176,
-218,
-5,
-222,
-144,
-134,
-238,
-250,
-57,
-18,
-208,
-181,
-16,
-24,
-141,
-51,
-27,
-184,
-183,
-143,
-36,
-1,
-63,
-174,
-223,
-181,
-198,
-120,
-70,
-150,
-237,
-108,
-196,
-32,
-132,
-240,
-238,
-58,
-244,
-190,
-196,
-36,
-132,
-176,
-97,
-238,
-250,
-169,
-146,
-246,
-13,
-33,
-188,
-189,
-173,
-190,
-205,
-113,
-171,
-128,
-4,
-228,
-183,
-182,
-157,
-19,
-81,
-212,
-255,
-117,
-36,
-253,
-178,
-205,
-134,
-178,
-230,
-224,
-57,
-253,
-165,
-117,
-176,
-148,
-70,
-136,
-173,
-189,
-10,
-69,
-239,
-188,
-100,
-196,
-120,
-151,
-164,
-99,
-218,
-236,
-195,
-220,
-104,
-14,
-126,
-135,
-76,
-14,
-72,
-134,
-11,
-111,
-255,
-47,
-114,
-125,
-68,
-9,
-111,
-158,
-48,
-163,
-219,
-13,
-169,
-7,
-161,
-47,
-12,
-80,
-177,
-115,
-120,
-219,
-216,
-70,
-102,
-228,
-169,
-131,
-55,
-36,
-197,
-182,
-100,
-107,
-69,
-120,
-115,
-219,
-65,
-97,
-144,
-235,
-112,
-98,
-142,
-51,
-7,
-251,
-50,
-43,
-154,
-116,
-194,
-173,
-107,
-43,
-202,
-150,
-173,
-117,
-240,
-134,
-164,
-151,
-242,
-23,
-235,
-10,
-111,
-37,
-24,
-177,
-211,
-235,
-28,
-199,
-0,
-146,
-94,
-46,
-185,
-247,
-37,
-73,
-159,
-117,
-107,
-91,
-12,
-111,
-2,
-222,
-28,
-209,
-5,
-204,
-82,
-124,
-4,
-104,
-5,
-69,
-140,
-228,
-186,
-147,
-5,
-134,
-115,
-191,
-133,
-57,
-142,
-1,
-202,
-132,
-213,
-16,
-194,
-206,
-21,
-197,
-255,
-216,
-33,
-205,
-93,
-143,
-142,
-0,
-255,
-23,
-48,
-199,
-49,
-64,
-83,
-84,
-172,
-114,
-138,
-100,
-128,
-57,
-2,
-221,
-172,
-224,
-230,
-198,
-85,
-64,
-19,
-204,
-82,
-100,
-4,
-0,
-78,
-165,
-96,
-71,
-180,
-185,
-5,
-255,
-103,
-70,
-128,
-50,
-132,
-16,
-22,
-45,
-184,
-213,
-186,
-226,
-101,
-20,
-35,
-16,
-20,
-196,
-252,
-187,
-103,
-211,
-26,
-53,
-234,
-105,
-197,
-186,
-215,
-79,
-140,
-142,
-0,
-134,
-34,
-141,
-92,
-173,
-108,
-105,
-115,
-145,
-54,
-117,
-20,
-163,
-24,
-197,
-40,
-70,
-49,
-138,
-81,
-140,
-98,
-20,
-163,
-24,
-197,
-40,
-70,
-49,
-138,
-81,
-140,
-98,
-20,
-163,
-24,
-197,
-40,
-70,
-49,
-138,
-81,
-204,
-37,
-248,
-255,
-129,
-51,
-157,
-250,
-111,
-139,
-157,
-153,
-0,
-0,
-0,
-0,
-73,
-69,
-78,
-68,
-174,
-66,
-96,
-130,
-};
-/* clang-format on */
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index e8157c7165..75dd417f7f 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -1032,7 +1032,10 @@ void BaseMaterial3D::_update_shader() {
if (features[FEATURE_REFRACTION]) {
if (features[FEATURE_NORMAL_MAPPING]) {
- code += "\tvec3 ref_normal = normalize( mix(NORMAL,TANGENT * NORMAL_MAP.x + BINORMAL * NORMAL_MAP.y + NORMAL * NORMAL_MAP.z,NORMAL_MAP_DEPTH) );\n";
+ code += "\tvec3 unpacked_normal = NORMAL_MAP;\n";
+ code += "\tunpacked_normal.xy = unpacked_normal.xy * 2.0 - 1.0;\n";
+ code += "\tunpacked_normal.z = sqrt(max(0.0, 1.0 - dot(unpacked_normal.xy, unpacked_normal.xy)));\n";
+ code += "\tvec3 ref_normal = normalize( mix(NORMAL,TANGENT * unpacked_normal.x + BINORMAL * unpacked_normal.y + NORMAL * unpacked_normal.z,NORMAL_MAP_DEPTH) );\n";
} else {
code += "\tvec3 ref_normal = NORMAL;\n";
}
@@ -2519,7 +2522,7 @@ void BaseMaterial3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv2_world_triplanar"), "set_flag", "get_flag", FLAG_UV2_USE_WORLD_TRIPLANAR);
ADD_GROUP("Sampling", "texture_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,MipmapNearest,MipmapLinear,MipmapNearestAniso,MipmapLinearAniso"), "set_texture_filter", "get_texture_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Aniso.,Linear Mipmap Aniso."), "set_texture_filter", "get_texture_filter");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "texture_repeat"), "set_flag", "get_flag", FLAG_USE_TEXTURE_REPEAT);
ADD_GROUP("Shadows", "");
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index d31dbc877b..33ad15b938 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -1401,7 +1401,7 @@ void ArrayMesh::regen_normal_maps() {
}
//dirty hack
-bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y, int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache);
+bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, const uint8_t *p_cache_data, bool *r_use_cache, uint8_t **r_mesh_cache, int *r_mesh_cache_size, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) = NULL;
struct ArrayMeshLightmapSurface {
Ref<Material> material;
@@ -1411,28 +1411,28 @@ struct ArrayMeshLightmapSurface {
};
Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texel_size) {
- int *cache_data = nullptr;
- unsigned int cache_size = 0;
- bool use_cache = false; // Don't use cache
- return lightmap_unwrap_cached(cache_data, cache_size, use_cache, p_base_transform, p_texel_size);
+ Vector<uint8_t> null_cache;
+ return lightmap_unwrap_cached(p_base_transform, p_texel_size, null_cache, null_cache, false);
}
-Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache, const Transform &p_base_transform, float p_texel_size) {
+Error ArrayMesh::lightmap_unwrap_cached(const Transform &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache, bool p_generate_cache) {
ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED);
ERR_FAIL_COND_V_MSG(blend_shapes.size() != 0, ERR_UNAVAILABLE, "Can't unwrap mesh with blend shapes.");
- Vector<float> vertices;
- Vector<float> normals;
- Vector<int> indices;
- Vector<float> uv;
- Vector<Pair<int, int>> uv_indices;
+ LocalVector<float> vertices;
+ LocalVector<float> normals;
+ LocalVector<int> indices;
+ LocalVector<float> uv;
+ LocalVector<Pair<int, int>> uv_indices;
Vector<ArrayMeshLightmapSurface> lightmap_surfaces;
// Keep only the scale
- Transform transform = p_base_transform;
- transform.origin = Vector3();
- transform.looking_at(Vector3(1, 0, 0), Vector3(0, 1, 0));
+ Basis basis = p_base_transform.get_basis();
+ Vector3 scale = Vector3(basis.get_axis(0).length(), basis.get_axis(1).length(), basis.get_axis(2).length());
+
+ Transform transform;
+ transform.scale(scale);
Basis normal_basis = transform.basis.inverse().transposed();
@@ -1446,14 +1446,12 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach
Array arrays = surface_get_arrays(i);
s.material = surface_get_material(i);
- SurfaceTool::create_vertex_array_from_triangle_arrays(arrays, s.vertices);
+ SurfaceTool::create_vertex_array_from_triangle_arrays(arrays, s.vertices, &s.format);
- Vector<Vector3> rvertices = arrays[Mesh::ARRAY_VERTEX];
+ PackedVector3Array rvertices = arrays[Mesh::ARRAY_VERTEX];
int vc = rvertices.size();
- const Vector3 *r = rvertices.ptr();
- Vector<Vector3> rnormals = arrays[Mesh::ARRAY_NORMAL];
- const Vector3 *rn = rnormals.ptr();
+ PackedVector3Array rnormals = arrays[Mesh::ARRAY_NORMAL];
int vertex_ofs = vertices.size() / 3;
@@ -1462,24 +1460,29 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach
uv_indices.resize(vertex_ofs + vc);
for (int j = 0; j < vc; j++) {
- Vector3 v = transform.xform(r[j]);
- Vector3 n = normal_basis.xform(rn[j]).normalized();
-
- vertices.write[(j + vertex_ofs) * 3 + 0] = v.x;
- vertices.write[(j + vertex_ofs) * 3 + 1] = v.y;
- vertices.write[(j + vertex_ofs) * 3 + 2] = v.z;
- normals.write[(j + vertex_ofs) * 3 + 0] = n.x;
- normals.write[(j + vertex_ofs) * 3 + 1] = n.y;
- normals.write[(j + vertex_ofs) * 3 + 2] = n.z;
- uv_indices.write[j + vertex_ofs] = Pair<int, int>(i, j);
+ Vector3 v = transform.xform(rvertices[j]);
+ Vector3 n = normal_basis.xform(rnormals[j]).normalized();
+
+ vertices[(j + vertex_ofs) * 3 + 0] = v.x;
+ vertices[(j + vertex_ofs) * 3 + 1] = v.y;
+ vertices[(j + vertex_ofs) * 3 + 2] = v.z;
+ normals[(j + vertex_ofs) * 3 + 0] = n.x;
+ normals[(j + vertex_ofs) * 3 + 1] = n.y;
+ normals[(j + vertex_ofs) * 3 + 2] = n.z;
+ uv_indices[j + vertex_ofs] = Pair<int, int>(i, j);
}
- Vector<int> rindices = arrays[Mesh::ARRAY_INDEX];
+ PackedInt32Array rindices = arrays[Mesh::ARRAY_INDEX];
int ic = rindices.size();
+ float eps = 1.19209290e-7F; // Taken from xatlas.h
if (ic == 0) {
for (int j = 0; j < vc / 3; j++) {
- if (Face3(r[j * 3 + 0], r[j * 3 + 1], r[j * 3 + 2]).is_degenerate()) {
+ Vector3 p0 = transform.xform(rvertices[j * 3 + 0]);
+ Vector3 p1 = transform.xform(rvertices[j * 3 + 1]);
+ Vector3 p2 = transform.xform(rvertices[j * 3 + 2]);
+
+ if ((p0 - p1).length_squared() < eps || (p1 - p2).length_squared() < eps || (p2 - p0).length_squared() < eps) {
continue;
}
@@ -1489,15 +1492,18 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach
}
} else {
- const int *ri = rindices.ptr();
-
for (int j = 0; j < ic / 3; j++) {
- if (Face3(r[ri[j * 3 + 0]], r[ri[j * 3 + 1]], r[ri[j * 3 + 2]]).is_degenerate()) {
+ Vector3 p0 = transform.xform(rvertices[rindices[j * 3 + 0]]);
+ Vector3 p1 = transform.xform(rvertices[rindices[j * 3 + 1]]);
+ Vector3 p2 = transform.xform(rvertices[rindices[j * 3 + 2]]);
+
+ if ((p0 - p1).length_squared() < eps || (p1 - p2).length_squared() < eps || (p2 - p0).length_squared() < eps) {
continue;
}
- indices.push_back(vertex_ofs + ri[j * 3 + 0]);
- indices.push_back(vertex_ofs + ri[j * 3 + 1]);
- indices.push_back(vertex_ofs + ri[j * 3 + 2]);
+
+ indices.push_back(vertex_ofs + rindices[j * 3 + 0]);
+ indices.push_back(vertex_ofs + rindices[j * 3 + 1]);
+ indices.push_back(vertex_ofs + rindices[j * 3 + 2]);
}
}
@@ -1506,6 +1512,9 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach
//unwrap
+ bool use_cache = p_generate_cache; // Used to request cache generation and to know if cache was used
+ uint8_t *gen_cache;
+ int gen_cache_size;
float *gen_uvs;
int *gen_vertices;
int *gen_indices;
@@ -1514,17 +1523,16 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach
int size_x;
int size_y;
- bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), indices.size(), &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y, r_cache_data, r_cache_size, r_used_cache);
+ bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), indices.size(), p_src_cache.ptr(), &use_cache, &gen_cache, &gen_cache_size, &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y);
if (!ok) {
return ERR_CANT_CREATE;
}
- //remove surfaces
clear_surfaces();
//create surfacetools for each surface..
- Vector<Ref<SurfaceTool>> surfaces_tools;
+ LocalVector<Ref<SurfaceTool>> surfaces_tools;
for (int i = 0; i < lightmap_surfaces.size(); i++) {
Ref<SurfaceTool> st;
@@ -1535,11 +1543,12 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach
}
print_verbose("Mesh: Gen indices: " + itos(gen_index_count));
+
//go through all indices
for (int i = 0; i < gen_index_count; i += 3) {
- ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], uv_indices.size(), ERR_BUG);
- ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], uv_indices.size(), ERR_BUG);
- ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], uv_indices.size(), ERR_BUG);
+ ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], (int)uv_indices.size(), ERR_BUG);
+ ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], (int)uv_indices.size(), ERR_BUG);
+ ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], (int)uv_indices.size(), ERR_BUG);
ERR_FAIL_COND_V(uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 1]]].first || uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG);
@@ -1549,48 +1558,53 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach
SurfaceTool::Vertex v = lightmap_surfaces[surface].vertices[uv_indices[gen_vertices[gen_indices[i + j]]].second];
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_COLOR) {
- surfaces_tools.write[surface]->set_color(v.color);
+ surfaces_tools[surface]->set_color(v.color);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TEX_UV) {
- surfaces_tools.write[surface]->set_uv(v.uv);
+ surfaces_tools[surface]->set_uv(v.uv);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_NORMAL) {
- surfaces_tools.write[surface]->set_normal(v.normal);
+ surfaces_tools[surface]->set_normal(v.normal);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TANGENT) {
Plane t;
t.normal = v.tangent;
t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1;
- surfaces_tools.write[surface]->set_tangent(t);
+ surfaces_tools[surface]->set_tangent(t);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_BONES) {
- surfaces_tools.write[surface]->set_bones(v.bones);
+ surfaces_tools[surface]->set_bones(v.bones);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) {
- surfaces_tools.write[surface]->set_weights(v.weights);
+ surfaces_tools[surface]->set_weights(v.weights);
}
Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]);
- surfaces_tools.write[surface]->set_uv2(uv2);
+ surfaces_tools[surface]->set_uv2(uv2);
- surfaces_tools.write[surface]->add_vertex(v.vertex);
+ surfaces_tools[surface]->add_vertex(v.vertex);
}
}
//generate surfaces
-
- for (int i = 0; i < surfaces_tools.size(); i++) {
- surfaces_tools.write[i]->index();
- surfaces_tools.write[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), lightmap_surfaces[i].format);
+ for (unsigned int i = 0; i < surfaces_tools.size(); i++) {
+ surfaces_tools[i]->index();
+ surfaces_tools[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), lightmap_surfaces[i].format);
}
set_lightmap_size_hint(Size2(size_x, size_y));
- if (!r_used_cache) {
- //free stuff
- ::free(gen_vertices);
- ::free(gen_indices);
- ::free(gen_uvs);
+ if (gen_cache_size > 0) {
+ r_dst_cache.resize(gen_cache_size);
+ memcpy(r_dst_cache.ptrw(), gen_cache, gen_cache_size);
+ memfree(gen_cache);
+ }
+
+ if (!use_cache) {
+ // Cache was not used, free the buffers
+ memfree(gen_vertices);
+ memfree(gen_indices);
+ memfree(gen_uvs);
}
return OK;
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 13019c691d..aa830d7b50 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -263,7 +263,7 @@ public:
void regen_normal_maps();
Error lightmap_unwrap(const Transform &p_base_transform = Transform(), float p_texel_size = 0.05);
- Error lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache, const Transform &p_base_transform = Transform(), float p_texel_size = 0.05);
+ Error lightmap_unwrap_cached(const Transform &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache, bool p_generate_cache = true);
virtual void reload_from_file() override;
diff --git a/scene/resources/physics_material.cpp b/scene/resources/physics_material.cpp
index d65b0c8927..31df35aa51 100644
--- a/scene/resources/physics_material.cpp
+++ b/scene/resources/physics_material.cpp
@@ -43,9 +43,9 @@ void PhysicsMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_absorbent", "absorbent"), &PhysicsMaterial::set_absorbent);
ClassDB::bind_method(D_METHOD("is_absorbent"), &PhysicsMaterial::is_absorbent);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "friction", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"), "set_friction", "get_friction");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rough"), "set_rough", "is_rough");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"), "set_bounce", "get_bounce");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "absorbent"), "set_absorbent", "is_absorbent");
}
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 78cbb5d90f..64b43f82c6 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -1133,7 +1133,7 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
Vector3 normal_left, normal_right;
normal_left = Vector3(-size.y, size.x * left_to_right, 0.0);
- normal_right = Vector3(size.y, size.x * left_to_right, 0.0);
+ normal_right = Vector3(size.y, size.x * (1.0 - left_to_right), 0.0);
normal_left.normalize();
normal_right.normalize();
@@ -2075,16 +2075,14 @@ void RibbonTrailMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_shape"), &RibbonTrailMesh::get_shape);
ADD_PROPERTY(PropertyInfo(Variant::INT, "shape", PROPERTY_HINT_ENUM, "Flat,Cross"), "set_shape", "get_shape");
-
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_size", "get_size");
-
ADD_PROPERTY(PropertyInfo(Variant::INT, "sections", PROPERTY_HINT_RANGE, "2,128,1"), "set_sections", "get_sections");
-
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "section_length", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001,or_greater"), "set_section_length", "get_section_length");
-
ADD_PROPERTY(PropertyInfo(Variant::INT, "section_segments", PROPERTY_HINT_RANGE, "1,128,1"), "set_section_segments", "get_section_segments");
-
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve");
+
+ BIND_ENUM_CONSTANT(SHAPE_FLAT)
+ BIND_ENUM_CONSTANT(SHAPE_CROSS)
}
RibbonTrailMesh::RibbonTrailMesh() {
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index f2751b7604..2414704a57 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -978,7 +978,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
}
wf->store_32(0); //string table size, will not be in use
- size_t ext_res_count_pos = wf->get_position();
+ uint64_t ext_res_count_pos = wf->get_position();
wf->store_32(0); //zero ext resources, still parsing them
@@ -1041,7 +1041,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
//now, save resources to a separate file, for now
- size_t sub_res_count_pos = wf->get_position();
+ uint64_t sub_res_count_pos = wf->get_position();
wf->store_32(0); //zero sub resources, still parsing them
String temp_file = p_path + ".temp";
@@ -1050,8 +1050,8 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
return ERR_CANT_OPEN;
}
- Vector<size_t> local_offsets;
- Vector<size_t> local_pointers_pos;
+ Vector<uint64_t> local_offsets;
+ Vector<uint64_t> local_pointers_pos;
while (next_tag.name == "sub_resource" || next_tag.name == "resource") {
String type;
@@ -1089,7 +1089,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
wf->store_64(0); //temp local offset
bs_save_unicode_string(wf2, type);
- size_t propcount_ofs = wf2->get_position();
+ uint64_t propcount_ofs = wf2->get_position();
wf2->store_32(0);
int prop_count = 0;
@@ -1159,7 +1159,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
local_offsets.push_back(wf2->get_position());
bs_save_unicode_string(wf2, "PackedScene");
- size_t propcount_ofs = wf2->get_position();
+ uint64_t propcount_ofs = wf2->get_position();
wf2->store_32(0);
int prop_count = 0;
@@ -1185,7 +1185,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
wf2->close();
- size_t offset_from = wf->get_position();
+ uint64_t offset_from = wf->get_position();
wf->seek(sub_res_count_pos); //plus one because the saved one
wf->store_32(local_offsets.size());
diff --git a/scene/resources/shape_3d.cpp b/scene/resources/shape_3d.cpp
index 5761a405ce..cb44e059a3 100644
--- a/scene/resources/shape_3d.cpp
+++ b/scene/resources/shape_3d.cpp
@@ -102,6 +102,8 @@ void Shape3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_margin", "margin"), &Shape3D::set_margin);
ClassDB::bind_method(D_METHOD("get_margin"), &Shape3D::get_margin);
+ ClassDB::bind_method(D_METHOD("get_debug_mesh"), &Shape3D::get_debug_mesh);
+
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0.001,10,0.001"), "set_margin", "get_margin");
}
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index c30bd7927d..ff682a40f4 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -663,6 +663,8 @@ void SurfaceTool::deindex() {
}
void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, LocalVector<Vertex> *r_vertex, LocalVector<int> *r_index, uint32_t &lformat) {
+ ERR_FAIL_NULL_MSG(p_existing, "First argument in SurfaceTool::_create_list() must be a valid object of type Mesh");
+
Array arr = p_existing->surface_get_arrays(p_surface);
ERR_FAIL_COND(arr.size() != RS::ARRAY_MAX);
_create_list_from_arrays(arr, r_vertex, r_index, lformat);
@@ -824,6 +826,8 @@ void SurfaceTool::create_from_triangle_arrays(const Array &p_arrays) {
}
void SurfaceTool::create_from(const Ref<Mesh> &p_existing, int p_surface) {
+ ERR_FAIL_NULL_MSG(p_existing, "First argument in SurfaceTool::create_from() must be a valid object of type Mesh");
+
clear();
primitive = p_existing->surface_get_primitive_type(p_surface);
_create_list(p_existing, p_surface, &vertex_array, &index_array, format);
@@ -831,6 +835,8 @@ void SurfaceTool::create_from(const Ref<Mesh> &p_existing, int p_surface) {
}
void SurfaceTool::create_from_blend_shape(const Ref<Mesh> &p_existing, int p_surface, const String &p_blend_shape_name) {
+ ERR_FAIL_NULL_MSG(p_existing, "First argument in SurfaceTool::create_from_blend_shape() must be a valid object of type Mesh");
+
clear();
primitive = p_existing->surface_get_primitive_type(p_surface);
Array arr = p_existing->surface_get_blend_shape_arrays(p_surface);
@@ -851,6 +857,8 @@ void SurfaceTool::create_from_blend_shape(const Ref<Mesh> &p_existing, int p_sur
}
void SurfaceTool::append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform &p_xform) {
+ ERR_FAIL_NULL_MSG(p_existing, "First argument in SurfaceTool::append_from() must be a valid object of type Mesh");
+
if (vertex_array.size() == 0) {
primitive = p_existing->surface_get_primitive_type(p_surface);
format = 0;
diff --git a/scene/resources/text_file.cpp b/scene/resources/text_file.cpp
index cf07003720..b71909b6bb 100644
--- a/scene/resources/text_file.cpp
+++ b/scene/resources/text_file.cpp
@@ -55,10 +55,10 @@ Error TextFile::load_text(const String &p_path) {
ERR_FAIL_COND_V_MSG(err, err, "Cannot open TextFile '" + p_path + "'.");
- int len = f->get_len();
+ uint64_t len = f->get_len();
sourcef.resize(len + 1);
uint8_t *w = sourcef.ptrw();
- int r = f->get_buffer(w, len);
+ uint64_t r = f->get_buffer(w, len);
f->close();
memdelete(f);
ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 624eae0411..1b2176d30a 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -335,7 +335,7 @@ Ref<Image> StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit
//mipmaps need to be read independently, they will be later combined
Vector<Ref<Image>> mipmap_images;
- int total_size = 0;
+ uint64_t total_size = 0;
bool first = true;
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 84be69d0d6..c4b8a56f54 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -30,1150 +30,4221 @@
#include "tile_set.h"
-#include "core/config/engine.h"
#include "core/math/geometry_2d.h"
-#include "core/variant/array.h"
+#include "scene/2d/navigation_region_2d.h"
+#include "scene/gui/control.h"
+#include "scene/resources/convex_polygon_shape_2d.h"
+#include "servers/navigation_server_2d.h"
-bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
- String n = p_name;
- int slash = n.find("/");
- if (slash == -1) {
- return false;
- }
- int id = String::to_int(n.get_data(), slash);
-
- if (!tile_map.has(id)) {
- create_tile(id);
- }
- String what = n.substr(slash + 1, n.length());
-
- if (what == "name") {
- tile_set_name(id, p_value);
- } else if (what == "texture") {
- tile_set_texture(id, p_value);
- } else if (what == "tex_offset") {
- tile_set_texture_offset(id, p_value);
- } else if (what == "material") {
- tile_set_material(id, p_value);
- } else if (what == "modulate") {
- tile_set_modulate(id, p_value);
- } else if (what == "region") {
- tile_set_region(id, p_value);
- } else if (what == "tile_mode") {
- tile_set_tile_mode(id, (TileMode)((int)p_value));
- } else if (what == "is_autotile") {
- // backward compatibility for Godot 3.0.x
- // autotile used to be a bool, it's now an enum
- bool is_autotile = p_value;
- if (is_autotile) {
- tile_set_tile_mode(id, AUTO_TILE);
- }
- } else if (what.left(9) == "autotile/") {
- what = what.right(9);
- if (what == "bitmask_mode") {
- autotile_set_bitmask_mode(id, (BitmaskMode)((int)p_value));
- } else if (what == "icon_coordinate") {
- autotile_set_icon_coordinate(id, p_value);
- } else if (what == "tile_size") {
- autotile_set_size(id, p_value);
- } else if (what == "spacing") {
- autotile_set_spacing(id, p_value);
- } else if (what == "bitmask_flags") {
- tile_map[id].autotile_data.flags.clear();
- if (p_value.is_array()) {
- Array p = p_value;
- Vector2 last_coord;
- while (p.size() > 0) {
- if (p[0].get_type() == Variant::VECTOR2) {
- last_coord = p[0];
- } else if (p[0].get_type() == Variant::INT) {
- autotile_set_bitmask(id, last_coord, p[0]);
- }
- p.pop_front();
- }
- }
- } else if (what == "occluder_map") {
- tile_map[id].autotile_data.occluder_map.clear();
- Array p = p_value;
- Vector2 last_coord;
- while (p.size() > 0) {
- if (p[0].get_type() == Variant::VECTOR2) {
- last_coord = p[0];
- } else if (p[0].get_type() == Variant::OBJECT) {
- autotile_set_light_occluder(id, p[0], last_coord);
- }
- p.pop_front();
- }
- } else if (what == "navpoly_map") {
- tile_map[id].autotile_data.navpoly_map.clear();
- Array p = p_value;
- Vector2 last_coord;
- while (p.size() > 0) {
- if (p[0].get_type() == Variant::VECTOR2) {
- last_coord = p[0];
- } else if (p[0].get_type() == Variant::OBJECT) {
- autotile_set_navigation_polygon(id, p[0], last_coord);
- }
- p.pop_front();
- }
- } else if (what == "priority_map") {
- tile_map[id].autotile_data.priority_map.clear();
- Array p = p_value;
- Vector3 val;
- Vector2 v;
- int priority;
- while (p.size() > 0) {
- val = p[0];
- if (val.z > 1) {
- v.x = val.x;
- v.y = val.y;
- priority = (int)val.z;
- tile_map[id].autotile_data.priority_map[v] = priority;
- }
- p.pop_front();
- }
- } else if (what == "z_index_map") {
- tile_map[id].autotile_data.z_index_map.clear();
- Array p = p_value;
- Vector3 val;
- Vector2 v;
- int z_index;
- while (p.size() > 0) {
- val = p[0];
- if (val.z != 0) {
- v.x = val.x;
- v.y = val.y;
- z_index = (int)val.z;
- tile_map[id].autotile_data.z_index_map[v] = z_index;
- }
- p.pop_front();
- }
- }
- } else if (what == "shape") {
- 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") {
- 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") {
- 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") {
- 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") {
- 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") {
- tile_set_light_occluder(id, p_value);
- } else if (what == "occluder_offset") {
- tile_set_occluder_offset(id, p_value);
- } else if (what == "navigation") {
- tile_set_navigation_polygon(id, p_value);
- } else if (what == "navigation_offset") {
- tile_set_navigation_polygon_offset(id, p_value);
- } else if (what == "z_index") {
- tile_set_z_index(id, p_value);
- } else {
- return false;
- }
+/////////////////////////////// TileSet //////////////////////////////////////
- return true;
+// --- Plugins ---
+Vector<TileSetPlugin *> TileSet::get_tile_set_atlas_plugins() const {
+ return tile_set_plugins_vector;
}
-bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
- String n = p_name;
- int slash = n.find("/");
- if (slash == -1) {
- return false;
+// -- Shape and layout --
+void TileSet::set_tile_shape(TileSet::TileShape p_shape) {
+ tile_shape = p_shape;
+
+ for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
+ E_source->get()->notify_tile_data_properties_should_change();
}
- int id = String::to_int(n.get_data(), slash);
-
- ERR_FAIL_COND_V(!tile_map.has(id), false);
-
- String what = n.substr(slash + 1, n.length());
-
- if (what == "name") {
- r_ret = tile_get_name(id);
- } else if (what == "texture") {
- r_ret = tile_get_texture(id);
- } else if (what == "tex_offset") {
- r_ret = tile_get_texture_offset(id);
- } else if (what == "material") {
- r_ret = tile_get_material(id);
- } else if (what == "modulate") {
- r_ret = tile_get_modulate(id);
- } else if (what == "region") {
- r_ret = tile_get_region(id);
- } else if (what == "tile_mode") {
- r_ret = tile_get_tile_mode(id);
- } else if (what.left(9) == "autotile/") {
- what = what.right(9);
- if (what == "bitmask_mode") {
- r_ret = autotile_get_bitmask_mode(id);
- } else if (what == "icon_coordinate") {
- r_ret = autotile_get_icon_coordinate(id);
- } else if (what == "tile_size") {
- r_ret = autotile_get_size(id);
- } else if (what == "spacing") {
- r_ret = autotile_get_spacing(id);
- } else if (what == "bitmask_flags") {
- Array p;
- 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());
- }
- r_ret = p;
- } else if (what == "occluder_map") {
- Array p;
- for (Map<Vector2, Ref<OccluderPolygon2D>>::Element *E = tile_map[id].autotile_data.occluder_map.front(); E; E = E->next()) {
- p.push_back(E->key());
- p.push_back(E->value());
- }
- r_ret = p;
- } else if (what == "navpoly_map") {
- Array p;
- for (Map<Vector2, Ref<NavigationPolygon>>::Element *E = tile_map[id].autotile_data.navpoly_map.front(); E; E = E->next()) {
- p.push_back(E->key());
- p.push_back(E->value());
- }
- r_ret = p;
- } else if (what == "priority_map") {
- Array p;
- Vector3 v;
- for (Map<Vector2, int>::Element *E = tile_map[id].autotile_data.priority_map.front(); E; E = E->next()) {
- if (E->value() > 1) {
- //Don't save default value
- v.x = E->key().x;
- v.y = E->key().y;
- v.z = E->value();
- p.push_back(v);
- }
- }
- r_ret = p;
- } else if (what == "z_index_map") {
- Array p;
- Vector3 v;
- for (Map<Vector2, int>::Element *E = tile_map[id].autotile_data.z_index_map.front(); E; E = E->next()) {
- if (E->value() != 0) {
- //Don't save default value
- v.x = E->key().x;
- v.y = E->key().y;
- v.z = E->value();
- p.push_back(v);
- }
- }
- r_ret = p;
- }
- } else if (what == "shape") {
- r_ret = tile_get_shape(id, 0);
- } else if (what == "shape_offset") {
- r_ret = tile_get_shape_offset(id, 0);
- } else if (what == "shape_transform") {
- r_ret = tile_get_shape_transform(id, 0);
- } else if (what == "shape_one_way") {
- r_ret = tile_get_shape_one_way(id, 0);
- } else if (what == "shape_one_way_margin") {
- r_ret = tile_get_shape_one_way_margin(id, 0);
- } else if (what == "shapes") {
- r_ret = _tile_get_shapes(id);
- } else if (what == "occluder") {
- r_ret = tile_get_light_occluder(id);
- } else if (what == "occluder_offset") {
- r_ret = tile_get_occluder_offset(id);
- } else if (what == "navigation") {
- r_ret = tile_get_navigation_polygon(id);
- } else if (what == "navigation_offset") {
- r_ret = tile_get_navigation_polygon_offset(id);
- } else if (what == "z_index") {
- r_ret = tile_get_z_index(id);
- } else {
- return false;
+
+ emit_changed();
+}
+TileSet::TileShape TileSet::get_tile_shape() const {
+ return tile_shape;
+}
+
+void TileSet::set_tile_layout(TileSet::TileLayout p_layout) {
+ tile_layout = p_layout;
+ emit_changed();
+}
+TileSet::TileLayout TileSet::get_tile_layout() const {
+ return tile_layout;
+}
+
+void TileSet::set_tile_offset_axis(TileSet::TileOffsetAxis p_alignment) {
+ tile_offset_axis = p_alignment;
+
+ for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
+ E_source->get()->notify_tile_data_properties_should_change();
}
- return true;
+ emit_changed();
+}
+TileSet::TileOffsetAxis TileSet::get_tile_offset_axis() const {
+ return tile_offset_axis;
}
-void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
- for (Map<int, TileData>::Element *E = tile_map.front(); E; E = E->next()) {
- int id = E->key();
- String pre = itos(id) + "/";
- p_list->push_back(PropertyInfo(Variant::STRING, pre + "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "tex_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::COLOR, pre + "modulate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::RECT2, pre + "region", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::INT, pre + "tile_mode", PROPERTY_HINT_ENUM, "SINGLE_TILE,AUTO_TILE,ATLAS_TILE", PROPERTY_USAGE_NOEDITOR));
- if (tile_get_tile_mode(id) == AUTO_TILE) {
- p_list->push_back(PropertyInfo(Variant::INT, pre + "autotile/bitmask_mode", PROPERTY_HINT_ENUM, "2X2,3X3 (minimal),3X3", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/bitmask_flags", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "autotile/icon_coordinate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "autotile/tile_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- 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));
- } else if (tile_get_tile_mode(id) == ATLAS_TILE) {
- p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "autotile/icon_coordinate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "autotile/tile_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- 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", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "occluder", PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "navigation_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "navigation", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::BOOL, pre + "shape_one_way", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::FLOAT, pre + "shape_one_way_margin", PROPERTY_HINT_RANGE, "0,128,0.01", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "shapes", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
- p_list->push_back(PropertyInfo(Variant::INT, pre + "z_index", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1", PROPERTY_USAGE_NOEDITOR));
- }
-}
-
-void TileSet::create_tile(int p_id) {
- ERR_FAIL_COND(tile_map.has(p_id));
- tile_map[p_id] = TileData();
- tile_map[p_id].autotile_data = AutotileData();
- notify_property_list_changed();
+void TileSet::set_tile_size(Size2i p_size) {
+ ERR_FAIL_COND(p_size.x < 1 || p_size.y < 1);
+ tile_size = p_size;
emit_changed();
}
+Size2i TileSet::get_tile_size() const {
+ return tile_size;
+}
-void TileSet::autotile_set_bitmask_mode(int p_id, BitmaskMode p_mode) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].autotile_data.bitmask_mode = p_mode;
- notify_property_list_changed();
+void TileSet::set_tile_skew(Vector2 p_skew) {
emit_changed();
+ tile_skew = p_skew;
+}
+Vector2 TileSet::get_tile_skew() const {
+ return tile_skew;
+}
+
+int TileSet::get_next_source_id() const {
+ return next_source_id;
}
-TileSet::BitmaskMode TileSet::autotile_get_bitmask_mode(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), BITMASK_2X2);
- return tile_map[p_id].autotile_data.bitmask_mode;
+void TileSet::_compute_next_source_id() {
+ while (sources.has(next_source_id)) {
+ next_source_id = (next_source_id + 1) % 1073741824; // 2 ** 30
+ };
}
-void TileSet::tile_set_texture(int p_id, const Ref<Texture2D> &p_texture) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].texture = p_texture;
+// Sources management
+int TileSet::add_source(Ref<TileSetAtlasSource> p_tile_atlas_source, int p_atlas_source_id_override) {
+ ERR_FAIL_COND_V(!p_tile_atlas_source.is_valid(), -1);
+ ERR_FAIL_COND_V_MSG(p_atlas_source_id_override >= 0 && (sources.has(p_atlas_source_id_override)), -1, vformat("Cannot create TileSet atlas source. Another atlas source exists with id %d.", p_atlas_source_id_override));
+
+ int new_source_id = p_atlas_source_id_override >= 0 ? p_atlas_source_id_override : next_source_id;
+ sources[new_source_id] = p_tile_atlas_source;
+ source_ids.append(new_source_id);
+ source_ids.sort();
+ p_tile_atlas_source->set_tile_set(this);
+ _compute_next_source_id();
+
+ sources[new_source_id]->connect("changed", callable_mp(this, &TileSet::_source_changed));
+
emit_changed();
+
+ return new_source_id;
}
-Ref<Texture2D> TileSet::tile_get_texture(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<Texture2D>());
- return tile_map[p_id].texture;
+void TileSet::remove_source(int p_source_id) {
+ ERR_FAIL_COND_MSG(!sources.has(p_source_id), vformat("Cannot remove TileSet atlas source. No tileset atlas source with id %d.", p_source_id));
+
+ sources[p_source_id]->disconnect("changed", callable_mp(this, &TileSet::_source_changed));
+
+ sources[p_source_id]->set_tile_set(nullptr);
+ sources.erase(p_source_id);
+ source_ids.erase(p_source_id);
+ source_ids.sort();
+
+ emit_changed();
}
-void TileSet::tile_set_material(int p_id, const Ref<ShaderMaterial> &p_material) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].material = p_material;
+void TileSet::set_source_id(int p_source_id, int p_new_source_id) {
+ ERR_FAIL_COND(p_new_source_id < 0);
+ ERR_FAIL_COND_MSG(!sources.has(p_source_id), vformat("Cannot change TileSet atlas source ID. No tileset atlas source with id %d.", p_source_id));
+ if (p_source_id == p_new_source_id) {
+ return;
+ }
+
+ ERR_FAIL_COND_MSG(sources.has(p_new_source_id), vformat("Cannot change TileSet atlas source ID. Another atlas source exists with id %d.", p_new_source_id));
+
+ sources[p_new_source_id] = sources[p_source_id];
+ sources.erase(p_source_id);
+
+ source_ids.erase(p_source_id);
+ source_ids.append(p_new_source_id);
+ source_ids.sort();
+
emit_changed();
}
-Ref<ShaderMaterial> TileSet::tile_get_material(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<ShaderMaterial>());
- return tile_map[p_id].material;
+bool TileSet::has_source(int p_source_id) const {
+ return sources.has(p_source_id);
+}
+
+Ref<TileSetSource> TileSet::get_source(int p_source_id) const {
+ ERR_FAIL_COND_V_MSG(!sources.has(p_source_id), nullptr, vformat("No TileSet atlas source with id %d.", p_source_id));
+
+ return sources[p_source_id];
+}
+
+int TileSet::get_source_count() const {
+ return source_ids.size();
}
-void TileSet::tile_set_modulate(int p_id, const Color &p_modulate) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].modulate = p_modulate;
+int TileSet::get_source_id(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, source_ids.size(), -1);
+ return source_ids[p_index];
+}
+
+// Rendering
+void TileSet::set_uv_clipping(bool p_uv_clipping) {
+ if (uv_clipping == p_uv_clipping) {
+ return;
+ }
+ uv_clipping = p_uv_clipping;
emit_changed();
}
+bool TileSet::is_uv_clipping() const {
+ return uv_clipping;
+};
-Color TileSet::tile_get_modulate(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Color(1, 1, 1));
- return tile_map[p_id].modulate;
+void TileSet::set_y_sorting(bool p_y_sort) {
+ if (y_sorting == p_y_sort) {
+ return;
+ }
+ y_sorting = p_y_sort;
+ emit_changed();
}
+bool TileSet::is_y_sorting() const {
+ return y_sorting;
+};
-void TileSet::tile_set_texture_offset(int p_id, const Vector2 &p_offset) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].offset = p_offset;
+void TileSet::set_occlusion_layers_count(int p_occlusion_layers_count) {
+ ERR_FAIL_COND(p_occlusion_layers_count < 0);
+ if (occlusion_layers.size() == p_occlusion_layers_count) {
+ return;
+ }
+
+ occlusion_layers.resize(p_occlusion_layers_count);
+
+ for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
+ E_source->get()->notify_tile_data_properties_should_change();
+ }
+
+ notify_property_list_changed();
emit_changed();
}
-Vector2 TileSet::tile_get_texture_offset(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Vector2());
- return tile_map[p_id].offset;
+int TileSet::get_occlusion_layers_count() const {
+ return occlusion_layers.size();
+};
+
+void TileSet::set_occlusion_layer_light_mask(int p_layer_index, int p_light_mask) {
+ ERR_FAIL_INDEX(p_layer_index, occlusion_layers.size());
+ occlusion_layers.write[p_layer_index].light_mask = p_light_mask;
+ emit_changed();
+}
+
+int TileSet::get_occlusion_layer_light_mask(int p_layer_index) const {
+ ERR_FAIL_INDEX_V(p_layer_index, occlusion_layers.size(), 0);
+ return occlusion_layers[p_layer_index].light_mask;
}
-void TileSet::tile_set_region(int p_id, const Rect2 &p_region) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].region = p_region;
+void TileSet::set_occlusion_layer_sdf_collision(int p_layer_index, int p_sdf_collision) {
+ ERR_FAIL_INDEX(p_layer_index, occlusion_layers.size());
+ occlusion_layers.write[p_layer_index].sdf_collision = p_sdf_collision;
emit_changed();
}
-Rect2 TileSet::tile_get_region(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Rect2());
- return tile_map[p_id].region;
+bool TileSet::get_occlusion_layer_sdf_collision(int p_layer_index) const {
+ ERR_FAIL_INDEX_V(p_layer_index, occlusion_layers.size(), false);
+ return occlusion_layers[p_layer_index].sdf_collision;
+}
+
+void TileSet::draw_tile_shape(CanvasItem *p_canvas_item, Rect2 p_region, Color p_color, bool p_filled, Ref<Texture2D> p_texture) {
+ // TODO: optimize this with 2D meshes when they work again.
+ if (get_tile_shape() == TileSet::TILE_SHAPE_SQUARE) {
+ if (p_filled && p_texture.is_valid()) {
+ p_canvas_item->draw_texture_rect(p_texture, p_region, false, p_color);
+ } else {
+ p_canvas_item->draw_rect(p_region, p_color, p_filled);
+ }
+ } else {
+ float overlap = 0.0;
+ switch (get_tile_shape()) {
+ case TileSet::TILE_SHAPE_ISOMETRIC:
+ overlap = 0.5;
+ break;
+ case TileSet::TILE_SHAPE_HEXAGON:
+ overlap = 0.25;
+ break;
+ case TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE:
+ overlap = 0.0;
+ break;
+ default:
+ break;
+ }
+
+ Vector<Vector2> uvs;
+ uvs.append(Vector2(0.5, 0.0));
+ uvs.append(Vector2(0.0, overlap));
+ uvs.append(Vector2(0.0, 1.0 - overlap));
+ uvs.append(Vector2(0.5, 1.0));
+ uvs.append(Vector2(1.0, 1.0 - overlap));
+ uvs.append(Vector2(1.0, overlap));
+ uvs.append(Vector2(0.5, 0.0));
+ if (get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
+ for (int i = 0; i < uvs.size(); i++) {
+ uvs.write[i] = Vector2(uvs[i].y, uvs[i].x);
+ }
+ }
+
+ Vector<Vector2> points;
+ for (int i = 0; i < uvs.size(); i++) {
+ points.append(p_region.position + uvs[i] * p_region.size);
+ }
+
+ if (p_filled) {
+ // This does hurt performances a lot. We should use a mesh if possible instead.
+ p_canvas_item->draw_colored_polygon(points, p_color, uvs, p_texture);
+
+ // Should improve performances, but does not work as draw_primitive does not work with textures :/ :
+ /*for (int i = 0; i < 6; i += 3) {
+ Vector<Vector2> quad;
+ quad.append(points[i]);
+ quad.append(points[(i + 1) % points.size()]);
+ quad.append(points[(i + 2) % points.size()]);
+ quad.append(points[(i + 3) % points.size()]);
+
+ Vector<Vector2> uv_quad;
+ uv_quad.append(uvs[i]);
+ uv_quad.append(uvs[(i + 1) % uvs.size()]);
+ uv_quad.append(uvs[(i + 2) % uvs.size()]);
+ uv_quad.append(uvs[(i + 3) % uvs.size()]);
+
+ p_control->draw_primitive(quad, Vector<Color>(), uv_quad, p_texture);
+ }*/
+
+ } else {
+ // This does hurt performances a lot. We should use a mesh if possible instead.
+ // tile_shape_grid->draw_polyline(points, p_color);
+ for (int i = 0; i < points.size() - 1; i++) {
+ p_canvas_item->draw_line(points[i], points[i + 1], p_color);
+ }
+ }
+ }
}
-void TileSet::tile_set_tile_mode(int p_id, TileMode p_tile_mode) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].tile_mode = p_tile_mode;
+// Physics
+void TileSet::set_physics_layers_count(int p_physics_layers_count) {
+ ERR_FAIL_COND(p_physics_layers_count < 0);
+ if (physics_layers.size() == p_physics_layers_count) {
+ return;
+ }
+
+ physics_layers.resize(p_physics_layers_count);
+
+ for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
+ E_source->get()->notify_tile_data_properties_should_change();
+ }
+
+ notify_property_list_changed();
emit_changed();
}
-TileSet::TileMode TileSet::tile_get_tile_mode(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), SINGLE_TILE);
- return tile_map[p_id].tile_mode;
+int TileSet::get_physics_layers_count() const {
+ return physics_layers.size();
}
-void TileSet::autotile_set_icon_coordinate(int p_id, Vector2 coord) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].autotile_data.icon_coord = coord;
+void TileSet::set_physics_layer_collision_layer(int p_layer_index, uint32_t p_layer) {
+ ERR_FAIL_INDEX(p_layer_index, physics_layers.size());
+ physics_layers.write[p_layer_index].collision_layer = p_layer;
emit_changed();
}
-Vector2 TileSet::autotile_get_icon_coordinate(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Vector2());
- return tile_map[p_id].autotile_data.icon_coord;
+uint32_t TileSet::get_physics_layer_collision_layer(int p_layer_index) const {
+ ERR_FAIL_INDEX_V(p_layer_index, physics_layers.size(), 0);
+ return physics_layers[p_layer_index].collision_layer;
}
-void TileSet::autotile_set_spacing(int p_id, int p_spacing) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- ERR_FAIL_COND(p_spacing < 0);
- tile_map[p_id].autotile_data.spacing = p_spacing;
+void TileSet::set_physics_layer_collision_mask(int p_layer_index, uint32_t p_mask) {
+ ERR_FAIL_INDEX(p_layer_index, physics_layers.size());
+ physics_layers.write[p_layer_index].collision_mask = p_mask;
emit_changed();
}
-int TileSet::autotile_get_spacing(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), 0);
- return tile_map[p_id].autotile_data.spacing;
+uint32_t TileSet::get_physics_layer_collision_mask(int p_layer_index) const {
+ ERR_FAIL_INDEX_V(p_layer_index, physics_layers.size(), 0);
+ return physics_layers[p_layer_index].collision_mask;
}
-void TileSet::autotile_set_size(int p_id, Size2 p_size) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- ERR_FAIL_COND(p_size.x <= 0 || p_size.y <= 0);
- tile_map[p_id].autotile_data.size = p_size;
+void TileSet::set_physics_layer_physics_material(int p_layer_index, Ref<PhysicsMaterial> p_physics_material) {
+ ERR_FAIL_INDEX(p_layer_index, physics_layers.size());
+ physics_layers.write[p_layer_index].physics_material = p_physics_material;
}
-Size2 TileSet::autotile_get_size(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Size2());
- return tile_map[p_id].autotile_data.size;
+Ref<PhysicsMaterial> TileSet::get_physics_layer_physics_material(int p_layer_index) const {
+ ERR_FAIL_INDEX_V(p_layer_index, physics_layers.size(), Ref<PhysicsMaterial>());
+ return physics_layers[p_layer_index].physics_material;
}
-void TileSet::autotile_clear_bitmask_map(int p_id) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].autotile_data.flags.clear();
+// Terrains
+void TileSet::set_terrain_sets_count(int p_terrains_sets_count) {
+ ERR_FAIL_COND(p_terrains_sets_count < 0);
+
+ terrain_sets.resize(p_terrains_sets_count);
+
+ notify_property_list_changed();
+ emit_changed();
}
-void TileSet::autotile_set_subtile_priority(int p_id, const Vector2 &p_coord, int p_priority) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- ERR_FAIL_COND(p_priority <= 0);
- tile_map[p_id].autotile_data.priority_map[p_coord] = p_priority;
+int TileSet::get_terrain_sets_count() const {
+ return terrain_sets.size();
}
-int TileSet::autotile_get_subtile_priority(int p_id, const Vector2 &p_coord) {
- ERR_FAIL_COND_V(!tile_map.has(p_id), 1);
- if (tile_map[p_id].autotile_data.priority_map.has(p_coord)) {
- return tile_map[p_id].autotile_data.priority_map[p_coord];
+void TileSet::set_terrain_set_mode(int p_terrain_set, TerrainMode p_terrain_mode) {
+ ERR_FAIL_INDEX(p_terrain_set, terrain_sets.size());
+ terrain_sets.write[p_terrain_set].mode = p_terrain_mode;
+ for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
+ E_source->get()->notify_tile_data_properties_should_change();
}
- //When not custom priority set return the default value
- return 1;
+
+ notify_property_list_changed();
+ emit_changed();
}
-const Map<Vector2, int> &TileSet::autotile_get_priority_map(int p_id) const {
- static Map<Vector2, int> dummy;
- ERR_FAIL_COND_V(!tile_map.has(p_id), dummy);
- return tile_map[p_id].autotile_data.priority_map;
+TileSet::TerrainMode TileSet::get_terrain_set_mode(int p_terrain_set) const {
+ ERR_FAIL_INDEX_V(p_terrain_set, terrain_sets.size(), TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES);
+ return terrain_sets[p_terrain_set].mode;
}
-void TileSet::autotile_set_z_index(int p_id, const Vector2 &p_coord, int p_z_index) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].autotile_data.z_index_map[p_coord] = p_z_index;
+void TileSet::set_terrains_count(int p_terrain_set, int p_terrains_layers_count) {
+ ERR_FAIL_INDEX(p_terrain_set, terrain_sets.size());
+ ERR_FAIL_COND(p_terrains_layers_count < 0);
+ if (terrain_sets[p_terrain_set].terrains.size() == p_terrains_layers_count) {
+ return;
+ }
+
+ int old_size = terrain_sets[p_terrain_set].terrains.size();
+ terrain_sets.write[p_terrain_set].terrains.resize(p_terrains_layers_count);
+
+ // Default name and color
+ for (int i = old_size; i < terrain_sets.write[p_terrain_set].terrains.size(); i++) {
+ float hue_rotate = (i * 2 % 16) / 16.0;
+ Color c;
+ c.set_hsv(Math::fmod(float(hue_rotate), float(1.0)), 0.5, 0.5);
+ terrain_sets.write[p_terrain_set].terrains.write[i].color = c;
+ terrain_sets.write[p_terrain_set].terrains.write[i].name = String(vformat("Terrain %d", i));
+ }
+
+ for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
+ E_source->get()->notify_tile_data_properties_should_change();
+ }
+
+ notify_property_list_changed();
emit_changed();
}
-int TileSet::autotile_get_z_index(int p_id, const Vector2 &p_coord) {
- ERR_FAIL_COND_V(!tile_map.has(p_id), 1);
- if (tile_map[p_id].autotile_data.z_index_map.has(p_coord)) {
- return tile_map[p_id].autotile_data.z_index_map[p_coord];
+int TileSet::get_terrains_count(int p_terrain_set) const {
+ ERR_FAIL_INDEX_V(p_terrain_set, terrain_sets.size(), -1);
+ return terrain_sets[p_terrain_set].terrains.size();
+}
+
+void TileSet::set_terrain_name(int p_terrain_set, int p_terrain_index, String p_name) {
+ ERR_FAIL_INDEX(p_terrain_set, terrain_sets.size());
+ ERR_FAIL_INDEX(p_terrain_index, terrain_sets[p_terrain_set].terrains.size());
+ terrain_sets.write[p_terrain_set].terrains.write[p_terrain_index].name = p_name;
+ emit_changed();
+}
+
+String TileSet::get_terrain_name(int p_terrain_set, int p_terrain_index) const {
+ ERR_FAIL_INDEX_V(p_terrain_set, terrain_sets.size(), String());
+ ERR_FAIL_INDEX_V(p_terrain_index, terrain_sets[p_terrain_set].terrains.size(), String());
+ return terrain_sets[p_terrain_set].terrains[p_terrain_index].name;
+}
+
+void TileSet::set_terrain_color(int p_terrain_set, int p_terrain_index, Color p_color) {
+ ERR_FAIL_INDEX(p_terrain_set, terrain_sets.size());
+ ERR_FAIL_INDEX(p_terrain_index, terrain_sets[p_terrain_set].terrains.size());
+ if (p_color.a != 1.0) {
+ WARN_PRINT("Terrain color should have alpha == 1.0");
+ p_color.a = 1.0;
}
- //When not custom z index set return the default value
- return 0;
+ terrain_sets.write[p_terrain_set].terrains.write[p_terrain_index].color = p_color;
+ emit_changed();
}
-const Map<Vector2, int> &TileSet::autotile_get_z_index_map(int p_id) const {
- static Map<Vector2, int> dummy;
- ERR_FAIL_COND_V(!tile_map.has(p_id), dummy);
- return tile_map[p_id].autotile_data.z_index_map;
+Color TileSet::get_terrain_color(int p_terrain_set, int p_terrain_index) const {
+ ERR_FAIL_INDEX_V(p_terrain_set, terrain_sets.size(), Color());
+ ERR_FAIL_INDEX_V(p_terrain_index, terrain_sets[p_terrain_set].terrains.size(), Color());
+ return terrain_sets[p_terrain_set].terrains[p_terrain_index].color;
}
-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) {
- if (tile_map[p_id].autotile_data.flags.has(p_coord)) {
- tile_map[p_id].autotile_data.flags.erase(p_coord);
+bool TileSet::is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeighbor p_peering_bit) const {
+ if (p_terrain_set < 0 || p_terrain_set >= get_terrain_sets_count()) {
+ return false;
+ }
+
+ TileSet::TerrainMode terrain_mode = get_terrain_set_mode(p_terrain_set);
+ if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
+ if (p_peering_bit == TileSet::CELL_NEIGHBOR_RIGHT_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_LEFT_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_SIDE) {
+ return true;
+ }
+ }
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ if (p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER) {
+ return true;
+ }
+ }
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
+ if (p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return true;
+ }
+ }
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ if (p_peering_bit == TileSet::CELL_NEIGHBOR_RIGHT_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_LEFT_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
+ return true;
+ }
}
} else {
- tile_map[p_id].autotile_data.flags[p_coord] = p_flag;
+ if (get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
+ if (p_peering_bit == TileSet::CELL_NEIGHBOR_RIGHT_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_LEFT_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return true;
+ }
+ }
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ if (p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER) {
+ return true;
+ }
+ }
+ } else {
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
+ if (p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_SIDE ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
+ return true;
+ }
+ }
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ if (p_peering_bit == TileSet::CELL_NEIGHBOR_RIGHT_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_LEFT_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER ||
+ p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+// Navigation
+void TileSet::set_navigation_layers_count(int p_navigation_layers_count) {
+ ERR_FAIL_COND(p_navigation_layers_count < 0);
+ if (navigation_layers.size() == p_navigation_layers_count) {
+ return;
+ }
+
+ navigation_layers.resize(p_navigation_layers_count);
+
+ for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
+ E_source->get()->notify_tile_data_properties_should_change();
}
+
+ notify_property_list_changed();
+ emit_changed();
+}
+
+int TileSet::get_navigation_layers_count() const {
+ return navigation_layers.size();
+}
+
+void TileSet::set_navigation_layer_layers(int p_layer_index, uint32_t p_layers) {
+ ERR_FAIL_INDEX(p_layer_index, navigation_layers.size());
+ navigation_layers.write[p_layer_index].layers = p_layers;
+ emit_changed();
}
-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)) {
- return 0;
+uint32_t TileSet::get_navigation_layer_layers(int p_layer_index) const {
+ ERR_FAIL_INDEX_V(p_layer_index, navigation_layers.size(), 0);
+ return navigation_layers[p_layer_index].layers;
+}
+
+// Custom data.
+void TileSet::set_custom_data_layers_count(int p_custom_data_layers_count) {
+ ERR_FAIL_COND(p_custom_data_layers_count < 0);
+ if (custom_data_layers.size() == p_custom_data_layers_count) {
+ return;
}
- return tile_map[p_id].autotile_data.flags[p_coord];
+
+ custom_data_layers.resize(p_custom_data_layers_count);
+
+ for (Map<String, int>::Element *E = custom_data_layers_by_name.front(); E; E = E->next()) {
+ if (E->get() >= custom_data_layers.size()) {
+ custom_data_layers_by_name.erase(E);
+ }
+ }
+
+ for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
+ E_source->get()->notify_tile_data_properties_should_change();
+ }
+
+ notify_property_list_changed();
+ emit_changed();
}
-const Map<Vector2, uint32_t> &TileSet::autotile_get_bitmask_map(int p_id) {
- 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, uint32_t>();
- Rect2 region = tile_get_region(p_id);
- Size2 size = autotile_get_size(p_id);
- float spacing = autotile_get_spacing(p_id);
- for (int x = 0; x < (region.size.x / (size.x + spacing)); x++) {
- for (int y = 0; y < (region.size.y / (size.y + spacing)); y++) {
- dummy_atlas.insert(Vector2(x, y), 0);
+int TileSet::get_custom_data_layers_count() const {
+ return custom_data_layers.size();
+}
+
+int TileSet::get_custom_data_layer_by_name(String p_value) const {
+ if (custom_data_layers_by_name.has(p_value)) {
+ return custom_data_layers_by_name[p_value];
+ } else {
+ return -1;
+ }
+}
+
+void TileSet::set_custom_data_name(int p_layer_id, String p_value) {
+ ERR_FAIL_INDEX(p_layer_id, custom_data_layers.size());
+
+ // Exit if another property has the same name.
+ if (!p_value.is_empty()) {
+ for (int other_layer_id = 0; other_layer_id < get_custom_data_layers_count(); other_layer_id++) {
+ if (other_layer_id != p_layer_id && get_custom_data_name(other_layer_id) == p_value) {
+ ERR_FAIL_MSG(vformat("There is already a custom property named %s", p_value));
}
}
- return dummy_atlas;
+ }
+
+ if (p_value.is_empty() && custom_data_layers_by_name.has(p_value)) {
+ custom_data_layers_by_name.erase(p_value);
} else {
- return tile_map[p_id].autotile_data.flags;
+ custom_data_layers_by_name[p_value] = p_layer_id;
}
+
+ custom_data_layers.write[p_layer_id].name = p_value;
+ emit_changed();
+}
+
+String TileSet::get_custom_data_name(int p_layer_id) const {
+ ERR_FAIL_INDEX_V(p_layer_id, custom_data_layers.size(), "");
+ return custom_data_layers[p_layer_id].name;
+}
+
+void TileSet::set_custom_data_type(int p_layer_id, Variant::Type p_value) {
+ ERR_FAIL_INDEX(p_layer_id, custom_data_layers.size());
+ custom_data_layers.write[p_layer_id].type = p_value;
+
+ for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
+ E_source->get()->notify_tile_data_properties_should_change();
+ }
+
+ emit_changed();
+}
+
+Variant::Type TileSet::get_custom_data_type(int p_layer_id) const {
+ ERR_FAIL_INDEX_V(p_layer_id, custom_data_layers.size(), Variant::NIL);
+ return custom_data_layers[p_layer_id].type;
+}
+
+void TileSet::_source_changed() {
+ emit_changed();
+ notify_property_list_changed();
+}
+
+void TileSet::reset_state() {
+ occlusion_layers.clear();
+ physics_layers.clear();
+ custom_data_layers.clear();
}
-Vector2 TileSet::autotile_get_subtile_for_bitmask(int p_id, uint16_t p_bitmask, 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 (p_tilemap_node->get_class_name() == "TileMap") {
- if (get_script_instance() != nullptr) {
- if (get_script_instance()->has_method("_forward_subtile_selection")) {
- Variant ret = get_script_instance()->call("_forward_subtile_selection", p_id, p_bitmask, p_tilemap_node, p_tile_location);
- if (ret.get_type() == Variant::VECTOR2) {
- return ret;
+const Vector2i TileSetAtlasSource::INVALID_ATLAS_COORDS = Vector2i(-1, -1);
+const int TileSetAtlasSource::INVALID_TILE_ALTERNATIVE = -1;
+
+#ifndef DISABLE_DEPRECATED
+void TileSet::compatibility_conversion() {
+ for (Map<int, CompatibilityTileData *>::Element *E = compatibility_data.front(); E; E = E->next()) {
+ CompatibilityTileData *ctd = E->value();
+
+ // Add the texture
+ TileSetAtlasSource *atlas_source = memnew(TileSetAtlasSource);
+ int source_id = add_source(Ref<TileSetSource>(atlas_source));
+
+ atlas_source->set_texture(ctd->texture);
+
+ // Handle each tile as a new source. Not optimal but at least it should stay compatible.
+ switch (ctd->tile_mode) {
+ case 0: // SINGLE_TILE
+ // TODO
+ break;
+ case 1: // AUTO_TILE
+ // TODO
+ break;
+ case 2: // ATLAS_TILE
+ atlas_source->set_margins(ctd->region.get_position());
+ atlas_source->set_separation(Vector2i(ctd->autotile_spacing, ctd->autotile_spacing));
+ atlas_source->set_texture_region_size(ctd->autotile_tile_size);
+
+ Size2i atlas_size = ctd->region.get_size() / (ctd->autotile_tile_size + atlas_source->get_separation());
+ for (int i = 0; i < atlas_size.x; i++) {
+ for (int j = 0; j < atlas_size.y; j++) {
+ Vector2i coords = Vector2i(i, j);
+
+ for (int flags = 0; flags < 8; flags++) {
+ bool flip_h = flags & 1;
+ bool flip_v = flags & 2;
+ bool transpose = flags & 4;
+
+ int alternative_tile = 0;
+ if (!atlas_source->has_tile(coords)) {
+ atlas_source->create_tile(coords);
+ } else {
+ alternative_tile = atlas_source->create_alternative_tile(coords);
+ }
+ TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(coords, alternative_tile));
+
+ tile_data->set_flip_h(flip_h);
+ tile_data->set_flip_v(flip_v);
+ tile_data->set_transpose(transpose);
+ tile_data->tile_set_material(ctd->material);
+ tile_data->set_modulate(ctd->modulate);
+ tile_data->set_z_index(ctd->z_index);
+ if (ctd->autotile_occluder_map.has(coords)) {
+ if (get_occlusion_layers_count() < 1) {
+ set_occlusion_layers_count(1);
+ }
+ tile_data->set_occluder(0, ctd->autotile_occluder_map[coords]);
+ }
+ if (ctd->autotile_navpoly_map.has(coords)) {
+ if (get_navigation_layers_count() < 1) {
+ set_navigation_layers_count(1);
+ }
+ tile_data->set_navigation_polygon(0, ctd->autotile_navpoly_map[coords]);
+ }
+ if (ctd->autotile_priority_map.has(coords)) {
+ tile_data->set_probability(ctd->autotile_priority_map[coords]);
+ }
+ if (ctd->autotile_z_index_map.has(coords)) {
+ tile_data->set_z_index(ctd->autotile_z_index_map[coords]);
+ }
+
+ // Add the shapes.
+ if (ctd->shapes.size() > 0) {
+ if (get_physics_layers_count() < 1) {
+ set_physics_layers_count(1);
+ }
+ }
+ for (int k = 0; k < ctd->shapes.size(); k++) {
+ CompatibilityShapeData csd = ctd->shapes[k];
+ if (csd.autotile_coords == coords) {
+ tile_data->set_collision_shapes_count(0, tile_data->get_collision_shapes_count(0) + 1);
+ int index = tile_data->get_collision_shapes_count(0) - 1;
+ tile_data->set_collision_shape_one_way(0, index, csd.one_way);
+ tile_data->set_collision_shape_one_way_margin(0, index, csd.one_way_margin);
+ tile_data->set_collision_shape_shape(0, index, csd.shape);
+ // Ignores transform for now.
+ }
+ }
+
+ // -- TODO: handle --
+ // Those are offset for the whole atlas, they are likely useless for the atlases, but might make sense for single tiles.
+ // texture offset
+ // occluder_offset
+ // navigation_offset
+
+ // For terrains, ignored for now?
+ // bitmask_mode
+ // bitmask_flags
+ }
+ }
+ }
+ break;
+ }
+
+ // Offset all shapes
+ for (int k = 0; k < ctd->shapes.size(); k++) {
+ Ref<ConvexPolygonShape2D> convex = ctd->shapes[k].shape;
+ if (convex.is_valid()) {
+ Vector<Vector2> points = convex->get_points();
+ for (int i_point = 0; i_point < points.size(); i_point++) {
+ points.write[i_point] = points[i_point] - get_tile_size() / 2;
}
+ convex->set_points(points);
}
}
+
+ // Add the mapping to the map
+ compatibility_source_mapping.insert(E->key(), source_id);
+ }
+
+ // Reset compatibility data
+ for (Map<int, CompatibilityTileData *>::Element *E = compatibility_data.front(); E; E = E->next()) {
+ memdelete(E->get());
}
+ compatibility_data = Map<int, CompatibilityTileData *>();
+}
+#endif // DISABLE_DEPRECATED
- List<Vector2> coords;
- 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_IGNORE_TOP | BIND_IGNORE_LEFT | BIND_IGNORE_CENTER | BIND_IGNORE_RIGHT | BIND_IGNORE_BOTTOM);
+bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
+ Vector<String> components = String(p_name).split("/", true, 2);
+
+#ifndef DISABLE_DEPRECATED
+ // TODO: THIS IS HOW WE CHECK IF WE HAVE A DEPRECATED RESOURCE
+ // This should be moved to a dedicated conversion system
+ if (components.size() >= 1 && components[0].is_valid_integer()) {
+ int id = components[0].to_int();
+
+ // Get or create the compatibility object
+ CompatibilityTileData *ctd;
+ Map<int, CompatibilityTileData *>::Element *E = compatibility_data.find(id);
+ if (!E) {
+ ctd = memnew(CompatibilityTileData);
+ compatibility_data.insert(id, ctd);
+ } else {
+ ctd = E->get();
}
- mask_ = mask & 0xFFFF;
- mask_ignore = mask >> 16;
+ if (components.size() < 2) {
+ return false;
+ }
- 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());
+ String what = components[1];
+
+ if (what == "name") {
+ ctd->name = p_value;
+ } else if (what == "texture") {
+ ctd->texture = p_value;
+ } else if (what == "tex_offset") {
+ ctd->tex_offset = p_value;
+ } else if (what == "material") {
+ ctd->material = p_value;
+ } else if (what == "modulate") {
+ ctd->modulate = p_value;
+ } else if (what == "region") {
+ ctd->region = p_value;
+ } else if (what == "tile_mode") {
+ ctd->tile_mode = p_value;
+ } else if (what.left(9) == "autotile") {
+ what = what.right(9);
+ if (what == "bitmask_mode") {
+ ctd->autotile_bitmask_mode = p_value;
+ } else if (what == "icon_coordinate") {
+ ctd->autotile_icon_coordinate = p_value;
+ } else if (what == "tile_size") {
+ ctd->autotile_tile_size = p_value;
+ } else if (what == "spacing") {
+ ctd->autotile_spacing = p_value;
+ } else if (what == "bitmask_flags") {
+ if (p_value.is_array()) {
+ Array p = p_value;
+ Vector2i last_coord;
+ while (p.size() > 0) {
+ if (p[0].get_type() == Variant::VECTOR2) {
+ last_coord = p[0];
+ } else if (p[0].get_type() == Variant::INT) {
+ ctd->autotile_bitmask_flags.insert(last_coord, p[0]);
+ }
+ p.pop_front();
+ }
+ }
+ } else if (what == "occluder_map") {
+ Array p = p_value;
+ Vector2 last_coord;
+ while (p.size() > 0) {
+ if (p[0].get_type() == Variant::VECTOR2) {
+ last_coord = p[0];
+ } else if (p[0].get_type() == Variant::OBJECT) {
+ ctd->autotile_occluder_map.insert(last_coord, p[0]);
+ }
+ p.pop_front();
+ }
+ } else if (what == "navpoly_map") {
+ Array p = p_value;
+ Vector2 last_coord;
+ while (p.size() > 0) {
+ if (p[0].get_type() == Variant::VECTOR2) {
+ last_coord = p[0];
+ } else if (p[0].get_type() == Variant::OBJECT) {
+ ctd->autotile_navpoly_map.insert(last_coord, p[0]);
+ }
+ p.pop_front();
+ }
+ } else if (what == "priority_map") {
+ Array p = p_value;
+ Vector3 val;
+ Vector2 v;
+ int priority;
+ while (p.size() > 0) {
+ val = p[0];
+ if (val.z > 1) {
+ v.x = val.x;
+ v.y = val.y;
+ priority = (int)val.z;
+ ctd->autotile_priority_map.insert(v, priority);
+ }
+ p.pop_front();
+ }
+ } else if (what == "z_index_map") {
+ Array p = p_value;
+ Vector3 val;
+ Vector2 v;
+ int z_index;
+ while (p.size() > 0) {
+ val = p[0];
+ if (val.z != 0) {
+ v.x = val.x;
+ v.y = val.y;
+ z_index = (int)val.z;
+ ctd->autotile_z_index_map.insert(v, z_index);
+ }
+ p.pop_front();
+ }
+ }
+
+ } else if (what == "shapes") {
+ Array p = p_value;
+ for (int i = 0; i < p.size(); i++) {
+ CompatibilityShapeData csd;
+ Dictionary d = p[i];
+ for (int j = 0; j < d.size(); j++) {
+ String key = d.get_key_at_index(j);
+ if (key == "autotile_coord") {
+ csd.autotile_coords = d[key];
+ } else if (key == "one_way") {
+ csd.one_way = d[key];
+ } else if (key == "one_way_margin") {
+ csd.one_way_margin = d[key];
+ } else if (key == "shape") {
+ csd.shape = d[key];
+ } else if (key == "shape_transform") {
+ csd.transform = d[key];
+ }
+ }
+ ctd->shapes.push_back(csd);
+ }
+
+ /*
+ // IGNORED FOR NOW, they seem duplicated data compared to the shapes array
+ } else if (what == "shape") {
+ // TODO
+ } else if (what == "shape_offset") {
+ // TODO
+ } else if (what == "shape_transform") {
+ // TODO
+ } else if (what == "shape_one_way") {
+ // TODO
+ } else if (what == "shape_one_way_margin") {
+ // TODO
}
- }
+ // IGNORED FOR NOW, maybe useless ?
+ else if (what == "occluder_offset") {
+ // Not
+ } else if (what == "navigation_offset") {
+ // TODO
+ }
+ */
- if (coords.size() == 0) {
- return autotile_get_icon_coordinate(p_id);
+ } else if (what == "z_index") {
+ ctd->z_index = p_value;
+
+ // TODO: remove the conversion from here, it's not where it should be done
+ compatibility_conversion();
+ } else {
+ return false;
+ }
} 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;
+#endif // DISABLE_DEPRECATED
+
+ // This is now a new property.
+ if (components.size() == 2 && components[0].begins_with("occlusion_layer_") && components[0].trim_prefix("occlusion_layer_").is_valid_integer()) {
+ // Occlusion layers.
+ int index = components[0].trim_prefix("occlusion_layer_").to_int();
+ ERR_FAIL_COND_V(index < 0, false);
+ if (components[1] == "light_mask") {
+ ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
+ if (index >= occlusion_layers.size()) {
+ set_occlusion_layers_count(index + 1);
+ }
+ set_occlusion_layer_light_mask(index, p_value);
+ return true;
+ } else if (components[1] == "sdf_collision") {
+ ERR_FAIL_COND_V(p_value.get_type() != Variant::BOOL, false);
+ if (index >= occlusion_layers.size()) {
+ set_occlusion_layers_count(index + 1);
+ }
+ set_occlusion_layer_sdf_collision(index, p_value);
+ return true;
+ }
+ } else if (components.size() == 2 && components[0].begins_with("physics_layer_") && components[0].trim_prefix("physics_layer_").is_valid_integer()) {
+ // Physics layers.
+ int index = components[0].trim_prefix("physics_layer_").to_int();
+ ERR_FAIL_COND_V(index < 0, false);
+ if (components[1] == "collision_layer") {
+ ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
+ if (index >= physics_layers.size()) {
+ set_physics_layers_count(index + 1);
+ }
+ set_physics_layer_collision_layer(index, p_value);
+ return true;
+ } else if (components[1] == "collision_mask") {
+ ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
+ if (index >= physics_layers.size()) {
+ set_physics_layers_count(index + 1);
+ }
+ set_physics_layer_collision_mask(index, p_value);
+ return true;
+ } else if (components[1] == "physics_material") {
+ Ref<PhysicsMaterial> physics_material = p_value;
+ ERR_FAIL_COND_V(!physics_material.is_valid(), false);
+ if (index >= physics_layers.size()) {
+ set_physics_layers_count(index + 1);
+ }
+ set_physics_layer_physics_material(index, physics_material);
+ return true;
+ }
+ } else if (components.size() >= 2 && components[0].begins_with("terrain_set_") && components[0].trim_prefix("terrain_set_").is_valid_integer()) {
+ // Terrains.
+ int terrain_set_index = components[0].trim_prefix("terrain_set_").to_int();
+ ERR_FAIL_COND_V(terrain_set_index < 0, false);
+ if (components[1] == "mode") {
+ ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
+ if (terrain_set_index >= terrain_sets.size()) {
+ set_terrain_sets_count(terrain_set_index + 1);
+ }
+ set_terrain_set_mode(terrain_set_index, TerrainMode(int(p_value)));
+ } else if (components[1] == "terrains_count") {
+ ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
+ if (terrain_set_index >= terrain_sets.size()) {
+ set_terrain_sets_count(terrain_set_index + 1);
+ }
+ set_terrains_count(terrain_set_index, p_value);
+ return true;
+ } else if (components.size() >= 3 && components[1].begins_with("terrain_") && components[1].trim_prefix("terrain_").is_valid_integer()) {
+ int terrain_index = components[1].trim_prefix("terrain_").to_int();
+ ERR_FAIL_COND_V(terrain_index < 0, false);
+ if (components[2] == "name") {
+ ERR_FAIL_COND_V(p_value.get_type() != Variant::STRING, false);
+ if (terrain_set_index >= terrain_sets.size()) {
+ set_terrain_sets_count(terrain_set_index + 1);
+ }
+ if (terrain_index >= terrain_sets[terrain_set_index].terrains.size()) {
+ set_terrains_count(terrain_set_index, terrain_index + 1);
+ }
+ set_terrain_name(terrain_set_index, terrain_index, p_value);
+ return true;
+ } else if (components[2] == "color") {
+ ERR_FAIL_COND_V(p_value.get_type() != Variant::COLOR, false);
+ if (terrain_set_index >= terrain_sets.size()) {
+ set_terrain_sets_count(terrain_set_index + 1);
+ }
+ if (terrain_index >= terrain_sets[terrain_set_index].terrains.size()) {
+ set_terrains_count(terrain_set_index, terrain_index + 1);
+ }
+ set_terrain_color(terrain_set_index, terrain_index, p_value);
+ return true;
+ }
+ }
+ } else if (components.size() == 2 && components[0].begins_with("navigation_layer_") && components[0].trim_prefix("navigation_layer_").is_valid_integer()) {
+ // Navigation layers.
+ int index = components[0].trim_prefix("navigation_layer_").to_int();
+ ERR_FAIL_COND_V(index < 0, false);
+ if (components[1] == "layers") {
+ ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
+ if (index >= navigation_layers.size()) {
+ set_navigation_layers_count(index + 1);
+ }
+ set_navigation_layer_layers(index, p_value);
+ return true;
+ }
+ } else if (components.size() == 2 && components[0].begins_with("custom_data_layer_") && components[0].trim_prefix("custom_data_layer_").is_valid_integer()) {
+ // Custom data layers.
+ int index = components[0].trim_prefix("custom_data_layer_").to_int();
+ ERR_FAIL_COND_V(index < 0, false);
+ if (components[1] == "name") {
+ ERR_FAIL_COND_V(p_value.get_type() != Variant::STRING, false);
+ if (index >= custom_data_layers.size()) {
+ set_custom_data_layers_count(index + 1);
+ }
+ set_custom_data_name(index, p_value);
+ return true;
+ } else if (components[1] == "type") {
+ ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
+ if (index >= custom_data_layers.size()) {
+ set_custom_data_layers_count(index + 1);
+ }
+ set_custom_data_type(index, Variant::Type(int(p_value)));
+ return true;
}
- lower_bound = upper_bound;
- priorities_E = priorities_E->next();
- coords_E = coords_E->next();
+ } else if (components.size() == 2 && components[0] == "sources" && components[1].is_valid_integer()) {
+ // Create atlas if it does not exists.
+ int source_id = components[1].to_int();
+
+ if (!has_source(source_id)) {
+ add_source(p_value, source_id);
+ }
+ return true;
}
- return result;
+#ifndef DISABLE_DEPRECATED
}
+#endif // DISABLE_DEPRECATED
+
+ return false;
}
-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() != nullptr) {
- 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;
+bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
+ 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_integer()) {
+ // Occlusion layers.
+ int index = components[0].trim_prefix("occlusion_layer_").to_int();
+ if (index < 0 || index >= occlusion_layers.size()) {
+ return false;
+ }
+ if (components[1] == "light_mask") {
+ r_ret = get_occlusion_layer_light_mask(index);
+ return true;
+ } else if (components[1] == "sdf_collision") {
+ r_ret = get_occlusion_layer_sdf_collision(index);
+ return true;
+ }
+ } else if (components.size() == 2 && components[0].begins_with("physics_layer_") && components[0].trim_prefix("physics_layer_").is_valid_integer()) {
+ // Physics layers.
+ int index = components[0].trim_prefix("physics_layer_").to_int();
+ if (index < 0 || index >= physics_layers.size()) {
+ return false;
+ }
+ if (components[1] == "collision_layer") {
+ r_ret = get_physics_layer_collision_layer(index);
+ return true;
+ } else if (components[1] == "collision_mask") {
+ r_ret = get_physics_layer_collision_mask(index);
+ return true;
+ } else if (components[1] == "physics_material") {
+ r_ret = get_physics_layer_physics_material(index);
+ return true;
+ }
+ } else if (components.size() >= 2 && components[0].begins_with("terrain_set_") && components[0].trim_prefix("terrain_set_").is_valid_integer()) {
+ // Terrains.
+ int terrain_set_index = components[0].trim_prefix("terrain_set_").to_int();
+ if (terrain_set_index < 0 || terrain_set_index >= terrain_sets.size()) {
+ return false;
+ }
+ if (components[1] == "mode") {
+ r_ret = get_terrain_set_mode(terrain_set_index);
+ return true;
+ } else if (components[1] == "terrains_count") {
+ r_ret = get_terrains_count(terrain_set_index);
+ return true;
+ } else if (components.size() >= 3 && components[1].begins_with("terrain_") && components[1].trim_prefix("terrain_").is_valid_integer()) {
+ int terrain_index = components[1].trim_prefix("terrain_").to_int();
+ if (terrain_index < 0 || terrain_index >= terrain_sets[terrain_set_index].terrains.size()) {
+ return false;
+ }
+ if (components[2] == "name") {
+ r_ret = get_terrain_name(terrain_set_index, terrain_index);
+ return true;
+ } else if (components[2] == "color") {
+ r_ret = get_terrain_color(terrain_set_index, terrain_index);
+ return true;
}
}
+ } else if (components.size() == 2 && components[0].begins_with("navigation_layer_") && components[0].trim_prefix("navigation_layer_").is_valid_integer()) {
+ // navigation layers.
+ int index = components[0].trim_prefix("navigation_layer_").to_int();
+ if (index < 0 || index >= navigation_layers.size()) {
+ return false;
+ }
+ if (components[1] == "layers") {
+ r_ret = get_navigation_layer_layers(index);
+ return true;
+ }
+ } else if (components.size() == 2 && components[0].begins_with("custom_data_layer_") && components[0].trim_prefix("custom_data_layer_").is_valid_integer()) {
+ // Custom data layers.
+ int index = components[0].trim_prefix("custom_data_layer_").to_int();
+ if (index < 0 || index >= custom_data_layers.size()) {
+ return false;
+ }
+ if (components[1] == "name") {
+ r_ret = get_custom_data_name(index);
+ return true;
+ } else if (components[1] == "type") {
+ r_ret = get_custom_data_type(index);
+ return true;
+ }
+ } else if (components.size() == 2 && components[0] == "sources" && components[1].is_valid_integer()) {
+ // Atlases data.
+ int source_id = components[1].to_int();
+
+ if (has_source(source_id)) {
+ r_ret = get_source(source_id);
+ return true;
+ } else {
+ return false;
+ }
}
- Vector2 coord = tile_get_region(p_id).size / autotile_get_size(p_id);
+ return false;
+}
- 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));
- }
+void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
+ PropertyInfo property_info;
+ // Rendering.
+ p_list->push_back(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ for (int i = 0; i < occlusion_layers.size(); i++) {
+ p_list->push_back(PropertyInfo(Variant::INT, vformat("occlusion_layer_%d/light_mask", i), PROPERTY_HINT_LAYERS_2D_RENDER));
+
+ // occlusion_layer_%d/sdf_collision
+ property_info = PropertyInfo(Variant::BOOL, vformat("occlusion_layer_%d/sdf_collision", i));
+ if (occlusion_layers[i].sdf_collision == false) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
}
+ p_list->push_back(property_info);
}
- if (coords.size() == 0) {
- return autotile_get_icon_coordinate(p_id);
- } else {
- return coords[Math::random(0, (int)coords.size())];
+
+ // Physics.
+ p_list->push_back(PropertyInfo(Variant::NIL, "Physics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ for (int i = 0; i < physics_layers.size(); i++) {
+ p_list->push_back(PropertyInfo(Variant::INT, vformat("physics_layer_%d/collision_layer", i), PROPERTY_HINT_LAYERS_2D_PHYSICS));
+
+ // physics_layer_%d/collision_mask
+ property_info = PropertyInfo(Variant::INT, vformat("physics_layer_%d/collision_mask", i), PROPERTY_HINT_LAYERS_2D_PHYSICS);
+ if (physics_layers[i].collision_mask == 1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+
+ // physics_layer_%d/physics_material
+ property_info = PropertyInfo(Variant::OBJECT, vformat("physics_layer_%d/physics_material", i), PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial");
+ if (!physics_layers[i].physics_material.is_valid()) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
}
-}
-void TileSet::tile_set_name(int p_id, const String &p_name) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].name = p_name;
- emit_changed();
+ // Terrains.
+ p_list->push_back(PropertyInfo(Variant::NIL, "Terrains", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ for (int terrain_set_index = 0; terrain_set_index < terrain_sets.size(); terrain_set_index++) {
+ p_list->push_back(PropertyInfo(Variant::INT, vformat("terrain_set_%d/mode", terrain_set_index), PROPERTY_HINT_ENUM, "Match corners and sides,Match corners,Match sides"));
+ p_list->push_back(PropertyInfo(Variant::INT, vformat("terrain_set_%d/terrains_count", terrain_set_index), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
+ for (int terrain_index = 0; terrain_index < terrain_sets[terrain_set_index].terrains.size(); terrain_index++) {
+ p_list->push_back(PropertyInfo(Variant::STRING, vformat("terrain_set_%d/terrain_%d/name", terrain_set_index, terrain_index)));
+ p_list->push_back(PropertyInfo(Variant::COLOR, vformat("terrain_set_%d/terrain_%d/color", terrain_set_index, terrain_index)));
+ }
+ }
+
+ // Navigation.
+ p_list->push_back(PropertyInfo(Variant::NIL, "Navigation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ for (int i = 0; i < navigation_layers.size(); i++) {
+ p_list->push_back(PropertyInfo(Variant::INT, vformat("navigation_layer_%d/layers", i), PROPERTY_HINT_LAYERS_2D_NAVIGATION));
+ }
+
+ // Custom data.
+ String argt = "Any";
+ for (int i = 1; i < Variant::VARIANT_MAX; i++) {
+ argt += "," + Variant::get_type_name(Variant::Type(i));
+ }
+ p_list->push_back(PropertyInfo(Variant::NIL, "Custom data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ for (int i = 0; i < custom_data_layers.size(); i++) {
+ p_list->push_back(PropertyInfo(Variant::STRING, vformat("custom_data_layer_%d/name", i)));
+ p_list->push_back(PropertyInfo(Variant::INT, vformat("custom_data_layer_%d/type", i), PROPERTY_HINT_ENUM, argt));
+ }
+
+ // Sources.
+ // Note: sources have to be listed in at the end as some TileData rely on the TileSet properties being initialized first.
+ for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
+ p_list->push_back(PropertyInfo(Variant::INT, vformat("sources/%d", E_source->key()), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+ }
}
-String TileSet::tile_get_name(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), String());
- return tile_map[p_id].name;
+void TileSet::_bind_methods() {
+ // Sources management.
+ ClassDB::bind_method(D_METHOD("get_next_source_id"), &TileSet::get_next_source_id);
+ ClassDB::bind_method(D_METHOD("add_source", "atlas_source_id_override"), &TileSet::add_source, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("remove_source", "source_id"), &TileSet::remove_source);
+ ClassDB::bind_method(D_METHOD("set_source_id", "source_id"), &TileSet::set_source_id);
+ ClassDB::bind_method(D_METHOD("get_source_count"), &TileSet::get_source_count);
+ ClassDB::bind_method(D_METHOD("get_source_id", "index"), &TileSet::get_source_id);
+ ClassDB::bind_method(D_METHOD("has_source", "index"), &TileSet::has_source);
+ ClassDB::bind_method(D_METHOD("get_source", "index"), &TileSet::get_source);
+
+ // Shape and layout.
+ ClassDB::bind_method(D_METHOD("set_tile_shape", "shape"), &TileSet::set_tile_shape);
+ ClassDB::bind_method(D_METHOD("get_tile_shape"), &TileSet::get_tile_shape);
+ ClassDB::bind_method(D_METHOD("set_tile_layout", "layout"), &TileSet::set_tile_layout);
+ ClassDB::bind_method(D_METHOD("get_tile_layout"), &TileSet::get_tile_layout);
+ ClassDB::bind_method(D_METHOD("set_tile_offset_axis", "alignment"), &TileSet::set_tile_offset_axis);
+ ClassDB::bind_method(D_METHOD("get_tile_offset_axis"), &TileSet::get_tile_offset_axis);
+ ClassDB::bind_method(D_METHOD("set_tile_size", "size"), &TileSet::set_tile_size);
+ ClassDB::bind_method(D_METHOD("get_tile_size"), &TileSet::get_tile_size);
+ ClassDB::bind_method(D_METHOD("set_tile_skew", "skew"), &TileSet::set_tile_skew);
+ ClassDB::bind_method(D_METHOD("get_tile_skew"), &TileSet::get_tile_skew);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "tile_shape", PROPERTY_HINT_ENUM, "Square,Isometric,Half-offset square,Hexagon"), "set_tile_shape", "get_tile_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "tile_layout", PROPERTY_HINT_ENUM, "Stacked,Stacked Offset,Stairs Right,Stairs Down,Diamond Right,Diamond Down"), "set_tile_layout", "get_tile_layout");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "tile_offset_axis", PROPERTY_HINT_ENUM, "Horizontal Offset,Vertical Offset"), "set_tile_offset_axis", "get_tile_offset_axis");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "tile_size"), "set_tile_size", "get_tile_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "tile_skew"), "set_tile_skew", "get_tile_skew");
+
+ // Rendering.
+ ClassDB::bind_method(D_METHOD("set_uv_clipping", "uv_clipping"), &TileSet::set_uv_clipping);
+ ClassDB::bind_method(D_METHOD("is_uv_clipping"), &TileSet::is_uv_clipping);
+ ClassDB::bind_method(D_METHOD("set_y_sorting", "y_sorting"), &TileSet::set_y_sorting);
+ ClassDB::bind_method(D_METHOD("is_y_sorting"), &TileSet::is_y_sorting);
+
+ ClassDB::bind_method(D_METHOD("set_occlusion_layers_count", "occlusion_layers_count"), &TileSet::set_occlusion_layers_count);
+ ClassDB::bind_method(D_METHOD("get_occlusion_layers_count"), &TileSet::get_occlusion_layers_count);
+ ClassDB::bind_method(D_METHOD("set_occlusion_layer_light_mask", "layer_index", "light_mask"), &TileSet::set_occlusion_layer_light_mask);
+ ClassDB::bind_method(D_METHOD("get_occlusion_layer_light_mask"), &TileSet::get_occlusion_layer_light_mask);
+ ClassDB::bind_method(D_METHOD("set_occlusion_layer_sdf_collision", "layer_index", "sdf_collision"), &TileSet::set_occlusion_layer_sdf_collision);
+ ClassDB::bind_method(D_METHOD("get_occlusion_layer_sdf_collision"), &TileSet::get_occlusion_layer_sdf_collision);
+
+ // Physics
+ ClassDB::bind_method(D_METHOD("set_physics_layers_count", "physics_layers_count"), &TileSet::set_physics_layers_count);
+ ClassDB::bind_method(D_METHOD("get_physics_layers_count"), &TileSet::get_physics_layers_count);
+ ClassDB::bind_method(D_METHOD("set_physics_layer_collision_layer", "layer_index", "layer"), &TileSet::set_physics_layer_collision_layer);
+ ClassDB::bind_method(D_METHOD("get_physics_layer_collision_layer", "layer_index"), &TileSet::get_physics_layer_collision_layer);
+ ClassDB::bind_method(D_METHOD("set_physics_layer_collision_mask", "layer_index", "mask"), &TileSet::set_physics_layer_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_physics_layer_collision_mask", "layer_index"), &TileSet::get_physics_layer_collision_mask);
+ ClassDB::bind_method(D_METHOD("set_physics_layer_physics_material", "layer_index", "physics_material"), &TileSet::set_physics_layer_physics_material);
+ ClassDB::bind_method(D_METHOD("get_physics_layer_physics_material", "layer_index"), &TileSet::get_physics_layer_physics_material);
+
+ // Terrains
+ ClassDB::bind_method(D_METHOD("set_terrain_sets_count", "terrain_sets_count"), &TileSet::set_terrain_sets_count);
+ ClassDB::bind_method(D_METHOD("get_terrain_sets_count"), &TileSet::get_terrain_sets_count);
+ ClassDB::bind_method(D_METHOD("set_terrain_set_mode", "terrain_set", "mode"), &TileSet::set_terrain_set_mode);
+ ClassDB::bind_method(D_METHOD("get_terrain_set_mode", "terrain_set"), &TileSet::get_terrain_set_mode);
+
+ ClassDB::bind_method(D_METHOD("set_terrains_count", "terrain_set", "terrains_count"), &TileSet::set_terrains_count);
+ ClassDB::bind_method(D_METHOD("get_terrains_count", "terrain_set"), &TileSet::get_terrains_count);
+ ClassDB::bind_method(D_METHOD("set_terrain_name", "terrain_set", "terrain_index", "name"), &TileSet::set_terrain_name);
+ ClassDB::bind_method(D_METHOD("get_terrain_name", "terrain_set", "terrain_index"), &TileSet::get_terrain_name);
+ ClassDB::bind_method(D_METHOD("set_terrain_color", "terrain_set", "terrain_index", "color"), &TileSet::set_terrain_color);
+ ClassDB::bind_method(D_METHOD("get_terrain_color", "terrain_set", "terrain_index"), &TileSet::get_terrain_color);
+
+ // Navigation
+ ClassDB::bind_method(D_METHOD("set_navigation_layers_count", "navigation_layers_count"), &TileSet::set_navigation_layers_count);
+ ClassDB::bind_method(D_METHOD("get_navigation_layers_count"), &TileSet::get_navigation_layers_count);
+ ClassDB::bind_method(D_METHOD("set_navigation_layer_layers", "layer_index", "layers"), &TileSet::set_navigation_layer_layers);
+ ClassDB::bind_method(D_METHOD("get_navigation_layer_layers", "layer_index"), &TileSet::get_navigation_layer_layers);
+
+ // Custom data
+ ClassDB::bind_method(D_METHOD("set_custom_data_layers_count", "custom_data_layers_count"), &TileSet::set_custom_data_layers_count);
+ ClassDB::bind_method(D_METHOD("get_custom_data_layers_count"), &TileSet::get_custom_data_layers_count);
+
+ ADD_GROUP("Rendering", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uv_clipping"), "set_uv_clipping", "is_uv_clipping");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "y_sorting"), "set_y_sorting", "is_y_sorting");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "occlusion_layers_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_occlusion_layers_count", "get_occlusion_layers_count");
+
+ ADD_GROUP("Physics", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "physics_layers_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_physics_layers_count", "get_physics_layers_count");
+
+ ADD_GROUP("Terrains", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "terrains_sets_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_terrain_sets_count", "get_terrain_sets_count");
+
+ ADD_GROUP("Navigation", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_navigation_layers_count", "get_navigation_layers_count");
+
+ ADD_GROUP("Custom data", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "custom_data_layers_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_custom_data_layers_count", "get_custom_data_layers_count");
+
+ // -- Enum binding --
+ BIND_ENUM_CONSTANT(TILE_SHAPE_SQUARE);
+ BIND_ENUM_CONSTANT(TILE_SHAPE_ISOMETRIC);
+ BIND_ENUM_CONSTANT(TILE_SHAPE_HALF_OFFSET_SQUARE);
+ BIND_ENUM_CONSTANT(TILE_SHAPE_HEXAGON);
+
+ BIND_ENUM_CONSTANT(TILE_LAYOUT_STACKED);
+ BIND_ENUM_CONSTANT(TILE_LAYOUT_STACKED_OFFSET);
+ BIND_ENUM_CONSTANT(TILE_LAYOUT_STAIRS_RIGHT);
+ BIND_ENUM_CONSTANT(TILE_LAYOUT_STAIRS_DOWN);
+ BIND_ENUM_CONSTANT(TILE_LAYOUT_DIAMOND_RIGHT);
+ BIND_ENUM_CONSTANT(TILE_LAYOUT_DIAMOND_DOWN);
+
+ BIND_ENUM_CONSTANT(TILE_OFFSET_AXIS_HORIZONTAL);
+ BIND_ENUM_CONSTANT(TILE_OFFSET_AXIS_VERTICAL);
+
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_RIGHT_SIDE);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_RIGHT_CORNER);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_CORNER);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_LEFT_SIDE);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_LEFT_CORNER);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_SIDE);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_CORNER);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
+ BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER);
+
+ BIND_ENUM_CONSTANT(TERRAIN_MODE_MATCH_CORNERS_AND_SIDES);
+ BIND_ENUM_CONSTANT(TERRAIN_MODE_MATCH_CORNERS);
+ BIND_ENUM_CONSTANT(TERRAIN_MODE_MATCH_SIDES);
}
-void TileSet::tile_clear_shapes(int p_id) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].shapes_data.clear();
+TileSet::TileSet() {
+ // Instanciatie and list all plugins.
+ tile_set_plugins_vector.append(memnew(TileSetAtlasPluginRendering));
+ tile_set_plugins_vector.append(memnew(TileSetAtlasPluginPhysics));
+ tile_set_plugins_vector.append(memnew(TileSetAtlasPluginTerrain));
+ tile_set_plugins_vector.append(memnew(TileSetAtlasPluginNavigation));
}
-void TileSet::tile_add_shape(int p_id, const Ref<Shape2D> &p_shape, const Transform2D &p_transform, bool p_one_way, const Vector2 &p_autotile_coord) {
- ERR_FAIL_COND(!tile_map.has(p_id));
+TileSet::~TileSet() {
+ for (Map<int, CompatibilityTileData *>::Element *E = compatibility_data.front(); E; E = E->next()) {
+ memdelete(E->get());
+ }
+ while (!source_ids.is_empty()) {
+ remove_source(source_ids[0]);
+ }
+ for (int i = 0; i < tile_set_plugins_vector.size(); i++) {
+ memdelete(tile_set_plugins_vector[i]);
+ }
+}
- ShapeData new_data = ShapeData();
- new_data.shape = p_shape;
- new_data.shape_transform = p_transform;
- new_data.one_way_collision = p_one_way;
- new_data.autotile_coord = p_autotile_coord;
+/////////////////////////////// TileSetSource //////////////////////////////////////
- tile_map[p_id].shapes_data.push_back(new_data);
+void TileSetSource::set_tile_set(const TileSet *p_tile_set) {
+ tile_set = p_tile_set;
}
-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();
+/////////////////////////////// TileSetAtlasSource //////////////////////////////////////
+
+void TileSetAtlasSource::set_tile_set(const TileSet *p_tile_set) {
+ tile_set = p_tile_set;
+
+ // Set the TileSet on all TileData.
+ for (Map<Vector2i, TileAlternativesData>::Element *E_tile = tiles.front(); E_tile; E_tile = E_tile->next()) {
+ for (Map<int, TileData *>::Element *E_alternative = E_tile->get().alternatives.front(); E_alternative; E_alternative = E_alternative->next()) {
+ E_alternative->get()->set_tile_set(tile_set);
+ }
+ }
}
-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));
- ERR_FAIL_COND(p_shape_id < 0);
+void TileSetAtlasSource::notify_tile_data_properties_should_change() {
+ // Set the TileSet on all TileData.
+ for (Map<Vector2i, TileAlternativesData>::Element *E_tile = tiles.front(); E_tile; E_tile = E_tile->next()) {
+ for (Map<int, TileData *>::Element *E_alternative = E_tile->get().alternatives.front(); E_alternative; E_alternative = E_alternative->next()) {
+ E_alternative->get()->notify_tile_data_properties_should_change();
+ }
+ }
+}
- if (p_shape_id >= tile_map[p_id].shapes_data.size()) {
- tile_map[p_id].shapes_data.resize(p_shape_id + 1);
+void TileSetAtlasSource::reset_state() {
+ // Reset all TileData.
+ for (Map<Vector2i, TileAlternativesData>::Element *E_tile = tiles.front(); E_tile; E_tile = E_tile->next()) {
+ for (Map<int, TileData *>::Element *E_alternative = E_tile->get().alternatives.front(); E_alternative; E_alternative = E_alternative->next()) {
+ E_alternative->get()->reset_state();
+ }
}
- tile_map[p_id].shapes_data.write[p_shape_id].shape = p_shape;
- _decompose_convex_shape(p_shape);
+}
+
+void TileSetAtlasSource::set_texture(Ref<Texture2D> p_texture) {
+ texture = p_texture;
+
emit_changed();
}
-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>());
- ERR_FAIL_COND_V(p_shape_id < 0, Ref<Shape2D>());
+Ref<Texture2D> TileSetAtlasSource::get_texture() const {
+ return texture;
+}
- if (p_shape_id < tile_map[p_id].shapes_data.size()) {
- return tile_map[p_id].shapes_data[p_shape_id].shape;
+void TileSetAtlasSource::set_margins(Vector2i p_margins) {
+ if (p_margins.x < 0 || p_margins.y < 0) {
+ WARN_PRINT("Atlas source margins should be positive.");
+ margins = Vector2i(MAX(0, p_margins.x), MAX(0, p_margins.y));
+ } else {
+ margins = p_margins;
}
- return Ref<Shape2D>();
+ emit_changed();
+}
+Vector2i TileSetAtlasSource::get_margins() const {
+ return margins;
}
-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));
- ERR_FAIL_COND(p_shape_id < 0);
+void TileSetAtlasSource::set_separation(Vector2i p_separation) {
+ if (p_separation.x < 0 || p_separation.y < 0) {
+ WARN_PRINT("Atlas source separation should be positive.");
+ separation = Vector2i(MAX(0, p_separation.x), MAX(0, p_separation.y));
+ } else {
+ separation = p_separation;
+ }
+
+ emit_changed();
+}
+Vector2i TileSetAtlasSource::get_separation() const {
+ return separation;
+}
- if (p_shape_id >= tile_map[p_id].shapes_data.size()) {
- tile_map[p_id].shapes_data.resize(p_shape_id + 1);
+void TileSetAtlasSource::set_texture_region_size(Vector2i p_tile_size) {
+ if (p_tile_size.x <= 0 || p_tile_size.y <= 0) {
+ WARN_PRINT("Atlas source tile_size should be strictly positive.");
+ texture_region_size = Vector2i(MAX(1, p_tile_size.x), MAX(1, p_tile_size.y));
+ } else {
+ texture_region_size = p_tile_size;
}
- tile_map[p_id].shapes_data.write[p_shape_id].shape_transform = p_offset;
+
emit_changed();
}
+Vector2i TileSetAtlasSource::get_texture_region_size() const {
+ return texture_region_size;
+}
+
+Vector2i TileSetAtlasSource::get_atlas_grid_size() const {
+ Ref<Texture2D> texture = get_texture();
+ if (!texture.is_valid()) {
+ return Vector2i();
+ }
+
+ ERR_FAIL_COND_V(texture_region_size.x <= 0 || texture_region_size.y <= 0, Vector2i());
+
+ Size2i valid_area = texture->get_size() - margins;
+
+ // Compute the number of valid tiles in the tiles atlas
+ Size2i grid_size = Size2i();
+ if (valid_area.x >= texture_region_size.x && valid_area.y >= texture_region_size.y) {
+ valid_area -= texture_region_size;
+ grid_size = Size2i(1, 1) + valid_area / (texture_region_size + separation);
+ }
+ return grid_size;
+}
-Transform2D TileSet::tile_get_shape_transform(int p_id, int p_shape_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Transform2D());
- ERR_FAIL_COND_V(p_shape_id < 0, Transform2D());
+bool TileSetAtlasSource::_set(const StringName &p_name, const Variant &p_value) {
+ Vector<String> components = String(p_name).split("/", true, 2);
- if (p_shape_id < tile_map[p_id].shapes_data.size()) {
- return tile_map[p_id].shapes_data[p_shape_id].shape_transform;
+ // Compute the vector2i if we have coordinates.
+ Vector<String> coords_split = components[0].split(":");
+ Vector2i coords = TileSetAtlasSource::INVALID_ATLAS_COORDS;
+ if (coords_split.size() == 2 && coords_split[0].is_valid_integer() && coords_split[1].is_valid_integer()) {
+ coords = Vector2i(coords_split[0].to_int(), coords_split[1].to_int());
}
- return Transform2D();
+ // Properties.
+ if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ // Create the tile if needed.
+ if (!has_tile(coords)) {
+ create_tile(coords);
+ }
+ if (components.size() >= 2) {
+ // Properties.
+ if (components[1] == "size_in_atlas") {
+ move_tile_in_atlas(coords, coords, p_value);
+ } else if (components[1] == "next_alternative_id") {
+ tiles[coords].next_alternative_id = p_value;
+ } else if (components[1].is_valid_integer()) {
+ int alternative_id = components[1].to_int();
+ if (alternative_id != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
+ // Create the alternative if needed ?
+ if (!has_alternative_tile(coords, alternative_id)) {
+ create_alternative_tile(coords, alternative_id);
+ }
+ if (!tiles[coords].alternatives.has(alternative_id)) {
+ tiles[coords].alternatives[alternative_id] = memnew(TileData);
+ tiles[coords].alternatives[alternative_id]->set_tile_set(tile_set);
+ tiles[coords].alternatives[alternative_id]->set_allow_transform(alternative_id > 0);
+ tiles[coords].alternatives_ids.append(alternative_id);
+ }
+ if (components.size() >= 3) {
+ bool valid;
+ tiles[coords].alternatives[alternative_id]->set(components[2], p_value, &valid);
+ return valid;
+ } else {
+ // Only create the alternative if it did not exist yet.
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
}
-void TileSet::tile_set_shape_offset(int p_id, int p_shape_id, const Vector2 &p_offset) {
- Transform2D transform = tile_get_shape_transform(p_id, p_shape_id);
- transform.set_origin(p_offset);
- tile_set_shape_transform(p_id, p_shape_id, transform);
+bool TileSetAtlasSource::_get(const StringName &p_name, Variant &r_ret) const {
+ Vector<String> components = String(p_name).split("/", true, 2);
+
+ // Properties.
+ Vector<String> coords_split = components[0].split(":");
+ if (coords_split.size() == 2 && coords_split[0].is_valid_integer() && coords_split[1].is_valid_integer()) {
+ Vector2i coords = Vector2i(coords_split[0].to_int(), coords_split[1].to_int());
+ if (tiles.has(coords)) {
+ if (components.size() >= 2) {
+ // Properties.
+ if (components[1] == "size_in_atlas") {
+ r_ret = tiles[coords].size_in_atlas;
+ return true;
+ } else if (components[1] == "next_alternative_id") {
+ r_ret = tiles[coords].next_alternative_id;
+ return true;
+ } else if (components[1].is_valid_integer()) {
+ int alternative_id = components[1].to_int();
+ if (alternative_id != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE && tiles[coords].alternatives.has(alternative_id)) {
+ if (components.size() >= 3) {
+ bool valid;
+ r_ret = tiles[coords].alternatives[alternative_id]->get(components[2], &valid);
+ return valid;
+ } else {
+ // Only to notify the tile alternative exists.
+ r_ret = alternative_id;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
}
-Vector2 TileSet::tile_get_shape_offset(int p_id, int p_shape_id) const {
- return tile_get_shape_transform(p_id, p_shape_id).get_origin();
+void TileSetAtlasSource::_get_property_list(List<PropertyInfo> *p_list) const {
+ // Atlases data.
+ PropertyInfo property_info;
+ for (Map<Vector2i, TileAlternativesData>::Element *E_tile = tiles.front(); E_tile; E_tile = E_tile->next()) {
+ List<PropertyInfo> tile_property_list;
+
+ // size_in_atlas
+ property_info = PropertyInfo(Variant::VECTOR2I, "size_in_atlas", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR);
+ if (E_tile->get().size_in_atlas == Vector2i(1, 1)) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ tile_property_list.push_back(property_info);
+
+ // next_alternative_id
+ property_info = PropertyInfo(Variant::INT, "next_alternative_id", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR);
+ if (E_tile->get().next_alternative_id == 1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ tile_property_list.push_back(property_info);
+
+ for (Map<int, TileData *>::Element *E_alternative = E_tile->get().alternatives.front(); E_alternative; E_alternative = E_alternative->next()) {
+ // Add a dummy property to show the alternative exists.
+ tile_property_list.push_back(PropertyInfo(Variant::INT, vformat("%d", E_alternative->key()), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+
+ // Get the alternative tile's properties and append them to the list of properties.
+ List<PropertyInfo> alternative_property_list;
+ E_alternative->get()->get_property_list(&alternative_property_list);
+ for (List<PropertyInfo>::Element *E_property = alternative_property_list.front(); E_property; E_property = E_property->next()) {
+ property_info = E_property->get();
+ bool valid;
+ Variant default_value = ClassDB::class_get_default_property_value("TileData", property_info.name, &valid);
+ Variant value = E_alternative->get()->get(property_info.name);
+ if (valid && value == default_value) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ property_info.name = vformat("%s/%s", vformat("%d", E_alternative->key()), property_info.name);
+ tile_property_list.push_back(property_info);
+ }
+ }
+
+ // Add all alternative.
+ for (List<PropertyInfo>::Element *E_property = tile_property_list.front(); E_property; E_property = E_property->next()) {
+ E_property->get().name = vformat("%s/%s", vformat("%d:%d", E_tile->key().x, E_tile->key().y), E_property->get().name);
+ p_list->push_back(E_property->get());
+ }
+ }
}
-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));
- ERR_FAIL_COND(p_shape_id < 0);
+void TileSetAtlasSource::create_tile(const Vector2i p_atlas_coords, const Vector2i p_size) {
+ // Create a tile if it does not exists.
+ ERR_FAIL_COND(p_atlas_coords.x < 0 || p_atlas_coords.y < 0);
+ ERR_FAIL_COND(p_size.x <= 0 || p_size.y <= 0);
+ for (int x = 0; x < p_size.x; x++) {
+ for (int y = 0; y < p_size.y; y++) {
+ Vector2i coords = p_atlas_coords + Vector2i(x, y);
+ ERR_FAIL_COND_MSG(tiles.has(coords), vformat("Cannot create tile at position %s with size %s. Already a tile present at %s.", p_atlas_coords, p_size, coords));
+ }
+ }
- if (p_shape_id >= tile_map[p_id].shapes_data.size()) {
- tile_map[p_id].shapes_data.resize(p_shape_id + 1);
+ // Create and resize the tile.
+ tiles.insert(p_atlas_coords, TileSetAtlasSource::TileAlternativesData());
+ tiles_ids.append(p_atlas_coords);
+ tiles_ids.sort();
+
+ tiles[p_atlas_coords].size_in_atlas = p_size;
+ tiles[p_atlas_coords].alternatives[0] = memnew(TileData);
+ tiles[p_atlas_coords].alternatives[0]->set_tile_set(tile_set);
+ tiles[p_atlas_coords].alternatives[0]->set_allow_transform(false);
+ tiles[p_atlas_coords].alternatives[0]->connect("changed", callable_mp((Resource *)this, &TileSetAtlasSource::emit_changed));
+ tiles[p_atlas_coords].alternatives[0]->notify_property_list_changed();
+ tiles[p_atlas_coords].alternatives_ids.append(0);
+
+ // Add all covered positions to the mapping cache
+ for (int x = 0; x < p_size.x; x++) {
+ for (int y = 0; y < p_size.y; y++) {
+ Vector2i coords = p_atlas_coords + Vector2i(x, y);
+ _coords_mapping_cache[coords] = p_atlas_coords;
+ }
}
- tile_map[p_id].shapes_data.write[p_shape_id].one_way_collision = p_one_way;
- emit_changed();
+
+ emit_signal("changed");
}
-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);
- ERR_FAIL_COND_V(p_shape_id < 0, false);
+void TileSetAtlasSource::remove_tile(Vector2i p_atlas_coords) {
+ ERR_FAIL_COND_MSG(!tiles.has(p_atlas_coords), vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
+
+ // Remove all covered positions from the mapping cache
+ Size2i size = tiles[p_atlas_coords].size_in_atlas;
- if (p_shape_id < tile_map[p_id].shapes_data.size()) {
- return tile_map[p_id].shapes_data[p_shape_id].one_way_collision;
+ for (int x = 0; x < size.x; x++) {
+ for (int y = 0; y < size.y; y++) {
+ Vector2i coords = p_atlas_coords + Vector2i(x, y);
+ _coords_mapping_cache.erase(coords);
+ }
}
- return false;
+ // Free tile data.
+ for (Map<int, TileData *>::Element *E_tile_data = tiles[p_atlas_coords].alternatives.front(); E_tile_data; E_tile_data = E_tile_data->next()) {
+ memdelete(E_tile_data->get());
+ }
+
+ // Delete the tile
+ tiles.erase(p_atlas_coords);
+ tiles_ids.erase(p_atlas_coords);
+ tiles_ids.sort();
+
+ emit_signal("changed");
}
-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));
- ERR_FAIL_COND(p_shape_id < 0);
+bool TileSetAtlasSource::has_tile(Vector2i p_atlas_coords) const {
+ return tiles.has(p_atlas_coords);
+}
- if (p_shape_id >= tile_map[p_id].shapes_data.size()) {
- tile_map[p_id].shapes_data.resize(p_shape_id + 1);
+Vector2i TileSetAtlasSource::get_tile_at_coords(Vector2i p_atlas_coords) const {
+ if (!_coords_mapping_cache.has(p_atlas_coords)) {
+ return INVALID_ATLAS_COORDS;
}
- tile_map[p_id].shapes_data.write[p_shape_id].one_way_collision_margin = p_margin;
- emit_changed();
+
+ return _coords_mapping_cache[p_atlas_coords];
+}
+
+Vector2i TileSetAtlasSource::get_tile_size_in_atlas(Vector2i p_atlas_coords) const {
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), Vector2i(-1, -1), vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
+
+ return tiles[p_atlas_coords].size_in_atlas;
}
-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);
- ERR_FAIL_COND_V(p_shape_id < 0, 0);
+int TileSetAtlasSource::get_tiles_count() const {
+ return tiles_ids.size();
+}
+
+Vector2i TileSetAtlasSource::get_tile_id(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, tiles_ids.size(), TileSetAtlasSource::INVALID_ATLAS_COORDS);
+ return tiles_ids[p_index];
+}
+
+Rect2i TileSetAtlasSource::get_tile_texture_region(Vector2i p_atlas_coords) const {
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), Rect2i(), vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
+
+ Vector2i size_in_atlas = tiles[p_atlas_coords].size_in_atlas;
+ Vector2 region_size = texture_region_size * size_in_atlas + separation * (size_in_atlas - Vector2i(1, 1));
+
+ Vector2 origin = margins + (p_atlas_coords * (texture_region_size + separation));
+
+ return Rect2(origin, region_size);
+ ;
+}
- 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;
+Vector2i TileSetAtlasSource::get_tile_effective_texture_offset(Vector2i p_atlas_coords, int p_alternative_tile) const {
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), Vector2i(), vformat("TileSetAtlasSource has no tile at %s.", Vector2i(p_atlas_coords)));
+ ERR_FAIL_COND_V_MSG(!has_alternative_tile(p_atlas_coords, p_alternative_tile), Vector2i(), vformat("TileSetAtlasSource has no alternative tile with id %d at %s.", p_alternative_tile, String(p_atlas_coords)));
+ ERR_FAIL_COND_V(!tile_set, Vector2i());
+
+ Vector2 margin = (get_tile_texture_region(p_atlas_coords).size - tile_set->get_tile_size()) / 2;
+ margin = Vector2i(MAX(0, margin.x), MAX(0, margin.y));
+ Vector2i effective_texture_offset = Object::cast_to<TileData>(get_tile_data(p_atlas_coords, p_alternative_tile))->get_texture_offset();
+ if (ABS(effective_texture_offset.x) > margin.x || ABS(effective_texture_offset.y) > margin.y) {
+ effective_texture_offset.x = CLAMP(effective_texture_offset.x, -margin.x, margin.x);
+ effective_texture_offset.y = CLAMP(effective_texture_offset.y, -margin.y, margin.y);
}
- return 0;
+ return effective_texture_offset;
}
-void TileSet::tile_set_light_occluder(int p_id, const Ref<OccluderPolygon2D> &p_light_occluder) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].occluder = p_light_occluder;
+bool TileSetAtlasSource::can_move_tile_in_atlas(Vector2i p_atlas_coords, Vector2i p_new_atlas_coords, Vector2i p_new_size) const {
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), false, vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
+
+ Vector2i new_atlas_coords = (p_new_atlas_coords != INVALID_ATLAS_COORDS) ? p_new_atlas_coords : p_atlas_coords;
+ if (new_atlas_coords.x < 0 || new_atlas_coords.y < 0) {
+ return false;
+ }
+
+ Vector2i size = (p_new_size != Vector2i(-1, -1)) ? p_new_size : tiles[p_atlas_coords].size_in_atlas;
+ ERR_FAIL_COND_V(size.x <= 0 || size.y <= 0, false);
+
+ Size2i grid_size = get_atlas_grid_size();
+ if (new_atlas_coords.x + size.x > grid_size.x || new_atlas_coords.y + size.y > grid_size.y) {
+ return false;
+ }
+
+ Rect2i new_rect = Rect2i(new_atlas_coords, size);
+ // Check if the new tile can fit in the new rect.
+ for (int x = new_rect.position.x; x < new_rect.get_end().x; x++) {
+ for (int y = new_rect.position.y; y < new_rect.get_end().y; y++) {
+ Vector2i coords = get_tile_at_coords(Vector2i(x, y));
+ if (coords != p_atlas_coords && coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
-Ref<OccluderPolygon2D> TileSet::tile_get_light_occluder(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<OccluderPolygon2D>());
- return tile_map[p_id].occluder;
+void TileSetAtlasSource::move_tile_in_atlas(Vector2i p_atlas_coords, Vector2i p_new_atlas_coords, Vector2i p_new_size) {
+ bool can_move = can_move_tile_in_atlas(p_atlas_coords, p_new_atlas_coords, p_new_size);
+ ERR_FAIL_COND_MSG(!can_move, vformat("Cannot move tile at position %s with size %s. Tile already present.", p_new_atlas_coords, p_new_size));
+
+ // Compute the actual new rect from arguments.
+ Vector2i new_atlas_coords = (p_new_atlas_coords != INVALID_ATLAS_COORDS) ? p_new_atlas_coords : p_atlas_coords;
+ Vector2i size = (p_new_size != Vector2i(-1, -1)) ? p_new_size : tiles[p_atlas_coords].size_in_atlas;
+
+ if (new_atlas_coords == p_atlas_coords && size == tiles[p_atlas_coords].size_in_atlas) {
+ return;
+ }
+
+ // Remove all covered positions from the mapping cache.
+ Size2i old_size = tiles[p_atlas_coords].size_in_atlas;
+ for (int x = 0; x < old_size.x; x++) {
+ for (int y = 0; y < old_size.y; y++) {
+ Vector2i coords = p_atlas_coords + Vector2i(x, y);
+ _coords_mapping_cache.erase(coords);
+ }
+ }
+
+ // Move the tile and update its size.
+ if (new_atlas_coords != p_atlas_coords) {
+ tiles[new_atlas_coords] = tiles[p_atlas_coords];
+ tiles.erase(p_atlas_coords);
+
+ tiles_ids.erase(p_atlas_coords);
+ tiles_ids.append(new_atlas_coords);
+ tiles_ids.sort();
+ }
+ tiles[new_atlas_coords].size_in_atlas = size;
+
+ // Add all covered positions to the mapping cache again.
+ for (int x = 0; x < size.x; x++) {
+ for (int y = 0; y < size.y; y++) {
+ Vector2i coords = new_atlas_coords + Vector2i(x, y);
+ _coords_mapping_cache[coords] = new_atlas_coords;
+ }
+ }
+
+ emit_signal("changed");
}
-void TileSet::autotile_set_light_occluder(int p_id, const Ref<OccluderPolygon2D> &p_light_occluder, const Vector2 &p_coord) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- if (p_light_occluder.is_null()) {
- if (tile_map[p_id].autotile_data.occluder_map.has(p_coord)) {
- tile_map[p_id].autotile_data.occluder_map.erase(p_coord);
+bool TileSetAtlasSource::has_tiles_outside_texture() {
+ Vector2i grid_size = get_atlas_grid_size();
+ Vector<Vector2i> to_remove;
+
+ for (Map<Vector2i, TileSetAtlasSource::TileAlternativesData>::Element *E = tiles.front(); E; E = E->next()) {
+ if (E->key().x >= grid_size.x || E->key().y >= grid_size.y) {
+ return true;
}
- } else {
- tile_map[p_id].autotile_data.occluder_map[p_coord] = p_light_occluder;
}
+
+ return false;
}
-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>());
+void TileSetAtlasSource::clear_tiles_outside_texture() {
+ Vector2i grid_size = get_atlas_grid_size();
+ Vector<Vector2i> to_remove;
- if (!tile_map[p_id].autotile_data.occluder_map.has(p_coord)) {
- return Ref<OccluderPolygon2D>();
- } else {
- return tile_map[p_id].autotile_data.occluder_map[p_coord];
+ for (Map<Vector2i, TileSetAtlasSource::TileAlternativesData>::Element *E = tiles.front(); E; E = E->next()) {
+ if (E->key().x >= grid_size.x || E->key().y >= grid_size.y) {
+ to_remove.append(E->key());
+ }
+ }
+
+ for (int i = 0; i < to_remove.size(); i++) {
+ remove_tile(to_remove[i]);
}
}
-void TileSet::tile_set_navigation_polygon_offset(int p_id, const Vector2 &p_offset) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].navigation_polygon_offset = p_offset;
+int TileSetAtlasSource::create_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_id_override) {
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), -1, vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
+ ERR_FAIL_COND_V_MSG(p_alternative_id_override >= 0 && (tiles[p_atlas_coords].alternatives.has(p_alternative_id_override) || tiles[p_atlas_coords].alternatives.has(p_alternative_id_override)), -1, vformat("Cannot create alternative tile. Another alternative exists with id %d.", p_alternative_id_override));
+
+ int new_alternative_id = p_alternative_id_override >= 0 ? p_alternative_id_override : tiles[p_atlas_coords].next_alternative_id;
+
+ tiles[p_atlas_coords].alternatives[new_alternative_id] = memnew(TileData);
+ tiles[p_atlas_coords].alternatives[new_alternative_id]->set_tile_set(tile_set);
+ tiles[p_atlas_coords].alternatives[new_alternative_id]->set_allow_transform(true);
+ tiles[p_atlas_coords].alternatives[new_alternative_id]->notify_property_list_changed();
+ tiles[p_atlas_coords].alternatives_ids.append(new_alternative_id);
+ tiles[p_atlas_coords].alternatives_ids.sort();
+ _compute_next_alternative_id(p_atlas_coords);
+
+ emit_signal("changed");
+
+ return new_alternative_id;
+}
+
+void TileSetAtlasSource::remove_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_tile) {
+ ERR_FAIL_COND_MSG(!tiles.has(p_atlas_coords), vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
+ ERR_FAIL_COND_MSG(!tiles[p_atlas_coords].alternatives.has(p_alternative_tile), vformat("TileSetAtlasSource has no alternative with id %d for tile coords %s.", p_alternative_tile, String(p_atlas_coords)));
+ ERR_FAIL_COND_MSG(p_alternative_tile == 0, "Cannot remove the alternative with id 0, the base tile alternative cannot be removed.");
+
+ memdelete(tiles[p_atlas_coords].alternatives[p_alternative_tile]);
+ tiles[p_atlas_coords].alternatives.erase(p_alternative_tile);
+ tiles[p_atlas_coords].alternatives_ids.erase(p_alternative_tile);
+ tiles[p_atlas_coords].alternatives_ids.sort();
+
+ emit_signal("changed");
+}
+
+void TileSetAtlasSource::set_alternative_tile_id(const Vector2i p_atlas_coords, int p_alternative_tile, int p_new_id) {
+ ERR_FAIL_COND_MSG(!tiles.has(p_atlas_coords), vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
+ ERR_FAIL_COND_MSG(!tiles[p_atlas_coords].alternatives.has(p_alternative_tile), vformat("TileSetAtlasSource has no alternative with id %d for tile coords %s.", p_alternative_tile, String(p_atlas_coords)));
+ ERR_FAIL_COND_MSG(p_alternative_tile == 0, "Cannot change the alternative with id 0, the base tile alternative cannot be modified.");
+
+ ERR_FAIL_COND_MSG(tiles[p_atlas_coords].alternatives.has(p_new_id), vformat("TileSetAtlasSource has already an alternative with id %d at %s.", p_new_id, String(p_atlas_coords)));
+
+ tiles[p_atlas_coords].alternatives[p_new_id] = tiles[p_atlas_coords].alternatives[p_alternative_tile];
+ tiles[p_atlas_coords].alternatives_ids.append(p_new_id);
+
+ tiles[p_atlas_coords].alternatives.erase(p_alternative_tile);
+ tiles[p_atlas_coords].alternatives_ids.erase(p_alternative_tile);
+ tiles[p_atlas_coords].alternatives_ids.sort();
+
+ emit_signal("changed");
+}
+
+bool TileSetAtlasSource::has_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_tile) const {
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), false, vformat("The TileSetAtlasSource atlas has no tile at %s.", String(p_atlas_coords)));
+ return tiles[p_atlas_coords].alternatives.has(p_alternative_tile);
+}
+
+int TileSetAtlasSource::get_next_alternative_tile_id(const Vector2i p_atlas_coords) const {
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), -1, vformat("The TileSetAtlasSource atlas has no tile at %s.", String(p_atlas_coords)));
+ return tiles[p_atlas_coords].next_alternative_id;
}
-Vector2 TileSet::tile_get_navigation_polygon_offset(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Vector2());
- return tile_map[p_id].navigation_polygon_offset;
+int TileSetAtlasSource::get_alternative_tiles_count(const Vector2i p_atlas_coords) const {
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), -1, vformat("The TileSetAtlasSource atlas has no tile at %s.", String(p_atlas_coords)));
+ return tiles[p_atlas_coords].alternatives_ids.size();
}
-void TileSet::tile_set_navigation_polygon(int p_id, const Ref<NavigationPolygon> &p_navigation_polygon) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].navigation_polygon = p_navigation_polygon;
+int TileSetAtlasSource::get_alternative_tile_id(const Vector2i p_atlas_coords, int p_index) const {
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), -1, vformat("The TileSetAtlasSource atlas has no tile at %s.", String(p_atlas_coords)));
+ ERR_FAIL_INDEX_V(p_index, tiles[p_atlas_coords].alternatives_ids.size(), -1);
+
+ return tiles[p_atlas_coords].alternatives_ids[p_index];
}
-Ref<NavigationPolygon> TileSet::tile_get_navigation_polygon(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<NavigationPolygon>());
- return tile_map[p_id].navigation_polygon;
+Object *TileSetAtlasSource::get_tile_data(const Vector2i p_atlas_coords, int p_alternative_tile) const {
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), nullptr, vformat("The TileSetAtlasSource atlas has no tile at %s.", String(p_atlas_coords)));
+ ERR_FAIL_COND_V_MSG(!tiles[p_atlas_coords].alternatives.has(p_alternative_tile), nullptr, vformat("TileSetAtlasSource has no alternative with id %d for tile coords %s.", p_alternative_tile, String(p_atlas_coords)));
+
+ return tiles[p_atlas_coords].alternatives[p_alternative_tile];
}
-const Map<Vector2, Ref<OccluderPolygon2D>> &TileSet::autotile_get_light_oclusion_map(int p_id) const {
- static Map<Vector2, Ref<OccluderPolygon2D>> dummy;
- ERR_FAIL_COND_V(!tile_map.has(p_id), dummy);
- return tile_map[p_id].autotile_data.occluder_map;
+void TileSetAtlasSource::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_texture", "texture"), &TileSetAtlasSource::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture"), &TileSetAtlasSource::get_texture);
+ ClassDB::bind_method(D_METHOD("set_margins", "margins"), &TileSetAtlasSource::set_margins);
+ ClassDB::bind_method(D_METHOD("get_margins"), &TileSetAtlasSource::get_margins);
+ ClassDB::bind_method(D_METHOD("set_separation", "separation"), &TileSetAtlasSource::set_separation);
+ ClassDB::bind_method(D_METHOD("get_separation"), &TileSetAtlasSource::get_separation);
+ ClassDB::bind_method(D_METHOD("set_texture_region_size", "texture_region_size"), &TileSetAtlasSource::set_texture_region_size);
+ ClassDB::bind_method(D_METHOD("get_texture_region_size"), &TileSetAtlasSource::get_texture_region_size);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_NOEDITOR), "set_texture", "get_texture");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "margins", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_margins", "get_margins");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "separation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_separation", "get_separation");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "tile_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_texture_region_size", "get_texture_region_size");
+
+ // Base tiles
+ ClassDB::bind_method(D_METHOD("create_tile", "atlas_coords", "size"), &TileSetAtlasSource::create_tile, DEFVAL(Vector2i(1, 1)));
+ ClassDB::bind_method(D_METHOD("remove_tile", "atlas_coords"), &TileSetAtlasSource::remove_tile); // Remove a tile. If p_tile_key.alternative_tile if different from 0, remove the alternative
+ ClassDB::bind_method(D_METHOD("has_tile", "atlas_coords"), &TileSetAtlasSource::has_tile);
+ ClassDB::bind_method(D_METHOD("can_move_tile_in_atlas", "atlas_coords", "new_atlas_coords", "new_size"), &TileSetAtlasSource::can_move_tile_in_atlas, DEFVAL(INVALID_ATLAS_COORDS), DEFVAL(Vector2i(-1, -1)));
+ ClassDB::bind_method(D_METHOD("move_tile_in_atlas", "atlas_coords", "new_atlas_coords", "new_size"), &TileSetAtlasSource::move_tile_in_atlas, DEFVAL(INVALID_ATLAS_COORDS), DEFVAL(Vector2i(-1, -1)));
+ ClassDB::bind_method(D_METHOD("get_tile_size_in_atlas", "atlas_coords"), &TileSetAtlasSource::get_tile_size_in_atlas);
+
+ ClassDB::bind_method(D_METHOD("get_tiles_count"), &TileSetAtlasSource::get_tiles_count);
+ ClassDB::bind_method(D_METHOD("get_tile_id", "index"), &TileSetAtlasSource::get_tile_id);
+
+ ClassDB::bind_method(D_METHOD("get_tile_at_coords", "atlas_coords"), &TileSetAtlasSource::get_tile_at_coords);
+
+ // Alternative tiles
+ ClassDB::bind_method(D_METHOD("create_alternative_tile", "atlas_coords", "alternative_id_override"), &TileSetAtlasSource::create_alternative_tile, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("remove_alternative_tile", "atlas_coords", "alternative_tile"), &TileSetAtlasSource::remove_alternative_tile);
+ ClassDB::bind_method(D_METHOD("set_alternative_tile_id", "atlas_coords", "alternative_tile", "new_id"), &TileSetAtlasSource::set_alternative_tile_id);
+ ClassDB::bind_method(D_METHOD("has_alternative_tile", "atlas_coords", "alternative_tile"), &TileSetAtlasSource::has_alternative_tile);
+ ClassDB::bind_method(D_METHOD("get_next_alternative_tile_id", "atlas_coords"), &TileSetAtlasSource::get_next_alternative_tile_id);
+
+ ClassDB::bind_method(D_METHOD("get_alternative_tiles_count", "atlas_coords"), &TileSetAtlasSource::get_alternative_tiles_count);
+ ClassDB::bind_method(D_METHOD("get_alternative_tile_id", "atlas_coords", "index"), &TileSetAtlasSource::get_alternative_tile_id);
+
+ ClassDB::bind_method(D_METHOD("get_tile_data", "atlas_coords", "index"), &TileSetAtlasSource::get_tile_data);
+
+ // Helpers.
+ ClassDB::bind_method(D_METHOD("get_atlas_grid_size"), &TileSetAtlasSource::get_atlas_grid_size);
+ ClassDB::bind_method(D_METHOD("has_tiles_outside_texture"), &TileSetAtlasSource::has_tiles_outside_texture);
+ ClassDB::bind_method(D_METHOD("clear_tiles_outside_texture"), &TileSetAtlasSource::clear_tiles_outside_texture);
+ ClassDB::bind_method(D_METHOD("get_tile_texture_region", "atlas_coords"), &TileSetAtlasSource::get_tile_texture_region);
}
-void TileSet::autotile_set_navigation_polygon(int p_id, const Ref<NavigationPolygon> &p_navigation_polygon, const Vector2 &p_coord) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- if (p_navigation_polygon.is_null()) {
- if (tile_map[p_id].autotile_data.navpoly_map.has(p_coord)) {
- tile_map[p_id].autotile_data.navpoly_map.erase(p_coord);
+TileSetAtlasSource::~TileSetAtlasSource() {
+ // Free everything needed.
+ for (Map<Vector2i, TileAlternativesData>::Element *E_alternatives = tiles.front(); E_alternatives; E_alternatives = E_alternatives->next()) {
+ for (Map<int, TileData *>::Element *E_tile_data = E_alternatives->get().alternatives.front(); E_tile_data; E_tile_data = E_tile_data->next()) {
+ memdelete(E_tile_data->get());
}
- } else {
- tile_map[p_id].autotile_data.navpoly_map[p_coord] = p_navigation_polygon;
}
}
-Ref<NavigationPolygon> TileSet::autotile_get_navigation_polygon(int p_id, const Vector2 &p_coord) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<NavigationPolygon>());
- if (!tile_map[p_id].autotile_data.navpoly_map.has(p_coord)) {
- return Ref<NavigationPolygon>();
- } else {
- return tile_map[p_id].autotile_data.navpoly_map[p_coord];
+TileData *TileSetAtlasSource::_get_atlas_tile_data(Vector2i p_atlas_coords, int p_alternative_tile) {
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), nullptr, vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
+ ERR_FAIL_COND_V_MSG(!tiles[p_atlas_coords].alternatives.has(p_alternative_tile), nullptr, vformat("TileSetAtlasSource has no alternative with id %d for tile coords %s.", p_alternative_tile, String(p_atlas_coords)));
+
+ return tiles[p_atlas_coords].alternatives[p_alternative_tile];
+}
+
+const TileData *TileSetAtlasSource::_get_atlas_tile_data(Vector2i p_atlas_coords, int p_alternative_tile) const {
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), nullptr, vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
+ ERR_FAIL_COND_V_MSG(!tiles[p_atlas_coords].alternatives.has(p_alternative_tile), nullptr, vformat("TileSetAtlasSource has no alternative with id %d for tile coords %s.", p_alternative_tile, String(p_atlas_coords)));
+
+ return tiles[p_atlas_coords].alternatives[p_alternative_tile];
+}
+
+void TileSetAtlasSource::_compute_next_alternative_id(const Vector2i p_atlas_coords) {
+ ERR_FAIL_COND_MSG(!tiles.has(p_atlas_coords), vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
+
+ while (tiles[p_atlas_coords].alternatives.has(tiles[p_atlas_coords].next_alternative_id)) {
+ tiles[p_atlas_coords].next_alternative_id = (tiles[p_atlas_coords].next_alternative_id % 1073741823) + 1; // 2 ** 30
+ };
+}
+
+/////////////////////////////// TileData //////////////////////////////////////
+
+void TileData::set_tile_set(const TileSet *p_tile_set) {
+ tile_set = p_tile_set;
+ if (tile_set) {
+ occluders.resize(tile_set->get_occlusion_layers_count());
+ physics.resize(tile_set->get_physics_layers_count());
+ navigation.resize(tile_set->get_navigation_layers_count());
+ custom_data.resize(tile_set->get_custom_data_layers_count());
+ }
+ notify_property_list_changed();
+}
+
+void TileData::notify_tile_data_properties_should_change() {
+ occluders.resize(tile_set->get_occlusion_layers_count());
+ physics.resize(tile_set->get_physics_layers_count());
+ for (int bit_index = 0; bit_index < 16; bit_index++) {
+ if (terrain_set < 0 || terrain_peering_bits[bit_index] >= tile_set->get_terrains_count(terrain_set)) {
+ terrain_peering_bits[bit_index] = -1;
+ }
+ }
+ navigation.resize(tile_set->get_navigation_layers_count());
+
+ // Convert custom data to the new type.
+ custom_data.resize(tile_set->get_custom_data_layers_count());
+ for (int i = 0; i < custom_data.size(); i++) {
+ if (custom_data[i].get_type() != tile_set->get_custom_data_type(i)) {
+ Variant new_val;
+ Callable::CallError error;
+ if (Variant::can_convert(custom_data[i].get_type(), tile_set->get_custom_data_type(i))) {
+ const Variant *args[] = { &custom_data[i] };
+ Variant::construct(tile_set->get_custom_data_type(i), new_val, args, 1, error);
+ } else {
+ Variant::construct(tile_set->get_custom_data_type(i), new_val, nullptr, 0, error);
+ }
+ custom_data.write[i] = new_val;
+ }
}
+
+ notify_property_list_changed();
+ emit_signal("changed");
+}
+
+void TileData::reset_state() {
+ occluders.clear();
+ physics.clear();
+ navigation.clear();
+ custom_data.clear();
+}
+
+void TileData::set_allow_transform(bool p_allow_transform) {
+ allow_transform = p_allow_transform;
+}
+
+bool TileData::is_allowing_transform() const {
+ return allow_transform;
+}
+
+// Rendering
+void TileData::set_flip_h(bool p_flip_h) {
+ ERR_FAIL_COND_MSG(!allow_transform && p_flip_h, "Transform is only allowed for alternative tiles (with its alternative_id != 0)");
+ flip_h = p_flip_h;
+ emit_signal("changed");
+}
+bool TileData::get_flip_h() const {
+ return flip_h;
+}
+
+void TileData::set_flip_v(bool p_flip_v) {
+ ERR_FAIL_COND_MSG(!allow_transform && p_flip_v, "Transform is only allowed for alternative tiles (with its alternative_id != 0)");
+ flip_v = p_flip_v;
+ emit_signal("changed");
+}
+
+bool TileData::get_flip_v() const {
+ return flip_v;
+}
+
+void TileData::set_transpose(bool p_transpose) {
+ ERR_FAIL_COND_MSG(!allow_transform && p_transpose, "Transform is only allowed for alternative tiles (with its alternative_id != 0)");
+ transpose = p_transpose;
+ emit_signal("changed");
+}
+bool TileData::get_transpose() const {
+ return transpose;
+}
+
+void TileData::set_texture_offset(Vector2i p_texture_offset) {
+ tex_offset = p_texture_offset;
+ emit_signal("changed");
+}
+
+Vector2i TileData::get_texture_offset() const {
+ return tex_offset;
+}
+
+void TileData::tile_set_material(Ref<ShaderMaterial> p_material) {
+ material = p_material;
+ emit_signal("changed");
+}
+Ref<ShaderMaterial> TileData::tile_get_material() const {
+ return material;
+}
+
+void TileData::set_modulate(Color p_modulate) {
+ modulate = p_modulate;
+ emit_signal("changed");
+}
+Color TileData::get_modulate() const {
+ return modulate;
+}
+
+void TileData::set_z_index(int p_z_index) {
+ z_index = p_z_index;
+ emit_signal("changed");
+}
+int TileData::get_z_index() const {
+ return z_index;
+}
+
+void TileData::set_y_sort_origin(Vector2i p_y_sort_origin) {
+ y_sort_origin = p_y_sort_origin;
+ emit_signal("changed");
+}
+Vector2i TileData::get_y_sort_origin() const {
+ return y_sort_origin;
+}
+
+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] = p_occluder_polygon;
+ emit_signal("changed");
+}
+
+Ref<OccluderPolygon2D> TileData::get_occluder(int p_layer_id) const {
+ ERR_FAIL_INDEX_V(p_layer_id, occluders.size(), Ref<OccluderPolygon2D>());
+ return occluders[p_layer_id];
}
-const Map<Vector2, Ref<NavigationPolygon>> &TileSet::autotile_get_navigation_map(int p_id) const {
- static Map<Vector2, Ref<NavigationPolygon>> dummy;
- ERR_FAIL_COND_V(!tile_map.has(p_id), dummy);
- return tile_map[p_id].autotile_data.navpoly_map;
+// Physics
+int TileData::get_collision_shapes_count(int p_layer_id) const {
+ ERR_FAIL_INDEX_V(p_layer_id, physics.size(), 0);
+ return physics[p_layer_id].shapes.size();
}
-void TileSet::tile_set_occluder_offset(int p_id, const Vector2 &p_offset) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].occluder_offset = p_offset;
+void TileData::set_collision_shapes_count(int p_layer_id, int p_shapes_count) {
+ ERR_FAIL_INDEX(p_layer_id, physics.size());
+ ERR_FAIL_COND(p_shapes_count < 0);
+ physics.write[p_layer_id].shapes.resize(p_shapes_count);
+ notify_property_list_changed();
+ emit_signal("changed");
+}
+
+void TileData::add_collision_shape(int p_layer_id) {
+ ERR_FAIL_INDEX(p_layer_id, physics.size());
+ physics.write[p_layer_id].shapes.push_back(PhysicsLayerTileData::ShapeTileData());
+ emit_signal("changed");
+}
+
+void TileData::remove_collision_shape(int p_layer_id, int p_shape_index) {
+ ERR_FAIL_INDEX(p_layer_id, physics.size());
+ ERR_FAIL_INDEX(p_shape_index, physics[p_layer_id].shapes.size());
+ physics.write[p_layer_id].shapes.remove(p_shape_index);
+ emit_signal("changed");
+}
+
+void TileData::set_collision_shape_shape(int p_layer_id, int p_shape_index, Ref<Shape2D> p_shape) {
+ ERR_FAIL_INDEX(p_layer_id, physics.size());
+ ERR_FAIL_INDEX(p_shape_index, physics[p_layer_id].shapes.size());
+ physics.write[p_layer_id].shapes.write[p_shape_index].shape = p_shape;
+ emit_signal("changed");
}
-Vector2 TileSet::tile_get_occluder_offset(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Vector2());
- return tile_map[p_id].occluder_offset;
+Ref<Shape2D> TileData::get_collision_shape_shape(int p_layer_id, int p_shape_index) const {
+ ERR_FAIL_INDEX_V(p_layer_id, physics.size(), Ref<Shape2D>());
+ ERR_FAIL_INDEX_V(p_shape_index, physics[p_layer_id].shapes.size(), Ref<Shape2D>());
+ return physics[p_layer_id].shapes[p_shape_index].shape;
}
-void TileSet::tile_set_shapes(int p_id, const Vector<ShapeData> &p_shapes) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].shapes_data = p_shapes;
- for (int i = 0; i < p_shapes.size(); i++) {
- _decompose_convex_shape(p_shapes[i].shape);
+void TileData::set_collision_shape_one_way(int p_layer_id, int p_shape_index, bool p_one_way) {
+ ERR_FAIL_INDEX(p_layer_id, physics.size());
+ ERR_FAIL_INDEX(p_shape_index, physics[p_layer_id].shapes.size());
+ physics.write[p_layer_id].shapes.write[p_shape_index].one_way = p_one_way;
+ emit_signal("changed");
+}
+
+bool TileData::is_collision_shape_one_way(int p_layer_id, int p_shape_index) const {
+ ERR_FAIL_INDEX_V(p_layer_id, physics.size(), false);
+ ERR_FAIL_INDEX_V(p_shape_index, physics[p_layer_id].shapes.size(), false);
+ return physics[p_layer_id].shapes[p_shape_index].one_way;
+}
+
+void TileData::set_collision_shape_one_way_margin(int p_layer_id, int p_shape_index, float p_one_way_margin) {
+ ERR_FAIL_INDEX(p_layer_id, physics.size());
+ ERR_FAIL_INDEX(p_shape_index, physics[p_layer_id].shapes.size());
+ physics.write[p_layer_id].shapes.write[p_shape_index].one_way_margin = p_one_way_margin;
+ emit_signal("changed");
+}
+
+float TileData::get_collision_shape_one_way_margin(int p_layer_id, int p_shape_index) const {
+ ERR_FAIL_INDEX_V(p_layer_id, physics.size(), 0.0);
+ ERR_FAIL_INDEX_V(p_shape_index, physics[p_layer_id].shapes.size(), 0.0);
+ return physics[p_layer_id].shapes[p_shape_index].one_way_margin;
+}
+
+// Terrain
+void TileData::set_terrain_set(int p_terrain_set) {
+ ERR_FAIL_COND(p_terrain_set < -1);
+ if (tile_set) {
+ ERR_FAIL_COND(p_terrain_set >= tile_set->get_terrain_sets_count());
}
- emit_changed();
+ terrain_set = p_terrain_set;
+ notify_property_list_changed();
+ emit_signal("changed");
}
-Vector<TileSet::ShapeData> TileSet::tile_get_shapes(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Vector<ShapeData>());
+int TileData::get_terrain_set() const {
+ return terrain_set;
+}
- return tile_map[p_id].shapes_data;
+void TileData::set_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit, int p_terrain_index) {
+ ERR_FAIL_COND(p_terrain_index < -1);
+ if (tile_set) {
+ ERR_FAIL_COND(p_terrain_index >= tile_set->get_terrains_count(terrain_set));
+ ERR_FAIL_COND(!is_valid_peering_bit_terrain(p_peering_bit));
+ }
+ terrain_peering_bits[p_peering_bit] = p_terrain_index;
+ emit_signal("changed");
}
-int TileSet::tile_get_z_index(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), 0);
- return tile_map[p_id].z_index;
+int TileData::get_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit) const {
+ return terrain_peering_bits[p_peering_bit];
}
-void TileSet::tile_set_z_index(int p_id, int p_z_index) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].z_index = p_z_index;
- emit_changed();
+bool TileData::is_valid_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit) const {
+ ERR_FAIL_COND_V(!tile_set, false);
+
+ return tile_set->is_valid_peering_bit_terrain(terrain_set, p_peering_bit);
}
-void TileSet::_tile_set_shapes(int p_id, const Array &p_shapes) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- Vector<ShapeData> shapes_data;
- Transform2D default_transform = tile_get_shape_transform(p_id, 0);
- bool default_one_way = tile_get_shape_one_way(p_id, 0);
- Vector2 default_autotile_coord = Vector2();
- for (int i = 0; i < p_shapes.size(); i++) {
- ShapeData s = ShapeData();
+// Navigation
+void TileData::set_navigation_polygon(int p_layer_id, Ref<NavigationPolygon> p_navigation_polygon) {
+ ERR_FAIL_INDEX(p_layer_id, navigation.size());
+ navigation.write[p_layer_id] = p_navigation_polygon;
+ emit_signal("changed");
+}
- if (p_shapes[i].get_type() == Variant::OBJECT) {
- Ref<Shape2D> shape = p_shapes[i];
- if (shape.is_null()) {
- continue;
+Ref<NavigationPolygon> TileData::get_navigation_polygon(int p_layer_id) const {
+ ERR_FAIL_INDEX_V(p_layer_id, navigation.size(), Ref<NavigationPolygon>());
+ return navigation[p_layer_id];
+}
+
+// Misc
+void TileData::set_probability(float p_probability) {
+ ERR_FAIL_COND(p_probability <= 0.0);
+ probability = p_probability;
+ emit_signal("changed");
+}
+float TileData::get_probability() const {
+ return probability;
+}
+
+// Custom data
+void TileData::set_custom_data(String p_layer_name, Variant p_value) {
+ ERR_FAIL_COND(!tile_set);
+ int p_layer_id = tile_set->get_custom_data_layer_by_name(p_layer_name);
+ ERR_FAIL_COND_MSG(p_layer_id < 0, vformat("TileSet has no layer with name: %s", p_layer_name));
+ set_custom_data_by_layer_id(p_layer_id, p_value);
+}
+
+Variant TileData::get_custom_data(String p_layer_name) const {
+ ERR_FAIL_COND_V(!tile_set, Variant());
+ int p_layer_id = tile_set->get_custom_data_layer_by_name(p_layer_name);
+ ERR_FAIL_COND_V_MSG(p_layer_id < 0, Variant(), vformat("TileSet has no layer with name: %s", p_layer_name));
+ return get_custom_data_by_layer_id(p_layer_id);
+}
+
+void TileData::set_custom_data_by_layer_id(int p_layer_id, Variant p_value) {
+ ERR_FAIL_INDEX(p_layer_id, custom_data.size());
+ custom_data.write[p_layer_id] = p_value;
+ emit_signal("changed");
+}
+
+Variant TileData::get_custom_data_by_layer_id(int p_layer_id) const {
+ ERR_FAIL_INDEX_V(p_layer_id, custom_data.size(), Variant());
+ return custom_data[p_layer_id];
+}
+
+bool TileData::_set(const StringName &p_name, const Variant &p_value) {
+ 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_integer()) {
+ // 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 (!polygon.is_valid()) {
+ return false;
}
- s.shape = shape;
- s.shape_transform = default_transform;
- s.one_way_collision = default_one_way;
- s.autotile_coord = default_autotile_coord;
- } else if (p_shapes[i].get_type() == Variant::DICTIONARY) {
- Dictionary d = p_shapes[i];
+ if (layer_index >= occluders.size()) {
+ if (tile_set) {
+ return false;
+ } else {
+ occluders.resize(layer_index + 1);
+ }
+ }
+ set_occluder(layer_index, polygon);
+ return true;
+ }
+ } else if (components.size() >= 2 && components[0].begins_with("physics_layer_") && components[0].trim_prefix("physics_layer_").is_valid_integer()) {
+ // Physics layers.
+ int layer_index = components[0].trim_prefix("physics_layer_").to_int();
+ ERR_FAIL_COND_V(layer_index < 0, false);
+ if (components.size() == 2 && components[1] == "shapes_count") {
+ if (p_value.get_type() != Variant::INT) {
+ return false;
+ }
- if (d.has("shape") && d["shape"].get_type() == Variant::OBJECT) {
- s.shape = d["shape"];
- _decompose_convex_shape(s.shape);
- } else {
- continue;
+ if (layer_index >= physics.size()) {
+ if (tile_set) {
+ return false;
+ } else {
+ physics.resize(layer_index + 1);
+ }
}
+ set_collision_shapes_count(layer_index, p_value);
+ return true;
+ } else if (components.size() == 3 && components[1].begins_with("shape_") && components[1].trim_prefix("shape_").is_valid_integer()) {
+ int shape_index = components[1].trim_prefix("shape_").to_int();
+ ERR_FAIL_COND_V(shape_index < 0, false);
+
+ if (components[2] == "shape" || components[2] == "one_way" || components[2] == "one_way_margin") {
+ if (layer_index >= physics.size()) {
+ if (tile_set) {
+ return false;
+ } else {
+ physics.resize(layer_index + 1);
+ }
+ }
- if (d.has("shape_transform") && d["shape_transform"].get_type() == Variant::TRANSFORM2D) {
- s.shape_transform = d["shape_transform"];
- } else if (d.has("shape_offset") && d["shape_offset"].get_type() == Variant::VECTOR2) {
- s.shape_transform = Transform2D(0, (Vector2)d["shape_offset"]);
- } else {
- s.shape_transform = default_transform;
+ if (shape_index >= physics[layer_index].shapes.size()) {
+ physics.write[layer_index].shapes.resize(shape_index + 1);
+ }
+ }
+ if (components[2] == "shape") {
+ Ref<Shape2D> shape = p_value;
+ set_collision_shape_shape(layer_index, shape_index, shape);
+ return true;
+ } else if (components[2] == "one_way") {
+ set_collision_shape_one_way(layer_index, shape_index, p_value);
+ return true;
+ } else if (components[2] == "one_way_margin") {
+ set_collision_shape_one_way_margin(layer_index, shape_index, p_value);
+ return true;
+ }
+ }
+ } else if (components.size() == 2 && components[0].begins_with("navigation_layer_") && components[0].trim_prefix("navigation_layer_").is_valid_integer()) {
+ // Navigation layers.
+ int layer_index = components[0].trim_prefix("navigation_layer_").to_int();
+ ERR_FAIL_COND_V(layer_index < 0, false);
+ if (components[1] == "polygon") {
+ Ref<NavigationPolygon> polygon = p_value;
+ if (!polygon.is_valid()) {
+ return false;
}
- if (d.has("one_way") && d["one_way"].get_type() == Variant::BOOL) {
- s.one_way_collision = d["one_way"];
+ if (layer_index >= navigation.size()) {
+ if (tile_set) {
+ return false;
+ } else {
+ navigation.resize(layer_index + 1);
+ }
+ }
+ set_navigation_polygon(layer_index, polygon);
+ return true;
+ }
+ } else if (components.size() == 2 && components[0] == "terrains_peering_bit") {
+ // Terrains.
+ if (components[1] == "right_side") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, p_value);
+ } else if (components[1] == "right_corner") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_RIGHT_CORNER, p_value);
+ } else if (components[1] == "bottom_right_side") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, p_value);
+ } else if (components[1] == "bottom_right_corner") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER, p_value);
+ } else if (components[1] == "bottom_side") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, p_value);
+ } else if (components[1] == "bottom_corner") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_CORNER, p_value);
+ } else if (components[1] == "bottom_left_side") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, p_value);
+ } else if (components[1] == "bottom_left_corner") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER, p_value);
+ } else if (components[1] == "left_side") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_LEFT_SIDE, p_value);
+ } else if (components[1] == "left_corner") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_LEFT_CORNER, p_value);
+ } else if (components[1] == "top_left_side") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, p_value);
+ } else if (components[1] == "top_left_corner") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER, p_value);
+ } else if (components[1] == "top_side") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_SIDE, p_value);
+ } else if (components[1] == "top_corner") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_CORNER, p_value);
+ } else if (components[1] == "top_right_side") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, p_value);
+ } else if (components[1] == "top_right_corner") {
+ set_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER, p_value);
+ } else {
+ return false;
+ }
+ return true;
+ } else if (components.size() == 1 && components[0].begins_with("custom_data_") && components[0].trim_prefix("custom_data_").is_valid_integer()) {
+ // Custom data layers.
+ int layer_index = components[0].trim_prefix("custom_data_").to_int();
+ ERR_FAIL_COND_V(layer_index < 0, false);
+
+ if (layer_index >= custom_data.size()) {
+ if (tile_set) {
+ return false;
} else {
- s.one_way_collision = default_one_way;
+ custom_data.resize(layer_index + 1);
}
+ }
+ set_custom_data_by_layer_id(layer_index, p_value);
+
+ return true;
+ }
+
+ return false;
+}
- if (d.has("one_way_margin") && d["one_way_margin"].is_num()) {
- s.one_way_collision_margin = d["one_way_margin"];
+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_integer()) {
+ // 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;
+ }
+ } else if (components.size() >= 2 && components[0].begins_with("physics_layer_") && components[0].trim_prefix("physics_layer_").is_valid_integer()) {
+ // Physics layers.
+ int layer_index = components[0].trim_prefix("physics_layer_").to_int();
+ ERR_FAIL_COND_V(layer_index < 0, false);
+ if (layer_index >= physics.size()) {
+ return false;
+ }
+ if (components.size() == 2 && components[1] == "shapes_count") {
+ r_ret = get_collision_shapes_count(layer_index);
+ return true;
+ } else if (components.size() == 3 && components[1].begins_with("shape_") && components[1].trim_prefix("shape_").is_valid_integer()) {
+ int shape_index = components[1].trim_prefix("shape_").to_int();
+ ERR_FAIL_COND_V(shape_index < 0, false);
+ if (shape_index >= physics[layer_index].shapes.size()) {
+ return false;
+ }
+ if (components[2] == "shape") {
+ r_ret = get_collision_shape_shape(layer_index, shape_index);
+ return true;
+ } else if (components[2] == "one_way") {
+ r_ret = is_collision_shape_one_way(layer_index, shape_index);
+ return true;
+ } else if (components[2] == "one_way_margin") {
+ r_ret = get_collision_shape_one_way_margin(layer_index, shape_index);
+ return true;
+ }
+ }
+ } else if (components.size() == 2 && components[0] == "terrains_peering_bit") {
+ // Terrains.
+ if (components[1] == "right_side") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_RIGHT_SIDE];
+ } else if (components[1] == "right_corner") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_RIGHT_CORNER];
+ } else if (components[1] == "bottom_right_side") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE];
+ } else if (components[1] == "bottom_right_corner") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER];
+ } else if (components[1] == "bottom_side") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_BOTTOM_SIDE];
+ } else if (components[1] == "bottom_corner") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_BOTTOM_CORNER];
+ } else if (components[1] == "bottom_left_side") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE];
+ } else if (components[1] == "bottom_left_corner") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER];
+ } else if (components[1] == "left_side") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_LEFT_SIDE];
+ } else if (components[1] == "left_corner") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_LEFT_CORNER];
+ } else if (components[1] == "top_left_side") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE];
+ } else if (components[1] == "top_left_corner") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER];
+ } else if (components[1] == "top_side") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_TOP_SIDE];
+ } else if (components[1] == "top_corner") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_TOP_CORNER];
+ } else if (components[1] == "top_right_side") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE];
+ } else if (components[1] == "top_right_corner") {
+ r_ret = terrain_peering_bits[TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER];
} else {
- s.one_way_collision_margin = 1.0;
+ return false;
+ }
+ return true;
+ } else if (components.size() == 2 && components[0].begins_with("navigation_layer_") && components[0].trim_prefix("navigation_layer_").is_valid_integer()) {
+ // Occlusion layers.
+ int layer_index = components[0].trim_prefix("navigation_layer_").to_int();
+ ERR_FAIL_COND_V(layer_index < 0, false);
+ if (layer_index >= navigation.size()) {
+ return false;
+ }
+ if (components[1] == "polygon") {
+ r_ret = get_navigation_polygon(layer_index);
+ return true;
+ }
+ } else if (components.size() == 1 && components[0].begins_with("custom_data_") && components[0].trim_prefix("custom_data_").is_valid_integer()) {
+ // Custom data layers.
+ int layer_index = components[0].trim_prefix("custom_data_").to_int();
+ ERR_FAIL_COND_V(layer_index < 0, false);
+ if (layer_index >= custom_data.size()) {
+ return false;
}
+ r_ret = get_custom_data_by_layer_id(layer_index);
+ return true;
+ }
+ }
- if (d.has("autotile_coord") && d["autotile_coord"].get_type() == Variant::VECTOR2) {
- s.autotile_coord = d["autotile_coord"];
- } else {
- s.autotile_coord = default_autotile_coord;
+ return false;
+}
+
+void TileData::_get_property_list(List<PropertyInfo> *p_list) const {
+ PropertyInfo property_info;
+ // Add the groups manually.
+ if (tile_set) {
+ // Occlusion layers.
+ p_list->push_back(PropertyInfo(Variant::NIL, "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/polygon", i), PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_DEFAULT);
+ if (!occluders[i].is_valid()) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
}
+ p_list->push_back(property_info);
+ }
- } else {
- ERR_CONTINUE_MSG(true, "Expected an array of objects or dictionaries for tile_set_shapes.");
+ // Physics layers.
+ p_list->push_back(PropertyInfo(Variant::NIL, "Physics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ for (int i = 0; i < physics.size(); i++) {
+ p_list->push_back(PropertyInfo(Variant::INT, vformat("physics_layer_%d/shapes_count", i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
+
+ for (int j = 0; j < physics[i].shapes.size(); j++) {
+ // physics_layer_%d/shapes_count
+ property_info = PropertyInfo(Variant::OBJECT, vformat("physics_layer_%d/shape_%d/shape", i, j), PROPERTY_HINT_RESOURCE_TYPE, "Shape2D", PROPERTY_USAGE_DEFAULT);
+ if (!physics[i].shapes[j].shape.is_valid()) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+
+ // physics_layer_%d/shape_%d/one_way
+ property_info = PropertyInfo(Variant::BOOL, vformat("physics_layer_%d/shape_%d/one_way", i, j));
+ if (physics[i].shapes[j].one_way == false) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+
+ // physics_layer_%d/shape_%d/one_way_margin
+ property_info = PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/shape_%d/one_way_margin", i, j));
+ if (physics[i].shapes[j].one_way_margin == 1.0) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ }
+
+ // Terrain data
+ if (terrain_set >= 0) {
+ p_list->push_back(PropertyInfo(Variant::NIL, "Terrains", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_RIGHT_SIDE)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/right_side");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_RIGHT_SIDE) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_RIGHT_CORNER)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/right_corner");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_RIGHT_CORNER) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/bottom_right_side");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/bottom_right_corner");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/bottom_side");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_CORNER)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/bottom_corner");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_CORNER) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/bottom_left_side");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/bottom_left_corner");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_LEFT_SIDE)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/left_side");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_LEFT_SIDE) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_LEFT_CORNER)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/left_corner");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_LEFT_CORNER) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/top_left_side");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/top_left_corner");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_SIDE)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/top_side");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_SIDE) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_CORNER)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/top_corner");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_CORNER) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/top_right_side");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+ if (is_valid_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER)) {
+ property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/top_right_corner");
+ if (get_peering_bit_terrain(TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER) == -1) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
}
- shapes_data.push_back(s);
+ // Navigation layers.
+ p_list->push_back(PropertyInfo(Variant::NIL, "Navigation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ for (int i = 0; i < navigation.size(); i++) {
+ property_info = PropertyInfo(Variant::OBJECT, vformat("navigation_layer_%d/polygon", i), PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon", PROPERTY_USAGE_DEFAULT);
+ if (!navigation[i].is_valid()) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
+
+ // Custom data layers.
+ p_list->push_back(PropertyInfo(Variant::NIL, "Custom data", PROPERTY_HINT_NONE, "custom_data_", PROPERTY_USAGE_GROUP));
+ for (int i = 0; i < custom_data.size(); i++) {
+ Variant default_val;
+ Callable::CallError error;
+ Variant::construct(custom_data[i].get_type(), default_val, nullptr, 0, error);
+ property_info = PropertyInfo(tile_set->get_custom_data_type(i), vformat("custom_data_%d", i), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
+ if (custom_data[i] == default_val) {
+ property_info.usage ^= PROPERTY_USAGE_STORAGE;
+ }
+ p_list->push_back(property_info);
+ }
}
+}
- tile_map[p_id].shapes_data = shapes_data;
- emit_changed();
+void TileData::_bind_methods() {
+ // Rendering.
+ ClassDB::bind_method(D_METHOD("set_flip_h", "flip_h"), &TileData::set_flip_h);
+ ClassDB::bind_method(D_METHOD("get_flip_h"), &TileData::get_flip_h);
+ ClassDB::bind_method(D_METHOD("set_flip_v", "flip_v"), &TileData::set_flip_v);
+ ClassDB::bind_method(D_METHOD("get_flip_v"), &TileData::get_flip_v);
+ ClassDB::bind_method(D_METHOD("set_transpose", "transpose"), &TileData::set_transpose);
+ ClassDB::bind_method(D_METHOD("get_transpose"), &TileData::get_transpose);
+ ClassDB::bind_method(D_METHOD("tile_set_material", "material"), &TileData::tile_set_material);
+ ClassDB::bind_method(D_METHOD("tile_get_material"), &TileData::tile_get_material);
+ ClassDB::bind_method(D_METHOD("set_texture_offset", "texture_offset"), &TileData::set_texture_offset);
+ ClassDB::bind_method(D_METHOD("get_texture_offset"), &TileData::get_texture_offset);
+ ClassDB::bind_method(D_METHOD("set_modulate", "modulate"), &TileData::set_modulate);
+ ClassDB::bind_method(D_METHOD("get_modulate"), &TileData::get_modulate);
+ ClassDB::bind_method(D_METHOD("set_z_index", "z_index"), &TileData::set_z_index);
+ ClassDB::bind_method(D_METHOD("get_z_index"), &TileData::get_z_index);
+ 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", "layer_id", "occluder_polygon"), &TileData::set_occluder);
+ ClassDB::bind_method(D_METHOD("get_occluder", "layer_id"), &TileData::get_occluder);
+
+ // Physics.
+ ClassDB::bind_method(D_METHOD("get_collision_shapes_count", "layer_id"), &TileData::get_collision_shapes_count);
+ ClassDB::bind_method(D_METHOD("set_collision_shapes_count", "layer_id", "shapes_count"), &TileData::set_collision_shapes_count);
+ ClassDB::bind_method(D_METHOD("add_collision_shape", "layer_id"), &TileData::add_collision_shape);
+ ClassDB::bind_method(D_METHOD("remove_collision_shape", "layer_id", "shape_index"), &TileData::remove_collision_shape);
+ ClassDB::bind_method(D_METHOD("set_collision_shape_shape", "layer_id", "shape_index", "shape"), &TileData::set_collision_shape_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_shape_shape", "layer_id", "shape_index"), &TileData::get_collision_shape_shape);
+ ClassDB::bind_method(D_METHOD("set_collision_shape_one_way", "layer_id", "shape_index", "one_way"), &TileData::set_collision_shape_one_way);
+ ClassDB::bind_method(D_METHOD("is_collision_shape_one_way", "layer_id", "shape_index"), &TileData::is_collision_shape_one_way);
+ ClassDB::bind_method(D_METHOD("set_collision_shape_one_way_margin", "layer_id", "shape_index", "one_way_margin"), &TileData::set_collision_shape_one_way_margin);
+ ClassDB::bind_method(D_METHOD("get_collision_shape_one_way_margin", "layer_id", "shape_index"), &TileData::get_collision_shape_one_way_margin);
+
+ // Terrain
+ ClassDB::bind_method(D_METHOD("set_terrain_set", "terrain_set"), &TileData::set_terrain_set);
+ ClassDB::bind_method(D_METHOD("get_terrain_set"), &TileData::get_terrain_set);
+ ClassDB::bind_method(D_METHOD("set_peering_bit_terrain", "peering_bit", "terrain"), &TileData::set_peering_bit_terrain);
+ ClassDB::bind_method(D_METHOD("get_peering_bit_terrain", "peering_bit"), &TileData::get_peering_bit_terrain);
+
+ // Navigation
+ ClassDB::bind_method(D_METHOD("set_navigation_polygon", "layer_id", "navigation_polygon"), &TileData::set_navigation_polygon);
+ ClassDB::bind_method(D_METHOD("get_navigation_polygon", "layer_id"), &TileData::get_navigation_polygon);
+
+ // Misc.
+ ClassDB::bind_method(D_METHOD("set_probability", "probability"), &TileData::set_probability);
+ ClassDB::bind_method(D_METHOD("get_probability"), &TileData::get_probability);
+
+ // Custom data.
+ ClassDB::bind_method(D_METHOD("set_custom_data", "layer_name", "value"), &TileData::set_custom_data);
+ ClassDB::bind_method(D_METHOD("get_custom_data", "layer_name"), &TileData::get_custom_data);
+ ClassDB::bind_method(D_METHOD("set_custom_data_by_layer_id", "layer_id", "value"), &TileData::set_custom_data_by_layer_id);
+ ClassDB::bind_method(D_METHOD("get_custom_data_by_layer_id", "layer_id"), &TileData::get_custom_data_by_layer_id);
+
+ ADD_GROUP("Rendering", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "get_flip_h");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_v"), "set_flip_v", "get_flip_v");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transpose"), "set_transpose", "get_transpose");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "texture_offset"), "set_texture_offset", "get_texture_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "z_index"), "set_z_index", "get_z_index");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "y_sort_origin"), "set_y_sort_origin", "get_y_sort_origin");
+
+ ADD_GROUP("Terrains", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "terrain_set"), "set_terrain_set", "get_terrain_set");
+
+ ADD_GROUP("Miscellaneous", "");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "probability"), "set_probability", "get_probability");
+
+ ADD_SIGNAL(MethodInfo("changed"));
}
-Array TileSet::_tile_get_shapes(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), Array());
- Array arr;
+/////////////////////////////// TileSetAtlasPluginTerrain //////////////////////////////////////
+
+// --- PLUGINS ---
+void TileSetAtlasPluginTerrain::_draw_square_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
+ Rect2 bit_rect;
+ bit_rect.size = Vector2(p_size) / 3;
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
+ bit_rect.position = Vector2(1, -1);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
+ bit_rect.position = Vector2(1, 1);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
+ bit_rect.position = Vector2(-1, 1);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
+ bit_rect.position = Vector2(-3, 1);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
+ bit_rect.position = Vector2(-3, -1);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
+ bit_rect.position = Vector2(-3, -3);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_SIDE:
+ bit_rect.position = Vector2(-1, -3);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
+ bit_rect.position = Vector2(1, -3);
+ break;
+ default:
+ break;
+ }
+ bit_rect.position *= Vector2(p_size) / 6.0;
+ p_canvas_item->draw_rect(bit_rect, p_color);
+}
- Vector<ShapeData> data = tile_map[p_id].shapes_data;
- for (int i = 0; i < data.size(); i++) {
- Dictionary shape_data;
- shape_data["shape"] = data[i].shape;
- shape_data["shape_transform"] = data[i].shape_transform;
- shape_data["one_way"] = data[i].one_way_collision;
- shape_data["one_way_margin"] = data[i].one_way_collision_margin;
- shape_data["autotile_coord"] = data[i].autotile_coord;
- arr.push_back(shape_data);
+void TileSetAtlasPluginTerrain::_draw_square_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
+ PackedColorArray color_array;
+ color_array.push_back(p_color);
+
+ Vector2 unit = Vector2(p_size) / 6.0;
+ PackedVector2Array polygon;
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
+ polygon.push_back(Vector2(0, 3) * unit);
+ polygon.push_back(Vector2(3, 3) * unit);
+ polygon.push_back(Vector2(3, 0) * unit);
+ polygon.push_back(Vector2(1, 0) * unit);
+ polygon.push_back(Vector2(1, 1) * unit);
+ polygon.push_back(Vector2(0, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
+ polygon.push_back(Vector2(0, 3) * unit);
+ polygon.push_back(Vector2(-3, 3) * unit);
+ polygon.push_back(Vector2(-3, 0) * unit);
+ polygon.push_back(Vector2(-1, 0) * unit);
+ polygon.push_back(Vector2(-1, 1) * unit);
+ polygon.push_back(Vector2(0, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
+ polygon.push_back(Vector2(0, -3) * unit);
+ polygon.push_back(Vector2(-3, -3) * unit);
+ polygon.push_back(Vector2(-3, 0) * unit);
+ polygon.push_back(Vector2(-1, 0) * unit);
+ polygon.push_back(Vector2(-1, -1) * unit);
+ polygon.push_back(Vector2(0, -1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
+ polygon.push_back(Vector2(0, -3) * unit);
+ polygon.push_back(Vector2(3, -3) * unit);
+ polygon.push_back(Vector2(3, 0) * unit);
+ polygon.push_back(Vector2(1, 0) * unit);
+ polygon.push_back(Vector2(1, -1) * unit);
+ polygon.push_back(Vector2(0, -1) * unit);
+ break;
+ default:
+ break;
+ }
+ if (!polygon.is_empty()) {
+ p_canvas_item->draw_polygon(polygon, color_array);
}
+}
- return arr;
+void TileSetAtlasPluginTerrain::_draw_square_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
+ PackedColorArray color_array;
+ color_array.push_back(p_color);
+
+ Vector2 unit = Vector2(p_size) / 6.0;
+ PackedVector2Array polygon;
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
+ polygon.push_back(Vector2(1, -1) * unit);
+ polygon.push_back(Vector2(3, -3) * unit);
+ polygon.push_back(Vector2(3, 3) * unit);
+ polygon.push_back(Vector2(1, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
+ polygon.push_back(Vector2(-1, 1) * unit);
+ polygon.push_back(Vector2(-3, 3) * unit);
+ polygon.push_back(Vector2(3, 3) * unit);
+ polygon.push_back(Vector2(1, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
+ polygon.push_back(Vector2(-1, -1) * unit);
+ polygon.push_back(Vector2(-3, -3) * unit);
+ polygon.push_back(Vector2(-3, 3) * unit);
+ polygon.push_back(Vector2(-1, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_SIDE:
+ polygon.push_back(Vector2(-1, -1) * unit);
+ polygon.push_back(Vector2(-3, -3) * unit);
+ polygon.push_back(Vector2(3, -3) * unit);
+ polygon.push_back(Vector2(1, -1) * unit);
+ break;
+ default:
+ break;
+ }
+ if (!polygon.is_empty()) {
+ p_canvas_item->draw_polygon(polygon, color_array);
+ }
}
-Array TileSet::_get_tiles_ids() const {
- Array arr;
+void TileSetAtlasPluginTerrain::_draw_isometric_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
+ PackedColorArray color_array;
+ color_array.push_back(p_color);
+
+ Vector2 unit = Vector2(p_size) / 6.0;
+ PackedVector2Array polygon;
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
+ polygon.push_back(Vector2(1, 0) * unit);
+ polygon.push_back(Vector2(2, -1) * unit);
+ polygon.push_back(Vector2(3, 0) * unit);
+ polygon.push_back(Vector2(2, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
+ polygon.push_back(Vector2(0, 1) * unit);
+ polygon.push_back(Vector2(1, 2) * unit);
+ polygon.push_back(Vector2(2, 1) * unit);
+ polygon.push_back(Vector2(1, 0) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER:
+ polygon.push_back(Vector2(0, 1) * unit);
+ polygon.push_back(Vector2(-1, 2) * unit);
+ polygon.push_back(Vector2(0, 3) * unit);
+ polygon.push_back(Vector2(1, 2) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
+ polygon.push_back(Vector2(0, 1) * unit);
+ polygon.push_back(Vector2(-1, 2) * unit);
+ polygon.push_back(Vector2(-2, 1) * unit);
+ polygon.push_back(Vector2(-1, 0) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
+ polygon.push_back(Vector2(-1, 0) * unit);
+ polygon.push_back(Vector2(-2, -1) * unit);
+ polygon.push_back(Vector2(-3, 0) * unit);
+ polygon.push_back(Vector2(-2, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
+ polygon.push_back(Vector2(0, -1) * unit);
+ polygon.push_back(Vector2(-1, -2) * unit);
+ polygon.push_back(Vector2(-2, -1) * unit);
+ polygon.push_back(Vector2(-1, 0) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_CORNER:
+ polygon.push_back(Vector2(0, -1) * unit);
+ polygon.push_back(Vector2(-1, -2) * unit);
+ polygon.push_back(Vector2(0, -3) * unit);
+ polygon.push_back(Vector2(1, -2) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
+ polygon.push_back(Vector2(0, -1) * unit);
+ polygon.push_back(Vector2(1, -2) * unit);
+ polygon.push_back(Vector2(2, -1) * unit);
+ polygon.push_back(Vector2(1, 0) * unit);
+ break;
+ default:
+ break;
+ }
+ if (!polygon.is_empty()) {
+ p_canvas_item->draw_polygon(polygon, color_array);
+ }
+}
- for (Map<int, TileData>::Element *E = tile_map.front(); E; E = E->next()) {
- arr.push_back(E->key());
+void TileSetAtlasPluginTerrain::_draw_isometric_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
+ PackedColorArray color_array;
+ color_array.push_back(p_color);
+
+ Vector2 unit = Vector2(p_size) / 6.0;
+ PackedVector2Array polygon;
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
+ polygon.push_back(Vector2(0.5, -0.5) * unit);
+ polygon.push_back(Vector2(1.5, -1.5) * unit);
+ polygon.push_back(Vector2(3, 0) * unit);
+ polygon.push_back(Vector2(1.5, 1.5) * unit);
+ polygon.push_back(Vector2(0.5, 0.5) * unit);
+ polygon.push_back(Vector2(1, 0) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER:
+ polygon.push_back(Vector2(-0.5, 0.5) * unit);
+ polygon.push_back(Vector2(-1.5, 1.5) * unit);
+ polygon.push_back(Vector2(0, 3) * unit);
+ polygon.push_back(Vector2(1.5, 1.5) * unit);
+ polygon.push_back(Vector2(0.5, 0.5) * unit);
+ polygon.push_back(Vector2(0, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
+ polygon.push_back(Vector2(-0.5, -0.5) * unit);
+ polygon.push_back(Vector2(-1.5, -1.5) * unit);
+ polygon.push_back(Vector2(-3, 0) * unit);
+ polygon.push_back(Vector2(-1.5, 1.5) * unit);
+ polygon.push_back(Vector2(-0.5, 0.5) * unit);
+ polygon.push_back(Vector2(-1, 0) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_CORNER:
+ polygon.push_back(Vector2(-0.5, -0.5) * unit);
+ polygon.push_back(Vector2(-1.5, -1.5) * unit);
+ polygon.push_back(Vector2(0, -3) * unit);
+ polygon.push_back(Vector2(1.5, -1.5) * unit);
+ polygon.push_back(Vector2(0.5, -0.5) * unit);
+ polygon.push_back(Vector2(0, -1) * unit);
+ break;
+ default:
+ break;
}
+ if (!polygon.is_empty()) {
+ p_canvas_item->draw_polygon(polygon, color_array);
+ }
+}
- return arr;
+void TileSetAtlasPluginTerrain::_draw_isometric_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) {
+ PackedColorArray color_array;
+ color_array.push_back(p_color);
+
+ Vector2 unit = Vector2(p_size) / 6.0;
+ PackedVector2Array polygon;
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
+ polygon.push_back(Vector2(1, 0) * unit);
+ polygon.push_back(Vector2(3, 0) * unit);
+ polygon.push_back(Vector2(0, 3) * unit);
+ polygon.push_back(Vector2(0, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
+ polygon.push_back(Vector2(-1, 0) * unit);
+ polygon.push_back(Vector2(-3, 0) * unit);
+ polygon.push_back(Vector2(0, 3) * unit);
+ polygon.push_back(Vector2(0, 1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
+ polygon.push_back(Vector2(-1, 0) * unit);
+ polygon.push_back(Vector2(-3, 0) * unit);
+ polygon.push_back(Vector2(0, -3) * unit);
+ polygon.push_back(Vector2(0, -1) * unit);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
+ polygon.push_back(Vector2(1, 0) * unit);
+ polygon.push_back(Vector2(3, 0) * unit);
+ polygon.push_back(Vector2(0, -3) * unit);
+ polygon.push_back(Vector2(0, -1) * unit);
+ break;
+ default:
+ break;
+ }
+ if (!polygon.is_empty()) {
+ p_canvas_item->draw_polygon(polygon, color_array);
+ }
}
-void TileSet::_decompose_convex_shape(Ref<Shape2D> p_shape) {
- if (Engine::get_singleton()->is_editor_hint()) {
- return;
+void TileSetAtlasPluginTerrain::_draw_half_offset_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
+ PackedColorArray color_array;
+ color_array.push_back(p_color);
+
+ PackedVector2Array point_list;
+ point_list.push_back(Vector2(3, (3.0 * (1.0 - p_overlap * 2.0)) / 2.0));
+ point_list.push_back(Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(2, 3.0 * (1.0 - (p_overlap * 2.0) * 2.0 / 3.0)));
+ point_list.push_back(Vector2(1, 3.0 - p_overlap * 2.0));
+ point_list.push_back(Vector2(0, 3));
+ point_list.push_back(Vector2(-1, 3.0 - p_overlap * 2.0));
+ point_list.push_back(Vector2(-2, 3.0 * (1.0 - (p_overlap * 2.0) * 2.0 / 3.0)));
+ point_list.push_back(Vector2(-3, 3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(-3, (3.0 * (1.0 - p_overlap * 2.0)) / 2.0));
+ point_list.push_back(Vector2(-3, -(3.0 * (1.0 - p_overlap * 2.0)) / 2.0));
+ point_list.push_back(Vector2(-3, -3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(-2, -3.0 * (1.0 - (p_overlap * 2.0) * 2.0 / 3.0)));
+ point_list.push_back(Vector2(-1, -(3.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(0, -3));
+ point_list.push_back(Vector2(1, -(3.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(2, -3.0 * (1.0 - (p_overlap * 2.0) * 2.0 / 3.0)));
+ point_list.push_back(Vector2(3, -3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(3, -(3.0 * (1.0 - p_overlap * 2.0)) / 2.0));
+
+ Vector2 unit = Vector2(p_size) / 6.0;
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = point_list[i] * unit;
+ }
+
+ PackedVector2Array polygon;
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
+ polygon.push_back(point_list[17]);
+ polygon.push_back(point_list[0]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
+ polygon.push_back(point_list[0]);
+ polygon.push_back(point_list[1]);
+ polygon.push_back(point_list[2]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
+ polygon.push_back(point_list[2]);
+ polygon.push_back(point_list[3]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER:
+ polygon.push_back(point_list[3]);
+ polygon.push_back(point_list[4]);
+ polygon.push_back(point_list[5]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
+ polygon.push_back(point_list[5]);
+ polygon.push_back(point_list[6]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
+ polygon.push_back(point_list[6]);
+ polygon.push_back(point_list[7]);
+ polygon.push_back(point_list[8]);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
+ polygon.push_back(point_list[8]);
+ polygon.push_back(point_list[9]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
+ polygon.push_back(point_list[9]);
+ polygon.push_back(point_list[10]);
+ polygon.push_back(point_list[11]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
+ polygon.push_back(point_list[11]);
+ polygon.push_back(point_list[12]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_CORNER:
+ polygon.push_back(point_list[12]);
+ polygon.push_back(point_list[13]);
+ polygon.push_back(point_list[14]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
+ polygon.push_back(point_list[14]);
+ polygon.push_back(point_list[15]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
+ polygon.push_back(point_list[15]);
+ polygon.push_back(point_list[16]);
+ polygon.push_back(point_list[17]);
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = Vector2(point_list[i].y, point_list[i].x);
+ }
+ }
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
+ polygon.push_back(point_list[3]);
+ polygon.push_back(point_list[4]);
+ polygon.push_back(point_list[5]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
+ polygon.push_back(point_list[2]);
+ polygon.push_back(point_list[3]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
+ polygon.push_back(point_list[0]);
+ polygon.push_back(point_list[1]);
+ polygon.push_back(point_list[2]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
+ polygon.push_back(point_list[17]);
+ polygon.push_back(point_list[0]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
+ polygon.push_back(point_list[15]);
+ polygon.push_back(point_list[16]);
+ polygon.push_back(point_list[17]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
+ polygon.push_back(point_list[14]);
+ polygon.push_back(point_list[15]);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
+ polygon.push_back(point_list[12]);
+ polygon.push_back(point_list[13]);
+ polygon.push_back(point_list[14]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
+ polygon.push_back(point_list[11]);
+ polygon.push_back(point_list[12]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
+ polygon.push_back(point_list[9]);
+ polygon.push_back(point_list[10]);
+ polygon.push_back(point_list[11]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_SIDE:
+ polygon.push_back(point_list[8]);
+ polygon.push_back(point_list[9]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
+ polygon.push_back(point_list[6]);
+ polygon.push_back(point_list[7]);
+ polygon.push_back(point_list[8]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
+ polygon.push_back(point_list[5]);
+ polygon.push_back(point_list[6]);
+ break;
+ default:
+ break;
+ }
+ }
+
+ int half_polygon_size = polygon.size();
+ for (int i = 0; i < half_polygon_size; i++) {
+ polygon.push_back(polygon[half_polygon_size - 1 - i] / 3.0);
+ }
+
+ if (!polygon.is_empty()) {
+ p_canvas_item->draw_polygon(polygon, color_array);
+ }
+}
+
+void TileSetAtlasPluginTerrain::_draw_half_offset_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
+ PackedColorArray color_array;
+ color_array.push_back(p_color);
+
+ PackedVector2Array point_list;
+ point_list.push_back(Vector2(3, 0));
+ point_list.push_back(Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(1.5, (3.0 * (1.0 - p_overlap * 2.0) + 3.0) / 2.0));
+ point_list.push_back(Vector2(0, 3));
+ point_list.push_back(Vector2(-1.5, (3.0 * (1.0 - p_overlap * 2.0) + 3.0) / 2.0));
+ point_list.push_back(Vector2(-3, 3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(-3, 0));
+ point_list.push_back(Vector2(-3, -3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(-1.5, -(3.0 * (1.0 - p_overlap * 2.0) + 3.0) / 2.0));
+ point_list.push_back(Vector2(0, -3));
+ point_list.push_back(Vector2(1.5, -(3.0 * (1.0 - p_overlap * 2.0) + 3.0) / 2.0));
+ point_list.push_back(Vector2(3, -3.0 * (1.0 - p_overlap * 2.0)));
+
+ Vector2 unit = Vector2(p_size) / 6.0;
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = point_list[i] * unit;
+ }
+
+ PackedVector2Array polygon;
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
+ polygon.push_back(point_list[0]);
+ polygon.push_back(point_list[1]);
+ polygon.push_back(point_list[2]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_CORNER:
+ polygon.push_back(point_list[2]);
+ polygon.push_back(point_list[3]);
+ polygon.push_back(point_list[4]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
+ polygon.push_back(point_list[4]);
+ polygon.push_back(point_list[5]);
+ polygon.push_back(point_list[6]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
+ polygon.push_back(point_list[6]);
+ polygon.push_back(point_list[7]);
+ polygon.push_back(point_list[8]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_CORNER:
+ polygon.push_back(point_list[8]);
+ polygon.push_back(point_list[9]);
+ polygon.push_back(point_list[10]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
+ polygon.push_back(point_list[10]);
+ polygon.push_back(point_list[11]);
+ polygon.push_back(point_list[0]);
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = Vector2(point_list[i].y, point_list[i].x);
+ }
+ }
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_CORNER:
+ polygon.push_back(point_list[2]);
+ polygon.push_back(point_list[3]);
+ polygon.push_back(point_list[4]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER:
+ polygon.push_back(point_list[0]);
+ polygon.push_back(point_list[1]);
+ polygon.push_back(point_list[2]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER:
+ polygon.push_back(point_list[10]);
+ polygon.push_back(point_list[11]);
+ polygon.push_back(point_list[0]);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_CORNER:
+ polygon.push_back(point_list[8]);
+ polygon.push_back(point_list[9]);
+ polygon.push_back(point_list[10]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER:
+ polygon.push_back(point_list[6]);
+ polygon.push_back(point_list[7]);
+ polygon.push_back(point_list[8]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER:
+ polygon.push_back(point_list[4]);
+ polygon.push_back(point_list[5]);
+ polygon.push_back(point_list[6]);
+ break;
+ default:
+ break;
+ }
+ }
+
+ int half_polygon_size = polygon.size();
+ for (int i = 0; i < half_polygon_size; i++) {
+ polygon.push_back(polygon[half_polygon_size - 1 - i] / 3.0);
+ }
+
+ if (!polygon.is_empty()) {
+ p_canvas_item->draw_polygon(polygon, color_array);
+ }
+}
+
+void TileSetAtlasPluginTerrain::_draw_half_offset_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) {
+ PackedColorArray color_array;
+ color_array.push_back(p_color);
+
+ PackedVector2Array point_list;
+ point_list.push_back(Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(0, 3));
+ point_list.push_back(Vector2(-3, 3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(-3, -3.0 * (1.0 - p_overlap * 2.0)));
+ point_list.push_back(Vector2(0, -3));
+ point_list.push_back(Vector2(3, -3.0 * (1.0 - p_overlap * 2.0)));
+
+ Vector2 unit = Vector2(p_size) / 6.0;
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = point_list[i] * unit;
+ }
+
+ PackedVector2Array polygon;
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
+ polygon.push_back(point_list[5]);
+ polygon.push_back(point_list[0]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
+ polygon.push_back(point_list[0]);
+ polygon.push_back(point_list[1]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
+ polygon.push_back(point_list[1]);
+ polygon.push_back(point_list[2]);
+ break;
+ case TileSet::CELL_NEIGHBOR_LEFT_SIDE:
+ polygon.push_back(point_list[2]);
+ polygon.push_back(point_list[3]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
+ polygon.push_back(point_list[3]);
+ polygon.push_back(point_list[4]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
+ polygon.push_back(point_list[4]);
+ polygon.push_back(point_list[5]);
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
+ for (int i = 0; i < point_list.size(); i++) {
+ point_list.write[i] = Vector2(point_list[i].y, point_list[i].x);
+ }
+ }
+ switch (p_bit) {
+ case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE:
+ polygon.push_back(point_list[0]);
+ polygon.push_back(point_list[1]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_SIDE:
+ polygon.push_back(point_list[5]);
+ polygon.push_back(point_list[0]);
+ break;
+ case TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE:
+ polygon.push_back(point_list[4]);
+ polygon.push_back(point_list[5]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE:
+ polygon.push_back(point_list[3]);
+ polygon.push_back(point_list[4]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_SIDE:
+ polygon.push_back(point_list[2]);
+ polygon.push_back(point_list[3]);
+ break;
+ case TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE:
+ polygon.push_back(point_list[1]);
+ polygon.push_back(point_list[2]);
+ break;
+ default:
+ break;
+ }
+ }
+
+ int half_polygon_size = polygon.size();
+ for (int i = 0; i < half_polygon_size; i++) {
+ polygon.push_back(polygon[half_polygon_size - 1 - i] / 3.0);
+ }
+
+ if (!polygon.is_empty()) {
+ p_canvas_item->draw_polygon(polygon, color_array);
}
- Ref<ConvexPolygonShape2D> convex = p_shape;
- if (!convex.is_valid()) {
+}
+
+#define TERRAIN_ALPHA 0.8
+
+#define DRAW_TERRAIN_BIT(f, bit) \
+ { \
+ int terrain_id = p_tile_data->get_peering_bit_terrain((bit)); \
+ if (terrain_id >= 0) { \
+ Color color = p_tile_set->get_terrain_color(terrain_set, terrain_id); \
+ color.a = TERRAIN_ALPHA; \
+ f(p_canvas_item, color, size, (bit)); \
+ } \
+ }
+
+#define DRAW_HALF_OFFSET_TERRAIN_BIT(f, bit, overlap, half_offset_axis) \
+ { \
+ int terrain_id = p_tile_data->get_peering_bit_terrain((bit)); \
+ if (terrain_id >= 0) { \
+ Color color = p_tile_set->get_terrain_color(terrain_set, terrain_id); \
+ color.a = TERRAIN_ALPHA; \
+ f(p_canvas_item, color, size, (bit), overlap, half_offset_axis); \
+ } \
+ }
+
+void TileSetAtlasPluginTerrain::draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, const TileData *p_tile_data) {
+ ERR_FAIL_COND(!p_tile_set);
+ ERR_FAIL_COND(!p_tile_data);
+
+ int terrain_set = p_tile_data->get_terrain_set();
+ if (terrain_set < 0) {
return;
}
- Vector<Vector<Vector2>> decomp = Geometry2D::decompose_polygon_in_convex(convex->get_points());
- if (decomp.size() > 1) {
- Array sub_shapes;
- for (int i = 0; i < decomp.size(); i++) {
- Ref<ConvexPolygonShape2D> _convex = memnew(ConvexPolygonShape2D);
- _convex->set_points(decomp[i]);
- sub_shapes.append(_convex);
+ TileSet::TerrainMode terrain_mode = p_tile_set->get_terrain_set_mode(terrain_set);
+
+ TileSet::TileShape shape = p_tile_set->get_tile_shape();
+ Vector2i size = p_tile_set->get_tile_size();
+
+ RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), p_transform);
+ if (shape == TileSet::TILE_SHAPE_SQUARE) {
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
+ DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_SIDE);
+ DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER);
+ DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE);
+ DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER);
+ DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
+ DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER);
+ DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_SIDE);
+ DRAW_TERRAIN_BIT(_draw_square_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER);
+ } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ DRAW_TERRAIN_BIT(_draw_square_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER);
+ DRAW_TERRAIN_BIT(_draw_square_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER);
+ DRAW_TERRAIN_BIT(_draw_square_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER);
+ DRAW_TERRAIN_BIT(_draw_square_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER);
+ } else { // TileData::TERRAIN_MODE_MATCH_SIDES
+ DRAW_TERRAIN_BIT(_draw_square_side_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_SIDE);
+ DRAW_TERRAIN_BIT(_draw_square_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE);
+ DRAW_TERRAIN_BIT(_draw_square_side_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_SIDE);
+ DRAW_TERRAIN_BIT(_draw_square_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_SIDE);
+ }
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
+ DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_CORNER);
+ DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE);
+ DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_CORNER);
+ DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE);
+ DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_CORNER);
+ DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
+ DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_CORNER);
+ DRAW_TERRAIN_BIT(_draw_isometric_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
+ } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ DRAW_TERRAIN_BIT(_draw_isometric_corner_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_CORNER);
+ DRAW_TERRAIN_BIT(_draw_isometric_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_CORNER);
+ DRAW_TERRAIN_BIT(_draw_isometric_corner_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_CORNER);
+ DRAW_TERRAIN_BIT(_draw_isometric_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_CORNER);
+ } else { // TileData::TERRAIN_MODE_MATCH_SIDES
+ DRAW_TERRAIN_BIT(_draw_isometric_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE);
+ DRAW_TERRAIN_BIT(_draw_isometric_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE);
+ DRAW_TERRAIN_BIT(_draw_isometric_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
+ DRAW_TERRAIN_BIT(_draw_isometric_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
}
- convex->set_meta("decomposed", sub_shapes);
} else {
- convex->set_meta("decomposed", Variant());
+ TileSet::TileOffsetAxis offset_axis = p_tile_set->get_tile_offset_axis();
+ float overlap = 0.0;
+ switch (p_tile_set->get_tile_shape()) {
+ case TileSet::TILE_SHAPE_HEXAGON:
+ overlap = 0.25;
+ break;
+ case TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE:
+ overlap = 0.0;
+ break;
+ default:
+ break;
+ }
+ if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
+ if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER, overlap, offset_axis);
+ } else {
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_or_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, overlap, offset_axis);
+ }
+ } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
+ if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER, overlap, offset_axis);
+ } else {
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_corner_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER, overlap, offset_axis);
+ }
+ } else { // TileData::TERRAIN_MODE_MATCH_SIDES
+ if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_RIGHT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_LEFT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, overlap, offset_axis);
+ } else {
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_SIDE, overlap, offset_axis);
+ DRAW_HALF_OFFSET_TERRAIN_BIT(_draw_half_offset_side_terrain_bit, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, overlap, offset_axis);
+ }
+ }
}
+ RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), Transform2D());
}
-void TileSet::get_tile_list(List<int> *p_tiles) const {
- for (Map<int, TileData>::Element *E = tile_map.front(); E; E = E->next()) {
- p_tiles->push_back(E->key());
+/////////////////////////////// TileSetAtlasPluginRendering //////////////////////////////////////
+
+void TileSetAtlasPluginRendering::tilemap_notification(TileMap *p_tile_map, int p_what) {
+ switch (p_what) {
+ case CanvasItem::NOTIFICATION_VISIBILITY_CHANGED: {
+ bool visible = p_tile_map->is_visible_in_tree();
+ for (Map<Vector2i, TileMapQuadrant>::Element *E_quadrant = p_tile_map->get_quadrant_map().front(); E_quadrant; E_quadrant = E_quadrant->next()) {
+ TileMapQuadrant &q = E_quadrant->get();
+
+ // Update occluders transform.
+ for (Map<Vector2i, Vector2i, TileMapQuadrant::CoordsWorldComparator>::Element *E_cell = q.world_to_map.front(); E_cell; E_cell = E_cell->next()) {
+ Transform2D xform;
+ xform.set_origin(E_cell->key());
+ for (List<RID>::Element *E_occluder_id = q.occluders.front(); E_occluder_id; E_occluder_id = E_occluder_id->next()) {
+ RS::get_singleton()->canvas_light_occluder_set_enabled(E_occluder_id->get(), visible);
+ }
+ }
+ }
+ } break;
+ case CanvasItem::NOTIFICATION_TRANSFORM_CHANGED: {
+ if (!p_tile_map->is_inside_tree()) {
+ return;
+ }
+
+ for (Map<Vector2i, TileMapQuadrant>::Element *E_quadrant = p_tile_map->get_quadrant_map().front(); E_quadrant; E_quadrant = E_quadrant->next()) {
+ TileMapQuadrant &q = E_quadrant->get();
+
+ // Update occluders transform.
+ for (Map<Vector2i, Vector2i, TileMapQuadrant::CoordsWorldComparator>::Element *E_cell = q.world_to_map.front(); E_cell; E_cell = E_cell->next()) {
+ Transform2D xform;
+ xform.set_origin(E_cell->key());
+ for (List<RID>::Element *E_occluder_id = q.occluders.front(); E_occluder_id; E_occluder_id = E_occluder_id->next()) {
+ RS::get_singleton()->canvas_light_occluder_set_transform(E_occluder_id->get(), p_tile_map->get_global_transform() * xform);
+ }
+ }
+ }
+ } break;
}
}
-bool TileSet::has_tile(int p_id) const {
- return tile_map.has(p_id);
+void TileSetAtlasPluginRendering::draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, Color p_modulation) {
+ ERR_FAIL_COND(!p_tile_set.is_valid());
+ ERR_FAIL_COND(!p_tile_set->has_source(p_atlas_source_id));
+ ERR_FAIL_COND(!p_tile_set->get_source(p_atlas_source_id)->has_tile(p_atlas_coords));
+ ERR_FAIL_COND(!p_tile_set->get_source(p_atlas_source_id)->has_alternative_tile(p_atlas_coords, p_alternative_tile));
+
+ TileSetSource *source = *p_tile_set->get_source(p_atlas_source_id);
+ TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ if (atlas_source) {
+ // Get the texture.
+ Ref<Texture2D> tex = atlas_source->get_texture();
+ if (!tex.is_valid()) {
+ return;
+ }
+
+ // Get tile data.
+ TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(p_atlas_coords, p_alternative_tile));
+
+ // Compute the offset
+ Rect2i source_rect = atlas_source->get_tile_texture_region(p_atlas_coords);
+ Vector2i tile_offset = atlas_source->get_tile_effective_texture_offset(p_atlas_coords, p_alternative_tile);
+
+ // Compute the destination rectangle in the CanvasItem.
+ Rect2 dest_rect;
+ dest_rect.size = source_rect.size;
+ dest_rect.size.x += fp_adjust;
+ dest_rect.size.y += fp_adjust;
+
+ bool transpose = tile_data->get_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()) {
+ dest_rect.size.x = -dest_rect.size.x;
+ }
+
+ if (tile_data->get_flip_v()) {
+ dest_rect.size.y = -dest_rect.size.y;
+ }
+
+ // Get the tile modulation.
+ Color modulate = tile_data->get_modulate();
+ modulate = Color(modulate.r * p_modulation.r, modulate.g * p_modulation.g, modulate.b * p_modulation.b, modulate.a * p_modulation.a);
+
+ // Draw the tile.
+ tex->draw_rect_region(p_canvas_item, dest_rect, source_rect, modulate, transpose, p_tile_set->is_uv_clipping());
+ }
}
-bool TileSet::is_tile_bound(int p_drawn_id, int p_neighbor_id) {
- if (p_drawn_id == p_neighbor_id) {
- return true;
- } else if (get_script_instance() != nullptr) {
- if (get_script_instance()->has_method("_is_tile_bound")) {
- Variant ret = get_script_instance()->call("_is_tile_bound", p_drawn_id, p_neighbor_id);
- if (ret.get_type() == Variant::BOOL) {
- return ret;
+void TileSetAtlasPluginRendering::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) {
+ ERR_FAIL_COND(!p_tile_map);
+ ERR_FAIL_COND(!p_tile_map->is_inside_tree());
+ Ref<TileSet> tile_set = p_tile_map->get_tileset();
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ bool visible = p_tile_map->is_visible_in_tree();
+
+ SelfList<TileMapQuadrant> *q_list_element = r_dirty_quadrant_list.first();
+ while (q_list_element) {
+ TileMapQuadrant &q = *q_list_element->self();
+
+ RenderingServer *rs = RenderingServer::get_singleton();
+
+ // Free the canvas items.
+ for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) {
+ rs->free(E->get());
+ }
+ q.canvas_items.clear();
+
+ // Free the occluders.
+ for (List<RID>::Element *E = q.occluders.front(); E; E = E->next()) {
+ rs->free(E->get());
+ }
+ q.occluders.clear();
+
+ // Those allow to group cell per material or z-index.
+ Ref<ShaderMaterial> prev_material;
+ int prev_z_index = 0;
+ RID prev_canvas_item;
+
+ // Iterate over the cells of the quadrant.
+ for (Map<Vector2i, Vector2i, TileMapQuadrant::CoordsWorldComparator>::Element *E_cell = q.world_to_map.front(); E_cell; E_cell = E_cell->next()) {
+ TileMapCell c = p_tile_map->get_cell(E_cell->value());
+
+ TileSetSource *source;
+ if (tile_set->has_source(c.source_id)) {
+ source = *tile_set->get_source(c.source_id);
+
+ if (!source->has_tile(c.get_atlas_coords()) || !source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) {
+ continue;
+ }
+
+ TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ if (atlas_source) {
+ // Get the tile data.
+ TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile));
+ Ref<ShaderMaterial> mat = tile_data->tile_get_material();
+ int z_index = tile_data->get_z_index();
+
+ // Quandrant pos.
+ Vector2 position = p_tile_map->map_to_world(q.coords * p_tile_map->get_effective_quadrant_size()) - tile_set->get_tile_size() / 2;
+
+ // --- CanvasItems ---
+ // Create two canvas items, for rendering and debug.
+ RID canvas_item;
+
+ // Check if the material or the z_index changed.
+ if (prev_canvas_item == RID() || prev_material != mat || prev_z_index != z_index) {
+ canvas_item = rs->canvas_item_create();
+ if (mat.is_valid()) {
+ rs->canvas_item_set_material(canvas_item, mat->get_rid());
+ }
+ rs->canvas_item_set_parent(canvas_item, p_tile_map->get_canvas_item());
+ rs->canvas_item_set_use_parent_material(canvas_item, p_tile_map->get_use_parent_material() || p_tile_map->get_material().is_valid());
+ Transform2D xform;
+ xform.set_origin(position);
+
+ rs->canvas_item_set_transform(canvas_item, xform);
+ rs->canvas_item_set_light_mask(canvas_item, p_tile_map->get_light_mask());
+ rs->canvas_item_set_z_index(canvas_item, z_index);
+
+ rs->canvas_item_set_default_texture_filter(canvas_item, RS::CanvasItemTextureFilter(p_tile_map->CanvasItem::get_texture_filter()));
+ rs->canvas_item_set_default_texture_repeat(canvas_item, RS::CanvasItemTextureRepeat(p_tile_map->CanvasItem::get_texture_repeat()));
+
+ q.canvas_items.push_back(canvas_item);
+
+ prev_canvas_item = canvas_item;
+ prev_material = mat;
+ prev_z_index = z_index;
+
+ } else {
+ // Keep the same canvas_item to draw on.
+ canvas_item = prev_canvas_item;
+ }
+
+ // Drawing the tile in the canvas item.
+ draw_tile(canvas_item, E_cell->key() - position, tile_set, c.source_id, c.get_atlas_coords(), c.alternative_tile, p_tile_map->get_self_modulate());
+
+ // --- Occluders ---
+ for (int i = 0; i < tile_set->get_occlusion_layers_count(); i++) {
+ Transform2D xform;
+ xform.set_origin(E_cell->key());
+ if (tile_data->get_occluder(i).is_valid()) {
+ RID occluder_id = rs->canvas_light_occluder_create();
+ rs->canvas_light_occluder_set_enabled(occluder_id, visible);
+ rs->canvas_light_occluder_set_transform(occluder_id, p_tile_map->get_global_transform() * xform);
+ rs->canvas_light_occluder_set_polygon(occluder_id, tile_data->get_occluder(i)->get_rid());
+ rs->canvas_light_occluder_attach_to_canvas(occluder_id, p_tile_map->get_canvas());
+ rs->canvas_light_occluder_set_light_mask(occluder_id, tile_set->get_occlusion_layer_light_mask(i));
+ q.occluders.push_back(occluder_id);
+ }
+ }
+ }
}
}
+
+ quadrant_order_dirty = true;
+ q_list_element = q_list_element->next();
+ }
+
+ // Reset the drawing indices
+ if (quadrant_order_dirty) {
+ int index = -(int64_t)0x80000000; //always must be drawn below children.
+
+ // Sort the quadrants coords per world coordinates
+ Map<Vector2i, Vector2i, TileMapQuadrant::CoordsWorldComparator> world_to_map;
+ Map<Vector2i, TileMapQuadrant> quadrant_map = p_tile_map->get_quadrant_map();
+ for (Map<Vector2i, TileMapQuadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
+ world_to_map[p_tile_map->map_to_world(E->key())] = E->key();
+ }
+
+ // Sort the quadrants
+ for (Map<Vector2i, Vector2i, TileMapQuadrant::CoordsWorldComparator>::Element *E = world_to_map.front(); E; E = E->next()) {
+ TileMapQuadrant &q = quadrant_map[E->value()];
+ for (List<RID>::Element *F = q.canvas_items.front(); F; F = F->next()) {
+ RS::get_singleton()->canvas_item_set_draw_index(F->get(), index++);
+ }
+ }
+
+ quadrant_order_dirty = false;
}
- return false;
}
-void TileSet::remove_tile(int p_id) {
- ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map.erase(p_id);
- notify_property_list_changed();
- emit_changed();
+void TileSetAtlasPluginRendering::create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+ Ref<TileSet> tile_set = p_tile_map->get_tileset();
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ quadrant_order_dirty = true;
}
-int TileSet::get_last_unused_tile_id() const {
- if (tile_map.size()) {
- return tile_map.back()->key() + 1;
- } else {
- return 0;
+void TileSetAtlasPluginRendering::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+ // Free the canvas items.
+ for (List<RID>::Element *E = p_quadrant->canvas_items.front(); E; E = E->next()) {
+ RenderingServer::get_singleton()->free(E->get());
+ }
+ p_quadrant->canvas_items.clear();
+
+ // Free the occluders.
+ for (List<RID>::Element *E = p_quadrant->occluders.front(); E; E = E->next()) {
+ RenderingServer::get_singleton()->free(E->get());
}
+ p_quadrant->occluders.clear();
}
-int TileSet::find_tile_by_name(const String &p_name) const {
- for (Map<int, TileData>::Element *E = tile_map.front(); E; E = E->next()) {
- if (p_name == E->get().name) {
- return E->key();
+/////////////////////////////// TileSetAtlasPluginPhysics //////////////////////////////////////
+
+void TileSetAtlasPluginPhysics::tilemap_notification(TileMap *p_tile_map, int p_what) {
+ switch (p_what) {
+ case CanvasItem::NOTIFICATION_TRANSFORM_CHANGED: {
+ // Update the bodies transforms.
+ if (p_tile_map->is_inside_tree()) {
+ Map<Vector2i, TileMapQuadrant> quadrant_map = p_tile_map->get_quadrant_map();
+ Transform2D global_transform = p_tile_map->get_global_transform();
+
+ for (Map<Vector2i, TileMapQuadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
+ TileMapQuadrant &q = E->get();
+
+ Transform2D xform;
+ xform.set_origin(p_tile_map->map_to_world(E->key() * p_tile_map->get_effective_quadrant_size()));
+ xform = global_transform * xform;
+
+ for (int body_index = 0; body_index < q.bodies.size(); body_index++) {
+ PhysicsServer2D::get_singleton()->body_set_state(q.bodies[body_index], PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
+ }
+ }
+ }
+ } break;
+ }
+}
+
+void TileSetAtlasPluginPhysics::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) {
+ ERR_FAIL_COND(!p_tile_map);
+ ERR_FAIL_COND(!p_tile_map->is_inside_tree());
+ Ref<TileSet> tile_set = p_tile_map->get_tileset();
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ Transform2D global_transform = p_tile_map->get_global_transform();
+ PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
+
+ SelfList<TileMapQuadrant> *q_list_element = r_dirty_quadrant_list.first();
+ while (q_list_element) {
+ TileMapQuadrant &q = *q_list_element->self();
+
+ Vector2 quadrant_pos = p_tile_map->map_to_world(q.coords * p_tile_map->get_effective_quadrant_size());
+
+ // Clear shapes.
+ for (int body_index = 0; body_index < q.bodies.size(); body_index++) {
+ ps->body_clear_shapes(q.bodies[body_index]);
+
+ // Position the bodies.
+ Transform2D xform;
+ xform.set_origin(quadrant_pos);
+ xform = global_transform * xform;
+ ps->body_set_state(q.bodies[body_index], PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
}
+
+ for (Set<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) {
+ TileMapCell c = p_tile_map->get_cell(E_cell->get());
+
+ TileSetSource *source;
+ if (tile_set->has_source(c.source_id)) {
+ source = *tile_set->get_source(c.source_id);
+
+ if (!source->has_tile(c.get_atlas_coords()) || !source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) {
+ continue;
+ }
+
+ TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ if (atlas_source) {
+ TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile));
+
+ for (int body_index = 0; body_index < q.bodies.size(); body_index++) {
+ // Add the shapes again.
+ for (int shape_index = 0; shape_index < tile_data->get_collision_shapes_count(body_index); shape_index++) {
+ bool one_way_collision = tile_data->is_collision_shape_one_way(body_index, shape_index);
+ float one_way_collision_margin = tile_data->get_collision_shape_one_way_margin(body_index, shape_index);
+ Ref<Shape2D> shape = tile_data->get_collision_shape_shape(body_index, shape_index);
+ if (shape.is_valid()) {
+ Transform2D xform = Transform2D();
+ xform.set_origin(p_tile_map->map_to_world(E_cell->get()) - quadrant_pos);
+
+ // Add decomposed convex shapes.
+ ps->body_add_shape(q.bodies[body_index], shape->get_rid(), xform);
+ ps->body_set_shape_metadata(q.bodies[body_index], shape_index, E_cell->get());
+ ps->body_set_shape_as_one_way_collision(q.bodies[body_index], shape_index, one_way_collision, one_way_collision_margin);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ q_list_element = q_list_element->next();
}
- return -1;
}
-void TileSet::reset_state() {
- clear();
+void TileSetAtlasPluginPhysics::create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+ Ref<TileSet> tile_set = p_tile_map->get_tileset();
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ //Get the TileMap's gobla transform.
+ Transform2D global_transform;
+ if (p_tile_map->is_inside_tree()) {
+ global_transform = p_tile_map->get_global_transform();
+ }
+
+ // Clear all bodies.
+ p_quadrant->bodies.clear();
+
+ // Create the body and set its parameters.
+ for (int layer_index = 0; layer_index < tile_set->get_physics_layers_count(); layer_index++) {
+ RID body = PhysicsServer2D::get_singleton()->body_create();
+ PhysicsServer2D::get_singleton()->body_set_mode(body, PhysicsServer2D::BODY_MODE_STATIC);
+
+ PhysicsServer2D::get_singleton()->body_attach_object_instance_id(body, p_tile_map->get_instance_id());
+ PhysicsServer2D::get_singleton()->body_set_collision_layer(body, tile_set->get_physics_layer_collision_layer(layer_index));
+ PhysicsServer2D::get_singleton()->body_set_collision_mask(body, tile_set->get_physics_layer_collision_mask(layer_index));
+
+ Ref<PhysicsMaterial> physics_material = tile_set->get_physics_layer_physics_material(layer_index);
+ if (!physics_material.is_valid()) {
+ PhysicsServer2D::get_singleton()->body_set_param(body, PhysicsServer2D::BODY_PARAM_BOUNCE, 0);
+ PhysicsServer2D::get_singleton()->body_set_param(body, PhysicsServer2D::BODY_PARAM_FRICTION, 1);
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_param(body, PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material->computed_bounce());
+ PhysicsServer2D::get_singleton()->body_set_param(body, PhysicsServer2D::BODY_PARAM_FRICTION, physics_material->computed_friction());
+ }
+
+ if (p_tile_map->is_inside_tree()) {
+ RID space = p_tile_map->get_world_2d()->get_space();
+ PhysicsServer2D::get_singleton()->body_set_space(body, space);
+
+ Transform2D xform;
+ xform.set_origin(p_tile_map->map_to_world(p_quadrant->coords * p_tile_map->get_effective_quadrant_size()));
+ xform = global_transform * xform;
+ PhysicsServer2D::get_singleton()->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
+ }
+
+ p_quadrant->bodies.push_back(body);
+ }
}
-void TileSet::clear() {
- tile_map.clear();
- notify_property_list_changed();
- emit_changed();
+void TileSetAtlasPluginPhysics::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+ // Remove a quadrant.
+ for (int body_index = 0; body_index < p_quadrant->bodies.size(); body_index++) {
+ PhysicsServer2D::get_singleton()->free(p_quadrant->bodies[body_index]);
+ }
+ p_quadrant->bodies.clear();
}
-void TileSet::_bind_methods() {
- ClassDB::bind_method(D_METHOD("create_tile", "id"), &TileSet::create_tile);
- ClassDB::bind_method(D_METHOD("autotile_clear_bitmask_map", "id"), &TileSet::autotile_clear_bitmask_map);
- ClassDB::bind_method(D_METHOD("autotile_set_icon_coordinate", "id", "coord"), &TileSet::autotile_set_icon_coordinate);
- ClassDB::bind_method(D_METHOD("autotile_get_icon_coordinate", "id"), &TileSet::autotile_get_icon_coordinate);
- ClassDB::bind_method(D_METHOD("autotile_set_subtile_priority", "id", "coord", "priority"), &TileSet::autotile_set_subtile_priority);
- ClassDB::bind_method(D_METHOD("autotile_get_subtile_priority", "id", "coord"), &TileSet::autotile_get_subtile_priority);
- ClassDB::bind_method(D_METHOD("autotile_set_z_index", "id", "coord", "z_index"), &TileSet::autotile_set_z_index);
- ClassDB::bind_method(D_METHOD("autotile_get_z_index", "id", "coord"), &TileSet::autotile_get_z_index);
- ClassDB::bind_method(D_METHOD("autotile_set_light_occluder", "id", "light_occluder", "coord"), &TileSet::autotile_set_light_occluder);
- ClassDB::bind_method(D_METHOD("autotile_get_light_occluder", "id", "coord"), &TileSet::autotile_get_light_occluder);
- ClassDB::bind_method(D_METHOD("autotile_set_navigation_polygon", "id", "navigation_polygon", "coord"), &TileSet::autotile_set_navigation_polygon);
- ClassDB::bind_method(D_METHOD("autotile_get_navigation_polygon", "id", "coord"), &TileSet::autotile_get_navigation_polygon);
- ClassDB::bind_method(D_METHOD("autotile_set_bitmask", "id", "bitmask", "flag"), &TileSet::autotile_set_bitmask);
- ClassDB::bind_method(D_METHOD("autotile_get_bitmask", "id", "coord"), &TileSet::autotile_get_bitmask);
- ClassDB::bind_method(D_METHOD("autotile_set_bitmask_mode", "id", "mode"), &TileSet::autotile_set_bitmask_mode);
- ClassDB::bind_method(D_METHOD("autotile_get_bitmask_mode", "id"), &TileSet::autotile_get_bitmask_mode);
- ClassDB::bind_method(D_METHOD("autotile_set_spacing", "id", "spacing"), &TileSet::autotile_set_spacing);
- ClassDB::bind_method(D_METHOD("autotile_get_spacing", "id"), &TileSet::autotile_get_spacing);
- ClassDB::bind_method(D_METHOD("autotile_set_size", "id", "size"), &TileSet::autotile_set_size);
- ClassDB::bind_method(D_METHOD("autotile_get_size", "id"), &TileSet::autotile_get_size);
- ClassDB::bind_method(D_METHOD("tile_set_name", "id", "name"), &TileSet::tile_set_name);
- ClassDB::bind_method(D_METHOD("tile_get_name", "id"), &TileSet::tile_get_name);
- ClassDB::bind_method(D_METHOD("tile_set_texture", "id", "texture"), &TileSet::tile_set_texture);
- ClassDB::bind_method(D_METHOD("tile_get_texture", "id"), &TileSet::tile_get_texture);
- ClassDB::bind_method(D_METHOD("tile_set_material", "id", "material"), &TileSet::tile_set_material);
- ClassDB::bind_method(D_METHOD("tile_get_material", "id"), &TileSet::tile_get_material);
- ClassDB::bind_method(D_METHOD("tile_set_modulate", "id", "color"), &TileSet::tile_set_modulate);
- ClassDB::bind_method(D_METHOD("tile_get_modulate", "id"), &TileSet::tile_get_modulate);
- ClassDB::bind_method(D_METHOD("tile_set_texture_offset", "id", "texture_offset"), &TileSet::tile_set_texture_offset);
- ClassDB::bind_method(D_METHOD("tile_get_texture_offset", "id"), &TileSet::tile_get_texture_offset);
- ClassDB::bind_method(D_METHOD("tile_set_region", "id", "region"), &TileSet::tile_set_region);
- ClassDB::bind_method(D_METHOD("tile_get_region", "id"), &TileSet::tile_get_region);
- ClassDB::bind_method(D_METHOD("tile_set_shape", "id", "shape_id", "shape"), &TileSet::tile_set_shape);
- ClassDB::bind_method(D_METHOD("tile_get_shape", "id", "shape_id"), &TileSet::tile_get_shape);
- ClassDB::bind_method(D_METHOD("tile_set_shape_offset", "id", "shape_id", "shape_offset"), &TileSet::tile_set_shape_offset);
- ClassDB::bind_method(D_METHOD("tile_get_shape_offset", "id", "shape_id"), &TileSet::tile_get_shape_offset);
- ClassDB::bind_method(D_METHOD("tile_set_shape_transform", "id", "shape_id", "shape_transform"), &TileSet::tile_set_shape_transform);
- ClassDB::bind_method(D_METHOD("tile_get_shape_transform", "id", "shape_id"), &TileSet::tile_get_shape_transform);
- ClassDB::bind_method(D_METHOD("tile_set_shape_one_way", "id", "shape_id", "one_way"), &TileSet::tile_set_shape_one_way);
- ClassDB::bind_method(D_METHOD("tile_get_shape_one_way", "id", "shape_id"), &TileSet::tile_get_shape_one_way);
- ClassDB::bind_method(D_METHOD("tile_set_shape_one_way_margin", "id", "shape_id", "one_way"), &TileSet::tile_set_shape_one_way_margin);
- ClassDB::bind_method(D_METHOD("tile_get_shape_one_way_margin", "id", "shape_id"), &TileSet::tile_get_shape_one_way_margin);
- ClassDB::bind_method(D_METHOD("tile_add_shape", "id", "shape", "shape_transform", "one_way", "autotile_coord"), &TileSet::tile_add_shape, DEFVAL(false), DEFVAL(Vector2()));
- ClassDB::bind_method(D_METHOD("tile_get_shape_count", "id"), &TileSet::tile_get_shape_count);
- ClassDB::bind_method(D_METHOD("tile_set_shapes", "id", "shapes"), &TileSet::_tile_set_shapes);
- ClassDB::bind_method(D_METHOD("tile_get_shapes", "id"), &TileSet::_tile_get_shapes);
- ClassDB::bind_method(D_METHOD("tile_set_tile_mode", "id", "tilemode"), &TileSet::tile_set_tile_mode);
- ClassDB::bind_method(D_METHOD("tile_get_tile_mode", "id"), &TileSet::tile_get_tile_mode);
- ClassDB::bind_method(D_METHOD("tile_set_navigation_polygon", "id", "navigation_polygon"), &TileSet::tile_set_navigation_polygon);
- ClassDB::bind_method(D_METHOD("tile_get_navigation_polygon", "id"), &TileSet::tile_get_navigation_polygon);
- ClassDB::bind_method(D_METHOD("tile_set_navigation_polygon_offset", "id", "navigation_polygon_offset"), &TileSet::tile_set_navigation_polygon_offset);
- ClassDB::bind_method(D_METHOD("tile_get_navigation_polygon_offset", "id"), &TileSet::tile_get_navigation_polygon_offset);
- ClassDB::bind_method(D_METHOD("tile_set_light_occluder", "id", "light_occluder"), &TileSet::tile_set_light_occluder);
- ClassDB::bind_method(D_METHOD("tile_get_light_occluder", "id"), &TileSet::tile_get_light_occluder);
- ClassDB::bind_method(D_METHOD("tile_set_occluder_offset", "id", "occluder_offset"), &TileSet::tile_set_occluder_offset);
- ClassDB::bind_method(D_METHOD("tile_get_occluder_offset", "id"), &TileSet::tile_get_occluder_offset);
- ClassDB::bind_method(D_METHOD("tile_set_z_index", "id", "z_index"), &TileSet::tile_set_z_index);
- ClassDB::bind_method(D_METHOD("tile_get_z_index", "id"), &TileSet::tile_get_z_index);
-
- ClassDB::bind_method(D_METHOD("remove_tile", "id"), &TileSet::remove_tile);
- ClassDB::bind_method(D_METHOD("clear"), &TileSet::clear);
- ClassDB::bind_method(D_METHOD("get_last_unused_tile_id"), &TileSet::get_last_unused_tile_id);
- ClassDB::bind_method(D_METHOD("find_tile_by_name", "name"), &TileSet::find_tile_by_name);
- ClassDB::bind_method(D_METHOD("get_tiles_ids"), &TileSet::_get_tiles_ids);
-
- 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);
- BIND_ENUM_CONSTANT(BITMASK_3X3);
-
- BIND_ENUM_CONSTANT(BIND_TOPLEFT);
- BIND_ENUM_CONSTANT(BIND_TOP);
- BIND_ENUM_CONSTANT(BIND_TOPRIGHT);
- BIND_ENUM_CONSTANT(BIND_LEFT);
- BIND_ENUM_CONSTANT(BIND_CENTER);
- BIND_ENUM_CONSTANT(BIND_RIGHT);
- BIND_ENUM_CONSTANT(BIND_BOTTOMLEFT);
- BIND_ENUM_CONSTANT(BIND_BOTTOM);
- BIND_ENUM_CONSTANT(BIND_BOTTOMRIGHT);
-
- BIND_ENUM_CONSTANT(SINGLE_TILE);
- BIND_ENUM_CONSTANT(AUTO_TILE);
- BIND_ENUM_CONSTANT(ATLAS_TILE);
+void TileSetAtlasPluginPhysics::draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+ // Draw the debug collision shapes.
+ Ref<TileSet> tile_set = p_tile_map->get_tileset();
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ if (!p_tile_map->get_tree() || !(Engine::get_singleton()->is_editor_hint() || p_tile_map->get_tree()->is_debugging_collisions_hint())) {
+ return;
+ }
+
+ RenderingServer *rs = RenderingServer::get_singleton();
+
+ Vector2 quadrant_pos = p_tile_map->map_to_world(p_quadrant->coords * p_tile_map->get_effective_quadrant_size());
+
+ Color debug_collision_color = p_tile_map->get_tree()->get_debug_collisions_color();
+ for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) {
+ TileMapCell c = p_tile_map->get_cell(E_cell->get());
+
+ Transform2D xform;
+ xform.set_origin(p_tile_map->map_to_world(E_cell->get()) - quadrant_pos);
+ rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, xform);
+
+ if (tile_set->has_source(c.source_id)) {
+ TileSetSource *source = *tile_set->get_source(c.source_id);
+
+ if (!source->has_tile(c.get_atlas_coords()) || !source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) {
+ continue;
+ }
+
+ TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ if (atlas_source) {
+ TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile));
+
+ for (int body_index = 0; body_index < p_quadrant->bodies.size(); body_index++) {
+ for (int shape_index = 0; shape_index < tile_data->get_collision_shapes_count(body_index); shape_index++) {
+ // Draw the debug shape.
+ Ref<Shape2D> shape = tile_data->get_collision_shape_shape(body_index, shape_index);
+ if (shape.is_valid()) {
+ shape->draw(p_quadrant->debug_canvas_item, debug_collision_color);
+ }
+ }
+ }
+ }
+ }
+ rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, Transform2D());
+ }
+};
+
+/////////////////////////////// TileSetAtlasPluginNavigation //////////////////////////////////////
+
+void TileSetAtlasPluginNavigation::tilemap_notification(TileMap *p_tile_map, int p_what) {
+ switch (p_what) {
+ case CanvasItem::NOTIFICATION_TRANSFORM_CHANGED: {
+ if (p_tile_map->is_inside_tree()) {
+ Map<Vector2i, TileMapQuadrant> quadrant_map = p_tile_map->get_quadrant_map();
+ Transform2D tilemap_xform = p_tile_map->get_global_transform();
+ for (Map<Vector2i, TileMapQuadrant>::Element *E_quadrant = quadrant_map.front(); E_quadrant; E_quadrant = E_quadrant->next()) {
+ TileMapQuadrant &q = E_quadrant->get();
+ for (Map<Vector2i, Vector<RID>>::Element *E_region = q.navigation_regions.front(); E_region; E_region = E_region->next()) {
+ for (int layer_index = 0; layer_index < E_region->get().size(); layer_index++) {
+ RID region = E_region->get()[layer_index];
+ if (!region.is_valid()) {
+ continue;
+ }
+ Transform2D tile_transform;
+ tile_transform.set_origin(p_tile_map->map_to_world(E_region->key()));
+ NavigationServer2D::get_singleton()->region_set_transform(region, tilemap_xform * tile_transform);
+ }
+ }
+ }
+ }
+ } break;
+ }
}
-TileSet::TileSet() {
+void TileSetAtlasPluginNavigation::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) {
+ ERR_FAIL_COND(!p_tile_map);
+ ERR_FAIL_COND(!p_tile_map->is_inside_tree());
+ Ref<TileSet> tile_set = p_tile_map->get_tileset();
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ // Get colors for debug.
+ SceneTree *st = SceneTree::get_singleton();
+ Color debug_navigation_color;
+ bool debug_navigation = st && st->is_debugging_navigation_hint();
+ if (debug_navigation) {
+ debug_navigation_color = st->get_debug_navigation_color();
+ }
+
+ Transform2D tilemap_xform = p_tile_map->get_global_transform();
+ SelfList<TileMapQuadrant> *q_list_element = r_dirty_quadrant_list.first();
+ while (q_list_element) {
+ TileMapQuadrant &q = *q_list_element->self();
+
+ // Clear navigation shapes in the quadrant.
+ for (Map<Vector2i, Vector<RID>>::Element *E = q.navigation_regions.front(); E; E = E->next()) {
+ for (int i = 0; i < E->get().size(); i++) {
+ RID region = E->get()[i];
+ if (!region.is_valid()) {
+ continue;
+ }
+ NavigationServer2D::get_singleton()->region_set_map(region, RID());
+ }
+ }
+ q.navigation_regions.clear();
+
+ // Get the navigation polygons and create regions.
+ for (Set<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) {
+ TileMapCell c = p_tile_map->get_cell(E_cell->get());
+
+ TileSetSource *source;
+ if (tile_set->has_source(c.source_id)) {
+ source = *tile_set->get_source(c.source_id);
+
+ if (!source->has_tile(c.get_atlas_coords()) || !source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) {
+ continue;
+ }
+
+ TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ if (atlas_source) {
+ TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile));
+ q.navigation_regions[E_cell->get()].resize(tile_set->get_navigation_layers_count());
+
+ for (int layer_index = 0; layer_index < tile_set->get_navigation_layers_count(); layer_index++) {
+ Ref<NavigationPolygon> navpoly;
+ navpoly = tile_data->get_navigation_polygon(layer_index);
+
+ if (navpoly.is_valid()) {
+ Transform2D tile_transform;
+ tile_transform.set_origin(p_tile_map->map_to_world(E_cell->get()));
+
+ RID region = NavigationServer2D::get_singleton()->region_create();
+ NavigationServer2D::get_singleton()->region_set_map(region, p_tile_map->get_world_2d()->get_navigation_map());
+ NavigationServer2D::get_singleton()->region_set_transform(region, tilemap_xform * tile_transform);
+ NavigationServer2D::get_singleton()->region_set_navpoly(region, navpoly);
+ q.navigation_regions[E_cell->get()].write[layer_index] = region;
+ }
+ }
+ }
+ }
+ }
+
+ q_list_element = q_list_element->next();
+ }
+}
+
+void TileSetAtlasPluginNavigation::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+ // Clear navigation shapes in the quadrant.
+ for (Map<Vector2i, Vector<RID>>::Element *E = p_quadrant->navigation_regions.front(); E; E = E->next()) {
+ for (int i = 0; i < E->get().size(); i++) {
+ RID region = E->get()[i];
+ if (!region.is_valid()) {
+ continue;
+ }
+ NavigationServer2D::get_singleton()->free(region);
+ }
+ }
+ p_quadrant->navigation_regions.clear();
+}
+
+void TileSetAtlasPluginNavigation::draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
+ // Draw the debug collision shapes.
+ Ref<TileSet> tile_set = p_tile_map->get_tileset();
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ if (!p_tile_map->get_tree() || !(Engine::get_singleton()->is_editor_hint() || p_tile_map->get_tree()->is_debugging_navigation_hint())) {
+ return;
+ }
+
+ RenderingServer *rs = RenderingServer::get_singleton();
+
+ Color color = p_tile_map->get_tree()->get_debug_navigation_color();
+ RandomPCG rand;
+
+ Vector2 quadrant_pos = p_tile_map->map_to_world(p_quadrant->coords * p_tile_map->get_effective_quadrant_size());
+
+ for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) {
+ TileMapCell c = p_tile_map->get_cell(E_cell->get());
+
+ TileSetSource *source;
+ if (tile_set->has_source(c.source_id)) {
+ source = *tile_set->get_source(c.source_id);
+
+ if (!source->has_tile(c.get_atlas_coords()) || !source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) {
+ continue;
+ }
+
+ TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ if (atlas_source) {
+ TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile));
+
+ Transform2D xform;
+ xform.set_origin(p_tile_map->map_to_world(E_cell->get()) - quadrant_pos);
+ rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, xform);
+
+ for (int layer_index = 0; layer_index < tile_set->get_navigation_layers_count(); layer_index++) {
+ Ref<NavigationPolygon> navpoly = tile_data->get_navigation_polygon(layer_index);
+ if (navpoly.is_valid()) {
+ PackedVector2Array navigation_polygon_vertices = navpoly->get_vertices();
+
+ for (int i = 0; i < navpoly->get_polygon_count(); i++) {
+ // An array of vertices for this polygon.
+ Vector<int> polygon = navpoly->get_polygon(i);
+ Vector<Vector2> vertices;
+ vertices.resize(polygon.size());
+ for (int j = 0; j < polygon.size(); j++) {
+ ERR_FAIL_INDEX(polygon[j], navigation_polygon_vertices.size());
+ vertices.write[j] = navigation_polygon_vertices[polygon[j]];
+ }
+
+ // Generate the polygon color, slightly randomly modified from the settings one.
+ Color random_variation_color;
+ random_variation_color.set_hsv(color.get_h() + rand.random(-1.0, 1.0) * 0.05, color.get_s(), color.get_v() + rand.random(-1.0, 1.0) * 0.1);
+ random_variation_color.a = color.a;
+ Vector<Color> colors;
+ colors.push_back(random_variation_color);
+
+ RS::get_singleton()->canvas_item_add_polygon(p_quadrant->debug_canvas_item, vertices, colors);
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 0a8721f35b..20cf183a20 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -32,226 +32,614 @@
#define TILE_SET_H
#include "core/io/resource.h"
-#include "core/variant/array.h"
+#include "core/object/object.h"
#include "scene/2d/light_occluder_2d.h"
#include "scene/2d/navigation_region_2d.h"
+#include "scene/main/canvas_item.h"
#include "scene/resources/convex_polygon_shape_2d.h"
+#include "scene/resources/packed_scene.h"
+#include "scene/resources/physics_material.h"
+#include "scene/resources/shape_2d.h"
+
+#ifndef DISABLE_DEPRECATED
+#include "scene/2d/light_occluder_2d.h"
+#include "scene/2d/navigation_region_2d.h"
+#include "scene/resources/shader.h"
#include "scene/resources/shape_2d.h"
#include "scene/resources/texture.h"
+#endif
+
+class TileMap;
+struct TileMapQuadrant;
+class TileSetSource;
+class TileSetAtlasSource;
+class TileData;
+
+// Forward-declare the plugins.
+class TileSetPlugin;
+class TileSetAtlasPluginRendering;
+class TileSetAtlasPluginPhysics;
+class TileSetAtlasPluginNavigation;
+class TileSetAtlasPluginTerrain;
class TileSet : public Resource {
GDCLASS(TileSet, Resource);
-public:
- struct ShapeData {
+#ifndef DISABLE_DEPRECATED
+private:
+ struct CompatibilityShapeData {
+ Vector2i autotile_coords;
+ bool one_way;
+ float one_way_margin;
Ref<Shape2D> shape;
- Transform2D shape_transform;
- Vector2 autotile_coord;
- bool one_way_collision = false;
- float one_way_collision_margin = 1.0;
+ Transform2D transform;
+ };
- ShapeData() {}
+ struct CompatibilityTileData {
+ String name;
+ Ref<Texture2D> texture;
+ Vector2 tex_offset;
+ Ref<ShaderMaterial> material;
+ Rect2 region;
+ int tile_mode;
+ Color modulate;
+
+ // Atlas or autotiles data
+ int autotile_bitmask_mode;
+ Vector2 autotile_icon_coordinate;
+ Size2i autotile_tile_size = Size2i(16, 16);
+
+ int autotile_spacing;
+ Map<Vector2i, int> autotile_bitmask_flags;
+ Map<Vector2i, Ref<OccluderPolygon2D>> autotile_occluder_map;
+ Map<Vector2i, Ref<NavigationPolygon>> autotile_navpoly_map;
+ Map<Vector2i, int> autotile_priority_map;
+ Map<Vector2i, int> autotile_z_index_map;
+
+ Vector<CompatibilityShapeData> shapes;
+ Ref<OccluderPolygon2D> occluder;
+ Vector2 occluder_offset;
+ Ref<NavigationPolygon> navigation;
+ Vector2 navigation_offset;
+ int z_index;
};
- enum BitmaskMode {
- BITMASK_2X2,
- BITMASK_3X3_MINIMAL,
- BITMASK_3X3
+ Map<int, CompatibilityTileData *> compatibility_data = Map<int, CompatibilityTileData *>();
+ Map<int, int> compatibility_source_mapping = Map<int, int>();
+
+private:
+ void compatibility_conversion();
+
+public:
+ int compatibility_get_source_for_tile_id(int p_old_source) {
+ return compatibility_source_mapping[p_old_source];
};
- enum AutotileBindings {
- BIND_TOPLEFT = 1,
- BIND_TOP = 2,
- BIND_TOPRIGHT = 4,
- BIND_LEFT = 8,
- BIND_CENTER = 16,
- BIND_RIGHT = 32,
- BIND_BOTTOMLEFT = 64,
- BIND_BOTTOM = 128,
- BIND_BOTTOMRIGHT = 256,
-
- BIND_IGNORE_TOPLEFT = 1 << 16,
- BIND_IGNORE_TOP = 1 << 17,
- BIND_IGNORE_TOPRIGHT = 1 << 18,
- BIND_IGNORE_LEFT = 1 << 19,
- BIND_IGNORE_CENTER = 1 << 20,
- BIND_IGNORE_RIGHT = 1 << 21,
- BIND_IGNORE_BOTTOMLEFT = 1 << 22,
- BIND_IGNORE_BOTTOM = 1 << 23,
- BIND_IGNORE_BOTTOMRIGHT = 1 << 24
+#endif // DISABLE_DEPRECATED
+
+public:
+ enum CellNeighbor {
+ CELL_NEIGHBOR_RIGHT_SIDE = 0,
+ CELL_NEIGHBOR_RIGHT_CORNER,
+ CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE,
+ CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER,
+ CELL_NEIGHBOR_BOTTOM_SIDE,
+ CELL_NEIGHBOR_BOTTOM_CORNER,
+ CELL_NEIGHBOR_BOTTOM_LEFT_SIDE,
+ CELL_NEIGHBOR_BOTTOM_LEFT_CORNER,
+ CELL_NEIGHBOR_LEFT_SIDE,
+ CELL_NEIGHBOR_LEFT_CORNER,
+ CELL_NEIGHBOR_TOP_LEFT_SIDE,
+ CELL_NEIGHBOR_TOP_LEFT_CORNER,
+ CELL_NEIGHBOR_TOP_SIDE,
+ CELL_NEIGHBOR_TOP_CORNER,
+ CELL_NEIGHBOR_TOP_RIGHT_SIDE,
+ CELL_NEIGHBOR_TOP_RIGHT_CORNER,
+ CELL_NEIGHBOR_MAX,
};
- enum TileMode {
- SINGLE_TILE,
- AUTO_TILE,
- ATLAS_TILE
+ enum TerrainMode {
+ TERRAIN_MODE_MATCH_CORNERS_AND_SIDES = 0,
+ TERRAIN_MODE_MATCH_CORNERS,
+ TERRAIN_MODE_MATCH_SIDES,
};
- struct AutotileData {
- BitmaskMode bitmask_mode = BITMASK_2X2;
- // Default size to prevent invalid value
- Size2 size = Size2(64, 64);
- Vector2 icon_coord = Vector2(0, 0);
- int spacing = 0;
- Map<Vector2, uint32_t> flags;
- Map<Vector2, Ref<OccluderPolygon2D>> occluder_map;
- Map<Vector2, Ref<NavigationPolygon>> navpoly_map;
- Map<Vector2, int> priority_map;
- Map<Vector2, int> z_index_map;
-
- explicit AutotileData() {}
+ enum TileShape {
+ TILE_SHAPE_SQUARE,
+ TILE_SHAPE_ISOMETRIC,
+ TILE_SHAPE_HALF_OFFSET_SQUARE,
+ TILE_SHAPE_HEXAGON,
};
-private:
- struct TileData {
- String name;
- Ref<Texture2D> texture;
- Vector2 offset;
- Rect2i region;
- Vector<ShapeData> shapes_data;
- Vector2 occluder_offset;
- Ref<OccluderPolygon2D> occluder;
- Vector2 navigation_polygon_offset;
- Ref<NavigationPolygon> navigation_polygon;
- Ref<ShaderMaterial> material;
- TileMode tile_mode = SINGLE_TILE;
- // Default modulate for back-compat
- Color modulate = Color(1, 1, 1);
- AutotileData autotile_data;
- int z_index = 0;
+ enum TileLayout {
+ TILE_LAYOUT_STACKED,
+ TILE_LAYOUT_STACKED_OFFSET,
+ TILE_LAYOUT_STAIRS_RIGHT,
+ TILE_LAYOUT_STAIRS_DOWN,
+ TILE_LAYOUT_DIAMOND_RIGHT,
+ TILE_LAYOUT_DIAMOND_DOWN,
+ };
- explicit TileData() {}
+ enum TileOffsetAxis {
+ TILE_OFFSET_AXIS_HORIZONTAL,
+ TILE_OFFSET_AXIS_VERTICAL,
};
- Map<int, TileData> tile_map;
+public:
+ struct PackedSceneSource {
+ Ref<PackedScene> scene;
+ Vector2 offset;
+ };
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
- void _tile_set_shapes(int p_id, const Array &p_shapes);
- Array _tile_get_shapes(int p_id) const;
- Array _get_tiles_ids() const;
- void _decompose_convex_shape(Ref<Shape2D> p_shape);
+private:
+ // --- TileSet data ---
+ // Basic shape and layout.
+ TileShape tile_shape = TILE_SHAPE_SQUARE;
+ TileLayout tile_layout = TILE_LAYOUT_STACKED;
+ TileOffsetAxis tile_offset_axis = TILE_OFFSET_AXIS_HORIZONTAL;
+ Size2i tile_size = Size2i(16, 16); //Size2(64, 64);
+ Vector2 tile_skew = Vector2(0, 0);
+
+ // Rendering.
+ bool y_sorting = false;
+ bool uv_clipping = false;
+ struct OcclusionLayer {
+ uint32_t light_mask = 1;
+ bool sdf_collision = false;
+ };
+ Vector<OcclusionLayer> occlusion_layers;
+
+ // Physics
+ struct PhysicsLayer {
+ uint32_t collision_layer = 1;
+ uint32_t collision_mask = 1;
+ Ref<PhysicsMaterial> physics_material;
+ };
+ Vector<PhysicsLayer> physics_layers;
+
+ // Terrains
+ struct Terrain {
+ String name;
+ Color color;
+ };
+ struct TerrainSet {
+ TerrainMode mode = TERRAIN_MODE_MATCH_CORNERS_AND_SIDES;
+ Vector<Terrain> terrains;
+ };
+ Vector<TerrainSet> terrain_sets;
+
+ // Navigation
+ struct Navigationlayer {
+ uint32_t layers = 1;
+ };
+ Vector<Navigationlayer> navigation_layers;
+
+ // CustomData
+ struct CustomDataLayer {
+ String name;
+ Variant::Type type = Variant::NIL;
+ };
+ Vector<CustomDataLayer> custom_data_layers;
+ Map<String, int> custom_data_layers_by_name;
+
+ // Per Atlas source data.
+ Map<int, Ref<TileSetSource>> sources;
+ Vector<int> source_ids;
+ int next_source_id = 0;
+ // ---------------------
+
+ // Plugins themselves.
+ Vector<TileSetPlugin *> tile_set_plugins_vector;
+
+ void _compute_next_source_id();
+ void _source_changed();
+
+protected:
static void _bind_methods();
+public:
+ // --- Plugins ---
+ Vector<TileSetPlugin *> get_tile_set_atlas_plugins() const;
+
+ // --- Accessors for TileSet data ---
+
+ // -- Shape and layout --
+ void set_tile_shape(TileShape p_shape);
+ TileShape get_tile_shape() const;
+ void set_tile_layout(TileLayout p_layout);
+ TileLayout get_tile_layout() const;
+ void set_tile_offset_axis(TileOffsetAxis p_alignment);
+ TileOffsetAxis get_tile_offset_axis() const;
+ void set_tile_size(Size2i p_size);
+ Size2i get_tile_size() const;
+ void set_tile_skew(Vector2 p_skew);
+ Vector2 get_tile_skew() const;
+
+ // -- Sources management --
+ int get_next_source_id() const;
+ int get_source_count() const;
+ int get_source_id(int p_index) const;
+ int add_source(Ref<TileSetAtlasSource> p_tile_atlas_source, int p_source_id_override = -1);
+ void set_source_id(int p_source_id, int p_new_id);
+ void remove_source(int p_source_id);
+ bool has_source(int p_source_id) const;
+ Ref<TileSetSource> get_source(int p_source_id) const;
+
+ // Rendering
+ void set_y_sorting(bool p_y_sort);
+ bool is_y_sorting() const;
+
+ void set_uv_clipping(bool p_uv_clipping);
+ bool is_uv_clipping() const;
+
+ void set_occlusion_layers_count(int p_occlusion_layers_count);
+ int get_occlusion_layers_count() const;
+ void set_occlusion_layer_light_mask(int p_layer_index, int p_light_mask);
+ int get_occlusion_layer_light_mask(int p_layer_index) const;
+ void set_occlusion_layer_sdf_collision(int p_layer_index, int p_sdf_collision);
+ bool get_occlusion_layer_sdf_collision(int p_layer_index) const;
+
+ // Physics
+ void set_physics_layers_count(int p_physics_layers_count);
+ int get_physics_layers_count() const;
+ void set_physics_layer_collision_layer(int p_layer_index, uint32_t p_layer);
+ uint32_t get_physics_layer_collision_layer(int p_layer_index) const;
+ void set_physics_layer_collision_mask(int p_layer_index, uint32_t p_mask);
+ uint32_t get_physics_layer_collision_mask(int p_layer_index) const;
+ void set_physics_layer_physics_material(int p_layer_index, Ref<PhysicsMaterial> p_physics_material);
+ Ref<PhysicsMaterial> get_physics_layer_physics_material(int p_layer_index) const;
+
+ // Terrains
+ void set_terrain_sets_count(int p_terrains_sets_count);
+ int get_terrain_sets_count() const;
+ void set_terrain_set_mode(int p_terrain_set, TerrainMode p_terrain_mode);
+ TerrainMode get_terrain_set_mode(int p_terrain_set) const;
+ void set_terrains_count(int p_terrain_set, int p_terrains_count);
+ int get_terrains_count(int p_terrain_set) const;
+ void set_terrain_name(int p_terrain_set, int p_terrain_index, String p_name);
+ String get_terrain_name(int p_terrain_set, int p_terrain_index) const;
+ void set_terrain_color(int p_terrain_set, int p_terrain_index, Color p_color);
+ Color get_terrain_color(int p_terrain_set, int p_terrain_index) const;
+ bool is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeighbor p_peering_bit) const;
+
+ // Navigation
+ void set_navigation_layers_count(int p_navigation_layers_count);
+ int get_navigation_layers_count() const;
+ void set_navigation_layer_layers(int p_layer_index, uint32_t p_layers);
+ uint32_t get_navigation_layer_layers(int p_layer_index) const;
+
+ // Custom data
+ void set_custom_data_layers_count(int p_custom_data_layers_count);
+ int get_custom_data_layers_count() const;
+ int get_custom_data_layer_by_name(String p_value) const;
+ void set_custom_data_name(int p_layer_id, String p_value);
+ String get_custom_data_name(int p_layer_id) const;
+ void set_custom_data_type(int p_layer_id, Variant::Type p_value);
+ Variant::Type get_custom_data_type(int p_layer_id) const;
+
+ // Helpers
+ void draw_tile_shape(CanvasItem *p_canvas_item, Rect2 p_region, Color p_color, bool p_filled = false, Ref<Texture2D> p_texture = Ref<Texture2D>());
+
virtual void reset_state() override;
+ TileSet();
+ ~TileSet();
+};
+
+class TileSetSource : public Resource {
+ GDCLASS(TileSetSource, Resource);
+
+protected:
+ const TileSet *tile_set = nullptr;
+
public:
- void create_tile(int p_id);
+ // Not exposed.
+ virtual void set_tile_set(const TileSet *p_tile_set);
+ virtual void notify_tile_data_properties_should_change(){};
+ virtual void reset_state() override{};
+
+ // Tiles.
+ virtual int get_tiles_count() const = 0;
+ virtual Vector2i get_tile_id(int tile_index) const = 0;
+ virtual bool has_tile(Vector2i p_atlas_coords) const = 0;
+
+ // Alternative tiles.
+ virtual int get_alternative_tiles_count(const Vector2i p_atlas_coords) const = 0;
+ virtual int get_alternative_tile_id(const Vector2i p_atlas_coords, int p_index) const = 0;
+ virtual bool has_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_tile) const = 0;
+};
- void autotile_set_bitmask_mode(int p_id, BitmaskMode p_mode);
- BitmaskMode autotile_get_bitmask_mode(int p_id) const;
+class TileSetAtlasSource : public TileSetSource {
+ GDCLASS(TileSetAtlasSource, TileSetSource);
- void tile_set_name(int p_id, const String &p_name);
- String tile_get_name(int p_id) const;
+public:
+ static const Vector2i INVALID_ATLAS_COORDS; // Vector2i(-1, -1);
+ static const int INVALID_TILE_ALTERNATIVE; // -1;
+
+ struct TileAlternativesData {
+ Vector2i size_in_atlas = Vector2i(1, 1);
+ Vector2i texture_offset;
+ Map<int, TileData *> alternatives;
+ Vector<int> alternatives_ids;
+ int next_alternative_id = 1;
+ };
- void tile_set_texture(int p_id, const Ref<Texture2D> &p_texture);
- Ref<Texture2D> tile_get_texture(int p_id) const;
+private:
+ Ref<Texture2D> texture;
+ Vector2i margins;
+ Vector2i separation;
+ Size2i texture_region_size = Size2i(16, 16);
- void tile_set_texture_offset(int p_id, const Vector2 &p_offset);
- Vector2 tile_get_texture_offset(int p_id) const;
+ Map<Vector2i, TileAlternativesData> tiles;
+ Vector<Vector2i> tiles_ids;
+ Map<Vector2i, Vector2i> _coords_mapping_cache; // Maps any coordinate to the including tile
- void tile_set_region(int p_id, const Rect2 &p_region);
- Rect2 tile_get_region(int p_id) const;
+ TileData *_get_atlas_tile_data(Vector2i p_atlas_coords, int p_alternative_tile);
+ const TileData *_get_atlas_tile_data(Vector2i p_atlas_coords, int p_alternative_tile) const;
- void tile_set_tile_mode(int p_id, TileMode p_tile_mode);
- TileMode tile_get_tile_mode(int p_id) const;
+ void _compute_next_alternative_id(const Vector2i p_atlas_coords);
- void autotile_set_icon_coordinate(int p_id, Vector2 coord);
- Vector2 autotile_get_icon_coordinate(int p_id) const;
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
- void autotile_set_spacing(int p_id, int p_spacing);
- int autotile_get_spacing(int p_id) const;
+ static void _bind_methods();
- void autotile_set_size(int p_id, Size2 p_size);
- Size2 autotile_get_size(int p_id) const;
+public:
+ // Not exposed.
+ virtual void set_tile_set(const TileSet *p_tile_set) override;
+ virtual void notify_tile_data_properties_should_change() override;
+ virtual void reset_state() override;
- void autotile_clear_bitmask_map(int p_id);
- void autotile_set_subtile_priority(int p_id, const Vector2 &p_coord, int p_priority);
- int autotile_get_subtile_priority(int p_id, const Vector2 &p_coord);
- const Map<Vector2, int> &autotile_get_priority_map(int p_id) const;
+ // Base properties.
+ void set_texture(Ref<Texture2D> p_texture);
+ Ref<Texture2D> get_texture() const;
+ void set_margins(Vector2i p_margins);
+ Vector2i get_margins() const;
+ void set_separation(Vector2i p_separation);
+ Vector2i get_separation() const;
+ void set_texture_region_size(Vector2i p_tile_size);
+ Vector2i get_texture_region_size() const;
+
+ // Base tiles.
+ void create_tile(const Vector2i p_atlas_coords, const Vector2i p_size = Vector2i(1, 1)); // Create a tile if it does not exists, or add alternative tile if it does.
+ void remove_tile(Vector2i p_atlas_coords); // Remove a tile. If p_tile_key.alternative_tile if different from 0, remove the alternative
+ virtual bool has_tile(Vector2i p_atlas_coords) const override;
+ bool can_move_tile_in_atlas(Vector2i p_atlas_coords, Vector2i p_new_atlas_coords = INVALID_ATLAS_COORDS, Vector2i p_new_size = Vector2i(-1, -1)) const;
+ void move_tile_in_atlas(Vector2i p_atlas_coords, Vector2i p_new_atlas_coords = INVALID_ATLAS_COORDS, Vector2i p_new_size = Vector2i(-1, -1));
+ Vector2i get_tile_size_in_atlas(Vector2i p_atlas_coords) const;
+
+ virtual int get_tiles_count() const override;
+ virtual Vector2i get_tile_id(int p_index) const override;
+
+ Vector2i get_tile_at_coords(Vector2i p_atlas_coords) const;
+
+ // Alternative tiles.
+ int create_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_id_override = -1);
+ void remove_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_tile);
+ void set_alternative_tile_id(const Vector2i p_atlas_coords, int p_alternative_tile, int p_new_id);
+ virtual bool has_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_tile) const override;
+ int get_next_alternative_tile_id(const Vector2i p_atlas_coords) const;
+
+ virtual int get_alternative_tiles_count(const Vector2i p_atlas_coords) const override;
+ virtual int get_alternative_tile_id(const Vector2i p_atlas_coords, int p_index) const override;
+
+ // Get data associated to a tile.
+ Object *get_tile_data(const Vector2i p_atlas_coords, int p_alternative_tile) const;
+
+ // Helpers.
+ Vector2i get_atlas_grid_size() const;
+ bool has_tiles_outside_texture();
+ void clear_tiles_outside_texture();
+ Rect2i get_tile_texture_region(Vector2i p_atlas_coords) const;
+ Vector2i get_tile_effective_texture_offset(Vector2i p_atlas_coords, int p_alternative_tile) const;
+
+ ~TileSetAtlasSource();
+};
- void autotile_set_z_index(int p_id, const Vector2 &p_coord, int p_z_index);
- int autotile_get_z_index(int p_id, const Vector2 &p_coord);
- const Map<Vector2, int> &autotile_get_z_index_map(int p_id) const;
+class TileData : public Object {
+ GDCLASS(TileData, Object);
- void autotile_set_bitmask(int p_id, Vector2 p_coord, uint32_t p_flag);
- uint32_t autotile_get_bitmask(int p_id, Vector2 p_coord);
- const Map<Vector2, uint32_t> &autotile_get_bitmask_map(int p_id);
- Vector2 autotile_get_subtile_for_bitmask(int p_id, uint16_t p_bitmask, const Node *p_tilemap_node = nullptr, const Vector2 &p_tile_location = Vector2());
- Vector2 atlastile_get_subtile_by_priority(int p_id, const Node *p_tilemap_node = nullptr, const Vector2 &p_tile_location = Vector2());
+private:
+ const TileSet *tile_set = nullptr;
+ bool allow_transform = true;
+
+ // Rendering
+ bool flip_h = false;
+ bool flip_v = false;
+ bool transpose = false;
+ Vector2i tex_offset = Vector2i();
+ Ref<ShaderMaterial> material = Ref<ShaderMaterial>();
+ Color modulate = Color(1.0, 1.0, 1.0, 1.0);
+ int z_index = 0;
+ Vector2i y_sort_origin = Vector2i();
+ Vector<Ref<OccluderPolygon2D>> occluders;
+
+ // Physics
+ struct PhysicsLayerTileData {
+ struct ShapeTileData {
+ Ref<Shape2D> shape = Ref<Shape2D>();
+ bool one_way = false;
+ float one_way_margin = 1.0;
+ };
+
+ Vector<ShapeTileData> shapes;
+ };
+ Vector<PhysicsLayerTileData> physics;
+ // TODO add support for areas.
- void tile_set_shape(int p_id, int p_shape_id, const Ref<Shape2D> &p_shape);
- Ref<Shape2D> tile_get_shape(int p_id, int p_shape_id) const;
+ // Terrain
+ int terrain_set = -1;
+ int terrain_peering_bits[16] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
- void tile_set_shape_transform(int p_id, int p_shape_id, const Transform2D &p_offset);
- Transform2D tile_get_shape_transform(int p_id, int p_shape_id) const;
+ // Navigation
+ Vector<Ref<NavigationPolygon>> navigation;
- void tile_set_shape_offset(int p_id, int p_shape_id, const Vector2 &p_offset);
- Vector2 tile_get_shape_offset(int p_id, int p_shape_id) const;
+ // Misc
+ double probability = 1.0;
- void tile_set_shape_one_way(int p_id, int p_shape_id, bool p_one_way);
- bool tile_get_shape_one_way(int p_id, int p_shape_id) const;
+ // Custom data
+ Vector<Variant> custom_data;
- void tile_set_shape_one_way_margin(int p_id, int p_shape_id, float p_margin);
- float tile_get_shape_one_way_margin(int p_id, int p_shape_id) const;
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+ static void _bind_methods();
- void tile_clear_shapes(int p_id);
- void tile_add_shape(int p_id, const Ref<Shape2D> &p_shape, const Transform2D &p_transform, bool p_one_way = false, const Vector2 &p_autotile_coord = Vector2());
- int tile_get_shape_count(int p_id) const;
+public:
+ // Not exposed.
+ void set_tile_set(const TileSet *p_tile_set);
+ void notify_tile_data_properties_should_change();
+ void reset_state();
+ void set_allow_transform(bool p_allow_transform);
+ bool is_allowing_transform() const;
+
+ // Rendering
+ void set_flip_h(bool p_flip_h);
+ bool get_flip_h() const;
+ void set_flip_v(bool p_flip_v);
+ bool get_flip_v() const;
+ void set_transpose(bool p_transpose);
+ bool get_transpose() const;
+
+ void set_texture_offset(Vector2i p_texture_offset);
+ Vector2i get_texture_offset() const;
+ void tile_set_material(Ref<ShaderMaterial> p_material);
+ Ref<ShaderMaterial> tile_get_material() const;
+ void set_modulate(Color p_modulate);
+ Color get_modulate() const;
+ void set_z_index(int p_z_index);
+ int get_z_index() const;
+ void set_y_sort_origin(Vector2i p_y_sort_origin);
+ Vector2i get_y_sort_origin() const;
+
+ void set_occluder(int p_layer_id, Ref<OccluderPolygon2D> p_occluder_polygon);
+ Ref<OccluderPolygon2D> get_occluder(int p_layer_id) const;
+
+ // Physics
+ int get_collision_shapes_count(int p_layer_id) const;
+ void set_collision_shapes_count(int p_layer_id, int p_shapes_count);
+ void add_collision_shape(int p_layer_id);
+ void remove_collision_shape(int p_layer_id, int p_shape_index);
+ void set_collision_shape_shape(int p_layer_id, int p_shape_index, Ref<Shape2D> p_shape);
+ Ref<Shape2D> get_collision_shape_shape(int p_layer_id, int p_shape_index) const;
+ void set_collision_shape_one_way(int p_layer_id, int p_shape_index, bool p_one_way);
+ bool is_collision_shape_one_way(int p_layer_id, int p_shape_index) const;
+ void set_collision_shape_one_way_margin(int p_layer_id, int p_shape_index, float p_one_way_margin);
+ float get_collision_shape_one_way_margin(int p_layer_id, int p_shape_index) const;
+
+ // Terrain
+ void set_terrain_set(int p_terrain_id);
+ int get_terrain_set() const;
+ void set_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit, int p_terrain_id);
+ int get_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit) const;
+ bool is_valid_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit) const;
+
+ // Navigation
+ void set_navigation_polygon(int p_layer_id, Ref<NavigationPolygon> p_navigation_polygon);
+ Ref<NavigationPolygon> get_navigation_polygon(int p_layer_id) const;
+
+ // Misc
+ void set_probability(float p_probability);
+ float get_probability() const;
+
+ // Custom data.
+ void set_custom_data(String p_layer_name, Variant p_value);
+ Variant get_custom_data(String p_layer_name) const;
+ void set_custom_data_by_layer_id(int p_layer_id, Variant p_value);
+ Variant get_custom_data_by_layer_id(int p_layer_id) const;
+};
- void tile_set_shapes(int p_id, const Vector<ShapeData> &p_shapes);
- Vector<ShapeData> tile_get_shapes(int p_id) const;
+#include "scene/2d/tile_map.h"
- void tile_set_material(int p_id, const Ref<ShaderMaterial> &p_material);
- Ref<ShaderMaterial> tile_get_material(int p_id) const;
+class TileSetPlugin : public Object {
+ GDCLASS(TileSetPlugin, Object);
- void tile_set_modulate(int p_id, const Color &p_modulate);
- Color tile_get_modulate(int p_id) const;
+public:
+ // Tilemap updates.
+ virtual void tilemap_notification(TileMap *p_tile_map, int p_what){};
+ virtual void update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list){};
+ virtual void create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant){};
+ virtual void cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant){};
- void tile_set_occluder_offset(int p_id, const Vector2 &p_offset);
- Vector2 tile_get_occluder_offset(int p_id) const;
+ virtual void draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant){};
+};
- void tile_set_light_occluder(int p_id, const Ref<OccluderPolygon2D> &p_light_occluder);
- Ref<OccluderPolygon2D> tile_get_light_occluder(int p_id) const;
+class TileSetAtlasPluginRendering : public TileSetPlugin {
+ GDCLASS(TileSetAtlasPluginRendering, TileSetPlugin);
- void autotile_set_light_occluder(int p_id, const Ref<OccluderPolygon2D> &p_light_occluder, const Vector2 &p_coord);
- Ref<OccluderPolygon2D> autotile_get_light_occluder(int p_id, const Vector2 &p_coord) const;
- const Map<Vector2, Ref<OccluderPolygon2D>> &autotile_get_light_oclusion_map(int p_id) const;
+private:
+ static constexpr float fp_adjust = 0.00001;
+ bool quadrant_order_dirty = false;
- void tile_set_navigation_polygon_offset(int p_id, const Vector2 &p_offset);
- Vector2 tile_get_navigation_polygon_offset(int p_id) const;
+public:
+ // Tilemap updates
+ virtual void tilemap_notification(TileMap *p_tile_map, int p_what) override;
+ virtual void update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) override;
+ virtual void create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
+ virtual void cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
+
+ // Other.
+ static void draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, Color p_modulation = Color(1.0, 1.0, 1.0, 1.0));
+};
- void tile_set_navigation_polygon(int p_id, const Ref<NavigationPolygon> &p_navigation_polygon);
- Ref<NavigationPolygon> tile_get_navigation_polygon(int p_id) const;
+class TileSetAtlasPluginTerrain : public TileSetPlugin {
+ GDCLASS(TileSetAtlasPluginTerrain, TileSetPlugin);
- void autotile_set_navigation_polygon(int p_id, const Ref<NavigationPolygon> &p_navigation_polygon, const Vector2 &p_coord);
- Ref<NavigationPolygon> autotile_get_navigation_polygon(int p_id, const Vector2 &p_coord) const;
- const Map<Vector2, Ref<NavigationPolygon>> &autotile_get_navigation_map(int p_id) const;
+private:
+ static void _draw_square_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit);
+ static void _draw_square_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit);
+ static void _draw_square_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit);
- void tile_set_z_index(int p_id, int p_z_index);
- int tile_get_z_index(int p_id) const;
+ static void _draw_isometric_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit);
+ static void _draw_isometric_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit);
+ static void _draw_isometric_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit);
- void remove_tile(int p_id);
+ static void _draw_half_offset_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis);
+ static void _draw_half_offset_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis);
+ static void _draw_half_offset_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis);
- bool has_tile(int p_id) const;
+public:
+ //virtual void tilemap_notification(const TileMap * p_tile_map, int p_what);
- bool is_tile_bound(int p_drawn_id, int p_neighbor_id);
+ static void draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, const TileData *p_tile_data);
+};
- int find_tile_by_name(const String &p_name) const;
- void get_tile_list(List<int> *p_tiles) const;
+class TileSetAtlasPluginPhysics : public TileSetPlugin {
+ GDCLASS(TileSetAtlasPluginPhysics, TileSetPlugin);
- void clear();
+public:
+ // Tilemap updates
+ virtual void tilemap_notification(TileMap *p_tile_map, int p_what) override;
+ virtual void update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) override;
+ virtual void create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
+ virtual void cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
+ virtual void draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
+};
- int get_last_unused_tile_id() const;
+class TileSetAtlasPluginNavigation : public TileSetPlugin {
+ GDCLASS(TileSetAtlasPluginNavigation, TileSetPlugin);
- TileSet();
+public:
+ // Tilemap updates
+ virtual void tilemap_notification(TileMap *p_tile_map, int p_what) override;
+ virtual void update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) override;
+ //virtual void create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
+ virtual void cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
+ virtual void draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override;
};
-VARIANT_ENUM_CAST(TileSet::AutotileBindings);
-VARIANT_ENUM_CAST(TileSet::BitmaskMode);
-VARIANT_ENUM_CAST(TileSet::TileMode);
+VARIANT_ENUM_CAST(TileSet::CellNeighbor);
+VARIANT_ENUM_CAST(TileSet::TerrainMode);
+VARIANT_ENUM_CAST(TileSet::TileShape);
+VARIANT_ENUM_CAST(TileSet::TileLayout);
+VARIANT_ENUM_CAST(TileSet::TileOffsetAxis);
#endif // TILE_SET_H
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index b810f9562e..da29f2ebd8 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -3148,11 +3148,11 @@ int VisualShaderNodeGroupBase::get_free_output_port_id() const {
return output_ports.size();
}
-void VisualShaderNodeGroupBase::set_control(Control *p_control, int p_index) {
+void VisualShaderNodeGroupBase::set_ctrl_pressed(Control *p_control, int p_index) {
controls[p_index] = p_control;
}
-Control *VisualShaderNodeGroupBase::get_control(int p_index) {
+Control *VisualShaderNodeGroupBase::is_ctrl_pressed(int p_index) {
ERR_FAIL_COND_V(!controls.has(p_index), nullptr);
return controls[p_index];
}
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index 8af0fc9e44..a0e3bdf166 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -610,8 +610,8 @@ public:
int get_free_input_port_id() const;
int get_free_output_port_id() const;
- void set_control(Control *p_control, int p_index);
- Control *get_control(int p_index);
+ void set_ctrl_pressed(Control *p_control, int p_index);
+ Control *is_ctrl_pressed(int p_index);
void set_editable(bool p_enabled);
bool is_editable() const;