Prototype > PreAlpha #67

Merged
Rusfort merged 54 commits from Dev into Stable 2025-05-15 09:10:54 +02:00
9 changed files with 41 additions and 84 deletions
Showing only changes of commit 5707867942 - Show all commits

View File

@ -37,12 +37,13 @@ The pipeline steps are:
* Resizes images based on `Configuration`.
* Determines output bit depth and format based on `Configuration` and `SourceRule`.
* Converts data types and saves images (`cv2.imwrite`).
* The output filename uses the `standard_type` alias (e.g., `COL`, `NRM`) retrieved from the `Configuration.FILE_TYPE_DEFINITIONS` based on the file's effective `item_type`.
* Calculates image statistics.
* Stores processed map details.
7. **Map Merging (`_merge_maps_from_source`)**:
* Iterates through `MAP_MERGE_RULES` in `Configuration`.
* Identifies required source maps based on `SourceRule`.
* Identifies required source maps by checking the `item_type_override` within the `SourceRule` (specifically in the `FileRule` for each file). Files with a base `item_type` of `"FILE_IGNORE"` are explicitly excluded from consideration.
* Loads source channels, handling missing inputs with defaults from `Configuration` or `SourceRule`.
* Merges channels (`cv2.merge`).
* Determines output format/bit depth and saves the merged map.

View File

@ -166,9 +166,6 @@ class Configuration:
# Store the rule for potential priority access later (optional, index is now in tuple)
# self._map_type_rule_order.append(mapping_rule)
if target_type not in self.standard_map_types:
log.warning(f"Map rule {rule_index} uses target_type '{target_type}' which is not in core config STANDARD_MAP_TYPES. Classification might be incomplete.")
# Continue processing anyway, as it might be intended for merging etc.
# Compile keywords for this rule and store with context
for keyword in source_keywords:
@ -291,9 +288,6 @@ class Configuration:
def image_resolutions(self) -> dict[str, int]:
return self._core_settings['IMAGE_RESOLUTIONS']
@property
def standard_map_types(self) -> list[str]:
return self._core_settings['STANDARD_MAP_TYPES']
@property
def map_type_mapping(self) -> list:

View File

@ -282,10 +282,6 @@ class ConfigEditorDialog(QDialog):
standard_maps_label = QLabel("Standard Map Types:")
standard_maps_layout.addWidget(standard_maps_label)
self.standard_map_types_list = QListWidget()
self.standard_map_types_list.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # Allow list to expand
standard_maps_layout.addWidget(self.standard_map_types_list)
self.widgets["STANDARD_MAP_TYPES_LIST"] = self.standard_map_types_list # Store list widget reference
standard_maps_button_layout = QHBoxLayout()
add_button = QPushButton("Add")
@ -1080,10 +1076,6 @@ class ConfigEditorDialog(QDialog):
elif key == "MAP_BIT_DEPTH_RULES" and "MAP_BIT_DEPTH_RULES_TABLE" in self.widgets:
self.populate_map_bit_depth_rules_table(self.widgets["MAP_BIT_DEPTH_RULES_TABLE"], value)
elif key == "STANDARD_MAP_TYPES" and "STANDARD_MAP_TYPES_LIST" in self.widgets and isinstance(value, list):
self.widgets["STANDARD_MAP_TYPES_LIST"].addItems(value)
# Populate DEFAULT_ASSET_CATEGORY ComboBox from Asset Types table (deferred)
# This will be done after the Asset Types table is populated.
elif key == "MAP_MERGE_RULES" and hasattr(self, 'merge_rules_list'): # Check if the list widget exists
self.populate_merge_rules_list(value)

View File

@ -255,7 +255,7 @@ class ItemTypeSearchDelegate(QStyledItemDelegate):
value_to_set = final_text if final_text else None # Set None if empty after stripping
# Set data in the model
# The model's setData handles updating the override and standard_map_type
# The model's setData handles updating the override and item_type
model.setData(index, value_to_set, Qt.EditRole)
# DO NOT add to a persistent list or save back to config

View File

@ -348,7 +348,6 @@ class LLMPredictionHandler(BasePredictionHandler):
target_asset_name_override=asset_name, # Default to asset name
output_format_override=None,
is_gloss_source=False, # LLM doesn't predict this
standard_map_type=None, # LLM doesn't predict this directly
resolution_override=None,
channel_merge_instructions={}
)

View File

