maps4fs 1.9.2__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.
@@ -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
- mesh.apply_scale([0.5, 0.5, 0.5])
325
- self.mesh_to_stl(mesh, save_path=self.stl_preview_path)
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
@@ -35,7 +35,7 @@ class XMLComponent(Component):
35
35
  if not os.path.isfile(xml_path):
36
36
  raise FileNotFoundError(f"XML file {xml_path} does not exist.")
37
37
 
38
- return ET.parse(xml_path)
38
+ return ET.parse(xml_path) # type: ignore
39
39
 
40
40
  def save_tree(self, tree: ET.ElementTree, xml_path: str | None = None) -> None:
41
41
  """Saves the XML tree to the file.
@@ -40,7 +40,7 @@ class Config(XMLComponent):
40
40
  "height": str(self.scaled_size),
41
41
  }
42
42
 
43
- for element in root.iter("map"):
43
+ for element in root.iter("map"): # type: ignore
44
44
  self.update_element(element, data)
45
45
  break
46
46
  self.save_tree(tree)
@@ -204,7 +204,7 @@ class GRLE(ImageComponent, XMLComponent):
204
204
 
205
205
  tree = self.get_tree()
206
206
  root = tree.getroot()
207
- farmlands_node = root.find("farmlands")
207
+ farmlands_node = root.find("farmlands") # type: ignore
208
208
  if farmlands_node is None:
209
209
  raise ValueError("Farmlands XML element not found in the farmlands XML file.")
210
210
 
@@ -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:
@@ -85,8 +85,8 @@ class I3d(XMLComponent):
85
85
 
86
86
  data = {"heightScale": str(value)}
87
87
 
88
- self.get_and_update_element(root, path, data)
89
- self.save_tree(tree)
88
+ self.get_and_update_element(root, path, data) # type: ignore
89
+ self.save_tree(tree) # type: ignore
90
90
 
91
91
  def _update_parameters(self) -> None:
92
92
  """Updates the map I3D file with the sun bounding box and displacement layer size."""
@@ -101,11 +101,11 @@ class I3d(XMLComponent):
101
101
  "lastShadowMapSplitBboxMax": f"{distance},148,{distance}",
102
102
  }
103
103
 
104
- self.get_and_update_element(root, sun_element_path, data)
104
+ self.get_and_update_element(root, sun_element_path, data) # type: ignore
105
105
 
106
106
  displacement_layer_path = ".//Scene/TerrainTransformGroup/Layers/DisplacementLayer"
107
107
  data = {"size": str(int(self.map_size * 8))}
108
- self.get_and_update_element(root, displacement_layer_path, data)
108
+ self.get_and_update_element(root, displacement_layer_path, data) # type: ignore
109
109
 
110
110
  self.save_tree(tree)
111
111
 
@@ -125,9 +125,9 @@ class I3d(XMLComponent):
125
125
 
126
126
  root = tree.getroot()
127
127
  # Find <Shapes> element in the I3D file.
128
- shapes_node = root.find(".//Shapes")
128
+ shapes_node = root.find(".//Shapes") # type: ignore
129
129
  # Find <Scene> element in the I3D file.
130
- scene_node = root.find(".//Scene")
130
+ scene_node = root.find(".//Scene") # type: ignore
131
131
 
132
132
  if shapes_node is None or scene_node is None:
133
133
  self.logger.warning("Shapes or Scene node not found in I3D file.")
@@ -145,7 +145,7 @@ class I3d(XMLComponent):
145
145
  interpolation=cv2.INTER_NEAREST,
146
146
  )
147
147
 
148
- user_attributes_node = root.find(".//UserAttributes")
148
+ user_attributes_node = root.find(".//UserAttributes") # type: ignore
149
149
  if user_attributes_node is None:
150
150
  self.logger.warning("UserAttributes node not found in I3D file.")
151
151
  return
@@ -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()
@@ -240,12 +242,12 @@ class I3d(XMLComponent):
240
242
  self.logger.debug("Starging to add fields to the I3D file.")
241
243
 
242
244
  root = tree.getroot()
243
- gameplay_node = root.find(".//TransformGroup[@name='gameplay']")
245
+ gameplay_node = root.find(".//TransformGroup[@name='gameplay']") # type: ignore
244
246
 
245
247
  if gameplay_node is None:
246
248
  return
247
249
  fields_node = gameplay_node.find(".//TransformGroup[@name='fields']")
248
- user_attributes_node = root.find(".//UserAttributes")
250
+ user_attributes_node = root.find(".//UserAttributes") # type: ignore
249
251
 
250
252
  if fields_node is None or user_attributes_node is None:
251
253
  return
@@ -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]:
@@ -497,7 +501,7 @@ class I3d(XMLComponent):
497
501
 
498
502
  tree = self.get_tree()
499
503
  root = tree.getroot()
500
- scene_node = root.find(".//Scene")
504
+ scene_node = root.find(".//Scene") # type: ignore
501
505
  if scene_node is None:
502
506
  self.logger.warning("Scene element not found in I3D file.")
503
507
  return
@@ -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
@@ -58,7 +58,7 @@ class Map:
58
58
  **kwargs,
59
59
  ):
60
60
  if not logger:
61
- logger = Logger(to_stdout=True, to_file=False)
61
+ logger = Logger()
62
62
  self.logger = logger
63
63
  self.size = size
64
64
 
@@ -226,8 +226,8 @@ class Map:
226
226
  self.rotation,
227
227
  self.map_directory,
228
228
  self.logger,
229
- texture_custom_schema=self.texture_custom_schema,
230
- tree_custom_schema=self.tree_custom_schema,
229
+ texture_custom_schema=self.texture_custom_schema, # type: ignore
230
+ tree_custom_schema=self.tree_custom_schema, # type: ignore
231
231
  )
232
232
  self.components.append(component)
233
233
 
@@ -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 the file and stroudt with timestamps."""
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,5 +1,7 @@
1
1
  """This module contains functions to work with the background terrain of the map."""
