diff --git a/README.md b/README.md index 918c704d..45585f04 100644 --- a/README.md +++ b/README.md @@ -229,6 +229,10 @@ The tool now has a Modder Toolbox, which is a set of tools to help you with vari ### Tool Categories Tools are divided into categories, which are listed below. + +#### For custom schemas +- **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. + #### For Textures and DEM - **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. @@ -568,3 +572,4 @@ But also, I want to thank the people who helped me with the project in some way, - [Lucandia](https://github.com/Lucandia) - for the awesome StreamLit [widget to preview STL files](https://github.com/Lucandia/streamlit_stl). - [H4rdB4se](https://github.com/H4rdB4se) - for investigating the issue with custom OSM files and finding a proper way to work with the files in JOSM. - [kbrandwijk](https://github.com/kbrandwijk) - for providing [awesome tool](https://github.com/Paint-a-Farm/satmap_downloader) to download the satellite images from the Google Maps and giving a permission to modify it and create a Python Package. +- [Maaslandmods](https://github.com/Maaslandmods) - for the awesome idea to edit the tree schema in UI, images and code snippets on how to do it. diff --git a/maps4fs/generator/map.py b/maps4fs/generator/map.py index 99ac100d..42e95529 100644 --- a/maps4fs/generator/map.py +++ b/maps4fs/generator/map.py @@ -146,6 +146,7 @@ def __init__( # pylint: disable=R0917, R0915 self.tree_custom_schema = kwargs.get("tree_custom_schema", None) if self.tree_custom_schema: + self.logger.info("Custom tree schema contains %s trees", len(self.tree_custom_schema)) save_path = os.path.join(self.map_directory, "tree_custom_schema.json") with open(save_path, "w", encoding="utf-8") as file: json.dump(self.tree_custom_schema, file, indent=4) diff --git a/webui/tools/section.py b/webui/tools/section.py index b9f6482e..0c3f340e 100644 --- a/webui/tools/section.py +++ b/webui/tools/section.py @@ -3,6 +3,7 @@ from tools.background import ConvertImageToObj from tools.dem import GeoTIFFWindowingTool from tools.tool import Tool +from tools.trees import TreeSchemaEditorTool class Section: @@ -20,6 +21,12 @@ def add(cls): tool() +class Shemas(Section): + title = "📄 Schemas" + description = "Tools to work with different schemas." + tools = [TreeSchemaEditorTool] + + class TexturesAndDEM(Section): title = "🖼️ Textures and DEM" description = "Tools to work with textures and digital elevation models." diff --git a/webui/tools/trees.py b/webui/tools/trees.py new file mode 100644 index 00000000..c4a941a6 --- /dev/null +++ b/webui/tools/trees.py @@ -0,0 +1,73 @@ +import json +from typing import NamedTuple + +import streamlit as st +from config import FS25_TREE_SCHEMA_PATH +from tools.tool import Tool +from tools.trees_data import TREE_URLS + +COLUMNS_PER_ROW = 5 + + +class TreeInfo(NamedTuple): + name: str + reference_id: str + url: str + + +class TreeSchemaEditorTool(Tool): + title = "Tree Schema Editor" + description = ( + "This tool allows you to select which trees will be included in your tree schema and then " + "use it for the map generation." + ) + icon = "🪵" + + def content(self): + with open(FS25_TREE_SCHEMA_PATH, "r", encoding="utf-8") as f: + self.tree_schema = json.load(f) + + tree_infos = [] + for tree in self.tree_schema: + tree_name = tree["name"] + tree_id = tree["reference_id"] + tree_url = TREE_URLS.get(tree_name) + if not tree_url: + continue + + tree_infos.append(TreeInfo(tree_name, tree_id, tree_url)) + + self.button_container = st.container() + + # Create a grid of images using the number of columns per row + self.checkboxes = {} + for i in range(0, len(tree_infos), COLUMNS_PER_ROW): + row = st.columns(COLUMNS_PER_ROW) + for j, tree_info in enumerate(tree_infos[i : i + COLUMNS_PER_ROW]): + with row[j]: + st.image(tree_info.url, use_container_width=True) + tree_checkbox = st.checkbox( + tree_info.name, + value=True, + key=tree_info.reference_id, + ) + self.checkboxes[tree_info] = tree_checkbox + + with self.button_container: + if st.button("Show updated schema"): + tree_schema = self.read_schema() + st.success( + "Tree schema was generated, click the copy button to copy it to the " + "clipboard. \n" + "Then paste it into the tree schema input field in the generation tool." + ) + st.json(tree_schema, expanded=False) + + def read_schema(self) -> list[dict[str, str | int]]: + new_schema = [] + for tree_info, activated in self.checkboxes.items(): + if activated: + active_entry = {"name": tree_info.name, "reference_id": tree_info.reference_id} + new_schema.append(active_entry) + + return new_schema diff --git a/webui/tools/trees_data.py b/webui/tools/trees_data.py new file mode 100644 index 00000000..a00a3e29 --- /dev/null +++ b/webui/tools/trees_data.py @@ -0,0 +1,86 @@ +TREE_URLS = { + "americanElm_stage01": "https://github.com/user-attachments/assets/eb1857dd-47b7-4883-83fa-385fefad101c", + "americanElm_stage02": "https://github.com/user-attachments/assets/7688fd89-a006-4023-8c56-c3e4291d5357", + "americanElm_stage03": "https://github.com/user-attachments/assets/298729cb-809f-4d1e-bdbc-945dfd45a365", + "americanElm_stage04": "https://github.com/user-attachments/assets/c07e0d90-742b-4f9e-8799-71cc6a50f19d", + "americanElm_stage05": "https://github.com/user-attachments/assets/a2a1943d-6ddb-4496-9526-58919cdecdd4", + "americanElmRavaged": "https://github.com/user-attachments/assets/7556fde4-7dae-4418-af42-64651479c23f", + "apple_stage03": "https://github.com/user-attachments/assets/bbda1ccb-46a2-489c-b93d-ea51ce13683d", + "aspen_stage01": "https://github.com/user-attachments/assets/d53ae74c-6971-4547-bd65-cf6cd75180c3", + "aspen_stage02": "https://github.com/user-attachments/assets/e148daf8-066f-4a6f-be13-2838c632afce", + "aspen_stage03": "https://github.com/user-attachments/assets/f11e6843-30d2-4727-a96d-3599ee53eef3", + "aspen_stage04": "https://github.com/user-attachments/assets/157d0298-9893-487a-8598-bbbe5d8cc623", + "aspen_stage05": "https://github.com/user-attachments/assets/9031ee5e-598d-40c5-8237-dd9f8e74bd69", + "aspen_stage06_var01": "https://github.com/user-attachments/assets/68b71344-a069-46b3-b977-c454120efea4", + "aspen_stage06_var02": "https://github.com/user-attachments/assets/d4c942fb-29d8-46d7-9798-f40fe3895403", + "beech_stage01": "https://github.com/user-attachments/assets/c5b7e07d-eaf4-43f1-81d6-8b3641914e29", + "beech_stage02": "https://github.com/user-attachments/assets/15781495-d41d-4b34-9c96-2e0d365b82f0", + "beech_stage02_var02": "https://github.com/user-attachments/assets/1711ccf1-b41b-4152-bb62-48e98d8fe9b1", + "beech_stage02_var03": "https://github.com/user-attachments/assets/f9168063-77a7-43e6-9469-add6349eaeed", + "beech_stage03": "https://github.com/user-attachments/assets/c1b350c6-e98d-4ea6-929b-f43288147faa", + "beech_stage04": "https://github.com/user-attachments/assets/578d7e8a-3a26-4651-90c3-1297431a9574", + "beech_stage05": "https://github.com/user-attachments/assets/e827d20d-1138-47d3-b0fb-6c33f3882fe4", + "beech_stage06_var01": "https://github.com/user-attachments/assets/f9681fdb-d10f-43d5-8c5e-33e4b46c54f2", + "beech_stage06_var02": "https://github.com/user-attachments/assets/aaf1e2f2-7668-459b-b1ed-2cafb99baa6d", + "betulaErmanii_stage01": "https://github.com/user-attachments/assets/fe8455e1-605d-4eff-8f64-ce0b25f05e7a", + "betulaErmanii_stage02": "https://github.com/user-attachments/assets/998cc3ec-080d-4afa-90b9-31e481aa8f43", + "betulaErmanii_stage03": "https://github.com/user-attachments/assets/47b6ba66-62dd-4932-9267-40d9a6c33c1c", + "betulaErmanii_stage04": "https://github.com/user-attachments/assets/198b7c91-f95a-49be-a693-1b2c6a4110d6", + "boxelder_stage01": "https://github.com/user-attachments/assets/d97a9459-0936-4aaf-ae94-6dcbc9eab301", + "boxelder_stage02": "https://github.com/user-attachments/assets/7580d048-8789-42a7-a611-313f932b4751", + "boxelder_stage03": "https://github.com/user-attachments/assets/9d32deff-204d-434b-b5b3-3ef8bb4f31aa", + "cherry_stage01": "https://github.com/user-attachments/assets/9665a9b0-f68c-47cb-80b3-c08e6f148b30", + "cherry_stage02": "https://github.com/user-attachments/assets/eda62d03-08c9-446e-ba17-798476ebc0aa", + "cherry_stage03": "https://github.com/user-attachments/assets/555ebf25-3333-440a-aa31-7cc46f9429c0", + "cherry_stage04": "https://github.com/user-attachments/assets/b04e2f10-502c-4ae7-a618-0351cc116f5a", + "chineseElm_stage01": "https://github.com/user-attachments/assets/5927c18f-af18-4e2c-80eb-ba23e8d120f2", + "chineseElm_stage02": "https://github.com/user-attachments/assets/dc04f2fe-f962-4d2d-b8e0-9867adf50443", + "chineseElm_stage03": "https://github.com/user-attachments/assets/0aca52f0-cea6-45f7-ace6-d5a4150ab232", + "chineseElm_stage04": "https://github.com/user-attachments/assets/d5d89e6c-2158-4362-9a7f-88bf44b43aa8", + "deadwood": "https://github.com/user-attachments/assets/0095a837-a674-4398-a2e5-28fa132319a9", + "downeyServiceBerry_stage03": "https://github.com/user-attachments/assets/4ad7b300-6d38-47e6-821a-ac5a5c4a5cf5", + "downyServiceBerry_stage01": "https://github.com/user-attachments/assets/83005db3-eae5-4af3-9d97-ceb8a450afa7", + "downyServiceBerry_stage02": "https://github.com/user-attachments/assets/aaf30d40-765b-463f-b20e-63a2cae05e01", + "downyServiceBerry_stage03": "https://github.com/user-attachments/assets/4a52742f-e0b0-47e5-99af-41fcdac15d38", + "goldenRain_stage01": "https://github.com/user-attachments/assets/54241e46-2382-4d84-877e-e9aa89d70c4b", + "goldenRain_stage02": "https://github.com/user-attachments/assets/e5e0394d-2815-42d7-82fc-438b07718eb9", + "goldenRain_stage03": "https://github.com/user-attachments/assets/f49311b6-89bd-4ea7-8e34-7e419f388493", + "goldenRain_stage04": "https://github.com/user-attachments/assets/61d3d405-a34b-4dbc-9317-8f4a00b389e9", + "japaneseZelkova_stage01": "https://github.com/user-attachments/assets/f77c4590-e1ce-4b85-beb6-8fc99fb5869a", + "japaneseZelkova_stage02": "https://github.com/user-attachments/assets/3c69ae5f-b0de-42bf-b9b4-948f416d1b17", + "japaneseZelkova_stage03": "https://github.com/user-attachments/assets/c106212f-9831-4d02-9b00-21fd7bf89eee", + "japaneseZelkova_stage04": "https://github.com/user-attachments/assets/3288d14a-e7b5-4e0c-9a67-ab40c3da267f", + "lodgepolePine_stage01": "https://github.com/user-attachments/assets/6ea5cd22-42ea-4409-bbf5-243dd2a3ca1a", + "lodgepolePine_stage02": "https://github.com/user-attachments/assets/fcfa25ad-9c4a-4b4b-8952-076a20a54621", + "lodgepolePine_stage02Var2": "https://github.com/user-attachments/assets/b54dda48-af54-45e3-a048-3879f3e38681", + "lodgepolePine_stage03": "https://github.com/user-attachments/assets/9699c98f-ec94-457d-b567-9d61adc99808", + "lodgepolePine_stage03Var2": "https://github.com/user-attachments/assets/b947361f-ab52-4ce0-b3f9-f0dfecb45517", + "northernCatalpa_stage01": "https://github.com/user-attachments/assets/c2d95dd3-badb-4d20-ba8c-e1963ce3af10", + "northernCatalpa_stage02": "https://github.com/user-attachments/assets/91922759-21d8-408d-925f-4f569e8489a3", + "northernCatalpa_stage03": "https://github.com/user-attachments/assets/e232a83a-6268-43db-869a-8093ccdc74a4", + "northernCatalpa_stage04": "https://github.com/user-attachments/assets/7c1fa393-93e9-433b-8c1d-93336949c8cc", + "oak_stage01": "https://github.com/user-attachments/assets/d89a718f-7267-4c89-89ca-8e3cf0dbb89f", + "oak_stage02": "https://github.com/user-attachments/assets/65650e12-ff6f-4150-bf33-4e0973dbf1f8", + "oak_stage03": "https://github.com/user-attachments/assets/16e99c5f-474d-4b33-b84e-cadc27a42b65", + "oak_stage04": "https://github.com/user-attachments/assets/f7ead2b9-4764-4121-a835-a4338bdb0807", + "oak_stage05": "https://github.com/user-attachments/assets/5e28c082-36fb-4eb2-9c9f-af88da9dc188", + "pinusSylvestris_stage01": "https://github.com/user-attachments/assets/791b15ad-e8d1-4799-9787-3e4818f87a68", + "pinusSylvestris_stage02": "https://github.com/user-attachments/assets/23c6c0f5-5d1b-49aa-ad57-1ac657a6f1e5", + "pinusSylvestris_stage03": "https://github.com/user-attachments/assets/94618c71-9d70-4608-9a4b-828cc15d0d70", + "pinusSylvestris_stage04": "https://github.com/user-attachments/assets/9f91cd22-0f15-482b-a1ad-346589bf6691", + "pinusSylvestris_stage05": "https://github.com/user-attachments/assets/d7b0bdd5-6d36-4f8d-8692-9ac217ac8f41", + "pinusTabuliformis_stage01": "https://github.com/user-attachments/assets/fb884c92-8f06-43ed-bde8-769a071dc1a8", + "pinusTabuliformis_stage02": "https://github.com/user-attachments/assets/2cdf2419-41fd-4c40-9428-04b620dbf29f", + "pinusTabuliformis_stage03": "https://github.com/user-attachments/assets/c36884b4-d3c0-4af5-a9cb-506e4ff8a389", + "pinusTabuliformis_stage04": "https://github.com/user-attachments/assets/20f795ed-4ae4-4ff6-8f47-7a1470cd8202", + "pinusTabuliformis_stage05": "https://github.com/user-attachments/assets/40ded4f7-cf96-4b16-be42-b2d727ad2fab", + "shagbarkHickory_stage01": "https://github.com/user-attachments/assets/80e21d92-6233-4126-b1e3-d5492650c750", + "shagbarkHickory_stage02": "https://github.com/user-attachments/assets/acf77d66-6798-436e-bc1f-86757276f2bf", + "shagbarkHickory_stage03": "https://github.com/user-attachments/assets/9735c5db-3478-41a9-a3ec-e7c15fe10559", + "shagbarkHickory_stage04": "https://github.com/user-attachments/assets/82a8fc7e-92dc-4936-b201-c1e7a5ec915a", + "tiliaAmurensis_stage01": "https://github.com/user-attachments/assets/105f3e6f-b25e-4918-b93b-5c45d382f14f", + "tiliaAmurensis_stage02": "https://github.com/user-attachments/assets/2e3ad498-2d86-434b-89ca-84463ae620d1", + "tiliaAmurensis_stage03": "https://github.com/user-attachments/assets/87993bde-36bf-45aa-b482-2b8288d0cf47", + "tiliaAmurensis_stage04": "https://github.com/user-attachments/assets/06296049-7ce1-4aef-93bc-50e307c36062", + "treesRavaged": "https://github.com/user-attachments/assets/5718f33d-2893-48bb-9029-c011dd8ef241", +}