maps4fs 1.9.3__py3-none-any.whl → 1.9.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- maps4fs/generator/component/background.py +11 -2
- maps4fs/generator/component/base/component.py +12 -0
- maps4fs/generator/component/grle.py +5 -0
- maps4fs/generator/component/i3d.py +6 -0
- maps4fs/generator/component/satellite.py +4 -0
- maps4fs/generator/component/texture.py +4 -1
- maps4fs/generator/game.py +8 -0
- maps4fs/generator/map.py +1 -1
- maps4fs/generator/settings.py +7 -0
- maps4fs/logger.py +1 -19
- {maps4fs-1.9.3.dist-info → maps4fs-1.9.4.dist-info}/METADATA +7 -16
- {maps4fs-1.9.3.dist-info → maps4fs-1.9.4.dist-info}/RECORD +15 -15
- {maps4fs-1.9.3.dist-info → maps4fs-1.9.4.dist-info}/WHEEL +0 -0
- {maps4fs-1.9.3.dist-info → maps4fs-1.9.4.dist-info}/licenses/LICENSE.md +0 -0
- {maps4fs-1.9.3.dist-info → maps4fs-1.9.4.dist-info}/top_level.txt +0 -0
@@ -224,6 +224,8 @@ class Background(MeshComponent, ImageComponent):
|
|
224
224
|
save_path = os.path.join(self.background_directory, f"{filename}.obj")
|
225
225
|
self.logger.debug("Generating obj file in path: %s", save_path)
|
226
226
|
|
227
|
+
self.assets.background_mesh = save_path
|
228
|
+
|
227
229
|
dem_data = cv2.imread(self.output_path, cv2.IMREAD_UNCHANGED)
|
228
230
|
|
229
231
|
if self.map.output_size is not None:
|
@@ -279,6 +281,8 @@ class Background(MeshComponent, ImageComponent):
|
|
279
281
|
cv2.imwrite(main_dem_path, resized_dem_data)
|
280
282
|
self.logger.debug("DEM cutout saved: %s", main_dem_path)
|
281
283
|
|
284
|
+
self.assets.dem = main_dem_path
|
285
|
+
|
282
286
|
return main_dem_path
|
283
287
|
|
284
288
|
def plane_from_np(
|
@@ -321,8 +325,11 @@ class Background(MeshComponent, ImageComponent):
|
|
321
325
|
self.logger.debug("Obj file saved: %s", save_path)
|
322
326
|
|
323
327
|
if create_preview:
|
324
|
-
|
325
|
-
|
328
|
+
try:
|
329
|
+
mesh.apply_scale([0.5, 0.5, 0.5])
|
330
|
+
self.mesh_to_stl(mesh, save_path=self.stl_preview_path)
|
331
|
+
except Exception as e:
|
332
|
+
self.logger.error("Could not create STL preview: %s", e)
|
326
333
|
|
327
334
|
def update_mesh_info(self, save_path: str, mesh: Trimesh) -> None:
|
328
335
|
"""Updates the mesh info with the data from the mesh.
|
@@ -587,4 +594,6 @@ class Background(MeshComponent, ImageComponent):
|
|
587
594
|
elevated_water = np.where(mask, background_dem, elevated_water)
|
588
595
|
elevated_save_path = os.path.join(self.water_directory, "elevated_water.obj")
|
589
596
|
|
597
|
+
self.assets.water_mesh = elevated_save_path
|
598
|
+
|
590
599
|
self.plane_from_np(elevated_water, elevated_save_path, include_zeros=False)
|
@@ -20,6 +20,16 @@ if TYPE_CHECKING:
|
|
20
20
|
from maps4fs.generator.map import Map
|
21
21
|
|
22
22
|
|
23
|
+
class AttrDict(dict):
|
24
|
+
"""A dictionary that allows attribute-style access to its keys."""
|
25
|
+
|
26
|
+
def __getattr__(self, name):
|
27
|
+
return self[name]
|
28
|
+
|
29
|
+
def __setattr__(self, name, value):
|
30
|
+
self[name] = value
|
31
|
+
|
32
|
+
|
23
33
|
class Component:
|
24
34
|
"""Base class for all map generation components.
|
25
35
|
|
@@ -72,6 +82,8 @@ class Component:
|
|
72
82
|
self.save_bbox()
|
73
83
|
self.preprocess()
|
74
84
|
|
85
|
+
self.assets = AttrDict()
|
86
|
+
|
75
87
|
def preprocess(self) -> None:
|
76
88
|
"""Prepares the component for processing. Must be implemented in the child class."""
|
77
89
|
return
|
@@ -263,6 +263,8 @@ class GRLE(ImageComponent, XMLComponent):
|
|
263
263
|
|
264
264
|
cv2.imwrite(info_layer_farmlands_path, image)
|
265
265
|
|
266
|
+
self.assets.farmlands = info_layer_farmlands_path
|
267
|
+
|
266
268
|
self.preview_paths["farmlands"] = info_layer_farmlands_path
|
267
269
|
|
268
270
|
def _add_plants(self) -> None:
|
@@ -362,6 +364,9 @@ class GRLE(ImageComponent, XMLComponent):
|
|
362
364
|
# Ensure that order of channels is correct because CV2 uses BGR and we need RGB.
|
363
365
|
density_map_fruits = cv2.cvtColor(density_map_fruits, cv2.COLOR_BGR2RGB)
|
364
366
|
cv2.imwrite(density_map_fruit_path, density_map_fruits)
|
367
|
+
|
368
|
+
self.assets.plants = density_map_fruit_path
|
369
|
+
|
365
370
|
self.logger.debug("Updated density map for fruits saved in %s.", density_map_fruit_path)
|
366
371
|
|
367
372
|
def create_island_of_plants(self, image: np.ndarray, count: int) -> np.ndarray:
|
@@ -222,6 +222,8 @@ class I3d(XMLComponent):
|
|
222
222
|
tree.write(splines_i3d_path) # type: ignore
|
223
223
|
self.logger.debug("Splines I3D file saved to: %s.", splines_i3d_path)
|
224
224
|
|
225
|
+
self.assets.splines = splines_i3d_path
|
226
|
+
|
225
227
|
def _add_fields(self) -> None:
|
226
228
|
"""Adds fields to the map I3D file."""
|
227
229
|
tree = self.get_tree()
|
@@ -285,6 +287,8 @@ class I3d(XMLComponent):
|
|
285
287
|
|
286
288
|
self.save_tree(tree)
|
287
289
|
|
290
|
+
self.assets.fields = self.xml_path
|
291
|
+
|
288
292
|
def _get_field_xml_entry(
|
289
293
|
self, field_id: int, field_ccs: list[tuple[int, int]], node_id: int
|
290
294
|
) -> tuple[ET.Element, int] | tuple[None, int]:
|
@@ -559,6 +563,8 @@ class I3d(XMLComponent):
|
|
559
563
|
scene_node.append(trees_node)
|
560
564
|
self.save_tree(tree)
|
561
565
|
|
566
|
+
self.assets.forests = self.xml_path
|
567
|
+
|
562
568
|
@staticmethod
|
563
569
|
def randomize_coordinates(
|
564
570
|
coordinates: tuple[int, int], density: int, shift_percent: int
|
@@ -59,9 +59,13 @@ class Satellite(ImageComponent):
|
|
59
59
|
overview_size = (self.map_size + margin) * 2
|
60
60
|
overwiew_path = os.path.join(self.satellite_directory, "satellite_overview.png")
|
61
61
|
|
62
|
+
self.assets.overview = overwiew_path
|
63
|
+
|
62
64
|
background_size = self.map_size + (Parameters.BACKGROUND_DISTANCE + margin) * 2
|
63
65
|
background_path = os.path.join(self.satellite_directory, "satellite_background.png")
|
64
66
|
|
67
|
+
self.assets.background = background_path
|
68
|
+
|
65
69
|
sizes = [overview_size, background_size]
|
66
70
|
self.image_paths = [overwiew_path, background_path]
|
67
71
|
|
@@ -149,6 +149,9 @@ class Texture(ImageComponent):
|
|
149
149
|
self.dissolve()
|
150
150
|
self.copy_procedural()
|
151
151
|
|
152
|
+
for layer in self.layers:
|
153
|
+
self.assets[layer.name] = layer.path(self._weights_dir)
|
154
|
+
|
152
155
|
def add_borders(self) -> None:
|
153
156
|
"""Iterates over all the layers and picks the one which have the border propety defined.
|
154
157
|
Borders are distance from the edge of the map on each side (top, right, bottom, left).
|
@@ -504,7 +507,7 @@ class Texture(ImageComponent):
|
|
504
507
|
|
505
508
|
# Randomly assign non-zero values to sublayers.
|
506
509
|
for coord in non_zero_coords:
|
507
|
-
sublayers[np.random.randint(0, layer.count)][coord[0], coord[1]] = 255
|
510
|
+
sublayers[np.random.randint(0, layer.count)][coord[0], coord[1]] = 255 # type: ignore
|
508
511
|
|
509
512
|
# Save the sublayers.
|
510
513
|
for sublayer, sublayer_path in zip(sublayers, layer_paths):
|
maps4fs/generator/game.py
CHANGED
@@ -49,6 +49,14 @@ class Game:
|
|
49
49
|
if map_template_path:
|
50
50
|
self._map_template_path = map_template_path
|
51
51
|
|
52
|
+
def set_components_by_names(self, component_names: list[str]) -> None:
|
53
|
+
"""Sets the components used for map generation by their names.
|
54
|
+
|
55
|
+
Arguments:
|
56
|
+
component_names (list[str]): List of component names to be used.
|
57
|
+
"""
|
58
|
+
self.components = [comp for comp in self.components if comp.__name__ in component_names]
|
59
|
+
|
52
60
|
def map_xml_path(self, map_directory: str) -> str:
|
53
61
|
"""Returns the path to the map.xml file.
|
54
62
|
|
maps4fs/generator/map.py
CHANGED
maps4fs/generator/settings.py
CHANGED
@@ -145,6 +145,13 @@ class BackgroundSettings(SettingsModel):
|
|
145
145
|
generate_water (bool): generate obj files for the water.
|
146
146
|
resize_factor (int): resize factor for the background terrain and water.
|
147
147
|
It will be used as 1 / resize_factor of the original size.
|
148
|
+
water_blurriness (int): blurriness of the water.
|
149
|
+
remove_center (bool): remove the center of the background terrain.
|
150
|
+
It will be used to remove the center of the map where the player starts.
|
151
|
+
apply_decimation (bool): apply decimation to the background terrain.
|
152
|
+
decimation_percent (int): percentage of the decimation.
|
153
|
+
decimation_agression (int): agression of the decimation.
|
154
|
+
It will be used to control the amount of decimation applied to the background terrain.
|
148
155
|
"""
|
149
156
|
|
150
157
|
generate_background: bool = False
|
maps4fs/logger.py
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
import logging
|
4
4
|
import os
|
5
5
|
import sys
|
6
|
-
from datetime import datetime
|
7
6
|
from typing import Literal
|
8
7
|
|
9
8
|
LOGGER_NAME = "maps4fs"
|
@@ -12,35 +11,18 @@ os.makedirs(log_directory, exist_ok=True)
|
|
12
11
|
|
13
12
|
|
14
13
|
class Logger(logging.Logger):
|
15
|
-
"""Handles logging to
|
14
|
+
"""Handles logging to stdout with timestamps."""
|
16
15
|
|
17
16
|
def __init__(
|
18
17
|
self,
|
19
18
|
level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = "INFO",
|
20
19
|
to_stdout: bool = True,
|
21
|
-
to_file: bool = True,
|
22
20
|
):
|
23
21
|
super().__init__(LOGGER_NAME)
|
24
22
|
self.setLevel(level)
|
25
23
|
self.stdout_handler = logging.StreamHandler(sys.stdout)
|
26
|
-
self.file_handler = logging.FileHandler(
|
27
|
-
filename=self.log_file(), mode="a", encoding="utf-8"
|
28
|
-
)
|
29
24
|
formatter = "%(name)s | %(levelname)s | %(asctime)s | %(message)s"
|
30
25
|
self.fmt = formatter
|
31
26
|
self.stdout_handler.setFormatter(logging.Formatter(formatter))
|
32
|
-
self.file_handler.setFormatter(logging.Formatter(formatter))
|
33
27
|
if to_stdout:
|
34
28
|
self.addHandler(self.stdout_handler)
|
35
|
-
if to_file:
|
36
|
-
self.addHandler(self.file_handler)
|
37
|
-
|
38
|
-
def log_file(self) -> str:
|
39
|
-
"""Returns the path to the log file.
|
40
|
-
|
41
|
-
Returns:
|
42
|
-
str: The path to the log file.
|
43
|
-
"""
|
44
|
-
today = datetime.now().strftime("%Y-%m-%d")
|
45
|
-
log_file = os.path.join(log_directory, f"{today}.txt")
|
46
|
-
return log_file
|
@@ -1,22 +1,21 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: maps4fs
|
3
|
-
Version: 1.9.
|
3
|
+
Version: 1.9.4
|
4
4
|
Summary: Generate map templates for Farming Simulator from real places.
|
5
5
|
Author-email: iwatkot <iwatkot@gmail.com>
|
6
|
-
License:
|
6
|
+
License: Apache License 2.0
|
7
7
|
Project-URL: Homepage, https://github.com/iwatkot/maps4fs
|
8
8
|
Project-URL: Repository, https://github.com/iwatkot/maps4fs
|
9
9
|
Keywords: farmingsimulator,fs,farmingsimulator22,farmingsimulator25,fs22,fs25
|
10
10
|
Classifier: Programming Language :: Python :: 3.11
|
11
11
|
Classifier: Programming Language :: Python :: 3.12
|
12
|
-
Classifier: License :: OSI Approved ::
|
12
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
13
13
|
Classifier: Operating System :: OS Independent
|
14
14
|
Description-Content-Type: text/markdown
|
15
15
|
License-File: LICENSE.md
|
16
16
|
Requires-Dist: opencv-python
|
17
17
|
Requires-Dist: osmnx>=2.0.0
|
18
18
|
Requires-Dist: rasterio
|
19
|
-
Requires-Dist: folium
|
20
19
|
Requires-Dist: geopy
|
21
20
|
Requires-Dist: trimesh
|
22
21
|
Requires-Dist: imageio
|
@@ -29,7 +28,7 @@ Requires-Dist: tqdm
|
|
29
28
|
Requires-Dist: scipy
|
30
29
|
Dynamic: license-file
|
31
30
|
|
32
|
-
⚠️ Learn more about the upcoming 2.0
|
31
|
+
⚠️ Learn more about the upcoming 2.0 changes in the [migration guide](docs/migration.md).
|
33
32
|
⚠️ Some components are deprecated and there are major changes in the project structure.
|
34
33
|
|
35
34
|
|
@@ -52,7 +51,7 @@ Dynamic: license-file
|
|
52
51
|
<a href="docs/step_by_step.md">Create a map in 10 steps</a> •
|
53
52
|
<a href="#How-To-Run">How-To-Run</a><br>
|
54
53
|
<a href="docs/FAQ.md">FAQ</a> •
|
55
|
-
<a href="docs/map_structure.md">Map Structure</a>
|
54
|
+
<a href="docs/map_structure.md">Map Structure</a> •
|
56
55
|
<a href="#Schemas-Editor">Schemas Editor</a> •
|
57
56
|
<a href="#Main-Settings">Main Settings</a><br>
|
58
57
|
<a href="#Supported-objects">Supported objects</a> •
|
@@ -156,7 +155,7 @@ There are several ways to use the tool. You obviously need the **first one**, bu
|
|
156
155
|
**Option 2:** Run the Docker version in your browser. Launch the following command in your terminal:
|
157
156
|
|
158
157
|
```bash
|
159
|
-
docker run -d -p 8501:8501 --name maps4fs iwatkot/maps4fs
|
158
|
+
docker run -d -p 8501:8501 -p 8000:8000 --name maps4fs iwatkot/maps4fs
|
160
159
|
```
|
161
160
|
|
162
161
|
And open [http://localhost:8501](http://localhost:8501) in your browser.<br>
|
@@ -238,21 +237,13 @@ You can launch the project with minimalistic UI in your browser using Docker. Fo
|
|
238
237
|
2. Run the following command in your terminal:
|
239
238
|
|
240
239
|
```bash
|
241
|
-
docker run -d -p 8501:8501 --name maps4fs iwatkot/maps4fs
|
240
|
+
docker run -d -p 8501:8501 -p 8000:8000 --name maps4fs iwatkot/maps4fs
|
242
241
|
```
|
243
242
|
|
244
243
|
3. Open your browser and go to [http://localhost:8501](http://localhost:8501).
|
245
244
|
4. Fill in the required fields and click on the `Generate` button.
|
246
245
|
5. When the map is generated click on the `Download` button to get the map.
|
247
246
|
|
248
|
-
➡️ If you don't need Blender backend, you can use the **lite** version of the Docker image.
|
249
|
-
|
250
|
-
```bash
|
251
|
-
docker run -d -p 8501:8501 --name maps4fs iwatkot/maps4fs:*.*.*_lite
|
252
|
-
```
|
253
|
-
|
254
|
-
Remember to replace `*.*.*` with the version you want to use, e.g. `iwatkot/maps4fs:1.8.202_lite`. Also, pay attention that some features will not work in the lite version, such as removing the center part of the background mesh.
|
255
|
-
|
256
247
|
### Option 3: Python package or source code
|
257
248
|
|
258
249
|
🔴 Recommended for developers.
|
@@ -1,22 +1,22 @@
|
|
1
1
|
maps4fs/__init__.py,sha256=EGvLVoRpSt4jITswsGbe1ISVmGAZAMQJcBmTwtyuVxI,335
|
2
|
-
maps4fs/logger.py,sha256=
|
2
|
+
maps4fs/logger.py,sha256=WDfR14hxqy8b6xtwL6YIu2LGzFO1sbt0LxMgfsDTOkA,865
|
3
3
|
maps4fs/generator/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
|
4
|
-
maps4fs/generator/game.py,sha256=
|
5
|
-
maps4fs/generator/map.py,sha256=
|
4
|
+
maps4fs/generator/game.py,sha256=g8lMHuuRRmJLSDsQTAMv8p_-qntYMiZKnAqn7ru96i0,11645
|
5
|
+
maps4fs/generator/map.py,sha256=7-nx27M-VwTocPor8BCkkpthYBJYe_B-pe5_Dcsijaw,13899
|
6
6
|
maps4fs/generator/qgis.py,sha256=Es8hLuqN_KH8lDfnJE6He2rWYbAKJ3RGPn-o87S6CPI,6116
|
7
|
-
maps4fs/generator/settings.py,sha256=
|
7
|
+
maps4fs/generator/settings.py,sha256=E_M47X2QhbBqgiNraBDQd62lAQlNWHYLq30HQ59_4k4,7490
|
8
8
|
maps4fs/generator/statistics.py,sha256=aynS3zbAtiwnU_YLKHPTiiaKW98_suvQUhy1SGBA6mc,2448
|
9
9
|
maps4fs/generator/component/__init__.py,sha256=s01yVVVi8R2xxNvflu2D6wTd9I_g73AMM2x7vAC7GX4,490
|
10
|
-
maps4fs/generator/component/background.py,sha256=
|
10
|
+
maps4fs/generator/component/background.py,sha256=AfbgNUai3tvpMe8lYmfiaM1n51ssunECy4gRglihumU,24032
|
11
11
|
maps4fs/generator/component/config.py,sha256=IP530sapLofFskSnBEB96G0aUSd6Sno0G9ET3ca0ZOQ,3696
|
12
12
|
maps4fs/generator/component/dem.py,sha256=Bvm3ViA6PpR7RXRAHBj5rgYB9PWy55Qj6PhTMv6dJRI,11953
|
13
|
-
maps4fs/generator/component/grle.py,sha256=
|
14
|
-
maps4fs/generator/component/i3d.py,sha256=
|
13
|
+
maps4fs/generator/component/grle.py,sha256=ao3-4B4QUVl0XgOmYAj9L48KGaZtCZRTB1BqYgdAJIc,19613
|
14
|
+
maps4fs/generator/component/i3d.py,sha256=xTiZYQRahYBsVALxmnsBygzTHJLE54ucXvHK8LWCYAs,23914
|
15
15
|
maps4fs/generator/component/layer.py,sha256=-br4gAGcGeBNb3ldch9XFEK0lhXqb1IbArhFB5Owu54,6186
|
16
|
-
maps4fs/generator/component/satellite.py,sha256=
|
17
|
-
maps4fs/generator/component/texture.py,sha256=
|
16
|
+
maps4fs/generator/component/satellite.py,sha256=47V9aPbv7k-2C-PsoXd33EO92yavFzB6_MRCd7fLP6k,5042
|
17
|
+
maps4fs/generator/component/texture.py,sha256=Nc_oOHX3b4vJm8FnNOn3W4EQGFkW0zW0rGzO_0nTJMM,33392
|
18
18
|
maps4fs/generator/component/base/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
|
19
|
-
maps4fs/generator/component/base/component.py,sha256=
|
19
|
+
maps4fs/generator/component/base/component.py,sha256=HeNDaToKrS6OLeJepKZA7iQzZQDYy-9QRtv1A73Ire0,22090
|
20
20
|
maps4fs/generator/component/base/component_image.py,sha256=2NYJgCU8deHl7O2FYFYk38WKZVJygFoc2gjBXwH6vjM,5970
|
21
21
|
maps4fs/generator/component/base/component_mesh.py,sha256=BsxS5NlUK2hLhksgCwSoMK-00GNAwK2fYGpgb3R4n1w,9396
|
22
22
|
maps4fs/generator/component/base/component_xml.py,sha256=V9pGUvHh6UF6BP0qFARqDq9vquoAgq1zJqhOgBoeS_Y,3983
|
@@ -54,8 +54,8 @@ maps4fs/toolbox/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,4
|
|
54
54
|
maps4fs/toolbox/background.py,sha256=RB0pHuRyfnDuqYtO2gUypfPm4G5cYRFdT2W-DG49zy0,2427
|
55
55
|
maps4fs/toolbox/custom_osm.py,sha256=fjVSl9Ztc8_q0DxgNkhM7tE0Y-XpX8xcGGW-Tunp0R8,2518
|
56
56
|
maps4fs/toolbox/dem.py,sha256=mbn3ZqMRhhYmzgssm2CGvg6aa89MUBOJPq6QyE54OLY,4191
|
57
|
-
maps4fs-1.9.
|
58
|
-
maps4fs-1.9.
|
59
|
-
maps4fs-1.9.
|
60
|
-
maps4fs-1.9.
|
61
|
-
maps4fs-1.9.
|
57
|
+
maps4fs-1.9.4.dist-info/licenses/LICENSE.md,sha256=pTKD_oUexcn-yccFCTrMeLkZy0ifLRa-VNcDLqLZaIw,10749
|
58
|
+
maps4fs-1.9.4.dist-info/METADATA,sha256=MXtYH5U2kDN-FzFipLbbHxgOCaZPkt-UFqF5H6rIQQM,49319
|
59
|
+
maps4fs-1.9.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
60
|
+
maps4fs-1.9.4.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
|
61
|
+
maps4fs-1.9.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|