From eed5851583d38e0ff8d1484a7a5db2c2dc34557a Mon Sep 17 00:00:00 2001
From: Stan Soldatov <118521851+iwatkot@users.noreply.github.com>
Date: Mon, 6 Jan 2025 21:57:39 +0100
Subject: [PATCH] Files for procedural generation
* Procedural layers.
* README update.
---
README.md | 1 +
data/fs25-map-template.zip | Bin 2197113 -> 2200477 bytes
data/fs25-texture-schema.json | 21 ++++++++-----
maps4fs/generator/texture.py | 55 +++++++++++++++++++++++++++++++++-
4 files changed, 69 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index 337d968..9b006e7 100644
--- a/README.md
+++ b/README.md
@@ -397,6 +397,7 @@ Let's have a closer look at the fields:
- `background` - set it to True for the textures, which should have impact on the Background Terrain, by default it's used to subtract the water depth from the DEM and background terrain.
- `info_layer` - if the layer is saving some data in JSON format, this section will describe it's name in the JSON file. Used to find the needed JSON data, for example for fields it will be `fields` and as a value - list of polygon coordinates.
- `invisible` - set it to True for the textures, which should not be drawn in the files, but only to save the data in the JSON file (related to the previous field).
+- `procedural` - is a list of corresponding files, that will be used for a procedural generation. For example: `"procedural": ["PG_meadow", "PG_acres"]` - means that the texture will be used for two procedural generation files: `masks/PG_meadow.png` and `masks/PG_acres.png`. Note, that the one procuderal name can be applied to multiple textures, in this case they will be merged into one mask.
## Background terrain
The tool now supports the generation of the background terrain. If you don't know what it is, here's a brief explanation. The background terrain is the world around the map. It's important to create it because if you don't, the map will look like it's floating in the void. The background terrain is a simple plane that can (and should) be textured to look fine.
diff --git a/data/fs25-map-template.zip b/data/fs25-map-template.zip
index 98b509f741dc723e73d058ad4a3ce74052b7e78c..677c21aa69c94f3252a1da943c8037b4d1e6a18f 100644
GIT binary patch
delta 18815
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
MZYboI00&q64=aF0^Z)<=
delta 15423
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
Z9GuKj1rtaxQtcB-sGx+rNkBkA{tqkA dict[str, str | list[str] | bool]: # type: ignore
"""Returns dictionary with layer data.
@@ -99,6 +102,7 @@ def to_json(self) -> dict[str, str | list[str] | bool]: # type: ignore
"usage": self.usage,
"background": self.background,
"invisible": self.invisible,
+ "procedural": self.procedural,
}
data = {k: v for k, v in data.items() if v is not None}
@@ -212,6 +216,10 @@ def preprocess(self) -> None:
self._weights_dir = self.game.weights_dir_path(self.map_directory)
self.logger.debug("Weights directory: %s.", self._weights_dir)
+ self.procedural_dir = os.path.join(self._weights_dir, "masks")
+ os.makedirs(self.procedural_dir, exist_ok=True)
+ self.logger.debug("Procedural directory: %s.", self.procedural_dir)
+
self.info_save_path = os.path.join(self.map_directory, "generation_info.json")
self.logger.debug("Generation info save path: %s.", self.info_save_path)
@@ -251,11 +259,56 @@ def get_layer_by_usage(self, usage: str) -> Layer | None:
return layer
return None
- def process(self):
+ def process(self) -> None:
+ """Processes the data to generate textures."""
self._prepare_weights()
self._read_parameters()
self.draw()
self.rotate_textures()
+ self.copy_procedural()
+
+ def copy_procedural(self) -> None:
+ """Copies some of the textures to use them as mask for procedural generation.
+ Creates an empty blockmask if it does not exist."""
+ blockmask_path = os.path.join(self.procedural_dir, "BLOCKMASK.png")
+ if not os.path.isfile(blockmask_path):
+ self.logger.debug("BLOCKMASK.png not found, creating an empty file.")
+ img = np.zeros((self.map_size, self.map_size), dtype=np.uint8)
+ cv2.imwrite(blockmask_path, img) # pylint: disable=no-member
+
+ pg_layers_by_type = defaultdict(list)
+ for layer in self.layers:
+ if layer.procedural:
+ # Get path to the original file.
+ texture_path = layer.get_preview_or_path(self._weights_dir)
+ for procedural_layer_name in layer.procedural:
+ pg_layers_by_type[procedural_layer_name].append(texture_path)
+
+ if not pg_layers_by_type:
+ self.logger.debug("No procedural layers found.")
+ return
+
+ for procedural_layer_name, texture_paths in pg_layers_by_type.items():
+ procedural_save_path = os.path.join(self.procedural_dir, f"{procedural_layer_name}.png")
+ if len(texture_paths) > 1:
+ # If there are more than one texture, merge them.
+ merged_texture = np.zeros((self.map_size, self.map_size), dtype=np.uint8)
+ for texture_path in texture_paths:
+ # pylint: disable=E1101
+ texture = cv2.imread(texture_path, cv2.IMREAD_UNCHANGED)
+ merged_texture[texture == 255] = 255
+ cv2.imwrite(procedural_save_path, merged_texture) # pylint: disable=no-member
+ self.logger.debug(
+ "Procedural file %s merged from %s textures.",
+ procedural_save_path,
+ len(texture_paths),
+ )
+ elif len(texture_paths) == 1:
+ # Otherwise, copy the texture.
+ shutil.copyfile(texture_paths[0], procedural_save_path)
+ self.logger.debug(
+ "Procedural file %s copied from %s.", procedural_save_path, texture_paths[0]
+ )
def rotate_textures(self) -> None:
"""Rotates textures of the layers which have tags."""