Implemented RAO for LayeredTileMaps.

This commit is contained in:
Relintai 2024-03-12 00:50:47 +01:00
parent 765a8ded6a
commit 16699e7b5f
5 changed files with 256 additions and 11 deletions

View File

@ -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<Texture>(), 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<FastNoise>());
}
} 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<FastnoiseNoiseParams> &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<FastNoise>());
}
} 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<FastnoiseNoiseParams> LayeredTileMap::rao_get_noise_params() {
return _noise_params;
}
void LayeredTileMap::rao_setup_noise(Ref<FastNoise> 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() {

View File

@ -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 @@ private:
Transform2D last_valid_transform;
Transform2D new_transform;
//RAO
#ifdef MODULE_FASTNOISE_ENABLED
bool _use_rao;
real_t _rao_strength;
Ref<FastnoiseNoiseParams> _noise_params;
Ref<FastNoise> _rao_noise;
#endif
void _emit_changed();
protected:
@ -162,6 +178,20 @@ public:
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<FastnoiseNoiseParams> &noise);
Ref<FastnoiseNoiseParams> rao_get_noise_params();
void rao_setup_noise(Ref<FastNoise> 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;

View File

@ -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<float>(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<RID>::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<uint8_t>(static_cast<int>(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<RenderingQuadrant> 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<FastNoise> LayeredTileMapLayer::get_rao_noise() {
return _rao_noise;
}
void LayeredTileMapLayer::set_rao_noise(const Ref<FastNoise> &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<LayeredTileSet> 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() {

View File

@ -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<CellData> debug_quadrant_list_element;
@ -247,6 +257,10 @@ public:
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 @@ private:
LayeredTileMap *tile_map_node = nullptr;
int layer_index_in_tile_map_node = -1;
//RAO
#ifdef MODULE_FASTNOISE_ENABLED
real_t _rao_strength;
Ref<FastNoise> _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 @@ public:
void set_navigation_visibility_mode(VisibilityMode p_show_navigation);
VisibilityMode get_navigation_visibility_mode() const;
//RAO
#ifdef MODULE_FASTNOISE_ENABLED
Ref<FastNoise> get_rao_noise();
void set_rao_noise(const Ref<FastNoise> &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();

View File

@ -1508,6 +1508,7 @@ LayeredTileMapCell LayeredTileSet::get_random_tile_from_terrains_pattern(int p_t
ERR_FAIL_V(LayeredTileMapCell());
}
Vector<Vector2> LayeredTileSet::get_tile_shape_polygon() const {
Vector<Vector2> points;
if (tile_shape == LayeredTileSet::TILE_SHAPE_SQUARE) {
@ -2593,7 +2594,7 @@ Vector<Vector<Ref<Texture>>> 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();