TileMap Fixes

This commit is contained in:
Mariano Suligoy 2017-11-30 21:50:09 -03:00
parent 4170e8f3df
commit af719a90a7
7 changed files with 98 additions and 91 deletions

View File

@ -4753,9 +4753,9 @@ VSplitContainer *SpatialEditor::get_shader_split() {
return shader_split; return shader_split;
} }
HBoxContainer *SpatialEditor::get_palette_split() { HSplitContainer *SpatialEditor::get_palette_split() {
return palette_split_container; return palette_split;
} }
void SpatialEditor::_request_gizmo(Object *p_obj) { void SpatialEditor::_request_gizmo(Object *p_obj) {
@ -5046,10 +5046,6 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
palette_split->set_v_size_flags(SIZE_EXPAND_FILL); palette_split->set_v_size_flags(SIZE_EXPAND_FILL);
vbc->add_child(palette_split); vbc->add_child(palette_split);
palette_split_container = memnew(HBoxContainer);
palette_split_container->set_v_size_flags(SIZE_EXPAND_FILL);
palette_split->add_child(palette_split_container);
shader_split = memnew(VSplitContainer); shader_split = memnew(VSplitContainer);
shader_split->set_h_size_flags(SIZE_EXPAND_FILL); shader_split->set_h_size_flags(SIZE_EXPAND_FILL);
palette_split->add_child(shader_split); palette_split->add_child(shader_split);

View File

@ -413,7 +413,6 @@ private:
SpatialEditorViewport *viewports[VIEWPORTS_COUNT]; SpatialEditorViewport *viewports[VIEWPORTS_COUNT];
VSplitContainer *shader_split; VSplitContainer *shader_split;
HSplitContainer *palette_split; HSplitContainer *palette_split;
HBoxContainer *palette_split_container;
///// /////
@ -608,7 +607,7 @@ public:
void add_control_to_menu_panel(Control *p_control); void add_control_to_menu_panel(Control *p_control);
VSplitContainer *get_shader_split(); VSplitContainer *get_shader_split();
HBoxContainer *get_palette_split(); HSplitContainer *get_palette_split();
Spatial *get_selected() { return selected; } Spatial *get_selected() { return selected; }

View File

@ -123,12 +123,14 @@ void TileMapEditor::_menu_option(int p_option) {
return; return;
undo_redo->create_action(TTR("Erase Selection")); undo_redo->create_action(TTR("Erase Selection"));
undo_redo->add_undo_method(node, "set", "tile_data", node->get("tile_data"));
for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) { for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) {
for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) { for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) {
_set_cell(Point2i(j, i), TileMap::INVALID_CELL, false, false, false, true); _set_cell(Point2i(j, i), TileMap::INVALID_CELL, false, false, false);
} }
} }
undo_redo->add_do_method(node, "set", "tile_data", node->get("tile_data"));
undo_redo->commit_action(); undo_redo->commit_action();
selection_active = false; selection_active = false;
@ -171,7 +173,7 @@ void TileMapEditor::set_selected_tile(int p_tile) {
} }
} }
void TileMapEditor::_set_cell(const Point2i &p_pos, int p_value, bool p_flip_h, bool p_flip_v, bool p_transpose, bool p_with_undo) { void TileMapEditor::_set_cell(const Point2i &p_pos, int p_value, bool p_flip_h, bool p_flip_v, bool p_transpose) {
ERR_FAIL_COND(!node); ERR_FAIL_COND(!node);
@ -184,18 +186,9 @@ void TileMapEditor::_set_cell(const Point2i &p_pos, int p_value, bool p_flip_h,
if (p_value == prev_val && p_flip_h == prev_flip_h && p_flip_v == prev_flip_v && p_transpose == prev_transpose) if (p_value == prev_val && p_flip_h == prev_flip_h && p_flip_v == prev_flip_v && p_transpose == prev_transpose)
return; //check that it's actually different return; //check that it's actually different
if (p_with_undo) {
undo_redo->add_do_method(node, "set_cellv", Point2(p_pos), p_value, p_flip_h, p_flip_v, p_transpose);
undo_redo->add_do_method(node, "make_bitmask_area_dirty", Point2(p_pos));
undo_redo->add_undo_method(node, "set_cellv", Point2(p_pos), prev_val, prev_flip_h, prev_flip_v, prev_transpose);
undo_redo->add_undo_method(node, "make_bitmask_area_dirty", Point2(p_pos));
} else {
node->set_cell(p_pos.x, p_pos.y, p_value, p_flip_h, p_flip_v, p_transpose); node->set_cell(p_pos.x, p_pos.y, p_value, p_flip_h, p_flip_v, p_transpose);
node->update_bitmask_area(Point2(p_pos)); node->update_bitmask_area(Point2(p_pos));
} }
}
void TileMapEditor::_text_entered(const String &p_text) { void TileMapEditor::_text_entered(const String &p_text) {
@ -404,6 +397,7 @@ PoolVector<Vector2> TileMapEditor::_bucket_fill(const Point2i &p_start, bool era
} }
PoolVector<Vector2> points; PoolVector<Vector2> points;
Vector<Vector2> non_preview_cache;
int count = 0; int count = 0;
int limit = 0; int limit = 0;
@ -432,8 +426,10 @@ PoolVector<Vector2> TileMapEditor::_bucket_fill(const Point2i &p_start, bool era
bucket_cache_visited[loc] = true; bucket_cache_visited[loc] = true;
bucket_cache.push_back(n); bucket_cache.push_back(n);
} else { } else {
node->set_cellv(n, id, flip_h, flip_v, transpose); if (non_preview_cache.find(n) >= 0)
continue;
points.push_back(n); points.push_back(n);
non_preview_cache.push_back(n);
} }
bucket_queue.push_back(Point2i(n.x, n.y + 1)); bucket_queue.push_back(Point2i(n.x, n.y + 1));
@ -462,9 +458,10 @@ void TileMapEditor::_fill_points(const PoolVector<Vector2> p_points, const Dicti
bool tr = p_op["transpose"]; bool tr = p_op["transpose"];
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
_set_cell(pr[i], id, xf, yf, tr); _set_cell(pr[i], id, xf, yf, tr);
node->make_bitmask_area_dirty(pr[i]);
} }
node->update_dirty_bitmask();
} }
void TileMapEditor::_erase_points(const PoolVector<Vector2> p_points) { void TileMapEditor::_erase_points(const PoolVector<Vector2> p_points) {
@ -730,10 +727,8 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
tool = TOOL_PAINTING; tool = TOOL_PAINTING;
paint_undo.clear(); undo_redo->create_action(TTR("Paint TileMap"));
paint_undo[over_tile] = _get_op_from_cell(over_tile); undo_redo->add_undo_method(node, "set", "tile_data", node->get("tile_data"));
_set_cell(over_tile, id, flip_h, flip_v, transpose);
} }
} else if (tool == TOOL_PICKING) { } else if (tool == TOOL_PICKING) {
@ -754,15 +749,9 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
int id = get_selected_tile(); int id = get_selected_tile();
if (id != TileMap::INVALID_CELL && paint_undo.size()) { if (id != TileMap::INVALID_CELL) {
undo_redo->create_action(TTR("Paint TileMap")); undo_redo->add_do_method(node, "set", "tile_data", node->get("tile_data"));
for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
Point2 p = E->key();
undo_redo->add_do_method(node, "set_cellv", p, id, flip_h, flip_v, transpose);
undo_redo->add_undo_method(node, "set_cellv", p, E->get().idx, E->get().xf, E->get().yf, E->get().tr);
}
undo_redo->commit_action(); undo_redo->commit_action();
paint_undo.clear(); paint_undo.clear();
@ -774,10 +763,12 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
if (id != TileMap::INVALID_CELL) { if (id != TileMap::INVALID_CELL) {
undo_redo->create_action(TTR("Line Draw")); undo_redo->create_action(TTR("Line Draw"));
undo_redo->add_undo_method(node, "set", "tile_data", node->get("tile_data"));
for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) { for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
_set_cell(E->key(), id, flip_h, flip_v, transpose, true); _set_cell(E->key(), id, flip_h, flip_v, transpose);
} }
undo_redo->add_do_method(node, "set", "tile_data", node->get("tile_data"));
undo_redo->commit_action(); undo_redo->commit_action();
paint_undo.clear(); paint_undo.clear();
@ -791,12 +782,14 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
if (id != TileMap::INVALID_CELL) { if (id != TileMap::INVALID_CELL) {
undo_redo->create_action(TTR("Rectangle Paint")); undo_redo->create_action(TTR("Rectangle Paint"));
undo_redo->add_undo_method(node, "set", "tile_data", node->get("tile_data"));
for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) { for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) {
for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) { for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) {
_set_cell(Point2i(j, i), id, flip_h, flip_v, transpose, true); _set_cell(Point2i(j, i), id, flip_h, flip_v, transpose);
} }
} }
undo_redo->add_do_method(node, "set", "tile_data", node->get("tile_data"));
undo_redo->commit_action(); undo_redo->commit_action();
canvas_item_editor->update(); canvas_item_editor->update();
@ -806,10 +799,12 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
Point2 ofs = over_tile - rectangle.position; Point2 ofs = over_tile - rectangle.position;
undo_redo->create_action(TTR("Duplicate")); undo_redo->create_action(TTR("Duplicate"));
undo_redo->add_undo_method(node, "set", "tile_data", node->get("tile_data"));
for (List<TileData>::Element *E = copydata.front(); E; E = E->next()) { for (List<TileData>::Element *E = copydata.front(); E; E = E->next()) {
_set_cell(E->get().pos + ofs, E->get().cell, E->get().flip_h, E->get().flip_v, E->get().transpose, true); _set_cell(E->get().pos + ofs, E->get().cell, E->get().flip_h, E->get().flip_v, E->get().transpose);
} }
undo_redo->add_do_method(node, "set", "tile_data", node->get("tile_data"));
undo_redo->commit_action(); undo_redo->commit_action();
copydata.clear(); copydata.clear();
@ -822,28 +817,23 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
} else if (tool == TOOL_BUCKET) { } else if (tool == TOOL_BUCKET) {
Dictionary pop;
pop["id"] = node->get_cell(over_tile.x, over_tile.y);
pop["flip_h"] = node->is_cell_x_flipped(over_tile.x, over_tile.y);
pop["flip_v"] = node->is_cell_y_flipped(over_tile.x, over_tile.y);
pop["transpose"] = node->is_cell_transposed(over_tile.x, over_tile.y);
PoolVector<Vector2> points = _bucket_fill(over_tile); PoolVector<Vector2> points = _bucket_fill(over_tile);
if (points.size() == 0) if (points.size() == 0)
return false; return false;
undo_redo->create_action(TTR("Bucket Fill"));
undo_redo->add_undo_method(node, "set", "tile_data", node->get("tile_data"));
Dictionary op; Dictionary op;
op["id"] = get_selected_tile(); op["id"] = get_selected_tile();
op["flip_h"] = flip_h; op["flip_h"] = flip_h;
op["flip_v"] = flip_v; op["flip_v"] = flip_v;
op["transpose"] = transpose; op["transpose"] = transpose;
undo_redo->create_action(TTR("Bucket Fill")); _fill_points(points, op);
undo_redo->add_do_method(this, "_fill_points", points, op);
undo_redo->add_undo_method(this, "_fill_points", points, pop);
undo_redo->add_do_method(node, "set", "tile_data", node->get("tile_data"));
undo_redo->commit_action(); undo_redo->commit_action();
// We want to keep the bucket-tool active // We want to keep the bucket-tool active
@ -885,6 +875,9 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
Point2 local = node->world_to_map(xform_inv.xform(mb->get_position())); Point2 local = node->world_to_map(xform_inv.xform(mb->get_position()));
undo_redo->create_action(TTR("Erase TileMap"));
undo_redo->add_undo_method(node, "set", "tile_data", node->get("tile_data"));
if (mb->get_shift()) { if (mb->get_shift()) {
if (mb->get_control()) if (mb->get_control())
@ -898,7 +891,6 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
tool = TOOL_ERASING; tool = TOOL_ERASING;
paint_undo[local] = _get_op_from_cell(local);
_set_cell(local, TileMap::INVALID_CELL); _set_cell(local, TileMap::INVALID_CELL);
} }
@ -908,18 +900,8 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
} else { } else {
if (tool == TOOL_ERASING || tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) { if (tool == TOOL_ERASING || tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
if (paint_undo.size()) { undo_redo->add_do_method(node, "set", "tile_data", node->get("tile_data"));
undo_redo->create_action(TTR("Erase TileMap"));
for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
Point2 p = E->key();
undo_redo->add_do_method(node, "set_cellv", p, TileMap::INVALID_CELL, false, false, false);
undo_redo->add_undo_method(node, "set_cellv", p, E->get().idx, E->get().xf, E->get().yf, E->get().tr);
}
undo_redo->commit_action(); undo_redo->commit_action();
paint_undo.clear();
}
if (tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) { if (tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
canvas_item_editor->update(); canvas_item_editor->update();
@ -1006,10 +988,6 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
Point2i pos = points[i]; Point2i pos = points[i];
if (!paint_undo.has(pos)) {
paint_undo[pos] = _get_op_from_cell(pos);
}
_set_cell(pos, TileMap::INVALID_CELL); _set_cell(pos, TileMap::INVALID_CELL);
} }

View File

@ -167,7 +167,7 @@ class TileMapEditor : public VBoxContainer {
void _update_palette(); void _update_palette();
void _menu_option(int p_option); void _menu_option(int p_option);
void _set_cell(const Point2i &p_pos, int p_value, bool p_flip_h = false, bool p_flip_v = false, bool p_transpose = false, bool p_with_undo = false); void _set_cell(const Point2i &p_pos, int p_value, bool p_flip_h = false, bool p_flip_v = false, bool p_transpose = false);
void _canvas_mouse_enter(); void _canvas_mouse_enter();
void _canvas_mouse_exit(); void _canvas_mouse_exit();

View File

@ -1015,6 +1015,13 @@ void AutotileEditor::_on_tool_clicked(int p_tool) {
tile_set->autotile_clear_bitmask_map(get_current_tile()); tile_set->autotile_clear_bitmask_map(get_current_tile());
workspace->update(); workspace->update();
} else if (p_tool == SHAPE_DELETE) { } else if (p_tool == SHAPE_DELETE) {
if (creating_shape) {
creating_shape = false;
current_shape.resize(0);
workspace->update();
} else {
switch (edit_mode) {
case EDITMODE_COLLISION: {
if (!edited_collision_shape.is_null()) { if (!edited_collision_shape.is_null()) {
Vector<TileSet::ShapeData> sd = tile_set->tile_get_shapes(get_current_tile()); Vector<TileSet::ShapeData> sd = tile_set->tile_get_shapes(get_current_tile());
int index; int index;
@ -1027,11 +1034,30 @@ void AutotileEditor::_on_tool_clicked(int p_tool) {
if (index >= 0) { if (index >= 0) {
sd.remove(index); sd.remove(index);
tile_set->tile_set_shapes(get_current_tile(), sd); tile_set->tile_set_shapes(get_current_tile(), sd);
edited_collision_shape.unref(); edited_collision_shape = Ref<ConcavePolygonShape2D>();
current_shape.resize(0); current_shape.resize(0);
workspace->update(); workspace->update();
} }
} }
} break;
case EDITMODE_NAVIGATION: {
if (!edited_navigation_shape.is_null()) {
tile_set->autotile_set_navigation_polygon(get_current_tile(), Ref<NavigationPolygon>(), edited_shape_coord);
edited_navigation_shape = Ref<NavigationPolygon>();
current_shape.resize(0);
workspace->update();
}
} break;
case EDITMODE_OCCLUSION: {
if (!edited_occlusion_shape.is_null()) {
tile_set->autotile_set_light_occluder(get_current_tile(), Ref<OccluderPolygon2D>(), edited_shape_coord);
edited_occlusion_shape = Ref<OccluderPolygon2D>();
current_shape.resize(0);
workspace->update();
}
} break;
}
}
} else if (p_tool == ZOOM_OUT) { } else if (p_tool == ZOOM_OUT) {
float scale = workspace->get_scale().x; float scale = workspace->get_scale().x;
if (scale > 0.1) { if (scale > 0.1) {

View File

@ -716,7 +716,7 @@ void TileMap::set_cell(int p_x, int p_y, int p_tile, bool p_flip_x, bool p_flip_
} else { } else {
ERR_FAIL_COND(!Q); // quadrant should exist... ERR_FAIL_COND(!Q); // quadrant should exist...
if (E->get().id == p_tile && E->get().flip_h == p_flip_x && E->get().flip_v == p_flip_y && E->get().transpose == p_transpose) if (E->get().id == p_tile && E->get().flip_h == p_flip_x && E->get().flip_v == p_flip_y && E->get().transpose == p_transpose && E->get().autotile_coord_x == (uint16_t)p_autotile_coord.x && E->get().autotile_coord_y == (uint16_t)p_autotile_coord.y)
return; //nothing changed return; //nothing changed
} }
@ -741,7 +741,7 @@ int TileMap::get_cellv(const Vector2 &p_pos) const {
void TileMap::make_bitmask_area_dirty(const Vector2 &p_pos) { void TileMap::make_bitmask_area_dirty(const Vector2 &p_pos) {
for (int x = p_pos.x - 1; x <= p_pos.x + 1; x++) { for (int x = p_pos.x - 1; x <= p_pos.x + 1; x++) {
for (int y = p_pos.y - 1; x <= p_pos.y + 1; y++) { for (int y = p_pos.y - 1; y <= p_pos.y + 1; y++) {
PosKey p(x, y); PosKey p(x, y);
if (dirty_bitmask.find(p) == NULL) { if (dirty_bitmask.find(p) == NULL) {
dirty_bitmask.push_back(p); dirty_bitmask.push_back(p);
@ -810,6 +810,10 @@ void TileMap::update_cell_bitmask(int p_x, int p_y) {
Vector2 coord = tile_set->autotile_get_subtile_for_bitmask(id, mask, this, Vector2(p_x, p_y)); Vector2 coord = tile_set->autotile_get_subtile_for_bitmask(id, mask, this, Vector2(p_x, p_y));
E->get().autotile_coord_x = (int)coord.x; E->get().autotile_coord_x = (int)coord.x;
E->get().autotile_coord_y = (int)coord.y; E->get().autotile_coord_y = (int)coord.y;
PosKey qk(p_x / _get_quadrant_size(), p_y / _get_quadrant_size());
Map<PosKey, Quadrant>::Element *Q = quadrant_map.find(qk);
_make_quadrant_dirty(Q);
} else { } else {
E->get().autotile_coord_x = 0; E->get().autotile_coord_x = 0;
E->get().autotile_coord_y = 0; E->get().autotile_coord_y = 0;
@ -870,28 +874,31 @@ bool TileMap::is_cell_transposed(int p_x, int p_y) const {
return E->get().transpose; return E->get().transpose;
} }
int TileMap::get_cell_autotile_coord_x(int p_x, int p_y) const { void TileMap::set_cell_autotile_coord(int p_x, int p_y, const Vector2 &p_coord) {
PosKey pk(p_x, p_y); PosKey pk(p_x, p_y);
const Map<PosKey, Cell>::Element *E = tile_map.find(pk); const Map<PosKey, Cell>::Element *E = tile_map.find(pk);
if (!E) if (!E)
return 0; return;
return E->get().autotile_coord_x; Cell c = E->get();
c.autotile_coord_x = p_coord.x;
c.autotile_coord_y = p_coord.y;
tile_map[pk] = c;
} }
int TileMap::get_cell_autotile_coord_y(int p_x, int p_y) const { Vector2 TileMap::get_cell_autotile_coord(int p_x, int p_y) const {
PosKey pk(p_x, p_y); PosKey pk(p_x, p_y);
const Map<PosKey, Cell>::Element *E = tile_map.find(pk); const Map<PosKey, Cell>::Element *E = tile_map.find(pk);
if (!E) if (!E)
return 0; return Vector2();
return E->get().autotile_coord_y; return Vector2(E->get().autotile_coord_x, E->get().autotile_coord_y);
} }
void TileMap::_recreate_quadrants() { void TileMap::_recreate_quadrants() {
@ -963,6 +970,7 @@ void TileMap::_set_tile_data(const PoolVector<int> &p_data) {
int offset = (format == FORMAT_2_1_5) ? 3 : 2; int offset = (format == FORMAT_2_1_5) ? 3 : 2;
clear();
for (int i = 0; i < c; i += offset) { for (int i = 0; i < c; i += offset) {
const uint8_t *ptr = (const uint8_t *)&r[i]; const uint8_t *ptr = (const uint8_t *)&r[i];

View File

@ -241,8 +241,8 @@ public:
bool is_cell_x_flipped(int p_x, int p_y) const; bool is_cell_x_flipped(int p_x, int p_y) const;
bool is_cell_y_flipped(int p_x, int p_y) const; bool is_cell_y_flipped(int p_x, int p_y) const;
bool is_cell_transposed(int p_x, int p_y) const; bool is_cell_transposed(int p_x, int p_y) const;
int get_cell_autotile_coord_x(int p_x, int p_y) const; void set_cell_autotile_coord(int p_x, int p_y, const Vector2 &p_coord);
int get_cell_autotile_coord_y(int p_x, int p_y) const; Vector2 get_cell_autotile_coord(int p_x, int p_y) const;
void set_cellv(const Vector2 &p_pos, int p_tile, bool p_flip_x = false, bool p_flip_y = false, bool p_transpose = false); void set_cellv(const Vector2 &p_pos, int p_tile, bool p_flip_x = false, bool p_flip_y = false, bool p_transpose = false);
int get_cellv(const Vector2 &p_pos) const; int get_cellv(const Vector2 &p_pos) const;