Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove some TileMap dependencies from TileMapLayer #92194

Merged
merged 1 commit into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions editor/plugins/tiles/tile_atlas_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ void TileAtlasView::_draw_base_tiles() {
Vector2 offset_pos = Rect2(base_frame_rect).get_center() + Vector2(tile_set_atlas_source->get_tile_data(atlas_coords, 0)->get_texture_origin());

// Draw the tile.
TileMap::draw_tile(ci_rid, offset_pos, tile_set, source_id, atlas_coords, 0, frame);
TileMapLayer::draw_tile(ci_rid, offset_pos, tile_set, source_id, atlas_coords, 0, frame);
}
}

Expand Down Expand Up @@ -411,7 +411,7 @@ void TileAtlasView::_draw_alternatives() {
}

// Draw the tile.
TileMap::draw_tile(ci_rid, offset_pos, tile_set, source_id, atlas_coords, alternative_id);
TileMapLayer::draw_tile(ci_rid, offset_pos, tile_set, source_id, atlas_coords, alternative_id);

// Increment the x position.
current_pos.x += transposed ? texture_region_size.y : texture_region_size.x;
Expand Down
85 changes: 0 additions & 85 deletions scene/2d/tile_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,91 +225,6 @@ int TileMap::get_rendering_quadrant_size() const {
return rendering_quadrant_size;
}

void TileMap::draw_tile(RID p_canvas_item, const Vector2 &p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, const Vector2i &p_atlas_coords, int p_alternative_tile, int p_frame, Color p_modulation, const TileData *p_tile_data_override, real_t p_normalized_animation_offset) {
ERR_FAIL_COND(!p_tile_set.is_valid());
ERR_FAIL_COND(!p_tile_set->has_source(p_atlas_source_id));
ERR_FAIL_COND(!p_tile_set->get_source(p_atlas_source_id)->has_tile(p_atlas_coords));
ERR_FAIL_COND(!p_tile_set->get_source(p_atlas_source_id)->has_alternative_tile(p_atlas_coords, p_alternative_tile));
TileSetSource *source = *p_tile_set->get_source(p_atlas_source_id);
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
if (atlas_source) {
// Check for the frame.
if (p_frame >= 0) {
ERR_FAIL_INDEX(p_frame, atlas_source->get_tile_animation_frames_count(p_atlas_coords));
}

// Get the texture.
Ref<Texture2D> tex = atlas_source->get_runtime_texture();
if (!tex.is_valid()) {
return;
}

// Check if we are in the texture, return otherwise.
Vector2i grid_size = atlas_source->get_atlas_grid_size();
if (p_atlas_coords.x >= grid_size.x || p_atlas_coords.y >= grid_size.y) {
return;
}

// Get tile data.
const TileData *tile_data = p_tile_data_override ? p_tile_data_override : atlas_source->get_tile_data(p_atlas_coords, p_alternative_tile);

// Get the tile modulation.
Color modulate = tile_data->get_modulate() * p_modulation;

// Compute the offset.
Vector2 tile_offset = tile_data->get_texture_origin();

// Get destination rect.
Rect2 dest_rect;
dest_rect.size = atlas_source->get_runtime_tile_texture_region(p_atlas_coords).size;
dest_rect.size.x += FP_ADJUST;
dest_rect.size.y += FP_ADJUST;

bool transpose = tile_data->get_transpose() ^ bool(p_alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE);
if (transpose) {
dest_rect.position = (p_position - Vector2(dest_rect.size.y, dest_rect.size.x) / 2 - tile_offset);
} else {
dest_rect.position = (p_position - dest_rect.size / 2 - tile_offset);
}

if (tile_data->get_flip_h() ^ bool(p_alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H)) {
dest_rect.size.x = -dest_rect.size.x;
}

if (tile_data->get_flip_v() ^ bool(p_alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V)) {
dest_rect.size.y = -dest_rect.size.y;
}

// Draw the tile.
if (p_frame >= 0) {
Rect2i source_rect = atlas_source->get_runtime_tile_texture_region(p_atlas_coords, p_frame);
tex->draw_rect_region(p_canvas_item, dest_rect, source_rect, modulate, transpose, p_tile_set->is_uv_clipping());
} else if (atlas_source->get_tile_animation_frames_count(p_atlas_coords) == 1) {
Rect2i source_rect = atlas_source->get_runtime_tile_texture_region(p_atlas_coords, 0);
tex->draw_rect_region(p_canvas_item, dest_rect, source_rect, modulate, transpose, p_tile_set->is_uv_clipping());
} else {
real_t speed = atlas_source->get_tile_animation_speed(p_atlas_coords);
real_t animation_duration = atlas_source->get_tile_animation_total_duration(p_atlas_coords) / speed;
real_t animation_offset = p_normalized_animation_offset * animation_duration;
// Accumulate durations unaffected by the speed to avoid accumulating floating point division errors.
// Aka do `sum(duration[i]) / speed` instead of `sum(duration[i] / speed)`.
real_t time_unscaled = 0.0;
for (int frame = 0; frame < atlas_source->get_tile_animation_frames_count(p_atlas_coords); frame++) {
real_t frame_duration_unscaled = atlas_source->get_tile_animation_frame_duration(p_atlas_coords, frame);
real_t slice_start = time_unscaled / speed;
real_t slice_end = (time_unscaled + frame_duration_unscaled) / speed;
RenderingServer::get_singleton()->canvas_item_add_animation_slice(p_canvas_item, animation_duration, slice_start, slice_end, animation_offset);

Rect2i source_rect = atlas_source->get_runtime_tile_texture_region(p_atlas_coords, frame);
tex->draw_rect_region(p_canvas_item, dest_rect, source_rect, modulate, transpose, p_tile_set->is_uv_clipping());

time_unscaled += frame_duration_unscaled;
}
RenderingServer::get_singleton()->canvas_item_add_animation_slice(p_canvas_item, 1.0, 0.0, 1.0, 0.0);
}
}
}

