From 16699e7b5fd878bbbdac384751b69b64152a4b98 Mon Sep 17 00:00:00 2001 From: Relintai Date: Tue, 12 Mar 2024 00:50:47 +0100 Subject: [PATCH] Implemented RAO for LayeredTileMaps. --- modules/layered_tile_map/layered_tile_map.cpp | 140 ++++++++++++++++-- modules/layered_tile_map/layered_tile_map.h | 30 ++++ .../layered_tile_map_layer.cpp | 63 ++++++++ .../layered_tile_map/layered_tile_map_layer.h | 31 +++- modules/layered_tile_map/layered_tile_set.cpp | 3 +- 5 files changed, 256 insertions(+), 11 deletions(-) diff --git a/modules/layered_tile_map/layered_tile_map.cpp b/modules/layered_tile_map/layered_tile_map.cpp index 765752af01..681fa7e1c2 100644 --- a/modules/layered_tile_map/layered_tile_map.cpp +++ b/modules/layered_tile_map/layered_tile_map.cpp @@ -184,21 +184,21 @@ void LayeredTileMap::draw_tile(RID p_canvas_item, const Vector2 &p_position, con real_t speed = atlas_source->get_tile_animation_speed(p_atlas_coords); Array anim_data; - + for (int frame = 0; frame < atlas_source->get_tile_animation_frames_count(p_atlas_coords); frame++) { real_t frame_duration_scaled = atlas_source->get_tile_animation_frame_duration(p_atlas_coords, frame) * speed; - + RID tex_rid = tex.is_valid() ? tex->get_rid() : RID(); //RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID normal_rid = RID(); - + 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, Ref(), p_tile_set->is_uv_clipping()); - + Array d; d.resize(8); - + //real_t frame_time = d[0]; //Rect2 tex_rect = d[1]; //const Rect2 &p_rect //rect->texture = d[2]; //RID p_texture @@ -207,7 +207,7 @@ void LayeredTileMap::draw_tile(RID p_canvas_item, const Vector2 &p_position, con //bool transpose = d[5]; //bool p_transpose = false //rect->normal_map = d[6]; //RID p_normal_map = RID() //bool clip_uv = d[7]; //bool p_clip_uv = false - + d[0] = frame_duration_scaled; d[1] = dest_rect; d[2] = tex_rid; @@ -219,9 +219,9 @@ void LayeredTileMap::draw_tile(RID p_canvas_item, const Vector2 &p_position, con anim_data.push_back(d); } - + bool random_start_time = atlas_source->get_tile_animation_mode(p_atlas_coords) == LayeredTileSetAtlasSource::TILE_ANIMATION_MODE_RANDOM_START_TIMES; - + RenderingServer::get_singleton()->canvas_item_add_texture_rect_animation(p_canvas_item, anim_data, random_start_time); } } @@ -496,6 +496,106 @@ void LayeredTileMap::set_cells_terrain_path(int p_layer, PoolVector2iArray p_pat TILEMAP_CALL_FOR_LAYER(p_layer, set_cells_terrain_path, p_path, p_terrain_set, p_terrain, p_ignore_empty_terrains); } +//RAO +#ifdef MODULE_FASTNOISE_ENABLED +void LayeredTileMap::rao_set_use(bool p_rao) { + if (_use_rao == p_rao) { + return; + } + + _use_rao = p_rao; + + if (!_use_rao) { + for (uint32_t i = 0; i < layers.size(); ++i) { + LayeredTileMapLayer *layer = layers[i]; + + layer->set_rao_noise(Ref()); + } + + } else { + if (_noise_params.is_valid()) { + if (!_rao_noise.is_valid()) { + _rao_noise.instance(); + } + + rao_setup_noise(_rao_noise); + } else { + _rao_noise.unref(); + } + + for (uint32_t i = 0; i < layers.size(); ++i) { + LayeredTileMapLayer *layer = layers[i]; + + layer->set_rao_noise(_rao_noise); + } + } + + _emit_changed(); +} +bool LayeredTileMap::rao_get_use() const { + return _use_rao; +} + +void LayeredTileMap::rao_set_noise_params(const Ref &noise) { + if (_noise_params == noise) { + return; + } + + _noise_params = noise; + + if (!_use_rao) { + for (uint32_t i = 0; i < layers.size(); ++i) { + LayeredTileMapLayer *layer = layers[i]; + + layer->set_rao_noise(Ref()); + } + } else { + if (_noise_params.is_valid()) { + if (!_rao_noise.is_valid()) { + _rao_noise.instance(); + } + + rao_setup_noise(_rao_noise); + } else { + _rao_noise.unref(); + } + + for (uint32_t i = 0; i < layers.size(); ++i) { + LayeredTileMapLayer *layer = layers[i]; + + layer->set_rao_noise(_rao_noise); + } + } + + _emit_changed(); +} + +void LayeredTileMap::rao_set_strength(const real_t p_strength) { + _rao_strength = p_strength; + + for (uint32_t i = 0; i < layers.size(); ++i) { + LayeredTileMapLayer *layer = layers[i]; + + layer->set_rao_strength(p_strength); + } + + _emit_changed(); +} +real_t LayeredTileMap::rao_get_strength() const { + return _rao_strength; +} + +Ref LayeredTileMap::rao_get_noise_params() { + return _noise_params; +} + +void LayeredTileMap::rao_setup_noise(Ref noise) { + if (_noise_params.is_valid()) { + _noise_params->setup_noise(noise); + } +} +#endif + LayeredTileMapCell LayeredTileMap::get_cell(int p_layer, const Vector2i &p_coords, bool p_use_proxies) const { TILEMAP_CALL_FOR_LAYER_V(p_layer, LayeredTileMapCell(), get_cell, p_coords, p_use_proxies); } @@ -1046,6 +1146,23 @@ void LayeredTileMap::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_visibility_mode", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_collision_visibility_mode", "get_collision_visibility_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_visibility_mode", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_navigation_visibility_mode", "get_navigation_visibility_mode"); + //RAO +#ifdef MODULE_FASTNOISE_ENABLED + ADD_GROUP("RAO", "rao"); + + ClassDB::bind_method(D_METHOD("rao_set_use", "value"), &LayeredTileMap::rao_set_use); + ClassDB::bind_method(D_METHOD("rao_get_use"), &LayeredTileMap::rao_get_use); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rao_use"), "rao_set_use", "rao_get_use"); + + ClassDB::bind_method(D_METHOD("rao_set_strength", "value"), &LayeredTileMap::rao_set_strength); + ClassDB::bind_method(D_METHOD("rao_get_strength"), &LayeredTileMap::rao_get_strength); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "rao_strength"), "rao_set_strength", "rao_get_strength"); + + ClassDB::bind_method(D_METHOD("rao_set_noise_params", "noise"), &LayeredTileMap::rao_set_noise_params); + ClassDB::bind_method(D_METHOD("rao_get_noise_params"), &LayeredTileMap::rao_get_noise_params); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "rao_noise", PROPERTY_HINT_RESOURCE_TYPE, "FastnoiseNoiseParams"), "rao_set_noise_params", "rao_get_noise_params"); +#endif + ADD_ARRAY("layers", "layer_"); ADD_PROPERTY_DEFAULT("format", LayeredTileMapDataFormat::FORMAT_1); @@ -1066,6 +1183,11 @@ LayeredTileMap::LayeredTileMap() { new_layer->connect(CoreStringNames::get_singleton()->changed, this, "_emit_changed"); layers.push_back(new_layer); default_layer = memnew(LayeredTileMapLayer); + +#ifdef MODULE_FASTNOISE_ENABLED + _use_rao = true; + _rao_strength = 0.3; +#endif } LayeredTileMap::~LayeredTileMap() { diff --git a/modules/layered_tile_map/layered_tile_map.h b/modules/layered_tile_map/layered_tile_map.h index 21ab48d7ab..f6d0536c28 100644 --- a/modules/layered_tile_map/layered_tile_map.h +++ b/modules/layered_tile_map/layered_tile_map.h @@ -35,6 +35,13 @@ #include "layered_tile_map_layer_group.h" #include "layered_tile_set.h" +#include "modules/modules_enabled.gen.h" + +#ifdef MODULE_FASTNOISE_ENABLED +#include "modules/fastnoise/fastnoise_noise_params.h" +#include "modules/fastnoise/noise.h" +#endif + class Control; class LayeredTileMapLayer; class TerrainConstraint; @@ -79,6 +86,15 @@ class LayeredTileMap : public LayeredTileMapLayerGroup { Transform2D last_valid_transform; Transform2D new_transform; + //RAO +#ifdef MODULE_FASTNOISE_ENABLED + bool _use_rao; + real_t _rao_strength; + Ref _noise_params; + + Ref _rao_noise; +#endif + void _emit_changed(); protected: @@ -162,6 +178,20 @@ class LayeredTileMap : public LayeredTileMapLayerGroup { void set_cells_terrain_connect(int p_layer, PoolVector2iArray p_cells, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); void set_cells_terrain_path(int p_layer, PoolVector2iArray p_path, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); + //RAO +#ifdef MODULE_FASTNOISE_ENABLED + void rao_set_use(bool p_rao); + bool rao_get_use() const; + + void rao_set_strength(const real_t p_strength); + real_t rao_get_strength() const; + + void rao_set_noise_params(const Ref &noise); + Ref rao_get_noise_params(); + + void rao_setup_noise(Ref noise); +#endif + // Not exposed to users. LayeredTileMapCell get_cell(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const; int get_effective_quadrant_size(int p_layer) const; diff --git a/modules/layered_tile_map/layered_tile_map_layer.cpp b/modules/layered_tile_map/layered_tile_map_layer.cpp index e427f88b08..8387f89578 100644 --- a/modules/layered_tile_map/layered_tile_map_layer.cpp +++ b/modules/layered_tile_map/layered_tile_map_layer.cpp @@ -358,7 +358,25 @@ void LayeredTileMapLayer::_rendering_update() { } // Drawing the tile in the canvas item. + + //RAO +#ifdef MODULE_FASTNOISE_ENABLED + if (_rao_noise.is_valid()) { + float col = (static_cast(cell_data.rao) / 255.0) * _rao_strength; + + Color modulate = get_modulate(); + Color self_modulate = get_self_modulate(); + + Color m = Color(modulate.r * self_modulate.r - col, modulate.g * self_modulate.g - col, modulate.b * self_modulate.b - col, modulate.a * self_modulate.a); + + LayeredTileMap::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, m, tile_data, random_animation_offset); + } else { + LayeredTileMap::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); + } +#else LayeredTileMap::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); + +#endif } } else { // Free the quadrant. @@ -407,6 +425,8 @@ void LayeredTileMapLayer::_rendering_update() { for (List::Element *ci = rendering_quadrant->canvas_items.front(); ci; ci = ci->next()) { rs->canvas_item_set_light_mask(ci->get(), get_light_mask()); + + rs->canvas_item_set_self_modulate(ci->get(), get_self_modulate()); rs->canvas_item_set_self_modulate(ci->get(), get_self_modulate()); } } @@ -503,6 +523,16 @@ void LayeredTileMapLayer::_rendering_quadrants_update_cell(CellData &r_cell_data canvas_items_position = tile_set->map_to_local(rendering_quadrant_size * quadrant_coords); } +#ifdef MODULE_FASTNOISE_ENABLED + if (dirty.flags[DIRTY_FLAGS_LAYER_RAO]) { + if (_rao_noise.is_valid()) { + r_cell_data.rao = static_cast(static_cast(CLAMP(_rao_noise->get_noise_2d(r_cell_data.coords.x, r_cell_data.coords.y), 0, 1) * 255.0) % 255); + } else { + r_cell_data.rao = 0; + } + } +#endif + Ref rendering_quadrant; if (rendering_quadrant_map.has(quadrant_coords)) { // Reuse existing rendering quadrant. @@ -2802,6 +2832,35 @@ LayeredTileMapLayer::VisibilityMode LayeredTileMapLayer::get_navigation_visibili return navigation_visibility_mode; } +//RAO +#ifdef MODULE_FASTNOISE_ENABLED +Ref LayeredTileMapLayer::get_rao_noise() { + return _rao_noise; +} +void LayeredTileMapLayer::set_rao_noise(const Ref &noise) { + // Don't check if they are the same! + _rao_noise = noise; + + dirty.flags[DIRTY_FLAGS_LAYER_RAO] = true; + + _queue_internal_update(); + emit_signal(CoreStringNames::get_singleton()->changed); +} + +void LayeredTileMapLayer::set_rao_strength(const real_t p_strength) { + _rao_strength = p_strength; + + dirty.flags[DIRTY_FLAGS_LAYER_RAO] = true; + + _queue_internal_update(); + emit_signal(CoreStringNames::get_singleton()->changed); +} +real_t LayeredTileMapLayer::get_rao_strength() const { + return _rao_strength; +} + +#endif + void LayeredTileMapLayer::fix_invalid_tiles() { Ref tileset = get_effective_tile_set(); ERR_FAIL_COND_MSG(tileset.is_null(), "Cannot call fix_invalid_tiles() on a LayeredTileMap without a valid LayeredTileSet."); @@ -2845,6 +2904,10 @@ void LayeredTileMapLayer::tile_data_runtime_update(const Vector2i &p_coords, Lay LayeredTileMapLayer::LayeredTileMapLayer() { set_notify_transform(true); + +#ifdef MODULE_FASTNOISE_ENABLED + _rao_strength = 0.3; +#endif } LayeredTileMapLayer::~LayeredTileMapLayer() { diff --git a/modules/layered_tile_map/layered_tile_map_layer.h b/modules/layered_tile_map/layered_tile_map_layer.h index 7f3b0fbba1..cd352c9417 100644 --- a/modules/layered_tile_map/layered_tile_map_layer.h +++ b/modules/layered_tile_map/layered_tile_map_layer.h @@ -32,10 +32,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "layered_tile_set.h" #include "layered_tile_map.h" +#include "layered_tile_set.h" #include "scene/2d/y_sort.h" +#include "modules/modules_enabled.gen.h" + +#ifdef MODULE_FASTNOISE_ENABLED +#include "../fastnoise/noise.h" +#endif + class LayeredTileSetAtlasSource; class TerrainConstraint { @@ -99,6 +105,10 @@ struct CellData { Vector2i coords; LayeredTileMapCell cell; +#ifdef MODULE_FASTNOISE_ENABLED + uint8_t rao; +#endif + // Debug. SelfList debug_quadrant_list_element; @@ -247,6 +257,10 @@ class LayeredTileMapLayer : public YSort { DIRTY_FLAGS_LAYER_NAVIGATION_VISIBILITY_MODE, DIRTY_FLAGS_LAYER_RUNTIME_UPDATE, +#ifdef MODULE_FASTNOISE_ENABLED + DIRTY_FLAGS_LAYER_RAO, +#endif + DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE, // For compatibility. DIRTY_FLAGS_LAYER_GROUP_SELECTED_LAYERS, @@ -277,6 +291,12 @@ class LayeredTileMapLayer : public YSort { LayeredTileMap *tile_map_node = nullptr; int layer_index_in_tile_map_node = -1; + //RAO +#ifdef MODULE_FASTNOISE_ENABLED + real_t _rao_strength; + Ref _rao_noise; +#endif + // Dirty flag. Allows knowing what was modified since the last update. struct { bool flags[DIRTY_FLAGS_MAX] = { false }; @@ -434,6 +454,15 @@ class LayeredTileMapLayer : public YSort { void set_navigation_visibility_mode(VisibilityMode p_show_navigation); VisibilityMode get_navigation_visibility_mode() const; + //RAO +#ifdef MODULE_FASTNOISE_ENABLED + Ref get_rao_noise(); + void set_rao_noise(const Ref &noise); + + void set_rao_strength(const real_t p_strength); + real_t get_rao_strength() const; +#endif + // Fixing and clearing methods. void fix_invalid_tiles(); diff --git a/modules/layered_tile_map/layered_tile_set.cpp b/modules/layered_tile_map/layered_tile_set.cpp index a036205c44..036e312369 100644 --- a/modules/layered_tile_map/layered_tile_set.cpp +++ b/modules/layered_tile_map/layered_tile_set.cpp @@ -1508,6 +1508,7 @@ LayeredTileMapCell LayeredTileSet::get_random_tile_from_terrains_pattern(int p_t ERR_FAIL_V(LayeredTileMapCell()); } + Vector LayeredTileSet::get_tile_shape_polygon() const { Vector points; if (tile_shape == LayeredTileSet::TILE_SHAPE_SQUARE) { @@ -2593,7 +2594,7 @@ Vector>> LayeredTileSet::generate_terrains_icons(Size2i p_si dst_image->resize(p_size.x, p_size.y, Image::INTERPOLATE_NEAREST); } else { dst_image->create(1, 1, false, Image::FORMAT_RGBA8); - + dst_image->lock(); dst_image->set_pixel(0, 0, get_terrain_color(terrain_set, terrain)); dst_image->unlock();