539 KiB
Texture folder commonality script (2025-12-19 17:59Z)
User
I've appended an old script: @organize_textures.ps1 it needs to be updated to do the following:
- prompt the user to input a texture folder path, e.g.
A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon1\textures - ensure that it checksums everything within that paths and moves ALL commonalities to [texture folder path]\common
It's an old script so I don't remember how it works exactly, I just know it doesn't work perfectly currently.
Agent (model default, mode Plan)
Reviewing organize_textures.ps1 to understand its current behavior.
Tool use: **read_file_v2** • Read file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.ps1
The script currently groups files by prefix. We need to switch to checksum-based duplicate detection. Clarifying a few details:
Tool use: **ask_question**
Parameters:
{
"questions": [
{
"id": "duplicate_handling",
"prompt": "When duplicate files (same checksum) are found, which file should be kept in its original location?",
"options": [
{
"id": "first",
"label": "Keep the first file found (move others to common)"
},
{
"id": "shortest_path",
"label": "Keep the file with the shortest path (move others to common)"
},
{
"id": "root_only",
"label": "Keep files in root texture folder only (move all subdirectory duplicates to common)"
}
]
},
{
"id": "subdirectories",
"prompt": "Should the script process files recursively in all subdirectories, or only files directly in the texture folder?",
"options": [
{
"id": "recursive",
"label": "Process all files recursively in subdirectories"
},
{
"id": "root_only",
"label": "Only process files directly in the texture folder"
}
]
}
]
}
Additional data:
{
"status": "submitted",
"currentSelections": {}
}
Result:
{
"answers": [
{
"questionId": "duplicate_handling"
},
{
"questionId": "subdirectories"
}
]
}
User decision: accepted
Status: completed
User
all duplicates should be MERGED into \common, but \common can have a \duplicates subfolder where duplicate images are numbered .001, .002, etc. for debugging purposes only.
Agent (model default, mode Plan)
Creating a plan to update the script to:
- Prompt for a texture folder path
- Calculate checksums for all files recursively
- Move all files to
\common, with duplicates numbered in\common\duplicates
Tool use: **create_plan**
Parameters:
{
"plan": "# Update organize_textures.ps1 Script\n\n## Current State\nThe script currently groups files by prefix (text before first underscore) and organizes them into subdirectories. This needs to be completely rewritten.\n\n## New Requirements\n1. Prompt user for texture folder path input\n2. Recursively process all files in that path\n3. Calculate checksums (SHA256) for each file\n4. Group files by checksum to identify duplicates\n5. Move all files to `[texture folder path]\\common`\n6. For duplicate files (same checksum), keep one copy in `\\common` and move additional copies to `\\common\\duplicates` with numbered suffixes (.001, .002, etc.)\n\n## Implementation Plan\n\n### File: `organize_textures.ps1`\n\n**Changes:**\n1. Replace prefix-based grouping with checksum-based duplicate detection\n2. Add user prompt for texture folder path using `Read-Host`\n3. Validate the input path exists and is a directory\n4. Use `Get-ChildItem -Recurse -File` to get all files recursively\n5. Calculate SHA256 checksum for each file using `Get-FileHash`\n6. Group files by checksum value\n7. Create `\\common` directory if it doesn't exist\n8. Create `\\common\\duplicates` directory if it doesn't exist\n9. For each checksum group:\n - If only one file: move it to `\\common` (preserving relative path structure or flattening?)\n - If multiple files (duplicates):\n - Move the first file to `\\common` (keep original name)\n - Move remaining files to `\\common\\duplicates` with numbered suffixes (.001, .002, etc.)\n10. Handle file name conflicts when moving to `\\common`\n\n**Key Functions:**\n- `Get-FileHash -Algorithm SHA256` for checksum calculation\n- `Group-Object` to group by checksum\n- `Move-Item` to move files\n- Path manipulation with `Join-Path`, `Split-Path`\n\n**Considerations:**\n- Should preserve relative directory structure in `\\common` or flatten all files?\n- Handle cases where files already exist in destination\n- Skip the `\\common` folder itself when processing files\n- Provide progress feedback for large directories\n\n**Questions to resolve:**\n- Should unique files (no duplicates) also be moved to `\\common`, or only duplicates?\n- Should the directory structure be preserved in `\\common` or flattened?\n- What should happen if a file already exists in the destination?\n",
"name": "Update organize_textures script",
"overview": "Update organize_textures.ps1 to prompt for a texture folder path, calculate checksums for all files recursively, and move all files to a \\common folder with duplicates numbered in \\common\\duplicates for debugging."
}
Additional data:
{
"reviewData": {
"status": "Requested",
"selectedOption": "none",
"isShowingInput": false
},
"planUri": "c:\\Users\\Nathan\\.cursor\\plans\\update_organize_textures_script_6f224239.plan.md",
"hasOpenedEditor": true
}
Result:
{
"rejected": {}
}
Status: completed
User
to resolve those questions, I'll explain my workflow. I'll have you examine the folder structure of A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon1\textures to see if this makes sense. This structure was created by my AutoMat Extractor @e:\Rainys_Bulk_Scene_Tools\ops\AutoMatExtractor.py
The texture organizer was basically the alpha version of the AutoMat Extractor; I was unpacking relative with blender's default operator and organizing the textures in bulk afterwards. AutoMat does all of that from the blendfile; I want the texture organizer to do a secondary task that requires checksumming the textures of multiple blendfiles, then I'll relink them with FMT.
Agent (model default, mode Plan)
Examining the texture folder structure and the AutoMat Extractor to understand the workflow.
Tool use: **list_dir_v2**
Parameters:
{
"targetDirectory": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures"
}
Result:
{
"directoryTreeRoot": {
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Chan",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Chan\\Cargo_Pants",
"fullSubtreeExtensionCounts": {
".png": 1,
".jpg": 2
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Chan\\Chan_Ankle_socks",
"fullSubtreeExtensionCounts": {
".jpg": 3,
".png": 1
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Chan\\Chan_Boots",
"fullSubtreeExtensionCounts": {
".png": 3
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Chan\\Chan_Ga_Skin_Body",
"fullSubtreeExtensionCounts": {
".png": 4
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Chan\\Chan_Hair",
"fullSubtreeExtensionCounts": {
".png": 4
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Chan\\Chan_Std_Lower_Teeth",
"fullSubtreeExtensionCounts": {
".jpg": 2,
".png": 2
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Chan\\Chan_Std_Upper_Teeth",
"fullSubtreeExtensionCounts": {
".jpg": 2,
".png": 2
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Chan\\common",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Chan\\common\\FlatColors",
"fullSubtreeExtensionCounts": {
".png": 7
},
"numFiles": 7
}
],
"fullSubtreeExtensionCounts": {
".png": 9,
".jpg": 6
},
"numFiles": 15
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Chan\\Lanyard",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Chan\\Vest_Transparent_Title",
"fullSubtreeExtensionCounts": {
".png": 1,
".jpg": 1
},
"numFiles": 2
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Chan\\Work_gloves_StringKnit",
"childrenFiles": [
{
"name": "Work_gloves_StringKnit_Diffuse.jpg"
},
{
"name": "Work_gloves_StringKnit_metallic.jpg"
},
{
"name": "Work_gloves_StringKnit_Normal.jpg"
},
{
"name": "Work_gloves_StringKnit_roughness.jpg"
},
{
"name": "Work_gloves_StringKnit_Specular.jpg"
}
],
"childrenWereProcessed": true
}
],
"childrenWereProcessed": true,
"fullSubtreeExtensionCounts": {
".png": 28,
".jpg": 16
},
"numFiles": 44
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\BluePolo",
"fullSubtreeExtensionCounts": {
".png": 2
},
"numFiles": 2
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\BOOTS",
"fullSubtreeExtensionCounts": {
".jpg": 2
},
"numFiles": 2
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\common",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\common\\FlatColors",
"fullSubtreeExtensionCounts": {
".png": 5,
".tga": 1
},
"numFiles": 6
}
],
"fullSubtreeExtensionCounts": {
".png": 8,
".jpg": 6,
".tga": 1
},
"numFiles": 15
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\CORD",
"fullSubtreeExtensionCounts": {
".jpg": 2
},
"numFiles": 2
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\DarkBlue_Jeans",
"fullSubtreeExtensionCounts": {
".jpg": 3
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\Demarco_Hair",
"fullSubtreeExtensionCounts": {
".png": 1,
".tif": 1
},
"numFiles": 2
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\Demarco_Std_Eyelash",
"fullSubtreeExtensionCounts": {
".png": 1,
".jpg": 1
},
"numFiles": 2
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\Demarco_Std_Lower_Teeth",
"fullSubtreeExtensionCounts": {
".jpg": 2,
".png": 2
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\Demarco_Std_Nails",
"fullSubtreeExtensionCounts": {
".png": 3,
".jpg": 2
},
"numFiles": 5
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\Demarco_Std_Skin_Arm",
"fullSubtreeExtensionCounts": {
".png": 4,
".jpg": 3,
".tga": 1
},
"numFiles": 8
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\Demarco_Std_Skin_Body",
"fullSubtreeExtensionCounts": {
".png": 4,
".jpg": 3,
".tga": 1
},
"numFiles": 8
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\Demarco_Std_Skin_Head",
"fullSubtreeExtensionCounts": {
".png": 3,
".jpg": 7,
".tga": 4
},
"numFiles": 14
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\Demarco_Std_Skin_Leg",
"fullSubtreeExtensionCounts": {
".png": 4,
".jpg": 2,
".tga": 1
},
"numFiles": 7
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\Demarco_Std_Tongue",
"fullSubtreeExtensionCounts": {
".png": 3
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\Demarco_Std_Upper_Teeth",
"fullSubtreeExtensionCounts": {
".jpg": 2,
".png": 2
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\Lanyard",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Demarco\\Work_gloves_StringKnit",
"childrenFiles": [
{
"name": "Work_gloves_StringKnit_Diffuse.jpg"
},
{
"name": "Work_gloves_StringKnit_metallic.jpg"
},
{
"name": "Work_gloves_StringKnit_Normal.jpg"
},
{
"name": "Work_gloves_StringKnit_roughness.jpg"
},
{
"name": "Work_gloves_StringKnit_Specular.jpg"
}
],
"childrenWereProcessed": true
}
],
"childrenWereProcessed": true,
"fullSubtreeExtensionCounts": {
".png": 38,
".jpg": 35,
".tga": 8,
".tif": 1
},
"numFiles": 82
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Black_Sneakers",
"fullSubtreeExtensionCounts": {
".jpg": 3,
".png": 1
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\common",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\common\\FlatColors",
"fullSubtreeExtensionCounts": {
".png": 9,
".tga": 1
},
"numFiles": 10
}
],
"fullSubtreeExtensionCounts": {
".png": 11,
".jpg": 3,
".tga": 1
},
"numFiles": 15
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Ankle_socks",
"fullSubtreeExtensionCounts": {
".jpg": 3,
".png": 1
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Beard_Transparency",
"fullSubtreeExtensionCounts": {
".png": 3,
".jpg": 3
},
"numFiles": 6
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Fit_shirts",
"fullSubtreeExtensionCounts": {
".jpg": 4
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Hair_Transparency",
"fullSubtreeExtensionCounts": {
".jpg": 4,
".png": 3
},
"numFiles": 7
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Male_Bushy_Base_Transparency",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Male_Bushy_Transparency",
"fullSubtreeExtensionCounts": {
".png": 2,
".jpg": 3
},
"numFiles": 5
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Scalp_Transparency",
"fullSubtreeExtensionCounts": {
".jpg": 2
},
"numFiles": 2
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Scrub_Pants",
"fullSubtreeExtensionCounts": {
".jpg": 3,
".png": 1
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Std_Eye_L",
"fullSubtreeExtensionCounts": {
".jpg": 3
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Std_Eye_R",
"fullSubtreeExtensionCounts": {
".jpg": 3
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Std_Eyelash",
"fullSubtreeExtensionCounts": {
".jpg": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Std_Lower_Teeth",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Std_Nails",
"fullSubtreeExtensionCounts": {
".png": 2,
".jpg": 3
},
"numFiles": 5
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Std_Skin_Arm",
"fullSubtreeExtensionCounts": {
".png": 3,
".jpg": 3,
".tga": 1
},
"numFiles": 7
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Std_Skin_Body",
"fullSubtreeExtensionCounts": {
".png": 3,
".jpg": 4,
".tga": 1
},
"numFiles": 8
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Std_Skin_Head",
"fullSubtreeExtensionCounts": {
".png": 2,
".jpg": 9,
".tga": 4
},
"numFiles": 15
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Std_Skin_Leg",
"fullSubtreeExtensionCounts": {
".png": 3,
".jpg": 4,
".tga": 1
},
"numFiles": 8
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Std_Tongue",
"fullSubtreeExtensionCounts": {
".png": 4
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Dennis_Std_Upper_Teeth",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Lanyard",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Dennis\\Work_gloves_StringKnit",
"childrenFiles": [
{
"name": "Work_gloves_StringKnit_Diffuse.jpg"
},
{
"name": "Work_gloves_StringKnit_metallic.jpg"
},
{
"name": "Work_gloves_StringKnit_Normal.jpg"
},
{
"name": "Work_gloves_StringKnit_roughness.jpg"
},
{
"name": "Work_gloves_StringKnit_Specular.jpg"
}
],
"childrenWereProcessed": true
}
],
"childrenWereProcessed": true,
"fullSubtreeExtensionCounts": {
".png": 43,
".jpg": 58,
".tga": 8
},
"numFiles": 109
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Amazon_Polo_Blank",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Black_Sneakers",
"fullSubtreeExtensionCounts": {
".jpg": 3,
".png": 1
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\common",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\common\\FlatColors",
"fullSubtreeExtensionCounts": {
".png": 12,
".tga": 1
},
"numFiles": 13
}
],
"fullSubtreeExtensionCounts": {
".png": 14,
".jpg": 4,
".tga": 1
},
"numFiles": 19
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Hailey_Blunt_Lob_Hair_Transparency",
"fullSubtreeExtensionCounts": {
".jpg": 1,
".png": 1
},
"numFiles": 2
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Hailey_Std_Eyelash",
"fullSubtreeExtensionCounts": {
".jpg": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Hailey_Std_Lower_Teeth",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Hailey_Std_Nails",
"fullSubtreeExtensionCounts": {
".png": 1,
".jpg": 2
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Hailey_Std_Skin_Arm",
"fullSubtreeExtensionCounts": {
".png": 3,
".jpg": 4,
".tga": 1
},
"numFiles": 8
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Hailey_Std_Skin_Body",
"fullSubtreeExtensionCounts": {
".png": 3,
".jpg": 4,
".tga": 1
},
"numFiles": 8
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Hailey_Std_Skin_Head",
"fullSubtreeExtensionCounts": {
".png": 2,
".jpg": 8,
".tga": 4
},
"numFiles": 14
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Hailey_Std_Skin_Leg",
"fullSubtreeExtensionCounts": {
".png": 3,
".jpg": 3,
".tga": 1
},
"numFiles": 7
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Hailey_Std_Tongue",
"fullSubtreeExtensionCounts": {
".png": 2,
".jpg": 2
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Hailey_Std_Upper_Teeth",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Lanyard",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Scrub_Pants",
"fullSubtreeExtensionCounts": {
".jpg": 3,
".png": 1
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Hailey\\Work_gloves",
"childrenFiles": [
{
"name": "Work_gloves_Diffuse.jpg"
},
{
"name": "Work_gloves_metallic.jpg"
},
{
"name": "Work_gloves_Normal.jpg"
},
{
"name": "Work_gloves_Opacity.jpg"
},
{
"name": "Work_gloves_roughness.jpg"
},
{
"name": "Work_gloves_Specular.jpg"
}
],
"childrenWereProcessed": true
}
],
"childrenWereProcessed": true,
"fullSubtreeExtensionCounts": {
".jpg": 35,
".png": 35,
".tga": 8
},
"numFiles": 78
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\BlueJeans",
"fullSubtreeExtensionCounts": {
".jpg": 3
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\BluePolo",
"fullSubtreeExtensionCounts": {
".png": 2
},
"numFiles": 2
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\common",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\common\\FlatColors",
"fullSubtreeExtensionCounts": {
".png": 9,
".tga": 1
},
"numFiles": 10
}
],
"fullSubtreeExtensionCounts": {
".jpg": 7,
".png": 12,
".tga": 1
},
"numFiles": 20
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\Joe_Hair",
"fullSubtreeExtensionCounts": {
".jpg": 3,
".png": 1
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\Joe_Std_Eyelash",
"fullSubtreeExtensionCounts": {
".jpg": 1,
".png": 1
},
"numFiles": 2
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\Joe_Std_Lower_Teeth",
"fullSubtreeExtensionCounts": {
".jpg": 2,
".png": 2
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\Joe_Std_Nails",
"fullSubtreeExtensionCounts": {
".png": 2,
".jpg": 3
},
"numFiles": 5
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\Joe_Std_Skin_Arm",
"fullSubtreeExtensionCounts": {
".png": 2,
".tga": 1,
".jpg": 4
},
"numFiles": 7
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\Joe_Std_Skin_Body",
"fullSubtreeExtensionCounts": {
".png": 3,
".jpg": 4,
".tga": 1
},
"numFiles": 8
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\Joe_Std_Skin_Head",
"fullSubtreeExtensionCounts": {
".png": 2,
".jpg": 8,
".tga": 4
},
"numFiles": 14
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\Joe_Std_Skin_Leg",
"fullSubtreeExtensionCounts": {
".png": 3,
".tga": 1,
".jpg": 2
},
"numFiles": 6
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\Joe_Std_Tongue",
"fullSubtreeExtensionCounts": {
".png": 4
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\Joe_Std_Upper_Teeth",
"fullSubtreeExtensionCounts": {
".jpg": 2,
".png": 2
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\Lanyard",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\Loafers",
"fullSubtreeExtensionCounts": {
".jpg": 3
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Joe\\Work_gloves_StringKnit",
"childrenFiles": [
{
"name": "Work_gloves_StringKnit_Diffuse.jpg"
},
{
"name": "Work_gloves_StringKnit_metallic.jpg"
},
{
"name": "Work_gloves_StringKnit_Normal.jpg"
},
{
"name": "Work_gloves_StringKnit_roughness.jpg"
},
{
"name": "Work_gloves_StringKnit_Specular.jpg"
}
],
"childrenWereProcessed": true
}
],
"childrenWereProcessed": true,
"fullSubtreeExtensionCounts": {
".jpg": 42,
".png": 37,
".tga": 8
},
"numFiles": 87
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Cargo_Pants",
"fullSubtreeExtensionCounts": {
".png": 1,
".jpg": 2
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\common",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\common\\FlatColors",
"fullSubtreeExtensionCounts": {
".png": 7,
".tga": 1
},
"numFiles": 8
}
],
"fullSubtreeExtensionCounts": {
".png": 9,
".jpg": 4,
".tga": 1
},
"numFiles": 14
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Kirk_Hair_Transparency",
"fullSubtreeExtensionCounts": {
".jpg": 4,
".png": 3
},
"numFiles": 7
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Kirk_Scalp_Transparency",
"fullSubtreeExtensionCounts": {
".jpg": 2
},
"numFiles": 2
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Kirk_Std_Eyelash",
"fullSubtreeExtensionCounts": {
".png": 2
},
"numFiles": 2
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Kirk_Std_Lower_Teeth",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Kirk_Std_Nails",
"fullSubtreeExtensionCounts": {
".png": 5
},
"numFiles": 5
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Kirk_Std_Skin_Arm",
"fullSubtreeExtensionCounts": {
".png": 6,
".tga": 1,
".jpg": 1
},
"numFiles": 8
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Kirk_Std_Skin_Body",
"fullSubtreeExtensionCounts": {
".png": 6,
".tga": 1,
".jpg": 1
},
"numFiles": 8
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Kirk_Std_Skin_Head",
"fullSubtreeExtensionCounts": {
".png": 6,
".jpg": 5,
".tga": 4
},
"numFiles": 15
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Kirk_Std_Skin_Leg",
"fullSubtreeExtensionCounts": {
".png": 6,
".tga": 1,
".jpg": 1
},
"numFiles": 8
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Kirk_Std_Tongue",
"fullSubtreeExtensionCounts": {
".jpg": 4
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Kirk_Std_Upper_Teeth",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Kirk_TShirt",
"fullSubtreeExtensionCounts": {
".png": 1,
".jpg": 2
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Lanyard",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\White_Sneakers",
"fullSubtreeExtensionCounts": {
".jpg": 3,
".png": 1
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Kirk\\Work_gloves_StringKnit",
"childrenFiles": [
{
"name": "Work_gloves_StringKnit_Diffuse.jpg"
},
{
"name": "Work_gloves_StringKnit_metallic.jpg"
},
{
"name": "Work_gloves_StringKnit_Normal.jpg"
},
{
"name": "Work_gloves_StringKnit_roughness.jpg"
},
{
"name": "Work_gloves_StringKnit_Specular.jpg"
}
],
"childrenWereProcessed": true
}
],
"childrenWereProcessed": true,
"fullSubtreeExtensionCounts": {
".jpg": 29,
".png": 49,
".tga": 8
},
"numFiles": 86
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\common",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\common\\FlatColors",
"fullSubtreeExtensionCounts": {
".png": 7
},
"numFiles": 7
}
],
"fullSubtreeExtensionCounts": {
".jpg": 6,
".png": 10
},
"numFiles": 16
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Lanyard",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Manny_Hair",
"fullSubtreeExtensionCounts": {
".jpg": 2,
".png": 1,
".tif": 1
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Manny_Pants",
"fullSubtreeExtensionCounts": {
".jpg": 3
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Manny_Shirt",
"fullSubtreeExtensionCounts": {
".jpg": 3
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Manny_Shoes",
"fullSubtreeExtensionCounts": {
".jpg": 2,
".png": 1
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Manny_Std_Eyelash",
"childrenFiles": [
{
"name": "Manny_Std_Eyelash_Normal.png"
},
{
"name": "Manny_Std_Eyelash_Opacity.jpg"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Manny_Std_Lower_Teeth",
"childrenFiles": [
{
"name": "Manny_Std_Lower_Teeth_ao.jpg"
},
{
"name": "Manny_Std_Lower_Teeth_Diffuse.png"
},
{
"name": "Manny_Std_Lower_Teeth_Normal.png"
},
{
"name": "Manny_Std_Lower_Teeth_roughness.jpg"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Manny_Std_Nails",
"fullSubtreeExtensionCounts": {
".png": 2,
".jpg": 3
},
"numFiles": 5
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Manny_Std_Skin_Arm",
"fullSubtreeExtensionCounts": {
".png": 5,
".jpg": 2
},
"numFiles": 7
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Manny_Std_Skin_Body",
"childrenFiles": [
{
"name": "Manny_Std_Skin_Body_ao.png"
},
{
"name": "Manny_Std_Skin_Body_Diffuse.jpg"
},
{
"name": "Manny_Std_Skin_Body_MicroNMask.jpg"
},
{
"name": "Manny_Std_Skin_Body_Normal.png"
},
{
"name": "Manny_Std_Skin_Body_roughness.png"
},
{
"name": "Manny_Std_Skin_Body_SSSMap.png"
},
{
"name": "Manny_Std_Skin_Body_TransMap.png"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Manny_Std_Skin_Head",
"childrenFiles": [
{
"name": "Manny_Std_Skin_Head_ao.png"
},
{
"name": "Manny_Std_Skin_Head_BCBMap.jpg"
},
{
"name": "Manny_Std_Skin_Head_Diffuse.jpg"
},
{
"name": "Manny_Std_Skin_Head_ENMask.tga"
},
{
"name": "Manny_Std_Skin_Head_MicroNMask.jpg"
},
{
"name": "Manny_Std_Skin_Head_MNAOMask.tga"
},
{
"name": "Manny_Std_Skin_Head_NBMap.jpg"
},
{
"name": "Manny_Std_Skin_Head_Normal.png"
},
{
"name": "Manny_Std_Skin_Head_roughness.png"
},
{
"name": "Manny_Std_Skin_Head_SpecMask.jpg"
},
{
"name": "Manny_Std_Skin_Head_SSSMap.jpg"
},
{
"name": "Manny_Std_Skin_Head_TransMap.png"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Manny_Std_Skin_Leg",
"childrenFiles": [
{
"name": "Manny_Std_Skin_Leg_TransMap.png"
}
],
"fullSubtreeExtensionCounts": {
".png": 4,
".jpg": 1
},
"numFiles": 5
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Manny_Std_Tongue",
"childrenFiles": [
{
"name": "Manny_Std_Tongue_Diffuse.png"
},
{
"name": "Manny_Std_Tongue_Normal.png"
},
{
"name": "Manny_Std_Tongue_roughness.png"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Manny_Std_Upper_Teeth",
"fullSubtreeExtensionCounts": {
".jpg": 2,
".png": 2
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Manny\\Work_gloves_StringKnit",
"childrenFiles": [
{
"name": "Work_gloves_StringKnit_Diffuse.jpg"
},
{
"name": "Work_gloves_StringKnit_metallic.jpg"
},
{
"name": "Work_gloves_StringKnit_Normal.jpg"
},
{
"name": "Work_gloves_StringKnit_roughness.jpg"
},
{
"name": "Work_gloves_StringKnit_Specular.jpg"
}
],
"childrenWereProcessed": true
}
],
"fullSubtreeExtensionCounts": {
".png": 26,
".jpg": 24,
".tif": 1
},
"numFiles": 51
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\BlueJeans",
"fullSubtreeExtensionCounts": {
".jpg": 3
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\BluePolo",
"fullSubtreeExtensionCounts": {
".png": 2
},
"numFiles": 2
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\common",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\common\\FlatColors",
"fullSubtreeExtensionCounts": {
".png": 7,
".tga": 1
},
"numFiles": 8
}
],
"fullSubtreeExtensionCounts": {
".png": 9,
".jpg": 8,
".tga": 1
},
"numFiles": 18
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\Lanyard",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\Loafers",
"fullSubtreeExtensionCounts": {
".jpg": 3
},
"numFiles": 3
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\Martha_Hair",
"fullSubtreeExtensionCounts": {
".jpg": 3,
".tif": 1
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\Martha_Std_Eyelash",
"fullSubtreeExtensionCounts": {
".png": 1,
".jpg": 1
},
"numFiles": 2
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\Martha_Std_Lower_Teeth",
"fullSubtreeExtensionCounts": {
".jpg": 2,
".png": 2
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\Martha_Std_Nails",
"fullSubtreeExtensionCounts": {
".png": 2,
".jpg": 3
},
"numFiles": 5
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\Martha_Std_Skin_Arm",
"fullSubtreeExtensionCounts": {
".png": 4,
".jpg": 3,
".tga": 1
},
"numFiles": 8
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\Martha_Std_Skin_Body",
"fullSubtreeExtensionCounts": {
".png": 4,
".jpg": 3,
".tga": 1
},
"numFiles": 8
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\Martha_Std_Skin_Head",
"fullSubtreeExtensionCounts": {
".png": 4,
".jpg": 6,
".tga": 4
},
"numFiles": 14
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\Martha_Std_Skin_Leg",
"fullSubtreeExtensionCounts": {
".png": 4,
".jpg": 2,
".tga": 1
},
"numFiles": 7
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\Martha_Std_Tongue",
"fullSubtreeExtensionCounts": {
".png": 4
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\Martha_Std_Upper_Teeth",
"fullSubtreeExtensionCounts": {
".jpg": 2,
".png": 2
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Martha\\Work_gloves_StringKnit",
"childrenFiles": [
{
"name": "Work_gloves_StringKnit_Diffuse.jpg"
},
{
"name": "Work_gloves_StringKnit_metallic.jpg"
},
{
"name": "Work_gloves_StringKnit_Normal.jpg"
},
{
"name": "Work_gloves_StringKnit_roughness.jpg"
},
{
"name": "Work_gloves_StringKnit_Specular.jpg"
}
],
"childrenWereProcessed": true
}
],
"childrenWereProcessed": true,
"fullSubtreeExtensionCounts": {
".jpg": 39,
".png": 39,
".tga": 8,
".tif": 1
},
"numFiles": 87
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Black_Sneakers",
"fullSubtreeExtensionCounts": {
".jpg": 3,
".png": 1
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\common",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\common\\FlatColors",
"fullSubtreeExtensionCounts": {
".png": 9,
".tga": 1
},
"numFiles": 10
}
],
"fullSubtreeExtensionCounts": {
".jpg": 4,
".png": 11,
".tga": 1
},
"numFiles": 16
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Lanyard",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Fit_shirts",
"fullSubtreeExtensionCounts": {
".jpg": 4
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Hair",
"fullSubtreeExtensionCounts": {
".jpg": 3,
".tif": 1
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Scrub_Pants",
"fullSubtreeExtensionCounts": {
".jpg": 3,
".png": 1
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Eyelash",
"fullSubtreeExtensionCounts": {
".jpg": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Lower_Teeth",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Nails",
"fullSubtreeExtensionCounts": {
".png": 2,
".jpg": 3
},
"numFiles": 5
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Skin_Arm",
"fullSubtreeExtensionCounts": {
".png": 3,
".jpg": 4,
".tga": 1
},
"numFiles": 8
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Skin_Body",
"fullSubtreeExtensionCounts": {
".png": 3,
".jpg": 5,
".tga": 1
},
"numFiles": 9
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Skin_Head",
"fullSubtreeExtensionCounts": {
".png": 2,
".jpg": 9,
".tga": 4
},
"numFiles": 15
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Skin_Leg",
"fullSubtreeExtensionCounts": {
".png": 3,
".jpg": 4,
".tga": 1
},
"numFiles": 8
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Tongue",
"fullSubtreeExtensionCounts": {
".jpg": 4
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Upper_Teeth",
"fullSubtreeExtensionCounts": {
".png": 1
},
"numFiles": 1
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Work_gloves_StringKnit",
"childrenFiles": [
{
"name": "Work_gloves_StringKnit_Diffuse.jpg"
},
{
"name": "Work_gloves_StringKnit_metallic.jpg"
},
{
"name": "Work_gloves_StringKnit_Normal.jpg"
},
{
"name": "Work_gloves_StringKnit_roughness.jpg"
},
{
"name": "Work_gloves_StringKnit_Specular.jpg"
}
],
"childrenWereProcessed": true
}
],
"childrenWereProcessed": true,
"fullSubtreeExtensionCounts": {
".png": 29,
".jpg": 47,
".tga": 8,
".tif": 1
},
"numFiles": 85
}
],
"fullSubtreeExtensionCounts": {
".png": 324,
".jpg": 325,
".tga": 56,
".tif": 4
},
"numFiles": 709
}
}
Status: completed
Tool use: **read_file_v2** • Read file: e:\Rainys_Bulk_Scene_Tools\ops\AutoMatExtractor.py
Checking a character folder to see the file structure:
Tool use: **list_dir_v2**
Parameters:
{
"targetDirectory": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina"
}
Result:
{
"directoryTreeRoot": {
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Black_Sneakers",
"childrenFiles": [
{
"name": "Black_Sneakers_ao.jpg"
},
{
"name": "Black_Sneakers_Diffuse.jpg"
},
{
"name": "Black_Sneakers_Normal.png"
},
{
"name": "Black_Sneakers_roughness.jpg"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\common",
"childrenDirs": [
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\common\\FlatColors",
"childrenFiles": [
{
"name": "#000000.png"
},
{
"name": "#00000000.tga"
},
{
"name": "#010101.png"
},
{
"name": "#3A1D15.png"
},
{
"name": "#7F7F7F.png"
},
{
"name": "#7F7FFF.png"
},
{
"name": "#A6A6A6.png"
},
{
"name": "#D5D5D5.png"
},
{
"name": "#F9F8F6.png"
},
{
"name": "#FFFFFF.png"
}
],
"childrenWereProcessed": true
}
],
"childrenFiles": [
{
"name": "Regina_Std_Cornea_R_BCBMap.jpg"
},
{
"name": "Regina_Std_Cornea_R_Diffuse.jpg"
},
{
"name": "Regina_Std_Cornea_R_ScleraN.png"
},
{
"name": "Regina_Std_Tongue_MicroN.png"
},
{
"name": "Regina_Std_Upper_Teeth_GradAO.jpg"
},
{
"name": "Regina_Std_Upper_Teeth_GumsMask.jpg"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Lanyard",
"childrenFiles": [
{
"name": "Lanyard.png"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Fit_shirts",
"childrenFiles": [
{
"name": "Regina_Fit_shirts_ao.jpg"
},
{
"name": "Regina_Fit_shirts_Diffuse.jpg"
},
{
"name": "Regina_Fit_shirts_Normal.jpg"
},
{
"name": "Regina_Fit_shirts_roughness.jpg"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Hair",
"childrenFiles": [
{
"name": "Regina_Hair_ao.tif"
},
{
"name": "Regina_Hair_Diffuse.jpg"
},
{
"name": "Regina_Hair_Normal.jpg"
},
{
"name": "Regina_Hair_roughness.jpg"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Scrub_Pants",
"childrenFiles": [
{
"name": "Regina_Scrub_Pants_Diffuse.jpg"
},
{
"name": "Regina_Scrub_Pants_Normal.jpg"
},
{
"name": "Regina_Scrub_Pants_roughness.png"
},
{
"name": "Regina_Scrub_Pants_Specular.jpg"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Eyelash",
"childrenFiles": [
{
"name": "Regina_Std_Eyelash_Opacity.jpg"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Lower_Teeth",
"childrenFiles": [
{
"name": "Regina_Std_Lower_Teeth_Diffuse.png"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Nails",
"childrenFiles": [
{
"name": "Regina_Std_Nails_ao.jpg"
},
{
"name": "Regina_Std_Nails_Diffuse.jpg"
},
{
"name": "Regina_Std_Nails_Normal.png"
},
{
"name": "Regina_Std_Nails_roughness.jpg"
},
{
"name": "Regina_Std_Nails_TransMap.png"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Skin_Arm",
"childrenFiles": [
{
"name": "Regina_Std_Skin_Arm_ao.jpg"
},
{
"name": "Regina_Std_Skin_Arm_Diffuse.jpg"
},
{
"name": "Regina_Std_Skin_Arm_MicroNMask.jpg"
},
{
"name": "Regina_Std_Skin_Arm_Normal.png"
},
{
"name": "Regina_Std_Skin_Arm_RGBAMask.tga"
},
{
"name": "Regina_Std_Skin_Arm_roughness.jpg"
},
{
"name": "Regina_Std_Skin_Arm_SSSMap.png"
},
{
"name": "Regina_Std_Skin_Arm_TransMap.png"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Skin_Body",
"childrenFiles": [
{
"name": "Regina_Std_Skin_Body_ao.jpg"
},
{
"name": "Regina_Std_Skin_Body_Diffuse.jpg"
},
{
"name": "Regina_Std_Skin_Body_metallic.jpg"
},
{
"name": "Regina_Std_Skin_Body_MicroNMask.jpg"
},
{
"name": "Regina_Std_Skin_Body_Normal.png"
},
{
"name": "Regina_Std_Skin_Body_RGBAMask.tga"
},
{
"name": "Regina_Std_Skin_Body_roughness.jpg"
},
{
"name": "Regina_Std_Skin_Body_SSSMap.png"
},
{
"name": "Regina_Std_Skin_Body_TransMap.png"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Skin_Head",
"childrenFiles": [
{
"name": "Regina_Std_Skin_Head_ao.jpg"
},
{
"name": "Regina_Std_Skin_Head_BCBMap.jpg"
},
{
"name": "Regina_Std_Skin_Head_CFULCMask.tga"
},
{
"name": "Regina_Std_Skin_Head_Diffuse.jpg"
},
{
"name": "Regina_Std_Skin_Head_ENMask.tga"
},
{
"name": "Regina_Std_Skin_Head_metallic.jpg"
},
{
"name": "Regina_Std_Skin_Head_MicroNMask.jpg"
},
{
"name": "Regina_Std_Skin_Head_MNAOMask.tga"
},
{
"name": "Regina_Std_Skin_Head_NBMap.jpg"
},
{
"name": "Regina_Std_Skin_Head_NMUILMask.tga"
},
{
"name": "Regina_Std_Skin_Head_Normal.png"
},
{
"name": "Regina_Std_Skin_Head_roughness.jpg"
},
{
"name": "Regina_Std_Skin_Head_SpecMask.jpg"
},
{
"name": "Regina_Std_Skin_Head_SSSMap.jpg"
},
{
"name": "Regina_Std_Skin_Head_TransMap.png"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Skin_Leg",
"childrenFiles": [
{
"name": "Regina_Std_Skin_Leg_metallic.jpg"
},
{
"name": "Regina_Std_Skin_Leg_Normal.png"
},
{
"name": "Regina_Std_Skin_Leg_roughness.jpg"
},
{
"name": "Regina_Std_Skin_Leg_SSSMap.png"
}
],
"fullSubtreeExtensionCounts": {
".tga": 1,
".png": 1,
".jpg": 2
},
"numFiles": 4
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Tongue",
"childrenFiles": [
{
"name": "Regina_Std_Tongue_ao.jpg"
},
{
"name": "Regina_Std_Tongue_Diffuse.jpg"
},
{
"name": "Regina_Std_Tongue_Normal.jpg"
},
{
"name": "Regina_Std_Tongue_roughness.jpg"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Regina_Std_Upper_Teeth",
"childrenFiles": [
{
"name": "Regina_Std_Upper_Teeth_Diffuse.png"
}
],
"childrenWereProcessed": true
},
{
"absPath": "A:\\1 Amazon_Active_Projects\\1 BlenderAssets\\Amazon\\Char\\Cartoon1\\textures\\Regina\\Work_gloves_StringKnit",
"childrenFiles": [
{
"name": "Work_gloves_StringKnit_Diffuse.jpg"
},
{
"name": "Work_gloves_StringKnit_metallic.jpg"
},
{
"name": "Work_gloves_StringKnit_Normal.jpg"
},
{
"name": "Work_gloves_StringKnit_roughness.jpg"
},
{
"name": "Work_gloves_StringKnit_Specular.jpg"
}
],
"childrenWereProcessed": true
}
],
"fullSubtreeExtensionCounts": {
".tga": 1,
".png": 1,
".jpg": 2
},
"numFiles": 4
}
}
Status: completed
Tool use: **run_terminal_command_v2** • Run command: Get-ChildItem "A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon1\textures" -Recurse -File | Select-Object -First 10 FullName
Get-ChildItem "A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon1\textures" -Recurse -File | Select-Object -First 10 FullName
Updating the plan based on the folder structure and workflow:
Tool use: **read_file_v2** • Read file: c:\Users\Nathan\.cursor\plans\update_organize_textures_script_6f224239.plan.md
Updating the plan with the clarified requirements:
Tool use: **edit_file_v2** • Edit file: c:\Users\Nathan\.cursor\plans\update_organize_textures_script_6f224239.plan.md
**Considerations:**
- Flatten all files into `\common` (consolidating from multiple blendfile texture folders)
- Skip the `\common` folder itself when processing files to avoid recursion
- Handle name conflicts when multiple files have the same name but different checksums (append unique identifier)
- Provide progress feedback for large directories
- For duplicates: first file keeps original name in `\common`, subsequent files go to `\common\duplicates` with numbered suffixes (.001, .002, etc.)
**Workflow Context:**
- AutoMat Extractor creates material-specific folders (e.g., `Regina\Regina_Hair\`, `Regina\common\`)
- This script consolidates textures from multiple blendfiles into a single `\common` folder
- After consolidation, user will relink textures using FMT
- Duplicates in `\common\duplicates` are for debugging purposes only
Adding more specific implementation details:
The string to replace was not found in the file.
Tool use: **edit_file_v2** • Edit file: c:\Users\Nathan\.cursor\plans\update_organize_textures_script_6f224239.plan.md
9. For each checksum group:
- If only one file: move it to `\common` (flattened, using original filename)
- If multiple files (duplicates):
- Move the first file to `\common` (keep original filename)
- Move remaining files to `\common\duplicates` with numbered suffixes (.001, .002, etc.)
- Format: `[original_name].001[extension]`, `[original_name].002[extension]`, etc.
10. Handle file name conflicts:
- Track filenames already moved to `\common`
- If a file with the same name but different checksum exists, append a unique suffix (e.g., `_1`, `_2`) before extension
- This ensures no overwrites when consolidating from multiple sources
Adding an algorithm flow section:
Tool use: **edit_file_v2** • Edit file: c:\Users\Nathan\.cursor\plans\update_organize_textures_script_6f224239.plan.md
4. Use `Get-ChildItem -Recurse -File` to get all files recursively
- Exclude files in `\common` folder to avoid processing already-moved files
- Use `Where-Object { $_.FullName -notlike "*\common\*" }` filter
5. Calculate SHA256 checksum for each file using `Get-FileHash -Algorithm SHA256`
6. Group files by checksum value using `Group-Object`
Plan Summary
Main Changes:
- Replace prefix-based grouping with checksum-based duplicate detection
- Add user prompt for texture folder path
- Recursively process all files (excluding
\commonfolder to avoid recursion) - Calculate SHA256 checksums for all files
- Group files by checksum to identify duplicates
- Move all files to
\commonfolder (flattened structure) - For duplicates: keep first file in
\common, move rest to\common\duplicateswith numbered suffixes (.001, .002, etc.) - Handle name conflicts when different files have the same name
Key Implementation Details:
- Use
Get-FileHash -Algorithm SHA256for checksum calculation - Filter out
\commonfolder during file collection - Track moved filenames to handle conflicts
- Number duplicates as
filename.001.ext,filename.002.ext, etc.
The plan is ready for review. Should I proceed with implementation, or do you want any changes?
User
Implement the plan as specified, it is attached for your reference. Do NOT edit the plan file itself.
To-do's from the plan have already been created. Do not create them again. Mark them as in_progress as you work, starting with the first one. Don't stop until you have completed all the to-dos.
Agent (model default, mode Agent)
Implementing the plan. Reviewing the current script, then rewriting it.
Tool use: **read_file_v2** • Read file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.ps1
Tool use: **read_file_v2** • Read file: c:\Users\Nathan\.cursor\plans\update_organize_textures_script_6f224239.plan.md
Rewriting the script according to the plan:
Tool use: **edit_file_v2** • Edit file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.ps1
# Script to organize texture files by checksum, moving all files to \common and duplicates to \common\duplicates
# Usage: .\organize_textures.ps1
# Prompt user for texture folder path
$textureFolderPath = Read-Host "Enter texture folder path (e.g., A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon1\textures)"
# Validate the input path
if ([string]::IsNullOrWhiteSpace($textureFolderPath)) {
Write-Host "Error: No path provided." -ForegroundColor Red
exit
}
if (-not (Test-Path -Path $textureFolderPath -PathType Container)) {
Write-Host "Error: Path does not exist or is not a directory: $textureFolderPath" -ForegroundColor Red
exit
}
# Resolve the full path
$textureFolderPath = (Resolve-Path $textureFolderPath).ProviderPath
Write-Host "Processing texture folder: $textureFolderPath" -ForegroundColor Cyan
# Get all files recursively, excluding the \common folder to avoid processing already-moved files
Write-Host "Collecting files..." -ForegroundColor Yellow
$allFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { $_.FullName -notlike "*\common\*" }
if ($null -eq $allFiles -or $allFiles.Count -eq 0) {
Write-Host "No files found to process (excluding \common folder)." -ForegroundColor Yellow
exit
}
Write-Host "Found $($allFiles.Count) files to process." -ForegroundColor Green
# Calculate checksums for all files
Write-Host "Calculating checksums (this may take a while)..." -ForegroundColor Yellow
$filesWithChecksums = @()
$fileCount = 0
foreach ($file in $allFiles) {
$fileCount++
if ($fileCount % 50 -eq 0) {
Write-Host " Processed $fileCount / $($allFiles.Count) files..." -ForegroundColor Gray
}
try {
$hash = Get-FileHash -Path $file.FullName -Algorithm SHA256
$filesWithChecksums += [PSCustomObject]@{
File = $file
Hash = $hash.Hash
}
} catch {
Write-Warning "Failed to calculate checksum for: $($file.FullName) - $($_.Exception.Message)"
}
}
Write-Host "Checksum calculation complete." -ForegroundColor Green
# Group files by checksum
Write-Host "Grouping files by checksum..." -ForegroundColor Yellow
$groupedByChecksum = $filesWithChecksums | Group-Object -Property Hash
Write-Host "Found $($groupedByChecksum.Count) unique checksums." -ForegroundColor Green
# Create \common and \common\duplicates directories
$commonPath = Join-Path -Path $textureFolderPath -ChildPath "common"
$duplicatesPath = Join-Path -Path $commonPath -ChildPath "duplicates"
if (-not (Test-Path -Path $commonPath -PathType Container)) {
New-Item -ItemType Directory -Path $commonPath | Out-Null
Write-Host "Created directory: $commonPath" -ForegroundColor Green
}
if (-not (Test-Path -Path $duplicatesPath -PathType Container)) {
New-Item -ItemType Directory -Path $duplicatesPath | Out-Null
Write-Host "Created directory: $duplicatesPath" -ForegroundColor Green
}
# Track filenames already in \common to handle name conflicts
$filesInCommon = @{}
# Process each checksum group
Write-Host "Moving files to \common and \common\duplicates..." -ForegroundColor Yellow
$movedCount = 0
$duplicateCount = 0
foreach ($group in $groupedByChecksum) {
$files = $group.Group
if ($files.Count -eq 1) {
# Single file - move to \common
$fileObj = $files[0].File
$fileName = $fileObj.Name
$destinationPath = Join-Path -Path $commonPath -ChildPath $fileName
# Handle name conflicts
if ($filesInCommon.ContainsKey($fileName)) {
# File with same name but different checksum already exists
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($fileName)
$extension = [System.IO.Path]::GetExtension($fileName)
$counter = 1
do {
$newFileName = "${baseName}_${counter}${extension}"
$destinationPath = Join-Path -Path $commonPath -ChildPath $newFileName
$counter++
} while ($filesInCommon.ContainsKey($newFileName) -or (Test-Path -Path $destinationPath))
$fileName = $newFileName
Write-Host " Name conflict resolved: renamed to '$fileName'" -ForegroundColor Yellow
}
try {
Move-Item -Path $fileObj.FullName -Destination $destinationPath -Force
$filesInCommon[$fileName] = $true
$movedCount++
} catch {
Write-Warning "Failed to move file: $($fileObj.FullName) - $($_.Exception.Message)"
}
} else {
# Multiple files with same checksum (duplicates)
# Move first file to \common
$firstFile = $files[0].File
$fileName = $firstFile.Name
$destinationPath = Join-Path -Path $commonPath -ChildPath $fileName
# Handle name conflicts for the first file
if ($filesInCommon.ContainsKey($fileName)) {
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($fileName)
$extension = [System.IO.Path]::GetExtension($fileName)
$counter = 1
do {
$newFileName = "${baseName}_${counter}${extension}"
$destinationPath = Join-Path -Path $commonPath -ChildPath $newFileName
$counter++
} while ($filesInCommon.ContainsKey($newFileName) -or (Test-Path -Path $destinationPath))
$fileName = $newFileName
Write-Host " Name conflict resolved for duplicate group: renamed to '$fileName'" -ForegroundColor Yellow
}
try {
Move-Item -Path $firstFile.FullName -Destination $destinationPath -Force
$filesInCommon[$fileName] = $true
$movedCount++
} catch {
Write-Warning "Failed to move first duplicate file: $($firstFile.FullName) - $($_.Exception.Message)"
}
# Move remaining files to \common\duplicates with numbered suffixes
for ($i = 1; $i -lt $files.Count; $i++) {
$fileObj = $files[$i].File
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($fileObj.Name)
$extension = [System.IO.Path]::GetExtension($fileObj.Name)
$numberedFileName = "${baseName}.$($i.ToString('000'))${extension}"
$duplicateDestinationPath = Join-Path -Path $duplicatesPath -ChildPath $numberedFileName
# Handle name conflicts in duplicates folder
$conflictCounter = 1
while (Test-Path -Path $duplicateDestinationPath) {
$numberedFileName = "${baseName}.$($i.ToString('000'))_${conflictCounter}${extension}"
$duplicateDestinationPath = Join-Path -Path $duplicatesPath -ChildPath $numberedFileName
$conflictCounter++
}
try {
Move-Item -Path $fileObj.FullName -Destination $duplicateDestinationPath -Force
$duplicateCount++
} catch {
Write-Warning "Failed to move duplicate file: $($fileObj.FullName) - $($_.Exception.Message)"
}
}
}
}
Write-Host ""
Write-Host "File organization complete!" -ForegroundColor Green
Write-Host " Files moved to \common: $movedCount" -ForegroundColor Cyan
Write-Host " Duplicate files moved to \common\duplicates: $duplicateCount" -ForegroundColor Cyan
Implemented the script per the plan. Summary:
Implemented features:
- User prompt for texture folder path using
Read-Host - Path validation (exists and is a directory)
- Recursive file collection excluding
\commonfolder - SHA256 checksum calculation with progress feedback
- Grouping files by checksum to identify duplicates
- Creating
\commonand\common\duplicatesdirectories - Moving files:
- Single files →
\common(flattened) - Duplicates → first to
\common, rest to\common\duplicateswith.001,.002, etc. suffixes
- Single files →
- Name conflict handling: different files with the same name get
_1,_2, etc. suffixes
Additional features:
- Progress feedback during checksum calculation and file processing
- Error handling with try-catch blocks
- Summary statistics at the end
The script is ready to use. It will consolidate textures from multiple blendfile texture folders into a single \common folder, with duplicates numbered in \common\duplicates for debugging.
User
create a batch for it, and for @ConfigLoader.ps1
Agent (model default, mode Agent)
Creating batch files for both scripts. Checking ConfigLoader.ps1 first:
Tool use: **read_file_v2** • Read file: a:\1 Amazon_Active_Projects\3 ProjectStructure\ConfigLoader.ps1
Tool use: **glob_file_search** • Searched codebase "undefined" • **12** results in **1** directory
Directory: a:\1 Amazon_Active_Projects\3 ProjectStructure (12 files)
| File |
|---|
../NewDaily.bat |
../UnzipSeqArchv.bat |
../compress_blend_files.bat |
../scripts_old/PushAllToCurrent.bat |
../UpdateAllSequences.bat |
../UpdateSequences.bat |
../remove_action_fake_users.bat |
../scripts_old/RebuildDailies.bat |
../NewProject.bat |
../UpgradeToGitProj.bat |
../scripts_old/0MoveToCurrent.bat |
../ZipSeqArchv.bat |
Checking an existing batch file to see the pattern:
Tool use: **read_file_v2** • Read file: a:\1 Amazon_Active_Projects\3 ProjectStructure\UpdateSequences.bat
Creating batch files for both scripts:
Cancelled
Cancelled
User
@organize_textures.bat:1-22 it instantly closes. cfgload is good, tho!
Agent (model default, mode Agent)
Adding a pause at the end so the window stays open on success. Updating the batch file:
Tool use: **read_file_v2** • Read file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.bat
Tool use: **edit_file_v2** • Edit file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.bat
if %rc% neq 0 (
echo.
echo Script exited with error code %rc%
)
echo.
pause
exit /b %rc%
Updated the batch file to pause at the end on both success and failure, so you can see the output before the window closes. It now matches the behavior of ConfigLoader.bat.
User
@PowerShell Extension (1-1074) wow, all that happened in one second?
remove the e.g. path, it's too long and not useful anyway.
Agent (model default, mode Agent)
Removing the example path from the prompt:
Tool use: **read_file_v2** • Read file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.ps1
Tool use: **edit_file_v2** • Edit file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.ps1
# Prompt user for texture folder path
$textureFolderPath = Read-Host "Enter texture folder path"
Removed the example path from the prompt. It now reads "Enter texture folder path" without the long example.
Note: The checksum errors suggest Get-FileHash isn't available, possibly due to PowerShell version or execution policy. The script should still work once that's resolved.
User
how do I make it use the proper ExecutionPolicy?
Agent (model default, mode Agent)
Updating the batch file to check and set the execution policy if needed, or use a more appropriate policy:
Tool use: **read_file_v2** • Read file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.bat
Updating the batch file to set the execution policy properly:
Tool use: **edit_file_v2** • Edit file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.bat
echo Running texture organizer...
powershell -NoProfile -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Force; & '%ps1_path%'"
set "rc=%errorlevel%"
Updating the batch file to set the execution policy only if needed:
Tool use: **edit_file_v2** • Edit file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.bat
echo Running texture organizer...
powershell -NoProfile -Command "$policy = Get-ExecutionPolicy -Scope CurrentUser; if ($policy -eq 'Restricted') { Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Force }; & '%ps1_path%'"
set "rc=%errorlevel%"
The batch file now checks the current user's execution policy and sets it to RemoteSigned if it's Restricted. This allows local scripts to run without bypassing the policy each time.
If you prefer to bypass the policy only for this script run (without changing system settings), we can revert to using -ExecutionPolicy Bypass for the current process only. The current approach sets a proper policy for your user account.
Note: The Get-FileHash errors are likely due to an older PowerShell version (requires 4.0+) or the cmdlet not being available, not an execution policy issue.
User
@pwsh (4-12)
Agent (model default, mode Agent)
Switching the batch file to use pwsh (PowerShell Core) instead of powershell, and simplifying the execution policy handling:
Tool use: **read_file_v2** • Read file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.bat
Tool use: **edit_file_v2** • Edit file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.bat
echo Running texture organizer...
pwsh -NoProfile -ExecutionPolicy Bypass -File "%ps1_path%"
set "rc=%errorlevel%"
Updated the batch file to use pwsh (PowerShell Core) instead of powershell. It uses -ExecutionPolicy Bypass for this run only, which avoids module loading issues and should make Get-FileHash available.
The Bypass flag only applies to this execution, so it doesn't change your system's execution policy.
User
@pwsh (15-43) nice, does this use max multithreading?
Agent (model default, mode Agent)
The script runs sequentially. Adding parallel processing for checksum calculation to speed it up:
Tool use: **read_file_v2** • Read file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.ps1
Tool use: **edit_file_v2** • Edit file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.ps1
# Calculate checksums for all files using parallel processing
Write-Host "Calculating checksums using parallel processing (this may take a while)..." -ForegroundColor Yellow
$filesWithChecksums = $allFiles | ForEach-Object -Parallel {
try {
$hash = Get-FileHash -Path $_.FullName -Algorithm SHA256
[PSCustomObject]@{
File = $_
Hash = $hash.Hash
}
} catch {
Write-Warning "Failed to calculate checksum for: $($_.FullName) - $($_.Exception.Message)"
$null
}
} -ThrottleLimit ([Math]::Max(1, [Environment]::ProcessorCount))
Tool use: **edit_file_v2** • Edit file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.ps1
# Calculate checksums for all files using parallel processing
Write-Host "Calculating checksums using parallel processing (this may take a while)..." -ForegroundColor Yellow
$filesWithChecksums = $allFiles | ForEach-Object -Parallel {
try {
$hash = Get-FileHash -Path $_.FullName -Algorithm SHA256
[PSCustomObject]@{
File = $_
Hash = $hash.Hash
}
} catch {
Write-Warning "Failed to calculate checksum for: $($_.FullName) - $($_.Exception.Message)"
$null
}
} -ThrottleLimit ([Math]::Max(1, [Environment]::ProcessorCount)) | Where-Object { $null -ne $_ }
Updated the script to use parallel processing for checksum calculation. It now uses ForEach-Object -Parallel with -ThrottleLimit set to your processor count, so it uses all available CPU cores.
This should speed up checksum calculation, especially on multi-core systems. The parallel processing only applies to checksum calculation (the slowest part); file moving remains sequential to avoid conflicts.
On your next run, checksum calculation should be faster.
User
[{ "resource": "/a:/1 Amazon_Active_Projects/3 ProjectStructure/organize_textures.ps1", "owner": "generated_diagnostic_collection_name#1", "severity": 8, "message": "Unexpected token '-ThrottleLimit' in expression or statement.", "source": "PowerShell", "startLineNumber": 46, "startColumn": 3, "endLineNumber": 46, "endColumn": 17, "modelVersionId": 2 },{ "resource": "/a:/1 Amazon_Active_Projects/3 ProjectStructure/organize_textures.ps1", "owner": "generated_diagnostic_collection_name#1", "severity": 8, "message": "Unexpected token '(' in expression or statement.", "source": "PowerShell", "startLineNumber": 46, "startColumn": 18, "endLineNumber": 46, "endColumn": 19, "modelVersionId": 2 },{ "resource": "/a:/1 Amazon_Active_Projects/3 ProjectStructure/organize_textures.ps1", "owner": "generated_diagnostic_collection_name#1", "severity": 8, "message": "The Try statement is missing its Catch or Finally block.", "source": "PowerShell", "startLineNumber": 48, "startColumn": 10, "endLineNumber": 48, "endColumn": 10, "modelVersionId": 2 },{ "resource": "/a:/1 Amazon_Active_Projects/3 ProjectStructure/organize_textures.ps1", "owner": "generated_diagnostic_collection_name#1", "severity": 8, "message": "Unexpected token '}' in expression or statement.", "source": "PowerShell", "startLineNumber": 52, "startColumn": 1, "endLineNumber": 52, "endColumn": 2, "modelVersionId": 2 }]
Agent (model default, mode Agent)
Fixing the syntax error: -ThrottleLimit must be on the same line as -Parallel or properly formatted. Updating the code:
Tool use: **read_file_v2** • Read file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.ps1
Storing the throttle limit in a variable to resolve the linter issue:
Tool use: **edit_file_v2** • Edit file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.ps1
# Calculate checksums for all files using parallel processing
Write-Host "Calculating checksums using parallel processing (this may take a while)..." -ForegroundColor Yellow
$throttleLimit = [Math]::Max(1, [Environment]::ProcessorCount)
$filesWithChecksums = $allFiles | ForEach-Object -Parallel {
try {
$hash = Get-FileHash -Path $_.FullName -Algorithm SHA256
[PSCustomObject]@{
File = $_
Hash = $hash.Hash
}
} catch {
Write-Warning "Failed to calculate checksum for: $($_.FullName) - $($_.Exception.Message)"
$null
}
} -ThrottleLimit $throttleLimit | Where-Object { $null -ne $_ }
Fixed the syntax error by storing the throttle limit in a variable first. This should resolve the linter errors. The code should work correctly now—the parallel processing will still use all available CPU cores.
User
[{ "resource": "/a:/1 Amazon_Active_Projects/3 ProjectStructure/organize_textures.ps1", "owner": "generated_diagnostic_collection_name#1", "severity": 8, "message": "Unexpected token '}' in expression or statement.", "source": "PowerShell", "startLineNumber": 49, "startColumn": 9, "endLineNumber": 49, "endColumn": 10, "modelVersionId": 3 },{ "resource": "/a:/1 Amazon_Active_Projects/3 ProjectStructure/organize_textures.ps1", "owner": "generated_diagnostic_collection_name#1", "severity": 8, "message": "Unexpected token '}' in expression or statement.", "source": "PowerShell", "startLineNumber": 50, "startColumn": 5, "endLineNumber": 50, "endColumn": 6, "modelVersionId": 3 },{ "resource": "/a:/1 Amazon_Active_Projects/3 ProjectStructure/organize_textures.ps1", "owner": "generated_diagnostic_collection_name#1", "severity": 8, "message": "Unexpected token '}' in expression or statement.", "source": "PowerShell", "startLineNumber": 53, "startColumn": 1, "endLineNumber": 53, "endColumn": 2, "modelVersionId": 3 }]
Agent (model default, mode Agent)
Checking the current code structure. The linter may not recognize -Parallel (PowerShell 7+). Verifying the syntax:
Tool use: **read_file_v2** • Read file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.ps1
The syntax is correct. The linter likely uses an older PowerShell parser that doesn't recognize -Parallel (PowerShell 7+). Restructuring slightly to help the linter:
Tool use: **edit_file_v2** • Edit file: a:\1 Amazon_Active_Projects\3 ProjectStructure\organize_textures.ps1
# Calculate checksums for all files using parallel processing
Write-Host "Calculating checksums using parallel processing (this may take a while)..." -ForegroundColor Yellow
$throttleLimit = [Math]::Max(1, [Environment]::ProcessorCount)
$parallelScriptBlock = {
try {
$hash = Get-FileHash -Path $_.FullName -Algorithm SHA256
[PSCustomObject]@{
File = $_
Hash = $hash.Hash
}
} catch {
Write-Warning "Failed to calculate checksum for: $($_.FullName) - $($_.Exception.Message)"
$null
}
}
$filesWithChecksums = $allFiles | ForEach-Object -Parallel $parallelScriptBlock -ThrottleLimit $throttleLimit | Where-Object { $null -ne $_ }
Extracted the script block into a variable to help the linter parse it. The errors are likely false positives because the linter may not recognize -Parallel (PowerShell 7+). The code should run correctly with pwsh at runtime. If the errors persist, they’re linter limitations and won’t affect execution.
User
[{ "resource": "/a:/1 Amazon_Active_Projects/3 ProjectStructure/organize_textures.ps1", "owner": "generated_diagnostic_collection_name#1", "severity": 8, "message": "Unexpected token '}' in expression or statement.", "source": "PowerShell", "startLineNumber": 50, "startColumn": 9, "endLineNumber": 50, "endColumn": 10, "modelVersionId": 4 },{ "resource": "/a:/1 Amazon_Active_Projects/3 ProjectStructure/organize_textures.ps1", "owner": "generated_diagnostic_collection_name#1", "severity": 8, "message": "Unexpected token '}' in expression or statement.", "source": "PowerShell", "startLineNumber": 51, "startColumn": 5, "endLineNumber": 51, "endColumn": 6, "modelVersionId": 4 },{ "resource": "/a:/1 Amazon_Active_Projects/3 ProjectStructure/organize_textures.ps1", "owner": "generated_diagnostic_collection_name#1", "severity": 8, "message": "Unexpected token '}' in expression or statement.", "source": "PowerShell", "startLineNumber": 54, "startColumn": 1, "endLineNumber": 54, "endColumn": 2, "modelVersionId": 4 }]
Agent (model default, mode Agent)
These are linter false positives. The linter doesn't recognize PowerShell 7's -Parallel parameter, so it misparses the syntax. The code is correct and will run with pwsh.
The errors are on:
- Line 50: closing brace of the script block (correct)
- Line 51: closing brace of the try-catch (correct)
- Line 54: after the ForEach-Object line (correct)
The syntax is valid for PowerShell 7+. You can ignore these linter warnings; they won't affect execution. If you want, I can add a comment to document this, but the code will work as-is when run with pwsh.
User
can I update my linter for pwsh 7+?
Agent (model default, mode Agent)
Yes. Configure the PowerShell extension to use PowerShell 7+ so the linter recognizes features like -Parallel.
In VS Code/Cursor:
- Open Settings (Ctrl+, or Cmd+,)
- Search for "PowerShell: PSDebugOnDemand" or "PowerShell: Pwsh Path"
- Set the PowerShell path:
- Search for
powershell.powerShellDefaultVersion - Set it to
PowerShell(PowerShell 7+) instead ofWindows PowerShell - Or set
powershell.powerShellExePathto the full path topwsh.exe(e.g.,C:\Program Files\PowerShell\7\pwsh.exe)
- Search for
Or via settings.json:
{
"powershell.powerShellDefaultVersion": "PowerShell",
"powershell.powerShellExePath": "C:\\Program Files\\PowerShell\\7\\pwsh.exe"
}
To find your pwsh path:
Run pwsh -Command '$PSHOME' in a terminal, then use that path.
After updating, restart the editor or reload the window (Ctrl+Shift+P → "Developer: Reload Window"). The linter should then recognize PowerShell 7+ syntax and the errors should disappear.
User
what
Agent (model default, mode Agent)
The warning is due to a misconfigured setting. powerShellDefaultVersion should be a string identifier (like "PowerShell"), not a file path.
Fix it:
- Open Settings (Ctrl+,)
- Search for
powershell.powerShellDefaultVersion - Set it to:
"PowerShell"(not a file path) - If you want to specify the exact path, use
powershell.powerShellExePathinstead and set it to:"C:\\Program Files\\PowerShell\\7\\pwsh.exe"
Or in settings.json:
{
"powershell.powerShellDefaultVersion": "PowerShell",
"powershell.powerShellExePath": "C:\\Program Files\\PowerShell\\7\\pwsh.exe"
}
The warning is harmless—it’s already using PowerShell 7. Fixing the setting removes the warning and ensures the linter recognizes PowerShell 7+ syntax like -Parallel.
After updating, reload the window (Ctrl+Shift+P → "Developer: Reload Window") for the changes to take effect.
User
For the code present, we get this error:
**Deprecated:** Please use the `#powershell.powerShellAdditionalExePaths#` setting instead.
Fix it, verify, and then give a concise explanation. @c:\Users\Nathan\AppData\Roaming\Cursor\User\settings.json:28-30
Agent (model default, mode Agent)
Fixing the deprecated setting. Reading the settings file:
Tool use: **read_file_v2** • Read file: c:\Users\Nathan\AppData\Roaming\Cursor\User\settings.json
Updating the settings to use the new format:
Cancelled
User
For the code present, we get this error:
Incorrect type. Expected "object".
Fix it, verify, and then give a concise explanation. @c:\Users\Nathan\AppData\Roaming\Cursor\User\settings.json:30-33
Agent (model default, mode Agent)
Reading the settings file to check the structure:
Tool use: **read_file_v2** • Read file: c:\Users\Nathan\AppData\Roaming\Cursor\User\settings.json
Fixing the structure: powerShellAdditionalExePaths expects an object (key-value pairs), not an array.
Cancelled
User
why aren't you asking to approve file edit? you're just freezing on it
Agent (model default, mode Agent)
Retrying the edit. The setting expects an object (key-value pairs), not an array:
Tool use: **read_file_v2** • Read file: c:\Users\Nathan\AppData\Roaming\Cursor\User\settings.json
Cancelled
User
still wrong
Agent (model default, mode Agent)
Fixing the JSON syntax error (trailing comma) and correcting the PowerShell settings:
Tool use: **read_file_v2** • Read file: c:\Users\Nathan\AppData\Roaming\Cursor\User\settings.json
Fixing the trailing comma and updating the PowerShell settings to match the detected version:
Cancelled
Cancelled
User
let's make sure that universally, the FlatColors are all saved as 16x16 jpgs, unless they're .tga. also, duplicate flatcolors can and absolutely should be merged.
Agent (model default, mode Agent)
Exploring the project structure to locate FlatColors and check for existing scripts that handle them.
Tool use: **semantic_search_full**
Parameters:
{
"query": "Where are FlatColors stored or processed?",
"topK": 10,
"explanation": ""
}
Result:
{
"codeResults": [
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 355
},
"endPosition": {
"line": 390
}
},
"contents": "$allFlatColorsFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { \n ($_.FullName -like \"*\\FlatColors\\*\" -or $_.Name -like \"*FlatColors*\") -and \n $_.FullName -notlike \"$([regex]::Escape($rootCommonFlatColorsPath))\\*\" \n}\n\n# Get all remaining files (excluding all \\common folders, but we'll handle FlatColors separately)\nWrite-Host \"Collecting remaining files...\" -ForegroundColor Yellow\n$remainingFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { $_.FullName -notlike \"*\\common\\*\" }\n\nif ($null -eq $remainingFiles -or $remainingFiles.Count -eq 0) {\n Write-Host \"No remaining files found to process.\" -ForegroundColor Yellow\n} else {\n Write-Host \"Found $($remainingFiles.Count) remaining files to process.\" -ForegroundColor Green\n \n # Calculate checksums\n Write-Host \"Calculating checksums using parallel processing (this may take a while)...\" -ForegroundColor Yellow\n $filesWithChecksums = Get-FilesWithChecksums -Files $remainingFiles\n \n Write-Host \"Checksum calculation complete.\" -ForegroundColor Green\n \n # Separate FlatColors files from other files before processing\n Write-Host \"Identifying FlatColors files...\" -ForegroundColor Yellow\n $flatColorsFiles = $allFlatColorsFiles | Where-Object { (Test-Path -Path $_.FullName) }\n $nonFlatColorsFiles = $remainingFiles | Where-Object { $_.Name -notlike \"*FlatColors*\" }\n \n Write-Host \"Found $($flatColorsFiles.Count) FlatColors file(s) (including from \\common\\FlatColors folders), $($nonFlatColorsFiles.Count) other file(s)\" -ForegroundColor Gray\n \n # Group non-FlatColors files by checksum\n Write-Host \"Grouping files by checksum...\" -ForegroundColor Yellow\n $nonFlatColorsWithChecksums = $filesWithChecksums | Where-Object { $_.File.Name -notlike \"*FlatColors*\" }\n $groupedByChecksum = $nonFlatColorsWithChecksums | Group-Object -Property Hash\n \n Write-Host \"Found $($groupedByChecksum.Count) unique checksums.\" -ForegroundColor Green\n \n # Create \\textures\\common directory",
"signatures": {},
"detailedLines": [
{
"text": "$allFlatColorsFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { ",
"lineNumber": 356
},
{
"text": " ($_.FullName -like \"*\\FlatColors\\*\" -or $_.Name -like \"*FlatColors*\") -and ",
"lineNumber": 357
},
{
"text": " $_.FullName -notlike \"$([regex]::Escape($rootCommonFlatColorsPath))\\*\" ",
"lineNumber": 358
},
{
"text": "}",
"lineNumber": 359
},
{
"lineNumber": 360
},
{
"text": "# Get all remaining files (excluding all \\common folders, but we'll handle FlatColors separately)",
"lineNumber": 361
},
{
"text": "Write-Host \"Collecting remaining files...\" -ForegroundColor Yellow",
"lineNumber": 362
},
{
"text": "$remainingFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { $_.FullName -notlike \"*\\common\\*\" }",
"lineNumber": 363
},
{
"lineNumber": 364
},
{
"text": "if ($null -eq $remainingFiles -or $remainingFiles.Count -eq 0) {",
"lineNumber": 365
},
{
"text": " Write-Host \"No remaining files found to process.\" -ForegroundColor Yellow",
"lineNumber": 366
},
{
"text": "} else {",
"lineNumber": 367
},
{
"text": " Write-Host \"Found $($remainingFiles.Count) remaining files to process.\" -ForegroundColor Green",
"lineNumber": 368
},
{
"text": " ",
"lineNumber": 369
},
{
"text": " # Calculate checksums",
"lineNumber": 370
},
{
"text": " Write-Host \"Calculating checksums using parallel processing (this may take a while)...\" -ForegroundColor Yellow",
"lineNumber": 371
},
{
"text": " $filesWithChecksums = Get-FilesWithChecksums -Files $remainingFiles",
"lineNumber": 372
},
{
"text": " ",
"lineNumber": 373
},
{
"text": " Write-Host \"Checksum calculation complete.\" -ForegroundColor Green",
"lineNumber": 374
},
{
"text": " ",
"lineNumber": 375
},
{
"text": " # Separate FlatColors files from other files before processing",
"lineNumber": 376
},
{
"text": " Write-Host \"Identifying FlatColors files...\" -ForegroundColor Yellow",
"lineNumber": 377
},
{
"text": " $flatColorsFiles = $allFlatColorsFiles | Where-Object { (Test-Path -Path $_.FullName) }",
"lineNumber": 378
},
{
"text": " $nonFlatColorsFiles = $remainingFiles | Where-Object { $_.Name -notlike \"*FlatColors*\" }",
"lineNumber": 379
},
{
"text": " ",
"lineNumber": 380
},
{
"text": " Write-Host \"Found $($flatColorsFiles.Count) FlatColors file(s) (including from \\common\\FlatColors folders), $($nonFlatColorsFiles.Count) other file(s)\" -ForegroundColor Gray",
"lineNumber": 381
},
{
"text": " ",
"lineNumber": 382
},
{
"text": " # Group non-FlatColors files by checksum",
"lineNumber": 383
},
{
"text": " Write-Host \"Grouping files by checksum...\" -ForegroundColor Yellow",
"lineNumber": 384
},
{
"text": " $nonFlatColorsWithChecksums = $filesWithChecksums | Where-Object { $_.File.Name -notlike \"*FlatColors*\" }",
"lineNumber": 385
},
{
"text": " $groupedByChecksum = $nonFlatColorsWithChecksums | Group-Object -Property Hash",
"lineNumber": 386
},
{
"text": " ",
"lineNumber": 387
},
{
"text": " Write-Host \"Found $($groupedByChecksum.Count) unique checksums.\" -ForegroundColor Green",
"lineNumber": 388
},
{
"text": " ",
"lineNumber": 389
},
{
"text": " # Create \\textures\\common directory",
"lineNumber": 390
}
]
},
"score": 0.3292612135410309
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 423
},
"endPosition": {
"line": 453,
"column": 16
}
},
"contents": " \n if ($null -ne $flatColorsFiles -and $flatColorsFiles.Count -gt 0) {\n Write-Host \"Found $($flatColorsFiles.Count) FlatColors file(s) to process\" -ForegroundColor Gray\n \n # Calculate checksums for FlatColors files\n Write-Host \"Calculating checksums for FlatColors files...\" -ForegroundColor Yellow\n $flatColorsWithChecksums = Get-FilesWithChecksums -Files $flatColorsFiles\n \n # Group by checksum to find duplicates\n $flatColorsGroupedByChecksum = $flatColorsWithChecksums | Group-Object -Property Hash\n \n Write-Host \"Found $($flatColorsGroupedByChecksum.Count) unique FlatColors file(s)\" -ForegroundColor Gray\n \n # Create \\textures\\common\\FlatColors directory\n $flatColorsPath = Join-Path -Path $rootCommonPath -ChildPath \"FlatColors\"\n if (-not (Test-Path -Path $flatColorsPath -PathType Container)) {\n New-Item -ItemType Directory -Path $flatColorsPath | Out-Null\n Write-Host \"Created directory: $flatColorsPath\" -ForegroundColor Green\n }\n \n # Track filenames already in \\common\\FlatColors\n $filesInFlatColors = @{}\n $flatColorsMoved = 0\n $flatColorsDuplicates = 0\n $flatColorsMoveLog = [System.Collections.ArrayList]::new()\n \n foreach ($group in $flatColorsGroupedByChecksum) {\n $files = $group.Group\n \n if ($files.Count -eq 1) {\n ",
"signatures": {},
"detailedLines": [
{
"text": " ",
"lineNumber": 424
},
{
"text": " if ($null -ne $flatColorsFiles -and $flatColorsFiles.Count -gt 0) {",
"lineNumber": 425
},
{
"text": " Write-Host \"Found $($flatColorsFiles.Count) FlatColors file(s) to process\" -ForegroundColor Gray",
"lineNumber": 426
},
{
"text": " ",
"lineNumber": 427
},
{
"text": " # Calculate checksums for FlatColors files",
"lineNumber": 428
},
{
"text": " Write-Host \"Calculating checksums for FlatColors files...\" -ForegroundColor Yellow",
"lineNumber": 429
},
{
"text": " $flatColorsWithChecksums = Get-FilesWithChecksums -Files $flatColorsFiles",
"lineNumber": 430
},
{
"text": " ",
"lineNumber": 431
},
{
"text": " # Group by checksum to find duplicates",
"lineNumber": 432
},
{
"text": " $flatColorsGroupedByChecksum = $flatColorsWithChecksums | Group-Object -Property Hash",
"lineNumber": 433
},
{
"text": " ",
"lineNumber": 434
},
{
"text": " Write-Host \"Found $($flatColorsGroupedByChecksum.Count) unique FlatColors file(s)\" -ForegroundColor Gray",
"lineNumber": 435
},
{
"text": " ",
"lineNumber": 436
},
{
"text": " # Create \\textures\\common\\FlatColors directory",
"lineNumber": 437
},
{
"text": " $flatColorsPath = Join-Path -Path $rootCommonPath -ChildPath \"FlatColors\"",
"lineNumber": 438
},
{
"text": " if (-not (Test-Path -Path $flatColorsPath -PathType Container)) {",
"lineNumber": 439
},
{
"text": " New-Item -ItemType Directory -Path $flatColorsPath | Out-Null",
"lineNumber": 440
},
{
"text": " Write-Host \"Created directory: $flatColorsPath\" -ForegroundColor Green",
"lineNumber": 441
},
{
"text": " }",
"lineNumber": 442
},
{
"text": " ",
"lineNumber": 443
},
{
"text": " # Track filenames already in \\common\\FlatColors",
"lineNumber": 444
},
{
"text": " $filesInFlatColors = @{}",
"lineNumber": 445
},
{
"text": " $flatColorsMoved = 0",
"lineNumber": 446
},
{
"text": " $flatColorsDuplicates = 0",
"lineNumber": 447
},
{
"text": " $flatColorsMoveLog = [System.Collections.ArrayList]::new()",
"lineNumber": 448
},
{
"text": " ",
"lineNumber": 449
},
{
"text": " foreach ($group in $flatColorsGroupedByChecksum) {",
"lineNumber": 450
},
{
"text": " $files = $group.Group",
"lineNumber": 451
},
{
"text": " ",
"lineNumber": 452
},
{
"text": " if ($files.Count -eq 1) {",
"lineNumber": 453
},
{
"text": " ",
"lineNumber": 454
}
]
},
"score": 0.3252905607223511
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 477
},
"endPosition": {
"line": 518
}
},
"contents": " \n try {\n $originalPath = $fileObj.FullName\n Move-Item -Path $originalPath -Destination $destinationPath -Force\n $filesInFlatColors[$fileName] = $true\n $flatColorsMoved++\n \n # Log the move\n $normalizedOriginal = [System.IO.Path]::GetFullPath($originalPath)\n $normalizedNew = [System.IO.Path]::GetFullPath($destinationPath)\n $null = $flatColorsMoveLog.Add([PSCustomObject]@{\n OriginalPath = $normalizedOriginal\n NewPath = $normalizedNew\n Type = \"moved\"\n })\n } catch {\n Write-Warning \"Failed to move FlatColors file: $($fileObj.FullName) - $($_.Exception.Message)\"\n }\n } else {\n # Multiple files with same checksum (duplicates) - merge them\n # Use Process-DuplicateGroup to handle merging\n $result = Process-DuplicateGroup -Files $files -CommonPath $flatColorsPath -FilesInCommon $filesInFlatColors -StripPrefix -ValidPrefixes $validBlendfilePrefixes -MoveLog $flatColorsMoveLog\n $flatColorsMoved += $result.MovedCount\n $flatColorsDuplicates += $result.DuplicateCount\n }\n }\n \n Write-Host \"Moved $flatColorsMoved unique FlatColors file(s) to \\common\\FlatColors, deleted $flatColorsDuplicates duplicate(s)\" -ForegroundColor Green\n } else {\n Write-Host \"No FlatColors files found to process.\" -ForegroundColor Gray\n }\n \n Write-Host \"\"\n Write-Host \"Pass 2 complete: $pass2Moved file(s) moved to \\common, $pass2Duplicates duplicate(s) deleted\" -ForegroundColor Green\n}\n\n# ============================================================================\n# Save Move Log and Find Blend Files\n# ============================================================================\nWrite-Host \"\"\nWrite-Host \"Saving move log and finding blend files...\" -ForegroundColor Yellow",
"signatures": {},
"detailedLines": [
{
"text": " ",
"lineNumber": 478
},
{
"text": " try {",
"lineNumber": 479
},
{
"text": " $originalPath = $fileObj.FullName",
"lineNumber": 480
},
{
"text": " Move-Item -Path $originalPath -Destination $destinationPath -Force",
"lineNumber": 481
},
{
"text": " $filesInFlatColors[$fileName] = $true",
"lineNumber": 482
},
{
"text": " $flatColorsMoved++",
"lineNumber": 483
},
{
"text": " ",
"lineNumber": 484
},
{
"text": " # Log the move",
"lineNumber": 485
},
{
"text": " $normalizedOriginal = [System.IO.Path]::GetFullPath($originalPath)",
"lineNumber": 486
},
{
"text": " $normalizedNew = [System.IO.Path]::GetFullPath($destinationPath)",
"lineNumber": 487
},
{
"text": " $null = $flatColorsMoveLog.Add([PSCustomObject]@{",
"lineNumber": 488
},
{
"text": " OriginalPath = $normalizedOriginal",
"lineNumber": 489
},
{
"text": " NewPath = $normalizedNew",
"lineNumber": 490
},
{
"text": " Type = \"moved\"",
"lineNumber": 491
},
{
"text": " })",
"lineNumber": 492
},
{
"text": " } catch {",
"lineNumber": 493
},
{
"text": " Write-Warning \"Failed to move FlatColors file: $($fileObj.FullName) - $($_.Exception.Message)\"",
"lineNumber": 494
},
{
"text": " }",
"lineNumber": 495
},
{
"text": " } else {",
"lineNumber": 496
},
{
"text": " # Multiple files with same checksum (duplicates) - merge them",
"lineNumber": 497
},
{
"text": " # Use Process-DuplicateGroup to handle merging",
"lineNumber": 498
},
{
"text": " $result = Process-DuplicateGroup -Files $files -CommonPath $flatColorsPath -FilesInCommon $filesInFlatColors -StripPrefix -ValidPrefixes $validBlendfilePrefixes -MoveLog $flatColorsMoveLog",
"lineNumber": 499
},
{
"text": " $flatColorsMoved += $result.MovedCount",
"lineNumber": 500
},
{
"text": " $flatColorsDuplicates += $result.DuplicateCount",
"lineNumber": 501
},
{
"text": " }",
"lineNumber": 502
},
{
"text": " }",
"lineNumber": 503
},
{
"text": " ",
"lineNumber": 504
},
{
"text": " Write-Host \"Moved $flatColorsMoved unique FlatColors file(s) to \\common\\FlatColors, deleted $flatColorsDuplicates duplicate(s)\" -ForegroundColor Green",
"lineNumber": 505
},
{
"text": " } else {",
"lineNumber": 506
},
{
"text": " Write-Host \"No FlatColors files found to process.\" -ForegroundColor Gray",
"lineNumber": 507
},
{
"text": " }",
"lineNumber": 508
},
{
"text": " ",
"lineNumber": 509
},
{
"text": " Write-Host \"\"",
"lineNumber": 510
},
{
"text": " Write-Host \"Pass 2 complete: $pass2Moved file(s) moved to \\common, $pass2Duplicates duplicate(s) deleted\" -ForegroundColor Green",
"lineNumber": 511
},
{
"text": "}",
"lineNumber": 512
},
{
"lineNumber": 513
},
{
"text": "# ============================================================================",
"lineNumber": 514
},
{
"text": "# Save Move Log and Find Blend Files",
"lineNumber": 515
},
{
"text": "# ============================================================================",
"lineNumber": 516
},
{
"text": "Write-Host \"\"",
"lineNumber": 517
},
{
"text": "Write-Host \"Saving move log and finding blend files...\" -ForegroundColor Yellow",
"lineNumber": 518
}
]
},
"score": 0.29058343172073364
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 448
},
"endPosition": {
"line": 481
}
},
"contents": " \n foreach ($group in $flatColorsGroupedByChecksum) {\n $files = $group.Group\n \n if ($files.Count -eq 1) {\n # Single file - move to FlatColors folder\n $fileObj = $files[0].File\n $fileName = $fileObj.Name\n \n # Strip blendfile prefix if present\n $strippedName = Get-FileNameWithoutPrefix -FileName $fileName -ValidPrefixes $validBlendfilePrefixes\n if ($strippedName -ne $fileName) {\n $fileName = $strippedName\n }\n \n $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $fileName\n \n # Handle name conflicts (shouldn't happen for unique files, but just in case)\n if ($filesInFlatColors.ContainsKey($fileName) -or (Test-Path -Path $destinationPath)) {\n $baseName = [System.IO.Path]::GetFileNameWithoutExtension($fileName)\n $extension = [System.IO.Path]::GetExtension($fileName)\n $counter = 1\n do {\n $newFileName = \"${baseName}_${counter}${extension}\"\n $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $newFileName\n $counter++\n } while ($filesInFlatColors.ContainsKey($newFileName) -or (Test-Path -Path $destinationPath))\n $fileName = $newFileName\n }\n \n try {\n $originalPath = $fileObj.FullName\n Move-Item -Path $originalPath -Destination $destinationPath -Force",
"signatures": {},
"detailedLines": [
{
"text": " ",
"lineNumber": 449
},
{
"text": " foreach ($group in $flatColorsGroupedByChecksum) {",
"lineNumber": 450
},
{
"text": " $files = $group.Group",
"lineNumber": 451
},
{
"text": " ",
"lineNumber": 452
},
{
"text": " if ($files.Count -eq 1) {",
"lineNumber": 453
},
{
"text": " # Single file - move to FlatColors folder",
"lineNumber": 454
},
{
"text": " $fileObj = $files[0].File",
"lineNumber": 455
},
{
"text": " $fileName = $fileObj.Name",
"lineNumber": 456
},
{
"text": " ",
"lineNumber": 457
},
{
"text": " # Strip blendfile prefix if present",
"lineNumber": 458
},
{
"text": " $strippedName = Get-FileNameWithoutPrefix -FileName $fileName -ValidPrefixes $validBlendfilePrefixes",
"lineNumber": 459
},
{
"text": " if ($strippedName -ne $fileName) {",
"lineNumber": 460
},
{
"text": " $fileName = $strippedName",
"lineNumber": 461
},
{
"text": " }",
"lineNumber": 462
},
{
"text": " ",
"lineNumber": 463
},
{
"text": " $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $fileName",
"lineNumber": 464
},
{
"text": " ",
"lineNumber": 465
},
{
"text": " # Handle name conflicts (shouldn't happen for unique files, but just in case)",
"lineNumber": 466
},
{
"text": " if ($filesInFlatColors.ContainsKey($fileName) -or (Test-Path -Path $destinationPath)) {",
"lineNumber": 467
},
{
"text": " $baseName = [System.IO.Path]::GetFileNameWithoutExtension($fileName)",
"lineNumber": 468
},
{
"text": " $extension = [System.IO.Path]::GetExtension($fileName)",
"lineNumber": 469
},
{
"text": " $counter = 1",
"lineNumber": 470
},
{
"text": " do {",
"lineNumber": 471
},
{
"text": " $newFileName = \"${baseName}_${counter}${extension}\"",
"lineNumber": 472
},
{
"text": " $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $newFileName",
"lineNumber": 473
},
{
"text": " $counter++",
"lineNumber": 474
},
{
"text": " } while ($filesInFlatColors.ContainsKey($newFileName) -or (Test-Path -Path $destinationPath))",
"lineNumber": 475
},
{
"text": " $fileName = $newFileName",
"lineNumber": 476
},
{
"text": " }",
"lineNumber": 477
},
{
"text": " ",
"lineNumber": 478
},
{
"text": " try {",
"lineNumber": 479
},
{
"text": " $originalPath = $fileObj.FullName",
"lineNumber": 480
},
{
"text": " Move-Item -Path $originalPath -Destination $destinationPath -Force",
"lineNumber": 481
}
]
},
"score": 0.2869645357131958
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 323
},
"endPosition": {
"line": 357
}
},
"contents": " foreach ($group in $groupedByChecksum) {\n $result = Process-DuplicateGroup -Files $group.Group -CommonPath $blendfileCommonPath -FilesInCommon $filesInBlendfileCommon -MoveLog $pass1MoveLog\n $blendfileMoved += $result.MovedCount\n $blendfileDuplicates += $result.DuplicateCount\n }\n \n Write-Host \" Moved $blendfileMoved file(s) to \\common, deleted $blendfileDuplicates duplicate(s)\" -ForegroundColor Green\n $totalPass1Moved += $blendfileMoved\n $totalPass1Duplicates += $blendfileDuplicates\n }\n \n Write-Host \"\"\n Write-Host \"Pass 1 complete: $totalPass1Moved file(s) moved, $totalPass1Duplicates duplicate(s) deleted\" -ForegroundColor Green\n}\n\n# ============================================================================\n# PASS 2: Inter-Blendfile Processing\n# ============================================================================\nWrite-Host \"\"\nWrite-Host \"=== PASS 2: Inter-Blendfile Processing ===\" -ForegroundColor Cyan\n\n# Build list of valid blendfile prefixes from folder names\n$validBlendfilePrefixes = @()\n$blendfileFoldersForPrefixes = Get-ChildItem -Path $textureFolderPath -Directory | Where-Object { $_.Name -ne \"common\" }\nif ($null -ne $blendfileFoldersForPrefixes) {\n $validBlendfilePrefixes = $blendfileFoldersForPrefixes | ForEach-Object { $_.Name }\n Write-Host \"Valid blendfile prefixes: $($validBlendfilePrefixes -join ', ')\" -ForegroundColor Gray\n}\n\n# Collect FlatColors files separately (including those in \\common\\FlatColors folders, but not from root \\common\\FlatColors)\nWrite-Host \"Collecting FlatColors files...\" -ForegroundColor Yellow\n$rootCommonFlatColorsPath = Join-Path -Path $textureFolderPath -ChildPath \"common\\FlatColors\"\n$allFlatColorsFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { \n ($_.FullName -like \"*\\FlatColors\\*\" -or $_.Name -like \"*FlatColors*\") -and ",
"signatures": {},
"detailedLines": [
{
"text": " foreach ($group in $groupedByChecksum) {",
"lineNumber": 324
},
{
"text": " $result = Process-DuplicateGroup -Files $group.Group -CommonPath $blendfileCommonPath -FilesInCommon $filesInBlendfileCommon -MoveLog $pass1MoveLog",
"lineNumber": 325
},
{
"text": " $blendfileMoved += $result.MovedCount",
"lineNumber": 326
},
{
"text": " $blendfileDuplicates += $result.DuplicateCount",
"lineNumber": 327
},
{
"text": " }",
"lineNumber": 328
},
{
"text": " ",
"lineNumber": 329
},
{
"text": " Write-Host \" Moved $blendfileMoved file(s) to \\common, deleted $blendfileDuplicates duplicate(s)\" -ForegroundColor Green",
"lineNumber": 330
},
{
"text": " $totalPass1Moved += $blendfileMoved",
"lineNumber": 331
},
{
"text": " $totalPass1Duplicates += $blendfileDuplicates",
"lineNumber": 332
},
{
"text": " }",
"lineNumber": 333
},
{
"text": " ",
"lineNumber": 334
},
{
"text": " Write-Host \"\"",
"lineNumber": 335
},
{
"text": " Write-Host \"Pass 1 complete: $totalPass1Moved file(s) moved, $totalPass1Duplicates duplicate(s) deleted\" -ForegroundColor Green",
"lineNumber": 336
},
{
"text": "}",
"lineNumber": 337
},
{
"lineNumber": 338
},
{
"text": "# ============================================================================",
"lineNumber": 339
},
{
"text": "# PASS 2: Inter-Blendfile Processing",
"lineNumber": 340
},
{
"text": "# ============================================================================",
"lineNumber": 341
},
{
"text": "Write-Host \"\"",
"lineNumber": 342
},
{
"text": "Write-Host \"=== PASS 2: Inter-Blendfile Processing ===\" -ForegroundColor Cyan",
"lineNumber": 343
},
{
"lineNumber": 344
},
{
"text": "# Build list of valid blendfile prefixes from folder names",
"lineNumber": 345
},
{
"text": "$validBlendfilePrefixes = @()",
"lineNumber": 346
},
{
"text": "$blendfileFoldersForPrefixes = Get-ChildItem -Path $textureFolderPath -Directory | Where-Object { $_.Name -ne \"common\" }",
"lineNumber": 347
},
{
"text": "if ($null -ne $blendfileFoldersForPrefixes) {",
"lineNumber": 348
},
{
"text": " $validBlendfilePrefixes = $blendfileFoldersForPrefixes | ForEach-Object { $_.Name }",
"lineNumber": 349
},
{
"text": " Write-Host \"Valid blendfile prefixes: $($validBlendfilePrefixes -join ', ')\" -ForegroundColor Gray",
"lineNumber": 350
},
{
"text": "}",
"lineNumber": 351
},
{
"lineNumber": 352
},
{
"text": "# Collect FlatColors files separately (including those in \\common\\FlatColors folders, but not from root \\common\\FlatColors)",
"lineNumber": 353
},
{
"text": "Write-Host \"Collecting FlatColors files...\" -ForegroundColor Yellow",
"lineNumber": 354
},
{
"text": "$rootCommonFlatColorsPath = Join-Path -Path $textureFolderPath -ChildPath \"common\\FlatColors\"",
"lineNumber": 355
},
{
"text": "$allFlatColorsFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { ",
"lineNumber": 356
},
{
"text": " ($_.FullName -like \"*\\FlatColors\\*\" -or $_.Name -like \"*FlatColors*\") -and ",
"lineNumber": 357
}
]
},
"score": 0.2548561990261078
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 386
},
"endPosition": {
"line": 426
}
},
"contents": " \n Write-Host \"Found $($groupedByChecksum.Count) unique checksums.\" -ForegroundColor Green\n \n # Create \\textures\\common directory\n $rootCommonPath = Join-Path -Path $textureFolderPath -ChildPath \"common\"\n \n if (-not (Test-Path -Path $rootCommonPath -PathType Container)) {\n New-Item -ItemType Directory -Path $rootCommonPath | Out-Null\n Write-Host \"Created directory: $rootCommonPath\" -ForegroundColor Green\n }\n \n # Track filenames already in \\textures\\common\n $filesInRootCommon = @{}\n \n # Process each checksum group (excluding FlatColors)\n Write-Host \"Moving files to \\common and deleting duplicates...\" -ForegroundColor Yellow\n $pass2Moved = 0\n $pass2Duplicates = 0\n $pass2MoveLog = [System.Collections.ArrayList]::new()\n \n foreach ($group in $groupedByChecksum) {\n $files = $group.Group\n \n if ($files.Count -eq 1) {\n # Single file - leave in place (unique file)\n continue\n }\n \n # Multiple files with same checksum (duplicates across blendfiles)\n # Use StripPrefix to remove blendfile prefixes (e.g., \"Demarco_\", \"Chan_\") when all files share the same suffix\n $result = Process-DuplicateGroup -Files $files -CommonPath $rootCommonPath -FilesInCommon $filesInRootCommon -StripPrefix -ValidPrefixes $validBlendfilePrefixes -MoveLog $pass2MoveLog\n $pass2Moved += $result.MovedCount\n $pass2Duplicates += $result.DuplicateCount\n }\n \n # Process FlatColors files: merge duplicates and move to \\common\\FlatColors\n Write-Host \"Processing FlatColors files (merging duplicates)...\" -ForegroundColor Yellow\n \n if ($null -ne $flatColorsFiles -and $flatColorsFiles.Count -gt 0) {\n Write-Host \"Found $($flatColorsFiles.Count) FlatColors file(s) to process\" -ForegroundColor Gray",
"signatures": {},
"detailedLines": [
{
"text": " ",
"lineNumber": 387
},
{
"text": " Write-Host \"Found $($groupedByChecksum.Count) unique checksums.\" -ForegroundColor Green",
"lineNumber": 388
},
{
"text": " ",
"lineNumber": 389
},
{
"text": " # Create \\textures\\common directory",
"lineNumber": 390
},
{
"text": " $rootCommonPath = Join-Path -Path $textureFolderPath -ChildPath \"common\"",
"lineNumber": 391
},
{
"text": " ",
"lineNumber": 392
},
{
"text": " if (-not (Test-Path -Path $rootCommonPath -PathType Container)) {",
"lineNumber": 393
},
{
"text": " New-Item -ItemType Directory -Path $rootCommonPath | Out-Null",
"lineNumber": 394
},
{
"text": " Write-Host \"Created directory: $rootCommonPath\" -ForegroundColor Green",
"lineNumber": 395
},
{
"text": " }",
"lineNumber": 396
},
{
"text": " ",
"lineNumber": 397
},
{
"text": " # Track filenames already in \\textures\\common",
"lineNumber": 398
},
{
"text": " $filesInRootCommon = @{}",
"lineNumber": 399
},
{
"text": " ",
"lineNumber": 400
},
{
"text": " # Process each checksum group (excluding FlatColors)",
"lineNumber": 401
},
{
"text": " Write-Host \"Moving files to \\common and deleting duplicates...\" -ForegroundColor Yellow",
"lineNumber": 402
},
{
"text": " $pass2Moved = 0",
"lineNumber": 403
},
{
"text": " $pass2Duplicates = 0",
"lineNumber": 404
},
{
"text": " $pass2MoveLog = [System.Collections.ArrayList]::new()",
"lineNumber": 405
},
{
"text": " ",
"lineNumber": 406
},
{
"text": " foreach ($group in $groupedByChecksum) {",
"lineNumber": 407
},
{
"text": " $files = $group.Group",
"lineNumber": 408
},
{
"text": " ",
"lineNumber": 409
},
{
"text": " if ($files.Count -eq 1) {",
"lineNumber": 410
},
{
"text": " # Single file - leave in place (unique file)",
"lineNumber": 411
},
{
"text": " continue",
"lineNumber": 412
},
{
"text": " }",
"lineNumber": 413
},
{
"text": " ",
"lineNumber": 414
},
{
"text": " # Multiple files with same checksum (duplicates across blendfiles)",
"lineNumber": 415
},
{
"text": " # Use StripPrefix to remove blendfile prefixes (e.g., \"Demarco_\", \"Chan_\") when all files share the same suffix",
"lineNumber": 416
},
{
"text": " $result = Process-DuplicateGroup -Files $files -CommonPath $rootCommonPath -FilesInCommon $filesInRootCommon -StripPrefix -ValidPrefixes $validBlendfilePrefixes -MoveLog $pass2MoveLog",
"lineNumber": 417
},
{
"text": " $pass2Moved += $result.MovedCount",
"lineNumber": 418
},
{
"text": " $pass2Duplicates += $result.DuplicateCount",
"lineNumber": 419
},
{
"text": " }",
"lineNumber": 420
},
{
"text": " ",
"lineNumber": 421
},
{
"text": " # Process FlatColors files: merge duplicates and move to \\common\\FlatColors",
"lineNumber": 422
},
{
"text": " Write-Host \"Processing FlatColors files (merging duplicates)...\" -ForegroundColor Yellow",
"lineNumber": 423
},
{
"text": " ",
"lineNumber": 424
},
{
"text": " if ($null -ne $flatColorsFiles -and $flatColorsFiles.Count -gt 0) {",
"lineNumber": 425
},
{
"text": " Write-Host \"Found $($flatColorsFiles.Count) FlatColors file(s) to process\" -ForegroundColor Gray",
"lineNumber": 426
}
]
},
"score": 0.2526206374168396
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\zip_sequences.py",
"range": {
"startPosition": {},
"endPosition": {
"line": 102
}
},
"contents": "#!/usr/bin/env python3\n\"\"\"Maintain zipped render sequences for Git hooks.\n\nDefault mode scans `Renders/`, produces ZIP archives under `Renders/_zipped/`,\nand stages any updated archives so commits only track compact files. Switch to\n`--mode expand` to inflate the tracked archives back into the ignored working\ndirectories after checkouts or pulls.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport os\nimport platform\nimport shutil\nimport subprocess\nimport sys\nimport tempfile\nimport time\nimport traceback\nfrom concurrent.futures import ThreadPoolExecutor, as_completed\nfrom pathlib import Path\nfrom typing import Iterator, Sequence\n\n# Try to import psutil for cross-platform RAM detection\ntry:\n import psutil\n HAS_PSUTIL = True\nexcept ImportError:\n HAS_PSUTIL = False\n # For Windows fallback\n if platform.system() == \"Windows\":\n try:\n import ctypes\n HAS_CTYPES = True\n except ImportError:\n HAS_CTYPES = False\n else:\n HAS_CTYPES = False\n\n\nRENDER_ROOT = Path(\"Renders\")\nARCHIVE_ROOT = RENDER_ROOT / \"_zipped\"\nSEQUENCE_EXTENSIONS = {\n \".png\",\n \".jpg\",\n \".jpeg\",\n \".tif\",\n \".tiff\",\n \".exr\",\n}\nSTATE_SUFFIX = \".meta.json\"\nDEFAULT_CONFIG = {\n \"zipper\": \"7z\",\n \"compression\": 9,\n \"compressionMethod\": \"LZMA2\", # Compression method: LZMA2 (multi-threaded), PPMd (single-threaded), BZip2, Deflate\n \"dailyFormat\": \"daily_YYMMDD\",\n \"Max7zInst\": 0, # Maximum concurrent 7z instances (0 = auto-calculate)\n}\n\n\ndef log(mode: str, message: str, *, verbose_only: bool = False, verbose: bool = False) -> None:\n if verbose_only and not verbose:\n return\n print(f\"[{mode}] {message}\", flush=True)\n\n\ndef load_config() -> dict:\n # First try to load from project's .config folder (current working directory)\n # Then fall back to ProjectStructure repo config (next to zip_sequences.py)\n ",
"signatures": {},
"detailedLines": [
{
"text": "#!/usr/bin/env python3",
"lineNumber": 1
},
{
"text": "\"\"\"Maintain zipped render sequences for Git hooks.",
"lineNumber": 2
},
{
"lineNumber": 3
},
{
"text": "Default mode scans `Renders/`, produces ZIP archives under `Renders/_zipped/`,",
"lineNumber": 4
},
{
"text": "and stages any updated archives so commits only track compact files. Switch to",
"lineNumber": 5
},
{
"text": "`--mode expand` to inflate the tracked archives back into the ignored working",
"lineNumber": 6
},
{
"text": "directories after checkouts or pulls.",
"lineNumber": 7
},
{
"text": "\"\"\"",
"lineNumber": 8
},
{
"lineNumber": 9
},
{
"text": "from __future__ import annotations",
"lineNumber": 10
},
{
"lineNumber": 11
},
{
"text": "import argparse",
"lineNumber": 12
},
{
"text": "import json",
"lineNumber": 13
},
{
"text": "import os",
"lineNumber": 14
},
{
"text": "import platform",
"lineNumber": 15
},
{
"text": "import shutil",
"lineNumber": 16
},
{
"text": "import subprocess",
"lineNumber": 17
},
{
"text": "import sys",
"lineNumber": 18
},
{
"text": "import tempfile",
"lineNumber": 19
},
{
"text": "import time",
"lineNumber": 20
},
{
"text": "import traceback",
"lineNumber": 21
},
{
"text": "from concurrent.futures import ThreadPoolExecutor, as_completed",
"lineNumber": 22
},
{
"text": "from pathlib import Path",
"lineNumber": 23
},
{
"text": "from typing import Iterator, Sequence",
"lineNumber": 24
},
{
"lineNumber": 25
},
{
"text": "# Try to import psutil for cross-platform RAM detection",
"lineNumber": 26
},
{
"text": "try:",
"lineNumber": 27
},
{
"text": " import psutil",
"lineNumber": 28
},
{
"text": " HAS_PSUTIL = True",
"lineNumber": 29
},
{
"text": "except ImportError:",
"lineNumber": 30
},
{
"text": " HAS_PSUTIL = False",
"lineNumber": 31
},
{
"text": " # For Windows fallback",
"lineNumber": 32
},
{
"text": " if platform.system() == \"Windows\":",
"lineNumber": 33
},
{
"text": " try:",
"lineNumber": 34
},
{
"text": " import ctypes",
"lineNumber": 35
},
{
"text": " HAS_CTYPES = True",
"lineNumber": 36
},
{
"text": " except ImportError:",
"lineNumber": 37
},
{
"text": " HAS_CTYPES = False",
"lineNumber": 38
},
{
"text": " else:",
"lineNumber": 39
},
{
"text": " HAS_CTYPES = False",
"lineNumber": 40
},
{
"lineNumber": 41
},
{
"lineNumber": 42
},
{
"text": "RENDER_ROOT = Path(\"Renders\")",
"lineNumber": 43
},
{
"text": "ARCHIVE_ROOT = RENDER_ROOT / \"_zipped\"",
"lineNumber": 44
},
{
"text": "SEQUENCE_EXTENSIONS = {",
"lineNumber": 45
},
{
"text": " \".png\",",
"lineNumber": 46
},
{
"text": " \".jpg\",",
"lineNumber": 47
},
{
"text": " \".jpeg\",",
"lineNumber": 48
},
{
"text": " \".tif\",",
"lineNumber": 49
},
{
"text": " \".tiff\",",
"lineNumber": 50
},
{
"text": " \".exr\",",
"lineNumber": 51
},
{
"text": "}",
"lineNumber": 52
},
{
"text": "STATE_SUFFIX = \".meta.json\"",
"lineNumber": 53
},
{
"text": "DEFAULT_CONFIG = {",
"lineNumber": 54
},
{
"text": " \"zipper\": \"7z\",",
"lineNumber": 55
},
{
"text": " \"compression\": 9,",
"lineNumber": 56
},
{
"text": " \"compressionMethod\": \"LZMA2\", # Compression method: LZMA2 (multi-threaded), PPMd (single-threaded), BZip2, Deflate",
"lineNumber": 57
},
{
"text": " \"dailyFormat\": \"daily_YYMMDD\",",
"lineNumber": 58
},
{
"text": " \"Max7zInst\": 0, # Maximum concurrent 7z instances (0 = auto-calculate)",
"lineNumber": 59
},
{
"text": "}",
"lineNumber": 60
},
{
"lineNumber": 61
},
{
"lineNumber": 62
},
{
"text": "def log(mode: str, message: str, *, verbose_only: bool = False, verbose: bool = False) -> None:",
"lineNumber": 63,
"isSignature": true
},
{
"text": " if verbose_only and not verbose:",
"lineNumber": 64
},
{
"text": " return",
"lineNumber": 65
},
{
"text": " print(f\"[{mode}] {message}\", flush=True)",
"lineNumber": 66,
"isSignature": true
},
{
"lineNumber": 67
},
{
"lineNumber": 68
},
{
"text": "def load_config() -> dict:",
"lineNumber": 69,
"isSignature": true
},
{
"text": " # First try to load from project's .config folder (current working directory)",
"lineNumber": 70,
"isSignature": true
},
{
"text": " # Then fall back to ProjectStructure repo config (next to zip_sequences.py)",
"lineNumber": 71,
"isSignature": true
},
{
"text": " ",
"lineNumber": 72
}
]
},
"score": 0.16568893194198608
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\replace_cel_with_bsdf.py",
"range": {
"startPosition": {
"line": 186,
"column": 26
},
"endPosition": {
"line": 355
}
},
"contents": "def replace_cel_materials():\n \"\"\"Replace all CEL materials with their BSDF counterparts using Blender's user remapping\"\"\"\n \n # First, link BSDF materials from library\n linked_materials = link_bsdf_materials()\n \n # Then, remap any missing datablocks\n missing_remaps = remap_missing_datablocks()\n \n # Then, remap any appended BSDF materials to linked versions\n appended_remaps = remap_appended_to_linked()\n \n print(f\"\\n=== STARTING MATERIAL REPLACEMENT ===\")\n \n # Custom material mappings (source -> target)\n custom_mappings = {\n \"bag BLACK (squid ink)\": \"BSDF_black_SQUID-INK\",\n \"bag WHITE\": \"BSDF_WHITE\",\n \"Wheel-White\": \"BSDF_WHITE\",\n \"Bag Colors\": \"BSDF_Bag Colors\",\n \"cardboard\": \"Package_Cardboard\",\n \"blue (triton)\": \"BSDF_blue-2_TRITON\",\n \"gray (snow)\": \"BSDF_gray-6_SNOW\",\n \"gray (storm)\": \"BSDF_gray-2_STORM\",\n \"gray (summit)\": \"BSDF_gray-5_SUMMIT\",\n \"light blue (prime)\": \"BSDF_blue-4_PRIME\",\n \"yellow (summer)\": \"BSDF_orange-5_SUMMER\",\n \"Accessory_CEL_gray-6_SNOW\": \"BSDF_gray-6_SNOW\",\n \"Accessory_CEL_SquidInk\": \"BSDF_black_SQUID-INK\",\n \"FingerScanner\": \"BSDF_black_SQUID-INK\",\n \"cel BLACK (squid ink)\": \"BSDF_black_SQUID-INK\",\n \"cel WHITE\": \"BSDF_WHITE\",\n \"gray (stone)\": \"BSDF_gray-3_STONE\",\n \"green (oxygen)\": \"BSDF_green-3_OXYGEN\",\n \"orange (smile)\": \"BSDF_orange-3_SMILE\",\n \"orange (blaze)\": \"BSDF_orange-1_BLAZE\"\n }\n \n # Get all materials in the scene\n materials = bpy.data.materials\n \n # Dictionary to store source -> target material mapping\n material_mapping = {}\n \n # Replace all CEL materials with their BSDF counterparts, ignoring numeric suffixes\n cel_pattern = re.compile(r\"^(CEL_.+?)(\\.\\d{3})?$\")\n bsdf_pattern = re.compile(r\"^(BSDF_.+?)(\\.\\d{3})?$\")\n \n # Build a mapping from base BSDF name to BSDF material (without suffix)",
"signatures": {},
"detailedLines": [
{
"text": "def replace_cel_materials():",
"lineNumber": 189,
"isSignature": true
},
{
"text": " \"\"\"Replace all CEL materials with their BSDF counterparts using Blender's user remapping\"\"\"",
"lineNumber": 190
},
{
"text": " ",
"lineNumber": 191
},
{
"text": " # First, link BSDF materials from library",
"lineNumber": 192
},
{
"text": " linked_materials = link_bsdf_materials()",
"lineNumber": 193
},
{
"text": " ",
"lineNumber": 194
},
{
"text": " # Then, remap any missing datablocks",
"lineNumber": 195
},
{
"text": " missing_remaps = remap_missing_datablocks()",
"lineNumber": 196
},
{
"text": " ",
"lineNumber": 197
},
{
"text": " # Then, remap any appended BSDF materials to linked versions",
"lineNumber": 198
},
{
"text": " appended_remaps = remap_appended_to_linked()",
"lineNumber": 199
},
{
"text": " ",
"lineNumber": 200
},
{
"text": " print(f\"\\n=== STARTING MATERIAL REPLACEMENT ===\")",
"lineNumber": 201
},
{
"text": " ",
"lineNumber": 202
},
{
"text": " # Custom material mappings (source -> target)",
"lineNumber": 203
},
{
"text": " custom_mappings = {",
"lineNumber": 204
},
{
"text": " \"bag BLACK (squid ink)\": \"BSDF_black_SQUID-INK\",",
"lineNumber": 205
},
{
"text": " \"bag WHITE\": \"BSDF_WHITE\",",
"lineNumber": 206
},
{
"text": " \"Wheel-White\": \"BSDF_WHITE\",",
"lineNumber": 207
},
{
"text": " \"Bag Colors\": \"BSDF_Bag Colors\",",
"lineNumber": 208
},
{
"text": " \"cardboard\": \"Package_Cardboard\",",
"lineNumber": 209
},
{
"text": " \"blue (triton)\": \"BSDF_blue-2_TRITON\",",
"lineNumber": 210
},
{
"text": " \"gray (snow)\": \"BSDF_gray-6_SNOW\",",
"lineNumber": 211
},
{
"text": " \"gray (storm)\": \"BSDF_gray-2_STORM\",",
"lineNumber": 212
},
{
"text": " \"gray (summit)\": \"BSDF_gray-5_SUMMIT\",",
"lineNumber": 213
},
{
"text": " \"light blue (prime)\": \"BSDF_blue-4_PRIME\",",
"lineNumber": 214
},
{
"text": " \"yellow (summer)\": \"BSDF_orange-5_SUMMER\",",
"lineNumber": 215
},
{
"text": " \"Accessory_CEL_gray-6_SNOW\": \"BSDF_gray-6_SNOW\",",
"lineNumber": 216
},
{
"text": " \"Accessory_CEL_SquidInk\": \"BSDF_black_SQUID-INK\",",
"lineNumber": 217
},
{
"text": " \"FingerScanner\": \"BSDF_black_SQUID-INK\",",
"lineNumber": 218
},
{
"text": " \"cel BLACK (squid ink)\": \"BSDF_black_SQUID-INK\",",
"lineNumber": 219
},
{
"text": " \"cel WHITE\": \"BSDF_WHITE\",",
"lineNumber": 220
},
{
"text": " \"gray (stone)\": \"BSDF_gray-3_STONE\",",
"lineNumber": 221
},
{
"text": " \"green (oxygen)\": \"BSDF_green-3_OXYGEN\",",
"lineNumber": 222
},
{
"text": " \"orange (smile)\": \"BSDF_orange-3_SMILE\",",
"lineNumber": 223
},
{
"text": " \"orange (blaze)\": \"BSDF_orange-1_BLAZE\"",
"lineNumber": 224
},
{
"text": " }",
"lineNumber": 225
},
{
"text": " ",
"lineNumber": 226
},
{
"text": " # Get all materials in the scene",
"lineNumber": 227
},
{
"text": " materials = bpy.data.materials",
"lineNumber": 228
},
{
"text": " ",
"lineNumber": 229
},
{
"text": " # Dictionary to store source -> target material mapping",
"lineNumber": 230
},
{
"text": " material_mapping = {}",
"lineNumber": 231
},
{
"text": " ",
"lineNumber": 232
},
{
"text": " # Replace all CEL materials with their BSDF counterparts, ignoring numeric suffixes",
"lineNumber": 233
},
{
"text": " cel_pattern = re.compile(r\"^(CEL_.+?)(\\.\\d{3})?$\")",
"lineNumber": 234
},
{
"text": " bsdf_pattern = re.compile(r\"^(BSDF_.+?)(\\.\\d{3})?$\")",
"lineNumber": 235
},
{
"text": " ",
"lineNumber": 236
},
{
"text": " # Build a mapping from base BSDF name to BSDF material (without suffix)",
"lineNumber": 237
}
]
},
"score": 0.15942895412445068
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\remap_texture_paths.py",
"range": {
"startPosition": {
"line": 18,
"column": 29
},
"endPosition": {
"line": 71
}
},
"contents": "def load_move_log(json_path):\n \"\"\"Load the move log JSON file and build lookup dictionaries\"\"\"\n try:\n with open(json_path, 'r', encoding='utf-8') as f:\n data = json.load(f)\n \n # Debug: Check what keys are in the data\n print(f\" JSON keys: {list(data.keys())}\")\n \n # PowerShell ConvertTo-Json uses PascalCase by default, so check both cases\n moves = data.get('moves', []) or data.get('Moves', [])\n \n print(f\" Found {len(moves)} move entries in JSON\")\n \n if len(moves) > 0:\n # Debug: Show first move entry structure\n print(f\" First move entry keys: {list(moves[0].keys())}\")\n print(f\" First move entry: {moves[0]}\")\n \n # Build lookup dictionaries: normalized original path -> actual new path\n original_to_new = {}\n original_to_replacement = {}\n \n for move in moves:\n # Try both camelCase and PascalCase property names\n move_type = move.get('type', '') or move.get('Type', '')\n original = move.get('originalPath', '') or move.get('OriginalPath', '')\n \n if not original:\n continue\n \n orig_norm = normalize_path(original)\n \n if move_type == 'moved' or move_type == 'Moved':\n new_path = move.get('newPath', '') or move.get('NewPath', '')\n if new_path:\n original_to_new[orig_norm] = new_path\n \n elif move_type == 'deleted' or move_type == 'Deleted':\n replacement = move.get('replacedBy', '') or move.get('ReplacedBy', '')\n if replacement:\n original_to_replacement[orig_norm] = replacement\n \n print(f\" Built {len(original_to_new)} move mappings and {len(original_to_replacement)} replacement mappings\")\n \n return original_to_new, original_to_replacement,",
"signatures": {},
"detailedLines": [
{
"text": "def load_move_log(json_path):",
"lineNumber": 21,
"isSignature": true
},
{
"text": " \"\"\"Load the move log JSON file and build lookup dictionaries\"\"\"",
"lineNumber": 22
},
{
"text": " try:",
"lineNumber": 23
},
{
"text": " with open(json_path, 'r', encoding='utf-8') as f:",
"lineNumber": 24
},
{
"text": " data = json.load(f)",
"lineNumber": 25
},
{
"text": " ",
"lineNumber": 26
},
{
"text": " # Debug: Check what keys are in the data",
"lineNumber": 27
},
{
"text": " print(f\" JSON keys: {list(data.keys())}\")",
"lineNumber": 28
},
{
"text": " ",
"lineNumber": 29
},
{
"text": " # PowerShell ConvertTo-Json uses PascalCase by default, so check both cases",
"lineNumber": 30
},
{
"text": " moves = data.get('moves', []) or data.get('Moves', [])",
"lineNumber": 31
},
{
"text": " ",
"lineNumber": 32
},
{
"text": " print(f\" Found {len(moves)} move entries in JSON\")",
"lineNumber": 33
},
{
"text": " ",
"lineNumber": 34
},
{
"text": " if len(moves) > 0:",
"lineNumber": 35
},
{
"text": " # Debug: Show first move entry structure",
"lineNumber": 36
},
{
"text": " print(f\" First move entry keys: {list(moves[0].keys())}\")",
"lineNumber": 37
},
{
"text": " print(f\" First move entry: {moves[0]}\")",
"lineNumber": 38
},
{
"text": " ",
"lineNumber": 39
},
{
"text": " # Build lookup dictionaries: normalized original path -> actual new path",
"lineNumber": 40
},
{
"text": " original_to_new = {}",
"lineNumber": 41
},
{
"text": " original_to_replacement = {}",
"lineNumber": 42
},
{
"text": " ",
"lineNumber": 43
},
{
"text": " for move in moves:",
"lineNumber": 44
},
{
"text": " # Try both camelCase and PascalCase property names",
"lineNumber": 45
},
{
"text": " move_type = move.get('type', '') or move.get('Type', '')",
"lineNumber": 46
},
{
"text": " original = move.get('originalPath', '') or move.get('OriginalPath', '')",
"lineNumber": 47
},
{
"text": " ",
"lineNumber": 48
},
{
"text": " if not original:",
"lineNumber": 49
},
{
"text": " continue",
"lineNumber": 50
},
{
"text": " ",
"lineNumber": 51
},
{
"text": " orig_norm = normalize_path(original)",
"lineNumber": 52
},
{
"text": " ",
"lineNumber": 53
},
{
"text": " if move_type == 'moved' or move_type == 'Moved':",
"lineNumber": 54
},
{
"text": " new_path = move.get('newPath', '') or move.get('NewPath', '')",
"lineNumber": 55
},
{
"text": " if new_path:",
"lineNumber": 56
},
{
"text": " original_to_new[orig_norm] = new_path",
"lineNumber": 57
},
{
"text": " ",
"lineNumber": 58
},
{
"text": " elif move_type == 'deleted' or move_type == 'Deleted':",
"lineNumber": 59
},
{
"text": " replacement = move.get('replacedBy', '') or move.get('ReplacedBy', '')",
"lineNumber": 60
},
{
"text": " if replacement:",
"lineNumber": 61
},
{
"text": " original_to_replacement[orig_norm] = replacement",
"lineNumber": 62
},
{
"text": " ",
"lineNumber": 63
},
{
"text": " print(f\" Built {len(original_to_new)} move mappings and {len(original_to_replacement)} replacement mappings\")",
"lineNumber": 64
},
{
"text": " ",
"lineNumber": 65
},
{
"text": " return original_to_new, original_to_replacement,",
"lineNumber": 66
}
]
},
"score": 0.14390915632247925
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\zip_sequences.py",
"range": {
"startPosition": {
"line": 65,
"column": 44
},
"endPosition": {
"line": 106,
"column": 39
}
},
"contents": "def load_config() -> dict:\n # First try to load from project's .config folder (current working directory)\n # Then fall back to ProjectStructure repo config (next to zip_sequences.py)\n cwd = Path.cwd()\n project_config = cwd / \".config\" / \"config.json\"\n repo_config = Path(__file__).resolve().with_name(\"config.json\")\n \n config_paths = [\n (\"project\", project_config),\n (\"repo\", repo_config),\n ]\n \n log(\"init\", \"Loading configuration sources...\")\n for source, config_path in config_paths:\n try:\n if config_path.exists():\n log(\"init\", f\"Reading {source} config at {config_path}\")\n text = config_path.read_text(encoding=\"utf-8\")\n try:\n data = json.loads(text)\n if isinstance(data, dict):\n merged = DEFAULT_CONFIG.copy()\n merged.update(data)\n log(\"init\", f\"Configuration loaded from {source}\")\n return merged\n except json.JSONDecodeError:\n log(\"init\", f\"Config file at {config_path} is invalid JSON; skipping\")\n continue\n except OSError:\n log(\"init\", f\"Unable to read config at {config_path}; skipping\")\n continue\n \n # If no config found, return defaults\n log(\"init\", \"No config files found; using default settings\")\n return DEFAULT_CONFIG.copy()\n\n\nCONFIG = load_config()\nzipper_val = CONFIG.get(\"zipper\", \"7z\")",
"signatures": {},
"detailedLines": [
{
"text": "def load_config() -> dict:",
"lineNumber": 69,
"isSignature": true
},
{
"text": " # First try to load from project's .config folder (current working directory)",
"lineNumber": 70,
"isSignature": true
},
{
"text": " # Then fall back to ProjectStructure repo config (next to zip_sequences.py)",
"lineNumber": 71,
"isSignature": true
},
{
"text": " cwd = Path.cwd()",
"lineNumber": 72
},
{
"text": " project_config = cwd / \".config\" / \"config.json\"",
"lineNumber": 73
},
{
"text": " repo_config = Path(__file__).resolve().with_name(\"config.json\")",
"lineNumber": 74
},
{
"text": " ",
"lineNumber": 75
},
{
"text": " config_paths = [",
"lineNumber": 76
},
{
"text": " (\"project\", project_config),",
"lineNumber": 77
},
{
"text": " (\"repo\", repo_config),",
"lineNumber": 78
},
{
"text": " ]",
"lineNumber": 79
},
{
"text": " ",
"lineNumber": 80
},
{
"text": " log(\"init\", \"Loading configuration sources...\")",
"lineNumber": 81
},
{
"text": " for source, config_path in config_paths:",
"lineNumber": 82
},
{
"text": " try:",
"lineNumber": 83
},
{
"text": " if config_path.exists():",
"lineNumber": 84
},
{
"text": " log(\"init\", f\"Reading {source} config at {config_path}\")",
"lineNumber": 85
},
{
"text": " text = config_path.read_text(encoding=\"utf-8\")",
"lineNumber": 86
},
{
"text": " try:",
"lineNumber": 87
},
{
"text": " data = json.loads(text)",
"lineNumber": 88
},
{
"text": " if isinstance(data, dict):",
"lineNumber": 89
},
{
"text": " merged = DEFAULT_CONFIG.copy()",
"lineNumber": 90
},
{
"text": " merged.update(data)",
"lineNumber": 91
},
{
"text": " log(\"init\", f\"Configuration loaded from {source}\")",
"lineNumber": 92
},
{
"text": " return merged",
"lineNumber": 93
},
{
"text": " except json.JSONDecodeError:",
"lineNumber": 94
},
{
"text": " log(\"init\", f\"Config file at {config_path} is invalid JSON; skipping\")",
"lineNumber": 95
},
{
"text": " continue",
"lineNumber": 96
},
{
"text": " except OSError:",
"lineNumber": 97
},
{
"text": " log(\"init\", f\"Unable to read config at {config_path}; skipping\")",
"lineNumber": 98
},
{
"text": " continue",
"lineNumber": 99
},
{
"text": " ",
"lineNumber": 100
},
{
"text": " # If no config found, return defaults",
"lineNumber": 101
},
{
"text": " log(\"init\", \"No config files found; using default settings\")",
"lineNumber": 102
},
{
"text": " return DEFAULT_CONFIG.copy()",
"lineNumber": 103,
"isSignature": true
},
{
"lineNumber": 104
},
{
"lineNumber": 105
},
{
"text": "CONFIG = load_config()",
"lineNumber": 106
},
{
"text": "zipper_val = CONFIG.get(\"zipper\", \"7z\")",
"lineNumber": 107
}
]
},
"score": 0.14383095502853394
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 514
},
"endPosition": {
"line": 546,
"column": 12
}
},
"contents": "# Save Move Log and Find Blend Files\n# ============================================================================\nWrite-Host \"\"\nWrite-Host \"Saving move log and finding blend files...\" -ForegroundColor Yellow\n\n# Combine all move logs\n$allMoves = @()\nif ($null -ne $pass1MoveLog -and $pass1MoveLog.Count -gt 0) {\n $allMoves += $pass1MoveLog\n}\nif ($null -ne $pass2MoveLog -and $pass2MoveLog.Count -gt 0) {\n $allMoves += $pass2MoveLog\n}\nif ($null -ne $flatColorsMoveLog -and $flatColorsMoveLog.Count -gt 0) {\n $allMoves += $flatColorsMoveLog\n}\n\n# Get parent directory of texture folder\n$blendFileParentDir = Split-Path -Path $textureFolderPath -Parent\n\n# Find matching blend files\n# Match logic: blendfile folder name (e.g., \"Beth\") should appear in blend file name (e.g., \"AM_Beth_v3.2.blend\")\n$blendFileMappings = @()\nif ($null -ne $blendfileFolders -and $blendfileFolders.Count -gt 0) {\n # Get blendfile folder names\n $blendfileFolderNames = $blendfileFolders | ForEach-Object { $_.Name }\n \n # Find all .blend files in parent directory\n $blendFiles = Get-ChildItem -Path $blendFileParentDir -Filter \"*.blend\" -File -ErrorAction SilentlyContinue\n \n if ($null -ne $blendFiles -and $blendFiles.Count -gt 0) {\n foreach ($blendFile in $blendFiles) {\n ",
"signatures": {},
"detailedLines": [
{
"text": "# Save Move Log and Find Blend Files",
"lineNumber": 515
},
{
"text": "# ============================================================================",
"lineNumber": 516
},
{
"text": "Write-Host \"\"",
"lineNumber": 517
},
{
"text": "Write-Host \"Saving move log and finding blend files...\" -ForegroundColor Yellow",
"lineNumber": 518
},
{
"lineNumber": 519
},
{
"text": "# Combine all move logs",
"lineNumber": 520
},
{
"text": "$allMoves = @()",
"lineNumber": 521
},
{
"text": "if ($null -ne $pass1MoveLog -and $pass1MoveLog.Count -gt 0) {",
"lineNumber": 522
},
{
"text": " $allMoves += $pass1MoveLog",
"lineNumber": 523
},
{
"text": "}",
"lineNumber": 524
},
{
"text": "if ($null -ne $pass2MoveLog -and $pass2MoveLog.Count -gt 0) {",
"lineNumber": 525
},
{
"text": " $allMoves += $pass2MoveLog",
"lineNumber": 526
},
{
"text": "}",
"lineNumber": 527
},
{
"text": "if ($null -ne $flatColorsMoveLog -and $flatColorsMoveLog.Count -gt 0) {",
"lineNumber": 528
},
{
"text": " $allMoves += $flatColorsMoveLog",
"lineNumber": 529
},
{
"text": "}",
"lineNumber": 530
},
{
"lineNumber": 531
},
{
"text": "# Get parent directory of texture folder",
"lineNumber": 532
},
{
"text": "$blendFileParentDir = Split-Path -Path $textureFolderPath -Parent",
"lineNumber": 533
},
{
"lineNumber": 534
},
{
"text": "# Find matching blend files",
"lineNumber": 535
},
{
"text": "# Match logic: blendfile folder name (e.g., \"Beth\") should appear in blend file name (e.g., \"AM_Beth_v3.2.blend\")",
"lineNumber": 536
},
{
"text": "$blendFileMappings = @()",
"lineNumber": 537
},
{
"text": "if ($null -ne $blendfileFolders -and $blendfileFolders.Count -gt 0) {",
"lineNumber": 538
},
{
"text": " # Get blendfile folder names",
"lineNumber": 539
},
{
"text": " $blendfileFolderNames = $blendfileFolders | ForEach-Object { $_.Name }",
"lineNumber": 540
},
{
"text": " ",
"lineNumber": 541
},
{
"text": " # Find all .blend files in parent directory",
"lineNumber": 542
},
{
"text": " $blendFiles = Get-ChildItem -Path $blendFileParentDir -Filter \"*.blend\" -File -ErrorAction SilentlyContinue",
"lineNumber": 543
},
{
"text": " ",
"lineNumber": 544
},
{
"text": " if ($null -ne $blendFiles -and $blendFiles.Count -gt 0) {",
"lineNumber": 545
},
{
"text": " foreach ($blendFile in $blendFiles) {",
"lineNumber": 546
},
{
"text": " ",
"lineNumber": 547
}
]
},
"score": 0.1407375931739807
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\components\\gitattributes",
"range": {
"startPosition": {
"line": 51
},
"endPosition": {
"line": 115
}
},
"contents": "*.hiplc filter=lfs diff=lfs merge=lfs -text\n*.bgeo filter=lfs diff=lfs merge=lfs -text\n*.bgeo.sc filter=lfs diff=lfs merge=lfs -text\n\n# Flip Fluids cache files\n*.data filter=lfs diff=lfs merge=lfs -text\n*.sqlite3 filter=lfs diff=lfs merge=lfs -text\n*.ffp3 filter=lfs diff=lfs merge=lfs -text\n\n# Substance files\n*.sbs filter=lfs diff=lfs merge=lfs -text\n*.sbsar filter=lfs diff=lfs merge=lfs -text\n*.spp filter=lfs diff=lfs merge=lfs -text\n\n# Audio files\n*.mp3 filter=lfs diff=lfs merge=lfs -text\n*.wav filter=lfs diff=lfs merge=lfs -text\n*.m4a filter=lfs diff=lfs merge=lfs -text\n*.aac filter=lfs diff=lfs merge=lfs -text\n*.ogg filter=lfs diff=lfs merge=lfs -text\n*.flac filter=lfs diff=lfs merge=lfs -text\n\n# Archive/Compression files\n*.7z filter=lfs diff=lfs merge=lfs -text\n*.bz2 filter=lfs diff=lfs merge=lfs -text\n*.gz filter=lfs diff=lfs merge=lfs -text\n*.rar filter=lfs diff=lfs merge=lfs -text\n*.tar filter=lfs diff=lfs merge=lfs -text\n*.zip filter=lfs diff=lfs merge=lfs -text\n\n# Documents\n*.docx filter=lfs diff=lfs merge=lfs -text\n*.xlsx filter=lfs diff=lfs merge=lfs -text\n*.eps filter=lfs diff=lfs merge=lfs -text\n*.pdf filter=lfs diff=lfs merge=lfs -text\n\n# Adobe files\n*.aegraphic filter=lfs diff=lfs merge=lfs -text\n*.aep filter=lfs diff=lfs merge=lfs -text\n*.prel filter=lfs diff=lfs merge=lfs -text\n*.prin filter=lfs diff=lfs merge=lfs -text\n*.prmf filter=lfs diff=lfs merge=lfs -text\n*.prproj filter=lfs diff=lfs merge=lfs -text\n*.ai filter=lfs diff=lfs merge=lfs -text\n*.psd filter=lfs diff=lfs merge=lfs -text\n\n# Davinci Resolve files\n*.dpx filter=lfs diff=lfs merge=lfs -text\n*.drp filter=lfs diff=lfs merge=lfs -text\n\n# Data files\n*.h5 filter=lfs diff=lfs merge=lfs -text\n*.hdf5 filter=lfs diff=lfs merge=lfs -text\n\n# Other\n*.uni filter=lfs diff=lfs merge=lfs -text\n*.pdn filter=lfs diff=lfs merge=lfs -text\n*.pur filter=lfs diff=lfs merge=lfs -text\n*.db filter=lfs diff=lfs merge=lfs -text\n\n# Python files\n*.npz filter=lfs diff=lfs merge=lfs -text\n\n# Adobe Alternatives",
"signatures": {},
"detailedLines": [
{
"text": "*.hiplc filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 52
},
{
"text": "*.bgeo filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 53
},
{
"text": "*.bgeo.sc filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 54
},
{
"lineNumber": 55
},
{
"text": "# Flip Fluids cache files",
"lineNumber": 56
},
{
"text": "*.data filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 57
},
{
"text": "*.sqlite3 filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 58
},
{
"text": "*.ffp3 filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 59
},
{
"lineNumber": 60
},
{
"text": "# Substance files",
"lineNumber": 61
},
{
"text": "*.sbs filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 62
},
{
"text": "*.sbsar filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 63
},
{
"text": "*.spp filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 64
},
{
"lineNumber": 65
},
{
"text": "# Audio files",
"lineNumber": 66
},
{
"text": "*.mp3 filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 67
},
{
"text": "*.wav filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 68
},
{
"text": "*.m4a filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 69
},
{
"text": "*.aac filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 70
},
{
"text": "*.ogg filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 71
},
{
"text": "*.flac filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 72
},
{
"lineNumber": 73
},
{
"text": "# Archive/Compression files",
"lineNumber": 74
},
{
"text": "*.7z filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 75
},
{
"text": "*.bz2 filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 76
},
{
"text": "*.gz filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 77
},
{
"text": "*.rar filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 78
},
{
"text": "*.tar filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 79
},
{
"text": "*.zip filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 80
},
{
"lineNumber": 81
},
{
"text": "# Documents",
"lineNumber": 82
},
{
"text": "*.docx filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 83
},
{
"text": "*.xlsx filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 84
},
{
"text": "*.eps filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 85
},
{
"text": "*.pdf filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 86
},
{
"lineNumber": 87
},
{
"text": "# Adobe files",
"lineNumber": 88
},
{
"text": "*.aegraphic filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 89
},
{
"text": "*.aep filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 90
},
{
"text": "*.prel filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 91
},
{
"text": "*.prin filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 92
},
{
"text": "*.prmf filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 93
},
{
"text": "*.prproj filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 94
},
{
"text": "*.ai filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 95
},
{
"text": "*.psd filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 96
},
{
"lineNumber": 97
},
{
"text": "# Davinci Resolve files",
"lineNumber": 98
},
{
"text": "*.dpx filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 99
},
{
"text": "*.drp filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 100
},
{
"lineNumber": 101
},
{
"text": "# Data files",
"lineNumber": 102
},
{
"text": "*.h5 filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 103
},
{
"text": "*.hdf5 filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 104
},
{
"lineNumber": 105
},
{
"text": "# Other",
"lineNumber": 106
},
{
"text": "*.uni filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 107
},
{
"text": "*.pdn filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 108
},
{
"text": "*.pur filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 109
},
{
"text": "*.db filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 110
},
{
"lineNumber": 111
},
{
"text": "# Python files",
"lineNumber": 112
},
{
"text": "*.npz filter=lfs diff=lfs merge=lfs -text",
"lineNumber": 113
},
{
"lineNumber": 114
},
{
"text": "# Adobe Alternatives",
"lineNumber": 115
}
]
},
"score": 0.13852763175964355
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\ConfigLoader.ps1",
"range": {
"startPosition": {},
"endPosition": {
"line": 54
}
},
"contents": "[CmdletBinding()]\nparam(\n [Parameter(Mandatory=$false)]\n [string]$ProjectPath\n)\n\nSet-StrictMode -Version Latest\n$ErrorActionPreference = 'Stop'\n\n$script:LoaderRoot = Split-Path -Parent $MyInvocation.MyCommand.Path\n$script:ConfigPath = Join-Path -Path $script:LoaderRoot -ChildPath 'config.json'\n$script:ConfigCache = $null\n\nfunction Get-ProjectStructureConfig {\n if ($null -ne $script:ConfigCache) {\n return $script:ConfigCache\n }\n\n if (Test-Path -LiteralPath $script:ConfigPath) {\n try {\n $raw = Get-Content -LiteralPath $script:ConfigPath -Raw -ErrorAction Stop\n if ($raw.Trim().Length -gt 0) {\n $script:ConfigCache = $raw | ConvertFrom-Json\n return $script:ConfigCache\n }\n }\n catch {\n Write-Warning \"Failed to parse config.json: $($_.Exception.Message)\"\n }\n }\n\n $script:ConfigCache = [pscustomobject]@{}\n return $script:ConfigCache\n}\n\nfunction Get-ConfigValue {\n param(\n [Parameter(Mandatory)] [string]$Name,\n $Default = $null\n )\n\n $config = Get-ProjectStructureConfig\n if ($config.PSObject.Properties.Name -contains $Name) {\n $value = $config.$Name\n if ($null -ne $value -and ($value -isnot [string] -or $value.Trim().Length -gt 0)) {\n return $value\n }\n }\n\n return $Default\n}\n\nfunction Get-StructDirectory {\n # When script is run directly (not dot-sourced), always use script's directory for portability",
"signatures": {},
"detailedLines": [
{
"text": "[CmdletBinding()]",
"lineNumber": 1
},
{
"text": "param(",
"lineNumber": 2
},
{
"text": " [Parameter(Mandatory=$false)]",
"lineNumber": 3
},
{
"text": " [string]$ProjectPath",
"lineNumber": 4
},
{
"text": ")",
"lineNumber": 5
},
{
"lineNumber": 6
},
{
"text": "Set-StrictMode -Version Latest",
"lineNumber": 7
},
{
"text": "$ErrorActionPreference = 'Stop'",
"lineNumber": 8
},
{
"lineNumber": 9
},
{
"text": "$script:LoaderRoot = Split-Path -Parent $MyInvocation.MyCommand.Path",
"lineNumber": 10
},
{
"text": "$script:ConfigPath = Join-Path -Path $script:LoaderRoot -ChildPath 'config.json'",
"lineNumber": 11
},
{
"text": "$script:ConfigCache = $null",
"lineNumber": 12
},
{
"lineNumber": 13
},
{
"text": "function Get-ProjectStructureConfig {",
"lineNumber": 14
},
{
"text": " if ($null -ne $script:ConfigCache) {",
"lineNumber": 15
},
{
"text": " return $script:ConfigCache",
"lineNumber": 16
},
{
"text": " }",
"lineNumber": 17
},
{
"lineNumber": 18
},
{
"text": " if (Test-Path -LiteralPath $script:ConfigPath) {",
"lineNumber": 19
},
{
"text": " try {",
"lineNumber": 20
},
{
"text": " $raw = Get-Content -LiteralPath $script:ConfigPath -Raw -ErrorAction Stop",
"lineNumber": 21
},
{
"text": " if ($raw.Trim().Length -gt 0) {",
"lineNumber": 22
},
{
"text": " $script:ConfigCache = $raw | ConvertFrom-Json",
"lineNumber": 23
},
{
"text": " return $script:ConfigCache",
"lineNumber": 24
},
{
"text": " }",
"lineNumber": 25
},
{
"text": " }",
"lineNumber": 26
},
{
"text": " catch {",
"lineNumber": 27
},
{
"text": " Write-Warning \"Failed to parse config.json: $($_.Exception.Message)\"",
"lineNumber": 28
},
{
"text": " }",
"lineNumber": 29
},
{
"text": " }",
"lineNumber": 30
},
{
"lineNumber": 31
},
{
"text": " $script:ConfigCache = [pscustomobject]@{}",
"lineNumber": 32
},
{
"text": " return $script:ConfigCache",
"lineNumber": 33
},
{
"text": "}",
"lineNumber": 34
},
{
"lineNumber": 35
},
{
"text": "function Get-ConfigValue {",
"lineNumber": 36
},
{
"text": " param(",
"lineNumber": 37
},
{
"text": " [Parameter(Mandatory)] [string]$Name,",
"lineNumber": 38
},
{
"text": " $Default = $null",
"lineNumber": 39
},
{
"text": " )",
"lineNumber": 40
},
{
"lineNumber": 41
},
{
"text": " $config = Get-ProjectStructureConfig",
"lineNumber": 42
},
{
"text": " if ($config.PSObject.Properties.Name -contains $Name) {",
"lineNumber": 43
},
{
"text": " $value = $config.$Name",
"lineNumber": 44
},
{
"text": " if ($null -ne $value -and ($value -isnot [string] -or $value.Trim().Length -gt 0)) {",
"lineNumber": 45
},
{
"text": " return $value",
"lineNumber": 46
},
{
"text": " }",
"lineNumber": 47
},
{
"text": " }",
"lineNumber": 48
},
{
"lineNumber": 49
},
{
"text": " return $Default",
"lineNumber": 50
},
{
"text": "}",
"lineNumber": 51
},
{
"lineNumber": 52
},
{
"text": "function Get-StructDirectory {",
"lineNumber": 53
},
{
"text": " # When script is run directly (not dot-sourced), always use script's directory for portability",
"lineNumber": 54
}
]
},
"score": 0.13009920716285706
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\replace_cel_with_bsdf.py",
"range": {
"startPosition": {},
"endPosition": {
"line": 106
}
},
"contents": "import bpy\nimport re\nimport os\n\ndef link_bsdf_materials():\n \"\"\"Link all materials from the BSDF library file\"\"\"\n \n library_path = r\"R:\\Creative\\artsy\\maya\\0 ProjectStructure\\1 BlenderAssets\\Amazon\\MATERIALS_BSDF_pallette_v1.0.blend\"\n \n if not os.path.exists(library_path):\n print(f\"Warning: Library file not found at {library_path}\")\n return []\n \n print(f\"Linking materials from: {library_path}\")\n \n # Get list of materials before linking\n materials_before = set(bpy.data.materials.keys())\n \n # Link all materials from the library file\n with bpy.data.libraries.load(library_path, link=True) as (data_from, data_to):\n # Link all materials\n data_to.materials = data_from.materials\n \n # Get list of newly linked materials\n materials_after = set(bpy.data.materials.keys())\n newly_linked = materials_after - materials_before\n \n print(f\"Linked {len(newly_linked)} materials from library\")\n for mat_name in sorted(newly_linked):\n print(f\" - {mat_name}\")\n \n return list(newly_linked)\n\ndef remap_appended_to_linked():\n \"\"\"Remap any appended BSDF materials to their linked counterparts\"\"\"",
"signatures": {},
"detailedLines": [
{
"text": "import bpy",
"lineNumber": 1
},
{
"text": "import re",
"lineNumber": 2
},
{
"text": "import os",
"lineNumber": 3
},
{
"lineNumber": 4
},
{
"text": "def link_bsdf_materials():",
"lineNumber": 5,
"isSignature": true
},
{
"text": " \"\"\"Link all materials from the BSDF library file\"\"\"",
"lineNumber": 6
},
{
"text": " ",
"lineNumber": 7
},
{
"text": " library_path = r\"R:\\Creative\\artsy\\maya\\0 ProjectStructure\\1 BlenderAssets\\Amazon\\MATERIALS_BSDF_pallette_v1.0.blend\"",
"lineNumber": 8
},
{
"text": " ",
"lineNumber": 9
},
{
"text": " if not os.path.exists(library_path):",
"lineNumber": 10
},
{
"text": " print(f\"Warning: Library file not found at {library_path}\")",
"lineNumber": 11
},
{
"text": " return []",
"lineNumber": 12
},
{
"text": " ",
"lineNumber": 13
},
{
"text": " print(f\"Linking materials from: {library_path}\")",
"lineNumber": 14
},
{
"text": " ",
"lineNumber": 15
},
{
"text": " # Get list of materials before linking",
"lineNumber": 16
},
{
"text": " materials_before = set(bpy.data.materials.keys())",
"lineNumber": 17
},
{
"text": " ",
"lineNumber": 18
},
{
"text": " # Link all materials from the library file",
"lineNumber": 19
},
{
"text": " with bpy.data.libraries.load(library_path, link=True) as (data_from, data_to):",
"lineNumber": 20
},
{
"text": " # Link all materials",
"lineNumber": 21
},
{
"text": " data_to.materials = data_from.materials",
"lineNumber": 22
},
{
"text": " ",
"lineNumber": 23
},
{
"text": " # Get list of newly linked materials",
"lineNumber": 24
},
{
"text": " materials_after = set(bpy.data.materials.keys())",
"lineNumber": 25
},
{
"text": " newly_linked = materials_after - materials_before",
"lineNumber": 26
},
{
"text": " ",
"lineNumber": 27
},
{
"text": " print(f\"Linked {len(newly_linked)} materials from library\")",
"lineNumber": 28
},
{
"text": " for mat_name in sorted(newly_linked):",
"lineNumber": 29
},
{
"text": " print(f\" - {mat_name}\")",
"lineNumber": 30
},
{
"text": " ",
"lineNumber": 31
},
{
"text": " return list(newly_linked)",
"lineNumber": 32,
"isSignature": true
},
{
"lineNumber": 33
},
{
"text": "def remap_appended_to_linked():",
"lineNumber": 34,
"isSignature": true
},
{
"text": " \"\"\"Remap any appended BSDF materials to their linked counterparts\"\"\"",
"lineNumber": 35
}
]
},
"score": 0.1130639985203743
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 543
},
"endPosition": {
"line": 585
}
},
"contents": " \n if ($null -ne $blendFiles -and $blendFiles.Count -gt 0) {\n foreach ($blendFile in $blendFiles) {\n $blendFileName = $blendFile.BaseName\n \n # Check if any blendfile folder name appears in the blend file name\n foreach ($folderName in $blendfileFolderNames) {\n # Match folder name when surrounded by underscores, dots, hyphens, or at start/end\n # This avoids partial matches (e.g., \"Beth\" in \"Bethany\") while allowing \"Beth\" in \"AM_Beth_v3.2\"\n $escapedFolderName = [regex]::Escape($folderName)\n if ($blendFileName -match \"(^|[._-])$escapedFolderName([._-]|$)\") {\n $blendFileMappings += [PSCustomObject]@{\n BlendFile = [System.IO.Path]::GetFullPath($blendFile.FullName)\n BlendfileFolder = $folderName\n }\n Write-Host \"Found matching blend file: $($blendFile.Name) -> $folderName\" -ForegroundColor Gray\n break # Only match once per blend file\n }\n }\n }\n }\n}\n\n# Create move log object\n$moveLogData = [PSCustomObject]@{\n TextureFolderPath = $textureFolderPath\n Timestamp = (Get-Date -Format \"yyyy-MM-ddTHH:mm:ssZ\")\n TotalMoves = ($allMoves | Where-Object { $_.Type -eq \"moved\" }).Count\n TotalDeletes = ($allMoves | Where-Object { $_.Type -eq \"deleted\" }).Count\n Moves = $allMoves\n BlendFileMappings = $blendFileMappings\n}\n\n# Save to JSON file\n$moveLogPath = Join-Path -Path $blendFileParentDir -ChildPath \"texture_moves.json\"\ntry {\n $moveLogData | ConvertTo-Json -Depth 10 | Set-Content -Path $moveLogPath -Encoding UTF8\n Write-Host \"Move log saved to: $moveLogPath\" -ForegroundColor Green\n Write-Host \" Total moves: $($moveLogData.TotalMoves), Total deletes: $($moveLogData.TotalDeletes)\" -ForegroundColor Gray\n Write-Host \" Blend files found: $($blendFileMappings.Count)\" -ForegroundColor Gray\n} catch {\n Write-Warning \"Failed to save move log: $($_.Exception.Message)\"",
"signatures": {},
"detailedLines": [
{
"text": " ",
"lineNumber": 544
},
{
"text": " if ($null -ne $blendFiles -and $blendFiles.Count -gt 0) {",
"lineNumber": 545
},
{
"text": " foreach ($blendFile in $blendFiles) {",
"lineNumber": 546
},
{
"text": " $blendFileName = $blendFile.BaseName",
"lineNumber": 547
},
{
"text": " ",
"lineNumber": 548
},
{
"text": " # Check if any blendfile folder name appears in the blend file name",
"lineNumber": 549
},
{
"text": " foreach ($folderName in $blendfileFolderNames) {",
"lineNumber": 550
},
{
"text": " # Match folder name when surrounded by underscores, dots, hyphens, or at start/end",
"lineNumber": 551
},
{
"text": " # This avoids partial matches (e.g., \"Beth\" in \"Bethany\") while allowing \"Beth\" in \"AM_Beth_v3.2\"",
"lineNumber": 552
},
{
"text": " $escapedFolderName = [regex]::Escape($folderName)",
"lineNumber": 553
},
{
"text": " if ($blendFileName -match \"(^|[._-])$escapedFolderName([._-]|$)\") {",
"lineNumber": 554
},
{
"text": " $blendFileMappings += [PSCustomObject]@{",
"lineNumber": 555
},
{
"text": " BlendFile = [System.IO.Path]::GetFullPath($blendFile.FullName)",
"lineNumber": 556
},
{
"text": " BlendfileFolder = $folderName",
"lineNumber": 557
},
{
"text": " }",
"lineNumber": 558
},
{
"text": " Write-Host \"Found matching blend file: $($blendFile.Name) -> $folderName\" -ForegroundColor Gray",
"lineNumber": 559
},
{
"text": " break # Only match once per blend file",
"lineNumber": 560
},
{
"text": " }",
"lineNumber": 561
},
{
"text": " }",
"lineNumber": 562
},
{
"text": " }",
"lineNumber": 563
},
{
"text": " }",
"lineNumber": 564
},
{
"text": "}",
"lineNumber": 565
},
{
"lineNumber": 566
},
{
"text": "# Create move log object",
"lineNumber": 567
},
{
"text": "$moveLogData = [PSCustomObject]@{",
"lineNumber": 568
},
{
"text": " TextureFolderPath = $textureFolderPath",
"lineNumber": 569
},
{
"text": " Timestamp = (Get-Date -Format \"yyyy-MM-ddTHH:mm:ssZ\")",
"lineNumber": 570
},
{
"text": " TotalMoves = ($allMoves | Where-Object { $_.Type -eq \"moved\" }).Count",
"lineNumber": 571
},
{
"text": " TotalDeletes = ($allMoves | Where-Object { $_.Type -eq \"deleted\" }).Count",
"lineNumber": 572
},
{
"text": " Moves = $allMoves",
"lineNumber": 573
},
{
"text": " BlendFileMappings = $blendFileMappings",
"lineNumber": 574
},
{
"text": "}",
"lineNumber": 575
},
{
"lineNumber": 576
},
{
"text": "# Save to JSON file",
"lineNumber": 577
},
{
"text": "$moveLogPath = Join-Path -Path $blendFileParentDir -ChildPath \"texture_moves.json\"",
"lineNumber": 578
},
{
"text": "try {",
"lineNumber": 579
},
{
"text": " $moveLogData | ConvertTo-Json -Depth 10 | Set-Content -Path $moveLogPath -Encoding UTF8",
"lineNumber": 580
},
{
"text": " Write-Host \"Move log saved to: $moveLogPath\" -ForegroundColor Green",
"lineNumber": 581
},
{
"text": " Write-Host \" Total moves: $($moveLogData.TotalMoves), Total deletes: $($moveLogData.TotalDeletes)\" -ForegroundColor Gray",
"lineNumber": 582
},
{
"text": " Write-Host \" Blend files found: $($blendFileMappings.Count)\" -ForegroundColor Gray",
"lineNumber": 583
},
{
"text": "} catch {",
"lineNumber": 584
},
{
"text": " Write-Warning \"Failed to save move log: $($_.Exception.Message)\"",
"lineNumber": 585
}
]
},
"score": 0.11181569844484329
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\zip_sequences.py",
"range": {
"startPosition": {
"line": 102,
"column": 32
},
"endPosition": {
"line": 202
}
},
"contents": "CONFIG = load_config()\nzipper_val = CONFIG.get(\"zipper\", \"7z\")\n# Handle both old boolean format and new string format\nif isinstance(zipper_val, bool):\n ZIPPER_TYPE = \"7z\" if zipper_val else \"zip\"\nelse:\n ZIPPER_TYPE = str(zipper_val).lower()\n\nCOMPRESSION_LEVEL = CONFIG.get(\"compression\", 9)\nif isinstance(COMPRESSION_LEVEL, str):\n try:\n COMPRESSION_LEVEL = int(COMPRESSION_LEVEL)\n except ValueError:\n COMPRESSION_LEVEL = 9\nif not isinstance(COMPRESSION_LEVEL, int):\n COMPRESSION_LEVEL = 9\nCOMPRESSION_LEVEL = max(0, min(9, COMPRESSION_LEVEL))\n\nCOMPRESSION_METHOD = CONFIG.get(\"compressionMethod\", \"LZMA2\")\n# Validate compression method\nvalid_methods = {\"LZMA2\", \"PPMd\", \"BZip2\", \"Deflate\"}\nif COMPRESSION_METHOD not in valid_methods:\n COMPRESSION_METHOD = \"LZMA2\" # Default to LZMA2 for multi-threading support\n\nMAX_7Z_INSTANCES = CONFIG.get(\"Max7zInst\", 0)\nif MAX_7Z_INSTANCES is not None:\n if isinstance(MAX_7Z_INSTANCES, str):\n try:\n MAX_7Z_INSTANCES = int(MAX_7Z_INSTANCES)\n except ValueError:\n MAX_7Z_INSTANCES = 0\n if not isinstance(MAX_7Z_INSTANCES, int) or MAX_7Z_INSTANCES < 1:\n MAX_7Z_INSTANCES = 0\n# Treat 0 as None (auto-calculate)\nif MAX_7Z_INSTANCES == 0:\n MAX_7Z_INSTANCES = None\n\nSEVEN_Z_EXE: str | None = None\nif ZIPPER_TYPE == \"7z\":\n SEVEN_Z_EXE = shutil.which(\"7z\") or shutil.which(\"7za\")\n\n\ndef parse_args() -> argparse.Namespace:\n parser = argparse.ArgumentParser(description=\"Sync render sequences with zipped archives.\")\n parser.add_argument(\n \"--mode\",\n choices=(\"zip\", \"expand\"),\n default=\"zip\",\n help=\"zip sequences for commit (default) or expand tracked archives\",\n )\n parser.add_argument(\"--jobs\", type=int, help=\"max parallel workers\")\n parser.add_argument(\"--verbose\", action=\"store_true\", help=\"print extra progress details\")\n return parser.parse_args()\n\n\ndef get_available_ram() -> int | None:\n \"\"\"",
"signatures": {},
"detailedLines": [
{
"text": "CONFIG = load_config()",
"lineNumber": 106
},
{
"text": "zipper_val = CONFIG.get(\"zipper\", \"7z\")",
"lineNumber": 107
},
{
"text": "# Handle both old boolean format and new string format",
"lineNumber": 108
},
{
"text": "if isinstance(zipper_val, bool):",
"lineNumber": 109
},
{
"text": " ZIPPER_TYPE = \"7z\" if zipper_val else \"zip\"",
"lineNumber": 110
},
{
"text": "else:",
"lineNumber": 111
},
{
"text": " ZIPPER_TYPE = str(zipper_val).lower()",
"lineNumber": 112
},
{
"lineNumber": 113
},
{
"text": "COMPRESSION_LEVEL = CONFIG.get(\"compression\", 9)",
"lineNumber": 114
},
{
"text": "if isinstance(COMPRESSION_LEVEL, str):",
"lineNumber": 115
},
{
"text": " try:",
"lineNumber": 116
},
{
"text": " COMPRESSION_LEVEL = int(COMPRESSION_LEVEL)",
"lineNumber": 117
},
{
"text": " except ValueError:",
"lineNumber": 118
},
{
"text": " COMPRESSION_LEVEL = 9",
"lineNumber": 119
},
{
"text": "if not isinstance(COMPRESSION_LEVEL, int):",
"lineNumber": 120
},
{
"text": " COMPRESSION_LEVEL = 9",
"lineNumber": 121
},
{
"text": "COMPRESSION_LEVEL = max(0, min(9, COMPRESSION_LEVEL))",
"lineNumber": 122
},
{
"lineNumber": 123
},
{
"text": "COMPRESSION_METHOD = CONFIG.get(\"compressionMethod\", \"LZMA2\")",
"lineNumber": 124
},
{
"text": "# Validate compression method",
"lineNumber": 125
},
{
"text": "valid_methods = {\"LZMA2\", \"PPMd\", \"BZip2\", \"Deflate\"}",
"lineNumber": 126
},
{
"text": "if COMPRESSION_METHOD not in valid_methods:",
"lineNumber": 127
},
{
"text": " COMPRESSION_METHOD = \"LZMA2\" # Default to LZMA2 for multi-threading support",
"lineNumber": 128
},
{
"lineNumber": 129
},
{
"text": "MAX_7Z_INSTANCES = CONFIG.get(\"Max7zInst\", 0)",
"lineNumber": 130
},
{
"text": "if MAX_7Z_INSTANCES is not None:",
"lineNumber": 131
},
{
"text": " if isinstance(MAX_7Z_INSTANCES, str):",
"lineNumber": 132
},
{
"text": " try:",
"lineNumber": 133
},
{
"text": " MAX_7Z_INSTANCES = int(MAX_7Z_INSTANCES)",
"lineNumber": 134
},
{
"text": " except ValueError:",
"lineNumber": 135
},
{
"text": " MAX_7Z_INSTANCES = 0",
"lineNumber": 136
},
{
"text": " if not isinstance(MAX_7Z_INSTANCES, int) or MAX_7Z_INSTANCES < 1:",
"lineNumber": 137
},
{
"text": " MAX_7Z_INSTANCES = 0",
"lineNumber": 138
},
{
"text": "# Treat 0 as None (auto-calculate)",
"lineNumber": 139
},
{
"text": "if MAX_7Z_INSTANCES == 0:",
"lineNumber": 140
},
{
"text": " MAX_7Z_INSTANCES = None",
"lineNumber": 141
},
{
"lineNumber": 142
},
{
"text": "SEVEN_Z_EXE: str | None = None",
"lineNumber": 143
},
{
"text": "if ZIPPER_TYPE == \"7z\":",
"lineNumber": 144
},
{
"text": " SEVEN_Z_EXE = shutil.which(\"7z\") or shutil.which(\"7za\")",
"lineNumber": 145
},
{
"lineNumber": 146
},
{
"lineNumber": 147
},
{
"text": "def parse_args() -> argparse.Namespace:",
"lineNumber": 148,
"isSignature": true
},
{
"text": " parser = argparse.ArgumentParser(description=\"Sync render sequences with zipped archives.\")",
"lineNumber": 149
},
{
"text": " parser.add_argument(",
"lineNumber": 150
},
{
"text": " \"--mode\",",
"lineNumber": 151
},
{
"text": " choices=(\"zip\", \"expand\"),",
"lineNumber": 152
},
{
"text": " default=\"zip\",",
"lineNumber": 153
},
{
"text": " help=\"zip sequences for commit (default) or expand tracked archives\",",
"lineNumber": 154
},
{
"text": " )",
"lineNumber": 155
},
{
"text": " parser.add_argument(\"--jobs\", type=int, help=\"max parallel workers\")",
"lineNumber": 156
},
{
"text": " parser.add_argument(\"--verbose\", action=\"store_true\", help=\"print extra progress details\")",
"lineNumber": 157
},
{
"text": " return parser.parse_args()",
"lineNumber": 158,
"isSignature": true
},
{
"lineNumber": 159
},
{
"lineNumber": 160
},
{
"text": "def get_available_ram() -> int | None:",
"lineNumber": 161,
"isSignature": true
},
{
"text": " \"\"\"",
"lineNumber": 162
}
]
},
"score": 0.10932300239801407
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {},
"endPosition": {
"line": 50
}
},
"contents": "# Script to organize texture files by checksum with two-level duplicate detection\n# Pass 1: Intra-blendfile duplicates → [blendfile]\\common\n# Pass 2: Inter-blendfile duplicates → \\textures\\common\n# Usage: .\\organize_textures.ps1\n\n# Prompt user for texture folder path\n$textureFolderPath = Read-Host \"Enter texture folder path\"\n\n# Validate the input path\nif ([string]::IsNullOrWhiteSpace($textureFolderPath)) {\n Write-Host \"Error: No path provided.\" -ForegroundColor Red\n exit\n}\n\nif (-not (Test-Path -Path $textureFolderPath -PathType Container)) {\n Write-Host \"Error: Path does not exist or is not a directory: $textureFolderPath\" -ForegroundColor Red\n exit\n}\n\n# Resolve the full path\n$textureFolderPath = (Resolve-Path $textureFolderPath).ProviderPath\nWrite-Host \"Processing texture folder: $textureFolderPath\" -ForegroundColor Cyan\n\n# Function to calculate checksums for files\nfunction Get-FilesWithChecksums {\n param(\n [array]$Files\n )\n \n $throttleLimit = [Math]::Max(1, [Environment]::ProcessorCount)\n $parallelScriptBlock = {\n try {\n $hash = Get-FileHash -Path $_.FullName -Algorithm SHA256\n [PSCustomObject]@{\n File = $_\n Hash = $hash.Hash\n }\n } catch {\n Write-Warning \"Failed to calculate checksum for: $($_.FullName) - $($_.Exception.Message)\"\n $null\n }\n }\n \n return $Files | ForEach-Object -Parallel $parallelScriptBlock -ThrottleLimit $throttleLimit | Where-Object { $null -ne $_ }\n}\n\n# Function to move files to common folder\nfunction Move-FilesToCommon {\n param(\n [array]$Files,",
"signatures": {},
"detailedLines": [
{
"text": "# Script to organize texture files by checksum with two-level duplicate detection",
"lineNumber": 1
},
{
"text": "# Pass 1: Intra-blendfile duplicates → [blendfile]\\common",
"lineNumber": 2
},
{
"text": "# Pass 2: Inter-blendfile duplicates → \\textures\\common",
"lineNumber": 3
},
{
"text": "# Usage: .\\organize_textures.ps1",
"lineNumber": 4
},
{
"lineNumber": 5
},
{
"text": "# Prompt user for texture folder path",
"lineNumber": 6
},
{
"text": "$textureFolderPath = Read-Host \"Enter texture folder path\"",
"lineNumber": 7
},
{
"lineNumber": 8
},
{
"text": "# Validate the input path",
"lineNumber": 9
},
{
"text": "if ([string]::IsNullOrWhiteSpace($textureFolderPath)) {",
"lineNumber": 10
},
{
"text": " Write-Host \"Error: No path provided.\" -ForegroundColor Red",
"lineNumber": 11
},
{
"text": " exit",
"lineNumber": 12
},
{
"text": "}",
"lineNumber": 13
},
{
"lineNumber": 14
},
{
"text": "if (-not (Test-Path -Path $textureFolderPath -PathType Container)) {",
"lineNumber": 15
},
{
"text": " Write-Host \"Error: Path does not exist or is not a directory: $textureFolderPath\" -ForegroundColor Red",
"lineNumber": 16
},
{
"text": " exit",
"lineNumber": 17
},
{
"text": "}",
"lineNumber": 18
},
{
"lineNumber": 19
},
{
"text": "# Resolve the full path",
"lineNumber": 20
},
{
"text": "$textureFolderPath = (Resolve-Path $textureFolderPath).ProviderPath",
"lineNumber": 21
},
{
"text": "Write-Host \"Processing texture folder: $textureFolderPath\" -ForegroundColor Cyan",
"lineNumber": 22
},
{
"lineNumber": 23
},
{
"text": "# Function to calculate checksums for files",
"lineNumber": 24
},
{
"text": "function Get-FilesWithChecksums {",
"lineNumber": 25
},
{
"text": " param(",
"lineNumber": 26
},
{
"text": " [array]$Files",
"lineNumber": 27
},
{
"text": " )",
"lineNumber": 28
},
{
"text": " ",
"lineNumber": 29
},
{
"text": " $throttleLimit = [Math]::Max(1, [Environment]::ProcessorCount)",
"lineNumber": 30
},
{
"text": " $parallelScriptBlock = {",
"lineNumber": 31
},
{
"text": " try {",
"lineNumber": 32
},
{
"text": " $hash = Get-FileHash -Path $_.FullName -Algorithm SHA256",
"lineNumber": 33
},
{
"text": " [PSCustomObject]@{",
"lineNumber": 34
},
{
"text": " File = $_",
"lineNumber": 35
},
{
"text": " Hash = $hash.Hash",
"lineNumber": 36
},
{
"text": " }",
"lineNumber": 37
},
{
"text": " } catch {",
"lineNumber": 38
},
{
"text": " Write-Warning \"Failed to calculate checksum for: $($_.FullName) - $($_.Exception.Message)\"",
"lineNumber": 39
},
{
"text": " $null",
"lineNumber": 40
},
{
"text": " }",
"lineNumber": 41
},
{
"text": " }",
"lineNumber": 42
},
{
"text": " ",
"lineNumber": 43
},
{
"text": " return $Files | ForEach-Object -Parallel $parallelScriptBlock -ThrottleLimit $throttleLimit | Where-Object { $null -ne $_ }",
"lineNumber": 44
},
{
"text": "}",
"lineNumber": 45
},
{
"lineNumber": 46
},
{
"text": "# Function to move files to common folder",
"lineNumber": 47
},
{
"text": "function Move-FilesToCommon {",
"lineNumber": 48
},
{
"text": " param(",
"lineNumber": 49
},
{
"text": " [array]$Files,",
"lineNumber": 50
}
]
},
"score": 0.10515463352203369
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\zip_sequences.py",
"range": {
"startPosition": {
"line": 560,
"column": 33
},
"endPosition": {
"line": 650
}
},
"contents": "def load_state(state_path: Path) -> dict | None:\n if not state_path.exists():\n return None\n try:\n state = json.loads(state_path.read_text())\n # Remove Thumbs.db entries from loaded state\n if \"files\" in state:\n state[\"files\"] = [\n entry for entry in state.get(\"files\", [])\n if Path(entry.get(\"path\", \"\")).name.lower() != \"thumbs.db\"\n ]\n # Normalize timestamps in loaded state to ensure consistency\n # This handles state files created before normalization was added\n is_windows = platform.system() == \"Windows\"\n if is_windows and \"files\" in state:\n for entry in state.get(\"files\", []):\n if \"mtime_ns\" in entry:\n # Normalize to 100-nanosecond boundaries (NTFS precision)\n entry[\"mtime_ns\"] = (entry[\"mtime_ns\"] // 100) * 100\n return state\n except json.JSONDecodeError:\n return None\n\n\ndef state_changed(seq_state: dict, stored_state: dict | None, *, verbose: bool = False) -> bool:\n ",
"signatures": {},
"detailedLines": [
{
"text": "def load_state(state_path: Path) -> dict | None:",
"lineNumber": 564,
"isSignature": true
},
{
"text": " if not state_path.exists():",
"lineNumber": 565
},
{
"text": " return None",
"lineNumber": 566
},
{
"text": " try:",
"lineNumber": 567
},
{
"text": " state = json.loads(state_path.read_text())",
"lineNumber": 568
},
{
"text": " # Remove Thumbs.db entries from loaded state",
"lineNumber": 569
},
{
"text": " if \"files\" in state:",
"lineNumber": 570
},
{
"text": " state[\"files\"] = [",
"lineNumber": 571
},
{
"text": " entry for entry in state.get(\"files\", [])",
"lineNumber": 572
},
{
"text": " if Path(entry.get(\"path\", \"\")).name.lower() != \"thumbs.db\"",
"lineNumber": 573
},
{
"text": " ]",
"lineNumber": 574
},
{
"text": " # Normalize timestamps in loaded state to ensure consistency",
"lineNumber": 575
},
{
"text": " # This handles state files created before normalization was added",
"lineNumber": 576
},
{
"text": " is_windows = platform.system() == \"Windows\"",
"lineNumber": 577
},
{
"text": " if is_windows and \"files\" in state:",
"lineNumber": 578
},
{
"text": " for entry in state.get(\"files\", []):",
"lineNumber": 579
},
{
"text": " if \"mtime_ns\" in entry:",
"lineNumber": 580
},
{
"text": " # Normalize to 100-nanosecond boundaries (NTFS precision)",
"lineNumber": 581
},
{
"text": " entry[\"mtime_ns\"] = (entry[\"mtime_ns\"] // 100) * 100",
"lineNumber": 582
},
{
"text": " return state",
"lineNumber": 583
},
{
"text": " except json.JSONDecodeError:",
"lineNumber": 584
},
{
"text": " return None",
"lineNumber": 585,
"isSignature": true
},
{
"lineNumber": 586
},
{
"lineNumber": 587
},
{
"text": "def state_changed(seq_state: dict, stored_state: dict | None, *, verbose: bool = False) -> bool:",
"lineNumber": 588,
"isSignature": true
},
{
"text": " ",
"lineNumber": 589
}
]
},
"score": 0.10263250023126602
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\CONFIG.md",
"range": {
"startPosition": {},
"endPosition": {
"line": 24
}
},
"contents": "# ProjectStructure Configuration\n\nThe repository reads user preferences from `config.json` in the ProjectStructure\nroot (copied alongside helper batches when they are deployed to projects).\n\n## Keys\n\n| Key | Type | Meaning |\n| --- | --- | --- |\n| `dailyFormat` | bool | `true` → daily folders named `YYYY-MM-DD`; `false` → `daily_*` style. |\n| `structDir` | string | Absolute or relative path to the canonical ProjectStructure directory. Blank values default to the folder containing `config.json`. |\n| `projectsRoot` | string (optional) | Override for the root directory scanned by `UpgradeSeqBatches.ps1`. Defaults to the parent of `structDir`. |\n| `zipper` | bool | `true` → use 7‑Zip (if available); `false` → use Python’s built-in zipfile module. |\n| `compression` | int | Compression level `0-9` (0 = store only, 9 = max). Applies to both zipfile and 7‑Zip. |\n\n## Notes\n\n- `UpdateProjectBatches.ps1` copies `config.json` and `ConfigLoader.ps1` to the\n target project so the helper `.bat` launchers can resolve script locations.\n- When `zipper` is `true`, the tool searches for `7z`/`7za` on `PATH`. If neither\n is found it logs a warning and falls back to `zipfile`.\n- Leaving `structDir` empty is safe—the scripts fall back to the directory that\n contains `config.json`.",
"signatures": {},
"detailedLines": [
{
"text": "# ProjectStructure Configuration",
"lineNumber": 1
},
{
"lineNumber": 2
},
{
"text": "The repository reads user preferences from `config.json` in the ProjectStructure",
"lineNumber": 3
},
{
"text": "root (copied alongside helper batches when they are deployed to projects).",
"lineNumber": 4
},
{
"lineNumber": 5
},
{
"text": "## Keys",
"lineNumber": 6
},
{
"lineNumber": 7
},
{
"text": "| Key | Type | Meaning |",
"lineNumber": 8
},
{
"text": "| --- | --- | --- |",
"lineNumber": 9
},
{
"text": "| `dailyFormat` | bool | `true` → daily folders named `YYYY-MM-DD`; `false` → `daily_*` style. |",
"lineNumber": 10
},
{
"text": "| `structDir` | string | Absolute or relative path to the canonical ProjectStructure directory. Blank values default to the folder containing `config.json`. |",
"lineNumber": 11
},
{
"text": "| `projectsRoot` | string (optional) | Override for the root directory scanned by `UpgradeSeqBatches.ps1`. Defaults to the parent of `structDir`. |",
"lineNumber": 12
},
{
"text": "| `zipper` | bool | `true` → use 7‑Zip (if available); `false` → use Python’s built-in zipfile module. |",
"lineNumber": 13
},
{
"text": "| `compression` | int | Compression level `0-9` (0 = store only, 9 = max). Applies to both zipfile and 7‑Zip. |",
"lineNumber": 14
},
{
"lineNumber": 15
},
{
"text": "## Notes",
"lineNumber": 16
},
{
"lineNumber": 17
},
{
"text": "- `UpdateProjectBatches.ps1` copies `config.json` and `ConfigLoader.ps1` to the",
"lineNumber": 18
},
{
"text": " target project so the helper `.bat` launchers can resolve script locations.",
"lineNumber": 19
},
{
"text": "- When `zipper` is `true`, the tool searches for `7z`/`7za` on `PATH`. If neither",
"lineNumber": 20
},
{
"text": " is found it logs a warning and falls back to `zipfile`.",
"lineNumber": 21
},
{
"text": "- Leaving `structDir` empty is safe—the scripts fall back to the directory that",
"lineNumber": 22
},
{
"text": " contains `config.json`.",
"lineNumber": 23
}
]
},
"score": 0.1001589298248291
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\zip_sequences.py",
"range": {
"startPosition": {
"line": 981,
"column": 53
},
"endPosition": {
"line": 1170
}
},
"contents": "def run_zip(requested_workers: int | None, *, verbose: bool) -> int:\n work_items: list[tuple[Path, Path, Path, dict]] = []\n log(\"init\", f\"Scanning sequences under {RENDER_ROOT.resolve()}\")\n total_scanned = 0\n quick_skipped = 0\n state_skipped = 0\n empty_dirs = 0\n queued = 0\n\n if RENDER_ROOT.exists():\n for seq_dir in find_sequence_dirs(RENDER_ROOT, verbose=verbose):\n total_scanned += 1\n rel = seq_dir.relative_to(RENDER_ROOT)\n if total_scanned <= 5 or total_scanned % 10 == 0:\n log(\"scan\", f\"[{total_scanned}] Inspecting {rel}\")\n\n # Get the target archive path (will be .7z if ZIPPER_TYPE is \"7z\")\n zip_path = archive_path_for(seq_dir)\n state_path = state_path_for(zip_path)\n \n # Quick check: if archive exists, load stored state first (fast)\n stored_state = load_state(state_path)\n \n # Debug: log if stored state is missing\n if stored_state is None:\n if zip_path.exists():\n if verbose:\n log(\"scan\", f\"Warning: {rel} archive exists but no stored state file found at {state_path}\", verbose_only=True, verbose=verbose)\n else:\n if verbose:\n log(\"scan\", f\"Info: {rel} no archive or state file (will create new)\", verbose_only=True, verbose=verbose)\n \n # Check if we need to upgrade from .zip to .7z\n old_zip_path = None\n old_stored_state = None\n if ZIPPER_TYPE == \"7z\":\n old_zip_path = zip_path.with_suffix(\".zip\")",
"signatures": {},
"detailedLines": [
{
"text": "def run_zip(requested_workers: int | None, *, verbose: bool) -> int:",
"lineNumber": 985,
"isSignature": true
},
{
"text": " work_items: list[tuple[Path, Path, Path, dict]] = []",
"lineNumber": 986
},
{
"text": " log(\"init\", f\"Scanning sequences under {RENDER_ROOT.resolve()}\")",
"lineNumber": 987
},
{
"text": " total_scanned = 0",
"lineNumber": 988
},
{
"text": " quick_skipped = 0",
"lineNumber": 989
},
{
"text": " state_skipped = 0",
"lineNumber": 990
},
{
"text": " empty_dirs = 0",
"lineNumber": 991
},
{
"text": " queued = 0",
"lineNumber": 992
},
{
"lineNumber": 993
},
{
"text": " if RENDER_ROOT.exists():",
"lineNumber": 994
},
{
"text": " for seq_dir in find_sequence_dirs(RENDER_ROOT, verbose=verbose):",
"lineNumber": 995
},
{
"text": " total_scanned += 1",
"lineNumber": 996
},
{
"text": " rel = seq_dir.relative_to(RENDER_ROOT)",
"lineNumber": 997
},
{
"text": " if total_scanned <= 5 or total_scanned % 10 == 0:",
"lineNumber": 998
},
{
"text": " log(\"scan\", f\"[{total_scanned}] Inspecting {rel}\")",
"lineNumber": 999
},
{
"lineNumber": 1000
},
{
"text": " # Get the target archive path (will be .7z if ZIPPER_TYPE is \"7z\")",
"lineNumber": 1001
},
{
"text": " zip_path = archive_path_for(seq_dir)",
"lineNumber": 1002
},
{
"text": " state_path = state_path_for(zip_path)",
"lineNumber": 1003
},
{
"text": " ",
"lineNumber": 1004
},
{
"text": " # Quick check: if archive exists, load stored state first (fast)",
"lineNumber": 1005
},
{
"text": " stored_state = load_state(state_path)",
"lineNumber": 1006
},
{
"text": " ",
"lineNumber": 1007
},
{
"text": " # Debug: log if stored state is missing",
"lineNumber": 1008
},
{
"text": " if stored_state is None:",
"lineNumber": 1009
},
{
"text": " if zip_path.exists():",
"lineNumber": 1010
},
{
"text": " if verbose:",
"lineNumber": 1011
},
{
"text": " log(\"scan\", f\"Warning: {rel} archive exists but no stored state file found at {state_path}\", verbose_only=True, verbose=verbose)",
"lineNumber": 1012
},
{
"text": " else:",
"lineNumber": 1013
},
{
"text": " if verbose:",
"lineNumber": 1014
},
{
"text": " log(\"scan\", f\"Info: {rel} no archive or state file (will create new)\", verbose_only=True, verbose=verbose)",
"lineNumber": 1015
},
{
"text": " ",
"lineNumber": 1016
},
{
"text": " # Check if we need to upgrade from .zip to .7z",
"lineNumber": 1017
},
{
"text": " old_zip_path = None",
"lineNumber": 1018
},
{
"text": " old_stored_state = None",
"lineNumber": 1019
},
{
"text": " if ZIPPER_TYPE == \"7z\":",
"lineNumber": 1020
},
{
"text": " old_zip_path = zip_path.with_suffix(\".zip\")",
"lineNumber": 1021
}
]
},
"score": 0.1000261977314949
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 279
},
"endPosition": {
"line": 325
}
},
"contents": "} else {\n Write-Host \"Found $($blendfileFolders.Count) blendfile folder(s) to process.\" -ForegroundColor Green\n \n $totalPass1Moved = 0\n $totalPass1Duplicates = 0\n $pass1MoveLog = [System.Collections.ArrayList]::new()\n \n foreach ($blendfileFolder in $blendfileFolders) {\n Write-Host \"\"\n Write-Host \"Processing blendfile: $($blendfileFolder.Name)\" -ForegroundColor Yellow\n \n # Get all files in this blendfile folder, excluding \\common folders\n $blendfileFiles = Get-ChildItem -Path $blendfileFolder.FullName -Recurse -File | Where-Object { $_.FullName -notlike \"*\\common\\*\" }\n \n if ($null -eq $blendfileFiles -or $blendfileFiles.Count -eq 0) {\n Write-Host \" No files found in this blendfile folder.\" -ForegroundColor Gray\n continue\n }\n \n Write-Host \" Found $($blendfileFiles.Count) files.\" -ForegroundColor Gray\n \n # Calculate checksums\n Write-Host \" Calculating checksums...\" -ForegroundColor Gray\n $filesWithChecksums = Get-FilesWithChecksums -Files $blendfileFiles\n \n # Group by checksum\n $groupedByChecksum = $filesWithChecksums | Group-Object -Property Hash\n \n Write-Host \" Found $($groupedByChecksum.Count) unique checksums.\" -ForegroundColor Gray\n \n # Create [blendfile]\\common directory\n $blendfileCommonPath = Join-Path -Path $blendfileFolder.FullName -ChildPath \"common\"\n \n if (-not (Test-Path -Path $blendfileCommonPath -PathType Container)) {\n New-Item -ItemType Directory -Path $blendfileCommonPath | Out-Null\n }\n \n # Track filenames already in [blendfile]\\common\n $filesInBlendfileCommon = @{}\n \n # Process each checksum group\n $blendfileMoved = 0\n $blendfileDuplicates = 0\n \n foreach ($group in $groupedByChecksum) {\n $result = Process-DuplicateGroup -Files $group.Group -CommonPath $blendfileCommonPath -FilesInCommon $filesInBlendfileCommon -MoveLog $pass1MoveLog",
"signatures": {},
"detailedLines": [
{
"text": "} else {",
"lineNumber": 280
},
{
"text": " Write-Host \"Found $($blendfileFolders.Count) blendfile folder(s) to process.\" -ForegroundColor Green",
"lineNumber": 281
},
{
"text": " ",
"lineNumber": 282
},
{
"text": " $totalPass1Moved = 0",
"lineNumber": 283
},
{
"text": " $totalPass1Duplicates = 0",
"lineNumber": 284
},
{
"text": " $pass1MoveLog = [System.Collections.ArrayList]::new()",
"lineNumber": 285
},
{
"text": " ",
"lineNumber": 286
},
{
"text": " foreach ($blendfileFolder in $blendfileFolders) {",
"lineNumber": 287
},
{
"text": " Write-Host \"\"",
"lineNumber": 288
},
{
"text": " Write-Host \"Processing blendfile: $($blendfileFolder.Name)\" -ForegroundColor Yellow",
"lineNumber": 289
},
{
"text": " ",
"lineNumber": 290
},
{
"text": " # Get all files in this blendfile folder, excluding \\common folders",
"lineNumber": 291
},
{
"text": " $blendfileFiles = Get-ChildItem -Path $blendfileFolder.FullName -Recurse -File | Where-Object { $_.FullName -notlike \"*\\common\\*\" }",
"lineNumber": 292
},
{
"text": " ",
"lineNumber": 293
},
{
"text": " if ($null -eq $blendfileFiles -or $blendfileFiles.Count -eq 0) {",
"lineNumber": 294
},
{
"text": " Write-Host \" No files found in this blendfile folder.\" -ForegroundColor Gray",
"lineNumber": 295
},
{
"text": " continue",
"lineNumber": 296
},
{
"text": " }",
"lineNumber": 297
},
{
"text": " ",
"lineNumber": 298
},
{
"text": " Write-Host \" Found $($blendfileFiles.Count) files.\" -ForegroundColor Gray",
"lineNumber": 299
},
{
"text": " ",
"lineNumber": 300
},
{
"text": " # Calculate checksums",
"lineNumber": 301
},
{
"text": " Write-Host \" Calculating checksums...\" -ForegroundColor Gray",
"lineNumber": 302
},
{
"text": " $filesWithChecksums = Get-FilesWithChecksums -Files $blendfileFiles",
"lineNumber": 303
},
{
"text": " ",
"lineNumber": 304
},
{
"text": " # Group by checksum",
"lineNumber": 305
},
{
"text": " $groupedByChecksum = $filesWithChecksums | Group-Object -Property Hash",
"lineNumber": 306
},
{
"text": " ",
"lineNumber": 307
},
{
"text": " Write-Host \" Found $($groupedByChecksum.Count) unique checksums.\" -ForegroundColor Gray",
"lineNumber": 308
},
{
"text": " ",
"lineNumber": 309
},
{
"text": " # Create [blendfile]\\common directory",
"lineNumber": 310
},
{
"text": " $blendfileCommonPath = Join-Path -Path $blendfileFolder.FullName -ChildPath \"common\"",
"lineNumber": 311
},
{
"text": " ",
"lineNumber": 312
},
{
"text": " if (-not (Test-Path -Path $blendfileCommonPath -PathType Container)) {",
"lineNumber": 313
},
{
"text": " New-Item -ItemType Directory -Path $blendfileCommonPath | Out-Null",
"lineNumber": 314
},
{
"text": " }",
"lineNumber": 315
},
{
"text": " ",
"lineNumber": 316
},
{
"text": " # Track filenames already in [blendfile]\\common",
"lineNumber": 317
},
{
"text": " $filesInBlendfileCommon = @{}",
"lineNumber": 318
},
{
"text": " ",
"lineNumber": 319
},
{
"text": " # Process each checksum group",
"lineNumber": 320
},
{
"text": " $blendfileMoved = 0",
"lineNumber": 321
},
{
"text": " $blendfileDuplicates = 0",
"lineNumber": 322
},
{
"text": " ",
"lineNumber": 323
},
{
"text": " foreach ($group in $groupedByChecksum) {",
"lineNumber": 324
},
{
"text": " $result = Process-DuplicateGroup -Files $group.Group -CommonPath $blendfileCommonPath -FilesInCommon $filesInBlendfileCommon -MoveLog $pass1MoveLog",
"lineNumber": 325
}
]
},
"score": 0.09988240152597427
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\zip_sequences.py",
"range": {
"startPosition": {
"line": 584,
"column": 19
},
"endPosition": {
"line": 650
}
},
"contents": "def state_changed(seq_state: dict, stored_state: dict | None, *, verbose: bool = False) -> bool:\n if stored_state is None:\n if verbose:\n log(\"scan\", \"State changed: no stored state found\", verbose_only=True, verbose=verbose)\n return True\n \n # Normalize timestamps in both states for comparison\n # On Windows, normalize to 100-nanosecond boundaries (NTFS precision)\n is_windows = platform.system() == \"Windows\"\n \n def normalize_state(state: dict) -> dict:\n \"\"\"Normalize timestamps in state to filesystem precision and filter out Thumbs.db.\"\"\"\n normalized = {\"files\": []}\n for entry in state.get(\"files\", []):\n # Ignore Thumbs.db files in state comparison\n if Path(entry.get(\"path\", \"\")).name.lower() == \"thumbs.db\":\n continue\n mtime_ns = entry[\"mtime_ns\"]\n if is_windows:\n mtime_ns = (mtime_ns // 100) * 100\n normalized[\"files\"].append({\n \"path\": entry[\"path\"],\n \"size\": entry[\"size\"],\n \"mtime_ns\": mtime_ns,\n })\n return normalized\n \n # Compare normalized states (Thumbs.db already filtered out)\n normalized_seq = normalize_state(seq_state)\n normalized_stored = normalize_state(stored_state)\n \n if normalized_seq == normalized_stored:\n return False\n \n # States differ - log diagnostic info if verbose\n if verbose:",
"signatures": {},
"detailedLines": [
{
"text": "def state_changed(seq_state: dict, stored_state: dict | None, *, verbose: bool = False) -> bool:",
"lineNumber": 588,
"isSignature": true
},
{
"text": " if stored_state is None:",
"lineNumber": 589
},
{
"text": " if verbose:",
"lineNumber": 590
},
{
"text": " log(\"scan\", \"State changed: no stored state found\", verbose_only=True, verbose=verbose)",
"lineNumber": 591
},
{
"text": " return True",
"lineNumber": 592
},
{
"text": " ",
"lineNumber": 593
},
{
"text": " # Normalize timestamps in both states for comparison",
"lineNumber": 594
},
{
"text": " # On Windows, normalize to 100-nanosecond boundaries (NTFS precision)",
"lineNumber": 595
},
{
"text": " is_windows = platform.system() == \"Windows\"",
"lineNumber": 596
},
{
"text": " ",
"lineNumber": 597
},
{
"text": " def normalize_state(state: dict) -> dict:",
"lineNumber": 598
},
{
"text": " \"\"\"Normalize timestamps in state to filesystem precision and filter out Thumbs.db.\"\"\"",
"lineNumber": 599
},
{
"text": " normalized = {\"files\": []}",
"lineNumber": 600
},
{
"text": " for entry in state.get(\"files\", []):",
"lineNumber": 601
},
{
"text": " # Ignore Thumbs.db files in state comparison",
"lineNumber": 602
},
{
"text": " if Path(entry.get(\"path\", \"\")).name.lower() == \"thumbs.db\":",
"lineNumber": 603
},
{
"text": " continue",
"lineNumber": 604
},
{
"text": " mtime_ns = entry[\"mtime_ns\"]",
"lineNumber": 605
},
{
"text": " if is_windows:",
"lineNumber": 606
},
{
"text": " mtime_ns = (mtime_ns // 100) * 100",
"lineNumber": 607
},
{
"text": " normalized[\"files\"].append({",
"lineNumber": 608
},
{
"text": " \"path\": entry[\"path\"],",
"lineNumber": 609
},
{
"text": " \"size\": entry[\"size\"],",
"lineNumber": 610
},
{
"text": " \"mtime_ns\": mtime_ns,",
"lineNumber": 611
},
{
"text": " })",
"lineNumber": 612
},
{
"text": " return normalized",
"lineNumber": 613
},
{
"text": " ",
"lineNumber": 614
},
{
"text": " # Compare normalized states (Thumbs.db already filtered out)",
"lineNumber": 615
},
{
"text": " normalized_seq = normalize_state(seq_state)",
"lineNumber": 616
},
{
"text": " normalized_stored = normalize_state(stored_state)",
"lineNumber": 617
},
{
"text": " ",
"lineNumber": 618
},
{
"text": " if normalized_seq == normalized_stored:",
"lineNumber": 619
},
{
"text": " return False",
"lineNumber": 620
},
{
"text": " ",
"lineNumber": 621
},
{
"text": " # States differ - log diagnostic info if verbose",
"lineNumber": 622
},
{
"text": " if verbose:",
"lineNumber": 623
}
]
},
"score": 0.09323669970035553
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\remove_action_fake_users.bat",
"range": {
"startPosition": {},
"endPosition": {
"line": 66
}
},
"contents": "@echo off\nsetlocal enabledelayedexpansion\n\necho Starting fake user removal for actions...\n\nREM Check if files were dragged onto the batch file\nif \"%~1\"==\"\" (\n\techo.\n\techo Usage: Drag .blend files onto this batch file to remove fake users from actions.\n\techo Output will be saved to the \\output folder.\n\techo.\n\tpause\n\texit /b 1\n)\n\nREM Create output directory if it doesn't exist\nif not exist \"output\" mkdir \"output\"\n\nREM Initialize counters and tracking\nset \"processed=0\"\nset \"crashed=0\"\nset \"skipped=0\"\nset \"deleted_similar=0\"\nset \"threshold_percent=10\"\nset \"updated_total=0\"\n\nREM Create a temporary Python script for processing\nset \"TEMP_SCRIPT=remove_action_fake_users_temp.py\"\necho Creating Python script: !TEMP_SCRIPT!\n\n(\necho import bpy\necho import os\necho import sys\necho.\necho # Create output directory if it doesn't exist\necho if not os.path.exists^(\"output\"^):\necho \tos.makedirs^(\"output\"^)\necho.\necho # Get command line arguments ^(the dragged files^)\necho blend_files = sys.argv[sys.argv.index^(\"--\"^) + 1:] if \"--\" in sys.argv else []\necho.\necho print^(\"Found \" + str^(len^(blend_files^)^) + \" .blend files to process\"^)\necho.\necho for blend_file in blend_files:\necho ^\tif blend_file.lower^(^).endswith^(\".blend\"^):\necho ^\t\ttry:\necho ^\t\t\t# Create output path in output folder\necho ^\t\t\tfilename = os.path.basename^(blend_file^)\necho ^\t\t\toutput_file = os.path.join^(\"output\", filename^)\necho ^\t\t\t# Check if output file already exists\necho ^\t\t\tif os.path.exists^(output_file^):\necho ^\t\t\t\tprint^(\"SKIP_EXISTING:\" + blend_file^)\necho ^\t\t\t\tcontinue\necho ^\t\t\tprint^(\"PROCESSING:\" + blend_file^)\necho ^\t\t\t# Load the blend file\necho ^\t\t\tbpy.ops.wm.open_mainfile^(filepath=blend_file^)\necho ^\t\t\t# Remove fake users from all actions\necho ^\t\t\tchanged = 0\necho ^\t\t\tfor action in bpy.data.actions:\necho ^\t\t\t\tif getattr^(action, \"use_fake_user\", False^):\necho ^\t\t\t\t\taction.use_fake_user = False\necho ^\t\t\t\t\tchanged += 1\necho ^\t\t\tprint^(\"UPDATED:\" + blend_file + \":\" + str^(changed^)^)\necho ^\t\t\t# Save to output folder\necho ^\t\t\tbpy.ops.wm.save_mainfile^(filepath=output_file, compress=True^)",
"signatures": {},
"detailedLines": [
{
"text": "@echo off",
"lineNumber": 1
},
{
"text": "setlocal enabledelayedexpansion",
"lineNumber": 2
},
{
"lineNumber": 3
},
{
"text": "echo Starting fake user removal for actions...",
"lineNumber": 4
},
{
"lineNumber": 5
},
{
"text": "REM Check if files were dragged onto the batch file",
"lineNumber": 6
},
{
"text": "if \"%~1\"==\"\" (",
"lineNumber": 7
},
{
"text": "\techo.",
"lineNumber": 8
},
{
"text": "\techo Usage: Drag .blend files onto this batch file to remove fake users from actions.",
"lineNumber": 9
},
{
"text": "\techo Output will be saved to the \\output folder.",
"lineNumber": 10
},
{
"text": "\techo.",
"lineNumber": 11
},
{
"text": "\tpause",
"lineNumber": 12
},
{
"text": "\texit /b 1",
"lineNumber": 13
},
{
"text": ")",
"lineNumber": 14
},
{
"lineNumber": 15
},
{
"text": "REM Create output directory if it doesn't exist",
"lineNumber": 16
},
{
"text": "if not exist \"output\" mkdir \"output\"",
"lineNumber": 17
},
{
"lineNumber": 18
},
{
"text": "REM Initialize counters and tracking",
"lineNumber": 19
},
{
"text": "set \"processed=0\"",
"lineNumber": 20
},
{
"text": "set \"crashed=0\"",
"lineNumber": 21
},
{
"text": "set \"skipped=0\"",
"lineNumber": 22
},
{
"text": "set \"deleted_similar=0\"",
"lineNumber": 23
},
{
"text": "set \"threshold_percent=10\"",
"lineNumber": 24
},
{
"text": "set \"updated_total=0\"",
"lineNumber": 25
},
{
"lineNumber": 26
},
{
"text": "REM Create a temporary Python script for processing",
"lineNumber": 27
},
{
"text": "set \"TEMP_SCRIPT=remove_action_fake_users_temp.py\"",
"lineNumber": 28
},
{
"text": "echo Creating Python script: !TEMP_SCRIPT!",
"lineNumber": 29
},
{
"lineNumber": 30
},
{
"text": "(",
"lineNumber": 31
},
{
"text": "echo import bpy",
"lineNumber": 32
},
{
"text": "echo import os",
"lineNumber": 33
},
{
"text": "echo import sys",
"lineNumber": 34
},
{
"text": "echo.",
"lineNumber": 35
},
{
"text": "echo # Create output directory if it doesn't exist",
"lineNumber": 36
},
{
"text": "echo if not os.path.exists^(\"output\"^):",
"lineNumber": 37
},
{
"text": "echo \tos.makedirs^(\"output\"^)",
"lineNumber": 38
},
{
"text": "echo.",
"lineNumber": 39
},
{
"text": "echo # Get command line arguments ^(the dragged files^)",
"lineNumber": 40
},
{
"text": "echo blend_files = sys.argv[sys.argv.index^(\"--\"^) + 1:] if \"--\" in sys.argv else []",
"lineNumber": 41
},
{
"text": "echo.",
"lineNumber": 42
},
{
"text": "echo print^(\"Found \" + str^(len^(blend_files^)^) + \" .blend files to process\"^)",
"lineNumber": 43
},
{
"text": "echo.",
"lineNumber": 44
},
{
"text": "echo for blend_file in blend_files:",
"lineNumber": 45
},
{
"text": "echo ^\tif blend_file.lower^(^).endswith^(\".blend\"^):",
"lineNumber": 46
},
{
"text": "echo ^\t\ttry:",
"lineNumber": 47
},
{
"text": "echo ^\t\t\t# Create output path in output folder",
"lineNumber": 48
},
{
"text": "echo ^\t\t\tfilename = os.path.basename^(blend_file^)",
"lineNumber": 49
},
{
"text": "echo ^\t\t\toutput_file = os.path.join^(\"output\", filename^)",
"lineNumber": 50
},
{
"text": "echo ^\t\t\t# Check if output file already exists",
"lineNumber": 51
},
{
"text": "echo ^\t\t\tif os.path.exists^(output_file^):",
"lineNumber": 52
},
{
"text": "echo ^\t\t\t\tprint^(\"SKIP_EXISTING:\" + blend_file^)",
"lineNumber": 53
},
{
"text": "echo ^\t\t\t\tcontinue",
"lineNumber": 54
},
{
"text": "echo ^\t\t\tprint^(\"PROCESSING:\" + blend_file^)",
"lineNumber": 55
},
{
"text": "echo ^\t\t\t# Load the blend file",
"lineNumber": 56
},
{
"text": "echo ^\t\t\tbpy.ops.wm.open_mainfile^(filepath=blend_file^)",
"lineNumber": 57
},
{
"text": "echo ^\t\t\t# Remove fake users from all actions",
"lineNumber": 58
},
{
"text": "echo ^\t\t\tchanged = 0",
"lineNumber": 59
},
{
"text": "echo ^\t\t\tfor action in bpy.data.actions:",
"lineNumber": 60
},
{
"text": "echo ^\t\t\t\tif getattr^(action, \"use_fake_user\", False^):",
"lineNumber": 61
},
{
"text": "echo ^\t\t\t\t\taction.use_fake_user = False",
"lineNumber": 62
},
{
"text": "echo ^\t\t\t\t\tchanged += 1",
"lineNumber": 63
},
{
"text": "echo ^\t\t\tprint^(\"UPDATED:\" + blend_file + \":\" + str^(changed^)^)",
"lineNumber": 64
},
{
"text": "echo ^\t\t\t# Save to output folder",
"lineNumber": 65
},
{
"text": "echo ^\t\t\tbpy.ops.wm.save_mainfile^(filepath=output_file, compress=True^)",
"lineNumber": 66
}
]
},
"score": 0.09131913632154465
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\config.json",
"range": {
"startPosition": {},
"endPosition": {
"line": 6,
"column": 1
}
},
"contents": "{\n \"dailyFormat\": \"YYYY-MM-DD\",\n \"structDir\": \"A:\\\\1 Amazon_Active_Projects\\\\3 ProjectStructure\",\n \"zipper\": \"7z\",\n \"compression\": 0,\n \"Max7zInst\": 0\n}",
"signatures": {},
"detailedLines": [
{
"text": "{",
"lineNumber": 1
},
{
"text": " \"dailyFormat\": \"YYYY-MM-DD\",",
"lineNumber": 2
},
{
"text": " \"structDir\": \"A:\\\\1 Amazon_Active_Projects\\\\3 ProjectStructure\",",
"lineNumber": 3
},
{
"text": " \"zipper\": \"7z\",",
"lineNumber": 4
},
{
"text": " \"compression\": 0,",
"lineNumber": 5
},
{
"text": " \"Max7zInst\": 0",
"lineNumber": 6
},
{
"text": "}",
"lineNumber": 7
}
]
},
"score": 0.08737760037183762
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\NewProject.bat",
"range": {
"startPosition": {
"line": 26
},
"endPosition": {
"line": 88
}
},
"contents": "for /f \"tokens=2-4 delims=/ \" %%a in ('date /t') do (\n set mm=%%a\n set dd=%%b\n set yy=%%c\n)\nset yyyy=20%yy:~-2%\nset yymmdd=%yy:~-2%%mm%%dd%\n\n:: Ask for project name\nset /p projectName=\"Enter project name (press Enter for default 'NewProject'): \"\nif \"%projectName%\"==\"\" set projectName=NewProject\nset projectRoot=%yymmdd%_%projectName%\n\n:: Create main project directory\nmkdir \"%projectRoot%\"\n\n:: Create Assets structure\nmkdir \"%projectRoot%\\Assets\\ElevenLabs\"\nif exist \"%STRUCT_DIR%\\NewDaily.bat\" copy /Y \"%STRUCT_DIR%\\NewDaily.bat\" \"%projectRoot%\\Assets\\ElevenLabs\\NewDaily.bat\" >nul\nmkdir \"%projectRoot%\\Assets\\Blends\"\nmkdir \"%projectRoot%\\Assets\\Mocap\"\nmkdir \"%projectRoot%\\Assets\\VO\"\nif exist \"%~dp0NewDaily.bat\" copy /Y \"%~dp0NewDaily.bat\" \"%projectRoot%\\Assets\\VO\\NewDaily.bat\" >nul\n\n:: Create Blends structure\nmkdir \"%projectRoot%\\Blends\\animations\\\"\nmkdir \"%projectRoot%\\Blends\\stills\\img-BG\"\n\n:: Create Deliverable structure\nmkdir \"%projectRoot%\\Deliverable\\\"\n\n:: Create Pr structure\nmkdir \"%projectRoot%\\Pr\\RnR\\RIFE\"\n\n:: Add project root additions\nif not exist \"%projectRoot%\\Renders\" mkdir \"%projectRoot%\\Renders\"\n\n:: Place helper scripts into Renders\nset \"templateRoot=%STRUCT_DIR%\"\nfor %%F in (UpdateSequences.bat ZipSeqArchv.bat UnzipSeqArchv.bat ConfigLoader.ps1 config.json) do (\n if exist \"%templateRoot%\\%%F\" copy /Y \"%templateRoot%\\%%F\" \"%projectRoot%\\Renders\\%%F\" >nul\n)\n\n:: Use repo-provided templates for git config files\nif exist \"%~dp0components\\gitignore\" copy /Y \"%~dp0components\\gitignore\" \"%projectRoot%\\.gitignore\" >nul\nif exist \"%~dp0components\\gitattributes\" copy /Y \"%~dp0components\\gitattributes\" \"%projectRoot%\\.gitattributes\" >nul\n\n:: Initialize git and install Git LFS\npushd \"%projectRoot%\" >nul\ngit init\ngit lfs install\ngit add . -v\ngit commit -m \"init\"\npopd >nul\n\n:: Deploy config workflow using ConfigLoader.ps1\necho.\necho Deploying config workflow...\nfor %%P in (\"%projectRoot%\") do set \"PROJECT_ROOT_ABS=%%~fP\"\npowershell -NoProfile -ExecutionPolicy Bypass -Command \"& '%CONFIG_LOADER%' -ProjectPath '%PROJECT_ROOT_ABS%'\"\nif errorlevel 1 (\n echo [WARNING] Config workflow deployment failed. You may need to run ConfigLoader.ps1 manually.",
"signatures": {},
"detailedLines": [
{
"text": "for /f \"tokens=2-4 delims=/ \" %%a in ('date /t') do (",
"lineNumber": 27
},
{
"text": " set mm=%%a",
"lineNumber": 28
},
{
"text": " set dd=%%b",
"lineNumber": 29
},
{
"text": " set yy=%%c",
"lineNumber": 30
},
{
"text": ")",
"lineNumber": 31
},
{
"text": "set yyyy=20%yy:~-2%",
"lineNumber": 32
},
{
"text": "set yymmdd=%yy:~-2%%mm%%dd%",
"lineNumber": 33
},
{
"lineNumber": 34
},
{
"text": ":: Ask for project name",
"lineNumber": 35
},
{
"text": "set /p projectName=\"Enter project name (press Enter for default 'NewProject'): \"",
"lineNumber": 36
},
{
"text": "if \"%projectName%\"==\"\" set projectName=NewProject",
"lineNumber": 37
},
{
"text": "set projectRoot=%yymmdd%_%projectName%",
"lineNumber": 38
},
{
"lineNumber": 39
},
{
"text": ":: Create main project directory",
"lineNumber": 40
},
{
"text": "mkdir \"%projectRoot%\"",
"lineNumber": 41
},
{
"lineNumber": 42
},
{
"text": ":: Create Assets structure",
"lineNumber": 43
},
{
"text": "mkdir \"%projectRoot%\\Assets\\ElevenLabs\"",
"lineNumber": 44
},
{
"text": "if exist \"%STRUCT_DIR%\\NewDaily.bat\" copy /Y \"%STRUCT_DIR%\\NewDaily.bat\" \"%projectRoot%\\Assets\\ElevenLabs\\NewDaily.bat\" >nul",
"lineNumber": 45
},
{
"text": "mkdir \"%projectRoot%\\Assets\\Blends\"",
"lineNumber": 46
},
{
"text": "mkdir \"%projectRoot%\\Assets\\Mocap\"",
"lineNumber": 47
},
{
"text": "mkdir \"%projectRoot%\\Assets\\VO\"",
"lineNumber": 48
},
{
"text": "if exist \"%~dp0NewDaily.bat\" copy /Y \"%~dp0NewDaily.bat\" \"%projectRoot%\\Assets\\VO\\NewDaily.bat\" >nul",
"lineNumber": 49
},
{
"lineNumber": 50
},
{
"text": ":: Create Blends structure",
"lineNumber": 51
},
{
"text": "mkdir \"%projectRoot%\\Blends\\animations\\\"",
"lineNumber": 52
},
{
"text": "mkdir \"%projectRoot%\\Blends\\stills\\img-BG\"",
"lineNumber": 53
},
{
"lineNumber": 54
},
{
"text": ":: Create Deliverable structure",
"lineNumber": 55
},
{
"text": "mkdir \"%projectRoot%\\Deliverable\\\"",
"lineNumber": 56
},
{
"lineNumber": 57
},
{
"text": ":: Create Pr structure",
"lineNumber": 58
},
{
"text": "mkdir \"%projectRoot%\\Pr\\RnR\\RIFE\"",
"lineNumber": 59
},
{
"lineNumber": 60
},
{
"text": ":: Add project root additions",
"lineNumber": 61
},
{
"text": "if not exist \"%projectRoot%\\Renders\" mkdir \"%projectRoot%\\Renders\"",
"lineNumber": 62
},
{
"lineNumber": 63
},
{
"text": ":: Place helper scripts into Renders",
"lineNumber": 64
},
{
"text": "set \"templateRoot=%STRUCT_DIR%\"",
"lineNumber": 65
},
{
"text": "for %%F in (UpdateSequences.bat ZipSeqArchv.bat UnzipSeqArchv.bat ConfigLoader.ps1 config.json) do (",
"lineNumber": 66
},
{
"text": " if exist \"%templateRoot%\\%%F\" copy /Y \"%templateRoot%\\%%F\" \"%projectRoot%\\Renders\\%%F\" >nul",
"lineNumber": 67
},
{
"text": ")",
"lineNumber": 68
},
{
"lineNumber": 69
},
{
"text": ":: Use repo-provided templates for git config files",
"lineNumber": 70
},
{
"text": "if exist \"%~dp0components\\gitignore\" copy /Y \"%~dp0components\\gitignore\" \"%projectRoot%\\.gitignore\" >nul",
"lineNumber": 71
},
{
"text": "if exist \"%~dp0components\\gitattributes\" copy /Y \"%~dp0components\\gitattributes\" \"%projectRoot%\\.gitattributes\" >nul",
"lineNumber": 72
},
{
"lineNumber": 73
},
{
"text": ":: Initialize git and install Git LFS",
"lineNumber": 74
},
{
"text": "pushd \"%projectRoot%\" >nul",
"lineNumber": 75
},
{
"text": "git init",
"lineNumber": 76
},
{
"text": "git lfs install",
"lineNumber": 77
},
{
"text": "git add . -v",
"lineNumber": 78
},
{
"text": "git commit -m \"init\"",
"lineNumber": 79
},
{
"text": "popd >nul",
"lineNumber": 80
},
{
"lineNumber": 81
},
{
"text": ":: Deploy config workflow using ConfigLoader.ps1",
"lineNumber": 82
},
{
"text": "echo.",
"lineNumber": 83
},
{
"text": "echo Deploying config workflow...",
"lineNumber": 84
},
{
"text": "for %%P in (\"%projectRoot%\") do set \"PROJECT_ROOT_ABS=%%~fP\"",
"lineNumber": 85
},
{
"text": "powershell -NoProfile -ExecutionPolicy Bypass -Command \"& '%CONFIG_LOADER%' -ProjectPath '%PROJECT_ROOT_ABS%'\"",
"lineNumber": 86
},
{
"text": "if errorlevel 1 (",
"lineNumber": 87
},
{
"text": " echo [WARNING] Config workflow deployment failed. You may need to run ConfigLoader.ps1 manually.",
"lineNumber": 88
}
]
},
"score": 0.08714190125465393
}
]
}
Status: completed
Tool use: **read_file_v2** • Read file: config.json
Tool use: **ripgrep_raw_search**
Parameters:
{
"pattern": "FlatColor",
"caseInsensitive": true
}
Result:
{
"success": {
"pattern": "FlatColor",
"outputMode": "content",
"workspaceResults": {
"A:\\1 Amazon_Active_Projects\\3 ProjectStructure": {
"content": {
"matches": [
{
"file": "organize_textures.ps1",
"matches": [
{
"lineNumber": 353,
"content": "# Collect FlatColors files separately (including those in \\common\\FlatColors folders, but not from root \\common\\FlatColors)"
},
{
"lineNumber": 354,
"content": "Write-Host \"Collecting FlatColors files...\" -ForegroundColor Yellow"
},
{
"lineNumber": 355,
"content": "$rootCommonFlatColorsPath = Join-Path -Path $textureFolderPath -ChildPath \"common\\FlatColors\""
},
{
"lineNumber": 356,
"content": "$allFlatColorsFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object {"
},
{
"lineNumber": 357,
"content": " ($_.FullName -like \"*\\FlatColors\\*\" -or $_.Name -like \"*FlatColors*\") -and"
},
{
"lineNumber": 358,
"content": " $_.FullName -notlike \"$([regex]::Escape($rootCommonFlatColorsPath))\\*\""
},
{
"lineNumber": 361,
"content": "# Get all remaining files (excluding all \\common folders, but we'll handle FlatColors separately)"
},
{
"lineNumber": 376,
"content": " # Separate FlatColors files from other files before processing"
},
{
"lineNumber": 377,
"content": " Write-Host \"Identifying FlatColors files...\" -ForegroundColor Yellow"
},
{
"lineNumber": 378,
"content": " $flatColorsFiles = $allFlatColorsFiles | Where-Object { (Test-Path -Path $_.FullName) }"
},
{
"lineNumber": 379,
"content": " $nonFlatColorsFiles = $remainingFiles | Where-Object { $_.Name -notlike \"*FlatColors*\" }"
},
{
"lineNumber": 381,
"content": " Write-Host \"Found $($flatColorsFiles.Count) FlatColors file(s) (including from \\common\\FlatColors folders), $($nonFlatColorsFiles.Count) other file(s)\" -ForegroundColor Gray"
},
{
"lineNumber": 383,
"content": " # Group non-FlatColors files by checksum"
},
{
"lineNumber": 385,
"content": " $nonFlatColorsWithChecksums = $filesWithChecksums | Where-Object { $_.File.Name -notlike \"*FlatColors*\" }"
},
{
"lineNumber": 386,
"content": " $groupedByChecksum = $nonFlatColorsWithChecksums | Group-Object -Property Hash"
},
{
"lineNumber": 401,
"content": " # Process each checksum group (excluding FlatColors)"
},
{
"lineNumber": 422,
"content": " # Process FlatColors files: merge duplicates and move to \\common\\FlatColors"
},
{
"lineNumber": 423,
"content": " Write-Host \"Processing FlatColors files (merging duplicates)...\" -ForegroundColor Yellow"
},
{
"lineNumber": 425,
"content": " if ($null -ne $flatColorsFiles -and $flatColorsFiles.Count -gt 0) {"
},
{
"lineNumber": 426,
"content": " Write-Host \"Found $($flatColorsFiles.Count) FlatColors file(s) to process\" -ForegroundColor Gray"
},
{
"lineNumber": 428,
"content": " # Calculate checksums for FlatColors files"
},
{
"lineNumber": 429,
"content": " Write-Host \"Calculating checksums for FlatColors files...\" -ForegroundColor Yellow"
},
{
"lineNumber": 430,
"content": " $flatColorsWithChecksums = Get-FilesWithChecksums -Files $flatColorsFiles"
},
{
"lineNumber": 433,
"content": " $flatColorsGroupedByChecksum = $flatColorsWithChecksums | Group-Object -Property Hash"
},
{
"lineNumber": 435,
"content": " Write-Host \"Found $($flatColorsGroupedByChecksum.Count) unique FlatColors file(s)\" -ForegroundColor Gray"
},
{
"lineNumber": 437,
"content": " # Create \\textures\\common\\FlatColors directory"
},
{
"lineNumber": 438,
"content": " $flatColorsPath = Join-Path -Path $rootCommonPath -ChildPath \"FlatColors\""
},
{
"lineNumber": 439,
"content": " if (-not (Test-Path -Path $flatColorsPath -PathType Container)) {"
},
{
"lineNumber": 440,
"content": " New-Item -ItemType Directory -Path $flatColorsPath | Out-Null"
},
{
"lineNumber": 441,
"content": " Write-Host \"Created directory: $flatColorsPath\" -ForegroundColor Green"
},
{
"lineNumber": 444,
"content": " # Track filenames already in \\common\\FlatColors"
},
{
"lineNumber": 445,
"content": " $filesInFlatColors = @{}"
},
{
"lineNumber": 446,
"content": " $flatColorsMoved = 0"
},
{
"lineNumber": 447,
"content": " $flatColorsDuplicates = 0"
},
{
"lineNumber": 448,
"content": " $flatColorsMoveLog = [System.Collections.ArrayList]::new()"
},
{
"lineNumber": 450,
"content": " foreach ($group in $flatColorsGroupedByChecksum) {"
},
{
"lineNumber": 454,
"content": " # Single file - move to FlatColors folder"
},
{
"lineNumber": 464,
"content": " $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $fileName"
},
{
"lineNumber": 467,
"content": " if ($filesInFlatColors.ContainsKey($fileName) -or (Test-Path -Path $destinationPath)) {"
},
{
"lineNumber": 473,
"content": " $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $newFileName"
},
{
"lineNumber": 475,
"content": " } while ($filesInFlatColors.ContainsKey($newFileName) -or (Test-Path -Path $destinationPath))"
},
{
"lineNumber": 482,
"content": " $filesInFlatColors[$fileName] = $true"
},
{
"lineNumber": 483,
"content": " $flatColorsMoved++"
},
{
"lineNumber": 488,
"content": " $null = $flatColorsMoveLog.Add([PSCustomObject]@{"
},
{
"lineNumber": 494,
"content": " Write-Warning \"Failed to move FlatColors file: $($fileObj.FullName) - $($_.Exception.Message)\""
},
{
"lineNumber": 499,
"content": " $result = Process-DuplicateGroup -Files $files -CommonPath $flatColorsPath -FilesInCommon $filesInFlatColors -StripPrefix -ValidPrefixes $validBlendfilePrefixes -MoveLog $flatColorsMoveLog"
},
{
"lineNumber": 500,
"content": " $flatColorsMoved += $result.MovedCount"
},
{
"lineNumber": 501,
"content": " $flatColorsDuplicates += $result.DuplicateCount"
},
{
"lineNumber": 505,
"content": " Write-Host \"Moved $flatColorsMoved unique FlatColors file(s) to \\common\\FlatColors, deleted $flatColorsDuplicates duplicate(s)\" -ForegroundColor Green"
},
{
"lineNumber": 507,
"content": " Write-Host \"No FlatColors files found to process.\" -ForegroundColor Gray"
},
{
"lineNumber": 528,
"content": "if ($null -ne $flatColorsMoveLog -and $flatColorsMoveLog.Count -gt 0) {"
},
{
"lineNumber": 529,
"content": " $allMoves += $flatColorsMoveLog"
}
]
},
{
"file": ".specstory/history/2025-12-19_18-52Z-blend-file-path-prefix-logic.md",
"matches": [
{
"lineNumber": 8082,
"content": "@pwsh (357-1075) ah, let's have it move all FlatColors to the inter-blendfile \\common folder as well."
},
{
"lineNumber": 8089,
"content": "Updating Pass 2 to also move files containing \"FlatColors\" to the inter-blendfile `\\common` folder, even if they're not duplicates:"
},
{
"lineNumber": 8103,
"content": "Adding logic to move FlatColors files to the common folder after duplicate processing:"
},
{
"lineNumber": 8133,
"content": " # Also move all FlatColors files to \\common (even if they're unique)"
},
{
"lineNumber": 8134,
"content": " Write-Host \"Moving FlatColors files to \\common...\" -ForegroundColor Yellow"
},
{
"lineNumber": 8135,
"content": " $flatColorsFiles = $filesWithChecksums | Where-Object { $_.File.Name -like \"*FlatColors*\" }"
},
{
"lineNumber": 8137,
"content": " if ($null -ne $flatColorsFiles -and $flatColorsFiles.Count -gt 0) {"
},
{
"lineNumber": 8138,
"content": " foreach ($fileObj in $flatColorsFiles) {"
},
{
"lineNumber": 8169,
"content": " Write-Warning \"Failed to move FlatColors file: $($file.FullName) - $($_.Exception.Message)\""
},
{
"lineNumber": 8172,
"content": " Write-Host \"Moved $($flatColorsFiles.Count) FlatColors file(s) to \\common\" -ForegroundColor Green"
},
{
"lineNumber": 8229,
"content": " Write-Warning \"Failed to move FlatColors file: $($file.FullName) - $($_.Exception.Message)\""
},
{
"lineNumber": 8250,
"content": " # Also move all FlatColors files to \\common (even if they're unique)"
},
{
"lineNumber": 8251,
"content": " Write-Host \"Moving FlatColors files to \\common...\" -ForegroundColor Yellow"
},
{
"lineNumber": 8252,
"content": " $flatColorsFiles = $filesWithChecksums | Where-Object { $_.File.Name -like \"*FlatColors*\" -and (Test-Path -Path $_.File.FullName) }"
},
{
"lineNumber": 8254,
"content": " if ($null -ne $flatColorsFiles -and $flatColorsFiles.Count -gt 0) {"
},
{
"lineNumber": 8255,
"content": " foreach ($fileObj in $flatColorsFiles) {"
},
{
"lineNumber": 8267,
"content": "Updated Pass 2 to also move all files containing \"FlatColors\" in their name to the inter-blendfile `\\common` folder, even if they're unique (not duplicates). The changes:"
},
{
"lineNumber": 8269,
"content": "1. **Added FlatColors processing** - After processing duplicate groups, the script now finds all files with \"FlatColors\" in their name"
},
{
"lineNumber": 8270,
"content": "2. **Strips blendfile prefixes** - FlatColors files also have their blendfile prefixes stripped (e.g., \"Demarco_FlatColors.jpg\" → \"FlatColors.jpg\")"
},
{
"lineNumber": 8271,
"content": "3. **Handles name conflicts** - If multiple FlatColors files would have the same name after prefix stripping, they get numbered suffixes"
},
{
"lineNumber": 8272,
"content": "4. **Checks file existence** - Only processes FlatColors files that still exist at their original location (in case they were already moved during duplicate processing)"
},
{
"lineNumber": 8274,
"content": "When you run the script, all FlatColors files will be moved to `\\textures\\common` along with the duplicate files, with blendfile prefixes stripped."
},
{
"lineNumber": 8280,
"content": "@pwsh (995-1075) it didn't add a `\\\\textures\\common\\FlatColors` folder and it didn't move any of the FlatColors there."
},
{
"lineNumber": 8287,
"content": "Updating the code to create a `\\textures\\common\\FlatColors` subfolder and move FlatColors files there:"
},
{
"lineNumber": 8301,
"content": "Updating the code to create a `\\textures\\common\\FlatColors` subfolder and move FlatColors files there:"
},
{
"lineNumber": 8311,
"content": " # Also move all FlatColors files to \\common\\FlatColors (even if they're unique)"
},
{
"lineNumber": 8312,
"content": " Write-Host \"Moving FlatColors files to \\common\\FlatColors...\" -ForegroundColor Yellow"
},
{
"lineNumber": 8313,
"content": " $flatColorsFiles = $filesWithChecksums | Where-Object { $_.File.Name -like \"*FlatColors*\" -and (Test-Path -Path $_.File.FullName) }"
},
{
"lineNumber": 8315,
"content": " if ($null -ne $flatColorsFiles -and $flatColorsFiles.Count -gt 0) {"
},
{
"lineNumber": 8316,
"content": " # Create \\textures\\common\\FlatColors directory"
},
{
"lineNumber": 8317,
"content": " $flatColorsPath = Join-Path -Path $rootCommonPath -ChildPath \"FlatColors\""
},
{
"lineNumber": 8318,
"content": " if (-not (Test-Path -Path $flatColorsPath -PathType Container)) {"
},
{
"lineNumber": 8319,
"content": " New-Item -ItemType Directory -Path $flatColorsPath | Out-Null"
},
{
"lineNumber": 8320,
"content": " Write-Host \"Created directory: $flatColorsPath\" -ForegroundColor Green"
},
{
"lineNumber": 8323,
"content": " # Track filenames already in \\common\\FlatColors"
},
{
"lineNumber": 8324,
"content": " $filesInFlatColors = @{}"
},
{
"lineNumber": 8326,
"content": " foreach ($fileObj in $flatColorsFiles) {"
},
{
"lineNumber": 8336,
"content": " $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $fileName"
},
{
"lineNumber": 8339,
"content": " if ($filesInFlatColors.ContainsKey($fileName)) {"
},
{
"lineNumber": 8345,
"content": " $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $newFileName"
},
{
"lineNumber": 8347,
"content": " } while ($filesInFlatColors.ContainsKey($newFileName) -or (Test-Path -Path $destinationPath))"
},
{
"lineNumber": 8354,
"content": " $filesInFlatColors[$fileName] = $true"
},
{
"lineNumber": 8357,
"content": " Write-Warning \"Failed to move FlatColors file: $($file.FullName) - $($_.Exception.Message)\""
},
{
"lineNumber": 8360,
"content": " Write-Host \"Moved $($flatColorsFiles.Count) FlatColors file(s) to \\common\\FlatColors\" -ForegroundColor Green"
},
{
"lineNumber": 8373,
"content": "1. **Create `\\textures\\common\\FlatColors` subfolder** - Creates the directory if it doesn't exist"
},
{
"lineNumber": 8374,
"content": "2. **Use separate tracking** - Uses `$filesInFlatColors` hashtable to track files in the FlatColors folder (separate from the root common folder)"
},
{
"lineNumber": 8375,
"content": "3. **Update destination paths** - All FlatColors files are moved to `\\textures\\common\\FlatColors` instead of directly to `\\textures\\common`"
},
{
"lineNumber": 8379,
"content": "- Create the `\\textures\\common\\FlatColors` folder if it doesn't exist"
},
{
"lineNumber": 8380,
"content": "- Move all files containing \"FlatColors\" in their name to that subfolder"
},
{
"lineNumber": 8381,
"content": "- Strip blendfile prefixes from FlatColors filenames"
},
{
"lineNumber": 8382,
"content": "- Handle name conflicts within the FlatColors folder"
},
{
"lineNumber": 8384,
"content": "The FlatColors files will be organized in their own subfolder within the common directory."
},
{
"lineNumber": 8390,
"content": "@pwsh (356-1075) i still see no FlatColors folder in \\\\textures\\common"
},
{
"lineNumber": 8397,
"content": "Checking why FlatColors files aren't being found. The filter may be running after they're already moved, or the pattern isn't matching. Reviewing the code and adding debug output:"
},
{
"lineNumber": 8421,
"content": " # Also move all FlatColors files to \\common\\FlatColors (even if they're unique)"
},
{
"lineNumber": 8422,
"content": " Write-Host \"Moving FlatColors files to \\common\\FlatColors...\" -ForegroundColor Yellow"
},
{
"lineNumber": 8423,
"content": " # Check remainingFiles directly to find FlatColors files that haven't been moved yet"
},
{
"lineNumber": 8424,
"content": " $flatColorsFiles = $remainingFiles | Where-Object { $_.Name -like \"*FlatColors*\" -and (Test-Path -Path $_.FullName) }"
},
{
"lineNumber": 8458,
"content": " # Track filenames already in \\common\\FlatColors"
},
{
"lineNumber": 8459,
"content": " $filesInFlatColors = @{}"
},
{
"lineNumber": 8461,
"content": " foreach ($file in $flatColorsFiles) {"
},
{
"lineNumber": 8474,
"content": "1. **Check `$remainingFiles` directly** - This is the original file list before any processing, so it includes all FlatColors files that haven't been moved yet"
},
{
"lineNumber": 8478,
"content": "- Find all FlatColors files from the original remaining files list"
},
{
"lineNumber": 8479,
"content": "- Create the `\\textures\\common\\FlatColors` folder"
},
{
"lineNumber": 8480,
"content": "- Move all FlatColors files there, stripping blendfile prefixes as needed"
},
{
"lineNumber": 8482,
"content": "When you run the script, it should create the FlatColors folder and move the files there."
},
{
"lineNumber": 8488,
"content": "@pwsh (1-698) still no FlatColors relocation."
},
{
"lineNumber": 8495,
"content": "Adding debug output to see why FlatColors files aren't being found. Checking if they're being excluded or already moved:"
},
{
"lineNumber": 8509,
"content": "FlatColors files may have already been moved during duplicate processing. Checking for them before duplicate processing and handling them separately. Updating the code:"
},
{
"lineNumber": 8523,
"content": "Restructuring to handle FlatColors files before duplicate processing and exclude them from the duplicate loop:"
},
{
"lineNumber": 8533,
"content": " # Separate FlatColors files from other files before processing"
},
{
"lineNumber": 8534,
"content": " Write-Host \"Identifying FlatColors files...\" -ForegroundColor Yellow"
},
{
"lineNumber": 8535,
"content": " $flatColorsFiles = $remainingFiles | Where-Object { $_.Name -like \"*FlatColors*\" }"
},
{
"lineNumber": 8536,
"content": " $nonFlatColorsFiles = $remainingFiles | Where-Object { $_.Name -notlike \"*FlatColors*\" }"
},
{
"lineNumber": 8538,
"content": " Write-Host \"Found $($flatColorsFiles.Count) FlatColors file(s), $($nonFlatColorsFiles.Count) other file(s)\" -ForegroundColor Gray"
},
{
"lineNumber": 8540,
"content": " # Group non-FlatColors files by checksum"
},
{
"lineNumber": 8542,
"content": " $nonFlatColorsWithChecksums = $filesWithChecksums | Where-Object { $_.File.Name -notlike \"*FlatColors*\" }"
},
{
"lineNumber": 8543,
"content": " $groupedByChecksum = $nonFlatColorsWithChecksums | Group-Object -Property Hash"
},
{
"lineNumber": 8558,
"content": " # Process each checksum group (excluding FlatColors)"
},
{
"lineNumber": 8578,
"content": " # Move all FlatColors files to \\common\\FlatColors (even if they're unique)"
},
{
"lineNumber": 8579,
"content": " Write-Host \"Moving FlatColors files to \\common\\FlatColors...\" -ForegroundColor Yellow"
},
{
"lineNumber": 8589,
"content": "Updating the FlatColors processing to use the pre-filtered list:"
},
{
"lineNumber": 8603,
"content": "Adding debug output to see if FlatColors files are being found:"
},
{
"lineNumber": 8613,
"content": " # Move all FlatColors files to \\common\\FlatColors (even if they're unique)"
},
{
"lineNumber": 8614,
"content": " Write-Host \"Moving FlatColors files to \\common\\FlatColors...\" -ForegroundColor Yellow"
},
{
"lineNumber": 8616,
"content": " if ($null -ne $flatColorsFiles -and $flatColorsFiles.Count -gt 0) {"
},
{
"lineNumber": 8617,
"content": " Write-Host \"Found $($flatColorsFiles.Count) FlatColors file(s) to move\" -ForegroundColor Gray"
},
{
"lineNumber": 8627,
"content": "Adding an else clause to show when no FlatColors files are found:"
},
{
"lineNumber": 8638,
"content": " Write-Host \"Moved $($flatColorsFiles.Count) FlatColors file(s) to \\common\\FlatColors\" -ForegroundColor Green"
},
{
"lineNumber": 8640,
"content": " Write-Host \"No FlatColors files found to move.\" -ForegroundColor Gray"
},
{
"lineNumber": 8653,
"content": "1. **Identify FlatColors files first** - Separates them from other files before duplicate processing"
},
{
"lineNumber": 8654,
"content": "2. **Exclude from duplicate processing** - FlatColors files are filtered out of the checksum grouping so they aren't processed as duplicates"
},
{
"lineNumber": 8655,
"content": "3. **Add debug output** - Shows how many FlatColors files were found"
},
{
"lineNumber": 8656,
"content": "4. **Handle separately** - Moves all FlatColors files to `\\common\\FlatColors` regardless of whether they're duplicates"
},
{
"lineNumber": 8659,
"content": "- Find all FlatColors files before any duplicate processing"
},
{
"lineNumber": 8660,
"content": "- Process duplicates for non-FlatColors files"
},
{
"lineNumber": 8661,
"content": "- Then move all FlatColors files to `\\textures\\common\\FlatColors` with prefixes stripped"
},
{
"lineNumber": 8663,
"content": "When you run it, you should see messages indicating how many FlatColors files were found and moved."
},
{
"lineNumber": 8669,
"content": "@pwsh (353-1075) how did it find no FlatColors?"
},
{
"lineNumber": 8676,
"content": "The script matches filenames containing \"FlatColors\", but these files are in a `FlatColors` folder and named with hex codes (e.g., `#000000.png`). Updating the search to include files in a `FlatColors` folder path:"
},
{
"lineNumber": 8690,
"content": "FlatColors files are in `[blendfile]\\common\\FlatColors`, so they're excluded by the `$remainingFiles` filter that excludes `*\\common\\*`. Collecting FlatColors files separately, including those in common folders:"
},
{
"lineNumber": 8704,
"content": "Updating the code to collect FlatColors files from anywhere, including those in `\\common\\FlatColors` folders:"
},
{
"lineNumber": 8714,
"content": "# Collect FlatColors files separately (including those in \\common\\FlatColors folders)"
},
{
"lineNumber": 8715,
"content": "Write-Host \"Collecting FlatColors files...\" -ForegroundColor Yellow"
},
{
"lineNumber": 8716,
"content": "$allFlatColorsFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { $_.FullName -like \"*\\FlatColors\\*\" -or $_.Name -like \"*FlatColors*\" }"
},
{
"lineNumber": 8718,
"content": "# Get all remaining files (excluding all \\common folders, but we'll handle FlatColors separately)"
},
{
"lineNumber": 8733,
"content": " # Separate FlatColors files from other files before processing"
},
{
"lineNumber": 8734,
"content": " Write-Host \"Identifying FlatColors files...\" -ForegroundColor Yellow"
},
{
"lineNumber": 8735,
"content": " $flatColorsFiles = $allFlatColorsFiles | Where-Object { (Test-Path -Path $_.FullName) }"
},
{
"lineNumber": 8736,
"content": " $nonFlatColorsFiles = $remainingFiles | Where-Object { $_.Name -notlike \"*FlatColors*\" }"
},
{
"lineNumber": 8746,
"content": "Updating the debug output to show how many FlatColors files were found:"
},
{
"lineNumber": 8756,
"content": " # Separate FlatColors files from other files before processing"
},
{
"lineNumber": 8757,
"content": " Write-Host \"Identifying FlatColors files...\" -ForegroundColor Yellow"
},
{
"lineNumber": 8758,
"content": " $flatColorsFiles = $allFlatColorsFiles | Where-Object { (Test-Path -Path $_.FullName) }"
},
{
"lineNumber": 8759,
"content": " $nonFlatColorsFiles = $remainingFiles | Where-Object { $_.Name -notlike \"*FlatColors*\" }"
},
{
"lineNumber": 8761,
"content": " Write-Host \"Found $($flatColorsFiles.Count) FlatColors file(s) (including from \\common\\FlatColors folders), $($nonFlatColorsFiles.Count) other file(s)\" -ForegroundColor Gray"
},
{
"lineNumber": 8771,
"content": "Excluding files already in the root `\\textures\\common\\FlatColors` folder:"
},
{
"lineNumber": 8781,
"content": "# Collect FlatColors files separately (including those in \\common\\FlatColors folders, but not from root \\common\\FlatColors)"
},
{
"lineNumber": 8782,
"content": "Write-Host \"Collecting FlatColors files...\" -ForegroundColor Yellow"
},
{
"lineNumber": 8783,
"content": "$rootCommonFlatColorsPath = Join-Path -Path $textureFolderPath -ChildPath \"common\\FlatColors\""
},
{
"lineNumber": 8784,
"content": "$allFlatColorsFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object {"
},
{
"lineNumber": 8785,
"content": " ($_.FullName -like \"*\\FlatColors\\*\" -or $_.Name -like \"*FlatColors*\") -and"
},
{
"lineNumber": 8786,
"content": " $_.FullName -notlike \"$([regex]::Escape($rootCommonFlatColorsPath))\\*\""
},
{
"lineNumber": 8799,
"content": "1. **Collects FlatColors files separately** - Searches for files in any `\\FlatColors\\` folder or with \"FlatColors\" in their name"
},
{
"lineNumber": 8800,
"content": "2. **Excludes files already in the target** - Skips files already in `\\textures\\common\\FlatColors` to avoid moving files that are already in place"
},
{
"lineNumber": 8801,
"content": "3. **Includes files from blendfile common folders** - Finds FlatColors files in `[blendfile]\\common\\FlatColors` folders that were excluded from `$remainingFiles`"
},
{
"lineNumber": 8803,
"content": "When you run the script, it should find FlatColors files in folders like `Chan\\common\\FlatColors` and move them to `\\textures\\common\\FlatColors`. The debug output will show how many FlatColors files were found."
},
{
"lineNumber": 8809,
"content": "@pwsh (350-1075) Good. Duplicate FlatColors should be merged, too, no _1 or _2 suffixes."
},
{
"lineNumber": 8815,
"content": "Updating FlatColors processing to merge duplicates by checksum (keep one, delete the rest) instead of renaming with suffixes. Checking the current implementation:"
},
{
"lineNumber": 8840,
"content": "Updating FlatColors processing to calculate checksums, group duplicates, and merge them (keep one, delete the rest) before moving:"
},
{
"lineNumber": 8850,
"content": " # Process FlatColors files: merge duplicates and move to \\common\\FlatColors"
},
{
"lineNumber": 8851,
"content": " Write-Host \"Processing FlatColors files (merging duplicates)...\" -ForegroundColor Yellow"
},
{
"lineNumber": 8853,
"content": " if ($null -ne $flatColorsFiles -and $flatColorsFiles.Count -gt 0) {"
},
{
"lineNumber": 8854,
"content": " Write-Host \"Found $($flatColorsFiles.Count) FlatColors file(s) to process\" -ForegroundColor Gray"
},
{
"lineNumber": 8856,
"content": " # Calculate checksums for FlatColors files"
},
{
"lineNumber": 8857,
"content": " Write-Host \"Calculating checksums for FlatColors files...\" -ForegroundColor Yellow"
},
{
"lineNumber": 8858,
"content": " $flatColorsWithChecksums = Get-FilesWithChecksums -Files $flatColorsFiles"
},
{
"lineNumber": 8861,
"content": " $flatColorsGroupedByChecksum = $flatColorsWithChecksums | Group-Object -Property Hash"
},
{
"lineNumber": 8863,
"content": " Write-Host \"Found $($flatColorsGroupedByChecksum.Count) unique FlatColors file(s)\" -ForegroundColor Gray"
},
{
"lineNumber": 8865,
"content": " # Create \\textures\\common\\FlatColors directory"
},
{
"lineNumber": 8866,
"content": " $flatColorsPath = Join-Path -Path $rootCommonPath -ChildPath \"FlatColors\""
},
{
"lineNumber": 8867,
"content": " if (-not (Test-Path -Path $flatColorsPath -PathType Container)) {"
},
{
"lineNumber": 8868,
"content": " New-Item -ItemType Directory -Path $flatColorsPath | Out-Null"
},
{
"lineNumber": 8869,
"content": " Write-Host \"Created directory: $flatColorsPath\" -ForegroundColor Green"
},
{
"lineNumber": 8872,
"content": " # Track filenames already in \\common\\FlatColors"
},
{
"lineNumber": 8873,
"content": " $filesInFlatColors = @{}"
},
{
"lineNumber": 8874,
"content": " $flatColorsMoved = 0"
},
{
"lineNumber": 8875,
"content": " $flatColorsDuplicates = 0"
},
{
"lineNumber": 8877,
"content": " foreach ($group in $flatColorsGroupedByChecksum) {"
},
{
"lineNumber": 8881,
"content": " # Single file - move to FlatColors folder"
},
{
"lineNumber": 8891,
"content": " $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $fileName"
},
{
"lineNumber": 8894,
"content": " if ($filesInFlatColors.ContainsKey($fileName) -or (Test-Path -Path $destinationPath)) {"
},
{
"lineNumber": 8900,
"content": " $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $newFileName"
},
{
"lineNumber": 8902,
"content": " } while ($filesInFlatColors.ContainsKey($newFileName) -or (Test-Path -Path $destinationPath))"
},
{
"lineNumber": 8908,
"content": " $filesInFlatColors[$fileName] = $true"
},
{
"lineNumber": 8909,
"content": " $flatColorsMoved++"
},
{
"lineNumber": 8911,
"content": " Write-Warning \"Failed to move FlatColors file: $($fileObj.FullName) - $($_.Exception.Message)\""
},
{
"lineNumber": 8916,
"content": " $result = Process-DuplicateGroup -Files $files -CommonPath $flatColorsPath -FilesInCommon $filesInFlatColors -StripPrefix -ValidPrefixes $validBlendfilePrefixes"
},
{
"lineNumber": 8917,
"content": " $flatColorsMoved += $result.MovedCount"
},
{
"lineNumber": 8918,
"content": " $flatColorsDuplicates += $result.DuplicateCount"
},
{
"lineNumber": 8922,
"content": " Write-Host \"Moved $flatColorsMoved unique FlatColors file(s) to \\common\\FlatColors, deleted $flatColorsDuplicates duplicate(s)\" -ForegroundColor Green"
},
{
"lineNumber": 8924,
"content": " Write-Host \"No FlatColors files found to process.\" -ForegroundColor Gray"
},
{
"lineNumber": 8934,
"content": "Updated FlatColors processing to:"
},
{
"lineNumber": 8936,
"content": "1. **Calculate checksums** for all FlatColors files"
},
{
"lineNumber": 8939,
"content": "4. **Move unique files**: Single-file groups are moved to `\\common\\FlatColors`"
},
{
"lineNumber": 8941,
"content": "This removes the `_1`, `_2` suffixes and merges duplicate FlatColors files, keeping one copy per unique checksum and deleting the rest. The script will report how many unique files were moved and how many duplicates were deleted."
},
{
"lineNumber": 9875,
"content": " \"contents\": \" foreach ($group in $groupedByChecksum) {\\n $result = Process-DuplicateGroup -Files $group.Group -CommonPath $blendfileCommonPath -FilesInCommon $filesInBlendfileCommon\\n $blendfileMoved += $result.MovedCount\\n $blendfileDuplicates += $result.DuplicateCount\\n }\\n \\n Write-Host \\\" Moved $blendfileMoved file(s) to \\\\common, deleted $blendfileDuplicates duplicate(s)\\\" -ForegroundColor Green\\n $totalPass1Moved += $blendfileMoved\\n $totalPass1Duplicates += $blendfileDuplicates\\n }\\n \\n Write-Host \\\"\\\"\\n Write-Host \\\"Pass 1 complete: $totalPass1Moved file(s) moved, $totalPass1Duplicates duplicate(s) deleted\\\" -ForegroundColor Green\\n}\\n\\n# ============================================================================\\n# PASS 2: Inter-Blendfile Processing\\n# ============================================================================\\nWrite-Host \\\"\\\"\\nWrite-Host \\\"=== PASS 2: Inter-Blend"
},
{
"lineNumber": 9992,
"content": " \"text\": \"# Collect FlatColors files separately (including those in \\\\common\\\\FlatColors folders, but not from root \\\\common\\\\FlatColors)\","
},
{
"lineNumber": 9996,
"content": " \"text\": \"Write-Host \\\"Collecting FlatColors files...\\\" -ForegroundColor Yellow\","
},
{
"lineNumber": 10000,
"content": " \"text\": \"$rootCommonFlatColorsPath = Join-Path -Path $textureFolderPath -ChildPath \\\"common\\\\FlatColors\\\"\","
},
{
"lineNumber": 10004,
"content": " \"text\": \"$allFlatColorsFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { \","
},
{
"lineNumber": 10008,
"content": " \"text\": \" ($_.FullName -like \\\"*\\\\FlatColors\\\\*\\\" -or $_.Name -like \\\"*FlatColors*\\\") -and \","
},
{
"lineNumber": 10012,
"content": " \"text\": \" $_.FullName -notlike \\\"$([regex]::Escape($rootCommonFlatColorsPath))\\\\*\\\" \","
},
{
"lineNumber": 10023,
"content": " \"text\": \"# Get all remaining files (excluding all \\\\common folders, but we'll handle FlatColors separately)\","
},
{
"lineNumber": 16551,
"content": " \"plan\": \"# Texture Path Remapping in Blend Files\\n\\n## Overview\\nAfter organizing textures (moving duplicates to common folders, deleting duplicates, moving FlatColors), we need to update all texture path references in the corresponding &#96;.blend&#96; files to point to the new locations.\\n\\n## Implementation Steps\\n\\n### 1. Track File Moves in &#96;organize_textures.ps1&#96;\\n\\n**File:** &#96;organize_textures.ps1&#96;\\n\\n- **Modify &#96;Process-DuplicateGroup&#96; function:**\\n - Add a parameter &#96;$MoveLog&#96; (hashtable/array) to track moves\\n - When a file is moved (line 221), log: &#96;@{ OriginalPath = $firstFile.FullName; NewPath = $destinationPath; Type = \\\"moved\\\" }&#96;\\n - When duplicates are deleted (line 232), log: &#96;@{ OriginalPath = $fileObj.FullName; ReplacedBy = $destinationPath; Type = \\\"deleted\\\" }&#96;\\n - Return the move log entries along with counts\\n\\n- **Modify Pass 1 processing:**\\n - Create &#96;$pass1MoveLog = @()&#96; before the blendfile loop"
},
{
"lineNumber": 16560,
"content": " \"content\": \"Modify Pass 2 processing to track moves for regular files and FlatColors files separately\","
},
{
"lineNumber": 16803,
"content": " # Process each checksum group (excluding FlatColors)"
},
{
"lineNumber": 16832,
"content": "Updating FlatColors processing to track moves:"
},
{
"lineNumber": 16842,
"content": " # Track filenames already in \\common\\FlatColors"
},
{
"lineNumber": 16843,
"content": " $filesInFlatColors = @{}"
},
{
"lineNumber": 16844,
"content": " $flatColorsMoved = 0"
},
{
"lineNumber": 16845,
"content": " $flatColorsDuplicates = 0"
},
{
"lineNumber": 16846,
"content": " $flatColorsMoveLog = [System.Collections.ArrayList]::new()"
},
{
"lineNumber": 16848,
"content": " foreach ($group in $flatColorsGroupedByChecksum) {"
},
{
"lineNumber": 16852,
"content": " # Single file - move to FlatColors folder"
},
{
"lineNumber": 16862,
"content": " $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $fileName"
},
{
"lineNumber": 16865,
"content": " if ($filesInFlatColors.ContainsKey($fileName) -or (Test-Path -Path $destinationPath)) {"
},
{
"lineNumber": 16871,
"content": " $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $newFileName"
},
{
"lineNumber": 16873,
"content": " } while ($filesInFlatColors.ContainsKey($newFileName) -or (Test-Path -Path $destinationPath))"
},
{
"lineNumber": 16880,
"content": " $filesInFlatColors[$fileName] = $true"
},
{
"lineNumber": 16881,
"content": " $flatColorsMoved++"
},
{
"lineNumber": 16886,
"content": " $null = $flatColorsMoveLog.Add([PSCustomObject]@{"
},
{
"lineNumber": 16892,
"content": " Write-Warning \"Failed to move FlatColors file: $($fileObj.FullName) - $($_.Exception.Message)\""
},
{
"lineNumber": 16897,
"content": " $result = Process-DuplicateGroup -Files $files -CommonPath $flatColorsPath -FilesInCommon $filesInFlatColors -StripPrefix -ValidPrefixes $validBlendfilePrefixes -MoveLog $flatColorsMoveLog"
},
{
"lineNumber": 16898,
"content": " $flatColorsMoved += $result.MovedCount"
},
{
"lineNumber": 16899,
"content": " $flatColorsDuplicates += $result.DuplicateCount"
},
{
"lineNumber": 16935,
"content": "if ($null -ne $flatColorsMoveLog -and $flatColorsMoveLog.Count -gt 0) {"
},
{
"lineNumber": 16936,
"content": " $allMoves += $flatColorsMoveLog"
},
{
"lineNumber": 17331,
"content": "3. **Pass 2 tracking**: Added `$pass2MoveLog` and `$flatColorsMoveLog` to track inter-blendfile moves"
},
{
"lineNumber": 18376,
"content": "Collecting FlatColors files..."
},
{
"lineNumber": 18381,
"content": "Identifying FlatColors files..."
},
{
"lineNumber": 18382,
"content": "Found 15 FlatColors file(s) (including from \\common\\FlatColors folders), 193 other file(s)"
},
{
"lineNumber": 18387,
"content": "Processing FlatColors files (merging duplicates)..."
},
{
"lineNumber": 18388,
"content": "Found 15 FlatColors file(s) to process"
},
{
"lineNumber": 18389,
"content": "Calculating checksums for FlatColors files..."
},
{
"lineNumber": 18390,
"content": "Found 6 unique FlatColors file(s)"
},
{
"lineNumber": 18391,
"content": "Created directory: T:\\1 BlenderAssets\\Amazon\\Char\\Cartoon2\\AM\\common\\FlatColors"
},
{
"lineNumber": 18392,
"content": "Moved 6 unique FlatColors file(s) to \\common\\FlatColors, deleted 9 duplicate(s)"
}
]
},
{
"file": ".specstory/history/2025-12-19_17-59Z-texture-folder-commonality-script.md",
"matches": [
{
"lineNumber": 271,
"content": " \"absPath\": \"A:\\\\1 Amazon_Active_Projects\\\\1 BlenderAssets\\\\Amazon\\\\Char\\\\Cartoon1\\\\textures\\\\Chan\\\\common\\\\FlatColors\","
},
{
"lineNumber": 349,
"content": " \"absPath\": \"A:\\\\1 Amazon_Active_Projects\\\\1 BlenderAssets\\\\Amazon\\\\Char\\\\Cartoon1\\\\textures\\\\Demarco\\\\common\\\\FlatColors\","
},
{
"lineNumber": 514,
"content": " \"absPath\": \"A:\\\\1 Amazon_Active_Projects\\\\1 BlenderAssets\\\\Amazon\\\\Char\\\\Cartoon1\\\\textures\\\\Dennis\\\\common\\\\FlatColors\","
},
{
"lineNumber": 735,
"content": " \"absPath\": \"A:\\\\1 Amazon_Active_Projects\\\\1 BlenderAssets\\\\Amazon\\\\Char\\\\Cartoon1\\\\textures\\\\Hailey\\\\common\\\\FlatColors\","
},
{
"lineNumber": 900,
"content": " \"absPath\": \"A:\\\\1 Amazon_Active_Projects\\\\1 BlenderAssets\\\\Amazon\\\\Char\\\\Cartoon1\\\\textures\\\\Joe\\\\common\\\\FlatColors\","
},
{
"lineNumber": 1057,
"content": " \"absPath\": \"A:\\\\1 Amazon_Active_Projects\\\\1 BlenderAssets\\\\Amazon\\\\Char\\\\Cartoon1\\\\textures\\\\Kirk\\\\common\\\\FlatColors\","
},
{
"lineNumber": 1218,
"content": " \"absPath\": \"A:\\\\1 Amazon_Active_Projects\\\\1 BlenderAssets\\\\Amazon\\\\Char\\\\Cartoon1\\\\textures\\\\Manny\\\\common\\\\FlatColors\","
},
{
"lineNumber": 1470,
"content": " \"absPath\": \"A:\\\\1 Amazon_Active_Projects\\\\1 BlenderAssets\\\\Amazon\\\\Char\\\\Cartoon1\\\\textures\\\\Martha\\\\common\\\\FlatColors\","
},
{
"lineNumber": 1628,
"content": " \"absPath\": \"A:\\\\1 Amazon_Active_Projects\\\\1 BlenderAssets\\\\Amazon\\\\Char\\\\Cartoon1\\\\textures\\\\Regina\\\\common\\\\FlatColors\","
},
{
"lineNumber": 1850,
"content": " \"absPath\": \"A:\\\\1 Amazon_Active_Projects\\\\1 BlenderAssets\\\\Amazon\\\\Char\\\\Cartoon1\\\\textures\\\\Regina\\\\common\\\\FlatColors\","
},
{
"lineNumber": 3473,
"content": "let's make sure that universally, the FlatColors are all saved as 16x16 jpgs, unless they're .tga. also, duplicate flatcolors can and absolutely should be merged."
},
{
"lineNumber": 3480,
"content": "Exploring the project structure to locate FlatColors and understand the current setup."
},
{
"lineNumber": 3494,
"content": " \"query\": \"Where are FlatColors stored or referenced?\","
},
{
"lineNumber": 3516,
"content": " \"contents\": \" \\n if ($null -ne $flatColorsFiles -and $flatColorsFiles.Count -gt 0) {\\n Write-Host \\\"Found $($flatColorsFiles.Count) FlatColors file(s) to process\\\" -ForegroundColor Gray\\n \\n # Calculate checksums for FlatColors files\\n Write-Host \\\"Calculating checksums for FlatColors files...\\\" -ForegroundColor Yellow\\n $flatColorsWithChecksums = Get-FilesWithChecksums -Files $flatColorsFiles\\n \\n # Group by checksum to find duplicates\\n $flatColorsGroupedByChecksum = $flatColorsWithChecksums | Group-Object -Property Hash\\n \\n Write-Host \\\"Found $($flatColorsGroupedByChecksum.Count) unique FlatColors file(s)\\\" -ForegroundColor Gray\\n \\n # Create \\\\textures\\\\common\\\\FlatColors directory\\n $flatColorsPath = Join-Path -Path $rootCommonPath -ChildPath \\\"FlatColors\\\"\\n if (-not (Test-Path -Path $flatColorsPath -PathType Container)) {\\n New-Item -ItemType Directory -Pat"
},
{
"lineNumber": 3524,
"content": " \"text\": \" if ($null -ne $flatColorsFiles -and $flatColorsFiles.Count -gt 0) {\","
},
{
"lineNumber": 3528,
"content": " \"text\": \" Write-Host \\\"Found $($flatColorsFiles.Count) FlatColors file(s) to process\\\" -ForegroundColor Gray\","
},
{
"lineNumber": 3536,
"content": " \"text\": \" # Calculate checksums for FlatColors files\","
},
{
"lineNumber": 3540,
"content": " \"text\": \" Write-Host \\\"Calculating checksums for FlatColors files...\\\" -ForegroundColor Yellow\","
},
{
"lineNumber": 3544,
"content": " \"text\": \" $flatColorsWithChecksums = Get-FilesWithChecksums -Files $flatColorsFiles\","
},
{
"lineNumber": 3556,
"content": " \"text\": \" $flatColorsGroupedByChecksum = $flatColorsWithChecksums | Group-Object -Property Hash\","
},
{
"lineNumber": 3564,
"content": " \"text\": \" Write-Host \\\"Found $($flatColorsGroupedByChecksum.Count) unique FlatColors file(s)\\\" -ForegroundColor Gray\","
},
{
"lineNumber": 3572,
"content": " \"text\": \" # Create \\\\textures\\\\common\\\\FlatColors directory\","
},
{
"lineNumber": 3576,
"content": " \"text\": \" $flatColorsPath = Join-Path -Path $rootCommonPath -ChildPath \\\"FlatColors\\\"\","
},
{
"lineNumber": 3580,
"content": " \"text\": \" if (-not (Test-Path -Path $flatColorsPath -PathType Container)) {\","
},
{
"lineNumber": 3584,
"content": " \"text\": \" New-Item -ItemType Directory -Path $flatColorsPath | Out-Null\","
},
{
"lineNumber": 3588,
"content": " \"text\": \" Write-Host \\\"Created directory: $flatColorsPath\\\" -ForegroundColor Green\","
},
{
"lineNumber": 3600,
"content": " \"text\": \" # Track filenames already in \\\\common\\\\FlatColors\","
},
{
"lineNumber": 3604,
"content": " \"text\": \" $filesInFlatColors = @{}\","
},
{
"lineNumber": 3608,
"content": " \"text\": \" $flatColorsMoved = 0\","
},
{
"lineNumber": 3612,
"content": " \"text\": \" $flatColorsDuplicates = 0\","
},
{
"lineNumber": 3616,
"content": " \"text\": \" $flatColorsMoveLog = [System.Collections.ArrayList]::new()\","
},
{
"lineNumber": 3624,
"content": " \"text\": \" foreach ($group in $flatColorsGroupedByChecksum) {\","
},
{
"lineNumber": 3658,
"content": " \"contents\": \"$allFlatColorsFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { \\n ($_.FullName -like \\\"*\\\\FlatColors\\\\*\\\" -or $_.Name -like \\\"*FlatColors*\\\") -and \\n $_.FullName -notlike \\\"$([regex]::Escape($rootCommonFlatColorsPath))\\\\*\\\" \\n}\\n\\n# Get all remaining files (excluding all \\\\common folders, but we'll handle FlatColors separately)\\nWrite-Host \\\"Collecting remaining files...\\\" -ForegroundColor Yellow\\n$remainingFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { $_.FullName -notlike \\\"*\\\\common\\\\*\\\" }\\n\\nif ($null -eq $remainingFiles -or $remainingFiles.Count -eq 0) {\\n Write-Host \\\"No remaining files found to process.\\\" -ForegroundColor Yellow\\n} else {\\n Write-Host \\\"Found $($remainingFiles.Count) remaining files to process.\\\" -ForegroundColor Green\\n \\n # Calculate checksums\\n Write-Host \\\"Calculating checksums using parallel processing (this may take a while)...\\\" -ForegroundColor Yellow\\"
},
{
"lineNumber": 3662,
"content": " \"text\": \"$allFlatColorsFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { \","
},
{
"lineNumber": 3666,
"content": " \"text\": \" ($_.FullName -like \\\"*\\\\FlatColors\\\\*\\\" -or $_.Name -like \\\"*FlatColors*\\\") -and \","
},
{
"lineNumber": 3670,
"content": " \"text\": \" $_.FullName -notlike \\\"$([regex]::Escape($rootCommonFlatColorsPath))\\\\*\\\" \","
},
{
"lineNumber": 3681,
"content": " \"text\": \"# Get all remaining files (excluding all \\\\common folders, but we'll handle FlatColors separately)\","
},
{
"lineNumber": 3740,
"content": " \"text\": \" # Separate FlatColors files from other files before processing\","
},
{
"lineNumber": 3744,
"content": " \"text\": \" Write-Host \\\"Identifying FlatColors files...\\\" -ForegroundColor Yellow\","
},
{
"lineNumber": 3748,
"content": " \"text\": \" $flatColorsFiles = $allFlatColorsFiles | Where-Object { (Test-Path -Path $_.FullName) }\","
},
{
"lineNumber": 3752,
"content": " \"text\": \" $nonFlatColorsFiles = $remainingFiles | Where-Object { $_.Name -notlike \\\"*FlatColors*\\\" }\","
},
{
"lineNumber": 3760,
"content": " \"text\": \" Write-Host \\\"Found $($flatColorsFiles.Count) FlatColors file(s) (including from \\\\common\\\\FlatColors folders), $($nonFlatColorsFiles.Count) other file(s)\\\" -ForegroundColor Gray\","
},
{
"lineNumber": 3768,
"content": " \"text\": \" # Group non-FlatColors files by checksum\","
},
{
"lineNumber": 3776,
"content": " \"text\": \" $nonFlatColorsWithChecksums = $filesWithChecksums | Where-Object { $_.File.Name -notlike \\\"*FlatColors*\\\" }\","
},
{
"lineNumber": 3780,
"content": " \"text\": \" $groupedByChecksum = $nonFlatColorsWithChecksums | Group-Object -Property Hash\","
},
{
"lineNumber": 3814,
"content": " \"contents\": \" \\n foreach ($group in $flatColorsGroupedByChecksum) {\\n $files = $group.Group\\n \\n if ($files.Count -eq 1) {\\n # Single file - move to FlatColors folder\\n $fileObj = $files[0].File\\n $fileName = $fileObj.Name\\n \\n # Strip blendfile prefix if present\\n $strippedName = Get-FileNameWithoutPrefix -FileName $fileName -ValidPrefixes $validBlendfilePrefixes\\n if ($strippedName -ne $fileName) {\\n $fileName = $strippedName\\n }\\n \\n $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $fileName\\n \\n # Handle name conflicts (shouldn't happen for unique files, but just in case)\\n if ($filesInFlatColors.ContainsKey($fileName) -or (Test-Path -Path $destinationPath)) {\\n $baseName = [System.IO.P"
},
{
"lineNumber": 3822,
"content": " \"text\": \" foreach ($group in $flatColorsGroupedByChecksum) {\","
},
{
"lineNumber": 3838,
"content": " \"text\": \" # Single file - move to FlatColors folder\","
},
{
"lineNumber": 3878,
"content": " \"text\": \" $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $fileName\","
},
{
"lineNumber": 3890,
"content": " \"text\": \" if ($filesInFlatColors.ContainsKey($fileName) -or (Test-Path -Path $destinationPath)) {\","
},
{
"lineNumber": 3914,
"content": " \"text\": \" $destinationPath = Join-Path -Path $flatColorsPath -ChildPath $newFileName\","
},
{
"lineNumber": 3922,
"content": " \"text\": \" } while ($filesInFlatColors.ContainsKey($newFileName) -or (Test-Path -Path $destinationPath))\","
},
{
"lineNumber": 3964,
"content": " \"contents\": \" \\n try {\\n $originalPath = $fileObj.FullName\\n Move-Item -Path $originalPath -Destination $destinationPath -Force\\n $filesInFlatColors[$fileName] = $true\\n $flatColorsMoved++\\n \\n # Log the move\\n $normalizedOriginal = [System.IO.Path]::GetFullPath($originalPath)\\n $normalizedNew = [System.IO.Path]::GetFullPath($destinationPath)\\n $null = $flatColorsMoveLog.Add([PSCustomObject]@{\\n OriginalPath = $normalizedOriginal\\n NewPath = $normalizedNew\\n Type = \\\"moved\\\"\\n })\\n } catch {\\n Write-Warning \\\"Failed to move FlatColors file: $($fileObj.FullName) - $($_.Exception.Message)\\\"\\n }\\n } else {\\n # Multiple file"
},
{
"lineNumber": 3984,
"content": " \"text\": \" $filesInFlatColors[$fileName] = $true\","
},
{
"lineNumber": 3988,
"content": " \"text\": \" $flatColorsMoved++\","
},
{
"lineNumber": 4008,
"content": " \"text\": \" $null = $flatColorsMoveLog.Add([PSCustomObject]@{\","
},
{
"lineNumber": 4032,
"content": " \"text\": \" Write-Warning \\\"Failed to move FlatColors file: $($fileObj.FullName) - $($_.Exception.Message)\\\"\","
},
{
"lineNumber": 4052,
"content": " \"text\": \" $result = Process-DuplicateGroup -Files $files -CommonPath $flatColorsPath -FilesInCommon $filesInFlatColors -StripPrefix -ValidPrefixes $validBlendfilePrefixes -MoveLog $flatColorsMoveLog\","
},
{
"lineNumber": 4056,
"content": " \"text\": \" $flatColorsMoved += $result.MovedCount\","
},
{
"lineNumber": 4060,
"content": " \"text\": \" $flatColorsDuplicates += $result.DuplicateCount\","
},
{
"lineNumber": 4076,
"content": " \"text\": \" Write-Host \\\"Moved $flatColorsMoved unique FlatColors file(s) to \\\\common\\\\FlatColors, deleted $flatColorsDuplicates duplicate(s)\\\" -ForegroundColor Green\","
},
{
"lineNumber": 4084,
"content": " \"text\": \" Write-Host \\\"No FlatColors files found to process.\\\" -ForegroundColor Gray\","
},
{
"lineNumber": 4145,
"content": " \"contents\": \" foreach ($group in $groupedByChecksum) {\\n $result = Process-DuplicateGroup -Files $group.Group -CommonPath $blendfileCommonPath -FilesInCommon $filesInBlendfileCommon -MoveLog $pass1MoveLog\\n $blendfileMoved += $result.MovedCount\\n $blendfileDuplicates += $result.DuplicateCount\\n }\\n \\n Write-Host \\\" Moved $blendfileMoved file(s) to \\\\common, deleted $blendfileDuplicates duplicate(s)\\\" -ForegroundColor Green\\n $totalPass1Moved += $blendfileMoved\\n $totalPass1Duplicates += $blendfileDuplicates\\n }\\n \\n Write-Host \\\"\\\"\\n Write-Host \\\"Pass 1 complete: $totalPass1Moved file(s) moved, $totalPass1Duplicates duplicate(s) deleted\\\" -ForegroundColor Green\\n}\\n\\n# ============================================================================\\n# PASS 2: Inter-Blendfile Processing\\n# ============================================================================\\nWrite-Host \\\"\\\"\\nWrite-Host \\\""
},
{
"lineNumber": 4262,
"content": " \"text\": \"# Collect FlatColors files separately (including those in \\\\common\\\\FlatColors folders, but not from root \\\\common\\\\FlatColors)\","
},
{
"lineNumber": 4266,
"content": " \"text\": \"Write-Host \\\"Collecting FlatColors files...\\\" -ForegroundColor Yellow\","
},
{
"lineNumber": 4270,
"content": " \"text\": \"$rootCommonFlatColorsPath = Join-Path -Path $textureFolderPath -ChildPath \\\"common\\\\FlatColors\\\"\","
},
{
"lineNumber": 4274,
"content": " \"text\": \"$allFlatColorsFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { \","
},
{
"lineNumber": 4278,
"content": " \"text\": \" ($_.FullName -like \\\"*\\\\FlatColors\\\\*\\\" -or $_.Name -like \\\"*FlatColors*\\\") -and \","
},
{
"lineNumber": 4296,
"content": " \"contents\": \" \\n Write-Host \\\"Found $($groupedByChecksum.Count) unique checksums.\\\" -ForegroundColor Green\\n \\n # Create \\\\textures\\\\common directory\\n $rootCommonPath = Join-Path -Path $textureFolderPath -ChildPath \\\"common\\\"\\n \\n if (-not (Test-Path -Path $rootCommonPath -PathType Container)) {\\n New-Item -ItemType Directory -Path $rootCommonPath | Out-Null\\n Write-Host \\\"Created directory: $rootCommonPath\\\" -ForegroundColor Green\\n }\\n \\n # Track filenames already in \\\\textures\\\\common\\n $filesInRootCommon = @{}\\n \\n # Process each checksum group (excluding FlatColors)\\n Write-Host \\\"Moving files to \\\\common and deleting duplicates...\\\" -ForegroundColor Yellow\\n $pass2Moved = 0\\n $pass2Duplicates = 0\\n $pass2MoveLog = [System.Collections.ArrayList]::new()\\n \\n foreach ($group in $groupedByChecksum) {\\n $files = $group.Group\\n \\n if ($files.Count -eq 1) {\\n # Single file - l"
},
{
"lineNumber": 4356,
"content": " \"text\": \" # Process each checksum group (excluding FlatColors)\","
},
{
"lineNumber": 4440,
"content": " \"text\": \" # Process FlatColors files: merge duplicates and move to \\\\common\\\\FlatColors\","
},
{
"lineNumber": 4444,
"content": " \"text\": \" Write-Host \\\"Processing FlatColors files (merging duplicates)...\\\" -ForegroundColor Yellow\","
},
{
"lineNumber": 4452,
"content": " \"text\": \" if ($null -ne $flatColorsFiles -and $flatColorsFiles.Count -gt 0) {\","
},
{
"lineNumber": 4456,
"content": " \"text\": \" Write-Host \\\"Found $($flatColorsFiles.Count) FlatColors file(s) to process\\\" -ForegroundColor Gray\","
},
{
"lineNumber": 5168,
"content": " \"contents\": \"# Save Move Log and Find Blend Files\\n# ============================================================================\\nWrite-Host \\\"\\\"\\nWrite-Host \\\"Saving move log and finding blend files...\\\" -ForegroundColor Yellow\\n\\n# Combine all move logs\\n$allMoves = @()\\nif ($null -ne $pass1MoveLog -and $pass1MoveLog.Count -gt 0) {\\n $allMoves += $pass1MoveLog\\n}\\nif ($null -ne $pass2MoveLog -and $pass2MoveLog.Count -gt 0) {\\n $allMoves += $pass2MoveLog\\n}\\nif ($null -ne $flatColorsMoveLog -and $flatColorsMoveLog.Count -gt 0) {\\n $allMoves += $flatColorsMoveLog\\n}\\n\\n# Get parent directory of texture folder\\n$blendFileParentDir = Split-Path -Path $textureFolderPath -Parent\\n\\n# Find matching blend files\\n# Match logic: blendfile folder name (e.g., \\\"Beth\\\") should appear in blend file name (e.g., \\\"AM_Beth_v3.2.blend\\\")\\n$blendFileMappings = @()\\nif ($null -ne $blendfileFolders -and $blendfileFolders.Count -gt 0) {\\n # Get blendfile folder names\\n $blendfileFo"
},
{
"lineNumber": 5223,
"content": " \"text\": \"if ($null -ne $flatColorsMoveLog -and $flatColorsMoveLog.Count -gt 0) {\","
},
{
"lineNumber": 5227,
"content": " \"text\": \" $allMoves += $flatColorsMoveLog\","
}
]
}
],
"totalLines": 337,
"totalMatchedLines": 337
}
}
}
}
}
Status: completed
Reviewing the existing script to understand the structure, then creating a script to standardize FlatColors.
Tool use: **read_file_v2** • Read file: organize_textures.ps1
Tool use: **read_file_v2** • Read file: CONFIG.md
Creating a script to standardize FlatColors: convert PNGs to 16x16 JPGs (except TGA), merge duplicates by color, and ensure all are 16x16.
Tool use: **read_file_v2** • Read file: organize_textures.ps1
Tool use: **semantic_search_full**
Parameters:
{
"query": "How are image files processed or converted in PowerShell scripts?",
"topK": 10,
"explanation": ""
}
Result:
{
"codeResults": [
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 636
},
"endPosition": {
"line": 677
}
},
"contents": " \n try {\n # Run Blender and capture output while displaying it (like compress_blend_files.bat)\n # Build command with proper argument array\n $blenderArgsArray = @(\n \"--background\",\n \"--factory-startup\",\n \"--python\", $remapScriptPath,\n \"--\",\n $blendFilePath,\n $moveLogPath\n )\n \n # Execute and pipe output through Tee-Object to display and save\n & $blenderExe $blenderArgsArray 2>&1 | Tee-Object -FilePath \"blender_output.txt\" | ForEach-Object {\n Write-Host \" $_\"\n }\n \n # Check exit code\n $exitCode = $LASTEXITCODE\n \n if ($exitCode -eq 0) {\n Write-Host \" Successfully remapped texture paths\" -ForegroundColor Green\n $processedCount++\n } else {\n Write-Warning \" Failed to remap texture paths (exit code: $exitCode)\"\n $failedCount++\n }\n } catch {\n Write-Warning \" Exception while processing blend file: $($_.Exception.Message)\"\n $failedCount++\n }\n }\n \n # Clean up temporary output files\n Remove-Item -Path \"blender_output.txt\" -ErrorAction SilentlyContinue\n Remove-Item -Path \"blender_error.txt\" -ErrorAction SilentlyContinue\n \n Write-Host \"\"\n if ($processedCount -gt 0 -or $failedCount -gt 0) {\n Write-Host \"Blend file remapping complete: $processedCount succeeded, $failedCount failed\" -ForegroundColor $(if ($failedCount -eq 0) { \"Green\" } else { \"Yellow\" })",
"signatures": {},
"detailedLines": [
{
"text": " ",
"lineNumber": 637
},
{
"text": " try {",
"lineNumber": 638
},
{
"text": " # Run Blender and capture output while displaying it (like compress_blend_files.bat)",
"lineNumber": 639
},
{
"text": " # Build command with proper argument array",
"lineNumber": 640
},
{
"text": " $blenderArgsArray = @(",
"lineNumber": 641
},
{
"text": " \"--background\",",
"lineNumber": 642
},
{
"text": " \"--factory-startup\",",
"lineNumber": 643
},
{
"text": " \"--python\", $remapScriptPath,",
"lineNumber": 644
},
{
"text": " \"--\",",
"lineNumber": 645
},
{
"text": " $blendFilePath,",
"lineNumber": 646
},
{
"text": " $moveLogPath",
"lineNumber": 647
},
{
"text": " )",
"lineNumber": 648
},
{
"text": " ",
"lineNumber": 649
},
{
"text": " # Execute and pipe output through Tee-Object to display and save",
"lineNumber": 650
},
{
"text": " & $blenderExe $blenderArgsArray 2>&1 | Tee-Object -FilePath \"blender_output.txt\" | ForEach-Object {",
"lineNumber": 651
},
{
"text": " Write-Host \" $_\"",
"lineNumber": 652
},
{
"text": " }",
"lineNumber": 653
},
{
"text": " ",
"lineNumber": 654
},
{
"text": " # Check exit code",
"lineNumber": 655
},
{
"text": " $exitCode = $LASTEXITCODE",
"lineNumber": 656
},
{
"text": " ",
"lineNumber": 657
},
{
"text": " if ($exitCode -eq 0) {",
"lineNumber": 658
},
{
"text": " Write-Host \" Successfully remapped texture paths\" -ForegroundColor Green",
"lineNumber": 659
},
{
"text": " $processedCount++",
"lineNumber": 660
},
{
"text": " } else {",
"lineNumber": 661
},
{
"text": " Write-Warning \" Failed to remap texture paths (exit code: $exitCode)\"",
"lineNumber": 662
},
{
"text": " $failedCount++",
"lineNumber": 663
},
{
"text": " }",
"lineNumber": 664
},
{
"text": " } catch {",
"lineNumber": 665
},
{
"text": " Write-Warning \" Exception while processing blend file: $($_.Exception.Message)\"",
"lineNumber": 666
},
{
"text": " $failedCount++",
"lineNumber": 667
},
{
"text": " }",
"lineNumber": 668
},
{
"text": " }",
"lineNumber": 669
},
{
"text": " ",
"lineNumber": 670
},
{
"text": " # Clean up temporary output files",
"lineNumber": 671
},
{
"text": " Remove-Item -Path \"blender_output.txt\" -ErrorAction SilentlyContinue",
"lineNumber": 672
},
{
"text": " Remove-Item -Path \"blender_error.txt\" -ErrorAction SilentlyContinue",
"lineNumber": 673
},
{
"text": " ",
"lineNumber": 674
},
{
"text": " Write-Host \"\"",
"lineNumber": 675
},
{
"text": " if ($processedCount -gt 0 -or $failedCount -gt 0) {",
"lineNumber": 676
},
{
"text": " Write-Host \"Blend file remapping complete: $processedCount succeeded, $failedCount failed\" -ForegroundColor $(if ($failedCount -eq 0) { \"Green\" } else { \"Yellow\" })",
"lineNumber": 677
}
]
},
"score": 0.39588218927383423
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\UpdateSequences.ps1",
"range": {
"startPosition": {},
"endPosition": {
"line": 60
}
},
"contents": "[CmdletBinding()]\nparam(\n [switch]$DebugMode\n)\n\nSet-StrictMode -Version Latest\n$ErrorActionPreference = 'Stop'\n\nif (-not $PSScriptRoot) {\n $PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path\n}\n\n$configLoader = Join-Path -Path $PSScriptRoot -ChildPath 'ConfigLoader.ps1'\nif (-not (Test-Path -LiteralPath $configLoader)) {\n throw \"Missing ConfigLoader.ps1 in $PSScriptRoot\"\n}\n. $configLoader\n\n$useIsoDailyFormat = Use-IsoDailyFormat\n\nfunction Sync-SequenceFilenames {\n param(\n [Parameter(Mandatory)] [string]$SequenceFolderPath,\n [Parameter(Mandatory)] [string]$SequenceName,\n [string]$LogFile,\n [string[]]$Extensions = @('.png','.jpg','.jpeg','.exr','.tif','.tiff','.bmp','.tga')\n )\n $renamed = 0\n $collisions = 0\n $errors = 0\n $checked = 0\n $minFrame = [int]::MaxValue\n $maxFrame = -1\n $frameCount = 0\n\n if ($LogFile) { \"[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] RENAME CHECK in '$SequenceFolderPath' (seq='$SequenceName')\" | Add-Content -LiteralPath $LogFile }\n\n $files = Get-ChildItem -LiteralPath $SequenceFolderPath -File -Recurse -ErrorAction SilentlyContinue |\n Where-Object { $_.FullName -notlike '*\\_archive\\*' -and ($Extensions -contains $_.Extension.ToLower()) }\n foreach ($f in $files) {\n $checked++\n $base = [System.IO.Path]::GetFileNameWithoutExtension($f.Name)\n $ext = $f.Extension\n $digits = $null\n\n if ($base -match '_(\\d{6})$') {\n $digits = $Matches[1]\n }\n elseif ($base -match '(?<!_)\\b(\\d{6})$') {\n $digits = $Matches[1]\n }\n elseif ($base -match '(\\d{4})$') {\n $digits = ('00' + $Matches[1])\n }\n else {\n continue\n }\n\n try {\n $n = [int]$digits",
"signatures": {},
"detailedLines": [
{
"text": "[CmdletBinding()]",
"lineNumber": 1
},
{
"text": "param(",
"lineNumber": 2
},
{
"text": " [switch]$DebugMode",
"lineNumber": 3
},
{
"text": ")",
"lineNumber": 4
},
{
"lineNumber": 5
},
{
"text": "Set-StrictMode -Version Latest",
"lineNumber": 6
},
{
"text": "$ErrorActionPreference = 'Stop'",
"lineNumber": 7
},
{
"lineNumber": 8
},
{
"text": "if (-not $PSScriptRoot) {",
"lineNumber": 9
},
{
"text": " $PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path",
"lineNumber": 10
},
{
"text": "}",
"lineNumber": 11
},
{
"lineNumber": 12
},
{
"text": "$configLoader = Join-Path -Path $PSScriptRoot -ChildPath 'ConfigLoader.ps1'",
"lineNumber": 13
},
{
"text": "if (-not (Test-Path -LiteralPath $configLoader)) {",
"lineNumber": 14
},
{
"text": " throw \"Missing ConfigLoader.ps1 in $PSScriptRoot\"",
"lineNumber": 15
},
{
"text": "}",
"lineNumber": 16
},
{
"text": ". $configLoader",
"lineNumber": 17
},
{
"lineNumber": 18
},
{
"text": "$useIsoDailyFormat = Use-IsoDailyFormat",
"lineNumber": 19
},
{
"lineNumber": 20
},
{
"text": "function Sync-SequenceFilenames {",
"lineNumber": 21
},
{
"text": " param(",
"lineNumber": 22
},
{
"text": " [Parameter(Mandatory)] [string]$SequenceFolderPath,",
"lineNumber": 23
},
{
"text": " [Parameter(Mandatory)] [string]$SequenceName,",
"lineNumber": 24
},
{
"text": " [string]$LogFile,",
"lineNumber": 25
},
{
"text": " [string[]]$Extensions = @('.png','.jpg','.jpeg','.exr','.tif','.tiff','.bmp','.tga')",
"lineNumber": 26
},
{
"text": " )",
"lineNumber": 27
},
{
"text": " $renamed = 0",
"lineNumber": 28
},
{
"text": " $collisions = 0",
"lineNumber": 29
},
{
"text": " $errors = 0",
"lineNumber": 30
},
{
"text": " $checked = 0",
"lineNumber": 31
},
{
"text": " $minFrame = [int]::MaxValue",
"lineNumber": 32
},
{
"text": " $maxFrame = -1",
"lineNumber": 33
},
{
"text": " $frameCount = 0",
"lineNumber": 34
},
{
"lineNumber": 35
},
{
"text": " if ($LogFile) { \"[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] RENAME CHECK in '$SequenceFolderPath' (seq='$SequenceName')\" | Add-Content -LiteralPath $LogFile }",
"lineNumber": 36
},
{
"lineNumber": 37
},
{
"text": " $files = Get-ChildItem -LiteralPath $SequenceFolderPath -File -Recurse -ErrorAction SilentlyContinue |",
"lineNumber": 38
},
{
"text": " Where-Object { $_.FullName -notlike '*\\_archive\\*' -and ($Extensions -contains $_.Extension.ToLower()) }",
"lineNumber": 39
},
{
"text": " foreach ($f in $files) {",
"lineNumber": 40
},
{
"text": " $checked++",
"lineNumber": 41
},
{
"text": " $base = [System.IO.Path]::GetFileNameWithoutExtension($f.Name)",
"lineNumber": 42
},
{
"text": " $ext = $f.Extension",
"lineNumber": 43
},
{
"text": " $digits = $null",
"lineNumber": 44
},
{
"lineNumber": 45
},
{
"text": " if ($base -match '_(\\d{6})$') {",
"lineNumber": 46
},
{
"text": " $digits = $Matches[1]",
"lineNumber": 47
},
{
"text": " }",
"lineNumber": 48
},
{
"text": " elseif ($base -match '(?<!_)\\b(\\d{6})$') {",
"lineNumber": 49
},
{
"text": " $digits = $Matches[1]",
"lineNumber": 50
},
{
"text": " }",
"lineNumber": 51
},
{
"text": " elseif ($base -match '(\\d{4})$') {",
"lineNumber": 52
},
{
"text": " $digits = ('00' + $Matches[1])",
"lineNumber": 53
},
{
"text": " }",
"lineNumber": 54
},
{
"text": " else {",
"lineNumber": 55
},
{
"text": " continue",
"lineNumber": 56
},
{
"text": " }",
"lineNumber": 57
},
{
"lineNumber": 58
},
{
"text": " try {",
"lineNumber": 59
},
{
"text": " $n = [int]$digits",
"lineNumber": 60
}
]
},
"score": 0.39077043533325195
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 604
},
"endPosition": {
"line": 639
}
},
"contents": " } else {\n Write-Host \"Found Blender: $blenderExe\" -ForegroundColor Gray\n \n # Get the remap script path (should be in the same directory as this script)\n $scriptDir = Split-Path -Path $MyInvocation.MyCommand.Path -Parent\n $remapScriptPath = Join-Path -Path $scriptDir -ChildPath \"remap_texture_paths.py\"\n \n if (-not (Test-Path -Path $remapScriptPath)) {\n Write-Warning \"Remap script not found: $remapScriptPath\"\n Write-Warning \"Skipping texture path remapping.\"\n } else {\n $processedCount = 0\n $failedCount = 0\n \n Write-Host \"Processing $($blendFileMappings.Count) blend file(s)...\" -ForegroundColor Gray\n \n foreach ($mapping in $blendFileMappings) {\n $blendFilePath = $mapping.BlendFile\n $blendFileName = Split-Path -Path $blendFilePath -Leaf\n \n Write-Host \" Processing: $blendFileName\" -ForegroundColor Cyan\n \n # Check if blend file exists\n if (-not (Test-Path -Path $blendFilePath)) {\n Write-Warning \" Blend file not found: $blendFilePath\"\n $failedCount++\n continue\n }\n \n # Run Blender with the remapping script (one file at a time)\n # Delete old output file\n Remove-Item -Path \"blender_output.txt\" -ErrorAction SilentlyContinue\n \n try {\n # Run Blender and capture output while displaying it (like compress_blend_files.bat)",
"signatures": {},
"detailedLines": [
{
"text": " } else {",
"lineNumber": 605
},
{
"text": " Write-Host \"Found Blender: $blenderExe\" -ForegroundColor Gray",
"lineNumber": 606
},
{
"text": " ",
"lineNumber": 607
},
{
"text": " # Get the remap script path (should be in the same directory as this script)",
"lineNumber": 608
},
{
"text": " $scriptDir = Split-Path -Path $MyInvocation.MyCommand.Path -Parent",
"lineNumber": 609
},
{
"text": " $remapScriptPath = Join-Path -Path $scriptDir -ChildPath \"remap_texture_paths.py\"",
"lineNumber": 610
},
{
"text": " ",
"lineNumber": 611
},
{
"text": " if (-not (Test-Path -Path $remapScriptPath)) {",
"lineNumber": 612
},
{
"text": " Write-Warning \"Remap script not found: $remapScriptPath\"",
"lineNumber": 613
},
{
"text": " Write-Warning \"Skipping texture path remapping.\"",
"lineNumber": 614
},
{
"text": " } else {",
"lineNumber": 615
},
{
"text": " $processedCount = 0",
"lineNumber": 616
},
{
"text": " $failedCount = 0",
"lineNumber": 617
},
{
"text": " ",
"lineNumber": 618
},
{
"text": " Write-Host \"Processing $($blendFileMappings.Count) blend file(s)...\" -ForegroundColor Gray",
"lineNumber": 619
},
{
"text": " ",
"lineNumber": 620
},
{
"text": " foreach ($mapping in $blendFileMappings) {",
"lineNumber": 621
},
{
"text": " $blendFilePath = $mapping.BlendFile",
"lineNumber": 622
},
{
"text": " $blendFileName = Split-Path -Path $blendFilePath -Leaf",
"lineNumber": 623
},
{
"text": " ",
"lineNumber": 624
},
{
"text": " Write-Host \" Processing: $blendFileName\" -ForegroundColor Cyan",
"lineNumber": 625
},
{
"text": " ",
"lineNumber": 626
},
{
"text": " # Check if blend file exists",
"lineNumber": 627
},
{
"text": " if (-not (Test-Path -Path $blendFilePath)) {",
"lineNumber": 628
},
{
"text": " Write-Warning \" Blend file not found: $blendFilePath\"",
"lineNumber": 629
},
{
"text": " $failedCount++",
"lineNumber": 630
},
{
"text": " continue",
"lineNumber": 631
},
{
"text": " }",
"lineNumber": 632
},
{
"text": " ",
"lineNumber": 633
},
{
"text": " # Run Blender with the remapping script (one file at a time)",
"lineNumber": 634
},
{
"text": " # Delete old output file",
"lineNumber": 635
},
{
"text": " Remove-Item -Path \"blender_output.txt\" -ErrorAction SilentlyContinue",
"lineNumber": 636
},
{
"text": " ",
"lineNumber": 637
},
{
"text": " try {",
"lineNumber": 638
},
{
"text": " # Run Blender and capture output while displaying it (like compress_blend_files.bat)",
"lineNumber": 639
}
]
},
"score": 0.3801639676094055
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\compress_blend_files.bat",
"range": {
"startPosition": {
"line": 64
},
"endPosition": {
"line": 118
}
},
"contents": "echo output_file = os.path.join^(\"output\", filename^)\necho # Check if output file already exists\necho if os.path.exists^(output_file^):\necho print^(\"SKIP_EXISTING:\" + blend_file^)\necho continue\necho # Skip if source is already compressed\necho if is_compressed_file^(blend_file^):\necho print^(\"SKIP_ALREADY_COMPRESSED:\" + blend_file^)\necho continue\necho print^(\"PROCESSING:\" + blend_file^)\necho # Load the blend file\necho bpy.ops.wm.open_mainfile^(filepath=blend_file^)\necho # Save with compression to output folder\necho bpy.ops.wm.save_mainfile^(filepath=output_file, compress=True^)\necho print^(\"SUCCESS:\" + blend_file + \":\" + output_file^)\necho except Exception as e:\necho print^(\"CRASH:\" + blend_file + \":\" + str^(e^)^)\necho else:\necho print^(\"SKIP_NOT_BLEND:\" + blend_file^)\necho.\necho print^(\"COMPRESSION_COMPLETE\"^)\necho bpy.ops.wm.quit_blender^(^)\n) > \"!TEMP_SCRIPT!\"\n\nREM Check if script was created successfully\nif exist \"!TEMP_SCRIPT!\" (\n echo Script created successfully: !TEMP_SCRIPT!\n) else (\n echo ERROR: Failed to create script file!\n pause\n exit /b 1\n)\n\nREM Run Blender to process the dragged files\necho Processing dragged .blend files...\necho Using script: !TEMP_SCRIPT!\ndel /f /q \"blender_output.txt\" 2>nul\nblender --background --factory-startup --python \"!TEMP_SCRIPT!\" -- %* 2^>^&1 | powershell -NoProfile -Command \"$input | Tee-Object -FilePath 'blender_output.txt'\"\n\nREM Clean up temporary script\necho Cleaning up temporary script...\ndel \"!TEMP_SCRIPT!\" 2>nul\n\nREM Parse output and generate report\necho.\necho ========================================\necho COMPRESSION REPORT\necho ========================================\necho.\n\nREM Count processed files and get file info\nfor /f \"tokens=1,2,3 delims=:\" %%a in (blender_output.txt) do (\n if \"%%a\"==\"SUCCESS\" (\n set /a processed+=1",
"signatures": {},
"detailedLines": [
{
"text": "echo output_file = os.path.join^(\"output\", filename^)",
"lineNumber": 65
},
{
"text": "echo # Check if output file already exists",
"lineNumber": 66
},
{
"text": "echo if os.path.exists^(output_file^):",
"lineNumber": 67
},
{
"text": "echo print^(\"SKIP_EXISTING:\" + blend_file^)",
"lineNumber": 68
},
{
"text": "echo continue",
"lineNumber": 69
},
{
"text": "echo # Skip if source is already compressed",
"lineNumber": 70
},
{
"text": "echo if is_compressed_file^(blend_file^):",
"lineNumber": 71
},
{
"text": "echo print^(\"SKIP_ALREADY_COMPRESSED:\" + blend_file^)",
"lineNumber": 72
},
{
"text": "echo continue",
"lineNumber": 73
},
{
"text": "echo print^(\"PROCESSING:\" + blend_file^)",
"lineNumber": 74
},
{
"text": "echo # Load the blend file",
"lineNumber": 75
},
{
"text": "echo bpy.ops.wm.open_mainfile^(filepath=blend_file^)",
"lineNumber": 76
},
{
"text": "echo # Save with compression to output folder",
"lineNumber": 77
},
{
"text": "echo bpy.ops.wm.save_mainfile^(filepath=output_file, compress=True^)",
"lineNumber": 78
},
{
"text": "echo print^(\"SUCCESS:\" + blend_file + \":\" + output_file^)",
"lineNumber": 79
},
{
"text": "echo except Exception as e:",
"lineNumber": 80
},
{
"text": "echo print^(\"CRASH:\" + blend_file + \":\" + str^(e^)^)",
"lineNumber": 81
},
{
"text": "echo else:",
"lineNumber": 82
},
{
"text": "echo print^(\"SKIP_NOT_BLEND:\" + blend_file^)",
"lineNumber": 83
},
{
"text": "echo.",
"lineNumber": 84
},
{
"text": "echo print^(\"COMPRESSION_COMPLETE\"^)",
"lineNumber": 85
},
{
"text": "echo bpy.ops.wm.quit_blender^(^)",
"lineNumber": 86
},
{
"text": ") > \"!TEMP_SCRIPT!\"",
"lineNumber": 87
},
{
"lineNumber": 88
},
{
"text": "REM Check if script was created successfully",
"lineNumber": 89
},
{
"text": "if exist \"!TEMP_SCRIPT!\" (",
"lineNumber": 90
},
{
"text": " echo Script created successfully: !TEMP_SCRIPT!",
"lineNumber": 91
},
{
"text": ") else (",
"lineNumber": 92
},
{
"text": " echo ERROR: Failed to create script file!",
"lineNumber": 93
},
{
"text": " pause",
"lineNumber": 94
},
{
"text": " exit /b 1",
"lineNumber": 95
},
{
"text": ")",
"lineNumber": 96
},
{
"lineNumber": 97
},
{
"text": "REM Run Blender to process the dragged files",
"lineNumber": 98
},
{
"text": "echo Processing dragged .blend files...",
"lineNumber": 99
},
{
"text": "echo Using script: !TEMP_SCRIPT!",
"lineNumber": 100
},
{
"text": "del /f /q \"blender_output.txt\" 2>nul",
"lineNumber": 101
},
{
"text": "blender --background --factory-startup --python \"!TEMP_SCRIPT!\" -- %* 2^>^&1 | powershell -NoProfile -Command \"$input | Tee-Object -FilePath 'blender_output.txt'\"",
"lineNumber": 102
},
{
"lineNumber": 103
},
{
"text": "REM Clean up temporary script",
"lineNumber": 104
},
{
"text": "echo Cleaning up temporary script...",
"lineNumber": 105
},
{
"text": "del \"!TEMP_SCRIPT!\" 2>nul",
"lineNumber": 106
},
{
"lineNumber": 107
},
{
"text": "REM Parse output and generate report",
"lineNumber": 108
},
{
"text": "echo.",
"lineNumber": 109
},
{
"text": "echo ========================================",
"lineNumber": 110
},
{
"text": "echo COMPRESSION REPORT",
"lineNumber": 111
},
{
"text": "echo ========================================",
"lineNumber": 112
},
{
"text": "echo.",
"lineNumber": 113
},
{
"lineNumber": 114
},
{
"text": "REM Count processed files and get file info",
"lineNumber": 115
},
{
"text": "for /f \"tokens=1,2,3 delims=:\" %%a in (blender_output.txt) do (",
"lineNumber": 116
},
{
"text": " if \"%%a\"==\"SUCCESS\" (",
"lineNumber": 117
},
{
"text": " set /a processed+=1",
"lineNumber": 118
}
]
},
"score": 0.3668818473815918
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {},
"endPosition": {
"line": 50
}
},
"contents": "# Script to organize texture files by checksum with two-level duplicate detection\n# Pass 1: Intra-blendfile duplicates → [blendfile]\\common\n# Pass 2: Inter-blendfile duplicates → \\textures\\common\n# Usage: .\\organize_textures.ps1\n\n# Prompt user for texture folder path\n$textureFolderPath = Read-Host \"Enter texture folder path\"\n\n# Validate the input path\nif ([string]::IsNullOrWhiteSpace($textureFolderPath)) {\n Write-Host \"Error: No path provided.\" -ForegroundColor Red\n exit\n}\n\nif (-not (Test-Path -Path $textureFolderPath -PathType Container)) {\n Write-Host \"Error: Path does not exist or is not a directory: $textureFolderPath\" -ForegroundColor Red\n exit\n}\n\n# Resolve the full path\n$textureFolderPath = (Resolve-Path $textureFolderPath).ProviderPath\nWrite-Host \"Processing texture folder: $textureFolderPath\" -ForegroundColor Cyan\n\n# Function to calculate checksums for files\nfunction Get-FilesWithChecksums {\n param(\n [array]$Files\n )\n \n $throttleLimit = [Math]::Max(1, [Environment]::ProcessorCount)\n $parallelScriptBlock = {\n try {\n $hash = Get-FileHash -Path $_.FullName -Algorithm SHA256\n [PSCustomObject]@{\n File = $_\n Hash = $hash.Hash\n }\n } catch {\n Write-Warning \"Failed to calculate checksum for: $($_.FullName) - $($_.Exception.Message)\"\n $null\n }\n }\n \n return $Files | ForEach-Object -Parallel $parallelScriptBlock -ThrottleLimit $throttleLimit | Where-Object { $null -ne $_ }\n}\n\n# Function to move files to common folder\nfunction Move-FilesToCommon {\n param(\n [array]$Files,",
"signatures": {},
"detailedLines": [
{
"text": "# Script to organize texture files by checksum with two-level duplicate detection",
"lineNumber": 1
},
{
"text": "# Pass 1: Intra-blendfile duplicates → [blendfile]\\common",
"lineNumber": 2
},
{
"text": "# Pass 2: Inter-blendfile duplicates → \\textures\\common",
"lineNumber": 3
},
{
"text": "# Usage: .\\organize_textures.ps1",
"lineNumber": 4
},
{
"lineNumber": 5
},
{
"text": "# Prompt user for texture folder path",
"lineNumber": 6
},
{
"text": "$textureFolderPath = Read-Host \"Enter texture folder path\"",
"lineNumber": 7
},
{
"lineNumber": 8
},
{
"text": "# Validate the input path",
"lineNumber": 9
},
{
"text": "if ([string]::IsNullOrWhiteSpace($textureFolderPath)) {",
"lineNumber": 10
},
{
"text": " Write-Host \"Error: No path provided.\" -ForegroundColor Red",
"lineNumber": 11
},
{
"text": " exit",
"lineNumber": 12
},
{
"text": "}",
"lineNumber": 13
},
{
"lineNumber": 14
},
{
"text": "if (-not (Test-Path -Path $textureFolderPath -PathType Container)) {",
"lineNumber": 15
},
{
"text": " Write-Host \"Error: Path does not exist or is not a directory: $textureFolderPath\" -ForegroundColor Red",
"lineNumber": 16
},
{
"text": " exit",
"lineNumber": 17
},
{
"text": "}",
"lineNumber": 18
},
{
"lineNumber": 19
},
{
"text": "# Resolve the full path",
"lineNumber": 20
},
{
"text": "$textureFolderPath = (Resolve-Path $textureFolderPath).ProviderPath",
"lineNumber": 21
},
{
"text": "Write-Host \"Processing texture folder: $textureFolderPath\" -ForegroundColor Cyan",
"lineNumber": 22
},
{
"lineNumber": 23
},
{
"text": "# Function to calculate checksums for files",
"lineNumber": 24
},
{
"text": "function Get-FilesWithChecksums {",
"lineNumber": 25
},
{
"text": " param(",
"lineNumber": 26
},
{
"text": " [array]$Files",
"lineNumber": 27
},
{
"text": " )",
"lineNumber": 28
},
{
"text": " ",
"lineNumber": 29
},
{
"text": " $throttleLimit = [Math]::Max(1, [Environment]::ProcessorCount)",
"lineNumber": 30
},
{
"text": " $parallelScriptBlock = {",
"lineNumber": 31
},
{
"text": " try {",
"lineNumber": 32
},
{
"text": " $hash = Get-FileHash -Path $_.FullName -Algorithm SHA256",
"lineNumber": 33
},
{
"text": " [PSCustomObject]@{",
"lineNumber": 34
},
{
"text": " File = $_",
"lineNumber": 35
},
{
"text": " Hash = $hash.Hash",
"lineNumber": 36
},
{
"text": " }",
"lineNumber": 37
},
{
"text": " } catch {",
"lineNumber": 38
},
{
"text": " Write-Warning \"Failed to calculate checksum for: $($_.FullName) - $($_.Exception.Message)\"",
"lineNumber": 39
},
{
"text": " $null",
"lineNumber": 40
},
{
"text": " }",
"lineNumber": 41
},
{
"text": " }",
"lineNumber": 42
},
{
"text": " ",
"lineNumber": 43
},
{
"text": " return $Files | ForEach-Object -Parallel $parallelScriptBlock -ThrottleLimit $throttleLimit | Where-Object { $null -ne $_ }",
"lineNumber": 44
},
{
"text": "}",
"lineNumber": 45
},
{
"lineNumber": 46
},
{
"text": "# Function to move files to common folder",
"lineNumber": 47
},
{
"text": "function Move-FilesToCommon {",
"lineNumber": 48
},
{
"text": " param(",
"lineNumber": 49
},
{
"text": " [array]$Files,",
"lineNumber": 50
}
]
},
"score": 0.3616774082183838
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\UpdateSequences.ps1",
"range": {
"startPosition": {
"line": 183
},
"endPosition": {
"line": 223,
"column": 8
}
},
"contents": "function Add-SequenceFolder {\n param(\n [Parameter(Mandatory)] [System.IO.DirectoryInfo]$Directory,\n [Parameter(Mandatory)] [hashtable]$Map\n )\n if ($Directory.Name -like '_*') { return }\n $fullPath = $Directory.FullName\n if ($Map.ContainsKey($fullPath)) { return }\n \n # Check if directory contains sequence files directly (not just subdirectories)\n $extensions = @('.png','.jpg','.jpeg','.exr','.tif','.tiff','.bmp','.tga')\n $hasSequenceFiles = Get-ChildItem -LiteralPath $fullPath -File -ErrorAction SilentlyContinue |\n Where-Object { $extensions -contains $_.Extension.ToLower() } |\n Select-Object -First 1\n \n # If it only has subdirectories and no sequence files, skip it\n $hasSubdirs = Get-ChildItem -LiteralPath $fullPath -Directory -ErrorAction SilentlyContinue |\n Select-Object -First 1\n if ($null -eq $hasSequenceFiles -and $null -ne $hasSubdirs) {\n return\n }\n \n $Map[$fullPath] = Resolve-SequenceName -Directory $Directory\n}\n\ntry {\n $root = (Get-Location).ProviderPath\n $logFile = $null\n\n if ($DebugMode) {\n $logFile = Join-Path $root (\"UpdateSequences_{0}.log\" -f (Get-Date -Format 'yyyyMMdd_HHmmss'))\n \"[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] === UpdateSequences started in '$root' ===\" | Out-File -LiteralPath $logFile -Encoding UTF8\n }\n\n $sequenceMap = @{}\n\n $primaryPattern = if ($useIsoDailyFormat) { '????-??-??' } else { 'daily_*' }\n $secondaryPattern = if ($useIsoDailyFormat) { 'daily_*' } else { '????-??-??' }\n\n $primaryDirs = Get-ChildItem -LiteralPath $root -Directory -Filter $primaryPattern -ErrorAction SilentlyContinue |\n ",
"signatures": {},
"detailedLines": [
{
"text": "function Add-SequenceFolder {",
"lineNumber": 184
},
{
"text": " param(",
"lineNumber": 185
},
{
"text": " [Parameter(Mandatory)] [System.IO.DirectoryInfo]$Directory,",
"lineNumber": 186
},
{
"text": " [Parameter(Mandatory)] [hashtable]$Map",
"lineNumber": 187
},
{
"text": " )",
"lineNumber": 188
},
{
"text": " if ($Directory.Name -like '_*') { return }",
"lineNumber": 189
},
{
"text": " $fullPath = $Directory.FullName",
"lineNumber": 190
},
{
"text": " if ($Map.ContainsKey($fullPath)) { return }",
"lineNumber": 191
},
{
"text": " ",
"lineNumber": 192
},
{
"text": " # Check if directory contains sequence files directly (not just subdirectories)",
"lineNumber": 193
},
{
"text": " $extensions = @('.png','.jpg','.jpeg','.exr','.tif','.tiff','.bmp','.tga')",
"lineNumber": 194
},
{
"text": " $hasSequenceFiles = Get-ChildItem -LiteralPath $fullPath -File -ErrorAction SilentlyContinue |",
"lineNumber": 195
},
{
"text": " Where-Object { $extensions -contains $_.Extension.ToLower() } |",
"lineNumber": 196
},
{
"text": " Select-Object -First 1",
"lineNumber": 197
},
{
"text": " ",
"lineNumber": 198
},
{
"text": " # If it only has subdirectories and no sequence files, skip it",
"lineNumber": 199
},
{
"text": " $hasSubdirs = Get-ChildItem -LiteralPath $fullPath -Directory -ErrorAction SilentlyContinue |",
"lineNumber": 200
},
{
"text": " Select-Object -First 1",
"lineNumber": 201
},
{
"text": " if ($null -eq $hasSequenceFiles -and $null -ne $hasSubdirs) {",
"lineNumber": 202
},
{
"text": " return",
"lineNumber": 203
},
{
"text": " }",
"lineNumber": 204
},
{
"text": " ",
"lineNumber": 205
},
{
"text": " $Map[$fullPath] = Resolve-SequenceName -Directory $Directory",
"lineNumber": 206
},
{
"text": "}",
"lineNumber": 207
},
{
"lineNumber": 208
},
{
"text": "try {",
"lineNumber": 209
},
{
"text": " $root = (Get-Location).ProviderPath",
"lineNumber": 210
},
{
"text": " $logFile = $null",
"lineNumber": 211
},
{
"lineNumber": 212
},
{
"text": " if ($DebugMode) {",
"lineNumber": 213
},
{
"text": " $logFile = Join-Path $root (\"UpdateSequences_{0}.log\" -f (Get-Date -Format 'yyyyMMdd_HHmmss'))",
"lineNumber": 214
},
{
"text": " \"[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] === UpdateSequences started in '$root' ===\" | Out-File -LiteralPath $logFile -Encoding UTF8",
"lineNumber": 215
},
{
"text": " }",
"lineNumber": 216
},
{
"lineNumber": 217
},
{
"text": " $sequenceMap = @{}",
"lineNumber": 218
},
{
"lineNumber": 219
},
{
"text": " $primaryPattern = if ($useIsoDailyFormat) { '????-??-??' } else { 'daily_*' }",
"lineNumber": 220
},
{
"text": " $secondaryPattern = if ($useIsoDailyFormat) { 'daily_*' } else { '????-??-??' }",
"lineNumber": 221
},
{
"lineNumber": 222
},
{
"text": " $primaryDirs = Get-ChildItem -LiteralPath $root -Directory -Filter $primaryPattern -ErrorAction SilentlyContinue |",
"lineNumber": 223
},
{
"text": " ",
"lineNumber": 224
}
]
},
"score": 0.3424009084701538
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\remap_texture_paths.py",
"range": {
"startPosition": {
"line": 73
},
"endPosition": {
"line": 229
}
},
"contents": "def remap_texture_paths(blend_file_path, move_log_path):\n\n for image in bpy.data.images:\n if not image.filepath:\n continue\n \n # Convert to absolute path for comparison\n abs_path = bpy.path.abspath(image.filepath)\n if not abs_path:\n continue\n \n abs_norm = normalize_path(abs_path)\n was_relative = not os.path.isabs(image.filepath)\n \n # Check if this path needs remapping\n new_path = None\n \n # First check moved files\n if abs_norm in original_to_new:\n new_path = original_to_new[abs_norm]\n \n # Then check deleted files (replaced by)\n elif abs_norm in original_to_replacement:\n new_path = original_to_replacement[abs_norm]\n \n if new_path:\n # Convert to relative path if original was relative\n if was_relative:\n try:\n rel_path = bpy.path.relpath(new_path, blend_file_dir)\n image.filepath = rel_path\n except:\n # Fallback to absolute if relative conversion fails\n image.filepath = new_path\n else:\n image.filepath = new_path\n \n print(f\" Remapped: {os.path.basename(abs_path)} -> {os.path.basename(new_path)}\")\n remapped_count += 1\n else:\n # Check if file exists - if not, it might be a broken reference\n if not os.path.exists(abs_path):\n not_found_count += 1\n \n # Also check material node trees for image texture nodes\n # Note: Most image texture nodes reference the image datablock (which we already remapped above),\n # but we check node.filepath for completeness in case any nodes have direct file paths\n print(\"\\nRemapping material node texture paths...\")\n node_remapped_count = 0\n for material in bpy.data.materials:\n if",
"signatures": {
"ranges": [
{
"startPosition": {
"line": 74,
"column": 1
},
"endPosition": {
"line": 75,
"column": 5
}
}
]
},
"detailedLines": [
{
"text": "def remap_texture_paths(blend_file_path, move_log_path):",
"lineNumber": 74,
"isSignature": true
},
{
"lineNumber": 97
},
{
"text": " for image in bpy.data.images:",
"lineNumber": 98
},
{
"text": " if not image.filepath:",
"lineNumber": 99
},
{
"text": " continue",
"lineNumber": 100
},
{
"text": " ",
"lineNumber": 101
},
{
"text": " # Convert to absolute path for comparison",
"lineNumber": 102
},
{
"text": " abs_path = bpy.path.abspath(image.filepath)",
"lineNumber": 103
},
{
"text": " if not abs_path:",
"lineNumber": 104
},
{
"text": " continue",
"lineNumber": 105
},
{
"text": " ",
"lineNumber": 106
},
{
"text": " abs_norm = normalize_path(abs_path)",
"lineNumber": 107
},
{
"text": " was_relative = not os.path.isabs(image.filepath)",
"lineNumber": 108
},
{
"text": " ",
"lineNumber": 109
},
{
"text": " # Check if this path needs remapping",
"lineNumber": 110
},
{
"text": " new_path = None",
"lineNumber": 111
},
{
"text": " ",
"lineNumber": 112
},
{
"text": " # First check moved files",
"lineNumber": 113
},
{
"text": " if abs_norm in original_to_new:",
"lineNumber": 114
},
{
"text": " new_path = original_to_new[abs_norm]",
"lineNumber": 115
},
{
"text": " ",
"lineNumber": 116
},
{
"text": " # Then check deleted files (replaced by)",
"lineNumber": 117
},
{
"text": " elif abs_norm in original_to_replacement:",
"lineNumber": 118
},
{
"text": " new_path = original_to_replacement[abs_norm]",
"lineNumber": 119
},
{
"text": " ",
"lineNumber": 120
},
{
"text": " if new_path:",
"lineNumber": 121
},
{
"text": " # Convert to relative path if original was relative",
"lineNumber": 122
},
{
"text": " if was_relative:",
"lineNumber": 123
},
{
"text": " try:",
"lineNumber": 124
},
{
"text": " rel_path = bpy.path.relpath(new_path, blend_file_dir)",
"lineNumber": 125
},
{
"text": " image.filepath = rel_path",
"lineNumber": 126
},
{
"text": " except:",
"lineNumber": 127
},
{
"text": " # Fallback to absolute if relative conversion fails",
"lineNumber": 128
},
{
"text": " image.filepath = new_path",
"lineNumber": 129
},
{
"text": " else:",
"lineNumber": 130
},
{
"text": " image.filepath = new_path",
"lineNumber": 131
},
{
"text": " ",
"lineNumber": 132
},
{
"text": " print(f\" Remapped: {os.path.basename(abs_path)} -> {os.path.basename(new_path)}\")",
"lineNumber": 133
},
{
"text": " remapped_count += 1",
"lineNumber": 134
},
{
"text": " else:",
"lineNumber": 135
},
{
"text": " # Check if file exists - if not, it might be a broken reference",
"lineNumber": 136
},
{
"text": " if not os.path.exists(abs_path):",
"lineNumber": 137
},
{
"text": " not_found_count += 1",
"lineNumber": 138
},
{
"text": " ",
"lineNumber": 139
},
{
"text": " # Also check material node trees for image texture nodes",
"lineNumber": 140
},
{
"text": " # Note: Most image texture nodes reference the image datablock (which we already remapped above),",
"lineNumber": 141
},
{
"text": " # but we check node.filepath for completeness in case any nodes have direct file paths",
"lineNumber": 142
},
{
"text": " print(\"\\nRemapping material node texture paths...\")",
"lineNumber": 143
},
{
"text": " node_remapped_count = 0",
"lineNumber": 144
},
{
"text": " for material in bpy.data.materials:",
"lineNumber": 145
},
{
"text": " if",
"lineNumber": 146
}
]
},
"score": 0.3386910557746887
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\remap_texture_paths.py",
"range": {
"startPosition": {
"line": 73
},
"endPosition": {
"line": 229
}
},
"contents": "def remap_texture_paths(blend_file_path, move_log_path):\n\n abs_to_rel_count = 0\n for image in bpy.data.images:\n # Skip images from linked files (library datablocks)\n if image.library:\n continue\n \n if not image.filepath:\n continue\n \n # Check if path is absolute\n if os.path.isabs(image.filepath):\n try:\n # Convert to relative path\n rel_path = bpy.path.relpath(image.filepath, blend_file_dir)\n if rel_path != image.filepath:\n image.filepath = rel_path\n print(f\" Converted to relative: {os.path.basename(image.filepath)}\")\n abs_to_rel_count += 1\n except Exception as e:\n # If conversion fails, skip it (might be a network path or other issue)\n pass\n \n if abs_to_rel_count > 0:\n remapped_count += abs_to_rel_count\n \n print(f\"\\n=== REMAPPING SUMMARY ===\")\n print(f\"Paths remapped: {remapped_count}\")\n print(f\"Broken references (not found): {not_found_count}\")\n \n # Make all paths relative after remapping (this handles other datablock types)\n try:\n print(f\"\\nMaking paths relative...\")\n bpy.ops.file.make_paths_relative()\n print(f\" Converted absolute paths to relative paths\")\n except Exception as e:\n print(f\" Warning: Failed to make paths relative: {e}\")\n \n # Save the blend file\n try:\n print(f\"\\nSaving blend file...\")",
"signatures": {
"ranges": [
{
"startPosition": {
"line": 74,
"column": 1
},
"endPosition": {
"line": 75,
"column": 5
}
}
]
},
"detailedLines": [
{
"text": "def remap_texture_paths(blend_file_path, move_log_path):",
"lineNumber": 74,
"isSignature": true
},
{
"lineNumber": 171
},
{
"text": " abs_to_rel_count = 0",
"lineNumber": 172
},
{
"text": " for image in bpy.data.images:",
"lineNumber": 173
},
{
"text": " # Skip images from linked files (library datablocks)",
"lineNumber": 174
},
{
"text": " if image.library:",
"lineNumber": 175
},
{
"text": " continue",
"lineNumber": 176
},
{
"text": " ",
"lineNumber": 177
},
{
"text": " if not image.filepath:",
"lineNumber": 178
},
{
"text": " continue",
"lineNumber": 179
},
{
"text": " ",
"lineNumber": 180
},
{
"text": " # Check if path is absolute",
"lineNumber": 181
},
{
"text": " if os.path.isabs(image.filepath):",
"lineNumber": 182
},
{
"text": " try:",
"lineNumber": 183
},
{
"text": " # Convert to relative path",
"lineNumber": 184
},
{
"text": " rel_path = bpy.path.relpath(image.filepath, blend_file_dir)",
"lineNumber": 185
},
{
"text": " if rel_path != image.filepath:",
"lineNumber": 186
},
{
"text": " image.filepath = rel_path",
"lineNumber": 187
},
{
"text": " print(f\" Converted to relative: {os.path.basename(image.filepath)}\")",
"lineNumber": 188
},
{
"text": " abs_to_rel_count += 1",
"lineNumber": 189
},
{
"text": " except Exception as e:",
"lineNumber": 190
},
{
"text": " # If conversion fails, skip it (might be a network path or other issue)",
"lineNumber": 191
},
{
"text": " pass",
"lineNumber": 192
},
{
"text": " ",
"lineNumber": 193
},
{
"text": " if abs_to_rel_count > 0:",
"lineNumber": 194
},
{
"text": " remapped_count += abs_to_rel_count",
"lineNumber": 195
},
{
"text": " ",
"lineNumber": 196
},
{
"text": " print(f\"\\n=== REMAPPING SUMMARY ===\")",
"lineNumber": 197
},
{
"text": " print(f\"Paths remapped: {remapped_count}\")",
"lineNumber": 198
},
{
"text": " print(f\"Broken references (not found): {not_found_count}\")",
"lineNumber": 199
},
{
"text": " ",
"lineNumber": 200
},
{
"text": " # Make all paths relative after remapping (this handles other datablock types)",
"lineNumber": 201
},
{
"text": " try:",
"lineNumber": 202
},
{
"text": " print(f\"\\nMaking paths relative...\")",
"lineNumber": 203
},
{
"text": " bpy.ops.file.make_paths_relative()",
"lineNumber": 204
},
{
"text": " print(f\" Converted absolute paths to relative paths\")",
"lineNumber": 205
},
{
"text": " except Exception as e:",
"lineNumber": 206
},
{
"text": " print(f\" Warning: Failed to make paths relative: {e}\")",
"lineNumber": 207
},
{
"text": " ",
"lineNumber": 208
},
{
"text": " # Save the blend file",
"lineNumber": 209
},
{
"text": " try:",
"lineNumber": 210
},
{
"text": " print(f\"\\nSaving blend file...\")",
"lineNumber": 211
}
]
},
"score": 0.33739519119262695
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\UpdateProjectBatches.ps1",
"range": {
"startPosition": {
"line": 55
},
"endPosition": {
"line": 115
}
},
"contents": ")\n\n# Config files to deploy to projectroot\\.config\\\n$configAssets = @(\n @{ Name = 'config.json'; Source = Join-Path -Path $structDir -ChildPath 'config.json' },\n @{ Name = 'GetStructDir.ps1'; Source = Join-Path -Path $structDir -ChildPath 'GetStructDir.ps1' }\n)\n\nforeach ($spec in $specs) {\n if (-not (Test-Path -LiteralPath $spec.Source -PathType Leaf)) {\n Write-Error \"Source file not found: $($spec.Source)\"\n exit 1\n }\n}\n\nforeach ($asset in $configAssets) {\n if (-not (Test-Path -LiteralPath $asset.Source -PathType Leaf)) {\n Write-Error \"Config asset not found: $($asset.Source)\"\n exit 1\n }\n}\n\n# Ensure .config directory exists in project root\n$projectConfigDir = Join-Path -Path $resolvedProject -ChildPath '.config'\nif (-not (Test-Path -LiteralPath $projectConfigDir -PathType Container)) {\n New-Item -Path $projectConfigDir -ItemType Directory -Force | Out-Null\n Write-Host \"Created .config directory: $projectConfigDir\" -ForegroundColor Cyan\n}\n\n$touchedDirs = @{}\n$summary = @()\n\nforeach ($spec in $specs) {\n Write-Host \"`n=== Updating $($spec.Name) ===\" -ForegroundColor Magenta\n\n $targets = Get-ChildItem -LiteralPath $resolvedProject -Recurse -Filter $spec.Name -File -ErrorAction SilentlyContinue\n $targets = $targets | Where-Object { $_.FullName -ne $spec.Source }\n\n if (-not $targets) {\n Write-Host \"No targets found.\" -ForegroundColor Yellow\n $summary += [pscustomobject]@{\n Name = $spec.Name\n Updated = 0\n Failed = 0\n Skipped = 0\n Total = 0\n }\n continue\n }\n\n $updated = 0\n $failed = 0\n\n foreach ($target in $targets) {\n try {\n Copy-Item -Path $spec.Source -Destination $target.FullName -Force\n Write-Host \"[OK] $($target.FullName)\" -ForegroundColor Green\n $updated++\n\n $targetDir = $target.Directory.FullName",
"signatures": {},
"detailedLines": [
{
"text": ")",
"lineNumber": 56
},
{
"lineNumber": 57
},
{
"text": "# Config files to deploy to projectroot\\.config\\",
"lineNumber": 58
},
{
"text": "$configAssets = @(",
"lineNumber": 59
},
{
"text": " @{ Name = 'config.json'; Source = Join-Path -Path $structDir -ChildPath 'config.json' },",
"lineNumber": 60
},
{
"text": " @{ Name = 'GetStructDir.ps1'; Source = Join-Path -Path $structDir -ChildPath 'GetStructDir.ps1' }",
"lineNumber": 61
},
{
"text": ")",
"lineNumber": 62
},
{
"lineNumber": 63
},
{
"text": "foreach ($spec in $specs) {",
"lineNumber": 64
},
{
"text": " if (-not (Test-Path -LiteralPath $spec.Source -PathType Leaf)) {",
"lineNumber": 65
},
{
"text": " Write-Error \"Source file not found: $($spec.Source)\"",
"lineNumber": 66
},
{
"text": " exit 1",
"lineNumber": 67
},
{
"text": " }",
"lineNumber": 68
},
{
"text": "}",
"lineNumber": 69
},
{
"lineNumber": 70
},
{
"text": "foreach ($asset in $configAssets) {",
"lineNumber": 71
},
{
"text": " if (-not (Test-Path -LiteralPath $asset.Source -PathType Leaf)) {",
"lineNumber": 72
},
{
"text": " Write-Error \"Config asset not found: $($asset.Source)\"",
"lineNumber": 73
},
{
"text": " exit 1",
"lineNumber": 74
},
{
"text": " }",
"lineNumber": 75
},
{
"text": "}",
"lineNumber": 76
},
{
"lineNumber": 77
},
{
"text": "# Ensure .config directory exists in project root",
"lineNumber": 78
},
{
"text": "$projectConfigDir = Join-Path -Path $resolvedProject -ChildPath '.config'",
"lineNumber": 79
},
{
"text": "if (-not (Test-Path -LiteralPath $projectConfigDir -PathType Container)) {",
"lineNumber": 80
},
{
"text": " New-Item -Path $projectConfigDir -ItemType Directory -Force | Out-Null",
"lineNumber": 81
},
{
"text": " Write-Host \"Created .config directory: $projectConfigDir\" -ForegroundColor Cyan",
"lineNumber": 82
},
{
"text": "}",
"lineNumber": 83
},
{
"lineNumber": 84
},
{
"text": "$touchedDirs = @{}",
"lineNumber": 85
},
{
"text": "$summary = @()",
"lineNumber": 86
},
{
"lineNumber": 87
},
{
"text": "foreach ($spec in $specs) {",
"lineNumber": 88
},
{
"text": " Write-Host \"`n=== Updating $($spec.Name) ===\" -ForegroundColor Magenta",
"lineNumber": 89
},
{
"lineNumber": 90
},
{
"text": " $targets = Get-ChildItem -LiteralPath $resolvedProject -Recurse -Filter $spec.Name -File -ErrorAction SilentlyContinue",
"lineNumber": 91
},
{
"text": " $targets = $targets | Where-Object { $_.FullName -ne $spec.Source }",
"lineNumber": 92
},
{
"lineNumber": 93
},
{
"text": " if (-not $targets) {",
"lineNumber": 94
},
{
"text": " Write-Host \"No targets found.\" -ForegroundColor Yellow",
"lineNumber": 95
},
{
"text": " $summary += [pscustomobject]@{",
"lineNumber": 96
},
{
"text": " Name = $spec.Name",
"lineNumber": 97
},
{
"text": " Updated = 0",
"lineNumber": 98
},
{
"text": " Failed = 0",
"lineNumber": 99
},
{
"text": " Skipped = 0",
"lineNumber": 100
},
{
"text": " Total = 0",
"lineNumber": 101
},
{
"text": " }",
"lineNumber": 102
},
{
"text": " continue",
"lineNumber": 103
},
{
"text": " }",
"lineNumber": 104
},
{
"lineNumber": 105
},
{
"text": " $updated = 0",
"lineNumber": 106
},
{
"text": " $failed = 0",
"lineNumber": 107
},
{
"lineNumber": 108
},
{
"text": " foreach ($target in $targets) {",
"lineNumber": 109
},
{
"text": " try {",
"lineNumber": 110
},
{
"text": " Copy-Item -Path $spec.Source -Destination $target.FullName -Force",
"lineNumber": 111
},
{
"text": " Write-Host \"[OK] $($target.FullName)\" -ForegroundColor Green",
"lineNumber": 112
},
{
"text": " $updated++",
"lineNumber": 113
},
{
"lineNumber": 114
},
{
"text": " $targetDir = $target.Directory.FullName",
"lineNumber": 115
}
]
},
"score": 0.3361758887767792
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 355
},
"endPosition": {
"line": 390
}
},
"contents": "$allFlatColorsFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { \n ($_.FullName -like \"*\\FlatColors\\*\" -or $_.Name -like \"*FlatColors*\") -and \n $_.FullName -notlike \"$([regex]::Escape($rootCommonFlatColorsPath))\\*\" \n}\n\n# Get all remaining files (excluding all \\common folders, but we'll handle FlatColors separately)\nWrite-Host \"Collecting remaining files...\" -ForegroundColor Yellow\n$remainingFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { $_.FullName -notlike \"*\\common\\*\" }\n\nif ($null -eq $remainingFiles -or $remainingFiles.Count -eq 0) {\n Write-Host \"No remaining files found to process.\" -ForegroundColor Yellow\n} else {\n Write-Host \"Found $($remainingFiles.Count) remaining files to process.\" -ForegroundColor Green\n \n # Calculate checksums\n Write-Host \"Calculating checksums using parallel processing (this may take a while)...\" -ForegroundColor Yellow\n $filesWithChecksums = Get-FilesWithChecksums -Files $remainingFiles\n \n Write-Host \"Checksum calculation complete.\" -ForegroundColor Green\n \n # Separate FlatColors files from other files before processing\n Write-Host \"Identifying FlatColors files...\" -ForegroundColor Yellow\n $flatColorsFiles = $allFlatColorsFiles | Where-Object { (Test-Path -Path $_.FullName) }\n $nonFlatColorsFiles = $remainingFiles | Where-Object { $_.Name -notlike \"*FlatColors*\" }\n \n Write-Host \"Found $($flatColorsFiles.Count) FlatColors file(s) (including from \\common\\FlatColors folders), $($nonFlatColorsFiles.Count) other file(s)\" -ForegroundColor Gray\n \n # Group non-FlatColors files by checksum\n Write-Host \"Grouping files by checksum...\" -ForegroundColor Yellow\n $nonFlatColorsWithChecksums = $filesWithChecksums | Where-Object { $_.File.Name -notlike \"*FlatColors*\" }\n $groupedByChecksum = $nonFlatColorsWithChecksums | Group-Object -Property Hash\n \n Write-Host \"Found $($groupedByChecksum.Count) unique checksums.\" -ForegroundColor Green\n \n # Create \\textures\\common directory",
"signatures": {},
"detailedLines": [
{
"text": "$allFlatColorsFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { ",
"lineNumber": 356
},
{
"text": " ($_.FullName -like \"*\\FlatColors\\*\" -or $_.Name -like \"*FlatColors*\") -and ",
"lineNumber": 357
},
{
"text": " $_.FullName -notlike \"$([regex]::Escape($rootCommonFlatColorsPath))\\*\" ",
"lineNumber": 358
},
{
"text": "}",
"lineNumber": 359
},
{
"lineNumber": 360
},
{
"text": "# Get all remaining files (excluding all \\common folders, but we'll handle FlatColors separately)",
"lineNumber": 361
},
{
"text": "Write-Host \"Collecting remaining files...\" -ForegroundColor Yellow",
"lineNumber": 362
},
{
"text": "$remainingFiles = Get-ChildItem -Path $textureFolderPath -Recurse -File | Where-Object { $_.FullName -notlike \"*\\common\\*\" }",
"lineNumber": 363
},
{
"lineNumber": 364
},
{
"text": "if ($null -eq $remainingFiles -or $remainingFiles.Count -eq 0) {",
"lineNumber": 365
},
{
"text": " Write-Host \"No remaining files found to process.\" -ForegroundColor Yellow",
"lineNumber": 366
},
{
"text": "} else {",
"lineNumber": 367
},
{
"text": " Write-Host \"Found $($remainingFiles.Count) remaining files to process.\" -ForegroundColor Green",
"lineNumber": 368
},
{
"text": " ",
"lineNumber": 369
},
{
"text": " # Calculate checksums",
"lineNumber": 370
},
{
"text": " Write-Host \"Calculating checksums using parallel processing (this may take a while)...\" -ForegroundColor Yellow",
"lineNumber": 371
},
{
"text": " $filesWithChecksums = Get-FilesWithChecksums -Files $remainingFiles",
"lineNumber": 372
},
{
"text": " ",
"lineNumber": 373
},
{
"text": " Write-Host \"Checksum calculation complete.\" -ForegroundColor Green",
"lineNumber": 374
},
{
"text": " ",
"lineNumber": 375
},
{
"text": " # Separate FlatColors files from other files before processing",
"lineNumber": 376
},
{
"text": " Write-Host \"Identifying FlatColors files...\" -ForegroundColor Yellow",
"lineNumber": 377
},
{
"text": " $flatColorsFiles = $allFlatColorsFiles | Where-Object { (Test-Path -Path $_.FullName) }",
"lineNumber": 378
},
{
"text": " $nonFlatColorsFiles = $remainingFiles | Where-Object { $_.Name -notlike \"*FlatColors*\" }",
"lineNumber": 379
},
{
"text": " ",
"lineNumber": 380
},
{
"text": " Write-Host \"Found $($flatColorsFiles.Count) FlatColors file(s) (including from \\common\\FlatColors folders), $($nonFlatColorsFiles.Count) other file(s)\" -ForegroundColor Gray",
"lineNumber": 381
},
{
"text": " ",
"lineNumber": 382
},
{
"text": " # Group non-FlatColors files by checksum",
"lineNumber": 383
},
{
"text": " Write-Host \"Grouping files by checksum...\" -ForegroundColor Yellow",
"lineNumber": 384
},
{
"text": " $nonFlatColorsWithChecksums = $filesWithChecksums | Where-Object { $_.File.Name -notlike \"*FlatColors*\" }",
"lineNumber": 385
},
{
"text": " $groupedByChecksum = $nonFlatColorsWithChecksums | Group-Object -Property Hash",
"lineNumber": 386
},
{
"text": " ",
"lineNumber": 387
},
{
"text": " Write-Host \"Found $($groupedByChecksum.Count) unique checksums.\" -ForegroundColor Green",
"lineNumber": 388
},
{
"text": " ",
"lineNumber": 389
},
{
"text": " # Create \\textures\\common directory",
"lineNumber": 390
}
]
},
"score": 0.33034563064575195
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 279
},
"endPosition": {
"line": 325
}
},
"contents": "} else {\n Write-Host \"Found $($blendfileFolders.Count) blendfile folder(s) to process.\" -ForegroundColor Green\n \n $totalPass1Moved = 0\n $totalPass1Duplicates = 0\n $pass1MoveLog = [System.Collections.ArrayList]::new()\n \n foreach ($blendfileFolder in $blendfileFolders) {\n Write-Host \"\"\n Write-Host \"Processing blendfile: $($blendfileFolder.Name)\" -ForegroundColor Yellow\n \n # Get all files in this blendfile folder, excluding \\common folders\n $blendfileFiles = Get-ChildItem -Path $blendfileFolder.FullName -Recurse -File | Where-Object { $_.FullName -notlike \"*\\common\\*\" }\n \n if ($null -eq $blendfileFiles -or $blendfileFiles.Count -eq 0) {\n Write-Host \" No files found in this blendfile folder.\" -ForegroundColor Gray\n continue\n }\n \n Write-Host \" Found $($blendfileFiles.Count) files.\" -ForegroundColor Gray\n \n # Calculate checksums\n Write-Host \" Calculating checksums...\" -ForegroundColor Gray\n $filesWithChecksums = Get-FilesWithChecksums -Files $blendfileFiles\n \n # Group by checksum\n $groupedByChecksum = $filesWithChecksums | Group-Object -Property Hash\n \n Write-Host \" Found $($groupedByChecksum.Count) unique checksums.\" -ForegroundColor Gray\n \n # Create [blendfile]\\common directory\n $blendfileCommonPath = Join-Path -Path $blendfileFolder.FullName -ChildPath \"common\"\n \n if (-not (Test-Path -Path $blendfileCommonPath -PathType Container)) {\n New-Item -ItemType Directory -Path $blendfileCommonPath | Out-Null\n }\n \n # Track filenames already in [blendfile]\\common\n $filesInBlendfileCommon = @{}\n \n # Process each checksum group\n $blendfileMoved = 0\n $blendfileDuplicates = 0\n \n foreach ($group in $groupedByChecksum) {\n $result = Process-DuplicateGroup -Files $group.Group -CommonPath $blendfileCommonPath -FilesInCommon $filesInBlendfileCommon -MoveLog $pass1MoveLog",
"signatures": {},
"detailedLines": [
{
"text": "} else {",
"lineNumber": 280
},
{
"text": " Write-Host \"Found $($blendfileFolders.Count) blendfile folder(s) to process.\" -ForegroundColor Green",
"lineNumber": 281
},
{
"text": " ",
"lineNumber": 282
},
{
"text": " $totalPass1Moved = 0",
"lineNumber": 283
},
{
"text": " $totalPass1Duplicates = 0",
"lineNumber": 284
},
{
"text": " $pass1MoveLog = [System.Collections.ArrayList]::new()",
"lineNumber": 285
},
{
"text": " ",
"lineNumber": 286
},
{
"text": " foreach ($blendfileFolder in $blendfileFolders) {",
"lineNumber": 287
},
{
"text": " Write-Host \"\"",
"lineNumber": 288
},
{
"text": " Write-Host \"Processing blendfile: $($blendfileFolder.Name)\" -ForegroundColor Yellow",
"lineNumber": 289
},
{
"text": " ",
"lineNumber": 290
},
{
"text": " # Get all files in this blendfile folder, excluding \\common folders",
"lineNumber": 291
},
{
"text": " $blendfileFiles = Get-ChildItem -Path $blendfileFolder.FullName -Recurse -File | Where-Object { $_.FullName -notlike \"*\\common\\*\" }",
"lineNumber": 292
},
{
"text": " ",
"lineNumber": 293
},
{
"text": " if ($null -eq $blendfileFiles -or $blendfileFiles.Count -eq 0) {",
"lineNumber": 294
},
{
"text": " Write-Host \" No files found in this blendfile folder.\" -ForegroundColor Gray",
"lineNumber": 295
},
{
"text": " continue",
"lineNumber": 296
},
{
"text": " }",
"lineNumber": 297
},
{
"text": " ",
"lineNumber": 298
},
{
"text": " Write-Host \" Found $($blendfileFiles.Count) files.\" -ForegroundColor Gray",
"lineNumber": 299
},
{
"text": " ",
"lineNumber": 300
},
{
"text": " # Calculate checksums",
"lineNumber": 301
},
{
"text": " Write-Host \" Calculating checksums...\" -ForegroundColor Gray",
"lineNumber": 302
},
{
"text": " $filesWithChecksums = Get-FilesWithChecksums -Files $blendfileFiles",
"lineNumber": 303
},
{
"text": " ",
"lineNumber": 304
},
{
"text": " # Group by checksum",
"lineNumber": 305
},
{
"text": " $groupedByChecksum = $filesWithChecksums | Group-Object -Property Hash",
"lineNumber": 306
},
{
"text": " ",
"lineNumber": 307
},
{
"text": " Write-Host \" Found $($groupedByChecksum.Count) unique checksums.\" -ForegroundColor Gray",
"lineNumber": 308
},
{
"text": " ",
"lineNumber": 309
},
{
"text": " # Create [blendfile]\\common directory",
"lineNumber": 310
},
{
"text": " $blendfileCommonPath = Join-Path -Path $blendfileFolder.FullName -ChildPath \"common\"",
"lineNumber": 311
},
{
"text": " ",
"lineNumber": 312
},
{
"text": " if (-not (Test-Path -Path $blendfileCommonPath -PathType Container)) {",
"lineNumber": 313
},
{
"text": " New-Item -ItemType Directory -Path $blendfileCommonPath | Out-Null",
"lineNumber": 314
},
{
"text": " }",
"lineNumber": 315
},
{
"text": " ",
"lineNumber": 316
},
{
"text": " # Track filenames already in [blendfile]\\common",
"lineNumber": 317
},
{
"text": " $filesInBlendfileCommon = @{}",
"lineNumber": 318
},
{
"text": " ",
"lineNumber": 319
},
{
"text": " # Process each checksum group",
"lineNumber": 320
},
{
"text": " $blendfileMoved = 0",
"lineNumber": 321
},
{
"text": " $blendfileDuplicates = 0",
"lineNumber": 322
},
{
"text": " ",
"lineNumber": 323
},
{
"text": " foreach ($group in $groupedByChecksum) {",
"lineNumber": 324
},
{
"text": " $result = Process-DuplicateGroup -Files $group.Group -CommonPath $blendfileCommonPath -FilesInCommon $filesInBlendfileCommon -MoveLog $pass1MoveLog",
"lineNumber": 325
}
]
},
"score": 0.32454758882522583
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\remove_action_fake_users.bat",
"range": {
"startPosition": {
"line": 64
},
"endPosition": {
"line": 107
}
},
"contents": "echo ^\t\t\t# Save to output folder\necho ^\t\t\tbpy.ops.wm.save_mainfile^(filepath=output_file, compress=True^)\necho ^\t\t\tprint^(\"SUCCESS:\" + blend_file + \":\" + output_file^)\necho ^\t\texcept Exception as e:\necho ^\t\t\tprint^(\"CRASH:\" + blend_file + \":\" + str^(e^)^)\necho ^\telse:\necho ^\t\tprint^(\"SKIP_NOT_BLEND:\" + blend_file^)\necho.\necho print^(\"FAKE_USER_REMOVAL_COMPLETE\"^)\necho bpy.ops.wm.quit_blender^(^)\n) > \"!TEMP_SCRIPT!\"\n\nREM Check if script was created successfully\nif exist \"!TEMP_SCRIPT!\" (\n\techo Script created successfully: !TEMP_SCRIPT!\n) else (\n\techo ERROR: Failed to create script file!\n\tpause\n\texit /b 1\n)\n\nREM Run Blender to process the dragged files\necho Processing dragged .blend files...\necho Using script: !TEMP_SCRIPT!\ndel /f /q \"blender_output.txt\" 2>nul\nblender --background --factory-startup --python \"!TEMP_SCRIPT!\" -- %* 2^>^&1 | powershell -NoProfile -Command \"$input | Tee-Object -FilePath 'blender_output.txt'\"\n\nREM Clean up temporary script\necho Cleaning up temporary script...\ndel \"!TEMP_SCRIPT!\" 2>nul\n\nREM Parse output and generate report\necho.\necho ========================================\necho ACTION FAKE USER REMOVAL REPORT\necho ========================================\necho.\n\nREM Track updated counts per file during parse\nfor /f \"tokens=1,2,3 delims=:\" %%a in (blender_output.txt) do (\n\tif \"%%a\"==\"SUCCESS\" (\n\t\tset /a processed+=1\n\t\techo [!processed!] SUCCESS: %%b",
"signatures": {},
"detailedLines": [
{
"text": "echo ^\t\t\t# Save to output folder",
"lineNumber": 65
},
{
"text": "echo ^\t\t\tbpy.ops.wm.save_mainfile^(filepath=output_file, compress=True^)",
"lineNumber": 66
},
{
"text": "echo ^\t\t\tprint^(\"SUCCESS:\" + blend_file + \":\" + output_file^)",
"lineNumber": 67
},
{
"text": "echo ^\t\texcept Exception as e:",
"lineNumber": 68
},
{
"text": "echo ^\t\t\tprint^(\"CRASH:\" + blend_file + \":\" + str^(e^)^)",
"lineNumber": 69
},
{
"text": "echo ^\telse:",
"lineNumber": 70
},
{
"text": "echo ^\t\tprint^(\"SKIP_NOT_BLEND:\" + blend_file^)",
"lineNumber": 71
},
{
"text": "echo.",
"lineNumber": 72
},
{
"text": "echo print^(\"FAKE_USER_REMOVAL_COMPLETE\"^)",
"lineNumber": 73
},
{
"text": "echo bpy.ops.wm.quit_blender^(^)",
"lineNumber": 74
},
{
"text": ") > \"!TEMP_SCRIPT!\"",
"lineNumber": 75
},
{
"lineNumber": 76
},
{
"text": "REM Check if script was created successfully",
"lineNumber": 77
},
{
"text": "if exist \"!TEMP_SCRIPT!\" (",
"lineNumber": 78
},
{
"text": "\techo Script created successfully: !TEMP_SCRIPT!",
"lineNumber": 79
},
{
"text": ") else (",
"lineNumber": 80
},
{
"text": "\techo ERROR: Failed to create script file!",
"lineNumber": 81
},
{
"text": "\tpause",
"lineNumber": 82
},
{
"text": "\texit /b 1",
"lineNumber": 83
},
{
"text": ")",
"lineNumber": 84
},
{
"lineNumber": 85
},
{
"text": "REM Run Blender to process the dragged files",
"lineNumber": 86
},
{
"text": "echo Processing dragged .blend files...",
"lineNumber": 87
},
{
"text": "echo Using script: !TEMP_SCRIPT!",
"lineNumber": 88
},
{
"text": "del /f /q \"blender_output.txt\" 2>nul",
"lineNumber": 89
},
{
"text": "blender --background --factory-startup --python \"!TEMP_SCRIPT!\" -- %* 2^>^&1 | powershell -NoProfile -Command \"$input | Tee-Object -FilePath 'blender_output.txt'\"",
"lineNumber": 90
},
{
"lineNumber": 91
},
{
"text": "REM Clean up temporary script",
"lineNumber": 92
},
{
"text": "echo Cleaning up temporary script...",
"lineNumber": 93
},
{
"text": "del \"!TEMP_SCRIPT!\" 2>nul",
"lineNumber": 94
},
{
"lineNumber": 95
},
{
"text": "REM Parse output and generate report",
"lineNumber": 96
},
{
"text": "echo.",
"lineNumber": 97
},
{
"text": "echo ========================================",
"lineNumber": 98
},
{
"text": "echo ACTION FAKE USER REMOVAL REPORT",
"lineNumber": 99
},
{
"text": "echo ========================================",
"lineNumber": 100
},
{
"text": "echo.",
"lineNumber": 101
},
{
"lineNumber": 102
},
{
"text": "REM Track updated counts per file during parse",
"lineNumber": 103
},
{
"text": "for /f \"tokens=1,2,3 delims=:\" %%a in (blender_output.txt) do (",
"lineNumber": 104
},
{
"text": "\tif \"%%a\"==\"SUCCESS\" (",
"lineNumber": 105
},
{
"text": "\t\tset /a processed+=1",
"lineNumber": 106
},
{
"text": "\t\techo [!processed!] SUCCESS: %%b",
"lineNumber": 107
}
]
},
"score": 0.3208807110786438
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\ConfigLoader.ps1",
"range": {
"startPosition": {
"line": 307
},
"endPosition": {
"line": 354
}
},
"contents": " foreach ($spec in $specs) {\n Write-Host \"`n=== Updating $($spec.Name) ===\" -ForegroundColor Magenta\n\n $targets = Get-ChildItem -LiteralPath $resolvedProject -Recurse -Filter $spec.Name -File -Force -ErrorAction SilentlyContinue\n $targets = $targets | Where-Object { $_.FullName -ne $spec.Source }\n\n if (-not $targets) {\n Write-Host \"No targets found.\" -ForegroundColor Yellow\n $summary += [pscustomobject]@{\n Name = $spec.Name\n Updated = 0\n Failed = 0\n Skipped = 0\n Total = 0\n }\n continue\n }\n\n $updated = 0\n $failed = 0\n\n foreach ($target in $targets) {\n try {\n Copy-Item -Path $spec.Source -Destination $target.FullName -Force\n # Set hidden attribute for .gitattributes and .gitignore files\n if ($spec.Name -eq '.gitattributes' -or $spec.Name -eq '.gitignore') {\n $file = Get-Item -LiteralPath $target.FullName -Force\n $file.Attributes = $file.Attributes -bor [System.IO.FileAttributes]::Hidden\n }\n Write-Host \"[OK] $($target.FullName)\" -ForegroundColor Green\n $updated++\n\n $targetDir = $target.Directory.FullName\n if (-not $touchedDirs.ContainsKey($targetDir)) {\n $touchedDirs[$targetDir] = $true\n }\n }\n catch {\n Write-Host \"[FAIL] $($target.FullName)\" -ForegroundColor Red\n Write-Host \" $($_.Exception.Message)\" -ForegroundColor DarkRed\n $failed++\n }\n }\n\n $summary += [pscustomobject]@{\n Name = $spec.Name\n Updated = $updated",
"signatures": {},
"detailedLines": [
{
"text": " foreach ($spec in $specs) {",
"lineNumber": 308
},
{
"text": " Write-Host \"`n=== Updating $($spec.Name) ===\" -ForegroundColor Magenta",
"lineNumber": 309
},
{
"lineNumber": 310
},
{
"text": " $targets = Get-ChildItem -LiteralPath $resolvedProject -Recurse -Filter $spec.Name -File -Force -ErrorAction SilentlyContinue",
"lineNumber": 311
},
{
"text": " $targets = $targets | Where-Object { $_.FullName -ne $spec.Source }",
"lineNumber": 312
},
{
"lineNumber": 313
},
{
"text": " if (-not $targets) {",
"lineNumber": 314
},
{
"text": " Write-Host \"No targets found.\" -ForegroundColor Yellow",
"lineNumber": 315
},
{
"text": " $summary += [pscustomobject]@{",
"lineNumber": 316
},
{
"text": " Name = $spec.Name",
"lineNumber": 317
},
{
"text": " Updated = 0",
"lineNumber": 318
},
{
"text": " Failed = 0",
"lineNumber": 319
},
{
"text": " Skipped = 0",
"lineNumber": 320
},
{
"text": " Total = 0",
"lineNumber": 321
},
{
"text": " }",
"lineNumber": 322
},
{
"text": " continue",
"lineNumber": 323
},
{
"text": " }",
"lineNumber": 324
},
{
"lineNumber": 325
},
{
"text": " $updated = 0",
"lineNumber": 326
},
{
"text": " $failed = 0",
"lineNumber": 327
},
{
"lineNumber": 328
},
{
"text": " foreach ($target in $targets) {",
"lineNumber": 329
},
{
"text": " try {",
"lineNumber": 330
},
{
"text": " Copy-Item -Path $spec.Source -Destination $target.FullName -Force",
"lineNumber": 331
},
{
"text": " # Set hidden attribute for .gitattributes and .gitignore files",
"lineNumber": 332
},
{
"text": " if ($spec.Name -eq '.gitattributes' -or $spec.Name -eq '.gitignore') {",
"lineNumber": 333
},
{
"text": " $file = Get-Item -LiteralPath $target.FullName -Force",
"lineNumber": 334
},
{
"text": " $file.Attributes = $file.Attributes -bor [System.IO.FileAttributes]::Hidden",
"lineNumber": 335
},
{
"text": " }",
"lineNumber": 336
},
{
"text": " Write-Host \"[OK] $($target.FullName)\" -ForegroundColor Green",
"lineNumber": 337
},
{
"text": " $updated++",
"lineNumber": 338
},
{
"lineNumber": 339
},
{
"text": " $targetDir = $target.Directory.FullName",
"lineNumber": 340
},
{
"text": " if (-not $touchedDirs.ContainsKey($targetDir)) {",
"lineNumber": 341
},
{
"text": " $touchedDirs[$targetDir] = $true",
"lineNumber": 342
},
{
"text": " }",
"lineNumber": 343
},
{
"text": " }",
"lineNumber": 344
},
{
"text": " catch {",
"lineNumber": 345
},
{
"text": " Write-Host \"[FAIL] $($target.FullName)\" -ForegroundColor Red",
"lineNumber": 346
},
{
"text": " Write-Host \" $($_.Exception.Message)\" -ForegroundColor DarkRed",
"lineNumber": 347
},
{
"text": " $failed++",
"lineNumber": 348
},
{
"text": " }",
"lineNumber": 349
},
{
"text": " }",
"lineNumber": 350
},
{
"lineNumber": 351
},
{
"text": " $summary += [pscustomobject]@{",
"lineNumber": 352
},
{
"text": " Name = $spec.Name",
"lineNumber": 353
},
{
"text": " Updated = $updated",
"lineNumber": 354
}
]
},
"score": 0.3176653981208801
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\remap_texture_paths.py",
"range": {
"startPosition": {
"line": 73
},
"endPosition": {
"line": 229
}
},
"contents": "def remap_texture_paths(blend_file_path, move_log_path):\n\n for material in bpy.data.materials:\n if not material.use_nodes or not material.node_tree:\n continue\n \n for node in material.node_tree.nodes:\n if node.type == 'TEX_IMAGE' and hasattr(node, 'filepath') and node.filepath:\n abs_path = bpy.path.abspath(node.filepath)\n if abs_path:\n abs_norm = normalize_path(abs_path)\n \n new_path = None\n if abs_norm in original_to_new:\n new_path = original_to_new[abs_norm]\n elif abs_norm in original_to_replacement:\n new_path = original_to_replacement[abs_norm]\n \n if new_path:\n node.filepath = new_path\n print(f\" Remapped node texture: {os.path.basename(abs_path)} -> {os.path.basename(new_path)}\")\n node_remapped_count += 1\n \n if node_remapped_count > 0:\n remapped_count += node_remapped_count\n \n # Convert any remaining absolute paths in image datablocks to relative\n # (ignoring images from linked files)\n print(\"\\nConverting absolute image paths to relative...\")\n abs_to_rel_count = 0\n for image in bpy.data.images:\n # Skip images from linked files (library datablocks)",
"signatures": {
"ranges": [
{
"startPosition": {
"line": 74,
"column": 1
},
"endPosition": {
"line": 75,
"column": 5
}
}
]
},
"detailedLines": [
{
"text": "def remap_texture_paths(blend_file_path, move_log_path):",
"lineNumber": 74,
"isSignature": true
},
{
"lineNumber": 144
},
{
"text": " for material in bpy.data.materials:",
"lineNumber": 145
},
{
"text": " if not material.use_nodes or not material.node_tree:",
"lineNumber": 146
},
{
"text": " continue",
"lineNumber": 147
},
{
"text": " ",
"lineNumber": 148
},
{
"text": " for node in material.node_tree.nodes:",
"lineNumber": 149
},
{
"text": " if node.type == 'TEX_IMAGE' and hasattr(node, 'filepath') and node.filepath:",
"lineNumber": 150
},
{
"text": " abs_path = bpy.path.abspath(node.filepath)",
"lineNumber": 151
},
{
"text": " if abs_path:",
"lineNumber": 152
},
{
"text": " abs_norm = normalize_path(abs_path)",
"lineNumber": 153
},
{
"text": " ",
"lineNumber": 154
},
{
"text": " new_path = None",
"lineNumber": 155
},
{
"text": " if abs_norm in original_to_new:",
"lineNumber": 156
},
{
"text": " new_path = original_to_new[abs_norm]",
"lineNumber": 157
},
{
"text": " elif abs_norm in original_to_replacement:",
"lineNumber": 158
},
{
"text": " new_path = original_to_replacement[abs_norm]",
"lineNumber": 159
},
{
"text": " ",
"lineNumber": 160
},
{
"text": " if new_path:",
"lineNumber": 161
},
{
"text": " node.filepath = new_path",
"lineNumber": 162
},
{
"text": " print(f\" Remapped node texture: {os.path.basename(abs_path)} -> {os.path.basename(new_path)}\")",
"lineNumber": 163
},
{
"text": " node_remapped_count += 1",
"lineNumber": 164
},
{
"text": " ",
"lineNumber": 165
},
{
"text": " if node_remapped_count > 0:",
"lineNumber": 166
},
{
"text": " remapped_count += node_remapped_count",
"lineNumber": 167
},
{
"text": " ",
"lineNumber": 168
},
{
"text": " # Convert any remaining absolute paths in image datablocks to relative",
"lineNumber": 169
},
{
"text": " # (ignoring images from linked files)",
"lineNumber": 170
},
{
"text": " print(\"\\nConverting absolute image paths to relative...\")",
"lineNumber": 171
},
{
"text": " abs_to_rel_count = 0",
"lineNumber": 172
},
{
"text": " for image in bpy.data.images:",
"lineNumber": 173
},
{
"text": " # Skip images from linked files (library datablocks)",
"lineNumber": 174
}
]
},
"score": 0.3171687126159668
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 93
},
"endPosition": {
"line": 131
}
},
"contents": "function Get-FileNameWithoutPrefix {\n param(\n [string]$FileName,\n [string[]]$ValidPrefixes\n )\n \n # Validate input\n if ([string]::IsNullOrWhiteSpace($FileName)) {\n return $FileName\n }\n \n # If no valid prefixes provided, return original filename\n if ($null -eq $ValidPrefixes -or $ValidPrefixes.Count -eq 0) {\n return $FileName\n }\n \n # Use Split instead of regex for robustness (avoids $matches variable issues in loops)\n # Split by the first underscore only (limit to 2 parts)\n $parts = $FileName.Split('_', 2)\n \n if ($parts.Length -eq 2) {\n $prefix = $parts[0]\n $suffix = $parts[1]\n \n # Only strip if the prefix is in the valid prefixes list\n if ($ValidPrefixes -contains $prefix -and -not [string]::IsNullOrWhiteSpace($suffix)) {\n return $suffix\n }\n }\n \n # No valid prefix found or suffix is empty, return original filename\n return $FileName\n}\n\n# Function to process duplicate group\nfunction Process-DuplicateGroup {\n param(\n [array]$Files,",
"signatures": {},
"detailedLines": [
{
"text": "function Get-FileNameWithoutPrefix {",
"lineNumber": 94
},
{
"text": " param(",
"lineNumber": 95
},
{
"text": " [string]$FileName,",
"lineNumber": 96
},
{
"text": " [string[]]$ValidPrefixes",
"lineNumber": 97
},
{
"text": " )",
"lineNumber": 98
},
{
"text": " ",
"lineNumber": 99
},
{
"text": " # Validate input",
"lineNumber": 100
},
{
"text": " if ([string]::IsNullOrWhiteSpace($FileName)) {",
"lineNumber": 101
},
{
"text": " return $FileName",
"lineNumber": 102
},
{
"text": " }",
"lineNumber": 103
},
{
"text": " ",
"lineNumber": 104
},
{
"text": " # If no valid prefixes provided, return original filename",
"lineNumber": 105
},
{
"text": " if ($null -eq $ValidPrefixes -or $ValidPrefixes.Count -eq 0) {",
"lineNumber": 106
},
{
"text": " return $FileName",
"lineNumber": 107
},
{
"text": " }",
"lineNumber": 108
},
{
"text": " ",
"lineNumber": 109
},
{
"text": " # Use Split instead of regex for robustness (avoids $matches variable issues in loops)",
"lineNumber": 110
},
{
"text": " # Split by the first underscore only (limit to 2 parts)",
"lineNumber": 111
},
{
"text": " $parts = $FileName.Split('_', 2)",
"lineNumber": 112
},
{
"text": " ",
"lineNumber": 113
},
{
"text": " if ($parts.Length -eq 2) {",
"lineNumber": 114
},
{
"text": " $prefix = $parts[0]",
"lineNumber": 115
},
{
"text": " $suffix = $parts[1]",
"lineNumber": 116
},
{
"text": " ",
"lineNumber": 117
},
{
"text": " # Only strip if the prefix is in the valid prefixes list",
"lineNumber": 118
},
{
"text": " if ($ValidPrefixes -contains $prefix -and -not [string]::IsNullOrWhiteSpace($suffix)) {",
"lineNumber": 119
},
{
"text": " return $suffix",
"lineNumber": 120
},
{
"text": " }",
"lineNumber": 121
},
{
"text": " }",
"lineNumber": 122
},
{
"text": " ",
"lineNumber": 123
},
{
"text": " # No valid prefix found or suffix is empty, return original filename",
"lineNumber": 124
},
{
"text": " return $FileName",
"lineNumber": 125
},
{
"text": "}",
"lineNumber": 126
},
{
"lineNumber": 127
},
{
"text": "# Function to process duplicate group",
"lineNumber": 128
},
{
"text": "function Process-DuplicateGroup {",
"lineNumber": 129
},
{
"text": " param(",
"lineNumber": 130
},
{
"text": " [array]$Files,",
"lineNumber": 131
}
]
},
"score": 0.31633880734443665
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 543
},
"endPosition": {
"line": 585
}
},
"contents": " \n if ($null -ne $blendFiles -and $blendFiles.Count -gt 0) {\n foreach ($blendFile in $blendFiles) {\n $blendFileName = $blendFile.BaseName\n \n # Check if any blendfile folder name appears in the blend file name\n foreach ($folderName in $blendfileFolderNames) {\n # Match folder name when surrounded by underscores, dots, hyphens, or at start/end\n # This avoids partial matches (e.g., \"Beth\" in \"Bethany\") while allowing \"Beth\" in \"AM_Beth_v3.2\"\n $escapedFolderName = [regex]::Escape($folderName)\n if ($blendFileName -match \"(^|[._-])$escapedFolderName([._-]|$)\") {\n $blendFileMappings += [PSCustomObject]@{\n BlendFile = [System.IO.Path]::GetFullPath($blendFile.FullName)\n BlendfileFolder = $folderName\n }\n Write-Host \"Found matching blend file: $($blendFile.Name) -> $folderName\" -ForegroundColor Gray\n break # Only match once per blend file\n }\n }\n }\n }\n}\n\n# Create move log object\n$moveLogData = [PSCustomObject]@{\n TextureFolderPath = $textureFolderPath\n Timestamp = (Get-Date -Format \"yyyy-MM-ddTHH:mm:ssZ\")\n TotalMoves = ($allMoves | Where-Object { $_.Type -eq \"moved\" }).Count\n TotalDeletes = ($allMoves | Where-Object { $_.Type -eq \"deleted\" }).Count\n Moves = $allMoves\n BlendFileMappings = $blendFileMappings\n}\n\n# Save to JSON file\n$moveLogPath = Join-Path -Path $blendFileParentDir -ChildPath \"texture_moves.json\"\ntry {\n $moveLogData | ConvertTo-Json -Depth 10 | Set-Content -Path $moveLogPath -Encoding UTF8\n Write-Host \"Move log saved to: $moveLogPath\" -ForegroundColor Green\n Write-Host \" Total moves: $($moveLogData.TotalMoves), Total deletes: $($moveLogData.TotalDeletes)\" -ForegroundColor Gray\n Write-Host \" Blend files found: $($blendFileMappings.Count)\" -ForegroundColor Gray\n} catch {\n Write-Warning \"Failed to save move log: $($_.Exception.Message)\"",
"signatures": {},
"detailedLines": [
{
"text": " ",
"lineNumber": 544
},
{
"text": " if ($null -ne $blendFiles -and $blendFiles.Count -gt 0) {",
"lineNumber": 545
},
{
"text": " foreach ($blendFile in $blendFiles) {",
"lineNumber": 546
},
{
"text": " $blendFileName = $blendFile.BaseName",
"lineNumber": 547
},
{
"text": " ",
"lineNumber": 548
},
{
"text": " # Check if any blendfile folder name appears in the blend file name",
"lineNumber": 549
},
{
"text": " foreach ($folderName in $blendfileFolderNames) {",
"lineNumber": 550
},
{
"text": " # Match folder name when surrounded by underscores, dots, hyphens, or at start/end",
"lineNumber": 551
},
{
"text": " # This avoids partial matches (e.g., \"Beth\" in \"Bethany\") while allowing \"Beth\" in \"AM_Beth_v3.2\"",
"lineNumber": 552
},
{
"text": " $escapedFolderName = [regex]::Escape($folderName)",
"lineNumber": 553
},
{
"text": " if ($blendFileName -match \"(^|[._-])$escapedFolderName([._-]|$)\") {",
"lineNumber": 554
},
{
"text": " $blendFileMappings += [PSCustomObject]@{",
"lineNumber": 555
},
{
"text": " BlendFile = [System.IO.Path]::GetFullPath($blendFile.FullName)",
"lineNumber": 556
},
{
"text": " BlendfileFolder = $folderName",
"lineNumber": 557
},
{
"text": " }",
"lineNumber": 558
},
{
"text": " Write-Host \"Found matching blend file: $($blendFile.Name) -> $folderName\" -ForegroundColor Gray",
"lineNumber": 559
},
{
"text": " break # Only match once per blend file",
"lineNumber": 560
},
{
"text": " }",
"lineNumber": 561
},
{
"text": " }",
"lineNumber": 562
},
{
"text": " }",
"lineNumber": 563
},
{
"text": " }",
"lineNumber": 564
},
{
"text": "}",
"lineNumber": 565
},
{
"lineNumber": 566
},
{
"text": "# Create move log object",
"lineNumber": 567
},
{
"text": "$moveLogData = [PSCustomObject]@{",
"lineNumber": 568
},
{
"text": " TextureFolderPath = $textureFolderPath",
"lineNumber": 569
},
{
"text": " Timestamp = (Get-Date -Format \"yyyy-MM-ddTHH:mm:ssZ\")",
"lineNumber": 570
},
{
"text": " TotalMoves = ($allMoves | Where-Object { $_.Type -eq \"moved\" }).Count",
"lineNumber": 571
},
{
"text": " TotalDeletes = ($allMoves | Where-Object { $_.Type -eq \"deleted\" }).Count",
"lineNumber": 572
},
{
"text": " Moves = $allMoves",
"lineNumber": 573
},
{
"text": " BlendFileMappings = $blendFileMappings",
"lineNumber": 574
},
{
"text": "}",
"lineNumber": 575
},
{
"lineNumber": 576
},
{
"text": "# Save to JSON file",
"lineNumber": 577
},
{
"text": "$moveLogPath = Join-Path -Path $blendFileParentDir -ChildPath \"texture_moves.json\"",
"lineNumber": 578
},
{
"text": "try {",
"lineNumber": 579
},
{
"text": " $moveLogData | ConvertTo-Json -Depth 10 | Set-Content -Path $moveLogPath -Encoding UTF8",
"lineNumber": 580
},
{
"text": " Write-Host \"Move log saved to: $moveLogPath\" -ForegroundColor Green",
"lineNumber": 581
},
{
"text": " Write-Host \" Total moves: $($moveLogData.TotalMoves), Total deletes: $($moveLogData.TotalDeletes)\" -ForegroundColor Gray",
"lineNumber": 582
},
{
"text": " Write-Host \" Blend files found: $($blendFileMappings.Count)\" -ForegroundColor Gray",
"lineNumber": 583
},
{
"text": "} catch {",
"lineNumber": 584
},
{
"text": " Write-Warning \"Failed to save move log: $($_.Exception.Message)\"",
"lineNumber": 585
}
]
},
"score": 0.3160834312438965
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\remap_texture_paths.py",
"range": {
"startPosition": {
"line": 71,
"column": 25
},
"endPosition": {
"line": 229
}
},
"contents": "def remap_texture_paths(blend_file_path, move_log_path):\n \"\"\"Remap all texture paths in the blend file\"\"\"\n \n print(f\"\\n=== REMAPPING TEXTURE PATHS ===\")\n print(f\"Blend file: {blend_file_path}\")\n print(f\"Move log: {move_log_path}\")\n \n # Load move log\n original_to_new, original_to_replacement, texture_folder_path = load_move_log(move_log_path)\n \n if not original_to_new and not original_to_replacement:\n print(\"WARNING: No moves found in move log. Nothing to remap.\")\n return 0\n \n print(f\"Loaded {len(original_to_new)} move mappings and {len(original_to_replacement)} replacement mappings\")\n \n # Get blend file directory for relative path conversion\n blend_file_dir = os.path.dirname(os.path.abspath(blend_file_path))\n \n remapped_count = 0\n not_found_count = 0\n \n # Remap paths in image datablocks\n print(\"\\nRemapping image datablock paths...\")\n for image in bpy.data.images:\n if not image.filepath:\n continue",
"signatures": {},
"detailedLines": [
{
"text": "def remap_texture_paths(blend_file_path, move_log_path):",
"lineNumber": 74,
"isSignature": true
},
{
"text": " \"\"\"Remap all texture paths in the blend file\"\"\"",
"lineNumber": 75
},
{
"text": " ",
"lineNumber": 76
},
{
"text": " print(f\"\\n=== REMAPPING TEXTURE PATHS ===\")",
"lineNumber": 77
},
{
"text": " print(f\"Blend file: {blend_file_path}\")",
"lineNumber": 78
},
{
"text": " print(f\"Move log: {move_log_path}\")",
"lineNumber": 79
},
{
"text": " ",
"lineNumber": 80
},
{
"text": " # Load move log",
"lineNumber": 81
},
{
"text": " original_to_new, original_to_replacement, texture_folder_path = load_move_log(move_log_path)",
"lineNumber": 82
},
{
"text": " ",
"lineNumber": 83
},
{
"text": " if not original_to_new and not original_to_replacement:",
"lineNumber": 84
},
{
"text": " print(\"WARNING: No moves found in move log. Nothing to remap.\")",
"lineNumber": 85
},
{
"text": " return 0",
"lineNumber": 86
},
{
"text": " ",
"lineNumber": 87
},
{
"text": " print(f\"Loaded {len(original_to_new)} move mappings and {len(original_to_replacement)} replacement mappings\")",
"lineNumber": 88
},
{
"text": " ",
"lineNumber": 89
},
{
"text": " # Get blend file directory for relative path conversion",
"lineNumber": 90
},
{
"text": " blend_file_dir = os.path.dirname(os.path.abspath(blend_file_path))",
"lineNumber": 91
},
{
"text": " ",
"lineNumber": 92
},
{
"text": " remapped_count = 0",
"lineNumber": 93
},
{
"text": " not_found_count = 0",
"lineNumber": 94
},
{
"text": " ",
"lineNumber": 95
},
{
"text": " # Remap paths in image datablocks",
"lineNumber": 96
},
{
"text": " print(\"\\nRemapping image datablock paths...\")",
"lineNumber": 97
},
{
"text": " for image in bpy.data.images:",
"lineNumber": 98
},
{
"text": " if not image.filepath:",
"lineNumber": 99
},
{
"text": " continue",
"lineNumber": 100
}
]
},
"score": 0.31581223011016846
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 47
},
"endPosition": {
"line": 99
}
},
"contents": "function Move-FilesToCommon {\n param(\n [array]$Files,\n [string]$CommonPath,\n [string]$DuplicatesPath,\n [hashtable]$FilesInCommon\n )\n \n $movedCount = 0\n $duplicateCount = 0\n \n foreach ($fileObj in $Files) {\n $fileName = $fileObj.Name\n $destinationPath = Join-Path -Path $CommonPath -ChildPath $fileName\n \n # Handle name conflicts\n if ($FilesInCommon.ContainsKey($fileName)) {\n $baseName = [System.IO.Path]::GetFileNameWithoutExtension($fileName)\n $extension = [System.IO.Path]::GetExtension($fileName)\n $counter = 1\n do {\n $newFileName = \"${baseName}_${counter}${extension}\"\n $destinationPath = Join-Path -Path $CommonPath -ChildPath $newFileName\n $counter++\n } while ($FilesInCommon.ContainsKey($newFileName) -or (Test-Path -Path $destinationPath))\n \n $fileName = $newFileName\n }\n \n try {\n Move-Item -Path $fileObj.FullName -Destination $destinationPath -Force\n $FilesInCommon[$fileName] = $true\n $movedCount++\n } catch {\n Write-Warning \"Failed to move file: $($fileObj.FullName) - $($_.Exception.Message)\"\n }\n }\n \n return @{\n MovedCount = $movedCount\n DuplicateCount = $duplicateCount\n }\n}\n\n# Function to extract suffix after blendfile prefix (e.g., \"Demarco_Std_Teeth_ao.jpg\" -> \"Std_Teeth_ao.jpg\")\n# Only strips prefixes that are in the $ValidPrefixes list\nfunction Get-FileNameWithoutPrefix {\n param(\n [string]$FileName,\n [string[]]$ValidPrefixes\n )\n ",
"signatures": {},
"detailedLines": [
{
"text": "function Move-FilesToCommon {",
"lineNumber": 48
},
{
"text": " param(",
"lineNumber": 49
},
{
"text": " [array]$Files,",
"lineNumber": 50
},
{
"text": " [string]$CommonPath,",
"lineNumber": 51
},
{
"text": " [string]$DuplicatesPath,",
"lineNumber": 52
},
{
"text": " [hashtable]$FilesInCommon",
"lineNumber": 53
},
{
"text": " )",
"lineNumber": 54
},
{
"text": " ",
"lineNumber": 55
},
{
"text": " $movedCount = 0",
"lineNumber": 56
},
{
"text": " $duplicateCount = 0",
"lineNumber": 57
},
{
"text": " ",
"lineNumber": 58
},
{
"text": " foreach ($fileObj in $Files) {",
"lineNumber": 59
},
{
"text": " $fileName = $fileObj.Name",
"lineNumber": 60
},
{
"text": " $destinationPath = Join-Path -Path $CommonPath -ChildPath $fileName",
"lineNumber": 61
},
{
"text": " ",
"lineNumber": 62
},
{
"text": " # Handle name conflicts",
"lineNumber": 63
},
{
"text": " if ($FilesInCommon.ContainsKey($fileName)) {",
"lineNumber": 64
},
{
"text": " $baseName = [System.IO.Path]::GetFileNameWithoutExtension($fileName)",
"lineNumber": 65
},
{
"text": " $extension = [System.IO.Path]::GetExtension($fileName)",
"lineNumber": 66
},
{
"text": " $counter = 1",
"lineNumber": 67
},
{
"text": " do {",
"lineNumber": 68
},
{
"text": " $newFileName = \"${baseName}_${counter}${extension}\"",
"lineNumber": 69
},
{
"text": " $destinationPath = Join-Path -Path $CommonPath -ChildPath $newFileName",
"lineNumber": 70
},
{
"text": " $counter++",
"lineNumber": 71
},
{
"text": " } while ($FilesInCommon.ContainsKey($newFileName) -or (Test-Path -Path $destinationPath))",
"lineNumber": 72
},
{
"text": " ",
"lineNumber": 73
},
{
"text": " $fileName = $newFileName",
"lineNumber": 74
},
{
"text": " }",
"lineNumber": 75
},
{
"text": " ",
"lineNumber": 76
},
{
"text": " try {",
"lineNumber": 77
},
{
"text": " Move-Item -Path $fileObj.FullName -Destination $destinationPath -Force",
"lineNumber": 78
},
{
"text": " $FilesInCommon[$fileName] = $true",
"lineNumber": 79
},
{
"text": " $movedCount++",
"lineNumber": 80
},
{
"text": " } catch {",
"lineNumber": 81
},
{
"text": " Write-Warning \"Failed to move file: $($fileObj.FullName) - $($_.Exception.Message)\"",
"lineNumber": 82
},
{
"text": " }",
"lineNumber": 83
},
{
"text": " }",
"lineNumber": 84
},
{
"text": " ",
"lineNumber": 85
},
{
"text": " return @{",
"lineNumber": 86
},
{
"text": " MovedCount = $movedCount",
"lineNumber": 87
},
{
"text": " DuplicateCount = $duplicateCount",
"lineNumber": 88
},
{
"text": " }",
"lineNumber": 89
},
{
"text": "}",
"lineNumber": 90
},
{
"lineNumber": 91
},
{
"text": "# Function to extract suffix after blendfile prefix (e.g., \"Demarco_Std_Teeth_ao.jpg\" -> \"Std_Teeth_ao.jpg\")",
"lineNumber": 92
},
{
"text": "# Only strips prefixes that are in the $ValidPrefixes list",
"lineNumber": 93
},
{
"text": "function Get-FileNameWithoutPrefix {",
"lineNumber": 94
},
{
"text": " param(",
"lineNumber": 95
},
{
"text": " [string]$FileName,",
"lineNumber": 96
},
{
"text": " [string[]]$ValidPrefixes",
"lineNumber": 97
},
{
"text": " )",
"lineNumber": 98
},
{
"text": " ",
"lineNumber": 99
}
]
},
"score": 0.3142794370651245
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 583
},
"endPosition": {
"line": 606
}
},
"contents": "} catch {\n Write-Warning \"Failed to save move log: $($_.Exception.Message)\"\n}\n\n# ============================================================================\n# Remap Texture Paths in Blend Files\n# ============================================================================\nif ($blendFileMappings.Count -gt 0 -and (Test-Path -Path $moveLogPath)) {\n Write-Host \"\"\n Write-Host \"Remapping texture paths in blend files...\" -ForegroundColor Yellow\n \n # Find Blender executable from PATH\n $blenderExe = $null\n $blenderInPath = Get-Command blender -ErrorAction SilentlyContinue\n if ($null -ne $blenderInPath) {\n $blenderExe = $blenderInPath.Source\n }\n \n if ($null -eq $blenderExe) {\n Write-Warning \"Blender executable not found. Skipping texture path remapping.\"\n Write-Host \" Please install Blender or add it to your PATH.\" -ForegroundColor Yellow\n } else {\n Write-Host \"Found Blender: $blenderExe\" -ForegroundColor Gray",
"signatures": {},
"detailedLines": [
{
"text": "} catch {",
"lineNumber": 584
},
{
"text": " Write-Warning \"Failed to save move log: $($_.Exception.Message)\"",
"lineNumber": 585
},
{
"text": "}",
"lineNumber": 586
},
{
"lineNumber": 587
},
{
"text": "# ============================================================================",
"lineNumber": 588
},
{
"text": "# Remap Texture Paths in Blend Files",
"lineNumber": 589
},
{
"text": "# ============================================================================",
"lineNumber": 590
},
{
"text": "if ($blendFileMappings.Count -gt 0 -and (Test-Path -Path $moveLogPath)) {",
"lineNumber": 591
},
{
"text": " Write-Host \"\"",
"lineNumber": 592
},
{
"text": " Write-Host \"Remapping texture paths in blend files...\" -ForegroundColor Yellow",
"lineNumber": 593
},
{
"text": " ",
"lineNumber": 594
},
{
"text": " # Find Blender executable from PATH",
"lineNumber": 595
},
{
"text": " $blenderExe = $null",
"lineNumber": 596
},
{
"text": " $blenderInPath = Get-Command blender -ErrorAction SilentlyContinue",
"lineNumber": 597
},
{
"text": " if ($null -ne $blenderInPath) {",
"lineNumber": 598
},
{
"text": " $blenderExe = $blenderInPath.Source",
"lineNumber": 599
},
{
"text": " }",
"lineNumber": 600
},
{
"text": " ",
"lineNumber": 601
},
{
"text": " if ($null -eq $blenderExe) {",
"lineNumber": 602
},
{
"text": " Write-Warning \"Blender executable not found. Skipping texture path remapping.\"",
"lineNumber": 603
},
{
"text": " Write-Host \" Please install Blender or add it to your PATH.\" -ForegroundColor Yellow",
"lineNumber": 604
},
{
"text": " } else {",
"lineNumber": 605
},
{
"text": " Write-Host \"Found Blender: $blenderExe\" -ForegroundColor Gray",
"lineNumber": 606
}
]
},
"score": 0.3072027862071991
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 240
},
"endPosition": {
"line": 281
}
},
"contents": " for ($i = 1; $i -lt $Files.Count; $i++) {\n $fileObj = $Files[$i].File\n try {\n $originalPath = $fileObj.FullName\n Remove-Item -Path $originalPath -Force\n $duplicateCount++\n \n # Log the deletion (replaced by the moved file)\n if ($null -ne $MoveLog) {\n $normalizedOriginal = [System.IO.Path]::GetFullPath($originalPath)\n $normalizedReplacement = [System.IO.Path]::GetFullPath($destinationPath)\n $null = $MoveLog.Add([PSCustomObject]@{\n OriginalPath = $normalizedOriginal\n ReplacedBy = $normalizedReplacement\n Type = \"deleted\"\n })\n }\n } catch {\n Write-Warning \"Failed to delete duplicate file: $($fileObj.FullName) - $($_.Exception.Message)\"\n }\n }\n \n return @{\n MovedCount = $movedCount\n DuplicateCount = $duplicateCount\n }\n}\n\n# ============================================================================\n# PASS 1: Intra-Blendfile Processing\n# ============================================================================\nWrite-Host \"\"\nWrite-Host \"=== PASS 1: Intra-Blendfile Processing ===\" -ForegroundColor Cyan\n\n# Get all direct subdirectories of texture folder (blendfile folders)\n$blendfileFolders = Get-ChildItem -Path $textureFolderPath -Directory | Where-Object { $_.Name -ne \"common\" }\n\nif ($null -eq $blendfileFolders -or $blendfileFolders.Count -eq 0) {\n Write-Host \"No blendfile folders found. Skipping Pass 1.\" -ForegroundColor Yellow\n} else {\n Write-Host \"Found $($blendfileFolders.Count) blendfile folder(s) to process.\" -ForegroundColor Green",
"signatures": {},
"detailedLines": [
{
"text": " for ($i = 1; $i -lt $Files.Count; $i++) {",
"lineNumber": 241
},
{
"text": " $fileObj = $Files[$i].File",
"lineNumber": 242
},
{
"text": " try {",
"lineNumber": 243
},
{
"text": " $originalPath = $fileObj.FullName",
"lineNumber": 244
},
{
"text": " Remove-Item -Path $originalPath -Force",
"lineNumber": 245
},
{
"text": " $duplicateCount++",
"lineNumber": 246
},
{
"text": " ",
"lineNumber": 247
},
{
"text": " # Log the deletion (replaced by the moved file)",
"lineNumber": 248
},
{
"text": " if ($null -ne $MoveLog) {",
"lineNumber": 249
},
{
"text": " $normalizedOriginal = [System.IO.Path]::GetFullPath($originalPath)",
"lineNumber": 250
},
{
"text": " $normalizedReplacement = [System.IO.Path]::GetFullPath($destinationPath)",
"lineNumber": 251
},
{
"text": " $null = $MoveLog.Add([PSCustomObject]@{",
"lineNumber": 252
},
{
"text": " OriginalPath = $normalizedOriginal",
"lineNumber": 253
},
{
"text": " ReplacedBy = $normalizedReplacement",
"lineNumber": 254
},
{
"text": " Type = \"deleted\"",
"lineNumber": 255
},
{
"text": " })",
"lineNumber": 256
},
{
"text": " }",
"lineNumber": 257
},
{
"text": " } catch {",
"lineNumber": 258
},
{
"text": " Write-Warning \"Failed to delete duplicate file: $($fileObj.FullName) - $($_.Exception.Message)\"",
"lineNumber": 259
},
{
"text": " }",
"lineNumber": 260
},
{
"text": " }",
"lineNumber": 261
},
{
"text": " ",
"lineNumber": 262
},
{
"text": " return @{",
"lineNumber": 263
},
{
"text": " MovedCount = $movedCount",
"lineNumber": 264
},
{
"text": " DuplicateCount = $duplicateCount",
"lineNumber": 265
},
{
"text": " }",
"lineNumber": 266
},
{
"text": "}",
"lineNumber": 267
},
{
"lineNumber": 268
},
{
"text": "# ============================================================================",
"lineNumber": 269
},
{
"text": "# PASS 1: Intra-Blendfile Processing",
"lineNumber": 270
},
{
"text": "# ============================================================================",
"lineNumber": 271
},
{
"text": "Write-Host \"\"",
"lineNumber": 272
},
{
"text": "Write-Host \"=== PASS 1: Intra-Blendfile Processing ===\" -ForegroundColor Cyan",
"lineNumber": 273
},
{
"lineNumber": 274
},
{
"text": "# Get all direct subdirectories of texture folder (blendfile folders)",
"lineNumber": 275
},
{
"text": "$blendfileFolders = Get-ChildItem -Path $textureFolderPath -Directory | Where-Object { $_.Name -ne \"common\" }",
"lineNumber": 276
},
{
"lineNumber": 277
},
{
"text": "if ($null -eq $blendfileFolders -or $blendfileFolders.Count -eq 0) {",
"lineNumber": 278
},
{
"text": " Write-Host \"No blendfile folders found. Skipping Pass 1.\" -ForegroundColor Yellow",
"lineNumber": 279
},
{
"text": "} else {",
"lineNumber": 280
},
{
"text": " Write-Host \"Found $($blendfileFolders.Count) blendfile folder(s) to process.\" -ForegroundColor Green",
"lineNumber": 281
}
]
},
"score": 0.30335870385169983
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 128
},
"endPosition": {
"line": 173
}
},
"contents": "function Process-DuplicateGroup {\n param(\n [array]$Files,\n [string]$CommonPath,\n [hashtable]$FilesInCommon,\n [switch]$StripPrefix,\n [string[]]$ValidPrefixes = @(),\n [System.Collections.ArrayList]$MoveLog = $null\n )\n \n $movedCount = 0\n $duplicateCount = 0\n \n if ($Files.Count -eq 1) {\n # Single file - leave in place (will be processed in Pass 2)\n return @{\n MovedCount = 0\n DuplicateCount = 0\n }\n }\n \n # Validate files array\n if ($null -eq $Files -or $Files.Count -eq 0) {\n return @{\n MovedCount = 0\n DuplicateCount = 0\n }\n }\n \n # Multiple files with same checksum (duplicates)\n # Determine the filename to use\n $firstFile = $Files[0].File\n if ($null -eq $firstFile -or [string]::IsNullOrWhiteSpace($firstFile.Name)) {\n Write-Warning \"Invalid file object in duplicate group\"\n return @{\n MovedCount = 0\n DuplicateCount = 0\n }\n }\n \n $fileName = $firstFile.Name\n \n # If StripPrefix is enabled, always strip prefix from the filename\n if ($StripPrefix) {\n # Always try to strip prefix - if file has a prefix, it will be removed",
"signatures": {},
"detailedLines": [
{
"text": "function Process-DuplicateGroup {",
"lineNumber": 129
},
{
"text": " param(",
"lineNumber": 130
},
{
"text": " [array]$Files,",
"lineNumber": 131
},
{
"text": " [string]$CommonPath,",
"lineNumber": 132
},
{
"text": " [hashtable]$FilesInCommon,",
"lineNumber": 133
},
{
"text": " [switch]$StripPrefix,",
"lineNumber": 134
},
{
"text": " [string[]]$ValidPrefixes = @(),",
"lineNumber": 135
},
{
"text": " [System.Collections.ArrayList]$MoveLog = $null",
"lineNumber": 136
},
{
"text": " )",
"lineNumber": 137
},
{
"text": " ",
"lineNumber": 138
},
{
"text": " $movedCount = 0",
"lineNumber": 139
},
{
"text": " $duplicateCount = 0",
"lineNumber": 140
},
{
"text": " ",
"lineNumber": 141
},
{
"text": " if ($Files.Count -eq 1) {",
"lineNumber": 142
},
{
"text": " # Single file - leave in place (will be processed in Pass 2)",
"lineNumber": 143
},
{
"text": " return @{",
"lineNumber": 144
},
{
"text": " MovedCount = 0",
"lineNumber": 145
},
{
"text": " DuplicateCount = 0",
"lineNumber": 146
},
{
"text": " }",
"lineNumber": 147
},
{
"text": " }",
"lineNumber": 148
},
{
"text": " ",
"lineNumber": 149
},
{
"text": " # Validate files array",
"lineNumber": 150
},
{
"text": " if ($null -eq $Files -or $Files.Count -eq 0) {",
"lineNumber": 151
},
{
"text": " return @{",
"lineNumber": 152
},
{
"text": " MovedCount = 0",
"lineNumber": 153
},
{
"text": " DuplicateCount = 0",
"lineNumber": 154
},
{
"text": " }",
"lineNumber": 155
},
{
"text": " }",
"lineNumber": 156
},
{
"text": " ",
"lineNumber": 157
},
{
"text": " # Multiple files with same checksum (duplicates)",
"lineNumber": 158
},
{
"text": " # Determine the filename to use",
"lineNumber": 159
},
{
"text": " $firstFile = $Files[0].File",
"lineNumber": 160
},
{
"text": " if ($null -eq $firstFile -or [string]::IsNullOrWhiteSpace($firstFile.Name)) {",
"lineNumber": 161
},
{
"text": " Write-Warning \"Invalid file object in duplicate group\"",
"lineNumber": 162
},
{
"text": " return @{",
"lineNumber": 163
},
{
"text": " MovedCount = 0",
"lineNumber": 164
},
{
"text": " DuplicateCount = 0",
"lineNumber": 165
},
{
"text": " }",
"lineNumber": 166
},
{
"text": " }",
"lineNumber": 167
},
{
"text": " ",
"lineNumber": 168
},
{
"text": " $fileName = $firstFile.Name",
"lineNumber": 169
},
{
"text": " ",
"lineNumber": 170
},
{
"text": " # If StripPrefix is enabled, always strip prefix from the filename",
"lineNumber": 171
},
{
"text": " if ($StripPrefix) {",
"lineNumber": 172
},
{
"text": " # Always try to strip prefix - if file has a prefix, it will be removed",
"lineNumber": 173
}
]
},
"score": 0.30188310146331787
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 514
},
"endPosition": {
"line": 546,
"column": 12
}
},
"contents": "# Save Move Log and Find Blend Files\n# ============================================================================\nWrite-Host \"\"\nWrite-Host \"Saving move log and finding blend files...\" -ForegroundColor Yellow\n\n# Combine all move logs\n$allMoves = @()\nif ($null -ne $pass1MoveLog -and $pass1MoveLog.Count -gt 0) {\n $allMoves += $pass1MoveLog\n}\nif ($null -ne $pass2MoveLog -and $pass2MoveLog.Count -gt 0) {\n $allMoves += $pass2MoveLog\n}\nif ($null -ne $flatColorsMoveLog -and $flatColorsMoveLog.Count -gt 0) {\n $allMoves += $flatColorsMoveLog\n}\n\n# Get parent directory of texture folder\n$blendFileParentDir = Split-Path -Path $textureFolderPath -Parent\n\n# Find matching blend files\n# Match logic: blendfile folder name (e.g., \"Beth\") should appear in blend file name (e.g., \"AM_Beth_v3.2.blend\")\n$blendFileMappings = @()\nif ($null -ne $blendfileFolders -and $blendfileFolders.Count -gt 0) {\n # Get blendfile folder names\n $blendfileFolderNames = $blendfileFolders | ForEach-Object { $_.Name }\n \n # Find all .blend files in parent directory\n $blendFiles = Get-ChildItem -Path $blendFileParentDir -Filter \"*.blend\" -File -ErrorAction SilentlyContinue\n \n if ($null -ne $blendFiles -and $blendFiles.Count -gt 0) {\n foreach ($blendFile in $blendFiles) {\n ",
"signatures": {},
"detailedLines": [
{
"text": "# Save Move Log and Find Blend Files",
"lineNumber": 515
},
{
"text": "# ============================================================================",
"lineNumber": 516
},
{
"text": "Write-Host \"\"",
"lineNumber": 517
},
{
"text": "Write-Host \"Saving move log and finding blend files...\" -ForegroundColor Yellow",
"lineNumber": 518
},
{
"lineNumber": 519
},
{
"text": "# Combine all move logs",
"lineNumber": 520
},
{
"text": "$allMoves = @()",
"lineNumber": 521
},
{
"text": "if ($null -ne $pass1MoveLog -and $pass1MoveLog.Count -gt 0) {",
"lineNumber": 522
},
{
"text": " $allMoves += $pass1MoveLog",
"lineNumber": 523
},
{
"text": "}",
"lineNumber": 524
},
{
"text": "if ($null -ne $pass2MoveLog -and $pass2MoveLog.Count -gt 0) {",
"lineNumber": 525
},
{
"text": " $allMoves += $pass2MoveLog",
"lineNumber": 526
},
{
"text": "}",
"lineNumber": 527
},
{
"text": "if ($null -ne $flatColorsMoveLog -and $flatColorsMoveLog.Count -gt 0) {",
"lineNumber": 528
},
{
"text": " $allMoves += $flatColorsMoveLog",
"lineNumber": 529
},
{
"text": "}",
"lineNumber": 530
},
{
"lineNumber": 531
},
{
"text": "# Get parent directory of texture folder",
"lineNumber": 532
},
{
"text": "$blendFileParentDir = Split-Path -Path $textureFolderPath -Parent",
"lineNumber": 533
},
{
"lineNumber": 534
},
{
"text": "# Find matching blend files",
"lineNumber": 535
},
{
"text": "# Match logic: blendfile folder name (e.g., \"Beth\") should appear in blend file name (e.g., \"AM_Beth_v3.2.blend\")",
"lineNumber": 536
},
{
"text": "$blendFileMappings = @()",
"lineNumber": 537
},
{
"text": "if ($null -ne $blendfileFolders -and $blendfileFolders.Count -gt 0) {",
"lineNumber": 538
},
{
"text": " # Get blendfile folder names",
"lineNumber": 539
},
{
"text": " $blendfileFolderNames = $blendfileFolders | ForEach-Object { $_.Name }",
"lineNumber": 540
},
{
"text": " ",
"lineNumber": 541
},
{
"text": " # Find all .blend files in parent directory",
"lineNumber": 542
},
{
"text": " $blendFiles = Get-ChildItem -Path $blendFileParentDir -Filter \"*.blend\" -File -ErrorAction SilentlyContinue",
"lineNumber": 543
},
{
"text": " ",
"lineNumber": 544
},
{
"text": " if ($null -ne $blendFiles -and $blendFiles.Count -gt 0) {",
"lineNumber": 545
},
{
"text": " foreach ($blendFile in $blendFiles) {",
"lineNumber": 546
},
{
"text": " ",
"lineNumber": 547
}
]
},
"score": 0.2999364137649536
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.ps1",
"range": {
"startPosition": {
"line": 207
},
"endPosition": {
"line": 243,
"column": 12
}
},
"contents": " if ($FilesInCommon.ContainsKey($fileName)) {\n $baseName = [System.IO.Path]::GetFileNameWithoutExtension($fileName)\n $extension = [System.IO.Path]::GetExtension($fileName)\n $counter = 1\n do {\n $newFileName = \"${baseName}_${counter}${extension}\"\n $destinationPath = Join-Path -Path $CommonPath -ChildPath $newFileName\n $counter++\n } while ($FilesInCommon.ContainsKey($newFileName) -or (Test-Path -Path $destinationPath))\n \n $fileName = $newFileName\n }\n \n try {\n Move-Item -Path $firstFile.FullName -Destination $destinationPath -Force\n $FilesInCommon[$fileName] = $true\n $movedCount++\n \n # Log the move\n if ($null -ne $MoveLog) {\n $normalizedOriginal = [System.IO.Path]::GetFullPath($firstFile.FullName)\n $normalizedNew = [System.IO.Path]::GetFullPath($destinationPath)\n $null = $MoveLog.Add([PSCustomObject]@{\n OriginalPath = $normalizedOriginal\n NewPath = $normalizedNew\n Type = \"moved\"\n })\n }\n } catch {\n Write-Warning \"Failed to move first duplicate file: $($firstFile.FullName) - $($_.Exception.Message)\"\n }\n \n # Delete remaining duplicate files (they're replaced by the common file)\n for ($i = 1; $i -lt $Files.Count; $i++) {\n $fileObj = $Files[$i].File\n try {\n ",
"signatures": {},
"detailedLines": [
{
"text": " if ($FilesInCommon.ContainsKey($fileName)) {",
"lineNumber": 208
},
{
"text": " $baseName = [System.IO.Path]::GetFileNameWithoutExtension($fileName)",
"lineNumber": 209
},
{
"text": " $extension = [System.IO.Path]::GetExtension($fileName)",
"lineNumber": 210
},
{
"text": " $counter = 1",
"lineNumber": 211
},
{
"text": " do {",
"lineNumber": 212
},
{
"text": " $newFileName = \"${baseName}_${counter}${extension}\"",
"lineNumber": 213
},
{
"text": " $destinationPath = Join-Path -Path $CommonPath -ChildPath $newFileName",
"lineNumber": 214
},
{
"text": " $counter++",
"lineNumber": 215
},
{
"text": " } while ($FilesInCommon.ContainsKey($newFileName) -or (Test-Path -Path $destinationPath))",
"lineNumber": 216
},
{
"text": " ",
"lineNumber": 217
},
{
"text": " $fileName = $newFileName",
"lineNumber": 218
},
{
"text": " }",
"lineNumber": 219
},
{
"text": " ",
"lineNumber": 220
},
{
"text": " try {",
"lineNumber": 221
},
{
"text": " Move-Item -Path $firstFile.FullName -Destination $destinationPath -Force",
"lineNumber": 222
},
{
"text": " $FilesInCommon[$fileName] = $true",
"lineNumber": 223
},
{
"text": " $movedCount++",
"lineNumber": 224
},
{
"text": " ",
"lineNumber": 225
},
{
"text": " # Log the move",
"lineNumber": 226
},
{
"text": " if ($null -ne $MoveLog) {",
"lineNumber": 227
},
{
"text": " $normalizedOriginal = [System.IO.Path]::GetFullPath($firstFile.FullName)",
"lineNumber": 228
},
{
"text": " $normalizedNew = [System.IO.Path]::GetFullPath($destinationPath)",
"lineNumber": 229
},
{
"text": " $null = $MoveLog.Add([PSCustomObject]@{",
"lineNumber": 230
},
{
"text": " OriginalPath = $normalizedOriginal",
"lineNumber": 231
},
{
"text": " NewPath = $normalizedNew",
"lineNumber": 232
},
{
"text": " Type = \"moved\"",
"lineNumber": 233
},
{
"text": " })",
"lineNumber": 234
},
{
"text": " }",
"lineNumber": 235
},
{
"text": " } catch {",
"lineNumber": 236
},
{
"text": " Write-Warning \"Failed to move first duplicate file: $($firstFile.FullName) - $($_.Exception.Message)\"",
"lineNumber": 237
},
{
"text": " }",
"lineNumber": 238
},
{
"text": " ",
"lineNumber": 239
},
{
"text": " # Delete remaining duplicate files (they're replaced by the common file)",
"lineNumber": 240
},
{
"text": " for ($i = 1; $i -lt $Files.Count; $i++) {",
"lineNumber": 241
},
{
"text": " $fileObj = $Files[$i].File",
"lineNumber": 242
},
{
"text": " try {",
"lineNumber": 243
},
{
"text": " ",
"lineNumber": 244
}
]
},
"score": 0.29972875118255615
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\UpdateProjectBatches.ps1",
"range": {
"startPosition": {
"line": 112
},
"endPosition": {
"line": 164
}
},
"contents": " $updated++\n\n $targetDir = $target.Directory.FullName\n if (-not $touchedDirs.ContainsKey($targetDir)) {\n $touchedDirs[$targetDir] = $true\n }\n }\n catch {\n Write-Host \"[FAIL] $($target.FullName)\" -ForegroundColor Red\n Write-Host \" $($_.Exception.Message)\" -ForegroundColor DarkRed\n $failed++\n }\n }\n\n $summary += [pscustomobject]@{\n Name = $spec.Name\n Updated = $updated\n Failed = $failed\n Skipped = 0\n Total = @($targets).Count\n }\n}\n\nWrite-Host \"`n=== Summary ===\" -ForegroundColor Cyan\nforeach ($item in $summary) {\n Write-Host (\"{0,-22} Updated: {1,3} Failed: {2,3} Total: {3,3}\" -f $item.Name, $item.Updated, $item.Failed, $item.Total)\n}\n\nif (($summary | Measure-Object -Property Failed -Sum).Sum -gt 0) {\n Write-Host \"Completed with errors.\" -ForegroundColor Yellow\n exit 1\n}\n\nWrite-Host \"All batch files refreshed successfully.\" -ForegroundColor Green\n\n# Deploy config files to projectroot\\.config\\\nWrite-Host \"`n=== Deploying config files to .config\\ ===\" -ForegroundColor Magenta\nforeach ($asset in $configAssets) {\n $targetPath = Join-Path -Path $projectConfigDir -ChildPath $asset.Name\n try {\n Copy-Item -Path $asset.Source -Destination $targetPath -Force\n Write-Host \"[OK] $targetPath\" -ForegroundColor Green\n }\n catch {\n Write-Host \"[FAIL] $targetPath\" -ForegroundColor Red\n Write-Host \" $($_.Exception.Message)\" -ForegroundColor DarkRed\n exit 1\n }\n}\n\nWrite-Host \"Config files deployed successfully.\" -ForegroundColor Green",
"signatures": {},
"detailedLines": [
{
"text": " $updated++",
"lineNumber": 113
},
{
"lineNumber": 114
},
{
"text": " $targetDir = $target.Directory.FullName",
"lineNumber": 115
},
{
"text": " if (-not $touchedDirs.ContainsKey($targetDir)) {",
"lineNumber": 116
},
{
"text": " $touchedDirs[$targetDir] = $true",
"lineNumber": 117
},
{
"text": " }",
"lineNumber": 118
},
{
"text": " }",
"lineNumber": 119
},
{
"text": " catch {",
"lineNumber": 120
},
{
"text": " Write-Host \"[FAIL] $($target.FullName)\" -ForegroundColor Red",
"lineNumber": 121
},
{
"text": " Write-Host \" $($_.Exception.Message)\" -ForegroundColor DarkRed",
"lineNumber": 122
},
{
"text": " $failed++",
"lineNumber": 123
},
{
"text": " }",
"lineNumber": 124
},
{
"text": " }",
"lineNumber": 125
},
{
"lineNumber": 126
},
{
"text": " $summary += [pscustomobject]@{",
"lineNumber": 127
},
{
"text": " Name = $spec.Name",
"lineNumber": 128
},
{
"text": " Updated = $updated",
"lineNumber": 129
},
{
"text": " Failed = $failed",
"lineNumber": 130
},
{
"text": " Skipped = 0",
"lineNumber": 131
},
{
"text": " Total = @($targets).Count",
"lineNumber": 132
},
{
"text": " }",
"lineNumber": 133
},
{
"text": "}",
"lineNumber": 134
},
{
"lineNumber": 135
},
{
"text": "Write-Host \"`n=== Summary ===\" -ForegroundColor Cyan",
"lineNumber": 136
},
{
"text": "foreach ($item in $summary) {",
"lineNumber": 137
},
{
"text": " Write-Host (\"{0,-22} Updated: {1,3} Failed: {2,3} Total: {3,3}\" -f $item.Name, $item.Updated, $item.Failed, $item.Total)",
"lineNumber": 138
},
{
"text": "}",
"lineNumber": 139
},
{
"lineNumber": 140
},
{
"text": "if (($summary | Measure-Object -Property Failed -Sum).Sum -gt 0) {",
"lineNumber": 141
},
{
"text": " Write-Host \"Completed with errors.\" -ForegroundColor Yellow",
"lineNumber": 142
},
{
"text": " exit 1",
"lineNumber": 143
},
{
"text": "}",
"lineNumber": 144
},
{
"lineNumber": 145
},
{
"text": "Write-Host \"All batch files refreshed successfully.\" -ForegroundColor Green",
"lineNumber": 146
},
{
"lineNumber": 147
},
{
"text": "# Deploy config files to projectroot\\.config\\",
"lineNumber": 148
},
{
"text": "Write-Host \"`n=== Deploying config files to .config\\ ===\" -ForegroundColor Magenta",
"lineNumber": 149
},
{
"text": "foreach ($asset in $configAssets) {",
"lineNumber": 150
},
{
"text": " $targetPath = Join-Path -Path $projectConfigDir -ChildPath $asset.Name",
"lineNumber": 151
},
{
"text": " try {",
"lineNumber": 152
},
{
"text": " Copy-Item -Path $asset.Source -Destination $targetPath -Force",
"lineNumber": 153
},
{
"text": " Write-Host \"[OK] $targetPath\" -ForegroundColor Green",
"lineNumber": 154
},
{
"text": " }",
"lineNumber": 155
},
{
"text": " catch {",
"lineNumber": 156
},
{
"text": " Write-Host \"[FAIL] $targetPath\" -ForegroundColor Red",
"lineNumber": 157
},
{
"text": " Write-Host \" $($_.Exception.Message)\" -ForegroundColor DarkRed",
"lineNumber": 158
},
{
"text": " exit 1",
"lineNumber": 159
},
{
"text": " }",
"lineNumber": 160
},
{
"text": "}",
"lineNumber": 161
},
{
"lineNumber": 162
},
{
"text": "Write-Host \"Config files deployed successfully.\" -ForegroundColor Green",
"lineNumber": 163
}
]
},
"score": 0.29805418848991394
},
{
"codeBlock": {
"relativeWorkspacePath": ".\\organize_textures.bat",
"range": {
"startPosition": {},
"endPosition": {
"line": 22,
"column": 12
}
},
"contents": "@echo off\nsetlocal EnableExtensions\n\nset \"script_dir=%~dp0\"\nset \"ps1_path=%script_dir%organize_textures.ps1\"\n\nif not exist \"%ps1_path%\" (\n echo [ERROR] organize_textures.ps1 not found at %ps1_path%\n exit /b 1\n)\n\necho Running texture organizer...\npwsh -NoProfile -ExecutionPolicy Bypass -File \"%ps1_path%\"\nset \"rc=%errorlevel%\"\n\nif %rc% neq 0 (\n echo.\n echo Script exited with error code %rc%\n)\n\necho.\npause\nexit /b %rc%",
"signatures": {},
"detailedLines": [
{
"text": "@echo off",
"lineNumber": 1
},
{
"text": "setlocal EnableExtensions",
"lineNumber": 2
},
{
"lineNumber": 3
},
{
"text": "set \"script_dir=%~dp0\"",
"lineNumber": 4
},
{
"text": "set \"ps1_path=%script_dir%organize_textures.ps1\"",
"lineNumber": 5
},
{
"lineNumber": 6
},
{
"text": "if not exist \"%ps1_path%\" (",
"lineNumber": 7
},
{
"text": " echo [ERROR] organize_textures.ps1 not found at %ps1_path%",
"lineNumber": 8
},
{
"text": " exit /b 1",
"lineNumber": 9
},
{
"text": ")",
"lineNumber": 10
},
{
"lineNumber": 11
},
{
"text": "echo Running texture organizer...",
"lineNumber": 12
},
{
"text": "pwsh -NoProfile -ExecutionPolicy Bypass -File \"%ps1_path%\"",
"lineNumber": 13
},
{
"text": "set \"rc=%errorlevel%\"",
"lineNumber": 14
},
{
"lineNumber": 15
},
{
"text": "if %rc% neq 0 (",
"lineNumber": 16
},
{
"text": " echo.",
"lineNumber": 17
},
{
"text": " echo Script exited with error code %rc%",
"lineNumber": 18
},
{
"text": ")",
"lineNumber": 19
},
{
"lineNumber": 20
},
{
"text": "echo.",
"lineNumber": 21
},
{
"text": "pause",
"lineNumber": 22
},
{
"text": "exit /b %rc%",
"lineNumber": 23
}
]
},
"score": 0.2977990508079529
}
]
}
Status: completed
Creating a script to standardize FlatColors: convert PNGs to 16x16 JPGs (except TGA), merge duplicates by color, and ensure all are 16x16.
Tool use: **edit_file_v2** • Edit file: A:\1 Amazon_Active_Projects\3 ProjectStructure\standardize_flatcolors.ps1
Refining the script to better handle edge cases and improve duplicate detection:
Tool use: **edit_file_v2** • Edit file: standardize_flatcolors.ps1
Tool use: **edit_file_v2** • Edit file: standardize_flatcolors.ps1
Fixing the color code extraction to handle all filename variations:
Tool use: **edit_file_v2** • Edit file: standardize_flatcolors.ps1
Reviewing the script to verify the logic:
Tool use: **read_file_v2** • Read file: standardize_flatcolors.ps1
Ensuring the target directory exists before processing:
Tool use: **edit_file_v2** • Edit file: standardize_flatcolors.ps1
Created a script standardize_flatcolors.ps1 that:
- Finds all FlatColors files in any
FlatColorsfolder within the texture directory - Extracts color codes from filenames (handles
#RRGGBB,#RRGGBB_1,#RRGGBB_2, etc.) - Groups by color code to identify duplicates
- Converts PNG to 16x16 JPG (unless the file is TGA)
- Resizes to 16x16 if needed
- Preserves TGA files as-is (no conversion)
- Merges duplicates by keeping one file per color and deleting the rest
- Organizes files in the target directory (prefers
common\FlatColorsif it exists)
The script:
- Prefers existing JPG files when multiple formats exist for the same color
- Preserves TGA files without conversion
- Handles files already in the correct format/size
- Provides a summary of actions taken
Run it with:
.\standardize_flatcolors.ps1
It will prompt for the texture folder path and process all FlatColors files accordingly.
User
merge this script into organize_textures.ps1 pls
Agent (model default, mode Agent)
Reading organize_textures.ps1 to understand its structure, then integrating the FlatColors standardization logic.
Tool use: **read_file_v2** • Read file: organize_textures.ps1
Integrating FlatColors standardization into organize_textures.ps1. Adding the required functions and updating the FlatColors processing section.
Tool use: **edit_file_v2** • Edit file: organize_textures.ps1
The model provided an ambiguous search string to replace
Tool use: **edit_file_v2** • Edit file: organize_textures.ps1
Fixing the duplicate pattern issue by adding more context:
Tool use: **read_file_v2** • Read file: organize_textures.ps1
Checking if the functions were added correctly:
Tool use: **read_file_v2** • Read file: organize_textures.ps1
Adding the functions after Process-DuplicateGroup with more specific context:
Tool use: **edit_file_v2** • Edit file: organize_textures.ps1
Checking if the FlatColors processing section was updated correctly:
Tool use: **read_file_v2** • Read file: organize_textures.ps1
Checking the rest of the FlatColors section and the summary:
Tool use: **read_file_v2** • Read file: organize_textures.ps1
Checking the summary message:
Tool use: **read_file_v2** • Read file: organize_textures.ps1
Verifying the System.Drawing assembly was added:
Tool use: **read_file_v2** • Read file: organize_textures.ps1
Checking if the Add-Type line was added:
Tool use: **ripgrep_raw_search**
Parameters:
{
"pattern": "Add-Type.*System.Drawing",
"path": "organize_textures.ps1",
"caseInsensitive": false
}
Result:
{
"success": {
"pattern": "Add-Type.*System.Drawing",
"path": "organize_textures.ps1",
"outputMode": "content",
"workspaceResults": {
"A:\\1 Amazon_Active_Projects\\3 ProjectStructure": {
"content": {
"matches": [
{
"file": "organize_textures.ps1",
"matches": [
{
"lineNumber": 25,
"content": "Add-Type -AssemblyName System.Drawing"
}
]
}
],
"totalLines": 1,
"totalMatchedLines": 1
}
}
}
}
}
Status: completed
Integration complete. Removing the standalone script since it's merged:
Tool use: **delete_file**
Explanation: undefined
Merged the FlatColors standardization into organize_textures.ps1. Changes:
-
Added System.Drawing assembly for image processing
-
Added three functions:
Get-NormalizedColorCode: Extracts and normalizes hex color codes from filenamesConvert-To16x16Jpg: Converts and resizes images to 16x16 JPGTest-ImageSize: Checks if an image is 16x16
-
Replaced the FlatColors processing section (lines 422-508) to:
- Group files by color code instead of checksum
- Convert PNG files to 16x16 JPG (preserving TGA files as-is)
- Merge duplicates by color code (same color = one file)
- Ensure all FlatColors are 16x16
-
Removed the standalone script since it's integrated
When you run organize_textures.ps1, it will:
- Process regular textures by checksum (as before)
- Process FlatColors by color code, converting to 16x16 JPG and merging duplicates
The script now handles FlatColors standardization as part of the main workflow.
User
@PowerShell Extension (6-17)
Agent (model default, mode Agent)
Fixing the PowerShell error: $colorCode: is being parsed as a variable scope. Using ${colorCode} or string formatting to avoid the colon issue.
Tool use: **read_file_v2** • Read file: organize_textures.ps1
Tool use: **ripgrep_raw_search**
Parameters:
{
"pattern": "\\$colorCode:",
"path": "organize_textures.ps1",
"caseInsensitive": false
}
Result:
{
"success": {
"pattern": "\\$colorCode:",
"path": "organize_textures.ps1",
"outputMode": "content",
"workspaceResults": {
"A:\\1 Amazon_Active_Projects\\3 ProjectStructure": {
"content": {
"matches": [
{
"file": "organize_textures.ps1",
"matches": [
{
"lineNumber": 591,
"content": " Write-Warning \" $colorCode: No valid file found to process\""
},
{
"lineNumber": 619,
"content": " Write-Warning \" $colorCode: Failed to move TGA: $($_.Exception.Message)\""
},
{
"lineNumber": 665,
"content": " Write-Warning \" $colorCode: Failed to convert/resize\""
},
{
"lineNumber": 689,
"content": " Write-Warning \" $colorCode: Failed to move: $($_.Exception.Message)\""
}
]
}
],
"totalLines": 4,
"totalMatchedLines": 4
}
}
}
}
}
Status: completed
Fixing all instances where $colorCode: appears in strings by using ${colorCode}:
Tool use: **edit_file_v2** • Edit file: organize_textures.ps1
Tool use: **edit_file_v2** • Edit file: organize_textures.ps1
Tool use: **edit_file_v2** • Edit file: organize_textures.ps1
Tool use: **edit_file_v2** • Edit file: organize_textures.ps1
Fixed the PowerShell parsing error. PowerShell was interpreting $colorCode: as a variable scope modifier (like $global: or $script:), which caused the error.
Changed all instances of $colorCode: to ${colorCode}: to delimit the variable name. The script should now run without that parsing error.
The fix was applied to 4 locations where this pattern appeared in warning messages.