void TileMap::set_tileset(const Ref<TileSet> &p_tileset) {
if (p_tileset == tile_set) {
return;
Expand Down
4 changes: 0 additions & 4 deletions scene/2d/tile_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ class TileMap : public Node2D {
// A compatibility enum to specify how is the data if formatted.
mutable TileMapDataFormat format = TileMapDataFormat::TILE_MAP_DATA_FORMAT_3;

static constexpr float FP_ADJUST = 0.00001;

// Properties.
Ref<TileSet> tile_set;
int rendering_quadrant_size = 16;
Expand Down Expand Up @@ -123,8 +121,6 @@ class TileMap : public Node2D {
void set_rendering_quadrant_size(int p_size);
int get_rendering_quadrant_size() const;

static void draw_tile(RID p_canvas_item, const Vector2 &p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, const Vector2i &p_atlas_coords, int p_alternative_tile, int p_frame = -1, Color p_modulation = Color(1.0, 1.0, 1.0, 1.0), const TileData *p_tile_data_override = nullptr, real_t p_normalized_animation_offset = 0.0);

// Accessors.
void set_tileset(const Ref<TileSet> &p_tileset);
Ref<TileSet> get_tileset() const;
Expand Down
95 changes: 90 additions & 5 deletions scene/2d/tile_map_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
}

// Drawing the tile in the canvas item.
TileMap::draw_tile(ci, local_tile_pos - rendering_quadrant->canvas_items_position, tile_set, cell_data.cell.source_id, cell_data.cell.get_atlas_coords(), cell_data.cell.alternative_tile, -1, get_self_modulate(), tile_data, random_animation_offset);
draw_tile(ci, local_tile_pos - rendering_quadrant->canvas_items_position, tile_set, cell_data.cell.source_id, cell_data.cell.get_atlas_coords(), cell_data.cell.alternative_tile, -1, get_self_modulate(), tile_data, random_animation_offset);
}

// Reset physics interpolation for any recreated canvas items.
Expand Down Expand Up @@ -1696,18 +1696,18 @@ void TileMapLayer::_notification(int p_what) {
_internal_update(true);
} break;

case TileMap::NOTIFICATION_ENTER_CANVAS: {
case NOTIFICATION_ENTER_CANVAS: {
dirty.flags[DIRTY_FLAGS_LAYER_IN_CANVAS] = true;
_queue_internal_update();
} break;

case TileMap::NOTIFICATION_EXIT_CANVAS: {
case NOTIFICATION_EXIT_CANVAS: {
dirty.flags[DIRTY_FLAGS_LAYER_IN_CANVAS] = true;
// Update immediately on exiting, and force cleanup.
_internal_update(true);
} break;

case TileMap::NOTIFICATION_VISIBILITY_CHANGED: {
case NOTIFICATION_VISIBILITY_CHANGED: {
dirty.flags[DIRTY_FLAGS_LAYER_VISIBILITY] = true;
_queue_internal_update();
} break;
Expand Down Expand Up @@ -2162,6 +2162,91 @@ TileMapCell TileMapLayer::get_cell(const Vector2i &p_coords) const {
}
}

void TileMapLayer::draw_tile(RID p_canvas_item, const Vector2 &p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, const Vector2i &p_atlas_coords, int p_alternative_tile, int p_frame, Color p_modulation, const TileData *p_tile_data_override, real_t p_normalized_animation_offset) {
ERR_FAIL_COND(p_tile_set.is_null());
ERR_FAIL_COND(!p_tile_set->has_source(p_atlas_source_id));
ERR_FAIL_COND(!p_tile_set->get_source(p_atlas_source_id)->has_tile(p_atlas_coords));
ERR_FAIL_COND(!p_tile_set->get_source(p_atlas_source_id)->has_alternative_tile(p_atlas_coords, p_alternative_tile));
TileSetSource *source = *p_tile_set->get_source(p_atlas_source_id);
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
if (atlas_source) {
// Check for the frame.
if (p_frame >= 0) {
ERR_FAIL_INDEX(p_frame, atlas_source->get_tile_animation_frames_count(p_atlas_coords));
}

// Get the texture.
Ref<Texture2D> tex = atlas_source->get_runtime_texture();
if (tex.is_null()) {
return;
}

// Check if we are in the texture, return otherwise.
Vector2i grid_size = atlas_source->get_atlas_grid_size();
if (p_atlas_coords.x >= grid_size.x || p_atlas_coords.y >= grid_size.y) {
return;
}

// Get tile data.
const TileData *tile_data = p_tile_data_override ? p_tile_data_override : atlas_source->get_tile_data(p_atlas_coords, p_alternative_tile);

// Get the tile modulation.
Color modulate = tile_data->get_modulate() * p_modulation;

// Compute the offset.
Vector2 tile_offset = tile_data->get_texture_origin();

// Get destination rect.
Rect2 dest_rect;
dest_rect.size = atlas_source->get_runtime_tile_texture_region(p_atlas_coords).size;
dest_rect.size.x += FP_ADJUST;
dest_rect.size.y += FP_ADJUST;

bool transpose = tile_data->get_transpose() ^ bool(p_alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE);
if (transpose) {
dest_rect.position = (p_position - Vector2(dest_rect.size.y, dest_rect.size.x) / 2 - tile_offset);
} else {
dest_rect.position = (p_position - dest_rect.size / 2 - tile_offset);
}

if (tile_data->get_flip_h() ^ bool(p_alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H)) {
dest_rect.size.x = -dest_rect.size.x;
}

if (tile_data->get_flip_v() ^ bool(p_alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_V)) {
dest_rect.size.y = -dest_rect.size.y;
}

// Draw the tile.
if (p_frame >= 0) {
Rect2i source_rect = atlas_source->get_runtime_tile_texture_region(p_atlas_coords, p_frame);
tex->draw_rect_region(p_canvas_item, dest_rect, source_rect, modulate, transpose, p_tile_set->is_uv_clipping());
} else if (atlas_source->get_tile_animation_frames_count(p_atlas_coords) == 1) {
Rect2i source_rect = atlas_source->get_runtime_tile_texture_region(p_atlas_coords, 0);
tex->draw_rect_region(p_canvas_item, dest_rect, source_rect, modulate, transpose, p_tile_set->is_uv_clipping());
} else {
real_t speed = atlas_source->get_tile_animation_speed(p_atlas_coords);
real_t animation_duration = atlas_source->get_tile_animation_total_duration(p_atlas_coords) / speed;
real_t animation_offset = p_normalized_animation_offset * animation_duration;
// Accumulate durations unaffected by the speed to avoid accumulating floating point division errors.
// Aka do `sum(duration[i]) / speed` instead of `sum(duration[i] / speed)`.
real_t time_unscaled = 0.0;
for (int frame = 0; frame < atlas_source->get_tile_animation_frames_count(p_atlas_coords); frame++) {
real_t frame_duration_unscaled = atlas_source->get_tile_animation_frame_duration(p_atlas_coords, frame);
real_t slice_start = time_unscaled / speed;
real_t slice_end = (time_unscaled + frame_duration_unscaled) / speed;
RenderingServer::get_singleton()->canvas_item_add_animation_slice(p_canvas_item, animation_duration, slice_start, slice_end, animation_offset);

Rect2i source_rect = atlas_source->get_runtime_tile_texture_region(p_atlas_coords, frame);
tex->draw_rect_region(p_canvas_item, dest_rect, source_rect, modulate, transpose, p_tile_set->is_uv_clipping());

time_unscaled += frame_duration_unscaled;
}
RenderingServer::get_singleton()->canvas_item_add_animation_slice(p_canvas_item, 1.0, 0.0, 1.0, 0.0);
}
}
}

void TileMapLayer::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i &p_atlas_coords, int p_alternative_tile) {
// Set the current cell tile (using integer position).
Vector2i pk(p_coords);
Expand Down Expand Up @@ -2212,7 +2297,7 @@ void TileMapLayer::erase_cell(const Vector2i &p_coords) {
}

void TileMapLayer::fix_invalid_tiles() {
ERR_FAIL_COND_MSG(tile_set.is_null(), "Cannot call fix_invalid_tiles() on a TileMap without a valid TileSet.");
ERR_FAIL_COND_MSG(tile_set.is_null(), "Cannot call fix_invalid_tiles() on a TileMapLayer without a valid TileSet.");

RBSet<Vector2i> coords;
for (const KeyValue<Vector2i, CellData> &E : tile_map_layer_data) {
Expand Down
4 changes: 4 additions & 0 deletions scene/2d/tile_map_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,8 @@ class TileMapLayer : public Node2D {
};

private:
static constexpr float FP_ADJUST = 0.00001;

// Properties.
HashMap<Vector2i, CellData> tile_map_layer_data;

Expand Down Expand Up @@ -407,6 +409,8 @@ class TileMapLayer : public Node2D {
// Not exposed to users.
TileMapCell get_cell(const Vector2i &p_coords) const;

static void draw_tile(RID p_canvas_item, const Vector2 &p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, const Vector2i &p_atlas_coords, int p_alternative_tile, int p_frame = -1, Color p_modulation = Color(1.0, 1.0, 1.0, 1.0), const TileData *p_tile_data_override = nullptr, real_t p_normalized_animation_offset = 0.0);

////////////// Exposed functions //////////////

// --- Cells manipulation ---
Expand Down
Loading