9.4 KiB
Project Plan: Modularizing the Asset Processing Engine
Last Updated: May 9, 2025
1. Project Vision & Goals
- Vision: Transform the asset processing pipeline into a highly modular, extensible, and testable system.
- Primary Goals:
- Decouple processing steps into independent, reusable stages.
- Simplify the addition of new processing capabilities (e.g., GLOSS > ROUGH conversion, Alpha to MASK, Normal Map Green Channel inversion).
- Improve code maintainability and readability.
- Enhance unit and integration testing capabilities for each processing component.
- Centralize common utility functions (image manipulation, path generation).
2. Proposed Architecture Overview
- Core Concept: A
PipelineOrchestratorwill manage a sequence ofProcessingStages. Each stage will operate on anAssetProcessingContextobject, which carries all necessary data and state for a single asset through the pipeline. - Key Components:
AssetProcessingContext: Data class holding asset-specific data, configuration, temporary paths, and status.PipelineOrchestrator: Class to manage the overall processing flow for aSourceRule, iterating through assets and executing the pipeline of stages for each.ProcessingStage(Base Class/Interface): Defines the contract for all individual processing stages (e.g.,execute(context)method).- Specific Stage Classes: (e.g.,
SupplierDeterminationStage,IndividualMapProcessingStage, etc.) - Utility Modules:
image_processing_utils.py, enhancements toutils/path_utils.py.
3. Proposed File Structure
processing/pipeline/__init__.pyasset_context.py(DefinesAssetProcessingContext)orchestrator.py(DefinesPipelineOrchestrator)stages/__init__.pybase_stage.py(DefinesProcessingStageinterface)supplier_determination.pyasset_skip_logic.pymetadata_initialization.pyfile_rule_filter.pygloss_to_rough_conversion.pyalpha_extraction_to_mask.pynormal_map_green_channel.pyindividual_map_processing.pymap_merging.pymetadata_finalization.pyoutput_organization.py
utils/__init__.pyimage_processing_utils.py(New module for image functions)
utils/(Top-level existing directory)path_utils.py(To be enhanced withsanitize_filenamefromprocessing_engine.py)
4. Detailed Phases and Tasks
Phase 0: Setup & Core Structures Definition Goal: Establish the foundational classes for the new pipeline.
- Task 0.1: Define
AssetProcessingContext- Create
processing/pipeline/asset_context.py. - Define the
AssetProcessingContextdata class with fields:source_rule: SourceRule,asset_rule: AssetRule,workspace_path: Path,engine_temp_dir: Path,output_base_path: Path,effective_supplier: Optional[str],asset_metadata: Dict,processed_maps_details: Dict[str, Dict[str, Dict]],merged_maps_details: Dict[str, Dict[str, Dict]],files_to_process: List[FileRule],loaded_data_cache: Dict,config_obj: Configuration,status_flags: Dict,incrementing_value: Optional[str],sha5_value: Optional[str]. - Ensure proper type hinting.
- Create
- Task 0.2: Define
ProcessingStageBase Class/Interface- Create
processing/pipeline/stages/base_stage.py. - Define an abstract base class
ProcessingStagewith an abstract methodexecute(self, context: AssetProcessingContext) -> AssetProcessingContext.
- Create
- Task 0.3: Implement Initial
PipelineOrchestrator- Create
processing/pipeline/orchestrator.py. - Define the
PipelineOrchestratorclass. - Implement
__init__(self, config_obj: Configuration, stages: List[ProcessingStage]). - Implement
process_source_rule(self, source_rule: SourceRule, workspace_path: Path, output_base_path: Path, overwrite: bool, incrementing_value: Optional[str], sha5_value: Optional[str]) -> Dict[str, List[str]].- Handles creation/cleanup of the main engine temporary directory.
- Loops through
source_rule.assets, initializesAssetProcessingContextfor each. - Iterates
self.stages, callingstage.execute(context). - Collects overall status.
- Create
Phase 1: Utility Module Refactoring Goal: Consolidate and centralize common utility functions.
- Task 1.1: Refactor Path Utilities
- Move
_sanitize_filenamefromprocessing_engine.pytoutils/path_utils.py. - Update uses to call the new utility function.
- Move
- Task 1.2: Create
image_processing_utils.py- Create
processing/utils/image_processing_utils.py. - Move general-purpose image functions from
processing_engine.py:is_power_of_twoget_nearest_potcalculate_target_dimensionscalculate_image_statsnormalize_aspect_ratio_change- Core image loading, BGR<>RGB conversion, generic resizing (from
_load_and_transform_source). - Core data type conversion for saving, color conversion for saving,
cv2.imwritecall (from_save_image).
- Ensure functions are pure and testable.
- Create
Phase 2: Implementing Core Processing Stages (Migrating Existing Logic)
Goal: Migrate existing functionalities from processing_engine.py into the new stage-based architecture.
(For each task: create stage file, implement class, move logic, adapt to AssetProcessingContext)
- Task 2.1: Implement
SupplierDeterminationStage - Task 2.2: Implement
AssetSkipLogicStage - Task 2.3: Implement
MetadataInitializationStage - Task 2.4: Implement
FileRuleFilterStage(New logic foritem_type == "FILE_IGNORE") - Task 2.5: Implement
IndividualMapProcessingStage(Adapts_process_individual_maps, usesimage_processing_utils.py) - Task 2.6: Implement
MapMergingStage(Adapts_merge_maps, usesimage_processing_utils.py) - Task 2.7: Implement
MetadataFinalizationAndSaveStage(Adapts_generate_metadata_file, usesutils.path_utils.generate_path_from_pattern) - Task 2.8: Implement
OutputOrganizationStage(Adapts_organize_output_files)
Phase 3: Implementing New Feature Stages Goal: Add the new desired processing capabilities as distinct stages.
- Task 3.1: Implement
GlossToRoughConversionStage(Identify gloss, convert, invert, save temp, updateFileRule) - Task 3.2: Implement
AlphaExtractionToMaskStage(Check existing mask, find MAP_COL with alpha, extract, save temp, add newFileRule) - Task 3.3: Implement
NormalMapGreenChannelStage(Identify normal maps, invert green based on config, save temp, updateFileRule)
Phase 4: Integration, Testing & Finalization Goal: Assemble the pipeline, test thoroughly, and deprecate old code.
- Task 4.1: Configure
PipelineOrchestrator- Instantiate
PipelineOrchestratorin main application logic with the ordered list of stage instances.
- Instantiate
- Task 4.2: Unit Testing
- Unit tests for each
ProcessingStage(mockingAssetProcessingContext). - Unit tests for
image_processing_utils.pyandutils/path_utils.pyfunctions.
- Unit tests for each
- Task 4.3: Integration Testing
- Test
PipelineOrchestratorend-to-end with sample data. - Compare outputs with the existing engine for consistency.
- Test
- Task 4.4: Documentation Update
- Update developer documentation (e.g.,
Documentation/02_Developer_Guide/05_Processing_Pipeline.md). - Document
AssetProcessingContextand stage responsibilities.
- Update developer documentation (e.g.,
- Task 4.5: Deprecate/Remove Old
ProcessingEngineCode- Gradually remove refactored logic from
processing_engine.py.
- Gradually remove refactored logic from
5. Workflow Diagram
graph TD
AA[Load SourceRule & Config] --> BA(PipelineOrchestrator: process_source_rule);
BA --> CA{For Each Asset in SourceRule};
CA -- Yes --> DA(Orchestrator: Create AssetProcessingContext);
DA --> EA(SupplierDeterminationStage);
EA -- context --> FA(AssetSkipLogicStage);
FA -- context --> GA{context.skip_asset?};
GA -- Yes --> HA(Orchestrator: Record Skipped);
HA --> CA;
GA -- No --> IA(MetadataInitializationStage);
IA -- context --> JA(FileRuleFilterStage);
JA -- context --> KA(GlossToRoughConversionStage);
KA -- context --> LA(AlphaExtractionToMaskStage);
LA -- context --> MA(NormalMapGreenChannelStage);
MA -- context --> NA(IndividualMapProcessingStage);
NA -- context --> OA(MapMergingStage);
OA -- context --> PA(MetadataFinalizationAndSaveStage);
PA -- context --> QA(OutputOrganizationStage);
QA -- context --> RA(Orchestrator: Record Processed/Failed);
RA --> CA;
CA -- No --> SA(Orchestrator: Cleanup Engine Temp Dir);
SA --> TA[Processing Complete];
subgraph Stages
direction LR
EA
FA
IA
JA
KA
LA
MA
NA
OA
PA
QA
end
subgraph Utils
direction LR
U1[image_processing_utils.py]
U2[utils/path_utils.py]
end
NA -.-> U1;
OA -.-> U1;
KA -.-> U1;
LA -.-> U1;
MA -.-> U1;
PA -.-> U2;
QA -.-> U2;
classDef context fill:#f9f,stroke:#333,stroke-width:2px;
class DA,EA,FA,IA,JA,KA,LA,MA,NA,OA,PA,QA context;