Skip to content

Commit

Permalink
Merge branch 'esuna/feature/tile_map_drop_shadows' into esuna/master
Browse files Browse the repository at this point in the history
  • Loading branch information
Eoin-ONeill-Yokai committed Oct 30, 2024
2 parents cdb855d + fe66b64 commit d0db0cd
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 2 deletions.
36 changes: 36 additions & 0 deletions scene/2d/tile_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,30 @@ RID TileMap::get_layer_navigation_map(int p_layer) const {
TILEMAP_CALL_FOR_LAYER_V(p_layer, RID(), get_navigation_map);
}

void TileMap::set_layer_dropshadow_enabled(int p_layer, bool p_enabled) {
TILEMAP_CALL_FOR_LAYER(p_layer, set_dropshadow_enabled, p_enabled);
}

inline bool TileMap::is_layer_dropshadow_enabled(int p_layer) const {
TILEMAP_CALL_FOR_LAYER_V(p_layer, false, is_dropshadow_enabled);
}

void TileMap::set_layer_dropshadow_offset(int p_layer, Vector2i p_offset) {
TILEMAP_CALL_FOR_LAYER(p_layer, set_dropshadow_offset, p_offset);
}

Vector2i TileMap::get_layer_dropshadow_offset(int p_layer) const {
TILEMAP_CALL_FOR_LAYER_V(p_layer, Vector2i(), get_dropshadow_offset);
}

void TileMap::set_layer_dropshadow_mod_color(int p_layer, Color p_color) {
TILEMAP_CALL_FOR_LAYER(p_layer, set_dropshadow_mod_color, p_color);
}

Color TileMap::get_layer_dropshadow_mod_color(int p_layer) const {
TILEMAP_CALL_FOR_LAYER_V(p_layer, Color(), get_dropshadow_mod_color);
}

