Prototype > PreAlpha #67
@ -15,7 +15,7 @@ The `app_settings.json` file is structured into several key sections, including:
|
||||
|
||||
### LLM Predictor Settings
|
||||
|
||||
For users who wish to utilize the experimental LLM Predictor feature, the following settings are available in `config/app_settings.json`:
|
||||
For users who wish to utilize the experimental LLM Predictor feature, the following settings are available in `config/llm_settings.json`:
|
||||
|
||||
* `llm_endpoint_url`: The URL of the LLM API endpoint. For local LLMs like LM Studio or Ollama, this will typically be `http://localhost:<port>/v1`. Consult your LLM server documentation for the exact endpoint.
|
||||
* `llm_api_key`: The API key required to access the LLM endpoint. Some local LLM servers may not require a key, in which case this can be left empty.
|
||||
@ -23,15 +23,39 @@ For users who wish to utilize the experimental LLM Predictor feature, the follow
|
||||
* `llm_temperature`: Controls the randomness of the LLM's output. Lower values (e.g., 0.1-0.5) make the output more deterministic and focused, while higher values (e.g., 0.6-1.0) make it more creative and varied. For prediction tasks, lower temperatures are generally recommended.
|
||||
* `llm_request_timeout`: The maximum time (in seconds) to wait for a response from the LLM API. Adjust this based on the performance of your LLM server and the complexity of the requests.
|
||||
|
||||
Note that the `llm_predictor_prompt` and `llm_predictor_examples` settings are also present in `app_settings.json`. These define the instructions and examples provided to the LLM for prediction. While they can be viewed here, they are primarily intended for developer reference and tuning the LLM's behavior, and most users will not need to modify them.
|
||||
Note that the `llm_predictor_prompt` and `llm_predictor_examples` settings are also present in `config/llm_settings.json`. These define the instructions and examples provided to the LLM for prediction. While they can be viewed here, they are primarily intended for developer reference and tuning the LLM's behavior, and most users will not need to modify them directly via the file. These settings are editable via the LLM Editor panel in the main GUI when the LLM interpretation mode is selected.
|
||||
|
||||
## GUI Configuration Editor
|
||||
## Application Preferences (`config/app_settings.json` overrides)
|
||||
|
||||
You can modify the `app_settings.json` file using the built-in GUI editor. Access it via the **Edit** -> **Preferences...** menu.
|
||||
You can modify user-overridable application settings using the built-in GUI editor. These settings are loaded from `config/app_settings.json` and saved as overrides in `config/user_settings.json`. Access it via the **Edit** -> **Preferences...** menu.
|
||||
|
||||
This editor provides a tabbed interface (e.g., "General", "Output & Naming") to view and change the core application settings defined in `app_settings.json`. Settings in the editor directly correspond to the structure and values within the JSON file. Note that any changes made through the GUI editor require an application restart to take effect.
|
||||
This editor provides a tabbed interface to view and change various application behaviors. The tabs include:
|
||||
* **General:** Basic settings like output base directory and temporary file prefix.
|
||||
* **Output & Naming:** Settings controlling output directory and filename patterns, and how variants are handled.
|
||||
* **Image Processing:** Settings related to image resolution definitions, compression levels, and format choices.
|
||||
* **Map Merging:** Configuration for how multiple input maps are combined into single output maps.
|
||||
* **Postprocess Scripts:** Paths to default Blender files for post-processing.
|
||||
|
||||
*(Ideally, a screenshot of the GUI Configuration Editor would be included here.)*
|
||||
Note that this editor focuses on user-specific overrides of core application settings. **Asset Type Definitions, File Type Definitions, and Supplier Settings are managed in a separate Definitions Editor.**
|
||||
|
||||
Any changes made through the Preferences editor require an application restart to take effect.
|
||||
|
||||
*(Ideally, a screenshot of the Application Preferences editor would be included here.)*
|
||||
|
||||
## Definitions Editor (`config/asset_type_definitions.json`, `config/file_type_definitions.json`, `config/suppliers.json`)
|
||||
|
||||
Core application definitions that are separate from general user preferences are managed in the dedicated Definitions Editor. This includes defining known asset types, file types, and configuring settings specific to different suppliers. Access it via the **Edit** -> **Edit Definitions...** menu.
|
||||
|
||||
The editor is organized into three tabs:
|
||||
* **Asset Type Definitions:** Define the different categories of assets (e.g., Surface, Model, Decal). For each asset type, you can configure its description, a color for UI representation, and example usage strings.
|
||||
* **File Type Definitions:** Define the specific types of files the tool recognizes (e.g., MAP_COL, MAP_NRM, MODEL). For each file type, you can configure its description, a color, example keywords/patterns, a standard type alias, bit depth handling rules, whether it's grayscale, and an optional keybind for quick assignment in the GUI.
|
||||
* **Supplier Settings:** Configure settings that are specific to assets originating from different suppliers. Currently, this includes the "Normal Map Type" (OpenGL or DirectX) used for normal maps from that supplier.
|
||||
|
||||
Each tab presents a list of the defined items on the left (Asset Types, File Types, or Suppliers). Selecting an item in the list displays its configurable details on the right. Buttons are provided to add new definitions or remove existing ones.
|
||||
|
||||
Changes made in the Definitions Editor are saved directly to their respective configuration files (`config/asset_type_definitions.json`, `config/file_type_definitions.json`, and `config/suppliers.json`). Some changes may require an application restart to take full effect in processing logic.
|
||||
|
||||
*(Ideally, screenshots of the Definitions Editor tabs would be included here.)*
|
||||
|
||||
## Preset Files (`presets/*.json`)
|
||||
|
||||
|
||||
@ -12,7 +12,10 @@ python -m gui.main_window
|
||||
|
||||
## Interface Overview
|
||||
|
||||
* **Menu Bar:** The "Edit" menu contains the "Preferences..." option to open the GUI Configuration Editor. The "View" menu allows you to toggle the visibility of the Log Console and the Detailed File Preview.
|
||||
* **Menu Bar:** The "Edit" menu contains options to configure application settings and definitions:
|
||||
* **Preferences...:** Opens the Application Preferences editor for user-overridable settings (saved to `config/user_settings.json`).
|
||||
* **Edit Definitions...:** Opens the Definitions Editor for managing Asset Type Definitions, File Type Definitions, and Supplier Settings (saved to their respective files).
|
||||
The "View" menu allows you to toggle the visibility of the Log Console and the Detailed File Preview.
|
||||
* **Preset Editor Panel (Left):**
|
||||
* **Optional Log Console:** Displays application logs (toggle via View menu).
|
||||
* **Preset List:** Create, delete, load, edit, and save presets. On startup, the "-- Select a Preset --" item is explicitly selected. You must select a specific preset from this list to load it into the editor below, enable the detailed file preview, and enable the "Start Processing" button.
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
This document describes the directory structure and contents of the processed assets generated by the Asset Processor Tool.
|
||||
|
||||
Processed assets are saved to a location determined by two global settings defined in `config/app_settings.json`:
|
||||
Processed assets are saved to a location determined by two global settings, `OUTPUT_DIRECTORY_PATTERN` and `OUTPUT_FILENAME_PATTERN`, defined in `config/app_settings.json`. These settings can be overridden by the user via `config/user_settings.json`.
|
||||
|
||||
* `OUTPUT_DIRECTORY_PATTERN`: Defines the directory structure *within* the Base Output Directory.
|
||||
* `OUTPUT_FILENAME_PATTERN`: Defines the naming convention for individual files *within* the directory created by `OUTPUT_DIRECTORY_PATTERN`.
|
||||
@ -23,7 +23,7 @@ The following tokens can be used in both `OUTPUT_DIRECTORY_PATTERN` and `OUTPUT_
|
||||
* `[Time]`: Current time (`HHMMSS`).
|
||||
* `[Sha5]`: The first 5 characters of the SHA-256 hash of the original input source file (e.g., the source zip archive).
|
||||
* `[ApplicationPath]`: Absolute path to the application directory.
|
||||
* `[maptype]`: The standardized map type identifier (e.g., `COL` for Color/Albedo, `NRM` for Normal, `RGH` for Roughness). This is derived from the `standard_type` defined in the application's `FILE_TYPE_DEFINITIONS` (see `config/app_settings.json`) and may include a variant suffix if applicable. (Primarily for filename pattern)
|
||||
* `[maptype]`: The standardized map type identifier (e.g., `COL` for Color/Albedo, `NRM` for Normal, `RGH` for Roughness). This is derived from the `standard_type` defined in the application's `FILE_TYPE_DEFINITIONS` (managed in `config/file_type_definitions.json` via the Definitions Editor) and may include a variant suffix if applicable. (Primarily for filename pattern)
|
||||
* `[dimensions]`: Pixel dimensions (e.g., `2048x2048`).
|
||||
* `[bitdepth]`: Output bit depth (e.g., `8bit`, `16bit`).
|
||||
* `[category]`: Asset category determined by preset rules.
|
||||
@ -51,7 +51,7 @@ The final output path is constructed by combining the Base Output Directory (set
|
||||
* `OUTPUT_FILENAME_PATTERN`: `[maptype].[ext]`
|
||||
* Resulting Path for a Normal map: `Output/Texture/Wood/WoodFloor001/Normal.exr`
|
||||
|
||||
The `<output_base_directory>` (the root folder where processing output starts) is configured separately via the GUI (**Edit** -> **Preferences...** -> **Output & Naming** tab -> **Base Output Directory**) or the `--output` CLI argument. The `OUTPUT_DIRECTORY_PATTERN` defines the structure *within* this base directory, and `OUTPUT_FILENAME_PATTERN` defines the filenames within that structure.
|
||||
The `<output_base_directory>` (the root folder where processing output starts) is configured separately via the GUI (**Edit** -> **Preferences...** -> **General** tab -> **Output Base Directory**) or the `--output` CLI argument. The `OUTPUT_DIRECTORY_PATTERN` defines the structure *within* this base directory, and `OUTPUT_FILENAME_PATTERN` defines the filenames within that structure.
|
||||
|
||||
## Contents of Each Asset Directory
|
||||
|
||||
|
||||
@ -8,45 +8,61 @@ The tool's configuration is managed by the `configuration.py` module and loaded
|
||||
|
||||
### Configuration Files
|
||||
|
||||
1. **Application Settings (`config/app_settings.json`):** This JSON file defines the core global default settings, constants, and rules that apply generally across different asset sources (e.g., the global `OUTPUT_DIRECTORY_PATTERN` and `OUTPUT_FILENAME_PATTERN`, standard image resolutions, map merge rules, output format rules, Blender paths). See the [User Guide: Output Structure](../01_User_Guide/09_Output_Structure.md#available-tokens) for a list of available tokens for these patterns.
|
||||
The tool's configuration is loaded from several JSON files, providing a layered approach for defaults, user overrides, definitions, and source-specific presets.
|
||||
|
||||
1. **Application Settings (`config/app_settings.json`):** This JSON file defines the core global default settings, constants, and rules that apply generally across different asset sources (e.g., the global `OUTPUT_DIRECTORY_PATTERN` and `OUTPUT_FILENAME_PATTERN`, standard image resolutions, map merge rules, output format rules, Blender paths, temporary directory prefix, initial scaling mode, merge dimension mismatch strategy). See the [User Guide: Output Structure](../01_User_Guide/09_Output_Structure.md#available-tokens) for a list of available tokens for these patterns.
|
||||
* *Note:* `ASSET_TYPE_DEFINITIONS` and `FILE_TYPE_DEFINITIONS` are no longer stored here; they have been moved to dedicated files.
|
||||
|
||||
2. **User Settings (`config/user_settings.json`):** This optional JSON file allows users to override specific settings defined in `config/app_settings.json`. If this file exists, its values for corresponding keys will take precedence over the base application settings. This file is primarily managed through the GUI's Configuration Editor.
|
||||
2. **User Settings (`config/user_settings.json`):** This optional JSON file allows users to override specific settings defined in `config/app_settings.json`. If this file exists, its values for corresponding keys will take precedence over the base application settings. This file is primarily managed through the GUI's Application Preferences Editor.
|
||||
|
||||
3. **Asset Type Definitions (`config/asset_type_definitions.json`):** This dedicated JSON file contains the definitions for different asset types (e.g., Surface, Model, Decal), including their descriptions, colors, and examples.
|
||||
3. **Asset Type Definitions (`config/asset_type_definitions.json`):** This dedicated JSON file contains the definitions for different asset types (e.g., Surface, Model, Decal), including their descriptions, colors for UI representation, and example usage strings.
|
||||
|
||||
4. **File Type Definitions (`config/file_type_definitions.json`):** This dedicated JSON file contains the definitions for different file types (specifically texture maps and models), including descriptions, colors, examples, standard aliases, bit depth rules, grayscale flags, and GUI keybinds.
|
||||
* **`keybind` Property:** Each file type object within `FILE_TYPE_DEFINITIONS` can optionally include a `keybind` property. This property accepts a single character string (e.g., `"C"`, `"R"`) representing the keyboard key. In the GUI, this key (typically combined with `Ctrl`, or standalone like `F2` for asset naming) is used as a shortcut to set or toggle the corresponding file type for selected items in the Preview Table.
|
||||
4. **File Type Definitions (`config/file_type_definitions.json`):** This dedicated JSON file contains the definitions for different file types (specifically texture maps and models), including descriptions, colors for UI representation, examples of keywords/patterns, a standard alias (`standard_type`), bit depth handling rules (`bit_depth_rule`), a grayscale flag (`is_grayscale`), and an optional GUI keybind (`keybind`).
|
||||
* **`keybind` Property:** Each file type object within `FILE_TYPE_DEFINITIONS` can optionally include a `keybind` property. This property accepts a single character string (e.g., `"C"`, `"R"`) representing the keyboard key. In the GUI, this key (typically combined with `Ctrl`) is used as a shortcut to set or toggle the corresponding file type for selected items in the Preview Table.
|
||||
*Example:*
|
||||
```json
|
||||
"MAP_COL": {
|
||||
"description": "Color/Albedo Map",
|
||||
"color": [200, 200, 200],
|
||||
"examples": ["albedo", "col", "basecolor"],
|
||||
"color": "#ffaa00",
|
||||
"examples": ["_col.", "_basecolor.", "albedo", "diffuse"],
|
||||
"standard_type": "COL",
|
||||
"bit_depth_rule": "respect",
|
||||
"bit_depth_rule": "force_8bit",
|
||||
"is_grayscale": false,
|
||||
"keybind": "C"
|
||||
},
|
||||
```
|
||||
* **New File Type `MAP_GLOSS`:** A standard file type, `MAP_GLOSS`, is defined here.
|
||||
*Example:*
|
||||
Note: The `bit_depth_rule` property in `FILE_TYPE_DEFINITIONS` is the primary source for determining bit depth handling for a given map type.
|
||||
|
||||
5. **Supplier Settings (`config/suppliers.json`):** This JSON file stores settings specific to different asset suppliers. It is now structured as a dictionary where keys are supplier names and values are objects containing supplier-specific configurations.
|
||||
* **Structure:**
|
||||
```json
|
||||
"MAP_GLOSS": {
|
||||
"description": "Glossiness Map",
|
||||
"color": [180, 180, 220],
|
||||
"examples": ["gloss", "gls"],
|
||||
"standard_type": "GLOSS",
|
||||
"bit_depth_rule": "respect",
|
||||
"is_grayscale": true,
|
||||
"keybind": "R"
|
||||
{
|
||||
"SupplierName1": {
|
||||
"setting_key1": "value",
|
||||
"setting_key2": "value"
|
||||
},
|
||||
"SupplierName2": {
|
||||
"setting_key1": "value"
|
||||
}
|
||||
}
|
||||
```
|
||||
* **`normal_map_type` Property:** A key setting within each supplier's object is `normal_map_type`, specifying whether normal maps from this supplier use "OpenGL" or "DirectX" conventions.
|
||||
*Example:*
|
||||
```json
|
||||
{
|
||||
"Poliigon": {
|
||||
"normal_map_type": "DirectX"
|
||||
},
|
||||
"Dimensiva": {
|
||||
"normal_map_type": "OpenGL"
|
||||
}
|
||||
}
|
||||
```
|
||||
Note: The `keybind` "R" for `MAP_GLOSS` is often shared with `MAP_ROUGH` to allow toggling between them.
|
||||
|
||||
5. **LLM Settings (`config/llm_settings.json`):** This JSON file contains settings specifically related to the LLM predictor, such as the API endpoint, model name, prompt template, and examples. These settings can be edited through the GUI using the `LLMEditorWidget`.
|
||||
6. **LLM Settings (`config/llm_settings.json`):** This JSON file contains settings specifically related to the LLM predictor, such as the API endpoint, model name, prompt template, and examples. These settings are managed through the GUI using the `LLMEditorWidget`.
|
||||
|
||||
7. **Preset Files (`Presets/*.json`):** These JSON files define source-specific rules and overrides. They contain patterns to interpret filenames, classify map types, handle variants, define naming conventions, and specify other source-specific behaviors. Preset settings override values from `app_settings.json` and `user_settings.json` where applicable.
|
||||
|
||||
6. **Preset Files (`Presets/*.json`):** These JSON files define supplier-specific rules and overrides. They contain patterns to interpret filenames, classify map types, handle variants, define naming conventions, and specify other source-specific behaviors. Preset settings override values from `app_settings.json` and `user_settings.json` where applicable.
|
||||
|
||||
### Configuration Loading and Access
|
||||
|
||||
|
||||
@ -10,13 +10,13 @@ The GUI is built using `PySide6`, which provides Python bindings for the Qt fram
|
||||
|
||||
The `MainWindow` class acts as the central **coordinator** for the GUI application. It is responsible for:
|
||||
|
||||
* Setting up the main application window structure and menu bar.
|
||||
* Setting up the main application window structure and menu bar, including actions to launch configuration and definition editors.
|
||||
* **Layout:** Arranging the main GUI components using a `QSplitter`.
|
||||
* **Left Pane:** Contains the preset selection controls (from `PresetEditorWidget`) permanently displayed at the top. Below this, a `QStackedWidget` switches between the preset JSON editor (also from `PresetEditorWidget`) and the `LLMEditorWidget`.
|
||||
* **Right Pane:** Contains the `MainPanelWidget`.
|
||||
* Instantiating and managing the major GUI widgets:
|
||||
* `PresetEditorWidget` (`gui/preset_editor_widget.py`): Provides the preset selector and the JSON editor parts.
|
||||
* `LLMEditorWidget` (`gui/llm_editor_widget.py`): Provides the editor for LLM settings.
|
||||
* `LLMEditorWidget` (`gui/llm_editor_widget.py`): Provides the editor for LLM settings (from `config/llm_settings.json`).
|
||||
* `MainPanelWidget` (`gui/main_panel_widget.py`): Contains the rule hierarchy view and processing controls.
|
||||
* `LogConsoleWidget` (`gui/log_console_widget.py`): Displays application logs.
|
||||
* Instantiating key models and handlers:
|
||||
@ -198,13 +198,24 @@ The `LogConsoleWidget` displays logs captured by a custom `QtLogHandler` from Py
|
||||
|
||||
The GUI provides a "Cancel" button. Cancellation logic for the actual processing is now likely handled within the `main.ProcessingTask` or the code that manages it, as the `ProcessingHandler` has been removed. The GUI button would signal this external task manager.
|
||||
|
||||
## GUI Configuration Editor (`gui/config_editor_dialog.py`)
|
||||
## Application Preferences Editor (`gui/config_editor_dialog.py`)
|
||||
|
||||
A dedicated dialog for editing `config/app_settings.json`.
|
||||
A dedicated dialog for editing user-overridable application settings. It loads base settings from `config/app_settings.json` and saves user overrides to `config/user_settings.json`.
|
||||
|
||||
* **Functionality:** Loads `config/app_settings.json`, presents in tabs, allows editing basic fields, definitions tables (with color editing), and merge rules list/detail.
|
||||
* **Limitations:** Editing complex fields like `IMAGE_RESOLUTIONS` or full `MAP_MERGE_RULES` details might still be limited.
|
||||
* **Integration:** Launched by `MainWindow` ("Edit" -> "Preferences...").
|
||||
* **Persistence:** Saves changes to `config/app_settings.json`. Requires application restart for changes to affect processing logic loaded by the `Configuration` class.
|
||||
* **Functionality:** Provides a tabbed interface to edit various application settings, including general paths, output/naming patterns, image processing options (like resolutions and compression), and map merging rules. It no longer includes editors for Asset Type or File Type Definitions.
|
||||
* **Integration:** Launched by `MainWindow` via the "Edit" -> "Preferences..." menu.
|
||||
* **Persistence:** Saves changes to `config/user_settings.json`. Changes require an application restart to take effect in processing logic.
|
||||
|
||||
The refactored GUI separates concerns into distinct widgets and handlers, coordinated by the `MainWindow`. Background tasks use `QThreadPool` and `QRunnable`. The `UnifiedViewModel` focuses on data presentation and simple edits, delegating complex restructuring to the `AssetRestructureHandler`.
|
||||
The refactored GUI separates concerns into distinct widgets and handlers, coordinated by the `MainWindow`. Background tasks use `QThreadPool` and `QRunnable`. The `UnifiedViewModel` focuses on data presentation and simple edits, delegating complex restructuring to the `AssetRestructureHandler`.
|
||||
|
||||
## Definitions Editor (`gui/definitions_editor_dialog.py`)
|
||||
|
||||
A new dedicated dialog for managing core application definitions that are separate from general user preferences.
|
||||
|
||||
* **Purpose:** Provides a structured UI for editing Asset Type Definitions, File Type Definitions, and Supplier Settings.
|
||||
* **Structure:** Uses a `QTabWidget` with three tabs:
|
||||
* **Asset Type Definitions:** Manages definitions from `config/asset_type_definitions.json`. Presents a list of asset types and allows editing their description, color, and examples.
|
||||
* **File Type Definitions:** Manages definitions from `config/file_type_definitions.json`. Presents a list of file types and allows editing their description, color, examples, standard type, bit depth rule, grayscale status, and keybind.
|
||||
* **Supplier Settings:** Manages settings from `config/suppliers.json`. Presents a list of suppliers and allows editing supplier-specific settings (e.g., Normal Map Type).
|
||||
* **Integration:** Launched by `MainWindow` via the "Edit" -> "Edit Definitions..." menu.
|
||||
* **Persistence:** Saves changes directly to the respective configuration files (`config/asset_type_definitions.json`, `config/file_type_definitions.json`, `config/suppliers.json`). Some changes may require an application restart.
|
||||
@ -1,5 +1,11 @@
|
||||
[
|
||||
"Dimensiva",
|
||||
"Dinesen",
|
||||
"Poliigon"
|
||||
]
|
||||
{
|
||||
"Dimensiva": {
|
||||
"normal_map_type": "OpenGL"
|
||||
},
|
||||
"Dinesen": {
|
||||
"normal_map_type": "OpenGL"
|
||||
},
|
||||
"Poliigon": {
|
||||
"normal_map_type": "OpenGL"
|
||||
}
|
||||
}
|
||||
147
configuration.py
147
configuration.py
@ -13,6 +13,7 @@ LLM_SETTINGS_PATH = BASE_DIR / "config" / "llm_settings.json"
|
||||
ASSET_TYPE_DEFINITIONS_PATH = BASE_DIR / "config" / "asset_type_definitions.json"
|
||||
FILE_TYPE_DEFINITIONS_PATH = BASE_DIR / "config" / "file_type_definitions.json"
|
||||
USER_SETTINGS_PATH = BASE_DIR / "config" / "user_settings.json" # New path for user settings
|
||||
SUPPLIERS_CONFIG_PATH = BASE_DIR / "config" / "suppliers.json"
|
||||
PRESETS_DIR = BASE_DIR / "Presets"
|
||||
|
||||
class ConfigurationError(Exception):
|
||||
@ -801,3 +802,149 @@ def save_base_config(settings_dict: dict):
|
||||
except Exception as e:
|
||||
log.error(f"Failed to save base configuration file {APP_SETTINGS_PATH}: {e}")
|
||||
raise ConfigurationError(f"Failed to save configuration: {e}")
|
||||
|
||||
def load_asset_definitions() -> dict:
|
||||
"""
|
||||
Reads config/asset_type_definitions.json.
|
||||
Returns the dictionary under the "ASSET_TYPE_DEFINITIONS" key.
|
||||
Handles file not found or JSON errors gracefully (e.g., return empty dict, log error).
|
||||
"""
|
||||
log.debug(f"Loading asset type definitions from: {ASSET_TYPE_DEFINITIONS_PATH}")
|
||||
if not ASSET_TYPE_DEFINITIONS_PATH.is_file():
|
||||
log.error(f"Asset type definitions file not found: {ASSET_TYPE_DEFINITIONS_PATH}")
|
||||
return {}
|
||||
try:
|
||||
with open(ASSET_TYPE_DEFINITIONS_PATH, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
if "ASSET_TYPE_DEFINITIONS" not in data:
|
||||
log.error(f"Key 'ASSET_TYPE_DEFINITIONS' not found in {ASSET_TYPE_DEFINITIONS_PATH}")
|
||||
return {}
|
||||
settings = data["ASSET_TYPE_DEFINITIONS"]
|
||||
if not isinstance(settings, dict):
|
||||
log.error(f"'ASSET_TYPE_DEFINITIONS' in {ASSET_TYPE_DEFINITIONS_PATH} must be a dictionary.")
|
||||
return {}
|
||||
log.debug(f"Asset type definitions loaded successfully.")
|
||||
return settings
|
||||
except json.JSONDecodeError as e:
|
||||
log.error(f"Failed to parse asset type definitions file {ASSET_TYPE_DEFINITIONS_PATH}: Invalid JSON - {e}")
|
||||
return {}
|
||||
except Exception as e:
|
||||
log.error(f"Failed to read asset type definitions file {ASSET_TYPE_DEFINITIONS_PATH}: {e}")
|
||||
return {}
|
||||
|
||||
def save_asset_definitions(data: dict):
|
||||
"""
|
||||
Takes a dictionary (representing the content for the "ASSET_TYPE_DEFINITIONS" key).
|
||||
Writes it to config/asset_type_definitions.json under the root key "ASSET_TYPE_DEFINITIONS".
|
||||
Handles potential I/O errors.
|
||||
"""
|
||||
log.debug(f"Saving asset type definitions to: {ASSET_TYPE_DEFINITIONS_PATH}")
|
||||
try:
|
||||
with open(ASSET_TYPE_DEFINITIONS_PATH, 'w', encoding='utf-8') as f:
|
||||
json.dump({"ASSET_TYPE_DEFINITIONS": data}, f, indent=4)
|
||||
log.info(f"Asset type definitions saved successfully to {ASSET_TYPE_DEFINITIONS_PATH}")
|
||||
except Exception as e:
|
||||
log.error(f"Failed to save asset type definitions file {ASSET_TYPE_DEFINITIONS_PATH}: {e}")
|
||||
raise ConfigurationError(f"Failed to save asset type definitions: {e}")
|
||||
|
||||
def load_file_type_definitions() -> dict:
|
||||
"""
|
||||
Reads config/file_type_definitions.json.
|
||||
Returns the dictionary under the "FILE_TYPE_DEFINITIONS" key.
|
||||
Handles errors gracefully.
|
||||
"""
|
||||
log.debug(f"Loading file type definitions from: {FILE_TYPE_DEFINITIONS_PATH}")
|
||||
if not FILE_TYPE_DEFINITIONS_PATH.is_file():
|
||||
log.error(f"File type definitions file not found: {FILE_TYPE_DEFINITIONS_PATH}")
|
||||
return {}
|
||||
try:
|
||||
with open(FILE_TYPE_DEFINITIONS_PATH, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
if "FILE_TYPE_DEFINITIONS" not in data:
|
||||
log.error(f"Key 'FILE_TYPE_DEFINITIONS' not found in {FILE_TYPE_DEFINITIONS_PATH}")
|
||||
return {}
|
||||
settings = data["FILE_TYPE_DEFINITIONS"]
|
||||
if not isinstance(settings, dict):
|
||||
log.error(f"'FILE_TYPE_DEFINITIONS' in {FILE_TYPE_DEFINITIONS_PATH} must be a dictionary.")
|
||||
return {}
|
||||
log.debug(f"File type definitions loaded successfully.")
|
||||
return settings
|
||||
except json.JSONDecodeError as e:
|
||||
log.error(f"Failed to parse file type definitions file {FILE_TYPE_DEFINITIONS_PATH}: Invalid JSON - {e}")
|
||||
return {}
|
||||
except Exception as e:
|
||||
log.error(f"Failed to read file type definitions file {FILE_TYPE_DEFINITIONS_PATH}: {e}")
|
||||
return {}
|
||||
|
||||
def save_file_type_definitions(data: dict):
|
||||
"""
|
||||
Takes a dictionary (representing content for "FILE_TYPE_DEFINITIONS" key).
|
||||
Writes it to config/file_type_definitions.json under the root key "FILE_TYPE_DEFINITIONS".
|
||||
Handles errors.
|
||||
"""
|
||||
log.debug(f"Saving file type definitions to: {FILE_TYPE_DEFINITIONS_PATH}")
|
||||
try:
|
||||
with open(FILE_TYPE_DEFINITIONS_PATH, 'w', encoding='utf-8') as f:
|
||||
json.dump({"FILE_TYPE_DEFINITIONS": data}, f, indent=4)
|
||||
log.info(f"File type definitions saved successfully to {FILE_TYPE_DEFINITIONS_PATH}")
|
||||
except Exception as e:
|
||||
log.error(f"Failed to save file type definitions file {FILE_TYPE_DEFINITIONS_PATH}: {e}")
|
||||
raise ConfigurationError(f"Failed to save file type definitions: {e}")
|
||||
|
||||
def load_supplier_settings() -> dict:
|
||||
"""
|
||||
Reads config/suppliers.json.
|
||||
Returns the entire dictionary.
|
||||
Handles file not found (return empty dict) or JSON errors.
|
||||
If the loaded data is a list (old format), convert it in memory to the new
|
||||
dictionary format, defaulting normal_map_type to "OpenGL" for each supplier.
|
||||
"""
|
||||
log.debug(f"Loading supplier settings from: {SUPPLIERS_CONFIG_PATH}")
|
||||
if not SUPPLIERS_CONFIG_PATH.is_file():
|
||||
log.warning(f"Supplier settings file not found: {SUPPLIERS_CONFIG_PATH}. Returning empty dict.")
|
||||
return {}
|
||||
try:
|
||||
with open(SUPPLIERS_CONFIG_PATH, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if isinstance(data, list):
|
||||
log.warning(f"Supplier settings in {SUPPLIERS_CONFIG_PATH} is in the old list format. Converting to new dictionary format.")
|
||||
new_data = {}
|
||||
for supplier_name in data:
|
||||
if isinstance(supplier_name, str):
|
||||
new_data[supplier_name] = {"normal_map_type": "OpenGL"}
|
||||
else:
|
||||
log.warning(f"Skipping non-string item '{supplier_name}' during old format conversion of supplier settings.")
|
||||
log.info(f"Supplier settings converted to new format: {new_data}")
|
||||
return new_data
|
||||
|
||||
if not isinstance(data, dict):
|
||||
log.error(f"Supplier settings in {SUPPLIERS_CONFIG_PATH} must be a dictionary. Found {type(data)}. Returning empty dict.")
|
||||
return {}
|
||||
|
||||
log.debug(f"Supplier settings loaded successfully.")
|
||||
return data
|
||||
except json.JSONDecodeError as e:
|
||||
log.error(f"Failed to parse supplier settings file {SUPPLIERS_CONFIG_PATH}: Invalid JSON - {e}. Returning empty dict.")
|
||||
return {}
|
||||
except Exception as e:
|
||||
log.error(f"Failed to read supplier settings file {SUPPLIERS_CONFIG_PATH}: {e}. Returning empty dict.")
|
||||
return {}
|
||||
|
||||
def save_supplier_settings(data: dict):
|
||||
"""
|
||||
Takes a dictionary (in the new format).
|
||||
Writes it directly to config/suppliers.json.
|
||||
Handles errors.
|
||||
"""
|
||||
log.debug(f"Saving supplier settings to: {SUPPLIERS_CONFIG_PATH}")
|
||||
if not isinstance(data, dict):
|
||||
log.error(f"Data for save_supplier_settings must be a dictionary. Got {type(data)}.")
|
||||
raise ConfigurationError(f"Invalid data type for saving supplier settings: {type(data)}")
|
||||
try:
|
||||
with open(SUPPLIERS_CONFIG_PATH, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, indent=2) # Using indent=2 as per the example for suppliers.json
|
||||
log.info(f"Supplier settings saved successfully to {SUPPLIERS_CONFIG_PATH}")
|
||||
except Exception as e:
|
||||
log.error(f"Failed to save supplier settings file {SUPPLIERS_CONFIG_PATH}: {e}")
|
||||
raise ConfigurationError(f"Failed to save supplier settings: {e}")
|
||||
|
||||
137
documentation/definitions_editor_plan.md
Normal file
137
documentation/definitions_editor_plan.md
Normal file
@ -0,0 +1,137 @@
|
||||
# Plan for New Definitions Editor UI
|
||||
|
||||
## 1. Overview
|
||||
|
||||
This document outlines the plan to create a new, dedicated UI for managing "Asset Type Definitions", "File Type Definitions", and "Supplier Settings". This editor will provide a more structured and user-friendly way to manage these core application configurations, which are currently stored in separate JSON files.
|
||||
|
||||
## 2. General Design Principles
|
||||
|
||||
* **Dedicated Dialog:** The editor will be a new `QDialog` (e.g., `DefinitionsEditorDialog`).
|
||||
* **Access Point:** Launched from the `MainWindow` menu bar (e.g., under a "Definitions" menu or "Edit" -> "Edit Definitions...").
|
||||
* **Tabbed Interface:** The dialog will use a `QTabWidget` to separate the management of different definition types.
|
||||
* **List/Details View:** Each tab will generally follow a two-pane layout:
|
||||
* **Left Pane:** A `QListWidget` displaying the primary keys or names of the definitions (e.g., asset type names, file type IDs, supplier names). Includes "Add" and "Remove" buttons for managing these primary entries.
|
||||
* **Right Pane:** A details area (e.g., `QGroupBox` with a `QFormLayout`) that shows the specific settings for the item selected in the left-pane list.
|
||||
* **Data Persistence:** The dialog will load from and save to the respective JSON configuration files:
|
||||
* Asset Types: `config/asset_type_definitions.json`
|
||||
* File Types: `config/file_type_definitions.json`
|
||||
* Supplier Settings: `config/suppliers.json` (This file will be refactored from a simple list to a dictionary of supplier objects).
|
||||
* **User Experience:** Standard "Save" and "Cancel" buttons, with a check for unsaved changes.
|
||||
|
||||
## 3. Tab-Specific Plans
|
||||
|
||||
### 3.1. Asset Type Definitions Tab
|
||||
|
||||
* **Manages:** `config/asset_type_definitions.json`
|
||||
* **UI Sketch:**
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph AssetTypeTab [Asset Type Definitions Tab]
|
||||
direction LR
|
||||
AssetList[QListWidget (Asset Type Keys e.g., "Surface")] --> AssetDetailsGroup{Details for Selected Asset Type};
|
||||
end
|
||||
|
||||
subgraph AssetDetailsGroup
|
||||
direction TB
|
||||
Desc[Description: QTextEdit]
|
||||
Color[Color: QPushButton ("Choose Color...") + Color Swatch Display]
|
||||
Examples[Examples: QListWidget + Add/Remove Example Buttons]
|
||||
end
|
||||
AssetActions["Add Asset Type (Prompt for Name)\nRemove Selected Asset Type"] --> AssetList
|
||||
```
|
||||
* **Details:**
|
||||
* **Left Pane:** `QListWidget` for asset type names. "Add Asset Type" (prompts for new key) and "Remove Selected Asset Type" buttons.
|
||||
* **Right Pane (Details):**
|
||||
* `description`: `QTextEdit`.
|
||||
* `color`: `QPushButton` opening `QColorDialog`, with an adjacent `QLabel` to display the color swatch.
|
||||
* `examples`: `QListWidget` with "Add Example" (`QInputDialog.getText`) and "Remove Selected Example" buttons.
|
||||
|
||||
### 3.2. File Type Definitions Tab
|
||||
|
||||
* **Manages:** `config/file_type_definitions.json`
|
||||
* **UI Sketch:**
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph FileTypeTab [File Type Definitions Tab]
|
||||
direction LR
|
||||
FileList[QListWidget (File Type Keys e.g., "MAP_COL")] --> FileDetailsGroup{Details for Selected File Type};
|
||||
end
|
||||
|
||||
subgraph FileDetailsGroup
|
||||
direction TB
|
||||
DescF[Description: QTextEdit]
|
||||
ColorF[Color: QPushButton ("Choose Color...") + Color Swatch Display]
|
||||
ExamplesF[Examples: QListWidget + Add/Remove Example Buttons]
|
||||
StdType[Standard Type: QLineEdit]
|
||||
BitDepth[Bit Depth Rule: QComboBox ("respect", "force_8bit", "force_16bit")]
|
||||
IsGrayscale[Is Grayscale: QCheckBox]
|
||||
Keybind[Keybind: QLineEdit (1 char)]
|
||||
end
|
||||
FileActions["Add File Type (Prompt for ID)\nRemove Selected File Type"] --> FileList
|
||||
```
|
||||
* **Details:**
|
||||
* **Left Pane:** `QListWidget` for file type IDs. "Add File Type" (prompts for new key) and "Remove Selected File Type" buttons.
|
||||
* **Right Pane (Details):**
|
||||
* `description`: `QTextEdit`.
|
||||
* `color`: `QPushButton` opening `QColorDialog`, with an adjacent `QLabel` for color swatch.
|
||||
* `examples`: `QListWidget` with "Add Example" and "Remove Selected Example" buttons.
|
||||
* `standard_type`: `QLineEdit`.
|
||||
* `bit_depth_rule`: `QComboBox` (options: "respect", "force_8bit", "force_16bit").
|
||||
* `is_grayscale`: `QCheckBox`.
|
||||
* `keybind`: `QLineEdit` (validation for single character recommended).
|
||||
|
||||
### 3.3. Supplier Settings Tab
|
||||
|
||||
* **Manages:** `config/suppliers.json` (This file will be refactored to a dictionary structure, e.g., `{"SupplierName": {"normal_map_type": "OpenGL", ...}}`).
|
||||
* **UI Sketch:**
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph SupplierTab [Supplier Settings Tab]
|
||||
direction LR
|
||||
SupplierList[QListWidget (Supplier Names)] --> SupplierDetailsGroup{Details for Selected Supplier};
|
||||
end
|
||||
|
||||
subgraph SupplierDetailsGroup
|
||||
direction TB
|
||||
NormalMapType[Normal Map Type: QComboBox ("OpenGL", "DirectX")]
|
||||
%% Future supplier-specific settings can be added here
|
||||
end
|
||||
SupplierActions["Add Supplier (Prompt for Name)\nRemove Selected Supplier"] --> SupplierList
|
||||
```
|
||||
* **Details:**
|
||||
* **Left Pane:** `QListWidget` for supplier names. "Add Supplier" (prompts for new name) and "Remove Selected Supplier" buttons.
|
||||
* **Right Pane (Details):**
|
||||
* `normal_map_type`: `QComboBox` (options: "OpenGL", "DirectX"). Default for new suppliers: "OpenGL".
|
||||
* *(Space for future supplier-specific settings).*
|
||||
* **Data Handling Note for `config/suppliers.json`:**
|
||||
* The editor will load from and save to `config/suppliers.json` using the new dictionary format (supplier name as key, object of settings as value).
|
||||
* Initial implementation might require `config/suppliers.json` to be manually updated to this new format if it currently exists as a simple list. Alternatively, the editor could attempt an automatic conversion on first load if the old list format is detected, or prompt the user. For the first pass, assuming the editor works with the new format is simpler.
|
||||
|
||||
## 4. Implementation Steps (High-Level)
|
||||
|
||||
1. **(Potentially Manual First Step) Refactor `config/suppliers.json`:** If `config/suppliers.json` exists as a list, manually convert it to the new dictionary structure (e.g., `{"SupplierName": {"normal_map_type": "OpenGL"}}`) before starting UI development for this tab, or plan for the editor to handle this conversion.
|
||||
2. **Create `DefinitionsEditorDialog` Class:** Inherit from `QDialog`.
|
||||
3. **Implement UI Structure:** Main `QTabWidget`, and for each tab, the two-pane layout with `QListWidget`, `QGroupBox` for details, and relevant input widgets (`QLineEdit`, `QTextEdit`, `QComboBox`, `QCheckBox`, `QPushButton`).
|
||||
4. **Implement Loading Logic:**
|
||||
* For each tab, read data from its corresponding JSON file.
|
||||
* Populate the left-pane `QListWidget` with the primary keys/names.
|
||||
* Store the full data structure internally (e.g., in dictionaries within the dialog instance).
|
||||
5. **Implement Display Logic:**
|
||||
* When an item is selected in a `QListWidget`, populate the right-pane detail fields with the data for that item.
|
||||
6. **Implement Editing Logic:**
|
||||
* Ensure that changes made in the detail fields (text edits, combobox selections, checkbox states, color choices, list example modifications) update the corresponding internal data structure for the currently selected item.
|
||||
7. **Implement Add/Remove Functionality:**
|
||||
* For each definition type (Asset Type, File Type, Supplier), implement the "Add" and "Remove" buttons.
|
||||
* "Add": Prompt for a unique key/name, create a new default entry in the internal data, and add it to the `QListWidget`.
|
||||
* "Remove": Remove the selected item from the `QListWidget` and the internal data.
|
||||
* For "examples" lists within Asset and File types, implement their "Add Example" and "Remove Selected Example" buttons.
|
||||
8. **Implement Saving Logic:**
|
||||
* When the main "Save" button is clicked:
|
||||
* Write the (potentially modified) Asset Type definitions data structure to `config/asset_type_definitions.json`.
|
||||
* Write File Type definitions to `config/file_type_definitions.json`.
|
||||
* Write Supplier settings (in the new dictionary format) to `config/suppliers.json`.
|
||||
* Consider creating new dedicated save functions in `configuration.py` for each of these files if they don't already exist or if existing ones are not suitable.
|
||||
9. **Implement Unsaved Changes Check & Cancel Logic.**
|
||||
10. **Integrate Dialog Launch:** Add a menu action in `MainWindow.py` to open the `DefinitionsEditorDialog`.
|
||||
|
||||
This plan provides a comprehensive approach to creating a dedicated editor for these crucial application definitions.
|
||||
File diff suppressed because it is too large
Load Diff
1068
gui/definitions_editor_dialog.py
Normal file
1068
gui/definitions_editor_dialog.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -27,6 +27,7 @@ from .llm_editor_widget import LLMEditorWidget
|
||||
from .log_console_widget import LogConsoleWidget
|
||||
from .main_panel_widget import MainPanelWidget
|
||||
|
||||
from .definitions_editor_dialog import DefinitionsEditorDialog
|
||||
# --- Backend Imports for Data Structures ---
|
||||
from rule_structure import SourceRule, AssetRule, FileRule
|
||||
|
||||
@ -861,6 +862,11 @@ class MainWindow(QMainWindow):
|
||||
self.preferences_action = QAction("&Preferences...", self)
|
||||
self.preferences_action.triggered.connect(self._open_config_editor)
|
||||
edit_menu.addAction(self.preferences_action)
|
||||
edit_menu.addSeparator()
|
||||
|
||||
self.definitions_editor_action = QAction("Edit Definitions...", self)
|
||||
self.definitions_editor_action.triggered.connect(self._open_definitions_editor)
|
||||
edit_menu.addAction(self.definitions_editor_action)
|
||||
|
||||
view_menu = self.menu_bar.addMenu("&View")
|
||||
|
||||
@ -904,6 +910,17 @@ class MainWindow(QMainWindow):
|
||||
log.exception(f"Error opening configuration editor dialog: {e}")
|
||||
QMessageBox.critical(self, "Error", f"An error occurred while opening the configuration editor:\n{e}")
|
||||
|
||||
@Slot() # PySide6.QtCore.Slot
|
||||
def _open_definitions_editor(self):
|
||||
log.debug("Opening Definitions Editor dialog.")
|
||||
try:
|
||||
# DefinitionsEditorDialog is imported at the top of the file
|
||||
dialog = DefinitionsEditorDialog(self)
|
||||
dialog.exec_() # Use exec_() for modal dialog
|
||||
log.debug("Definitions Editor dialog closed.")
|
||||
except Exception as e:
|
||||
log.exception(f"Error opening Definitions Editor dialog: {e}")
|
||||
QMessageBox.critical(self, "Error", f"An error occurred while opening the Definitions Editor:\n{e}")
|
||||
|
||||
@Slot(bool)
|
||||
def _toggle_log_console_visibility(self, checked):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user