diff --git a/addons/gaea/modifiers/modifier.gd b/addons/gaea/modifiers/modifier.gd index ff414a47..e2c2c906 100644 --- a/addons/gaea/modifiers/modifier.gd +++ b/addons/gaea/modifiers/modifier.gd @@ -3,24 +3,29 @@ class_name Modifier extends Resource ##@tutorial(Modifiers): https://benjatk.github.io/Gaea/#/modifiers -enum FilterType { NONE, BLACKLIST, WHITELIST } ## Won't apply any filtering. ## The modifier won't affect the [TileInfo]s in any of the [param check_for_in_layers] whose [param id] can be found in [param filter_ids]. ## The modifier will ONLY affect the [TileInfo]s in any of the [param check_for_in_layers] whose [param id] can be found in [param filter_ids]. +enum FilterType { + NONE, ## Won't apply any filtering. + BLACKLIST, ## The modifier won't affect the [TileInfo]s in any of the [param layers] whose [param id] can be found in [param ids]. + WHITELIST, ## The modifier will ONLY affect the [TileInfo]s in any of the [param layers] whose [param id] can be found in [param ids]. + ONLY_EMPTY_CELLS ## The modifier will ONLY affect empty ([code]null[/code]) cells. +} @export_group("") @export var enabled: bool = true @export var affected_layers: Array[int] = [0] -@export_group("Filters", "filter_") +@export_group("Filtering", "filter_") ## [i]Note: Some modifiers don't support filtering.[/i] @export var filter_type: FilterType = FilterType.NONE: set(value): filter_type = value notify_property_list_changed() -## All layers the filter should check for to find the ids in [param check_for_ids].[br][br] -## [b]E.g:[/b] If a NoisePainter wants to place a tile in (0, 0), and the filter type is WHITELIST, it checks that -## there's at least one tile in (0, 0) in any of the layers whose id can be found in [param check_for_ids]. -@export var filter_check_for_in_layers: Array[int] = [] ## An array containing ids that will be used ## to filter the modifier. -@export var filter_check_for_ids: Array[String] = [] +@export var filter_ids: Array[String] = [] +## All layers the filter should check in for the other filtering options. +## [b]E.g:[/b] If a NoisePainter wants to place a tile in (0, 0), and the filter type is WHITELIST, it checks that +## there's at least one tile in (0, 0) in any of the layers whose id can be found in [param check_for_ids]. +@export var filter_layers: Array[int] = [] func apply(grid: GaeaGrid, generator: GaeaGenerator) -> void: @@ -33,14 +38,26 @@ func _passes_filter(grid: GaeaGrid, cell) -> bool: if filter_type == FilterType.NONE: return true - for layer in filter_check_for_in_layers: + if filter_type == FilterType.ONLY_EMPTY_CELLS: + for layer in grid.get_layer_count(): + if grid.get_value(cell, layer) != null: + return false + return true + + var layers: Array = filter_layers + if layers.is_empty(): + layers = grid.get_grid().keys() + + for layer in layers: var value = grid.get_value(cell, layer) - if value is TileInfo and value.id in filter_check_for_ids: + if value is TileInfo and value.id in filter_ids: return filter_type == FilterType.WHITELIST return filter_type == FilterType.BLACKLIST func _validate_property(property: Dictionary) -> void: - if property.name.begins_with("filter_check") and filter_type == FilterType.NONE: + if (property.name == "filter_ids" or property.name == "filter_layers") and filter_type == FilterType.NONE: + property.usage = PROPERTY_USAGE_NONE + elif property.name == "filter_ids" and filter_type == FilterType.ONLY_EMPTY_CELLS: property.usage = PROPERTY_USAGE_NONE diff --git a/docs/modifiers.md b/docs/modifiers.md index 74c4e970..47586e23 100644 --- a/docs/modifiers.md +++ b/docs/modifiers.md @@ -1,9 +1,21 @@ # Modifiers -**Modifiers** are similar to those in software like Blender. You add these to your GeneratorSettings, and they get applied after the generation is finished, giving you varied results and possibilities. +**Modifiers** are similar to those in software like Blender. You add these to your GeneratorSettings, and they get applied after the generation is finished, giving you varied results and possibilities. You can think of them this way: each cell in the grid is checked, and if it meets a certain condition, it will get modified (deleted, replaced with another `TileInfo` or a `TileInfo` will be placed in the same spot on a different layer). > **NOTE**: In Gaea, the modifiers' array order matters. Modifiers get applied in this order, so different sequences can give different results. +## Filtering + +Modifiers can be filtered. This means it will only modify certain tiles. + +`filter_type`: can be NONE, BLACKLIST, WHITELIST, or ONLY_EMPTY_CELLS. + +`filter_ids`: in BLACKLIST, it will NOT attempt to modify tiles with an `id` that can be found in this list (`id`s are strings that make identifying `TileInfo`s easier, see [Gaea's Resources](resources.md)). WHITELIST will invert this logic. _For example, using a `NoisePainter` to only place gold ore in tiles with the `id` "stone"._ + +`filter_layers`: it will only check in these layers for the `id`s mentioned above or, if `filter_type` is ONLY_EMPTY_CELLS, for an empty cell. Leaving this array empty, the filtering will check for all layers. + +## List + There are a few modifiers in Gaea at the moment: ### Generate Borders diff --git a/docs/resources.md b/docs/resources.md index d5a315db..cdff25be 100644 --- a/docs/resources.md +++ b/docs/resources.md @@ -6,6 +6,12 @@ Gaea takes advantage of Godot's **resources**. In this addon, they're used for t Probably the most important resource in Gaea, it holds a dictionary of cells and their values, filled by the various generators found in the add-on. It can be easily saved using various methods, which means you can keep the world you generated without problem. +## TileInfo +This resource is stored in a certain position in the generator's grid. The base class is empty, but the subclasses such as `TilemapTileInfo` contain data that the renderer takes and uses to draw the grid. + +`id`: A string value that represents your `TileInfo`. (e.g "grass"). This is used for filtering modifiers and more.\ +`layer`: The `GaeaGrid` layer the TileInfo will be placed on. If it doesn't exist yet, it will automatically be created. + ## GeneratorSettings Each generator has a unique `GeneratorSettings` resource, which includes variables like world size, rules, and the modifiers that will be applied to your generation. @@ -14,5 +20,3 @@ You can use these resources to create different world types, floors for a roguel ## Modifiers Modifiers take the generation and change it algorithmically, similar to how Blender's modifiers work. They're non-destructive, meaning you can remove them, change their order, etc. without worrying about breaking your generator. -## TileInfo -This resource is stored in a certain position in the generator's grid. The base class is empty, but the subclasses such as `TilemapTileInfo` contain data that the renderer takes and uses to draw the grid. diff --git a/scenes/demos/heightmap/terraria-like_generation_settings.tres b/scenes/demos/heightmap/terraria-like_generation_settings.tres index 31114771..3f175813 100644 --- a/scenes/demos/heightmap/terraria-like_generation_settings.tres +++ b/scenes/demos/heightmap/terraria-like_generation_settings.tres @@ -7,13 +7,14 @@ [ext_resource type="Script" path="res://addons/gaea/generators/2D/heightmap_generator/heightmap_generator_2d_settings.gd" id="5_haojk"] [sub_resource type="Resource" id="Resource_6kmi4"] +resource_name = "Stone" script = ExtResource("2_6f082") type = 0 tilemap_layer = 0 source_id = 1 atlas_coord = Vector2i(0, 0) alternative_tile = 0 -id = "" +id = "stone" layer = 0 [sub_resource type="Resource" id="Resource_pu43q"] @@ -52,7 +53,7 @@ filter_type = 0 [sub_resource type="FastNoiseLite" id="FastNoiseLite_1mckf"] noise_type = 3 -seed = -319710493 +seed = 1045566220 frequency = 0.012 fractal_type = 2 fractal_octaves = 3 @@ -73,7 +74,7 @@ affected_layers = Array[int]([0]) filter_type = 0 [sub_resource type="FastNoiseLite" id="FastNoiseLite_kyspj"] -seed = -879214990 +seed = 486061723 frequency = 0.0617 fractal_octaves = 2 fractal_lacunarity = 2.95 @@ -101,10 +102,12 @@ bounds_max = Vector2(0, 0) bounds_min = Vector2(0, 0) salt = 1908549200 enabled = true -filter_type = 0 +filter_type = 2 +filter_ids = Array[String](["stone"]) +filter_layers = Array[int]([]) [sub_resource type="FastNoiseLite" id="FastNoiseLite_vkmxs"] -seed = -885391533 +seed = 479885180 frequency = 0.0511 fractal_lacunarity = 0.565 domain_warp_type = 2 @@ -133,11 +136,13 @@ bounds_max = Vector2(0, 0) bounds_min = Vector2(0, 0) salt = 1902372657 enabled = true -filter_type = 0 +filter_type = 2 +filter_ids = Array[String](["stone"]) +filter_layers = Array[int]([]) [sub_resource type="FastNoiseLite" id="FastNoiseLite_mwtbk"] noise_type = 3 -seed = 1507203106 +seed = -1422487477 [sub_resource type="Resource" id="Resource_hitrj"] script = ExtResource("2_6f082")