void TileMap::set_collision_animatable(bool p_collision_animatable) {
if (collision_animatable == p_collision_animatable) {
return;
Expand Down Expand Up @@ -927,6 +951,15 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_layer_navigation_map", "layer", "map"), &TileMap::set_layer_navigation_map);
ClassDB::bind_method(D_METHOD("get_layer_navigation_map", "layer"), &TileMap::get_layer_navigation_map);

ClassDB::bind_method(D_METHOD("set_layer_dropshadow_enabled", "layer", "enabled"), &TileMap::set_layer_dropshadow_enabled);
ClassDB::bind_method(D_METHOD("is_layer_dropshadow_enabled", "layer"), &TileMap::is_layer_dropshadow_enabled);

ClassDB::bind_method(D_METHOD("set_layer_dropshadow_offset", "layer", "offset"), &TileMap::set_layer_dropshadow_offset);
ClassDB::bind_method(D_METHOD("get_layer_dropshadow_offset", "layer"), &TileMap::get_layer_dropshadow_offset);

ClassDB::bind_method(D_METHOD("set_layer_dropshadow_color", "layer", "color"), &TileMap::set_layer_dropshadow_mod_color);
ClassDB::bind_method(D_METHOD("get_layer_dropshadow_mod_color", "layer"), &TileMap::get_layer_dropshadow_mod_color);

ClassDB::bind_method(D_METHOD("set_collision_animatable", "enabled"), &TileMap::set_collision_animatable);
ClassDB::bind_method(D_METHOD("is_collision_animatable"), &TileMap::is_collision_animatable);
ClassDB::bind_method(D_METHOD("set_collision_visibility_mode", "collision_visibility_mode"), &TileMap::set_collision_visibility_mode);
Expand Down Expand Up @@ -1018,6 +1051,9 @@ TileMap::TileMap() {
base_property_helper.register_property(PropertyInfo(Variant::INT, "y_sort_origin", PROPERTY_HINT_NONE, "suffix:px"), defaults->get_y_sort_origin(), &TileMap::set_layer_y_sort_origin, &TileMap::get_layer_y_sort_origin);
base_property_helper.register_property(PropertyInfo(Variant::INT, "z_index"), defaults->get_z_index(), &TileMap::set_layer_z_index, &TileMap::get_layer_z_index);
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "navigation_enabled"), defaults->is_navigation_enabled(), &TileMap::set_layer_navigation_enabled, &TileMap::is_layer_navigation_enabled);
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "dropshadow_enabled"), defaults->is_dropshadow_enabled(), &TileMap::set_layer_dropshadow_enabled, &TileMap::is_layer_dropshadow_enabled);
base_property_helper.register_property(PropertyInfo(Variant::VECTOR2I, "dropshadow_offset"), defaults->get_dropshadow_offset(), &TileMap::set_layer_dropshadow_offset, &TileMap::get_layer_dropshadow_offset);
base_property_helper.register_property(PropertyInfo(Variant::COLOR, "dropshadow_color"), defaults->get_dropshadow_mod_color(), &TileMap::set_layer_dropshadow_mod_color, &TileMap::get_layer_dropshadow_mod_color);
base_property_helper.register_property(PropertyInfo(Variant::PACKED_INT32_ARRAY, "tile_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), Vector<int>(), &TileMap::_set_layer_tile_data, &TileMap::_get_tile_map_data_using_compatibility_format);
PropertyListHelper::register_base_helper(&base_property_helper);

Expand Down
9 changes: 9 additions & 0 deletions scene/2d/tile_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ class TileMap : public Node2D {
void set_layer_navigation_map(int p_layer, RID p_map);
RID get_layer_navigation_map(int p_layer) const;

void set_layer_dropshadow_enabled(int p_layer, bool p_enabled);
bool is_layer_dropshadow_enabled(int p_layer) const;

void set_layer_dropshadow_offset(int p_layer, Vector2i p_offset);
Vector2i get_layer_dropshadow_offset(int p_layer) const;

void set_layer_dropshadow_mod_color(int p_layer, Color p_color);
Color get_layer_dropshadow_mod_color(int p_layer) const;

void set_collision_animatable(bool p_collision_animatable);
bool is_collision_animatable() const;

Expand Down
83 changes: 81 additions & 2 deletions scene/2d/tile_map_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,8 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
// If so, recreate everything.
bool quadrant_shape_changed = dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_TILE_SET] ||
(is_y_sort_enabled() && (dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] || dirty.flags[DIRTY_FLAGS_LAYER_X_DRAW_ORDER_REVERSED] || dirty.flags[DIRTY_FLAGS_LAYER_LOCAL_TRANSFORM])) ||
(!is_y_sort_enabled() && dirty.flags[DIRTY_FLAGS_LAYER_RENDERING_QUADRANT_SIZE]);
(!is_y_sort_enabled() && dirty.flags[DIRTY_FLAGS_LAYER_RENDERING_QUADRANT_SIZE]) ||
dirty.flags[DIRTY_FLAGS_LAYER_DROPSHADOW_CHANGED];

// Free all quadrants.
if (forced_cleanup || quadrant_shape_changed) {
Expand Down Expand Up @@ -280,6 +281,7 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
Ref<Material> prev_material;
int prev_z_index = 0;
RID prev_ci;
RID prev_dropshadow;

for (SelfList<CellData> *cell_data_quadrant_list_element = rendering_quadrant->cells.first(); cell_data_quadrant_list_element; cell_data_quadrant_list_element = cell_data_quadrant_list_element->next()) {
CellData &cell_data = *cell_data_quadrant_list_element->self();
Expand All @@ -301,9 +303,10 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {

// --- CanvasItems ---
RID ci;
RID dropshadow_ci;

// Check if the material or the z_index changed.
if (prev_ci == RID() || prev_material != mat || prev_z_index != tile_z_index) {
if (prev_ci == RID() || dropshadow_ci == RID() || prev_material != mat || prev_z_index != tile_z_index) {
// If so, create a new CanvasItem.
ci = rs->canvas_item_create();
if (needs_set_not_interpolated) {
Expand All @@ -325,15 +328,42 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(get_texture_filter_in_tree()));
rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(get_texture_repeat_in_tree()));

if (render_dropshadow) { // DROP SHADOW SETUP LOGIC START
dropshadow_ci = rs->canvas_item_create();
if (mat.is_valid()) {
rs->canvas_item_set_material(dropshadow_ci, mat->get_rid());
}
rs->canvas_item_set_parent(dropshadow_ci, get_canvas_item());
rs->canvas_item_set_use_parent_material(dropshadow_ci, !mat.is_valid());
Transform2D ds_xform(0, rendering_quadrant->canvas_items_position);

rs->canvas_item_set_transform(dropshadow_ci, xform);

rs->canvas_item_set_light_mask(dropshadow_ci, get_light_mask());

rs->canvas_item_set_z_as_relative_to_parent(dropshadow_ci, true);
rs->canvas_item_set_draw_behind_parent(dropshadow_ci, true);
rs->canvas_item_set_z_index(dropshadow_ci, tile_z_index - 1);

rs->canvas_item_set_default_texture_filter(dropshadow_ci, RS::CanvasItemTextureFilter(get_texture_filter_in_tree()));
rs->canvas_item_set_default_texture_repeat(dropshadow_ci, RS::CanvasItemTextureRepeat(get_texture_repeat_in_tree()));

rs->canvas_item_set_modulate(dropshadow_ci, dropshadow_modulate_color);

rendering_quadrant->canvas_items.push_back(dropshadow_ci);
} // DROP SHADOW SETUP LOGIC END

rendering_quadrant->canvas_items.push_back(ci);

prev_ci = ci;
prev_dropshadow = dropshadow_ci;
prev_material = mat;
prev_z_index = tile_z_index;

} else {
// Keep the same canvas_item to draw on.
ci = prev_ci;
dropshadow_ci = prev_dropshadow;
}

const Vector2 local_tile_pos = tile_set->map_to_local(cell_data.coords);
Expand All @@ -347,6 +377,11 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
random_animation_offset = RandomPCG(to_hash.hash()).randf();
}

// Drawing the dropshadow first, if it's available.
if (dropshadow_ci != RID()) {
draw_tile(dropshadow_ci, local_tile_pos - rendering_quadrant->canvas_items_position + dropshadow_offset, 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);
}

// Drawing the tile in the canvas item.
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);
}
Expand Down Expand Up @@ -1840,6 +1875,15 @@ void TileMapLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_navigation_visibility_mode", "show_navigation"), &TileMapLayer::set_navigation_visibility_mode);
ClassDB::bind_method(D_METHOD("get_navigation_visibility_mode"), &TileMapLayer::get_navigation_visibility_mode);

ClassDB::bind_method(D_METHOD("set_dropshadow_enabled", "enabled"), &TileMapLayer::set_dropshadow_enabled);
ClassDB::bind_method(D_METHOD("is_dropshadow_enabled"), &TileMapLayer::is_dropshadow_enabled);

ClassDB::bind_method(D_METHOD("set_dropshadow_offset", "offset"), &TileMapLayer::set_dropshadow_offset);
ClassDB::bind_method(D_METHOD("get_dropshadow_offset"), &TileMapLayer::get_dropshadow_offset);

ClassDB::bind_method(D_METHOD("set_dropshadow_color", "color"), &TileMapLayer::set_dropshadow_mod_color);
ClassDB::bind_method(D_METHOD("get_dropshadow_color"), &TileMapLayer::get_dropshadow_mod_color);

GDVIRTUAL_BIND(_use_tile_data_runtime_update, "coords");
GDVIRTUAL_BIND(_tile_data_runtime_update, "coords", "tile_data");

Expand All @@ -1859,6 +1903,11 @@ void TileMapLayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "navigation_enabled"), "set_navigation_enabled", "is_navigation_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_visibility_mode", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_navigation_visibility_mode", "get_navigation_visibility_mode");

