1 | /**************************************************************************/ |
2 | /* tile_map.h */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #ifndef TILE_MAP_H |
32 | #define TILE_MAP_H |
33 | |
34 | #include "scene/2d/node_2d.h" |
35 | #include "scene/gui/control.h" |
36 | #include "scene/resources/tile_set.h" |
37 | |
38 | class TileSetAtlasSource; |
39 | |
40 | class TerrainConstraint { |
41 | private: |
42 | const TileMap *tile_map = nullptr; |
43 | Vector2i base_cell_coords; |
44 | int bit = -1; |
45 | int terrain = -1; |
46 | |
47 | int priority = 1; |
48 | |
49 | public: |
50 | bool operator<(const TerrainConstraint &p_other) const { |
51 | if (base_cell_coords == p_other.base_cell_coords) { |
52 | return bit < p_other.bit; |
53 | } |
54 | return base_cell_coords < p_other.base_cell_coords; |
55 | } |
56 | |
57 | String to_string() const { |
58 | return vformat("Constraint {pos:%s, bit:%d, terrain:%d, priority:%d}" , base_cell_coords, bit, terrain, priority); |
59 | } |
60 | |
61 | Vector2i get_base_cell_coords() const { |
62 | return base_cell_coords; |
63 | } |
64 | |
65 | bool is_center_bit() const { |
66 | return bit == 0; |
67 | } |
68 | |
69 | HashMap<Vector2i, TileSet::CellNeighbor> get_overlapping_coords_and_peering_bits() const; |
70 | |
71 | void set_terrain(int p_terrain) { |
72 | terrain = p_terrain; |
73 | } |
74 | |
75 | int get_terrain() const { |
76 | return terrain; |
77 | } |
78 | |
79 | void set_priority(int p_priority) { |
80 | priority = p_priority; |
81 | } |
82 | |
83 | int get_priority() const { |
84 | return priority; |
85 | } |
86 | |
87 | TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, int p_terrain); // For the center terrain bit |
88 | TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, const TileSet::CellNeighbor &p_bit, int p_terrain); // For peering bits |
89 | TerrainConstraint(){}; |
90 | }; |
91 | |
92 | #ifdef DEBUG_ENABLED |
93 | class DebugQuadrant; |
94 | #endif // DEBUG_ENABLED |
95 | class RenderingQuadrant; |
96 | |
97 | struct CellData { |
98 | Vector2i coords; |
99 | TileMapCell cell; |
100 | |
101 | // Debug. |
102 | SelfList<CellData> debug_quadrant_list_element; |
103 | |
104 | // Rendering. |
105 | Ref<RenderingQuadrant> rendering_quadrant; |
106 | SelfList<CellData> rendering_quadrant_list_element; |
107 | List<RID> occluders; |
108 | |
109 | // Physics. |
110 | LocalVector<RID> bodies; |
111 | |
112 | // Navigation. |
113 | LocalVector<RID> navigation_regions; |
114 | |
115 | // Scenes. |
116 | String scene; |
117 | |
118 | // Runtime TileData cache. |
119 | TileData *runtime_tile_data_cache = nullptr; |
120 | |
121 | // List elements. |
122 | SelfList<CellData> dirty_list_element; |
123 | |
124 | // For those, copy everything but SelfList elements. |
125 | void operator=(const CellData &p_other) { |
126 | coords = p_other.coords; |
127 | cell = p_other.cell; |
128 | occluders = p_other.occluders; |
129 | bodies = p_other.bodies; |
130 | navigation_regions = p_other.navigation_regions; |
131 | scene = p_other.scene; |
132 | runtime_tile_data_cache = p_other.runtime_tile_data_cache; |
133 | } |
134 | |
135 | CellData(const CellData &p_other) : |
136 | debug_quadrant_list_element(this), |
137 | rendering_quadrant_list_element(this), |
138 | dirty_list_element(this) { |
139 | coords = p_other.coords; |
140 | cell = p_other.cell; |
141 | occluders = p_other.occluders; |
142 | bodies = p_other.bodies; |
143 | navigation_regions = p_other.navigation_regions; |
144 | scene = p_other.scene; |
145 | runtime_tile_data_cache = p_other.runtime_tile_data_cache; |
146 | } |
147 | |
148 | CellData() : |
149 | debug_quadrant_list_element(this), |
150 | rendering_quadrant_list_element(this), |
151 | dirty_list_element(this) { |
152 | } |
153 | }; |
154 | |
155 | #ifdef DEBUG_ENABLED |
156 | class DebugQuadrant : public RefCounted { |
157 | GDCLASS(DebugQuadrant, RefCounted); |
158 | |
159 | public: |
160 | Vector2i quadrant_coords; |
161 | SelfList<CellData>::List cells; |
162 | RID canvas_item; |
163 | |
164 | SelfList<DebugQuadrant> dirty_quadrant_list_element; |
165 | |
166 | // For those, copy everything but SelfList elements. |
167 | DebugQuadrant(const DebugQuadrant &p_other) : |
168 | dirty_quadrant_list_element(this) { |
169 | quadrant_coords = p_other.quadrant_coords; |
170 | cells = p_other.cells; |
171 | canvas_item = p_other.canvas_item; |
172 | } |
173 | |
174 | DebugQuadrant() : |
175 | dirty_quadrant_list_element(this) { |
176 | } |
177 | |
178 | ~DebugQuadrant() { |
179 | cells.clear(); |
180 | } |
181 | }; |
182 | #endif // DEBUG_ENABLED |
183 | |
184 | class RenderingQuadrant : public RefCounted { |
185 | GDCLASS(RenderingQuadrant, RefCounted); |
186 | |
187 | public: |
188 | struct CoordsWorldComparator { |
189 | _ALWAYS_INLINE_ bool operator()(const Vector2 &p_a, const Vector2 &p_b) const { |
190 | // We sort the cells by their local coords, as it is needed by rendering. |
191 | if (p_a.y == p_b.y) { |
192 | return p_a.x > p_b.x; |
193 | } else { |
194 | return p_a.y < p_b.y; |
195 | } |
196 | } |
197 | }; |
198 | |
199 | Vector2i quadrant_coords; |
200 | SelfList<CellData>::List cells; |
201 | List<RID> canvas_items; |
202 | |
203 | SelfList<RenderingQuadrant> dirty_quadrant_list_element; |
204 | |
205 | // For those, copy everything but SelfList elements. |
206 | RenderingQuadrant(const RenderingQuadrant &p_other) : |
207 | dirty_quadrant_list_element(this) { |
208 | quadrant_coords = p_other.quadrant_coords; |
209 | cells = p_other.cells; |
210 | canvas_items = p_other.canvas_items; |
211 | } |
212 | |
213 | RenderingQuadrant() : |
214 | dirty_quadrant_list_element(this) { |
215 | } |
216 | |
217 | ~RenderingQuadrant() { |
218 | cells.clear(); |
219 | } |
220 | }; |
221 | |
222 | class TileMapLayer : public RefCounted { |
223 | GDCLASS(TileMapLayer, RefCounted); |
224 | |
225 | public: |
226 | enum DataFormat { |
227 | FORMAT_1 = 0, |
228 | FORMAT_2, |
229 | FORMAT_3, |
230 | FORMAT_MAX, |
231 | }; |
232 | |
233 | enum DirtyFlags { |
234 | DIRTY_FLAGS_LAYER_ENABLED = 0, |
235 | DIRTY_FLAGS_LAYER_MODULATE, |
236 | DIRTY_FLAGS_LAYER_Y_SORT_ENABLED, |
237 | DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN, |
238 | DIRTY_FLAGS_LAYER_Z_INDEX, |
239 | DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE, |
240 | DIRTY_FLAGS_TILE_MAP_IN_TREE, |
241 | DIRTY_FLAGS_TILE_MAP_IN_CANVAS, |
242 | DIRTY_FLAGS_TILE_MAP_VISIBILITY, |
243 | DIRTY_FLAGS_TILE_MAP_XFORM, |
244 | DIRTY_FLAGS_TILE_MAP_LOCAL_XFORM, |
245 | DIRTY_FLAGS_TILE_MAP_SELECTED_LAYER, |
246 | DIRTY_FLAGS_TILE_MAP_LIGHT_MASK, |
247 | DIRTY_FLAGS_TILE_MAP_MATERIAL, |
248 | DIRTY_FLAGS_TILE_MAP_USE_PARENT_MATERIAL, |
249 | DIRTY_FLAGS_TILE_MAP_TEXTURE_FILTER, |
250 | DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT, |
251 | DIRTY_FLAGS_TILE_MAP_TILE_SET, |
252 | DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE, |
253 | DIRTY_FLAGS_TILE_MAP_COLLISION_ANIMATABLE, |
254 | DIRTY_FLAGS_TILE_MAP_COLLISION_VISIBILITY_MODE, |
255 | DIRTY_FLAGS_TILE_MAP_NAVIGATION_VISIBILITY_MODE, |
256 | DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED, |
257 | DIRTY_FLAGS_TILE_MAP_RUNTIME_UPDATE, |
258 | DIRTY_FLAGS_MAX, |
259 | }; |
260 | |
261 | private: |
262 | // Exposed properties. |
263 | String name; |
264 | bool enabled = true; |
265 | Color modulate = Color(1, 1, 1, 1); |
266 | bool y_sort_enabled = false; |
267 | int y_sort_origin = 0; |
268 | int z_index = 0; |
269 | RID navigation_map; |
270 | bool uses_world_navigation_map = false; |
271 | |
272 | // Internal. |
273 | TileMap *tile_map_node = nullptr; |
274 | int layer_index_in_tile_map_node = -1; |
275 | RID canvas_item; |
276 | HashMap<Vector2i, CellData> tile_map; |
277 | |
278 | // Dirty flag. Allows knowing what was modified since the last update. |
279 | struct { |
280 | bool flags[DIRTY_FLAGS_MAX] = { false }; |
281 | SelfList<CellData>::List cell_list; |
282 | } dirty; |
283 | bool in_destructor = false; |
284 | |
285 | // Rect cache. |
286 | mutable Rect2 rect_cache; |
287 | mutable bool rect_cache_dirty = true; |
288 | mutable Rect2i used_rect_cache; |
289 | mutable bool used_rect_cache_dirty = true; |
290 | |
291 | // Runtime tile data. |
292 | bool _runtime_update_tile_data_was_cleaned_up = false; |
293 | void _build_runtime_update_tile_data(); |
294 | void _build_runtime_update_tile_data_for_cell(CellData &r_cell_data, bool p_auto_add_to_dirty_list = false); |
295 | void _clear_runtime_update_tile_data(); |
296 | |
297 | // Per-system methods. |
298 | #ifdef DEBUG_ENABLED |
299 | HashMap<Vector2i, Ref<DebugQuadrant>> debug_quadrant_map; |
300 | Vector2i _coords_to_debug_quadrant_coords(const Vector2i &p_coords) const; |
301 | bool _debug_was_cleaned_up = false; |
302 | void _debug_update(); |
303 | void _debug_quadrants_update_cell(CellData &r_cell_data, SelfList<DebugQuadrant>::List &r_dirty_debug_quadrant_list); |
304 | #endif // DEBUG_ENABLED |
305 | |
306 | HashMap<Vector2i, Ref<RenderingQuadrant>> rendering_quadrant_map; |
307 | Vector2i _coords_to_rendering_quadrant_coords(const Vector2i &p_coords) const; |
308 | bool _rendering_was_cleaned_up = false; |
309 | void _rendering_update(); |
310 | void _rendering_quadrants_update_cell(CellData &r_cell_data, SelfList<RenderingQuadrant>::List &r_dirty_rendering_quadrant_list); |
311 | void _rendering_occluders_clear_cell(CellData &r_cell_data); |
312 | void _rendering_occluders_update_cell(CellData &r_cell_data); |
313 | #ifdef DEBUG_ENABLED |
314 | void _rendering_draw_cell_debug(const RID &p_canvas_item, const Vector2i &p_quadrant_pos, const CellData &r_cell_data); |
315 | #endif // DEBUG_ENABLED |
316 | |
317 | HashMap<RID, Vector2i> bodies_coords; // Mapping for RID to coords. |
318 | bool _physics_was_cleaned_up = false; |
319 | void _physics_update(); |
320 | void _physics_notify_tilemap_change(DirtyFlags p_what); |
321 | void _physics_clear_cell(CellData &r_cell_data); |
322 | void _physics_update_cell(CellData &r_cell_data); |
323 | #ifdef DEBUG_ENABLED |
324 | void _physics_draw_cell_debug(const RID &p_canvas_item, const Vector2i &p_quadrant_pos, const CellData &r_cell_data); |
325 | #endif // DEBUG_ENABLED |
326 | |
327 | bool _navigation_was_cleaned_up = false; |
328 | void _navigation_update(); |
329 | void _navigation_clear_cell(CellData &r_cell_data); |
330 | void _navigation_update_cell(CellData &r_cell_data); |
331 | #ifdef DEBUG_ENABLED |
332 | void _navigation_draw_cell_debug(const RID &p_canvas_item, const Vector2i &p_quadrant_pos, const CellData &r_cell_data); |
333 | #endif // DEBUG_ENABLED |
334 | |
335 | bool _scenes_was_cleaned_up = false; |
336 | void _scenes_update(); |
337 | void _scenes_clear_cell(CellData &r_cell_data); |
338 | void _scenes_update_cell(CellData &r_cell_data); |
339 | #ifdef DEBUG_ENABLED |
340 | void _scenes_draw_cell_debug(const RID &p_canvas_item, const Vector2i &p_quadrant_pos, const CellData &r_cell_data); |
341 | #endif // DEBUG_ENABLED |
342 | |
343 | // Terrains. |
344 | TileSet::TerrainsPattern _get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern); |
345 | RBSet<TerrainConstraint> _get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const; |
346 | RBSet<TerrainConstraint> _get_terrain_constraints_from_painted_cells_list(const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const; |
347 | |
348 | public: |
349 | // TileMap node. |
350 | void set_tile_map(TileMap *p_tile_map); |
351 | void set_layer_index_in_tile_map_node(int p_index); |
352 | |
353 | // Rect caching. |
354 | Rect2 get_rect(bool &r_changed) const; |
355 | |
356 | // Terrains. |
357 | HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints); // Not exposed. |
358 | HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_connect(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); // Not exposed. |
359 | HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_path(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); // Not exposed. |
360 | HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_pattern(const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains = true); // Not exposed. |
361 | |
362 | // Not exposed to users. |
363 | TileMapCell get_cell(const Vector2i &p_coords, bool p_use_proxies = false) const; |
364 | int get_effective_quadrant_size() const; |
365 | |
366 | // For TileMap node's use. |
367 | void set_tile_data(DataFormat p_format, const Vector<int> &p_data); |
368 | Vector<int> get_tile_data() const; |
369 | void notify_tile_map_change(DirtyFlags p_what); |
370 | void internal_update(); |
371 | |
372 | // --- Exposed in TileMap --- |
373 | |
374 | // Cells manipulation. |
375 | void set_cell(const Vector2i &p_coords, int p_source_id = TileSet::INVALID_SOURCE, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = 0); |
376 | void erase_cell(const Vector2i &p_coords); |
377 | |
378 | int get_cell_source_id(const Vector2i &p_coords, bool p_use_proxies = false) const; |
379 | Vector2i get_cell_atlas_coords(const Vector2i &p_coords, bool p_use_proxies = false) const; |
380 | int get_cell_alternative_tile(const Vector2i &p_coords, bool p_use_proxies = false) const; |
381 | TileData *get_cell_tile_data(const Vector2i &p_coords, bool p_use_proxies = false) const; // Helper method to make accessing the data easier. |
382 | void clear(); |
383 | |
384 | // Patterns. |
385 | Ref<TileMapPattern> get_pattern(TypedArray<Vector2i> p_coords_array); |
386 | void set_pattern(const Vector2i &p_position, const Ref<TileMapPattern> p_pattern); |
387 | |
388 | // Terrains. |
389 | void set_cells_terrain_connect(TypedArray<Vector2i> p_cells, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); |
390 | void set_cells_terrain_path(TypedArray<Vector2i> p_path, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); |
391 | |
392 | // Cells usage. |
393 | TypedArray<Vector2i> get_used_cells() const; |
394 | TypedArray<Vector2i> get_used_cells_by_id(int p_source_id = TileSet::INVALID_SOURCE, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE) const; |
395 | Rect2i get_used_rect() const; |
396 | |
397 | // Layer properties. |
398 | void set_name(String p_name); |
399 | String get_name() const; |
400 | void set_enabled(bool p_enabled); |
401 | bool is_enabled() const; |
402 | void set_modulate(Color p_modulate); |
403 | Color get_modulate() const; |
404 | void set_y_sort_enabled(bool p_y_sort_enabled); |
405 | bool is_y_sort_enabled() const; |
406 | void set_y_sort_origin(int p_y_sort_origin); |
407 | int get_y_sort_origin() const; |
408 | void set_z_index(int p_z_index); |
409 | int get_z_index() const; |
410 | void set_navigation_map(RID p_map); |
411 | RID get_navigation_map() const; |
412 | |
413 | // Fixing and clearing methods. |
414 | void fix_invalid_tiles(); |
415 | |
416 | // Find coords for body. |
417 | bool has_body_rid(RID p_physics_body) const; |
418 | Vector2i get_coords_for_body_rid(RID p_physics_body) const; // For finding tiles from collision. |
419 | |
420 | ~TileMapLayer(); |
421 | }; |
422 | |
423 | class TileMap : public Node2D { |
424 | GDCLASS(TileMap, Node2D); |
425 | |
426 | public: |
427 | enum VisibilityMode { |
428 | VISIBILITY_MODE_DEFAULT, |
429 | VISIBILITY_MODE_FORCE_SHOW, |
430 | VISIBILITY_MODE_FORCE_HIDE, |
431 | }; |
432 | |
433 | private: |
434 | friend class TileSetPlugin; |
435 | |
436 | // A compatibility enum to specify how is the data if formatted. |
437 | mutable TileMapLayer::DataFormat format = TileMapLayer::FORMAT_3; |
438 | |
439 | static constexpr float FP_ADJUST = 0.00001; |
440 | |
441 | // Properties. |
442 | Ref<TileSet> tile_set; |
443 | int rendering_quadrant_size = 16; |
444 | bool collision_animatable = false; |
445 | VisibilityMode collision_visibility_mode = VISIBILITY_MODE_DEFAULT; |
446 | VisibilityMode navigation_visibility_mode = VISIBILITY_MODE_DEFAULT; |
447 | |
448 | // Layers. |
449 | LocalVector<Ref<TileMapLayer>> layers; |
450 | int selected_layer = -1; |
451 | bool pending_update = false; |
452 | |
453 | Transform2D last_valid_transform; |
454 | Transform2D new_transform; |
455 | |
456 | void _tile_set_changed(); |
457 | |
458 | // Polygons. |
459 | HashMap<Pair<Ref<Resource>, int>, Ref<Resource>, PairHash<Ref<Resource>, int>> polygon_cache; |
460 | PackedVector2Array _get_transformed_vertices(const PackedVector2Array &p_vertices, int p_alternative_id); |
461 | |
462 | protected: |
463 | bool _set(const StringName &p_name, const Variant &p_value); |
464 | bool _get(const StringName &p_name, Variant &r_ret) const; |
465 | void _get_property_list(List<PropertyInfo> *p_list) const; |
466 | |
467 | void _notification(int p_what); |
468 | static void _bind_methods(); |
469 | |
470 | #ifndef DISABLE_DEPRECATED |
471 | Rect2i _get_used_rect_bind_compat_78328(); |
472 | void _set_quadrant_size_compat_81070(int p_quadrant_size); |
473 | int _get_quadrant_size_compat_81070() const; |
474 | |
475 | static void _bind_compatibility_methods(); |
476 | #endif |
477 | |
478 | public: |
479 | static Vector2i transform_coords_layout(const Vector2i &p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout); |
480 | |
481 | #ifdef TOOLS_ENABLED |
482 | virtual Rect2 _edit_get_rect() const override; |
483 | #endif |
484 | |
485 | #ifndef DISABLE_DEPRECATED |
486 | void force_update(int p_layer); |
487 | #endif |
488 | |
489 | // Called by TileMapLayers. |
490 | void queue_internal_update(); |
491 | void _internal_update(); |
492 | |
493 | void set_tileset(const Ref<TileSet> &p_tileset); |
494 | Ref<TileSet> get_tileset() const; |
495 | |
496 | void set_rendering_quadrant_size(int p_size); |
497 | int get_rendering_quadrant_size() const; |
498 | |
499 | static void draw_tile(RID p_canvas_item, const Vector2 &p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, const Vector2i &p_atlas_coords, int p_alternative_tile, int p_frame = -1, Color p_modulation = Color(1.0, 1.0, 1.0, 1.0), const TileData *p_tile_data_override = nullptr, real_t p_animation_offset = 0.0); |
500 | |
501 | // Layers management. |
502 | int get_layers_count() const; |
503 | void add_layer(int p_to_pos); |
504 | void move_layer(int p_layer, int p_to_pos); |
505 | void remove_layer(int p_layer); |
506 | |
507 | void set_layer_name(int p_layer, String p_name); |
508 | String get_layer_name(int p_layer) const; |
509 | void set_layer_enabled(int p_layer, bool p_visible); |
510 | bool is_layer_enabled(int p_layer) const; |
511 | void set_layer_modulate(int p_layer, Color p_modulate); |
512 | Color get_layer_modulate(int p_layer) const; |
513 | void set_layer_y_sort_enabled(int p_layer, bool p_enabled); |
514 | bool is_layer_y_sort_enabled(int p_layer) const; |
515 | void set_layer_y_sort_origin(int p_layer, int p_y_sort_origin); |
516 | int get_layer_y_sort_origin(int p_layer) const; |
517 | void set_layer_z_index(int p_layer, int p_z_index); |
518 | int get_layer_z_index(int p_layer) const; |
519 | |
520 | void set_layer_navigation_map(int p_layer, RID p_map); |
521 | RID get_layer_navigation_map(int p_layer) const; |
522 | |
523 | void set_selected_layer(int p_layer_id); // For editor use. |
524 | int get_selected_layer() const; |
525 | |
526 | void set_collision_animatable(bool p_enabled); |
527 | bool is_collision_animatable() const; |
528 | |
529 | // Debug visibility modes. |
530 | void set_collision_visibility_mode(VisibilityMode p_show_collision); |
531 | VisibilityMode get_collision_visibility_mode(); |
532 | |
533 | void set_navigation_visibility_mode(VisibilityMode p_show_navigation); |
534 | VisibilityMode get_navigation_visibility_mode(); |
535 | |
536 | // Cells accessors. |
537 | void set_cell(int p_layer, const Vector2i &p_coords, int p_source_id = TileSet::INVALID_SOURCE, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = 0); |
538 | void erase_cell(int p_layer, const Vector2i &p_coords); |
539 | int get_cell_source_id(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const; |
540 | Vector2i get_cell_atlas_coords(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const; |
541 | int get_cell_alternative_tile(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const; |
542 | // Helper method to make accessing the data easier. |
543 | TileData *get_cell_tile_data(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const; |
544 | |
545 | // Patterns. |
546 | Ref<TileMapPattern> get_pattern(int p_layer, TypedArray<Vector2i> p_coords_array); |
547 | Vector2i map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern); |
548 | void set_pattern(int p_layer, const Vector2i &p_position, const Ref<TileMapPattern> p_pattern); |
549 | |
550 | // Terrains (Not exposed). |
551 | HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_constraints(int p_layer, const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints); |
552 | HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_connect(int p_layer, const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); |
553 | HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_path(int p_layer, const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); |
554 | HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_pattern(int p_layer, const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains = true); |
555 | |
556 | // Terrains (exposed). |
557 | void set_cells_terrain_connect(int p_layer, TypedArray<Vector2i> p_cells, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); |
558 | void set_cells_terrain_path(int p_layer, TypedArray<Vector2i> p_path, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); |
559 | |
560 | // Not exposed to users. |
561 | TileMapCell get_cell(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const; |
562 | int get_effective_quadrant_size(int p_layer) const; |
563 | |
564 | virtual void set_y_sort_enabled(bool p_enable) override; |
565 | |
566 | Vector2 map_to_local(const Vector2i &p_pos) const; |
567 | Vector2i local_to_map(const Vector2 &p_pos) const; |
568 | |
569 | bool is_existing_neighbor(TileSet::CellNeighbor p_cell_neighbor) const; |
570 | Vector2i get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const; |
571 | |
572 | TypedArray<Vector2i> get_used_cells(int p_layer) const; |
573 | TypedArray<Vector2i> get_used_cells_by_id(int p_layer, int p_source_id = TileSet::INVALID_SOURCE, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE) const; |
574 | Rect2i get_used_rect() const; |
575 | |
576 | // Override some methods of the CanvasItem class to pass the changes to the quadrants CanvasItems. |
577 | virtual void set_light_mask(int p_light_mask) override; |
578 | virtual void set_material(const Ref<Material> &p_material) override; |
579 | virtual void set_use_parent_material(bool p_use_parent_material) override; |
580 | virtual void set_texture_filter(CanvasItem::TextureFilter p_texture_filter) override; |
581 | virtual void set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) override; |
582 | |
583 | // For finding tiles from collision. |
584 | Vector2i get_coords_for_body_rid(RID p_physics_body); |
585 | // For getting their layers as well. |
586 | int get_layer_for_body_rid(RID p_physics_body); |
587 | |
588 | // Fixing and clearing methods. |
589 | void fix_invalid_tiles(); |
590 | |
591 | // Clears tiles from a given layer. |
592 | void clear_layer(int p_layer); |
593 | void clear(); |
594 | |
595 | // Force a TileMap update. |
596 | void update_internals(); |
597 | void notify_runtime_tile_data_update(int p_layer = -1); |
598 | |
599 | // Helpers? |
600 | TypedArray<Vector2i> get_surrounding_cells(const Vector2i &coords); |
601 | void draw_cells_outline(Control *p_control, const RBSet<Vector2i> &p_cells, Color p_color, Transform2D p_transform = Transform2D()); |
602 | Ref<Resource> get_transformed_polygon(Ref<Resource> p_polygon, int p_alternative_id); |
603 | |
604 | // Virtual function to modify the TileData at runtime. |
605 | GDVIRTUAL2R(bool, _use_tile_data_runtime_update, int, Vector2i); |
606 | GDVIRTUAL3(_tile_data_runtime_update, int, Vector2i, TileData *); |
607 | |
608 | // Configuration warnings. |
609 | PackedStringArray get_configuration_warnings() const override; |
610 | |
611 | TileMap(); |
612 | ~TileMap(); |
613 | }; |
614 | |
615 | VARIANT_ENUM_CAST(TileMap::VisibilityMode); |
616 | |
617 | #endif // TILE_MAP_H |
618 | |