2
2
 
3
+ import warnings
4
+
3
5
  import cv2
4
6
  import numpy as np
5
7
  import trimesh # type: ignore
@@ -22,6 +24,13 @@ def plane_from_np(
22
24
  will result in a simpler mesh.
23
25
  save_path (str) -- The path to save the obj file.
24
26
  """
27
+ warnings.warn(
28
+ "The 'plane_from_np' function is deprecated and will be removed in maps4fs 2.0. "
29
+ "Use 'trimesh' directly instead or maps4fs.generator.component.base.component_mesh."
30
+ "MeshComponent.mesh_from_np' instead.",
31
+ DeprecationWarning,
32
+ stacklevel=2,
33
+ )
25
34
  dem_data = cv2.resize(dem_data, (0, 0), fx=resize_factor, fy=resize_factor)
26
35
 
27
36
  # Invert the height values.
@@ -1,6 +1,7 @@
1
1
  """This module contains functions to work with custom OSM files."""
2
2
 
3
3
  import json
4
+ import warnings
4
5
  from xml.etree import ElementTree as ET
5
6
 
6
7
  import osmnx as ox
@@ -19,6 +20,13 @@ def check_osm_file(file_path: str) -> bool:
19
20
  Returns:
20
21
  bool: True if the file is valid, False otherwise.
21
22
  """
23
+ warnings.warn(
24
+ "The 'check_osm_file' function is deprecated and will be removed in maps4fs 2.0. "
25
+ "The feature will be directly integrated into the maps4fs generator. "
26
+ "And will not be available as a separate function.",
27
+ DeprecationWarning,
28
+ stacklevel=2,
29
+ )
22
30
  with open(FS25().texture_schema, encoding="utf-8") as f:
23
31
  schema = json.load(f)
24
32
 
@@ -50,6 +58,13 @@ def fix_osm_file(input_file_path: str, output_file_path: str) -> tuple[bool, int
50
58
  tuple[bool, int]: A tuple containing the result of the check_osm_file function
51
59
  and the number of fixed errors.
52
60
  """
61
+ warnings.warn(
62
+ "The 'fix_osm_file' function is deprecated and will be removed in maps4fs 2.0. "
63
+ "The feature will be directly integrated into the maps4fs generator. "
64
+ "And will not be available as a separate function.",
65
+ DeprecationWarning,
66
+ stacklevel=2,
67
+ )
53
68
  broken_entries = ["relation", ".//*[@action='delete']"]
54
69
 
55
70
  tree = ET.parse(input_file_path)
maps4fs/toolbox/dem.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """This module contains functions for working with Digital Elevation Models (DEMs)."""
2
2
 
3
3
  import os
4
+ import warnings
4
5
 
5
6
  import rasterio # type: ignore
6
7
  from pyproj import Transformer
@@ -21,6 +22,12 @@ def read_geo_tiff(file_path: str) -> DatasetReader:
21
22
  Returns:
22
23
  DatasetReader: The DatasetReader object for the GeoTIFF file.
23
24
  """
25
+ warnings.warn(
26
+ "The 'read_geo_tiff' function is deprecated and will be removed in maps4fs 2.0. "
27
+ "Use 'rasterio.open' directly instead.",
28
+ DeprecationWarning,
29
+ stacklevel=2,
30
+ )
24
31
  if not os.path.isfile(file_path):
25
32
  raise FileNotFoundError(f"File not found: {file_path}")
26
33
 
@@ -51,6 +58,12 @@ def get_geo_tiff_bbox(
51
58
  tuple[float, float, float, float]: The bounding box in the destination CRS
52
59
  as (north, south, east, west).
53
60
  """
61
+ warnings.warn(
62
+ "The 'get_geo_tiff_bbox' function is deprecated and will be removed in maps4fs 2.0. "
63
+ "Use 'rasterio' methods directly instead.",
64
+ DeprecationWarning,
65
+ stacklevel=2,
66
+ )
54
67
  left, bottom, right, top = src.bounds
55
68
 
56
69
  transformer = Transformer.from_crs(src.crs, dst_crs, always_xy=True)
@@ -76,6 +89,12 @@ def extract_roi(file_path: str, bbox: tuple[float, float, float, float]) -> str:
76
89
  Returns:
77
90
  str: The path to the new GeoTIFF file containing the extracted ROI.
78
91
  """
92
+ warnings.warn(
93
+ "The 'extract_roi' function is deprecated and will be removed in maps4fs 2.0. "
94
+ "Use 'rasterio' methods directly instead.",
95
+ DeprecationWarning,
96
+ stacklevel=2,
97
+ )
79
98
  with rasterio.open(file_path) as src:
80
99
  transformer = Transformer.from_crs("EPSG:4326", src.crs, always_xy=True)
81
100
  north, south, east, west = bbox
@@ -1,22 +1,21 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maps4fs
3
- Version: 1.9.2
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: MIT 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 :: MIT License
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,6 +28,18 @@ Requires-Dist: tqdm
29
28
  Requires-Dist: scipy
30
29
  Dynamic: license-file
31
30
 
31
+ ⚠️ Learn more about the upcoming 2.0 changes in the [migration guide](docs/migration.md).
32
+ ⚠️ Some components are deprecated and there are major changes in the project structure.
33
+
34
+
35
+ <p align="center">
36
+ <a href="https://github.com/iwatkot/maps4fs">maps4fs</a> •
37
+ <a href="https://github.com/iwatkot/maps4fsui">maps4fs UI</a> •
38
+ <a href="https://github.com/iwatkot/maps4fsapi">maps4fs API</a> •
39
+ <a href="https://github.com/iwatkot/maps4fsstats">maps4fs Stats</a> •
40
+ <a href="https://github.com/iwatkot/maps4fsbot">maps4fs Bot</a>
41
+ </p>
42
+
32
43
  <div align="center" markdown>
33
44
  <a href="https://discord.gg/Sj5QKKyE42">
34
45
  <img src="https://github.com/user-attachments/assets/37043333-d6ef-4ca3-9f3c-81323d9d0b71">
@@ -40,8 +51,8 @@ Dynamic: license-file
40
51
  <a href="docs/step_by_step.md">Create a map in 10 steps</a> •
41
52
  <a href="#How-To-Run">How-To-Run</a><br>
42
53
  <a href="docs/FAQ.md">FAQ</a> •
43
- <a href="docs/map_structure.md">Map Structure</a>
44
- <a href="#Modder-Toolbox">Modder Toolbox</a> •
54
+ <a href="docs/map_structure.md">Map Structure</a>
55
+ <a href="#Schemas-Editor">Schemas Editor</a> •
45
56
  <a href="#Main-Settings">Main Settings</a><br>
46
57
  <a href="#Supported-objects">Supported objects</a> •
47
58
  <a href="#Generation-info">Generation info</a> •
@@ -69,7 +80,6 @@ Dynamic: license-file
69
80
  [![Build Status](https://github.com/iwatkot/maps4fs/actions/workflows/checks.yml/badge.svg)](https://github.com/iwatkot/maps4fs/actions)
70
81
  [![Test Coverage](https://api.codeclimate.com/v1/badges/b922fd0a7188d37e61de/test_coverage)](https://codeclimate.com/github/iwatkot/maps4fs/test_coverage)
71
82
  [![GitHub Repo stars](https://img.shields.io/github/stars/iwatkot/maps4fs)](https://github.com/iwatkot/maps4fs/stargazers)<br>
72
- [![Lines of code](https://tokei.rs/b1/github/iwatkot/maps4fs)](https://github.com/iwatkot/maps4fs)
73
83
 
74
84
  </div>
75
85
 
@@ -92,7 +102,6 @@ Dynamic: license-file
92
102
  🔷 Generates \*.obj files for background terrain based on the real-world height map<br>
93
103
  📄 Generates scripts to download high-resolution satellite images from [QGIS](https://qgis.org/download/) in one click<br>
94
104
  📕 Detailed [documentation](/docs) and tutorials <br>
95
- 🧰 Modder Toolbox to help you with various tasks <br>
96
105
 
97
106
  <p align="center">
98
107
  <img src="https://github.com/user-attachments/assets/cf8f5752-9c69-4018-bead-290f59ba6976"><br>
@@ -146,7 +155,7 @@ There are several ways to use the tool. You obviously need the **first one**, bu
146
155
  **Option 2:** Run the Docker version in your browser. Launch the following command in your terminal:
147
156
 
148
157
  ```bash
149
- docker run -d -p 8501:8501 --name maps4fs iwatkot/maps4fs
158
+ docker run -d -p 8501:8501 -p 8000:8000 --name maps4fs iwatkot/maps4fs
150
159
  ```
151
160
 
152
161
  And open [http://localhost:8501](http://localhost:8501) in your browser.<br>
@@ -228,21 +237,13 @@ You can launch the project with minimalistic UI in your browser using Docker. Fo
228
237
  2. Run the following command in your terminal:
229
238
 
230
239
  ```bash
231
- docker run -d -p 8501:8501 --name maps4fs iwatkot/maps4fs
240
+ docker run -d -p 8501:8501 -p 8000:8000 --name maps4fs iwatkot/maps4fs
232
241
  ```
233
242
 
234
243
  3. Open your browser and go to [http://localhost:8501](http://localhost:8501).
235
244
  4. Fill in the required fields and click on the `Generate` button.
236
245
  5. When the map is generated click on the `Download` button to get the map.
237
246
 
238
- ➡️ If you don't need Blender backend, you can use the **lite** version of the Docker image.
239
-
240
- ```bash
241
- docker run -d -p 8501:8501 --name maps4fs iwatkot/maps4fs:*.*.*_lite
242
- ```
243
-
244
- 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.
245
-
246
247
  ### Option 3: Python package or source code
247
248
 
248
249
  🔴 Recommended for developers.
@@ -326,32 +327,12 @@ The map will be saved in the `map_directory` directory.
326
327
 
327
328
  ➡️ Check out the [demo.py](demo.py) file for a complete example.
328
329
 
329
- ## Modder Toolbox
330
-
331
- The tool now has a Modder Toolbox, which is a set of tools to help you with various tasks. You can open the toolbox by switching to the `🧰 Modder Toolbox` tab in the StreamLit app.<br>
332
-
333
- ![Modder Toolbox](https://github.com/user-attachments/assets/dffb252f-f5c0-4021-9d45-31e5bccc0d9b)
334
-
335
- ### Tool Categories
336
-
337
- Tools are divided into categories, which are listed below.
338
-
339
- #### For custom schemas
330
+ ## Schemas Editor
340
331
 
341
332
  - **Tree Schema Editor** - allows you to view all the supported trees models and select the ones you need on your map. After it, you should click the Show updated schema button and copy the JSON schema to the clipboard. Then you can use it in the Expert settings to generate the map with the selected trees.
342
333
 
343
334
  - **Texture Schema Editor** - allows you to view all the supported textures and edit their parameters, such as priority, OSM tags and so on. After editing, you should click the Show updated schema button and copy the JSON schema to the clipboard. Then you can use it in the Expert settings to generate the map with the updated textures.
344
335
 
345
- #### For Textures and DEM
346
-
347
- - **Fix custom OSM file** - this tool fixes the most common errors in the custom OSM file, but it can not guarantee that the file will be fixed completely if some non-common errors are present.
348
-
349
- - **GeoTIFF windowing** - allows you to upload your GeoTIFF file and select the region of interest to extract it from the image. It's useful when you have high-resolution DEM data and want to create a height map using it.
350
-
351
- #### For Background terrain
352
-
353
- - **Convert image to obj model** - allows you to convert the image to the obj model. You can use this tool to create the background terrain for your map. It can be extremely useful if you have access to the sources of high-resolution DEM data and want to create the background terrain using it.
354
-
355
336
  ## Main Settings
356
337
 
357
338
  ### Game Selection
@@ -1,25 +1,25 @@
1
1
  maps4fs/__init__.py,sha256=EGvLVoRpSt4jITswsGbe1ISVmGAZAMQJcBmTwtyuVxI,335
2
- maps4fs/logger.py,sha256=HQrDyj72mUjVYo25aR_-_SxVn2rfFjDCNbj-JKJdSnE,1488
2
+ maps4fs/logger.py,sha256=WDfR14hxqy8b6xtwL6YIu2LGzFO1sbt0LxMgfsDTOkA,865
3
3
  maps4fs/generator/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
4
- maps4fs/generator/game.py,sha256=NZaxj5z7WzMiHzAvQyr-TvVjGoHgqGldM6ZsItuYyzA,11292
5
- maps4fs/generator/map.py,sha256=XYKzhr2SuC3ILty1RYfaWkxUr9VJF3FkpWJ6-dTwzB8,13896
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=E5sfkfJgcjh9QHpa7ILlV_jnrF6USpsOFxkooVnxrbs,6968
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=kt_RaLrj6hZeZaaFNT36jJyp9IofiN9CFsO8EYY7F7A,23756
11
- maps4fs/generator/component/config.py,sha256=dEezqrDJ9ghEvJ1Y2jdL-v7ezgeeTN415Fcr_vBQmqg,3680
10
+ maps4fs/generator/component/background.py,sha256=AfbgNUai3tvpMe8lYmfiaM1n51ssunECy4gRglihumU,24032
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=xwuwkqVDvxQL6r9E5pytIcPH0HsgHI7ZYGmCcyfd8Pc,19484
14
- maps4fs/generator/component/i3d.py,sha256=432LJWfOcY4rPXc2tb3okCRJ_DD9wgIHt0u0nqJBhJI,23617
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=oZBHjP_QY0ik1-Vk7JqMS__zIG8ffw2voeozB7-HUQc,4946
17
- maps4fs/generator/component/texture.py,sha256=tCMuuNcRwgdPkPVmNA7BCbnsTBnwkUXOrdlJJUoYAMU,33273
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=13ZjIatyxmxfcpE89cqlpQ6IBppJTeUisIEVa344eqM,21833
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
- maps4fs/generator/component/base/component_xml.py,sha256=6OO1dKoceO1ACk7-k1oGtnkfNud8ZN3u3ZNjdNMpTqw,3967
22
+ maps4fs/generator/component/base/component_xml.py,sha256=V9pGUvHh6UF6BP0qFARqDq9vquoAgq1zJqhOgBoeS_Y,3983
23
23
  maps4fs/generator/dtm/__init__.py,sha256=CzK8ZdLU5Iv7DrwK5hIQ41zVsLRFgZO-IuRxf-NCVqg,1516
24
24
  maps4fs/generator/dtm/arctic.py,sha256=LSivLLjtd6TJUaPYvgSYQ4KalMTaY58zFvwivSh45uM,2587
25
25
  maps4fs/generator/dtm/baden.py,sha256=PQTMEPm9hrO3nKbv_DXA9oNYnGK_0ei41Q_DhtethX0,1041
@@ -51,11 +51,11 @@ maps4fs/generator/dtm/utils.py,sha256=I-wUSA_J85Xbt8sZCZAVKHSIcrMj5Ng-0adtPVhVmk
51
51
  maps4fs/generator/dtm/base/wcs.py,sha256=lQAp_gVz9_XUmtyobJkskiefQpuJH4o1Vwb3CSQ0lQA,2510
52
52
  maps4fs/generator/dtm/base/wms.py,sha256=6Va2UMhg_s0TMOfMhxrPbsiAPiw6-vXBglnaij032I0,2264
53
53
  maps4fs/toolbox/__init__.py,sha256=zZMLEkGzb4z0xql650gOtGSvcgX58DnJ2yN3vC2daRk,43
54
- maps4fs/toolbox/background.py,sha256=RclEqxEWLbMxuEkkegQP8jybzugwQ1_R3rdfDe0s21U,2104
55
- maps4fs/toolbox/custom_osm.py,sha256=X6ZlPqiOhNjkmdD_qVroIfdOl9Rb90cDwVSLDVYgx80,1892
56
- maps4fs/toolbox/dem.py,sha256=z9IPFNmYbjiigb3t02ZenI3Mo8odd19c5MZbjDEovTo,3525
57
- maps4fs-1.9.2.dist-info/licenses/LICENSE.md,sha256=pTKD_oUexcn-yccFCTrMeLkZy0ifLRa-VNcDLqLZaIw,10749
58
- maps4fs-1.9.2.dist-info/METADATA,sha256=JbEQlBdtwmVmxgKqAX18yn6PFBwmyQrFGOo4ZJLa8iI,50476
59
- maps4fs-1.9.2.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
60
- maps4fs-1.9.2.dist-info/top_level.txt,sha256=Ue9DSRlejRQRCaJueB0uLcKrWwsEq9zezfv5dI5mV1M,8
61
- maps4fs-1.9.2.dist-info/RECORD,,
54
+ maps4fs/toolbox/background.py,sha256=RB0pHuRyfnDuqYtO2gUypfPm4G5cYRFdT2W-DG49zy0,2427
55
+ maps4fs/toolbox/custom_osm.py,sha256=fjVSl9Ztc8_q0DxgNkhM7tE0Y-XpX8xcGGW-Tunp0R8,2518
56
+ maps4fs/toolbox/dem.py,sha256=mbn3ZqMRhhYmzgssm2CGvg6aa89MUBOJPq6QyE54OLY,4191
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.8.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5