ADD_GROUP("Dropshadow", "dropshadow_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dropshadow_enabled"), "set_dropshadow_enabled", "is_dropshadow_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dropshadow_offset"), "set_dropshadow_offset", "get_dropshadow_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dropshadow_modulate_color"), "set_dropshadow_color", "get_dropshadow_color");

ADD_SIGNAL(MethodInfo(CoreStringName(changed)));

ADD_PROPERTY_DEFAULT("tile_map_data_format", TileMapDataFormat::TILE_MAP_DATA_FORMAT_1);
Expand Down Expand Up @@ -3040,6 +3089,36 @@ TileMapLayer::DebugVisibilityMode TileMapLayer::get_navigation_visibility_mode()
return navigation_visibility_mode;
}

void TileMapLayer::set_dropshadow_enabled(bool p_enabled) {
bool changed = p_enabled != render_dropshadow;
render_dropshadow = p_enabled;
if (changed) {
dirty.flags[DIRTY_FLAGS_LAYER_DROPSHADOW_CHANGED] = true;
_queue_internal_update();
emit_signal(CoreStringName(changed));
}
}

void TileMapLayer::set_dropshadow_offset(Vector2i p_offset) {
bool changed = p_offset != dropshadow_offset;
dropshadow_offset = p_offset;
if (changed) {
dirty.flags[DIRTY_FLAGS_LAYER_DROPSHADOW_CHANGED] = true;
_queue_internal_update();
emit_signal(CoreStringName(changed));
}
}

