Gui Regression Fixes

This commit is contained in:
Rusfort 2025-04-30 17:30:51 +02:00
parent a6dc49ebb1
commit 153e464387
7 changed files with 130 additions and 62 deletions

View File

@ -43,8 +43,7 @@
"keywords": [ "keywords": [
"NORMAL*", "NORMAL*",
"NORM*", "NORM*",
"NRM*", "NRM*"
"N"
] ]
}, },
{ {

Binary file not shown.

View File

@ -232,18 +232,60 @@ class AssetProcessor:
File-specific > Asset-specific > Source/General Rules > Config Default. File-specific > Asset-specific > Source/General Rules > Config Default.
""" """
# Prioritize File > Asset > Source > Config # Prioritize File > Asset > Source > Config
if file_path and rule_key in rules.file_rules.get(str(file_path), {}): # Prioritize File > Asset > Source > Config
log.debug(f"Rule '{rule_key}' found at File level for '{file_path}'.") # Check File-specific rules by iterating through AssetRule and FileRule objects
return rules.file_rules[str(file_path)][rule_key] if file_path and rules.assets: # Check if file_path is provided and there are assets to search
if asset_name and rule_key in rules.asset_rules.get(asset_name, {}): log.debug(f"Checking File level rules for '{file_path}'...")
log.debug(f"Rule '{rule_key}' found at Asset level for '{asset_name}'.") for asset_rule in rules.assets:
return rules.asset_rules[asset_name][rule_key] # Check if the current asset_rule matches the asset_name being processed
# This requires asset_name to be passed correctly to this method
if asset_name and asset_rule.asset_name == asset_name:
log.debug(f" Found matching AssetRule for '{asset_name}'. Checking its files...")
for file_rule in asset_rule.files:
# Check if the file_rule's path matches the file_path being processed
if file_rule.file_path and Path(file_rule.file_path) == file_path:
log.debug(f" Found matching FileRule for '{file_path}'. Checking for rule_key '{rule_key}'.")
# Check if rule_key is in channel_merge_instructions
if rule_key in file_rule.channel_merge_instructions:
log.debug(f" Rule '{rule_key}' found in channel_merge_instructions.")
return file_rule.channel_merge_instructions[rule_key]
# Check if rule_key is a direct attribute of FileRule (e.g., map_type_override)
if hasattr(file_rule, rule_key) and getattr(file_rule, rule_key) is not None:
log.debug(f" Rule '{rule_key}' found as direct attribute in FileRule.")
return getattr(file_rule, rule_key)
log.debug(f" Rule '{rule_key}' not found in matching FileRule for '{file_path}'.")
# Found the file rule, but the key wasn't there, so no need to check other files for this asset
break
# Found the asset rule, checked its files, now break from asset loop
break
# Check Asset-specific rules by iterating through the list of AssetRule objects
# Check Asset-specific rules by iterating through the list of AssetRule objects
if asset_name and rules.assets:
for asset_rule in rules.assets:
if asset_rule.asset_name == asset_name:
log.debug(f"Found matching AssetRule for '{asset_name}'. Checking for rule_key '{rule_key}'.")
# Check if rule_key is a direct attribute of AssetRule
if hasattr(asset_rule, rule_key) and getattr(asset_rule, rule_key) is not None:
log.debug(f"Rule '{rule_key}' found as direct attribute in AssetRule for '{asset_name}'.")
return getattr(asset_rule, rule_key)
# Check if rule_key is in common_metadata
if rule_key in asset_rule.common_metadata:
log.debug(f"Rule '{rule_key}' found in common_metadata for '{asset_name}'.")
return asset_rule.common_metadata[rule_key]
log.debug(f"Rule '{rule_key}' not found in matching AssetRule for '{asset_name}'.")
break # Found the asset rule, but the key wasn't there, so no need to continue searching assets
if rule_key in rules.high_level_sorting_parameters: if rule_key in rules.high_level_sorting_parameters:
log.debug(f"Rule '{rule_key}' found at Source level.") log.debug(f"Rule '{rule_key}' found at Source level.")
return rules.high_level_sorting_parameters[rule_key] return rules.high_level_sorting_parameters[rule_key]
# Fallback to config # Fallback to config
log.debug(f"Rule '{rule_key}' not found in rules, falling back to config default.") log.debug(f"Rule '{rule_key}' not found in rules, falling back to config default.")
return getattr(self.config, rule_key, default) config_default = getattr(self.config, rule_key, default)
# If the default is a callable method on the config object, call it
if callable(config_default) and hasattr(self.config, rule_key):
log.debug(f"Config default for '{rule_key}' is a callable method. Calling it.")
return config_default()
return config_default
# --- New Helper Function: Load and Transform Source --- # --- New Helper Function: Load and Transform Source ---
@ -1058,18 +1100,27 @@ class AssetProcessor:
for kw_regex, original_keyword, rule_index in regex_tuples: for kw_regex, original_keyword, rule_index in regex_tuples:
if kw_regex.search(file_stem): if kw_regex.search(file_stem):
# --- DIAGNOSTIC LOGGING START ---
log.debug(f" Checking file '{file_rel_path.name}' against keyword '{original_keyword}' (rule {rule_index}, pattern: '{kw_regex.pattern}') for base type '{base_map_type}'")
# --- DIAGNOSTIC LOGGING END ---
log.debug(f" Match found: '{file_rel_path}' matches keyword '{original_keyword}' (rule {rule_index}, pattern: '{kw_regex.pattern}') for base type '{base_map_type}'") log.debug(f" Match found: '{file_rel_path}' matches keyword '{original_keyword}' (rule {rule_index}, pattern: '{kw_regex.pattern}') for base type '{base_map_type}'")
# Find the index of the matched keyword within its rule's list # Find the index of the matched keyword within its rule's list
keyword_index_in_rule = -1 # Default if not found keyword_index_in_rule = -1 # Default if not found
if original_keywords_list: if original_keywords_list:
try: try:
# Use the original_keyword string directly # Use the original_keyword string directly
keyword_index_in_rule = original_keywords_list.index(original_keyword) keyword_index_in_rule = original_keywords_list.index(original_keyword)
except ValueError: except ValueError:
log.warning(f"Keyword '{original_keyword}' not found in its original rule list? {original_keywords_list}") log.warning(f"Keyword '{original_keyword}' not found in its original rule list? {original_keywords_list}")
# --- DIAGNOSTIC LOGGING START ---
log.debug(f" Checking file '{file_rel_path.name}' against keyword '{original_keyword}' (rule {rule_index}, pattern: '{kw_regex.pattern}') for base type '{base_map_type}'")
# --- DIAGNOSTIC LOGGING END ---
else: else:
log.warning(f"Original keywords list empty for rule {rule_index}, cannot find index for '{original_keyword}'.") log.warning(f"Original keywords list empty for rule {rule_index}, cannot find index for '{original_keyword}'.")
# Add candidate only if not already added # Add candidate only if not already added
if not any(c['source_path'] == file_rel_path for c in potential_map_candidates): if not any(c['source_path'] == file_rel_path for c in potential_map_candidates):
@ -1362,11 +1413,11 @@ class AssetProcessor:
log.debug(f"Determining category, archetype, and supplier for asset: '{asset_base_name}'") log.debug(f"Determining category, archetype, and supplier for asset: '{asset_base_name}'")
# Determine Supplier Name using fallback # Determine Supplier Name using fallback
determined_supplier_name = self._get_rule_with_fallback('supplier_name', asset_name=asset_base_name, default=self.config.supplier_name) determined_supplier_name = self._get_rule_with_fallback(rules, 'supplier_name', asset_name=asset_base_name, default=self.config.supplier_name)
log.debug(f" Determined Supplier Name for '{asset_base_name}': {determined_supplier_name}") log.debug(f" Determined Supplier Name for '{asset_base_name}': {determined_supplier_name}")
determined_category = self._get_rule_with_fallback('default_asset_category', asset_name=asset_base_name, default=self.config.default_asset_category) # Start with default from rules/config determined_category = self._get_rule_with_fallback(rules, 'default_asset_category', asset_name=asset_base_name, default=self.config.default_asset_category) # Start with default from rules/config
determined_archetype = "Unknown" determined_archetype = "Unknown"
# --- Determine Asset Category --- # --- Determine Asset Category ---
@ -1376,7 +1427,7 @@ class AssetProcessor:
else: else:
# Check for Decal keywords only if not an Asset # Check for Decal keywords only if not an Asset
# Get decal keywords using fallback # Get decal keywords using fallback
decal_keywords = self._get_rule_with_fallback('decal_keywords', asset_name=asset_base_name, default=[]) decal_keywords = self._get_rule_with_fallback(rules, 'decal_keywords', asset_name=asset_base_name, default=[])
found_decal = False found_decal = False
# Check map names first for decal keywords # Check map names first for decal keywords
candidate_files = [f['source_path'] for f in filtered_classified_files.get('maps', [])] candidate_files = [f['source_path'] for f in filtered_classified_files.get('maps', [])]
@ -1400,7 +1451,7 @@ class AssetProcessor:
# --- Determine Archetype (Usage) --- # --- Determine Archetype (Usage) ---
# Get archetype rules using fallback # Get archetype rules using fallback
archetype_rules = self._get_rule_with_fallback('archetype_rules', asset_name=asset_base_name, default=[]) archetype_rules = self._get_rule_with_fallback(rules, 'archetype_rules', asset_name=asset_base_name, default=[])
# Use stems from maps and models belonging *only* to this asset # Use stems from maps and models belonging *only* to this asset
check_stems = [f['source_path'].stem.lower() for f in filtered_classified_files.get('maps', [])] check_stems = [f['source_path'].stem.lower() for f in filtered_classified_files.get('maps', [])]
check_stems.extend([f['source_path'].stem.lower() for f in filtered_classified_files.get('models', [])]) check_stems.extend([f['source_path'].stem.lower() for f in filtered_classified_files.get('models', [])])
@ -1468,11 +1519,11 @@ class AssetProcessor:
ignored_rough_maps: List[Dict] = [] # Store ignored native rough maps ignored_rough_maps: List[Dict] = [] # Store ignored native rough maps
# --- Settings retrieval using fallback --- # --- Settings retrieval using fallback ---
resolutions = self._get_rule_with_fallback('image_resolutions', asset_name=asset_name, default=self.config.image_resolutions) resolutions = self._get_rule_with_fallback(rules, 'image_resolutions', asset_name=asset_name, default=self.config.image_resolutions)
stats_res_key = self._get_rule_with_fallback('calculate_stats_resolution', asset_name=asset_name, default=self.config.calculate_stats_resolution) stats_res_key = self._get_rule_with_fallback(rules, 'calculate_stats_resolution', asset_name=asset_name, default=self.config.calculate_stats_resolution)
stats_target_dim = resolutions.get(stats_res_key) stats_target_dim = resolutions.get(stats_res_key)
if not stats_target_dim: log.warning(f"Stats resolution key '{stats_res_key}' not found in rules/config. Stats skipped for '{asset_name}'.") if not stats_target_dim: log.warning(f"Stats resolution key '{stats_res_key}' not found in rules/config. Stats skipped for '{asset_name}'.")
gloss_keywords = self._get_rule_with_fallback('source_glossiness_keywords', asset_name=asset_name, default=self.config.source_glossiness_keywords) gloss_keywords = self._get_rule_with_fallback(rules, 'source_glossiness_keywords', asset_name=asset_name, default=self.config.source_glossiness_keywords)
# target_pattern = _get_rule_with_fallback('target_filename_pattern', asset_name=asset_name, default=self.config.target_filename_pattern) # Not needed here, handled by _save_image # target_pattern = _get_rule_with_fallback('target_filename_pattern', asset_name=asset_name, default=self.config.target_filename_pattern) # Not needed here, handled by _save_image
base_name = asset_name # Use the asset name passed in base_name = asset_name # Use the asset name passed in
@ -1505,7 +1556,7 @@ class AssetProcessor:
derived_from_gloss_flag['ROUGH'] = False derived_from_gloss_flag['ROUGH'] = False
# --- Identify maps used in merge rules (using fallback) --- # --- Identify maps used in merge rules (using fallback) ---
merge_rules = self._get_rule_with_fallback('map_merge_rules', asset_name=asset_name, default=self.config.map_merge_rules) merge_rules = self._get_rule_with_fallback(rules, 'map_merge_rules', asset_name=asset_name, default=self.config.map_merge_rules)
merge_input_map_types = set() merge_input_map_types = set()
for rule in merge_rules: for rule in merge_rules:
inputs_mapping = rule.get("inputs", {}) inputs_mapping = rule.get("inputs", {})
@ -1515,26 +1566,12 @@ class AssetProcessor:
merge_input_map_types.add(base_type) merge_input_map_types.add(base_type)
log.debug(f"Map types used as input for merge rules (from rules/config): {merge_input_map_types}") log.debug(f"Map types used as input for merge rules (from rules/config): {merge_input_map_types}")
# --- Filter maps to process individually --- log.info(f"Processing individual map files for asset '{asset_name}'...")
maps_to_process_individually = []
for map_info in filtered_maps_list:
base_map_type = _get_base_map_type(map_info['map_type'])
# Skip if this base map type is used in *any* merge rule input
if base_map_type in merge_input_map_types:
log.debug(f"Skipping individual processing for {map_info['map_type']} ({map_info['source_path']}) as its base type '{base_map_type}' is used in merge rules (from rules/config).")
continue
# Skip native rough map if gloss was prioritized
if map_info['map_type'].startswith('ROUGH') and any(ignored['source_path'] == map_info['source_path'] for ignored in ignored_rough_maps):
log.debug(f"Skipping individual processing of native rough map '{map_info['source_path']}' as gloss version was prioritized.")
continue
maps_to_process_individually.append(map_info)
log.info(f"Processing {len(maps_to_process_individually)} maps individually for asset '{asset_name}'...")
# --- Aspect Ratio Calculation Setup --- # --- Aspect Ratio Calculation Setup ---
# We need original dimensions once per asset for aspect ratio. # We need original dimensions once per asset for aspect ratio.
# Find the first map to process to get its dimensions. # Find the first map to process to get its dimensions.
first_map_info_for_aspect = next((m for m in maps_to_process_individually), None) first_map_info_for_aspect = next((m for m in filtered_maps_list), None) # Use the original list
orig_w_aspect, orig_h_aspect = None, None orig_w_aspect, orig_h_aspect = None, None
if first_map_info_for_aspect: if first_map_info_for_aspect:
# Load just to get dimensions (might hit cache if used later) # Load just to get dimensions (might hit cache if used later)
@ -1542,7 +1579,7 @@ class AssetProcessor:
first_res_key = next(iter(resolutions)) first_res_key = next(iter(resolutions))
temp_img_for_dims, _ = self._load_and_transform_source( temp_img_for_dims, _ = self._load_and_transform_source(
first_map_info_for_aspect['source_path'], first_map_info_for_aspect['source_path'],
first_map_info_for_aspect['map_type'], first_map_info_for_aspect['map_type'], # Use original map type for loading
first_res_key, first_res_key,
False, # is_gloss_source doesn't matter for dims False, # is_gloss_source doesn't matter for dims
loaded_data_cache # Use the main cache loaded_data_cache # Use the main cache
@ -1557,14 +1594,46 @@ class AssetProcessor:
# --- Process Each Individual Map --- # --- Process Each Individual Map ---
for map_info in maps_to_process_individually: # Iterate through the original list and filter/apply overrides here
map_type = map_info['map_type'] # Final type (e.g., COL-1) for map_info in filtered_maps_list:
source_path_rel = map_info['source_path'] source_path_rel = map_info['source_path']
original_extension = map_info.get('original_extension', '.png') original_extension = map_info.get('original_extension', '.png')
current_map_type = map_info['map_type'] # Start with the classified type
# --- Apply map_type_override from FileRule (Step 2) ---
map_type_override = self._get_rule_with_fallback(
rules,
'map_type_override',
file_path=source_path_rel,
asset_name=asset_name,
default=None
)
if map_type_override is not None:
log.debug(f"Asset '{asset_name}': Applying map_type_override '{map_type_override}' for source '{source_path_rel.name}' (originally '{current_map_type}').")
map_type = map_type_override # Use the override
else:
map_type = current_map_type # Use the original classified type
# --- Check if this map should be processed individually (Step 3) ---
base_map_type = _get_base_map_type(map_type) # Use the potentially updated map_type
if base_map_type in merge_input_map_types:
log.debug(f"Skipping individual processing for {map_type} (Source: {source_path_rel}) as its base type '{base_map_type}' is used in merge rules (from rules/config).")
continue # Skip to the next map in the loop
# Skip native rough map if gloss was prioritized (keep this check)
# This check needs to use the *original* source path to see if it was the native rough that was ignored
# The ignored_rough_maps list contains the original map_info dicts.
if map_type.startswith('ROUGH') and any(ignored['source_path'] == source_path_rel for ignored in ignored_rough_maps):
log.debug(f"Skipping individual processing of native rough map '{source_path_rel}' as gloss version was prioritized.")
continue # Skip to the next map in the loop
# Determine if this specific map type should use gloss inversion logic # Determine if this specific map type should use gloss inversion logic
# If ROUGH-1, ROUGH-2 etc derive from gloss, they all use inversion # If ROUGH-1, ROUGH-2 etc derive from gloss, they all use inversion
# This check should use the *final* map_type after override
is_gloss_source_for_this_map = map_type.startswith('ROUGH') and derived_from_gloss_flag.get('ROUGH', False) is_gloss_source_for_this_map = map_type.startswith('ROUGH') and derived_from_gloss_flag.get('ROUGH', False)
log.info(f"-- Asset '{asset_name}': Processing Individual Map: {map_type} (Source: {source_path_rel.name}) --") log.info(f"-- Asset '{asset_name}': Processing Individual Map: {map_type} (Source: {source_path_rel.name}) --")
current_map_details = {"derived_from_gloss": is_gloss_source_for_this_map} current_map_details = {"derived_from_gloss": is_gloss_source_for_this_map}
source_bit_depth_found = None # Track if we've found the bit depth for this map type source_bit_depth_found = None # Track if we've found the bit depth for this map type
@ -1622,17 +1691,17 @@ class AssetProcessor:
'involved_extensions': {original_extension} # Only self for individual maps 'involved_extensions': {original_extension} # Only self for individual maps
} }
# Get bit depth rule using fallback logic # Get bit depth rule using fallback logic
bit_depth_rules_map = self._get_rule_with_fallback('output_bit_depth_rules', file_path=source_path_rel, asset_name=asset_name, default={}) bit_depth_rules_map = self._get_rule_with_fallback(rules, 'output_bit_depth_rules', file_path=source_path_rel, asset_name=asset_name, default={})
bit_depth_rule = bit_depth_rules_map.get(map_type, 'respect') # Default to 'respect' if map type not in rules/config bit_depth_rule = bit_depth_rules_map.get(map_type, 'respect') # Default to 'respect' if map type not in rules/config
# Get additional config values using fallback for _save_image # Get additional config values using fallback for _save_image
output_formats_16bit = self._get_rule_with_fallback('get_16bit_output_formats', file_path=source_path_rel, asset_name=asset_name, default=self.config.get_16bit_output_formats()) output_formats_16bit = self._get_rule_with_fallback(rules, 'get_16bit_output_formats', file_path=source_path_rel, asset_name=asset_name, default=self.config.get_16bit_output_formats())
output_format_8bit = self._get_rule_with_fallback('get_8bit_output_format', file_path=source_path_rel, asset_name=asset_name, default=self.config.get_8bit_output_format()) output_format_8bit = self._get_rule_with_fallback(rules, 'get_8bit_output_format', file_path=source_path_rel, asset_name=asset_name, default=self.config.get_8bit_output_format())
resolution_threshold_for_jpg = self._get_rule_with_fallback('resolution_threshold_for_jpg', file_path=source_path_rel, asset_name=asset_name, default=self.config.resolution_threshold_for_jpg) resolution_threshold_for_jpg = self._get_rule_with_fallback(rules, 'resolution_threshold_for_jpg', file_path=source_path_rel, asset_name=asset_name, default=self.config.resolution_threshold_for_jpg)
force_lossless_map_types = self._get_rule_with_fallback('force_lossless_map_types', asset_name=asset_name, default=self.config.force_lossless_map_types) # This rule applies to map type, not individual file path force_lossless_map_types = self._get_rule_with_fallback(rules, 'force_lossless_map_types', asset_name=asset_name, default=self.config.force_lossless_map_types) # This rule applies to map type, not individual file path
jpg_quality = self._get_rule_with_fallback('jpg_quality', file_path=source_path_rel, asset_name=asset_name, default=self.config.jpg_quality) jpg_quality = self._get_rule_with_fallback(rules, 'jpg_quality', file_path=source_path_rel, asset_name=asset_name, default=self.config.jpg_quality)
png_compression_level = self._get_rule_with_fallback('_core_settings', asset_name=asset_name, default=self.config._core_settings).get('PNG_COMPRESSION_LEVEL', 6) # This rule applies broadly, not per file png_compression_level = self._get_rule_with_fallback(rules, '_core_settings', asset_name=asset_name, default=self.config._core_settings).get('PNG_COMPRESSION_LEVEL', 6) # This rule applies broadly, not per file
target_filename_pattern = self._get_rule_with_fallback('target_filename_pattern', file_path=source_path_rel, asset_name=asset_name, default=self.config.target_filename_pattern) target_filename_pattern = self._get_rule_with_fallback(rules, 'target_filename_pattern', file_path=source_path_rel, asset_name=asset_name, default=self.config.target_filename_pattern)
# image_resolutions is already retrieved at the start of the method # image_resolutions is already retrieved at the start of the method
save_result = self._save_image( save_result = self._save_image(
@ -1699,10 +1768,10 @@ class AssetProcessor:
if not self.temp_dir: raise AssetProcessingError("Workspace not setup.") if not self.temp_dir: raise AssetProcessingError("Workspace not setup.")
asset_name = current_asset_metadata.get("asset_name", "UnknownAsset") asset_name = current_asset_metadata.get("asset_name", "UnknownAsset")
# Get gloss keywords using fallback logic # Get gloss keywords using fallback logic
gloss_keywords = self._get_rule_with_fallback('source_glossiness_keywords', asset_name=asset_name, default=self.config.source_glossiness_keywords) gloss_keywords = self._get_rule_with_fallback(rules, 'source_glossiness_keywords', asset_name=asset_name, default=self.config.source_glossiness_keywords)
# Get merge rules using fallback logic # Get merge rules using fallback logic
merge_rules = self._get_rule_with_fallback('map_merge_rules', asset_name=asset_name, default=self.config.map_merge_rules) merge_rules = self._get_rule_with_fallback(rules, 'map_merge_rules', asset_name=asset_name, default=self.config.map_merge_rules)
log.info(f"Asset '{asset_name}': Applying {len(merge_rules)} map merging rule(s) from source (from rules/config)...") log.info(f"Asset '{asset_name}': Applying {len(merge_rules)} map merging rule(s) from source (from rules/config)...")
# Initialize results for this asset # Initialize results for this asset
@ -1765,7 +1834,7 @@ class AssetProcessor:
# This assumes _process_individual_maps ran first and populated processed_maps_details_asset # This assumes _process_individual_maps ran first and populated processed_maps_details_asset
possible_resolutions_per_input = [] possible_resolutions_per_input = []
# Get resolutions using fallback # Get resolutions using fallback
resolutions = self._get_rule_with_fallback('image_resolutions', asset_name=asset_name, default=self.config.image_resolutions) resolutions = self._get_rule_with_fallback(rules, 'image_resolutions', asset_name=asset_name, default=self.config.image_resolutions)
for input_type in set(inputs_mapping.values()): for input_type in set(inputs_mapping.values()):
if input_type in processed_maps_details_asset: if input_type in processed_maps_details_asset:
@ -1925,13 +1994,13 @@ class AssetProcessor:
# --- Save Merged Map using Helper --- # --- Save Merged Map using Helper ---
# Get additional config values using fallback for _save_image # Get additional config values using fallback for _save_image
output_formats_16bit = self._get_rule_with_fallback('get_16bit_output_formats', asset_name=asset_name, default=self.config.get_16bit_output_formats()) output_formats_16bit = self._get_rule_with_fallback(rules, 'get_16bit_output_formats', asset_name=asset_name, default=self.config.get_16bit_output_formats())
output_format_8bit = self._get_rule_with_fallback('get_8bit_output_format', asset_name=asset_name, default=self.config.get_8bit_output_format()) output_format_8bit = self._get_rule_with_fallback(rules, 'get_8bit_output_format', asset_name=asset_name, default=self.config.get_8bit_output_format())
resolution_threshold_for_jpg = self._get_rule_with_fallback('resolution_threshold_for_jpg', asset_name=asset_name, default=self.config.resolution_threshold_for_jpg) resolution_threshold_for_jpg = self._get_rule_with_fallback(rules, 'resolution_threshold_for_jpg', asset_name=asset_name, default=self.config.resolution_threshold_for_jpg)
force_lossless_map_types = self._get_rule_with_fallback('force_lossless_map_types', asset_name=asset_name, default=self.config.force_lossless_map_types) force_lossless_map_types = self._get_rule_with_fallback(rules, 'force_lossless_map_types', asset_name=asset_name, default=self.config.force_lossless_map_types)
jpg_quality = self._get_rule_with_fallback('jpg_quality', asset_name=asset_name, default=self.config.jpg_quality) jpg_quality = self._get_rule_with_fallback(rules, 'jpg_quality', asset_name=asset_name, default=self.config.jpg_quality)
png_compression_level = self._get_rule_with_fallback('_core_settings', asset_name=asset_name, default=self.config._core_settings).get('PNG_COMPRESSION_LEVEL', 6) png_compression_level = self._get_rule_with_fallback(rules, '_core_settings', asset_name=asset_name, default=self.config._core_settings).get('PNG_COMPRESSION_LEVEL', 6)
target_filename_pattern = self._get_rule_with_fallback('target_filename_pattern', asset_name=asset_name, default=self.config.target_filename_pattern) target_filename_pattern = self._get_rule_with_fallback(rules, 'target_filename_pattern', asset_name=asset_name, default=self.config.target_filename_pattern)
# image_resolutions is already retrieved at the start of the method # image_resolutions is already retrieved at the start of the method
save_result = self._save_image( save_result = self._save_image(
@ -2006,9 +2075,9 @@ class AssetProcessor:
final_metadata = current_asset_metadata.copy() final_metadata = current_asset_metadata.copy()
# Apply hierarchical rules for specific metadata fields # Apply hierarchical rules for specific metadata fields
final_metadata["supplier_name"] = self._get_rule_with_fallback('supplier_name', asset_name=asset_name, default=final_metadata.get("supplier_name", self.config.supplier_name)) final_metadata["supplier_name"] = self._get_rule_with_fallback(rules, 'supplier_name', asset_name=asset_name, default=final_metadata.get("supplier_name", self.config.supplier_name))
final_metadata["asset_category"] = self._get_rule_with_fallback('default_asset_category', asset_name=asset_name, default=final_metadata.get("asset_category", self.config.default_asset_category)) final_metadata["asset_category"] = self._get_rule_with_fallback(rules, 'default_asset_category', asset_name=asset_name, default=final_metadata.get("asset_category", self.config.default_asset_category))
final_metadata["archetype"] = self._get_rule_with_fallback('archetype', asset_name=asset_name, default=final_metadata.get("archetype", "Unknown")) # Archetype is determined earlier, but allow override final_metadata["archetype"] = self._get_rule_with_fallback(rules, 'archetype', asset_name=asset_name, default=final_metadata.get("archetype", "Unknown")) # Archetype is determined earlier, but allow override
# Populate map details from the specific asset's processing results # Populate map details from the specific asset's processing results
# Add merged map channel stats # Add merged map channel stats

View File

@ -798,7 +798,7 @@ class MainWindow(QMainWindow):
self.start_button.setText("Start Processing") self.start_button.setText("Start Processing")
return return
log.debug(f"Using SourceRule '{self._current_source_rule.name}' for processing.") log.debug(f"Using SourceRule '{self._current_source_rule.input_path}' for processing.")
self.processing_thread.started.connect( self.processing_thread.started.connect(
lambda: self.processing_handler.run_processing( lambda: self.processing_handler.run_processing(
@ -1699,7 +1699,7 @@ class MainWindow(QMainWindow):
filter_string = "^" + rule_item.asset_name.replace('\\', '\\\\').replace('.', '\\.') + "$" filter_string = "^" + rule_item.asset_name.replace('\\', '\\\\').replace('.', '\\.') + "$"
self.preview_proxy_model.setFilterRegularExpression(filter_string) self.preview_proxy_model.setFilterRegularExpression(filter_string)
self.preview_proxy_model.setFilterKeyColumn(self.preview_model.ROLE_SOURCE_ASSET) # Filter by source_asset column self.preview_proxy_model.setFilterKeyColumn(self.preview_model.ROLE_SOURCE_ASSET) # Filter by source_asset column
log.debug(f"Filtering preview table: Showing files for Asset '{rule_item.name}'. Filter: '{filter_string}' on column {self.preview_model.COL_SOURCE_ASSET}") log.debug(f"Filtering preview table: Showing files for Asset '{rule_item.asset_name}'. Filter: '{filter_string}' on column {self.preview_model.ROLE_SOURCE_ASSET}")
elif isinstance(rule_item, FileRule): elif isinstance(rule_item, FileRule):
# Show only this specific file # Show only this specific file
# Filter by the 'original_path' column # Filter by the 'original_path' column

View File

@ -134,7 +134,7 @@ def setup_arg_parser():
# --- Worker Function --- # --- Worker Function ---
def process_single_asset_wrapper(input_path_str: str, preset_name: str, output_dir_str: str, overwrite: bool, verbose: bool) -> Tuple[str, str, Optional[str]]: def process_single_asset_wrapper(input_path_str: str, preset_name: str, output_dir_str: str, overwrite: bool, verbose: bool, rules) -> Tuple[str, str, Optional[str]]:
""" """
Wrapper function for processing a single input path (which might contain multiple assets) Wrapper function for processing a single input path (which might contain multiple assets)
in a separate process. Handles instantiation of Configuration and AssetProcessor, in a separate process. Handles instantiation of Configuration and AssetProcessor,
@ -168,7 +168,7 @@ def process_single_asset_wrapper(input_path_str: str, preset_name: str, output_d
processor = AssetProcessor(input_path_obj, config, output_base_path, overwrite=overwrite) processor = AssetProcessor(input_path_obj, config, output_base_path, overwrite=overwrite)
# processor.process() now returns a Dict[str, List[str]] # processor.process() now returns a Dict[str, List[str]]
status_dict = processor.process() status_dict = processor.process(rules=rules)
# --- Interpret the status dictionary --- # --- Interpret the status dictionary ---
processed_assets = status_dict.get("processed", []) processed_assets = status_dict.get("processed", [])