@ -441,13 +441,9 @@ class RuleBasedPredictionHandler(BasePredictionHandler):
log.warning(f"Predicted ItemType '{base_item_type}' (checked as '{final_item_type}') for file '{file_info['file_path']}' is not in FILE_TYPE_DEFINITIONS. Setting to FILE_IGNORE.")
final_item_type = "FILE_IGNORE"
standard_map_type = None
file_type_details = file_type_definitions.get(final_item_type)
if file_type_details: standard_map_type = file_type_details.get('standard_type')
else:
file_type_details_alias = file_type_definitions.get(base_item_type)
if file_type_details_alias: standard_map_type = file_type_details_alias.get('standard_type')
elif base_item_type in file_type_definitions: standard_map_type = base_item_type
# standard_map_type is no longer stored on FileRule
# It will be looked up from config when needed for naming/output
# Remove the logic that determined and assigned it here.
is_gloss_source_value = file_info.get('is_gloss_source', False)
@ -458,7 +454,6 @@ class RuleBasedPredictionHandler(BasePredictionHandler):
target_asset_name_override=target_asset_name_override,
output_format_override=None,
is_gloss_source=is_gloss_source_value if isinstance(is_gloss_source_value, bool) else False,
standard_map_type=standard_map_type,
resolution_override=None,
channel_merge_instructions={},
)

View File

@ -415,47 +415,16 @@ class UnifiedViewModel(QAbstractItemModel):
if new_value == "": new_value = None # Treat empty string as None
# Update item_type_override
if item.item_type_override != new_value:
log.debug(f"setData COL_ITEM_TYPE: File='{Path(item.file_path).name}', Original Override='{item.item_type_override}', Original Standard='{getattr(item, 'standard_map_type', 'N/A')}', New Value='{new_value}'") # DEBUG LOG - Added getattr for safety
log.debug(f"setData COL_ITEM_TYPE: File='{Path(item.file_path).name}', Original Override='{item.item_type_override}', New Value='{new_value}'") # DEBUG LOG
old_override = item.item_type_override # Store old value for logging
item.item_type_override = new_value
changed = True
# --- BEGIN FIX: Update standard_map_type ---
try:
base_config = load_base_config()
file_type_definitions = base_config.get('FILE_TYPE_DEFINITIONS', {})
# standard_map_type is no longer stored on FileRule.
# Remove the logic that updated it here.
pass # No action needed to update standard_map_type
# Determine the type to look up (override first, then original)
type_to_lookup = new_value if new_value is not None else item.item_type
new_standard_type = None
if type_to_lookup:
type_info = file_type_definitions.get(type_to_lookup)
if type_info:
new_standard_type = type_info.get("standard_type")
# If standard_type itself is missing in the definition, treat as None or keep old? Let's default to None.
if new_standard_type is None:
log.warning(f"setData: No 'standard_type' defined for item type '{type_to_lookup}' in FILE_TYPE_DEFINITIONS.")
else:
log.warning(f"setData: Item type '{type_to_lookup}' not found in FILE_TYPE_DEFINITIONS.")
# Fallback: Keep the existing standard_map_type if lookup fails completely
new_standard_type = getattr(item, 'standard_map_type', None)
else:
# If both override and original type are None, standard type should be None
new_standard_type = None
# Update the standard_map_type if it changed or needs setting
current_standard_type = getattr(item, 'standard_map_type', None)
if current_standard_type != new_standard_type:
item.standard_map_type = new_standard_type
log.debug(f"setData: Updated standard_map_type from '{current_standard_type}' to '{new_standard_type}' for file '{Path(item.file_path).name}' based on type '{type_to_lookup}'")
# No need to set 'changed = True' again, already set above
except Exception as e:
log.exception(f"setData: Error updating standard_map_type for file '{Path(item.file_path).name}': {e}")
# --- END FIX ---
log.debug(f"setData COL_ITEM_TYPE: File='{Path(item.file_path).name}', Final Override='{item.item_type_override}', Final Standard='{getattr(item, 'standard_map_type', 'N/A')}'") # DEBUG LOG - Updated
log.debug(f"setData COL_ITEM_TYPE: File='{Path(item.file_path).name}', Final Override='{item.item_type_override}'") # DEBUG LOG - Updated
if changed:
@ -653,17 +622,9 @@ class UnifiedViewModel(QAbstractItemModel):
existing_file.item_type = new_file.item_type
changed_roles.extend([Qt.DisplayRole, Qt.EditRole, Qt.BackgroundRole]) # Include BackgroundRole for color
# Update standard_map_type (assuming it's derived/set during prediction)
# Check if standard_map_type exists on both objects before comparing
new_standard_type = getattr(new_file, 'standard_map_type', None)
old_standard_type = getattr(existing_file, 'standard_map_type', None)
if old_standard_type != new_standard_type:
# Update only if item_type_override is not set, as override dictates standard type
if existing_file.item_type_override is None:
existing_file.standard_map_type = new_standard_type
# standard_map_type might not directly affect display, but item_type change covers it
if Qt.DisplayRole not in changed_roles: # Avoid duplicates
changed_roles.extend([Qt.DisplayRole, Qt.EditRole])
# standard_map_type is no longer stored on FileRule.
# Remove the logic that updated it during merge.
pass # No action needed for standard_map_type during merge
# Emit dataChanged only if something actually changed

View File

@ -893,13 +893,21 @@ class ProcessingEngine:
for file_rule in asset_rule.files:
# --- Check if this file should be processed individually ---
# Skip if no item type is assigned, if it's explicitly "EXTRA", or if marked to skip
# Check if this file should be processed individually or skipped
should_skip = (
file_rule.item_type_override is None or
file_rule.item_type_override == "EXTRA" or # Explicitly skip "EXTRA" type
getattr(file_rule, 'skip_processing', False)
getattr(file_rule, 'skip_processing', False) or
(hasattr(file_rule, 'file_type') and file_rule.file_type == "FILE_IGNORE") # Skip files marked as FILE_IGNORE
)
if should_skip:
log.debug(f"Skipping individual processing for {file_rule.file_path} (ItemTypeOverride: {file_rule.item_type_override}, SkipProcessing: {getattr(file_rule, 'skip_processing', False)})")
skip_reason = []
if file_rule.item_type_override is None: skip_reason.append("No ItemTypeOverride")
if file_rule.item_type_override == "EXTRA": skip_reason.append("Explicitly EXTRA type")
if getattr(file_rule, 'skip_processing', False): skip_reason.append("SkipProcessing flag set")
if hasattr(file_rule, 'file_type') and file_rule.file_type == "FILE_IGNORE": skip_reason.append("FILE_IGNORE type")
log.debug(f"Skipping individual processing for {file_rule.file_path} ({', '.join(skip_reason)})")
continue # Skip to the next file_rule
# --- Proceed with processing for this file_rule ---
@ -974,8 +982,13 @@ class ProcessingEngine:
# Get bit depth rule solely from the static configuration using the correct method signature
bit_depth_rule = self.config_obj.get_bit_depth_rule(map_type) # Pass only map_type
# Determine the map_type to use for saving (prioritize standard_map_type)
save_map_type = file_rule.standard_map_type if file_rule.standard_map_type else map_type
# Determine the map_type to use for saving (use item_type_override)
save_map_type = file_rule.item_type_override
# If item_type_override is None, this file shouldn't be saved as an individual map.
# This case should ideally be caught by the skip logic earlier, but adding a check here for safety.
if save_map_type is None:
log.warning(f"Skipping save for {file_rule.file_path}: item_type_override is None.")
continue # Skip saving this file
save_result = self._save_image(
image_data=img_resized,
@ -1060,15 +1073,18 @@ class ProcessingEngine:
found_rule_for_type = False
# Search in the asset_rule's files
for file_rule in asset_rule.files:
# Check if the file_rule's standard_map_type matches the required input type
# This uses the new alias system for exact matching
if hasattr(file_rule, 'standard_map_type') and file_rule.standard_map_type == input_type:
# TODO: Add prioritization logic if multiple files match (e.g., prefer non-gloss rough if gloss exists but isn't needed?)
# For now, take the first match.
# Check if the file_rule's item_type_override matches the required input type
item_override = getattr(file_rule, 'item_type_override', None)
item_base_type = getattr(file_rule, 'item_type', None) # Get base type for ignore check
# Check if override matches the required input type AND the base type is not FILE_IGNORE
if item_override == input_type and item_base_type != "FILE_IGNORE":
# Found a valid match based on item_type_override and not ignored
required_input_file_rules[input_type] = file_rule
found_rule_for_type = True
log.debug(f"Found source FileRule for merge input '{input_type}': {file_rule.file_path} (StandardMapType: {file_rule.standard_map_type})") # Use standard_map_type in log
break # Found the first matching source for this input type
# Update log message (see step 2)
log.debug(f"Found source FileRule for merge input '{input_type}': {file_rule.file_path} (ItemTypeOverride: {item_override}, ItemType: {item_base_type})")
break # Take the first valid match found
if not found_rule_for_type:
log.warning(f"Asset '{asset_name}': Required source FileRule for input map type '{input_type}' not found in AssetRule. Cannot perform merge for '{output_map_type}'.")
possible_to_find_sources = False

View File

@ -11,7 +11,6 @@ class FileRule:
channel_merge_instructions: Dict[str, Any] = dataclasses.field(default_factory=dict)
output_format_override: str = None # Potentially others identified during integration
is_gloss_source: bool = False # Added flag to indicate if source is glossiness
standard_map_type: Optional[str] = None # Added for map type unification
def to_json(self) -> str:
return json.dumps(dataclasses.asdict(self), indent=4)