void TileMapLayer::set_dropshadow_mod_color(Color p_color) {
bool changed = dropshadow_modulate_color != p_color;
dropshadow_modulate_color = p_color;
if (changed) {
dirty.flags[DIRTY_FLAGS_LAYER_DROPSHADOW_CHANGED] = true;
_queue_internal_update();
emit_signal(CoreStringName(changed));
}
}

TileMapLayer::TileMapLayer() {
set_notify_transform(true);
}
Expand Down
14 changes: 14 additions & 0 deletions scene/2d/tile_map_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ class TileMapLayer : public Node2D {
DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED,
DIRTY_FLAGS_LAYER_NAVIGATION_MAP,
DIRTY_FLAGS_LAYER_NAVIGATION_VISIBILITY_MODE,
DIRTY_FLAGS_LAYER_DROPSHADOW_CHANGED,
DIRTY_FLAGS_LAYER_RUNTIME_UPDATE,

DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE, // For compatibility.
Expand Down Expand Up @@ -299,6 +300,10 @@ class TileMapLayer : public Node2D {
TileMap *tile_map_node = nullptr;
int layer_index_in_tile_map_node = -1;

bool render_dropshadow = true;
Vector2i dropshadow_offset = Vector2i(8, 8);
Color dropshadow_modulate_color = Color(0.0, 0.0, 0.0, 0.25);

// Dirty flag. Allows knowing what was modified since the last update.
struct {
bool flags[DIRTY_FLAGS_MAX] = { false };
Expand Down Expand Up @@ -506,6 +511,15 @@ class TileMapLayer : public Node2D {
void set_navigation_visibility_mode(DebugVisibilityMode p_show_navigation);
DebugVisibilityMode get_navigation_visibility_mode() const;

void set_dropshadow_enabled(bool p_enabled);
inline bool is_dropshadow_enabled() const { return render_dropshadow; }

void set_dropshadow_offset(Vector2i p_offset);
inline Vector2i get_dropshadow_offset() const { return dropshadow_offset; }

void set_dropshadow_mod_color(Color p_color);
inline Color get_dropshadow_mod_color() const { return dropshadow_modulate_color; }

TileMapLayer();
~TileMapLayer();
};
Expand Down

0 comments on commit d0db0cd

Please sign in to comment.