Change TileMapEditor to TileMapLayerEditor
This commit is contained in:
parent
4e990cd7e5
commit
5a999d67ec
16 changed files with 1506 additions and 1258 deletions
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="TileMap" inherits="Node2D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
|
||||
<class name="TileMap" inherits="TileMapLayerGroup" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
|
||||
<brief_description>
|
||||
Node for 2D tile-based maps.
|
||||
</brief_description>
|
||||
|
@ -488,9 +488,6 @@
|
|||
The quadrant size does not apply on Y-sorted layers, as tiles are be grouped by Y position instead in that case.
|
||||
[b]Note:[/b] As quadrants are created according to the map's coordinate system, the quadrant's "square shape" might not look like square in the TileMap's local coordinate system.
|
||||
</member>
|
||||
<member name="tile_set" type="TileSet" setter="set_tileset" getter="get_tileset">
|
||||
The assigned [TileSet].
|
||||
</member>
|
||||
</members>
|
||||
<signals>
|
||||
<signal name="changed">
|
||||
|
|
17
doc/classes/TileMapLayerGroup.xml
Normal file
17
doc/classes/TileMapLayerGroup.xml
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="TileMapLayerGroup" inherits="Node2D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
|
||||
<brief_description>
|
||||
Groups a set of tile map layers together, allowing them to share a provided [TileSet].
|
||||
</brief_description>
|
||||
<description>
|
||||
Groups together tile map layers as part or the same map, replacing the [TileMap] node. Child layers will use this node's [member tile_set].
|
||||
The editor also uses [TileMapLayerGroup] as a way to store which layers are selected in a given group. This allows highlighting the currently selected layers.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<members>
|
||||
<member name="tile_set" type="TileSet" setter="set_tileset" getter="get_tileset">
|
||||
The assigned [TileSet]. This TileSet will be applied to all child layers.
|
||||
</member>
|
||||
</members>
|
||||
</class>
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
/**************************************************************************/
|
||||
/* tile_map_editor.h */
|
||||
/* tile_map_layer_editor.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
|
@ -28,8 +28,8 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TILE_MAP_EDITOR_H
|
||||
#define TILE_MAP_EDITOR_H
|
||||
#ifndef TILE_MAP_LAYER_EDITOR_H
|
||||
#define TILE_MAP_LAYER_EDITOR_H
|
||||
|
||||
#include "tile_atlas_view.h"
|
||||
|
||||
|
@ -48,9 +48,13 @@
|
|||
#include "scene/gui/tab_bar.h"
|
||||
#include "scene/gui/tree.h"
|
||||
|
||||
class TileMapEditor;
|
||||
class TileMapLayerEditor;
|
||||
|
||||
class TileMapLayerSubEditorPlugin : public Object {
|
||||
protected:
|
||||
ObjectID edited_tile_map_layer_id;
|
||||
TileMapLayer *_get_edited_layer() const;
|
||||
|
||||
class TileMapSubEditorPlugin : public Object {
|
||||
public:
|
||||
struct TabData {
|
||||
Control *toolbar = nullptr;
|
||||
|
@ -64,11 +68,11 @@ public:
|
|||
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return false; };
|
||||
virtual void forward_canvas_draw_over_viewport(Control *p_overlay){};
|
||||
virtual void tile_set_changed(){};
|
||||
virtual void edit(ObjectID p_tile_map_id, int p_tile_map_layer){};
|
||||
virtual void edit(ObjectID p_tile_map_layer_id){};
|
||||
};
|
||||
|
||||
class TileMapEditorTilesPlugin : public TileMapSubEditorPlugin {
|
||||
GDCLASS(TileMapEditorTilesPlugin, TileMapSubEditorPlugin);
|
||||
class TileMapLayerEditorTilesPlugin : public TileMapLayerSubEditorPlugin {
|
||||
GDCLASS(TileMapLayerEditorTilesPlugin, TileMapLayerSubEditorPlugin);
|
||||
|
||||
public:
|
||||
enum {
|
||||
|
@ -79,10 +83,6 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
ObjectID tile_map_id;
|
||||
int tile_map_layer = -1;
|
||||
virtual void edit(ObjectID p_tile_map_id, int p_tile_map_layer) override;
|
||||
|
||||
///// Toolbar /////
|
||||
HBoxContainer *toolbar = nullptr;
|
||||
|
||||
|
@ -237,18 +237,16 @@ public:
|
|||
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override;
|
||||
virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override;
|
||||
|
||||
TileMapEditorTilesPlugin();
|
||||
~TileMapEditorTilesPlugin();
|
||||
virtual void edit(ObjectID p_tile_map_layer_id) override;
|
||||
|
||||
TileMapLayerEditorTilesPlugin();
|
||||
~TileMapLayerEditorTilesPlugin();
|
||||
};
|
||||
|
||||
class TileMapEditorTerrainsPlugin : public TileMapSubEditorPlugin {
|
||||
GDCLASS(TileMapEditorTerrainsPlugin, TileMapSubEditorPlugin);
|
||||
class TileMapLayerEditorTerrainsPlugin : public TileMapLayerSubEditorPlugin {
|
||||
GDCLASS(TileMapLayerEditorTerrainsPlugin, TileMapLayerSubEditorPlugin);
|
||||
|
||||
private:
|
||||
ObjectID tile_map_id;
|
||||
int tile_map_layer = -1;
|
||||
virtual void edit(ObjectID p_tile_map_id, int p_tile_map_layer) override;
|
||||
|
||||
// Toolbar.
|
||||
HBoxContainer *toolbar = nullptr;
|
||||
|
||||
|
@ -331,28 +329,33 @@ public:
|
|||
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override;
|
||||
virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override;
|
||||
|
||||
TileMapEditorTerrainsPlugin();
|
||||
~TileMapEditorTerrainsPlugin();
|
||||
virtual void edit(ObjectID p_tile_map_layer_id) override;
|
||||
|
||||
TileMapLayerEditorTerrainsPlugin();
|
||||
~TileMapLayerEditorTerrainsPlugin();
|
||||
};
|
||||
|
||||
class TileMapEditor : public VBoxContainer {
|
||||
GDCLASS(TileMapEditor, VBoxContainer);
|
||||
class TileMapLayerEditor : public VBoxContainer {
|
||||
GDCLASS(TileMapLayerEditor, VBoxContainer);
|
||||
|
||||
private:
|
||||
bool tileset_changed_needs_update = false;
|
||||
ObjectID tile_map_id;
|
||||
int tile_map_layer = -1;
|
||||
|
||||
ObjectID edited_tile_map_layer_id;
|
||||
TileMapLayer *_get_edited_layer() const;
|
||||
|
||||
// Vector to keep plugins.
|
||||
Vector<TileMapSubEditorPlugin *> tile_map_editor_plugins;
|
||||
Vector<TileMapLayerSubEditorPlugin *> tile_map_editor_plugins;
|
||||
|
||||
// Toolbar.
|
||||
HFlowContainer *tile_map_toolbar = nullptr;
|
||||
|
||||
OptionButton *layers_selection_button = nullptr;
|
||||
Button *toggle_highlight_selected_layer_button = nullptr;
|
||||
void _layers_selection_item_selected(int p_index);
|
||||
|
||||
Button *toggle_highlight_selected_layer_button = nullptr;
|
||||
void _highlight_selected_layer_button_toggled(bool p_pressed);
|
||||
|
||||
Button *toggle_grid_button = nullptr;
|
||||
void _on_grid_toggled(bool p_pressed);
|
||||
|
||||
|
@ -362,8 +365,8 @@ private:
|
|||
// Bottom panel.
|
||||
Label *missing_tileset_label = nullptr;
|
||||
TabBar *tabs_bar = nullptr;
|
||||
LocalVector<TileMapSubEditorPlugin::TabData> tabs_data;
|
||||
LocalVector<TileMapSubEditorPlugin *> tabs_plugins;
|
||||
LocalVector<TileMapLayerSubEditorPlugin::TabData> tabs_data;
|
||||
LocalVector<TileMapLayerSubEditorPlugin *> tabs_plugins;
|
||||
void _update_bottom_panel();
|
||||
|
||||
// TileMap.
|
||||
|
@ -371,31 +374,33 @@ private:
|
|||
Ref<Texture2D> warning_pattern_texture;
|
||||
|
||||
// CallBack.
|
||||
void _tile_map_changed();
|
||||
void _tile_map_layer_changed();
|
||||
void _tab_changed(int p_tab_changed);
|
||||
|
||||
// Updates.
|
||||
void _layers_select_next_or_previous(bool p_next);
|
||||
void _update_layers_selection();
|
||||
void _update_highlighting_toggle();
|
||||
|
||||
// Inspector undo/redo callback.
|
||||
void _move_tile_map_array_element(Object *p_undo_redo, Object *p_edited, String p_array_prefix, int p_from_index, int p_to_pos);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
void _draw_shape(Control *p_control, Rect2 p_region, TileSet::TileShape p_shape, TileSet::TileOffsetAxis p_offset_axis, Color p_color);
|
||||
|
||||
public:
|
||||
bool forward_canvas_gui_input(const Ref<InputEvent> &p_event);
|
||||
void forward_canvas_draw_over_viewport(Control *p_overlay);
|
||||
|
||||
void edit(TileMap *p_tile_map);
|
||||
void edit(TileMapLayer *p_tile_map_layer);
|
||||
void update_layers_selector();
|
||||
|
||||
TileMapEditor();
|
||||
~TileMapEditor();
|
||||
TileMapLayerEditor();
|
||||
~TileMapLayerEditor();
|
||||
|
||||
// Static functions.
|
||||
static Vector<Vector2i> get_line(TileMap *p_tile_map, Vector2i p_from_cell, Vector2i p_to_cell);
|
||||
static Vector<Vector2i> get_line(const TileMapLayer *p_tile_map_layer, Vector2i p_from_cell, Vector2i p_to_cell);
|
||||
};
|
||||
|
||||
#endif // TILE_MAP_EDITOR_H
|
||||
#endif // TILE_MAP_LAYER_EDITOR_H
|
|
@ -40,8 +40,8 @@
|
|||
#include "editor/editor_string_names.h"
|
||||
#include "editor/plugins/canvas_item_editor_plugin.h"
|
||||
#include "editor/themes/editor_scale.h"
|
||||
|
||||
#include "scene/2d/tile_map.h"
|
||||
#include "scene/2d/tile_map_layer.h"
|
||||
#include "scene/gui/box_container.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/gui/control.h"
|
||||
|
@ -324,7 +324,7 @@ TilesEditorUtils::~TilesEditorUtils() {
|
|||
singleton = nullptr;
|
||||
}
|
||||
|
||||
void TileMapEditorPlugin::_tile_map_changed() {
|
||||
void TileMapEditorPlugin::_tile_map_layer_changed() {
|
||||
if (tile_map_changed_needs_update) {
|
||||
return;
|
||||
}
|
||||
|
@ -332,23 +332,105 @@ void TileMapEditorPlugin::_tile_map_changed() {
|
|||
callable_mp(this, &TileMapEditorPlugin::_update_tile_map).call_deferred();
|
||||
}
|
||||
|
||||
void TileMapEditorPlugin::_update_tile_map() {
|
||||
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
|
||||
void TileMapEditorPlugin::_tile_map_layer_removed() {
|
||||
// Workaround for TileMap, making sure the editor stays open when you delete the currently edited layer.
|
||||
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_group_id));
|
||||
if (tile_map) {
|
||||
Ref<TileSet> tile_set = tile_map->get_tileset();
|
||||
if (tile_set.is_valid() && edited_tileset != tile_set->get_instance_id()) {
|
||||
tile_set_plugin_singleton->edit(tile_map->get_tileset().ptr());
|
||||
edit(tile_map);
|
||||
}
|
||||
}
|
||||
|
||||
void TileMapEditorPlugin::_update_tile_map() {
|
||||
TileMapLayer *edited_layer = Object::cast_to<TileMapLayer>(ObjectDB::get_instance(tile_map_layer_id));
|
||||
if (edited_layer) {
|
||||
Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
|
||||
if (tile_set.is_valid() && tile_set_id != tile_set->get_instance_id()) {
|
||||
tile_set_plugin_singleton->edit(tile_set.ptr());
|
||||
tile_set_plugin_singleton->make_visible(true);
|
||||
edited_tileset = tile_set->get_instance_id();
|
||||
tile_set_id = tile_set->get_instance_id();
|
||||
} else if (tile_set.is_null()) {
|
||||
tile_set_plugin_singleton->edit(nullptr);
|
||||
tile_set_plugin_singleton->make_visible(false);
|
||||
edited_tileset = ObjectID();
|
||||
tile_set_id = ObjectID();
|
||||
}
|
||||
}
|
||||
tile_map_changed_needs_update = false;
|
||||
}
|
||||
|
||||
void TileMapEditorPlugin::_select_layer(const StringName &p_name) {
|
||||
TileMapLayer *edited_layer = Object::cast_to<TileMapLayer>(ObjectDB::get_instance(tile_map_layer_id));
|
||||
ERR_FAIL_NULL(edited_layer);
|
||||
|
||||
Node *parent = edited_layer->get_parent();
|
||||
ERR_FAIL_NULL(parent);
|
||||
|
||||
TileMapLayer *new_layer = Object::cast_to<TileMapLayer>(parent->get_node_or_null(String(p_name)));
|
||||
edit(new_layer);
|
||||
}
|
||||
|
||||
void TileMapEditorPlugin::_edit_tile_map_layer(TileMapLayer *p_tile_map_layer) {
|
||||
ERR_FAIL_NULL(p_tile_map_layer);
|
||||
|
||||
editor->edit(p_tile_map_layer);
|
||||
|
||||
// Update the selected layers in the TileMapLayerGroup parent node.
|
||||
TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(p_tile_map_layer->get_parent());
|
||||
if (tile_map_layer_group) {
|
||||
Vector<StringName> selected;
|
||||
selected.push_back(p_tile_map_layer->get_name());
|
||||
tile_map_layer_group->set_selected_layers(selected);
|
||||
}
|
||||
|
||||
// Update the object IDs.
|
||||
tile_map_layer_id = p_tile_map_layer->get_instance_id();
|
||||
p_tile_map_layer->connect("changed", callable_mp(this, &TileMapEditorPlugin::_tile_map_layer_changed));
|
||||
p_tile_map_layer->connect("tree_exited", callable_mp(this, &TileMapEditorPlugin::_tile_map_layer_removed));
|
||||
if (tile_map_layer_group) {
|
||||
tile_map_group_id = tile_map_layer_group->get_instance_id();
|
||||
tile_map_layer_group->connect("child_entered_tree", callable_mp(editor, &TileMapLayerEditor::update_layers_selector).unbind(1));
|
||||
tile_map_layer_group->connect("child_exiting_tree", callable_mp(editor, &TileMapLayerEditor::update_layers_selector).unbind(1));
|
||||
tile_map_layer_group->connect("child_order_changed", callable_mp(editor, &TileMapLayerEditor::update_layers_selector));
|
||||
}
|
||||
|
||||
// Update the edited tileset.
|
||||
Ref<TileSet> tile_set = p_tile_map_layer->get_effective_tile_set();
|
||||
if (tile_set.is_valid()) {
|
||||
tile_set_plugin_singleton->edit(tile_set.ptr());
|
||||
tile_set_plugin_singleton->make_visible(true);
|
||||
tile_set_id = tile_set->get_instance_id();
|
||||
} else {
|
||||
tile_set_plugin_singleton->edit(nullptr);
|
||||
tile_set_plugin_singleton->make_visible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void TileMapEditorPlugin::_edit_tile_map_layer_group(TileMapLayerGroup *p_tile_map_layer_group) {
|
||||
ERR_FAIL_NULL(p_tile_map_layer_group);
|
||||
|
||||
Vector<StringName> selected_layers = p_tile_map_layer_group->get_selected_layers();
|
||||
|
||||
TileMapLayer *selected_layer = nullptr;
|
||||
if (selected_layers.size() > 0) {
|
||||
// Edit the selected layer.
|
||||
selected_layer = Object::cast_to<TileMapLayer>(p_tile_map_layer_group->get_node_or_null(String(selected_layers[0])));
|
||||
}
|
||||
if (!selected_layer) {
|
||||
// Edit the first layer found.
|
||||
for (int i = 0; i < p_tile_map_layer_group->get_child_count(); i++) {
|
||||
selected_layer = Object::cast_to<TileMapLayer>(p_tile_map_layer_group->get_child(i));
|
||||
if (selected_layer) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selected_layer) {
|
||||
_edit_tile_map_layer(selected_layer);
|
||||
} else {
|
||||
editor->edit(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void TileMapEditorPlugin::_notification(int p_notification) {
|
||||
if (p_notification == NOTIFICATION_EXIT_TREE) {
|
||||
get_tree()->queue_delete(TilesEditorUtils::get_singleton());
|
||||
|
@ -356,39 +438,42 @@ void TileMapEditorPlugin::_notification(int p_notification) {
|
|||
}
|
||||
|
||||
void TileMapEditorPlugin::edit(Object *p_object) {
|
||||
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
|
||||
if (tile_map) {
|
||||
tile_map->disconnect("changed", callable_mp(this, &TileMapEditorPlugin::_tile_map_changed));
|
||||
TileMapLayer *edited_layer = Object::cast_to<TileMapLayer>(ObjectDB::get_instance(tile_map_layer_id));
|
||||
if (edited_layer) {
|
||||
edited_layer->disconnect("changed", callable_mp(this, &TileMapEditorPlugin::_tile_map_layer_changed));
|
||||
edited_layer->disconnect("tree_exited", callable_mp(this, &TileMapEditorPlugin::_tile_map_layer_removed));
|
||||
}
|
||||
|
||||
tile_map = Object::cast_to<TileMap>(p_object);
|
||||
if (tile_map) {
|
||||
tile_map_id = tile_map->get_instance_id();
|
||||
TileMapLayerGroup *tile_map_group = Object::cast_to<TileMapLayerGroup>(ObjectDB::get_instance(tile_map_group_id));
|
||||
if (tile_map_group) {
|
||||
tile_map_group->disconnect("child_entered_tree", callable_mp(editor, &TileMapLayerEditor::update_layers_selector).unbind(1));
|
||||
tile_map_group->disconnect("child_exiting_tree", callable_mp(editor, &TileMapLayerEditor::update_layers_selector).unbind(1));
|
||||
tile_map_group->disconnect("child_order_changed", callable_mp(editor, &TileMapLayerEditor::update_layers_selector));
|
||||
}
|
||||
|
||||
tile_map_group_id = ObjectID();
|
||||
tile_map_layer_id = ObjectID();
|
||||
tile_set_id = ObjectID();
|
||||
|
||||
TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMap>(p_object);
|
||||
TileMapLayer *tile_map_layer = Object::cast_to<TileMapLayer>(p_object);
|
||||
if (tile_map_layer_group) {
|
||||
_edit_tile_map_layer_group(tile_map_layer_group);
|
||||
} else if (tile_map_layer) {
|
||||
_edit_tile_map_layer(tile_map_layer);
|
||||
} else {
|
||||
tile_map_id = ObjectID();
|
||||
// Deselect the layer in the group.
|
||||
if (edited_layer) {
|
||||
tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(edited_layer->get_parent());
|
||||
if (tile_map_layer_group) {
|
||||
tile_map_layer_group->set_selected_layers(Vector<StringName>());
|
||||
}
|
||||
|
||||
editor->edit(tile_map);
|
||||
if (tile_map) {
|
||||
tile_map->connect("changed", callable_mp(this, &TileMapEditorPlugin::_tile_map_changed));
|
||||
|
||||
if (tile_map->get_tileset().is_valid()) {
|
||||
tile_set_plugin_singleton->edit(tile_map->get_tileset().ptr());
|
||||
tile_set_plugin_singleton->make_visible(true);
|
||||
edited_tileset = tile_map->get_tileset()->get_instance_id();
|
||||
}
|
||||
} else if (edited_tileset.is_valid()) {
|
||||
// Hide the TileSet editor, unless another TileSet is being edited.
|
||||
if (tile_set_plugin_singleton->get_edited_tileset() == edited_tileset) {
|
||||
tile_set_plugin_singleton->edit(nullptr);
|
||||
tile_set_plugin_singleton->make_visible(false);
|
||||
}
|
||||
edited_tileset = ObjectID();
|
||||
}
|
||||
}
|
||||
|
||||
bool TileMapEditorPlugin::handles(Object *p_object) const {
|
||||
return Object::cast_to<TileMap>(p_object) != nullptr;
|
||||
return Object::cast_to<TileMapLayer>(p_object) != nullptr || Object::cast_to<TileMapLayerGroup>(p_object) != nullptr;
|
||||
}
|
||||
|
||||
void TileMapEditorPlugin::make_visible(bool p_visible) {
|
||||
|
@ -427,10 +512,11 @@ TileMapEditorPlugin::TileMapEditorPlugin() {
|
|||
}
|
||||
tile_map_plugin_singleton = this;
|
||||
|
||||
editor = memnew(TileMapEditor);
|
||||
editor = memnew(TileMapLayerEditor);
|
||||
editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE);
|
||||
editor->connect("change_selected_layer_request", callable_mp(this, &TileMapEditorPlugin::_select_layer));
|
||||
editor->hide();
|
||||
|
||||
button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("TileMap"), editor);
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include "scene/gui/box_container.h"
|
||||
|
||||
#include "tile_atlas_view.h"
|
||||
#include "tile_map_editor.h"
|
||||
#include "tile_map_layer_editor.h"
|
||||
#include "tile_set_editor.h"
|
||||
|
||||
class TilesEditorUtils : public Object {
|
||||
|
@ -113,15 +113,21 @@ public:
|
|||
class TileMapEditorPlugin : public EditorPlugin {
|
||||
GDCLASS(TileMapEditorPlugin, EditorPlugin);
|
||||
|
||||
TileMapEditor *editor = nullptr;
|
||||
TileMapLayerEditor *editor = nullptr;
|
||||
Button *button = nullptr;
|
||||
ObjectID tile_map_id;
|
||||
ObjectID tile_map_layer_id;
|
||||
ObjectID tile_map_group_id; // Allow keeping the layer selector up to date.
|
||||
|
||||
bool tile_map_changed_needs_update = false;
|
||||
ObjectID edited_tileset; // The TileSet associated with the TileMap.
|
||||
ObjectID tile_set_id; // The TileSet associated with the TileMap.
|
||||
|
||||
void _tile_map_changed();
|
||||
void _tile_map_layer_changed();
|
||||
void _tile_map_layer_removed();
|
||||
void _update_tile_map();
|
||||
void _select_layer(const StringName &p_name);
|
||||
|
||||
void _edit_tile_map_layer(TileMapLayer *p_tile_map_layer);
|
||||
void _edit_tile_map_layer_group(TileMapLayerGroup *p_tile_map_layer_group);
|
||||
|
||||
protected:
|
||||
void _notification(int p_notification);
|
||||
|
|
|
@ -104,3 +104,12 @@ Validate extension JSON: Error: Field 'classes/GLTFBufferView/methods/get_byte_s
|
|||
Validate extension JSON: Error: Field 'classes/GLTFBufferView/methods/get_indices': is_const changed value in new API, from false to true.
|
||||
|
||||
Change AudioStreamPlayer* is_autoplay_enabled and GLTFBufferView getters to be const.
|
||||
|
||||
|
||||
GH-87379
|
||||
--------
|
||||
Validate extension JSON: API was removed: classes/TileMap/methods/get_tileset
|
||||
Validate extension JSON: API was removed: classes/TileMap/methods/set_tileset
|
||||
Validate extension JSON: API was removed: classes/TileMap/properties/tile_set
|
||||
|
||||
Moved to the parent TileMapLayerGroup class. No change should be necessary.
|
||||
|
|
|
@ -49,131 +49,8 @@
|
|||
ERR_FAIL_INDEX_V(layer, (int)layers.size(), err_value); \
|
||||
return layers[layer]->function(__VA_ARGS__);
|
||||
|
||||
Vector2i TileMap::transform_coords_layout(const 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
|
||||
SWAP(output.x, output.y);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void TileMap::set_selected_layer(int p_layer_id) {
|
||||
ERR_FAIL_COND(p_layer_id < -1 || p_layer_id >= (int)layers.size());
|
||||
if (selected_layer == p_layer_id) {
|
||||
return;
|
||||
}
|
||||
selected_layer = p_layer_id;
|
||||
void TileMap::_emit_changed() {
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
|
||||
// Update the layers modulation.
|
||||
for (TileMapLayer *layer : layers) {
|
||||
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_SELECTED_LAYER);
|
||||
}
|
||||
}
|
||||
|
||||
int TileMap::get_selected_layer() const {
|
||||
return selected_layer;
|
||||
}
|
||||
|
||||
void TileMap::_notification(int p_what) {
|
||||
|
@ -188,7 +65,6 @@ void TileMap::_notification(int p_what) {
|
|||
if (is_inside_tree() && collision_animatable && !in_editor) {
|
||||
// Update transform on the physics tick when in animatable mode.
|
||||
last_valid_transform = new_transform;
|
||||
print_line("Physics: ", new_transform);
|
||||
set_notify_local_transform(false);
|
||||
set_global_transform(new_transform);
|
||||
set_notify_local_transform(true);
|
||||
|
@ -207,7 +83,6 @@ void TileMap::_notification(int p_what) {
|
|||
// Store last valid transform.
|
||||
new_transform = get_global_transform();
|
||||
|
||||
print_line("local XFORM: ", last_valid_transform);
|
||||
// ... but then revert changes.
|
||||
set_notify_local_transform(false);
|
||||
set_global_transform(last_valid_transform);
|
||||
|
@ -225,55 +100,6 @@ void TileMap::force_update(int p_layer) {
|
|||
}
|
||||
#endif
|
||||
|
||||
void TileMap::queue_internal_update() {
|
||||
if (pending_update) {
|
||||
return;
|
||||
}
|
||||
pending_update = true;
|
||||
callable_mp(this, &TileMap::_internal_update).call_deferred();
|
||||
}
|
||||
|
||||
void TileMap::_internal_update() {
|
||||
// Other updates.
|
||||
if (!pending_update) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update dirty quadrants on layers.
|
||||
for (TileMapLayer *layer : layers) {
|
||||
layer->internal_update();
|
||||
}
|
||||
|
||||
pending_update = false;
|
||||
}
|
||||
|
||||
void TileMap::set_tileset(const Ref<TileSet> &p_tileset) {
|
||||
if (p_tileset == tile_set) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the tileset, registering to its changes.
|
||||
if (tile_set.is_valid()) {
|
||||
tile_set->disconnect_changed(callable_mp(this, &TileMap::_tile_set_changed));
|
||||
}
|
||||
|
||||
tile_set = p_tileset;
|
||||
|
||||
if (tile_set.is_valid()) {
|
||||
tile_set->connect_changed(callable_mp(this, &TileMap::_tile_set_changed));
|
||||
}
|
||||
|
||||
for (TileMapLayer *layer : layers) {
|
||||
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_TILE_SET);
|
||||
}
|
||||
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
}
|
||||
|
||||
Ref<TileSet> TileMap::get_tileset() const {
|
||||
return tile_set;
|
||||
}
|
||||
|
||||
void TileMap::set_rendering_quadrant_size(int p_size) {
|
||||
ERR_FAIL_COND_MSG(p_size < 1, "TileMapQuadrant size cannot be smaller than 1.");
|
||||
|
||||
|
@ -281,7 +107,7 @@ void TileMap::set_rendering_quadrant_size(int p_size) {
|
|||
for (TileMapLayer *layer : layers) {
|
||||
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE);
|
||||
}
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_emit_changed();
|
||||
}
|
||||
|
||||
int TileMap::get_rendering_quadrant_size() const {
|
||||
|
@ -392,10 +218,11 @@ void TileMap::add_layer(int p_to_pos) {
|
|||
for (uint32_t i = 0; i < layers.size(); i++) {
|
||||
layers[i]->set_layer_index_in_tile_map_node(i);
|
||||
}
|
||||
queue_internal_update();
|
||||
new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
|
||||
|
||||
notify_property_list_changed();
|
||||
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_emit_changed();
|
||||
|
||||
update_configuration_warnings();
|
||||
}
|
||||
|
@ -412,14 +239,9 @@ void TileMap::move_layer(int p_layer, int p_to_pos) {
|
|||
move_child(layer, i);
|
||||
layers[i]->set_layer_index_in_tile_map_node(i);
|
||||
}
|
||||
queue_internal_update();
|
||||
notify_property_list_changed();
|
||||
|
||||
if (selected_layer == p_layer) {
|
||||
selected_layer = p_to_pos < p_layer ? p_to_pos - 1 : p_to_pos;
|
||||
}
|
||||
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_emit_changed();
|
||||
|
||||
update_configuration_warnings();
|
||||
}
|
||||
|
@ -433,14 +255,9 @@ void TileMap::remove_layer(int p_layer) {
|
|||
for (uint32_t i = 0; i < layers.size(); i++) {
|
||||
layers[i]->set_layer_index_in_tile_map_node(i);
|
||||
}
|
||||
queue_internal_update();
|
||||
notify_property_list_changed();
|
||||
|
||||
if (selected_layer >= p_layer) {
|
||||
selected_layer -= 1;
|
||||
}
|
||||
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_emit_changed();
|
||||
|
||||
update_configuration_warnings();
|
||||
}
|
||||
|
@ -533,7 +350,7 @@ void TileMap::set_collision_visibility_mode(TileMap::VisibilityMode p_show_colli
|
|||
for (TileMapLayer *layer : layers) {
|
||||
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_COLLISION_VISIBILITY_MODE);
|
||||
}
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_emit_changed();
|
||||
}
|
||||
|
||||
TileMap::VisibilityMode TileMap::get_collision_visibility_mode() const {
|
||||
|
@ -548,7 +365,7 @@ void TileMap::set_navigation_visibility_mode(TileMap::VisibilityMode p_show_navi
|
|||
for (TileMapLayer *layer : layers) {
|
||||
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_NAVIGATION_VISIBILITY_MODE);
|
||||
}
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_emit_changed();
|
||||
}
|
||||
|
||||
TileMap::VisibilityMode TileMap::get_navigation_visibility_mode() const {
|
||||
|
@ -563,7 +380,7 @@ void TileMap::set_y_sort_enabled(bool p_enable) {
|
|||
for (TileMapLayer *layer : layers) {
|
||||
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED);
|
||||
}
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_emit_changed();
|
||||
update_configuration_warnings();
|
||||
}
|
||||
|
||||
|
@ -671,8 +488,9 @@ void TileMap::clear() {
|
|||
}
|
||||
|
||||
void TileMap::update_internals() {
|
||||
pending_update = true;
|
||||
_internal_update();
|
||||
for (TileMapLayer *layer : layers) {
|
||||
layer->update_internals();
|
||||
}
|
||||
}
|
||||
|
||||
void TileMap::notify_runtime_tile_data_update(int p_layer) {
|
||||
|
@ -721,10 +539,11 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
|
|||
add_child(new_layer);
|
||||
new_layer->set_name("Layer0");
|
||||
new_layer->set_layer_index_in_tile_map_node(0);
|
||||
new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
|
||||
layers.push_back(new_layer);
|
||||
}
|
||||
layers[0]->set_tile_data(format, p_value);
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_emit_changed();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -745,11 +564,12 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
|
|||
add_child(new_layer);
|
||||
new_layer->set_name(vformat("Layer%d", index));
|
||||
new_layer->set_layer_index_in_tile_map_node(index);
|
||||
new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
|
||||
layers.push_back(new_layer);
|
||||
}
|
||||
|
||||
notify_property_list_changed();
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_emit_changed();
|
||||
update_configuration_warnings();
|
||||
}
|
||||
|
||||
|
@ -776,7 +596,7 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
|
|||
return true;
|
||||
} else if (components[1] == "tile_data") {
|
||||
layers[index]->set_tile_data(format, p_value);
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_emit_changed();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -1014,93 +834,12 @@ void TileMap::set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) {
|
|||
}
|
||||
}
|
||||
|
||||
TypedArray<Vector2i> TileMap::get_surrounding_cells(const Vector2i &coords) {
|
||||
TypedArray<Vector2i> TileMap::get_surrounding_cells(const Vector2i &p_coords) {
|
||||
if (!tile_set.is_valid()) {
|
||||
return TypedArray<Vector2i>();
|
||||
}
|
||||
|
||||
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 around;
|
||||
}
|
||||
|
||||
void TileMap::draw_cells_outline(Control *p_control, const RBSet<Vector2i> &p_cells, Color p_color, Transform2D p_transform) {
|
||||
if (!tile_set.is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a set.
|
||||
Vector2i tile_size = tile_set->get_tile_size();
|
||||
Vector<Vector2> polygon = tile_set->get_tile_shape_polygon();
|
||||
TileSet::TileShape shape = tile_set->get_tile_shape();
|
||||
|
||||
for (const Vector2i &E : p_cells) {
|
||||
Vector2 center = map_to_local(E);
|
||||
|
||||
#define DRAW_SIDE_IF_NEEDED(side, polygon_index_from, polygon_index_to) \
|
||||
if (!p_cells.has(get_neighbor_cell(E, side))) { \
|
||||
Vector2 from = p_transform.xform(center + polygon[polygon_index_from] * tile_size); \
|
||||
Vector2 to = p_transform.xform(center + polygon[polygon_index_to] * tile_size); \
|
||||
p_control->draw_line(from, to, p_color); \
|
||||
}
|
||||
|
||||
if (shape == TileSet::TILE_SHAPE_SQUARE) {
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, 1, 2);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 2, 3);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 3, 0);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 0, 1);
|
||||
} else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 2, 3);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 1, 2);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 3, 0);
|
||||
} else {
|
||||
if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 2, 3);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 1, 2);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 5, 0);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, 4, 5);
|
||||
} else {
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 4, 5);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 5, 0);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 1, 2);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 2, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef DRAW_SIDE_IF_NEEDED
|
||||
return tile_set->get_surrounding_cells(p_coords);
|
||||
}
|
||||
|
||||
Array TileMap::get_configuration_warnings() const {
|
||||
|
@ -1171,9 +910,6 @@ void TileMap::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("force_update", "layer"), &TileMap::force_update, DEFVAL(-1));
|
||||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
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_rendering_quadrant_size", "size"), &TileMap::set_rendering_quadrant_size);
|
||||
ClassDB::bind_method(D_METHOD("get_rendering_quadrant_size"), &TileMap::get_rendering_quadrant_size);
|
||||
|
||||
|
@ -1244,7 +980,6 @@ void TileMap::_bind_methods() {
|
|||
GDVIRTUAL_BIND(_use_tile_data_runtime_update, "layer", "coords");
|
||||
GDVIRTUAL_BIND(_tile_data_runtime_update, "layer", "coords", "tile_data");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tile_set", PROPERTY_HINT_RESOURCE_TYPE, "TileSet"), "set_tileset", "get_tileset");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "rendering_quadrant_size", PROPERTY_HINT_RANGE, "1,128,1"), "set_rendering_quadrant_size", "get_rendering_quadrant_size");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_animatable"), "set_collision_animatable", "is_collision_animatable");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_visibility_mode", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_collision_visibility_mode", "get_collision_visibility_mode");
|
||||
|
@ -1261,28 +996,18 @@ void TileMap::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(VISIBILITY_MODE_FORCE_SHOW);
|
||||
}
|
||||
|
||||
void TileMap::_tile_set_changed() {
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
for (TileMapLayer *layer : layers) {
|
||||
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_TILE_SET);
|
||||
}
|
||||
update_configuration_warnings();
|
||||
}
|
||||
|
||||
TileMap::TileMap() {
|
||||
TileMapLayer *new_layer = memnew(TileMapLayer);
|
||||
add_child(new_layer);
|
||||
new_layer->set_name("Layer0");
|
||||
new_layer->set_layer_index_in_tile_map_node(0);
|
||||
new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
|
||||
layers.push_back(new_layer);
|
||||
|
||||
default_layer = memnew(TileMapLayer);
|
||||
}
|
||||
|
||||
TileMap::~TileMap() {
|
||||
if (tile_set.is_valid()) {
|
||||
tile_set->disconnect_changed(callable_mp(this, &TileMap::_tile_set_changed));
|
||||
}
|
||||
memdelete(default_layer);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#ifndef TILE_MAP_H
|
||||
#define TILE_MAP_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/2d/tile_map_layer_group.h"
|
||||
#include "scene/resources/tile_set.h"
|
||||
|
||||
class Control;
|
||||
|
@ -45,8 +45,8 @@ enum TileMapDataFormat {
|
|||
FORMAT_MAX,
|
||||
};
|
||||
|
||||
class TileMap : public Node2D {
|
||||
GDCLASS(TileMap, Node2D);
|
||||
class TileMap : public TileMapLayerGroup {
|
||||
GDCLASS(TileMap, TileMapLayerGroup);
|
||||
|
||||
public:
|
||||
enum VisibilityMode {
|
||||
|
@ -64,7 +64,6 @@ private:
|
|||
static constexpr float FP_ADJUST = 0.00001;
|
||||
|
||||
// Properties.
|
||||
Ref<TileSet> tile_set;
|
||||
int rendering_quadrant_size = 16;
|
||||
bool collision_animatable = false;
|
||||
VisibilityMode collision_visibility_mode = VISIBILITY_MODE_DEFAULT;
|
||||
|
@ -73,14 +72,12 @@ private:
|
|||
// Layers.
|
||||
LocalVector<TileMapLayer *> layers;
|
||||
TileMapLayer *default_layer; // Dummy layer to fetch default values.
|
||||
int selected_layer = -1;
|
||||
bool pending_update = false;
|
||||
|
||||
// Transforms for collision_animatable.
|
||||
Transform2D last_valid_transform;
|
||||
Transform2D new_transform;
|
||||
|
||||
void _tile_set_changed();
|
||||
void _emit_changed();
|
||||
|
||||
protected:
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
|
@ -103,8 +100,6 @@ protected:
|
|||
#endif
|
||||
|
||||
public:
|
||||
static Vector2i transform_coords_layout(const Vector2i &p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout);
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
virtual Rect2 _edit_get_rect() const override;
|
||||
#endif
|
||||
|
@ -113,13 +108,6 @@ public:
|
|||
void force_update(int p_layer);
|
||||
#endif
|
||||
|
||||
// Called by TileMapLayers.
|
||||
void queue_internal_update();
|
||||
void _internal_update();
|
||||
|
||||
void set_tileset(const Ref<TileSet> &p_tileset);
|
||||
Ref<TileSet> get_tileset() const;
|
||||
|
||||
void set_rendering_quadrant_size(int p_size);
|
||||
int get_rendering_quadrant_size() const;
|
||||
|
||||
|
@ -148,9 +136,6 @@ public:
|
|||
void set_layer_navigation_map(int p_layer, RID p_map);
|
||||
RID get_layer_navigation_map(int p_layer) const;
|
||||
|
||||
void set_selected_layer(int p_layer_id); // For editor use.
|
||||
int get_selected_layer() const;
|
||||
|
||||
void set_collision_animatable(bool p_collision_animatable);
|
||||
bool is_collision_animatable() const;
|
||||
|
||||
|
@ -224,8 +209,7 @@ public:
|
|||
void notify_runtime_tile_data_update(int p_layer = -1);
|
||||
|
||||
// Helpers?
|
||||
TypedArray<Vector2i> get_surrounding_cells(const Vector2i &coords);
|
||||
void draw_cells_outline(Control *p_control, const RBSet<Vector2i> &p_cells, Color p_color, Transform2D p_transform = Transform2D());
|
||||
TypedArray<Vector2i> get_surrounding_cells(const Vector2i &p_coords);
|
||||
|
||||
// Virtual function to modify the TileData at runtime.
|
||||
GDVIRTUAL2R(bool, _use_tile_data_runtime_update, int, Vector2i);
|
||||
|
|
|
@ -44,14 +44,6 @@ TileMap *TileMapLayer::_fetch_tilemap() const {
|
|||
return TileMap::cast_to<TileMap>(get_parent());
|
||||
}
|
||||
|
||||
Ref<TileSet> TileMapLayer::_fetch_tileset() const {
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
if (!tile_map_node) {
|
||||
return Ref<TileSet>();
|
||||
}
|
||||
return tile_map_node->get_tileset();
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
/////////////////////////////// Debug //////////////////////////////////////////
|
||||
constexpr int TILE_MAP_DEBUG_QUADRANT_SIZE = 16;
|
||||
|
@ -63,7 +55,7 @@ Vector2i TileMapLayer::_coords_to_debug_quadrant_coords(const Vector2i &p_coords
|
|||
}
|
||||
|
||||
void TileMapLayer::_debug_update() {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
RenderingServer *rs = RenderingServer::get_singleton();
|
||||
|
||||
// Check if we should cleanup everything.
|
||||
|
@ -192,7 +184,7 @@ void TileMapLayer::_debug_quadrants_update_cell(CellData &r_cell_data, SelfList<
|
|||
/////////////////////////////// Rendering //////////////////////////////////////
|
||||
void TileMapLayer::_rendering_update() {
|
||||
const TileMap *tile_map_node = _fetch_tilemap();
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
RenderingServer *rs = RenderingServer::get_singleton();
|
||||
|
||||
// Check if we should cleanup everything.
|
||||
|
@ -206,17 +198,22 @@ void TileMapLayer::_rendering_update() {
|
|||
|
||||
// Modulate the layer.
|
||||
Color layer_modulate = get_modulate();
|
||||
int selected_layer = tile_map_node->get_selected_layer();
|
||||
if (selected_layer >= 0 && layer_index_in_tile_map_node != selected_layer) {
|
||||
int z_selected = tile_map_node->get_layer_z_index(selected_layer);
|
||||
#ifdef TOOLS_ENABLED
|
||||
const Vector<StringName> selected_layers = tile_map_node->get_selected_layers();
|
||||
if (tile_map_node->is_highlighting_selected_layer() && selected_layers.size() == 1 && get_name() != selected_layers[0]) {
|
||||
TileMapLayer *selected_layer = Object::cast_to<TileMapLayer>(tile_map_node->get_node_or_null(String(selected_layers[0])));
|
||||
if (selected_layer) {
|
||||
int z_selected = selected_layer->get_z_index();
|
||||
int layer_z_index = get_z_index();
|
||||
if (layer_z_index < z_selected || (layer_z_index == z_selected && layer_index_in_tile_map_node < selected_layer)) {
|
||||
if (layer_z_index < z_selected || (layer_z_index == z_selected && get_index() < selected_layer->get_index())) {
|
||||
layer_modulate = layer_modulate.darkened(0.5);
|
||||
} else if (layer_z_index > z_selected || (layer_z_index == z_selected && layer_index_in_tile_map_node > selected_layer)) {
|
||||
} else if (layer_z_index > z_selected || (layer_z_index == z_selected && get_index() > selected_layer->get_index())) {
|
||||
layer_modulate = layer_modulate.darkened(0.5);
|
||||
layer_modulate.a *= 0.3;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // TOOLS_ENABLED
|
||||
rs->canvas_item_set_modulate(get_canvas_item(), layer_modulate);
|
||||
}
|
||||
|
||||
|
@ -228,7 +225,7 @@ void TileMapLayer::_rendering_update() {
|
|||
// Check if anything changed that might change the quadrant shape.
|
||||
// If so, recreate everything.
|
||||
bool quandrant_shape_changed = dirty.flags[DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE] ||
|
||||
(is_y_sort_enabled() && (dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] || dirty.flags[DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_LOCAL_TRANSFORM] || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]));
|
||||
(is_y_sort_enabled() && (dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] || dirty.flags[DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_LOCAL_TRANSFORM] || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET]));
|
||||
|
||||
// Free all quadrants.
|
||||
if (forced_cleanup || quandrant_shape_changed) {
|
||||
|
@ -247,7 +244,7 @@ void TileMapLayer::_rendering_update() {
|
|||
|
||||
if (!forced_cleanup) {
|
||||
// List all quadrants to update, recreating them if needed.
|
||||
if (dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] || _rendering_was_cleaned_up) {
|
||||
if (dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] || _rendering_was_cleaned_up) {
|
||||
// Update all cells.
|
||||
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
|
||||
CellData &cell_data = kv.value;
|
||||
|
@ -427,7 +424,7 @@ void TileMapLayer::_rendering_update() {
|
|||
_rendering_occluders_clear_cell(kv.value);
|
||||
}
|
||||
} else {
|
||||
if (_rendering_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]) {
|
||||
if (_rendering_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET]) {
|
||||
// Update all cells.
|
||||
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
|
||||
_rendering_occluders_update_cell(kv.value);
|
||||
|
@ -448,7 +445,7 @@ void TileMapLayer::_rendering_update() {
|
|||
|
||||
void TileMapLayer::_rendering_notification(int p_what) {
|
||||
RenderingServer *rs = RenderingServer::get_singleton();
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
if (p_what == NOTIFICATION_TRANSFORM_CHANGED || p_what == NOTIFICATION_ENTER_CANVAS || p_what == NOTIFICATION_VISIBILITY_CHANGED) {
|
||||
if (tile_set.is_valid()) {
|
||||
Transform2D tilemap_xform = get_global_transform();
|
||||
|
@ -469,7 +466,7 @@ void TileMapLayer::_rendering_notification(int p_what) {
|
|||
|
||||
void TileMapLayer::_rendering_quadrants_update_cell(CellData &r_cell_data, SelfList<RenderingQuadrant>::List &r_dirty_rendering_quadrant_list) {
|
||||
const TileMap *tile_map_node = _fetch_tilemap();
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
|
||||
// Check if the cell is valid and retrieve its y_sort_origin.
|
||||
bool is_valid = false;
|
||||
|
@ -569,7 +566,7 @@ void TileMapLayer::_rendering_occluders_clear_cell(CellData &r_cell_data) {
|
|||
}
|
||||
|
||||
void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
RenderingServer *rs = RenderingServer::get_singleton();
|
||||
|
||||
// Free unused occluders then resize the occluders array.
|
||||
|
@ -638,7 +635,7 @@ void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
|
|||
|
||||
#ifdef DEBUG_ENABLED
|
||||
void TileMapLayer::_rendering_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
ERR_FAIL_COND(!tile_set.is_valid());
|
||||
|
||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||
|
@ -687,7 +684,7 @@ void TileMapLayer::_rendering_draw_cell_debug(const RID &p_canvas_item, const Ve
|
|||
/////////////////////////////// Physics //////////////////////////////////////
|
||||
|
||||
void TileMapLayer::_physics_update() {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
|
||||
// Check if we should cleanup everything.
|
||||
bool forced_cleanup = in_destructor || !enabled || !is_inside_tree() || !tile_set.is_valid();
|
||||
|
@ -697,7 +694,7 @@ void TileMapLayer::_physics_update() {
|
|||
_physics_clear_cell(kv.value);
|
||||
}
|
||||
} else {
|
||||
if (_physics_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
|
||||
if (_physics_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
|
||||
// Update all cells.
|
||||
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
|
||||
_physics_update_cell(kv.value);
|
||||
|
@ -717,7 +714,7 @@ void TileMapLayer::_physics_update() {
|
|||
}
|
||||
|
||||
void TileMapLayer::_physics_notification(int p_what) {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
Transform2D gl_transform = get_global_transform();
|
||||
PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
|
||||
|
||||
|
@ -771,7 +768,7 @@ void TileMapLayer::_physics_clear_cell(CellData &r_cell_data) {
|
|||
|
||||
void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
|
||||
const TileMap *tile_map_node = _fetch_tilemap();
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
Transform2D gl_transform = get_global_transform();
|
||||
RID space = get_world_2d()->get_space();
|
||||
PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
|
||||
|
@ -889,7 +886,7 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
|
|||
void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) {
|
||||
// Draw the debug collision shapes.
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
ERR_FAIL_COND(!tile_set.is_valid());
|
||||
|
||||
if (!get_tree()) {
|
||||
|
@ -945,7 +942,7 @@ void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vect
|
|||
|
||||
void TileMapLayer::_navigation_update() {
|
||||
ERR_FAIL_NULL(NavigationServer2D::get_singleton());
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
NavigationServer2D *ns = NavigationServer2D::get_singleton();
|
||||
|
||||
// Check if we should cleanup everything.
|
||||
|
@ -982,7 +979,7 @@ void TileMapLayer::_navigation_update() {
|
|||
_navigation_clear_cell(kv.value);
|
||||
}
|
||||
} else {
|
||||
if (_navigation_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
|
||||
if (_navigation_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
|
||||
// Update all cells.
|
||||
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
|
||||
_navigation_update_cell(kv.value);
|
||||
|
@ -1002,7 +999,7 @@ void TileMapLayer::_navigation_update() {
|
|||
}
|
||||
|
||||
void TileMapLayer::_navigation_notification(int p_what) {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
|
||||
if (tile_set.is_valid()) {
|
||||
Transform2D tilemap_xform = get_global_transform();
|
||||
|
@ -1037,7 +1034,7 @@ void TileMapLayer::_navigation_clear_cell(CellData &r_cell_data) {
|
|||
|
||||
void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) {
|
||||
const TileMap *tile_map_node = _fetch_tilemap();
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
NavigationServer2D *ns = NavigationServer2D::get_singleton();
|
||||
Transform2D gl_xform = get_global_transform();
|
||||
|
||||
|
@ -1136,7 +1133,7 @@ void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const V
|
|||
return;
|
||||
}
|
||||
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
|
||||
RenderingServer *rs = RenderingServer::get_singleton();
|
||||
const NavigationServer2D *ns2d = NavigationServer2D::get_singleton();
|
||||
|
@ -1222,7 +1219,7 @@ void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const V
|
|||
/////////////////////////////// Scenes //////////////////////////////////////
|
||||
|
||||
void TileMapLayer::_scenes_update() {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
|
||||
// Check if we should cleanup everything.
|
||||
bool forced_cleanup = in_destructor || !enabled || !is_inside_tree() || !tile_set.is_valid();
|
||||
|
@ -1233,7 +1230,7 @@ void TileMapLayer::_scenes_update() {
|
|||
_scenes_clear_cell(kv.value);
|
||||
}
|
||||
} else {
|
||||
if (_scenes_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
|
||||
if (_scenes_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
|
||||
// Update all cells.
|
||||
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
|
||||
_scenes_update_cell(kv.value);
|
||||
|
@ -1268,7 +1265,7 @@ void TileMapLayer::_scenes_clear_cell(CellData &r_cell_data) {
|
|||
|
||||
void TileMapLayer::_scenes_update_cell(CellData &r_cell_data) {
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
|
||||
// Clear the scene in any case.
|
||||
_scenes_clear_cell(r_cell_data);
|
||||
|
@ -1305,7 +1302,7 @@ void TileMapLayer::_scenes_update_cell(CellData &r_cell_data) {
|
|||
|
||||
#ifdef DEBUG_ENABLED
|
||||
void TileMapLayer::_scenes_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
ERR_FAIL_COND(!tile_set.is_valid());
|
||||
|
||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||
|
@ -1356,13 +1353,13 @@ void TileMapLayer::_scenes_draw_cell_debug(const RID &p_canvas_item, const Vecto
|
|||
|
||||
void TileMapLayer::_build_runtime_update_tile_data() {
|
||||
const TileMap *tile_map_node = _fetch_tilemap();
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
|
||||
// Check if we should cleanup everything.
|
||||
bool forced_cleanup = in_destructor || !enabled || !tile_set.is_valid() || !is_visible_in_tree();
|
||||
if (!forced_cleanup) {
|
||||
if (tile_map_node->GDVIRTUAL_IS_OVERRIDDEN(_use_tile_data_runtime_update) && tile_map_node->GDVIRTUAL_IS_OVERRIDDEN(_tile_data_runtime_update)) {
|
||||
if (_runtime_update_tile_data_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]) {
|
||||
if (_runtime_update_tile_data_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET]) {
|
||||
for (KeyValue<Vector2i, CellData> &E : tile_map) {
|
||||
_build_runtime_update_tile_data_for_cell(E.value);
|
||||
}
|
||||
|
@ -1386,7 +1383,7 @@ void TileMapLayer::_build_runtime_update_tile_data() {
|
|||
|
||||
void TileMapLayer::_build_runtime_update_tile_data_for_cell(CellData &r_cell_data, bool p_auto_add_to_dirty_list) {
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
|
||||
TileMapCell &c = r_cell_data.cell;
|
||||
TileSetSource *source;
|
||||
|
@ -1428,8 +1425,8 @@ void TileMapLayer::_clear_runtime_update_tile_data() {
|
|||
}
|
||||
}
|
||||
|
||||
TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern) {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern) const {
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
if (!tile_set.is_valid()) {
|
||||
return TileSet::TerrainsPattern();
|
||||
}
|
||||
|
@ -1490,7 +1487,7 @@ TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints
|
|||
}
|
||||
|
||||
RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
if (!tile_set.is_valid()) {
|
||||
return RBSet<TerrainConstraint>();
|
||||
}
|
||||
|
@ -1511,7 +1508,7 @@ RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_added_patte
|
|||
}
|
||||
|
||||
RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_painted_cells_list(const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
if (!tile_set.is_valid()) {
|
||||
return RBSet<TerrainConstraint>();
|
||||
}
|
||||
|
@ -1599,8 +1596,7 @@ RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_painted_cel
|
|||
}
|
||||
|
||||
void TileMapLayer::_renamed() {
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
}
|
||||
|
||||
void TileMapLayer::_update_notify_local_transform() {
|
||||
|
@ -1614,6 +1610,66 @@ void TileMapLayer::_update_notify_local_transform() {
|
|||
set_notify_local_transform(notify);
|
||||
}
|
||||
|
||||
void TileMapLayer::_queue_internal_update() {
|
||||
if (pending_update) {
|
||||
return;
|
||||
}
|
||||
pending_update = true;
|
||||
callable_mp(this, &TileMapLayer::_deferred_internal_update).call_deferred();
|
||||
}
|
||||
|
||||
void TileMapLayer::_deferred_internal_update() {
|
||||
// Other updates.
|
||||
if (!pending_update) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update dirty quadrants on layers.
|
||||
_internal_update();
|
||||
|
||||
pending_update = false;
|
||||
}
|
||||
|
||||
void TileMapLayer::_internal_update() {
|
||||
// Find TileData that need a runtime modification.
|
||||
// This may add cells to the dirty list is a runtime modification has been notified.
|
||||
_build_runtime_update_tile_data();
|
||||
|
||||
// Update all subsystems.
|
||||
_rendering_update();
|
||||
_physics_update();
|
||||
_navigation_update();
|
||||
_scenes_update();
|
||||
#ifdef DEBUG_ENABLED
|
||||
_debug_update();
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
_clear_runtime_update_tile_data();
|
||||
|
||||
// Clear the "what is dirty" flags.
|
||||
for (int i = 0; i < DIRTY_FLAGS_MAX; i++) {
|
||||
dirty.flags[i] = false;
|
||||
}
|
||||
|
||||
// List the cells to delete definitely.
|
||||
Vector<Vector2i> to_delete;
|
||||
for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) {
|
||||
CellData &cell_data = *cell_data_list_element->self();
|
||||
// Select the the cell from tile_map if it is invalid.
|
||||
if (cell_data.cell.source_id == TileSet::INVALID_SOURCE) {
|
||||
to_delete.push_back(cell_data.coords);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove cells that are empty after the cleanup.
|
||||
for (const Vector2i &coords : to_delete) {
|
||||
tile_map.erase(coords);
|
||||
}
|
||||
|
||||
// Clear the dirty cells list.
|
||||
dirty.cell_list.clear();
|
||||
}
|
||||
|
||||
void TileMapLayer::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_POSTINITIALIZE: {
|
||||
|
@ -1623,32 +1679,27 @@ void TileMapLayer::_notification(int p_what) {
|
|||
case NOTIFICATION_ENTER_TREE: {
|
||||
_update_notify_local_transform();
|
||||
dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] = true;
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->queue_internal_update();
|
||||
_queue_internal_update();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] = true;
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->queue_internal_update();
|
||||
_queue_internal_update();
|
||||
} break;
|
||||
|
||||
case TileMap::NOTIFICATION_ENTER_CANVAS: {
|
||||
dirty.flags[DIRTY_FLAGS_LAYER_IN_CANVAS] = true;
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->queue_internal_update();
|
||||
_queue_internal_update();
|
||||
} break;
|
||||
|
||||
case TileMap::NOTIFICATION_EXIT_CANVAS: {
|
||||
dirty.flags[DIRTY_FLAGS_LAYER_IN_CANVAS] = true;
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->queue_internal_update();
|
||||
_queue_internal_update();
|
||||
} break;
|
||||
|
||||
case TileMap::NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
dirty.flags[DIRTY_FLAGS_LAYER_VISIBILITY] = true;
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->queue_internal_update();
|
||||
_queue_internal_update();
|
||||
} break;
|
||||
}
|
||||
|
||||
|
@ -1657,18 +1708,23 @@ void TileMapLayer::_notification(int p_what) {
|
|||
_navigation_notification(p_what);
|
||||
}
|
||||
|
||||
void TileMapLayer::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapLayer::set_cell, DEFVAL(TileSet::INVALID_SOURCE), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(0));
|
||||
|
||||
ADD_SIGNAL(MethodInfo(CoreStringNames::get_singleton()->changed));
|
||||
}
|
||||
|
||||
void TileMapLayer::set_layer_index_in_tile_map_node(int p_index) {
|
||||
if (p_index == layer_index_in_tile_map_node) {
|
||||
return;
|
||||
}
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
layer_index_in_tile_map_node = p_index;
|
||||
dirty.flags[DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE] = true;
|
||||
tile_map_node->queue_internal_update();
|
||||
_queue_internal_update();
|
||||
}
|
||||
|
||||
Rect2 TileMapLayer::get_rect(bool &r_changed) const {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
if (tile_set.is_null()) {
|
||||
r_changed = rect_cache != Rect2();
|
||||
return Rect2();
|
||||
|
@ -1702,8 +1758,8 @@ Rect2 TileMapLayer::get_rect(bool &r_changed) const {
|
|||
return rect_cache;
|
||||
}
|
||||
|
||||
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints) {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints) const {
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
if (!tile_set.is_valid()) {
|
||||
return HashMap<Vector2i, TileSet::TerrainsPattern>();
|
||||
}
|
||||
|
@ -1750,9 +1806,9 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_constrain
|
|||
return output;
|
||||
}
|
||||
|
||||
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
|
||||
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) const {
|
||||
HashMap<Vector2i, TileSet::TerrainsPattern> output;
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
ERR_FAIL_COND_V(!tile_set.is_valid(), output);
|
||||
ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
|
||||
|
||||
|
@ -1856,9 +1912,9 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(c
|
|||
return output;
|
||||
}
|
||||
|
||||
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
|
||||
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) const {
|
||||
HashMap<Vector2i, TileSet::TerrainsPattern> output;
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
ERR_FAIL_COND_V(!tile_set.is_valid(), output);
|
||||
ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
|
||||
|
||||
|
@ -1930,9 +1986,9 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(cons
|
|||
return output;
|
||||
}
|
||||
|
||||
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_pattern(const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains) {
|
||||
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_pattern(const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains) const {
|
||||
HashMap<Vector2i, TileSet::TerrainsPattern> output;
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
ERR_FAIL_COND_V(!tile_set.is_valid(), output);
|
||||
ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
|
||||
|
||||
|
@ -1988,7 +2044,7 @@ TileMapCell TileMapLayer::get_cell(const Vector2i &p_coords, bool p_use_proxies)
|
|||
return TileMapCell();
|
||||
} else {
|
||||
TileMapCell c = tile_map.find(p_coords)->value.cell;
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
if (p_use_proxies && tile_set.is_valid()) {
|
||||
Array proxyed = tile_set->map_tile_proxy(c.source_id, c.get_atlas_coords(), c.alternative_tile);
|
||||
c.source_id = proxyed[0];
|
||||
|
@ -2064,7 +2120,7 @@ void TileMapLayer::set_tile_data(TileMapDataFormat p_format, const Vector<int> &
|
|||
coord_y = decode_uint16(&local[10]);
|
||||
}
|
||||
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
if (tile_set.is_valid()) {
|
||||
Array a = tile_set->compatibility_tilemap_map(v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose);
|
||||
if (a.size() == 3) {
|
||||
|
@ -2105,49 +2161,19 @@ Vector<int> TileMapLayer::get_tile_data() const {
|
|||
}
|
||||
|
||||
void TileMapLayer::notify_tile_map_change(DirtyFlags p_what) {
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
if (p_what == DIRTY_FLAGS_LAYER_GROUP_SELECTED_LAYERS ||
|
||||
p_what == DIRTY_FLAGS_LAYER_GROUP_HIGHLIGHT_SELECTED ||
|
||||
p_what == DIRTY_FLAGS_LAYER_GROUP_TILE_SET) {
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
}
|
||||
|
||||
dirty.flags[p_what] = true;
|
||||
tile_map_node->queue_internal_update();
|
||||
_queue_internal_update();
|
||||
}
|
||||
|
||||
void TileMapLayer::internal_update() {
|
||||
// Find TileData that need a runtime modification.
|
||||
// This may add cells to the dirty list is a runtime modification has been notified.
|
||||
_build_runtime_update_tile_data();
|
||||
|
||||
// Update all subsystems.
|
||||
_rendering_update();
|
||||
_physics_update();
|
||||
_navigation_update();
|
||||
_scenes_update();
|
||||
#ifdef DEBUG_ENABLED
|
||||
_debug_update();
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
_clear_runtime_update_tile_data();
|
||||
|
||||
// Clear the "what is dirty" flags.
|
||||
for (int i = 0; i < DIRTY_FLAGS_MAX; i++) {
|
||||
dirty.flags[i] = false;
|
||||
}
|
||||
|
||||
// List the cells to delete definitely.
|
||||
Vector<Vector2i> to_delete;
|
||||
for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) {
|
||||
CellData &cell_data = *cell_data_list_element->self();
|
||||
// Select the the cell from tile_map if it is invalid.
|
||||
if (cell_data.cell.source_id == TileSet::INVALID_SOURCE) {
|
||||
to_delete.push_back(cell_data.coords);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove cells that are empty after the cleanup.
|
||||
for (const Vector2i &coords : to_delete) {
|
||||
tile_map.erase(coords);
|
||||
}
|
||||
|
||||
// Clear the dirty cells list.
|
||||
dirty.cell_list.clear();
|
||||
void TileMapLayer::update_internals() {
|
||||
pending_update = true;
|
||||
_deferred_internal_update();
|
||||
}
|
||||
|
||||
void TileMapLayer::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile) {
|
||||
|
@ -2190,10 +2216,7 @@ void TileMapLayer::set_cell(const Vector2i &p_coords, int p_source_id, const Vec
|
|||
if (!E->value.dirty_list_element.in_list()) {
|
||||
dirty.cell_list.add(&(E->value.dirty_list_element));
|
||||
}
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
if (tile_map_node) { // Needed to avoid crashes in destructor.
|
||||
tile_map_node->queue_internal_update();
|
||||
}
|
||||
_queue_internal_update();
|
||||
|
||||
used_rect_cache_dirty = true;
|
||||
}
|
||||
|
@ -2210,7 +2233,7 @@ int TileMapLayer::get_cell_source_id(const Vector2i &p_coords, bool p_use_proxie
|
|||
return TileSet::INVALID_SOURCE;
|
||||
}
|
||||
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
if (p_use_proxies && tile_set.is_valid()) {
|
||||
Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile);
|
||||
return proxyed[0];
|
||||
|
@ -2227,7 +2250,7 @@ Vector2i TileMapLayer::get_cell_atlas_coords(const Vector2i &p_coords, bool p_us
|
|||
return TileSetSource::INVALID_ATLAS_COORDS;
|
||||
}
|
||||
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
if (p_use_proxies && tile_set.is_valid()) {
|
||||
Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile);
|
||||
return proxyed[1];
|
||||
|
@ -2244,7 +2267,7 @@ int TileMapLayer::get_cell_alternative_tile(const Vector2i &p_coords, bool p_use
|
|||
return TileSetSource::INVALID_TILE_ALTERNATIVE;
|
||||
}
|
||||
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
if (p_use_proxies && tile_set.is_valid()) {
|
||||
Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile);
|
||||
return proxyed[2];
|
||||
|
@ -2259,7 +2282,7 @@ TileData *TileMapLayer::get_cell_tile_data(const Vector2i &p_coords, bool p_use_
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
Ref<TileSetAtlasSource> source = tile_set->get_source(source_id);
|
||||
if (source.is_valid()) {
|
||||
return source->get_tile_data(get_cell_atlas_coords(p_coords, p_use_proxies), get_cell_alternative_tile(p_coords, p_use_proxies));
|
||||
|
@ -2277,7 +2300,7 @@ void TileMapLayer::clear() {
|
|||
}
|
||||
|
||||
Ref<TileMapPattern> TileMapLayer::get_pattern(TypedArray<Vector2i> p_coords_array) {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
ERR_FAIL_COND_V(!tile_set.is_valid(), nullptr);
|
||||
|
||||
Ref<TileMapPattern> output;
|
||||
|
@ -2331,7 +2354,7 @@ Ref<TileMapPattern> TileMapLayer::get_pattern(TypedArray<Vector2i> p_coords_arra
|
|||
}
|
||||
|
||||
void TileMapLayer::set_pattern(const Vector2i &p_position, const Ref<TileMapPattern> p_pattern) {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
ERR_FAIL_COND(tile_set.is_null());
|
||||
ERR_FAIL_COND(p_pattern.is_null());
|
||||
|
||||
|
@ -2343,7 +2366,7 @@ void TileMapLayer::set_pattern(const Vector2i &p_position, const Ref<TileMapPatt
|
|||
}
|
||||
|
||||
void TileMapLayer::set_cells_terrain_connect(TypedArray<Vector2i> p_cells, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
ERR_FAIL_COND(!tile_set.is_valid());
|
||||
ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count());
|
||||
|
||||
|
@ -2383,7 +2406,7 @@ void TileMapLayer::set_cells_terrain_connect(TypedArray<Vector2i> p_cells, int p
|
|||
}
|
||||
|
||||
void TileMapLayer::set_cells_terrain_path(TypedArray<Vector2i> p_path, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
|
||||
const Ref<TileSet> &tile_set = _fetch_tileset();
|
||||
const Ref<TileSet> &tile_set = get_effective_tile_set();
|
||||
ERR_FAIL_COND(!tile_set.is_valid());
|
||||
ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count());
|
||||
|
||||
|
@ -2490,10 +2513,10 @@ void TileMapLayer::set_enabled(bool p_enabled) {
|
|||
}
|
||||
enabled = p_enabled;
|
||||
dirty.flags[DIRTY_FLAGS_LAYER_ENABLED] = true;
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->queue_internal_update();
|
||||
tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_queue_internal_update();
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->update_configuration_warnings();
|
||||
}
|
||||
|
||||
|
@ -2507,9 +2530,8 @@ void TileMapLayer::set_self_modulate(const Color &p_self_modulate) {
|
|||
}
|
||||
CanvasItem::set_self_modulate(p_self_modulate);
|
||||
dirty.flags[DIRTY_FLAGS_LAYER_SELF_MODULATE] = true;
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->queue_internal_update();
|
||||
tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_queue_internal_update();
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
}
|
||||
|
||||
void TileMapLayer::set_y_sort_enabled(bool p_y_sort_enabled) {
|
||||
|
@ -2518,10 +2540,10 @@ void TileMapLayer::set_y_sort_enabled(bool p_y_sort_enabled) {
|
|||
}
|
||||
CanvasItem::set_y_sort_enabled(p_y_sort_enabled);
|
||||
dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] = true;
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->queue_internal_update();
|
||||
tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_queue_internal_update();
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->update_configuration_warnings();
|
||||
_update_notify_local_transform();
|
||||
}
|
||||
|
@ -2532,9 +2554,8 @@ void TileMapLayer::set_y_sort_origin(int p_y_sort_origin) {
|
|||
}
|
||||
y_sort_origin = p_y_sort_origin;
|
||||
dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] = true;
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->queue_internal_update();
|
||||
tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_queue_internal_update();
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
}
|
||||
|
||||
int TileMapLayer::get_y_sort_origin() const {
|
||||
|
@ -2547,19 +2568,18 @@ void TileMapLayer::set_z_index(int p_z_index) {
|
|||
}
|
||||
CanvasItem::set_z_index(p_z_index);
|
||||
dirty.flags[DIRTY_FLAGS_LAYER_Z_INDEX] = true;
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->queue_internal_update();
|
||||
tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_queue_internal_update();
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->update_configuration_warnings();
|
||||
}
|
||||
|
||||
void TileMapLayer::set_use_kinematic_bodies(bool p_use_kinematic_bodies) {
|
||||
use_kinematic_bodies = p_use_kinematic_bodies;
|
||||
dirty.flags[DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES] = p_use_kinematic_bodies;
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->queue_internal_update();
|
||||
tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_queue_internal_update();
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
}
|
||||
|
||||
bool TileMapLayer::is_using_kinematic_bodies() const {
|
||||
|
@ -2572,9 +2592,8 @@ void TileMapLayer::set_navigation_enabled(bool p_enabled) {
|
|||
}
|
||||
navigation_enabled = p_enabled;
|
||||
dirty.flags[DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED] = true;
|
||||
TileMap *tile_map_node = _fetch_tilemap();
|
||||
tile_map_node->queue_internal_update();
|
||||
tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
_queue_internal_update();
|
||||
emit_signal(CoreStringNames::get_singleton()->changed);
|
||||
}
|
||||
|
||||
bool TileMapLayer::is_navigation_enabled() const {
|
||||
|
@ -2595,7 +2614,7 @@ RID TileMapLayer::get_navigation_map() const {
|
|||
}
|
||||
|
||||
void TileMapLayer::fix_invalid_tiles() {
|
||||
Ref<TileSet> tileset = _fetch_tileset();
|
||||
Ref<TileSet> tileset = get_effective_tile_set();
|
||||
ERR_FAIL_COND_MSG(tileset.is_null(), "Cannot call fix_invalid_tiles() on a TileMap without a valid TileSet.");
|
||||
|
||||
RBSet<Vector2i> coords;
|
||||
|
@ -2618,6 +2637,15 @@ Vector2i TileMapLayer::get_coords_for_body_rid(RID p_physics_body) const {
|
|||
return bodies_coords[p_physics_body];
|
||||
}
|
||||
|
||||
Ref<TileSet> TileMapLayer::get_effective_tile_set() const {
|
||||
TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(get_parent());
|
||||
if (tile_map_layer_group) {
|
||||
return tile_map_layer_group->get_tileset();
|
||||
} else {
|
||||
return Ref<TileSet>();
|
||||
}
|
||||
}
|
||||
|
||||
TileMapLayer::TileMapLayer() {
|
||||
set_notify_transform(true);
|
||||
}
|
||||
|
@ -2625,7 +2653,7 @@ TileMapLayer::TileMapLayer() {
|
|||
TileMapLayer::~TileMapLayer() {
|
||||
in_destructor = true;
|
||||
clear();
|
||||
internal_update();
|
||||
_internal_update();
|
||||
}
|
||||
|
||||
HashMap<Vector2i, TileSet::CellNeighbor> TerrainConstraint::get_overlapping_coords_and_peering_bits() const {
|
||||
|
|
|
@ -232,13 +232,15 @@ public:
|
|||
DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED,
|
||||
DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE,
|
||||
|
||||
DIRTY_FLAGS_TILE_MAP_SELECTED_LAYER,
|
||||
DIRTY_FLAGS_LAYER_GROUP_SELECTED_LAYERS,
|
||||
DIRTY_FLAGS_LAYER_GROUP_HIGHLIGHT_SELECTED,
|
||||
DIRTY_FLAGS_LAYER_GROUP_TILE_SET,
|
||||
|
||||
DIRTY_FLAGS_TILE_MAP_LIGHT_MASK,
|
||||
DIRTY_FLAGS_TILE_MAP_MATERIAL,
|
||||
DIRTY_FLAGS_TILE_MAP_USE_PARENT_MATERIAL,
|
||||
DIRTY_FLAGS_TILE_MAP_TEXTURE_FILTER,
|
||||
DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT,
|
||||
DIRTY_FLAGS_TILE_MAP_TILE_SET,
|
||||
DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE,
|
||||
DIRTY_FLAGS_TILE_MAP_COLLISION_VISIBILITY_MODE,
|
||||
DIRTY_FLAGS_TILE_MAP_NAVIGATION_VISIBILITY_MODE,
|
||||
|
@ -259,6 +261,7 @@ private:
|
|||
// Internal.
|
||||
int layer_index_in_tile_map_node = -1;
|
||||
HashMap<Vector2i, CellData> tile_map;
|
||||
bool pending_update = false;
|
||||
|
||||
// Dirty flag. Allows knowing what was modified since the last update.
|
||||
struct {
|
||||
|
@ -275,7 +278,6 @@ private:
|
|||
|
||||
// Method to fetch the TileSet to use
|
||||
TileMap *_fetch_tilemap() const;
|
||||
Ref<TileSet> _fetch_tileset() const;
|
||||
|
||||
// Runtime tile data.
|
||||
bool _runtime_update_tile_data_was_cleaned_up = false;
|
||||
|
@ -331,15 +333,21 @@ private:
|
|||
#endif // DEBUG_ENABLED
|
||||
|
||||
// Terrains.
|
||||
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);
|
||||
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) const;
|
||||
RBSet<TerrainConstraint> _get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const;
|
||||
RBSet<TerrainConstraint> _get_terrain_constraints_from_painted_cells_list(const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const;
|
||||
|
||||
void _renamed();
|
||||
void _update_notify_local_transform();
|
||||
|
||||
// Internal updates.
|
||||
void _queue_internal_update();
|
||||
void _deferred_internal_update();
|
||||
void _internal_update();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
// TileMap node.
|
||||
|
@ -349,10 +357,10 @@ public:
|
|||
Rect2 get_rect(bool &r_changed) const;
|
||||
|
||||
// Terrains.
|
||||
HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints); // Not exposed.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints) const; // Not exposed.
|
||||
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) const; // Not exposed.
|
||||
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) const; // Not exposed.
|
||||
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) const; // Not exposed.
|
||||
|
||||
// Not exposed to users.
|
||||
TileMapCell get_cell(const Vector2i &p_coords, bool p_use_proxies = false) const;
|
||||
|
@ -361,10 +369,10 @@ public:
|
|||
void set_tile_data(TileMapDataFormat p_format, const Vector<int> &p_data);
|
||||
Vector<int> get_tile_data() const;
|
||||
void notify_tile_map_change(DirtyFlags p_what);
|
||||
void internal_update();
|
||||
|
||||
void update_internals();
|
||||
|
||||
// --- Exposed in TileMap ---
|
||||
|
||||
// Cells manipulation.
|
||||
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);
|
||||
void erase_cell(const Vector2i &p_coords);
|
||||
|
@ -410,6 +418,11 @@ public:
|
|||
bool has_body_rid(RID p_physics_body) const;
|
||||
Vector2i get_coords_for_body_rid(RID p_physics_body) const; // For finding tiles from collision.
|
||||
|
||||
// Helper.
|
||||
Ref<TileSet> get_effective_tile_set() const;
|
||||
|
||||
// ---
|
||||
|
||||
TileMapLayer();
|
||||
~TileMapLayer();
|
||||
};
|
||||
|
|
148
scene/2d/tile_map_layer_group.cpp
Normal file
148
scene/2d/tile_map_layer_group.cpp
Normal file
|
@ -0,0 +1,148 @@
|
|||
/**************************************************************************/
|
||||
/* tile_map_layer_group.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "tile_map_layer_group.h"
|
||||
|
||||
#include "core/core_string_names.h"
|
||||
#include "scene/2d/tile_map_layer.h"
|
||||
#include "scene/resources/tile_set.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
void TileMapLayerGroup::_cleanup_selected_layers() {
|
||||
for (int i = 0; i < selected_layers.size(); i++) {
|
||||
const String name = selected_layers[i];
|
||||
TileMapLayer *layer = Object::cast_to<TileMapLayer>(get_node_or_null(name));
|
||||
if (!layer) {
|
||||
selected_layers.remove_at(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
void TileMapLayerGroup::_tile_set_changed() {
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
TileMapLayer *layer = Object::cast_to<TileMapLayer>(get_child(i));
|
||||
if (layer) {
|
||||
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_TILE_SET);
|
||||
}
|
||||
}
|
||||
|
||||
update_configuration_warnings();
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
void TileMapLayerGroup::set_selected_layers(Vector<StringName> p_layer_names) {
|
||||
selected_layers = p_layer_names;
|
||||
_cleanup_selected_layers();
|
||||
|
||||
// Update the layers modulation.
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
TileMapLayer *layer = Object::cast_to<TileMapLayer>(get_child(i));
|
||||
if (layer) {
|
||||
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_SELECTED_LAYERS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector<StringName> TileMapLayerGroup::get_selected_layers() const {
|
||||
return selected_layers;
|
||||
}
|
||||
|
||||
void TileMapLayerGroup::set_highlight_selected_layer(bool p_highlight_selected_layer) {
|
||||
if (highlight_selected_layer == p_highlight_selected_layer) {
|
||||
return;
|
||||
}
|
||||
|
||||
highlight_selected_layer = p_highlight_selected_layer;
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
TileMapLayer *layer = Object::cast_to<TileMapLayer>(get_child(i));
|
||||
if (layer) {
|
||||
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_HIGHLIGHT_SELECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TileMapLayerGroup::is_highlighting_selected_layer() const {
|
||||
return highlight_selected_layer;
|
||||
}
|
||||
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
void TileMapLayerGroup::remove_child_notify(Node *p_child) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
_cleanup_selected_layers();
|
||||
#endif // TOOLS_ENABLED
|
||||
}
|
||||
|
||||
void TileMapLayerGroup::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_tileset", "tileset"), &TileMapLayerGroup::set_tileset);
|
||||
ClassDB::bind_method(D_METHOD("get_tileset"), &TileMapLayerGroup::get_tileset);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tile_set", PROPERTY_HINT_RESOURCE_TYPE, "TileSet"), "set_tileset", "get_tileset");
|
||||
}
|
||||
|
||||
void TileMapLayerGroup::set_tileset(const Ref<TileSet> &p_tileset) {
|
||||
if (p_tileset == tile_set) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the tileset, registering to its changes.
|
||||
if (tile_set.is_valid()) {
|
||||
tile_set->disconnect_changed(callable_mp(this, &TileMapLayerGroup::_tile_set_changed));
|
||||
}
|
||||
|
||||
tile_set = p_tileset;
|
||||
|
||||
if (tile_set.is_valid()) {
|
||||
tile_set->connect_changed(callable_mp(this, &TileMapLayerGroup::_tile_set_changed));
|
||||
}
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
TileMapLayer *layer = Object::cast_to<TileMapLayer>(get_child(i));
|
||||
if (layer) {
|
||||
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_TILE_SET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ref<TileSet> TileMapLayerGroup::get_tileset() const {
|
||||
return tile_set;
|
||||
}
|
||||
|
||||
TileMapLayerGroup::~TileMapLayerGroup() {
|
||||
if (tile_set.is_valid()) {
|
||||
tile_set->disconnect_changed(callable_mp(this, &TileMapLayerGroup::_tile_set_changed));
|
||||
}
|
||||
}
|
73
scene/2d/tile_map_layer_group.h
Normal file
73
scene/2d/tile_map_layer_group.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/**************************************************************************/
|
||||
/* tile_map_layer_group.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TILE_MAP_LAYER_GROUP_H
|
||||
#define TILE_MAP_LAYER_GROUP_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
|
||||
class TileSet;
|
||||
|
||||
class TileMapLayerGroup : public Node2D {
|
||||
GDCLASS(TileMapLayerGroup, Node2D);
|
||||
|
||||
private:
|
||||
mutable Vector<StringName> selected_layers;
|
||||
bool highlight_selected_layer = true;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
void _cleanup_selected_layers();
|
||||
#endif
|
||||
void _tile_set_changed();
|
||||
|
||||
protected:
|
||||
Ref<TileSet> tile_set;
|
||||
|
||||
virtual void remove_child_notify(Node *p_child) override;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
#ifdef TOOLS_ENABLED
|
||||
// For editor use.
|
||||
void set_selected_layers(Vector<StringName> p_layer_names);
|
||||
Vector<StringName> get_selected_layers() const;
|
||||
void set_highlight_selected_layer(bool p_highlight_selected_layer);
|
||||
bool is_highlighting_selected_layer() const;
|
||||
#endif
|
||||
|
||||
// Accessors.
|
||||
void set_tileset(const Ref<TileSet> &p_tileset);
|
||||
Ref<TileSet> get_tileset() const;
|
||||
|
||||
~TileMapLayerGroup();
|
||||
};
|
||||
|
||||
#endif // TILE_MAP_LAYER_GROUP_H
|
|
@ -783,6 +783,7 @@ void register_scene_types() {
|
|||
GDREGISTER_CLASS(TileMapPattern);
|
||||
GDREGISTER_CLASS(TileData);
|
||||
GDREGISTER_CLASS(TileMap);
|
||||
GDREGISTER_ABSTRACT_CLASS(TileMapLayerGroup);
|
||||
GDREGISTER_CLASS(ParallaxBackground);
|
||||
GDREGISTER_CLASS(ParallaxLayer);
|
||||
GDREGISTER_CLASS(TouchScreenButton);
|
||||
|
|
|
@ -1478,7 +1478,7 @@ TileMapCell TileSet::get_random_tile_from_terrains_pattern(int p_terrain_set, Ti
|
|||
ERR_FAIL_V(TileMapCell());
|
||||
}
|
||||
|
||||
Vector<Vector2> TileSet::get_tile_shape_polygon() {
|
||||
Vector<Vector2> TileSet::get_tile_shape_polygon() const {
|
||||
Vector<Vector2> points;
|
||||
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
|
||||
points.push_back(Vector2(-0.5, -0.5));
|
||||
|
@ -1519,7 +1519,7 @@ Vector<Vector2> TileSet::get_tile_shape_polygon() {
|
|||
return points;
|
||||
}
|
||||
|
||||
void TileSet::draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform, Color p_color, bool p_filled, Ref<Texture2D> p_texture) {
|
||||
void TileSet::draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform, Color p_color, bool p_filled, Ref<Texture2D> p_texture) const {
|
||||
if (tile_meshes_dirty) {
|
||||
Vector<Vector2> shape = get_tile_shape_polygon();
|
||||
Vector<Vector2> uvs;
|
||||
|
@ -2165,7 +2165,40 @@ Vector2i TileSet::get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeigh
|
|||
}
|
||||
}
|
||||
|
||||
Vector2i TileSet::map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern) {
|
||||
TypedArray<Vector2i> TileSet::get_surrounding_cells(const Vector2i &p_coords) const {
|
||||
TypedArray<Vector2i> around;
|
||||
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_LEFT_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_SIDE));
|
||||
} else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE));
|
||||
} else {
|
||||
if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_LEFT_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE));
|
||||
} else {
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_SIDE));
|
||||
around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE));
|
||||
}
|
||||
}
|
||||
|
||||
return around;
|
||||
}
|
||||
|
||||
Vector2i TileSet::map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern) const {
|
||||
ERR_FAIL_COND_V(p_pattern.is_null(), Vector2i());
|
||||
ERR_FAIL_COND_V(!p_pattern->has_cell(p_coords_in_pattern), Vector2i());
|
||||
|
||||
|
@ -2189,6 +2222,49 @@ Vector2i TileSet::map_pattern(const Vector2i &p_position_in_tilemap, const Vecto
|
|||
return output;
|
||||
}
|
||||
|
||||
void TileSet::draw_cells_outline(CanvasItem *p_canvas_item, const RBSet<Vector2i> &p_cells, Color p_color, Transform2D p_transform) const {
|
||||
Vector<Vector2> polygon = get_tile_shape_polygon();
|
||||
for (const Vector2i &E : p_cells) {
|
||||
Vector2 center = map_to_local(E);
|
||||
|
||||
#define DRAW_SIDE_IF_NEEDED(side, polygon_index_from, polygon_index_to) \
|
||||
if (!p_cells.has(get_neighbor_cell(E, side))) { \
|
||||
Vector2 from = p_transform.xform(center + polygon[polygon_index_from] * tile_size); \
|
||||
Vector2 to = p_transform.xform(center + polygon[polygon_index_to] * tile_size); \
|
||||
p_canvas_item->draw_line(from, to, p_color); \
|
||||
}
|
||||
|
||||
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, 1, 2);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 2, 3);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 3, 0);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 0, 1);
|
||||
} else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 2, 3);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 1, 2);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 3, 0);
|
||||
} else {
|
||||
if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 2, 3);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 1, 2);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 5, 0);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, 4, 5);
|
||||
} else {
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 4, 5);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 5, 0);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 1, 2);
|
||||
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 2, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef DRAW_SIDE_IF_NEEDED
|
||||
}
|
||||
|
||||
Vector<Point2> TileSet::get_terrain_polygon(int p_terrain_set) {
|
||||
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
|
||||
return _get_square_terrain_polygon(tile_size);
|
||||
|
@ -3185,6 +3261,115 @@ void TileSet::reset_state() {
|
|||
tile_size = Size2i(16, 16);
|
||||
}
|
||||
|
||||
Vector2i TileSet::transform_coords_layout(const 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
|
||||
SWAP(output.x, output.y);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
const Vector2i TileSetSource::INVALID_ATLAS_COORDS = Vector2i(-1, -1);
|
||||
const int TileSetSource::INVALID_TILE_ALTERNATIVE = -1;
|
||||
|
||||
|
|
|
@ -319,7 +319,7 @@ private:
|
|||
|
||||
Ref<ArrayMesh> tile_lines_mesh;
|
||||
Ref<ArrayMesh> tile_filled_mesh;
|
||||
bool tile_meshes_dirty = true;
|
||||
mutable bool tile_meshes_dirty = true;
|
||||
|
||||
// Physics
|
||||
struct PhysicsLayer {
|
||||
|
@ -527,15 +527,17 @@ public:
|
|||
TileMapCell get_random_tile_from_terrains_pattern(int p_terrain_set, TerrainsPattern p_terrain_tile_pattern);
|
||||
|
||||
// Helpers
|
||||
Vector<Vector2> get_tile_shape_polygon();
|
||||
void draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform, Color p_color, bool p_filled = false, Ref<Texture2D> p_texture = Ref<Texture2D>());
|
||||
Vector<Vector2> get_tile_shape_polygon() const;
|
||||
void draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform, Color p_color, bool p_filled = false, Ref<Texture2D> p_texture = Ref<Texture2D>()) const;
|
||||
|
||||
// Used by TileMap/TileMapLayer
|
||||
Vector2 map_to_local(const Vector2i &p_pos) const;
|
||||
Vector2i local_to_map(const Vector2 &p_pos) 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;
|
||||
Vector2i map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern);
|
||||
TypedArray<Vector2i> get_surrounding_cells(const Vector2i &p_coords) const;
|
||||
Vector2i map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern) const;
|
||||
void draw_cells_outline(CanvasItem *p_canvas_item, const RBSet<Vector2i> &p_cells, Color p_color, Transform2D p_transform = Transform2D()) const;
|
||||
|
||||
Vector<Point2> get_terrain_polygon(int p_terrain_set);
|
||||
Vector<Point2> get_terrain_peering_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit);
|
||||
|
@ -545,6 +547,9 @@ public:
|
|||
// Resource management
|
||||
virtual void reset_state() override;
|
||||
|
||||
// Helpers.
|
||||
static Vector2i transform_coords_layout(const Vector2i &p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout);
|
||||
|
||||
TileSet();
|
||||
~TileSet();
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue