Compare commits
13 Commits
14e39d4ec1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 25a886d67a | |||
| 1ee6762289 | |||
| c33e80fcab | |||
| 8d211429b7 | |||
| 98af7d9331 | |||
| f10c313458 | |||
| bc012861ec | |||
| 65786add38 | |||
| 6a0005df46 | |||
| b23508d00c | |||
| 4a8ba8fd3d | |||
| d9a94a7df9 | |||
| 38d7f5032a |
@@ -0,0 +1,182 @@
|
|||||||
|
<!-- Generated by SpecStory, Markdown v2.1.0 -->
|
||||||
|
|
||||||
|
<!-- cursor Session d34c4fcf-e407-4038-b155-4bec229ecc4e (2026-01-12 04:42Z) -->
|
||||||
|
|
||||||
|
# Screw head size comparison (2026-01-12 04:42Z)
|
||||||
|
|
||||||
|
_**User (2026-01-12 04:50Z)**_
|
||||||
|
|
||||||
|
how much smaller is the head of a phillips flat head screw 6#-32x6 compared to a hard drive screw 6#32x5?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_**Agent (model default, mode Agent)**_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
Searching for head dimensions for 6-32 Phillips flat head and 6-32 hard drive screws.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<tool-use data-tool-type="search" data-tool-name="web_search">
|
||||||
|
<details>
|
||||||
|
<summary>Tool use: **web_search** • Searched web `6-32 Phillips flat head screw head diameter dimensions` • **1** results</summary>
|
||||||
|
|
||||||
|
| Title | URL | Chunk |
|
||||||
|
|-------|-----|-------|
|
||||||
|
| Web Search Results | | The head size of a screw is primarily determined by its head type and diameter, not its length. Both screws you've mentioned are #6-32, indicating they have the same diameter and thread pitch. The difference in length (6 inches vs. 5 inches) doesn't affect the head size.<br/><br/>A #6-32 Phillips flat head screw typically has a head diameter ranging from 0.238 inches to 0.262 inches. ([lhdottie.com](https://lhdottie.com/6-32-flat-head-squarephillips/fmdd6321?utm_source=openai))<br/><br/>Hard drive screws are often #6-32 pan head screws, which generally have a head diameter of approximately 0.294 inches. ([digikey.com](https://www.digikey.com/en/products/detail/apm-hexseal/R6-32X5-16-2701/1159355?utm_source=openai))<br/><br/>Therefore, the head of a #6-32 Phillips flat head screw is smaller in diameter compared to a #6-32 pan head screw, with the flat head being about 0.032 to 0.056 inches smaller. |
|
||||||
|
|
||||||
|
</details>
|
||||||
|
</tool-use>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<tool-use data-tool-type="search" data-tool-name="web_search">
|
||||||
|
<details>
|
||||||
|
<summary>Tool use: **web_search** • Searched web `6-32 hard drive screw head diameter dimensions` • **1** results</summary>
|
||||||
|
|
||||||
|
| Title | URL | Chunk |
|
||||||
|
|-------|-----|-------|
|
||||||
|
| Web Search Results | | The head diameter of a #6-32 Phillips flat head machine screw typically ranges from 0.238 inches to 0.262 inches. ([lhdottie.com](https://lhdottie.com/6-32-flat-head-squarephillips/fmdd6321?utm_source=openai)) Flat head screws are designed to sit flush with the surface, so their head height is minimal, around 0.083 inches.<br/><br/>In contrast, hard drive screws often use a #6-32 thread size with a pan head design. For example, a #6-32x5/16" pan head Phillips machine screw has a head diameter of approximately 0.22 inches and a head height of about 0.09 inches. ([walmart.com](https://www.walmart.com/ip/3945824417?utm_source=openai))<br/><br/>Comparing the two:<br/><br/>- **Head Diameter**: The flat head screw's diameter (0.238" to 0.262") is slightly larger than the pan head screw's diameter (approximately 0.22").<br/><br/>- **Head Height**: The flat head screw's height (0.083") is slightly less than the pan head screw's height (0.09").<br/><br/>Therefore, the flat head screw has a marginally larger head diameter but a slightly shorter head height compared to the pan head screw. |
|
||||||
|
|
||||||
|
</details>
|
||||||
|
</tool-use>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
**Phillips flat head screw (6-32):**
|
||||||
|
- Head diameter: **0.238" to 0.262"** (about 6.05–6.65 mm)
|
||||||
|
|
||||||
|
**Hard drive screw (6-32):**
|
||||||
|
- Head diameter: **~0.294"** (about 7.47 mm) for pan head
|
||||||
|
- Or **~0.22"** (about 5.59 mm) for some button/flat variants
|
||||||
|
|
||||||
|
**Difference:**
|
||||||
|
- If the hard drive screw is a pan head: the flat head is about **0.032" to 0.056" smaller** (roughly 0.8–1.4 mm).
|
||||||
|
- If it’s a button/flat variant: the flat head may be slightly larger.
|
||||||
|
|
||||||
|
Note: Hard drive screws vary by manufacturer. Pan head is common, but some use button or flat heads. The length difference (6 vs 5) doesn’t affect head size.
|
||||||
|
|
||||||
|
If you have the exact screw type, I can provide a more precise comparison.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_**User (2026-01-12 04:50Z)**_
|
||||||
|
|
||||||
|
how much should I scale up the hole in blender? I haven't done CAD in a long time.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_**Agent (model default, mode Agent)**_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
Checking the Blender scene to see what we're working with:
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<tool-use data-tool-type="mcp" data-tool-name="mcp_blender_get_scene_info">
|
||||||
|
<details>
|
||||||
|
<summary>Tool use: **mcp_blender_get_scene_info**</summary>
|
||||||
|
|
||||||
|
*Called tool*: blender - get_scene_info: Get detailed information about the current Blender scene
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- user_prompt: The original user prompt that led to this tool call (required for telemetry)
|
||||||
|
|
||||||
|
|
||||||
|
*Parameters*:
|
||||||
|
* user_prompt: Checking scene to understand what hole needs to be scaled for screw clearance
|
||||||
|
|
||||||
|
*Result*:
|
||||||
|
Error getting scene info: Could not connect to Blender. Make sure the Blender addon is running.
|
||||||
|
</details>
|
||||||
|
</tool-use>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
File seems to be binary and cannot be opened as text
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
For a **#6-32 screw**, use these clearances:
|
||||||
|
|
||||||
|
**Screw specifications:**
|
||||||
|
- Major diameter: **0.138"** (3.505 mm)
|
||||||
|
- Thread pitch: 32 threads per inch
|
||||||
|
|
||||||
|
**Recommended hole sizes:**
|
||||||
|
- **Close fit**: **0.1495"** (3.80 mm) — #25 drill
|
||||||
|
- **Normal fit**: **0.152"** (3.86 mm) — #24 drill
|
||||||
|
- **Loose fit**: **0.159"** (4.04 mm) — #21 drill
|
||||||
|
|
||||||
|
**In Blender:**
|
||||||
|
- If your hole is currently **3.505 mm** (screw diameter), scale it to about **3.8–3.9 mm** for a normal fit.
|
||||||
|
- That’s roughly a **1.08–1.11x scale** (about 8–11% larger).
|
||||||
|
|
||||||
|
**Quick rule of thumb:**
|
||||||
|
- Add **0.3–0.5 mm** (0.012–0.020") to the screw’s major diameter for clearance.
|
||||||
|
|
||||||
|
**For your specific case:**
|
||||||
|
- If modeling for a **Phillips flat head** (head ~6.05–6.65 mm), the clearance hole can be smaller since the head sits on top.
|
||||||
|
- If it’s a **pan head hard drive screw** (head ~7.47 mm), ensure the head can pass through if it’s a through-hole, or use a counterbore.
|
||||||
|
|
||||||
|
What type of hole are you making (through-hole, counterbore, or tapped)?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_**User (2026-01-12 04:50Z)**_
|
||||||
|
|
||||||
|
how to export print-ready STL from Blender?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_**Agent (model default, mode Agent)**_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
Exporting a print-ready STL from Blender:
|
||||||
|
|
||||||
|
1. Select your object(s) in Object Mode.
|
||||||
|
2. File → Export → STL (.stl).
|
||||||
|
3. In the export dialog:
|
||||||
|
- Check "Selection Only" if you only want selected objects.
|
||||||
|
- Set "Scale" to 1.0 (or adjust if your model is in a different unit system).
|
||||||
|
- Check "Apply Modifiers" if you have modifiers (Subdivision Surface, etc.).
|
||||||
|
- Check "Forward: -Z Forward" and "Up: Y Up" (common for 3D printing).
|
||||||
|
4. Click "Export STL".
|
||||||
|
|
||||||
|
Important checks before exporting:
|
||||||
|
- Ensure the model is manifold (no holes, non-manifold edges, or inverted normals).
|
||||||
|
- Check scale: Blender units = mm by default. Verify your dimensions are correct.
|
||||||
|
- Remove internal geometry if not needed (to save material/time).
|
||||||
|
|
||||||
|
Quick check for issues:
|
||||||
|
- Edit Mode → Select All (A) → Mesh → Clean Up → "Select Non-Manifold" to find problems.
|
||||||
|
- Use the 3D Print Toolbox addon (Edit → Preferences → Add-ons → search "3D Print Toolbox") for analysis.
|
||||||
|
|
||||||
|
If you want, I can help check your model or set up the export settings.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
Binary file not shown.
BIN
Assets/Synology_D6_Tray_v28.stl
Normal file
BIN
Assets/Synology_D6_Tray_v28.stl
Normal file
Binary file not shown.
BIN
Blends/0template.blend
LFS
Normal file
BIN
Blends/0template.blend
LFS
Normal file
Binary file not shown.
BIN
Blends/SynologyD6_B.blend
LFS
Normal file
BIN
Blends/SynologyD6_B.blend
LFS
Normal file
Binary file not shown.
BIN
Blends/SynologyD6_C.blend
LFS
Normal file
BIN
Blends/SynologyD6_C.blend
LFS
Normal file
Binary file not shown.
BIN
Blends/SynologyD6_R.blend
LFS
Normal file
BIN
Blends/SynologyD6_R.blend
LFS
Normal file
Binary file not shown.
BIN
Blends/SynologyD6_S.blend
LFS
Normal file
BIN
Blends/SynologyD6_S.blend
LFS
Normal file
Binary file not shown.
BIN
Blends/stack.blend
LFS
Normal file
BIN
Blends/stack.blend
LFS
Normal file
Binary file not shown.
@@ -1,442 +0,0 @@
|
|||||||
[CmdletBinding()]
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory=$false)]
|
|
||||||
[string]$ProjectPath
|
|
||||||
)
|
|
||||||
|
|
||||||
Set-StrictMode -Version Latest
|
|
||||||
$ErrorActionPreference = 'Stop'
|
|
||||||
|
|
||||||
$script:LoaderRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
||||||
$script:ConfigPath = Join-Path -Path $script:LoaderRoot -ChildPath 'config.json'
|
|
||||||
$script:ConfigCache = $null
|
|
||||||
|
|
||||||
function Get-ProjectStructureConfig {
|
|
||||||
if ($null -ne $script:ConfigCache) {
|
|
||||||
return $script:ConfigCache
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Test-Path -LiteralPath $script:ConfigPath) {
|
|
||||||
try {
|
|
||||||
$raw = Get-Content -LiteralPath $script:ConfigPath -Raw -ErrorAction Stop
|
|
||||||
if ($raw.Trim().Length -gt 0) {
|
|
||||||
$script:ConfigCache = $raw | ConvertFrom-Json
|
|
||||||
return $script:ConfigCache
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Warning "Failed to parse config.json: $($_.Exception.Message)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$script:ConfigCache = [pscustomobject]@{}
|
|
||||||
return $script:ConfigCache
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-ConfigValue {
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory)] [string]$Name,
|
|
||||||
$Default = $null
|
|
||||||
)
|
|
||||||
|
|
||||||
$config = Get-ProjectStructureConfig
|
|
||||||
if ($config.PSObject.Properties.Name -contains $Name) {
|
|
||||||
$value = $config.$Name
|
|
||||||
if ($null -ne $value -and ($value -isnot [string] -or $value.Trim().Length -gt 0)) {
|
|
||||||
return $value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $Default
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-StructDirectory {
|
|
||||||
# When script is run directly (not dot-sourced), always use script's directory for portability
|
|
||||||
if ($MyInvocation.InvocationName -ne '.') {
|
|
||||||
return $script:LoaderRoot
|
|
||||||
}
|
|
||||||
|
|
||||||
$value = Get-ConfigValue -Name 'structDir'
|
|
||||||
if ($null -eq $value -or [string]::IsNullOrWhiteSpace($value)) {
|
|
||||||
return $script:LoaderRoot
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([System.IO.Path]::IsPathRooted($value)) {
|
|
||||||
$resolved = Resolve-Path -LiteralPath $value -ErrorAction SilentlyContinue
|
|
||||||
if ($null -ne $resolved) { return $resolved.Path }
|
|
||||||
return $value
|
|
||||||
}
|
|
||||||
|
|
||||||
$candidate = Join-Path -Path $script:LoaderRoot -ChildPath $value
|
|
||||||
$resolvedCandidate = Resolve-Path -LiteralPath $candidate -ErrorAction SilentlyContinue
|
|
||||||
if ($null -ne $resolvedCandidate) { return $resolvedCandidate.Path }
|
|
||||||
return $candidate
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-ProjectsRoot {
|
|
||||||
$value = Get-ConfigValue -Name 'projectsRoot'
|
|
||||||
if ($null -eq $value -or [string]::IsNullOrWhiteSpace($value)) {
|
|
||||||
$structDir = Get-StructDirectory
|
|
||||||
$parent = Split-Path -Parent $structDir
|
|
||||||
if ($null -eq $parent -or $parent.Length -eq 0 -or $parent -eq $structDir) {
|
|
||||||
return $structDir
|
|
||||||
}
|
|
||||||
return $parent
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([System.IO.Path]::IsPathRooted($value)) {
|
|
||||||
$resolved = Resolve-Path -LiteralPath $value -ErrorAction SilentlyContinue
|
|
||||||
if ($null -ne $resolved) { return $resolved.Path }
|
|
||||||
return $value
|
|
||||||
}
|
|
||||||
|
|
||||||
$candidate = Join-Path -Path $script:LoaderRoot -ChildPath $value
|
|
||||||
$resolvedCandidate = Resolve-Path -LiteralPath $candidate -ErrorAction SilentlyContinue
|
|
||||||
if ($null -ne $resolvedCandidate) { return $resolvedCandidate.Path }
|
|
||||||
return $candidate
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-ProjectPathFromUser {
|
|
||||||
param(
|
|
||||||
[string]$Prompt = "Paste the project path to deploy in"
|
|
||||||
)
|
|
||||||
|
|
||||||
do {
|
|
||||||
$inputPath = Read-Host -Prompt $Prompt
|
|
||||||
if ([string]::IsNullOrWhiteSpace($inputPath)) {
|
|
||||||
Write-Warning "Path cannot be empty. Please try again."
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
# Remove quotes if present
|
|
||||||
$inputPath = $inputPath.Trim('"', "'")
|
|
||||||
|
|
||||||
# Try to resolve the path
|
|
||||||
try {
|
|
||||||
if (Test-Path -LiteralPath $inputPath -PathType Container) {
|
|
||||||
$resolved = Resolve-Path -LiteralPath $inputPath -ErrorAction Stop
|
|
||||||
return $resolved.Path
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Warning "Path does not exist or is not a directory: $inputPath"
|
|
||||||
$retry = Read-Host "Try again? (Y/N)"
|
|
||||||
if ($retry -notmatch '^[Yy]') {
|
|
||||||
return $null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Warning "Invalid path: $($_.Exception.Message)"
|
|
||||||
$retry = Read-Host "Try again? (Y/N)"
|
|
||||||
if ($retry -notmatch '^[Yy]') {
|
|
||||||
return $null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while ($true)
|
|
||||||
}
|
|
||||||
|
|
||||||
function Use-IsoDailyFormat {
|
|
||||||
$dailyFormat = Get-ConfigValue -Name 'dailyFormat' -Default $true
|
|
||||||
|
|
||||||
# Handle backward compatibility with boolean values
|
|
||||||
if ($dailyFormat -is [bool]) {
|
|
||||||
return $dailyFormat
|
|
||||||
}
|
|
||||||
|
|
||||||
# Handle string values
|
|
||||||
if ($dailyFormat -is [string]) {
|
|
||||||
$formatStr = $dailyFormat.Trim()
|
|
||||||
# ISO format contains YYYY-MM-DD pattern
|
|
||||||
if ($formatStr -match 'YYYY-MM-DD' -or $formatStr -match '\d{4}-\d{2}-\d{2}') {
|
|
||||||
return $true
|
|
||||||
}
|
|
||||||
# daily_YYMMDD or other formats are not ISO
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
|
|
||||||
# Default to false (not ISO format) for unknown types
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
|
|
||||||
function Use-7Zip {
|
|
||||||
$zipper = Get-ConfigValue -Name 'zipper' -Default $true
|
|
||||||
|
|
||||||
# Handle backward compatibility with boolean values
|
|
||||||
if ($zipper -is [bool]) {
|
|
||||||
return $zipper
|
|
||||||
}
|
|
||||||
|
|
||||||
# Handle string values
|
|
||||||
if ($zipper -is [string]) {
|
|
||||||
$zipperStr = $zipper.Trim().ToLower()
|
|
||||||
return ($zipperStr -eq '7z')
|
|
||||||
}
|
|
||||||
|
|
||||||
# Default to false (use zip) for unknown types
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-ZipCompressionLevel {
|
|
||||||
$value = Get-ConfigValue -Name 'compression' -Default 9
|
|
||||||
if ($value -is [string]) {
|
|
||||||
$parsed = 0
|
|
||||||
if ([int]::TryParse($value, [ref]$parsed)) {
|
|
||||||
$value = $parsed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($value -isnot [int]) {
|
|
||||||
return 9
|
|
||||||
}
|
|
||||||
|
|
||||||
return [Math]::Min(9, [Math]::Max(0, $value))
|
|
||||||
}
|
|
||||||
|
|
||||||
function Update-ConfigStructDir {
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory)] [string]$StructDir
|
|
||||||
)
|
|
||||||
|
|
||||||
$config = Get-ProjectStructureConfig
|
|
||||||
$config.structDir = $StructDir
|
|
||||||
|
|
||||||
try {
|
|
||||||
$json = $config | ConvertTo-Json -Depth 10
|
|
||||||
Set-Content -LiteralPath $script:ConfigPath -Value $json -NoNewline -ErrorAction Stop
|
|
||||||
$script:ConfigCache = $config
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Warning "Failed to update config.json: $($_.Exception.Message)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# If script is run directly (not dot-sourced), prompt for project path and deploy
|
|
||||||
# When dot-sourced, InvocationName is '.'; when run directly, it's the script path or name
|
|
||||||
if ($MyInvocation.InvocationName -ne '.') {
|
|
||||||
# Update config.json to use script's directory as structDir for portability
|
|
||||||
Update-ConfigStructDir -StructDir $script:LoaderRoot
|
|
||||||
|
|
||||||
# Use provided ProjectPath parameter, or prompt user if not provided
|
|
||||||
if ([string]::IsNullOrWhiteSpace($ProjectPath)) {
|
|
||||||
$projectPath = Get-ProjectPathFromUser
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
# Remove quotes if present and resolve the provided path
|
|
||||||
$ProjectPath = $ProjectPath.Trim('"', "'")
|
|
||||||
try {
|
|
||||||
if (Test-Path -LiteralPath $ProjectPath -PathType Container) {
|
|
||||||
$projectPath = (Resolve-Path -LiteralPath $ProjectPath -ErrorAction Stop).Path
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Error "Project path does not exist or is not a directory: $ProjectPath"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Error "Unable to resolve project directory: $($_.Exception.Message)"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($null -ne $projectPath) {
|
|
||||||
# Deploy batch files and config to the project
|
|
||||||
$structDir = Get-StructDirectory
|
|
||||||
if (-not (Test-Path -LiteralPath $structDir -PathType Container)) {
|
|
||||||
Write-Error "Configured structDir not found: $structDir"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$resolvedProject = (Resolve-Path -LiteralPath $projectPath -ErrorAction Stop).Path
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Error "Unable to resolve project directory: $($_.Exception.Message)"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-not (Test-Path -LiteralPath $resolvedProject -PathType Container)) {
|
|
||||||
Write-Error "Project path is not a directory: $resolvedProject"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "`nDeploying to: $resolvedProject" -ForegroundColor Cyan
|
|
||||||
Write-Host "Struct directory: $structDir" -ForegroundColor Cyan
|
|
||||||
|
|
||||||
$specs = @(
|
|
||||||
@{ Name = 'UpdateSequences.bat'; Source = Join-Path -Path $structDir -ChildPath 'UpdateSequences.bat' },
|
|
||||||
@{ Name = 'UpdateAllSequences.bat'; Source = Join-Path -Path $structDir -ChildPath 'UpdateAllSequences.bat' },
|
|
||||||
@{ Name = 'ZipSeqArchv.bat'; Source = Join-Path -Path $structDir -ChildPath 'ZipSeqArchv.bat' },
|
|
||||||
@{ Name = 'UnzipSeqArchv.bat'; Source = Join-Path -Path $structDir -ChildPath 'UnzipSeqArchv.bat' },
|
|
||||||
@{ Name = 'NewDaily.bat'; Source = Join-Path -Path $structDir -ChildPath 'NewDaily.bat' },
|
|
||||||
@{ Name = '.gitattributes'; Source = Join-Path -Path $structDir -ChildPath 'components\gitattributes' },
|
|
||||||
@{ Name = '.gitignore'; Source = Join-Path -Path $structDir -ChildPath 'components\gitignore' }
|
|
||||||
)
|
|
||||||
|
|
||||||
# Config files to deploy to projectroot\.config\
|
|
||||||
$configAssets = @(
|
|
||||||
@{ Name = 'config.json'; Source = Join-Path -Path $structDir -ChildPath 'config.json' },
|
|
||||||
@{ Name = 'GetStructDir.ps1'; Source = Join-Path -Path $structDir -ChildPath 'GetStructDir.ps1' }
|
|
||||||
)
|
|
||||||
|
|
||||||
foreach ($spec in $specs) {
|
|
||||||
if (-not (Test-Path -LiteralPath $spec.Source -PathType Leaf)) {
|
|
||||||
Write-Error "Source file not found: $($spec.Source)"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($asset in $configAssets) {
|
|
||||||
if (-not (Test-Path -LiteralPath $asset.Source -PathType Leaf)) {
|
|
||||||
Write-Error "Config asset not found: $($asset.Source)"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Ensure .config directory exists in project root and is hidden
|
|
||||||
$projectConfigDir = Join-Path -Path $resolvedProject -ChildPath '.config'
|
|
||||||
if (-not (Test-Path -LiteralPath $projectConfigDir -PathType Container)) {
|
|
||||||
New-Item -Path $projectConfigDir -ItemType Directory -Force | Out-Null
|
|
||||||
Write-Host "Created .config directory: $projectConfigDir" -ForegroundColor Cyan
|
|
||||||
}
|
|
||||||
# Set hidden attribute on .config directory
|
|
||||||
$folder = Get-Item -LiteralPath $projectConfigDir -Force
|
|
||||||
$folder.Attributes = $folder.Attributes -bor [System.IO.FileAttributes]::Hidden
|
|
||||||
|
|
||||||
$touchedDirs = @{}
|
|
||||||
$summary = @()
|
|
||||||
|
|
||||||
foreach ($spec in $specs) {
|
|
||||||
Write-Host "`n=== Updating $($spec.Name) ===" -ForegroundColor Magenta
|
|
||||||
|
|
||||||
$targets = Get-ChildItem -LiteralPath $resolvedProject -Recurse -Filter $spec.Name -File -Force -ErrorAction SilentlyContinue
|
|
||||||
$targets = $targets | Where-Object { $_.FullName -ne $spec.Source }
|
|
||||||
|
|
||||||
if (-not $targets) {
|
|
||||||
Write-Host "No targets found." -ForegroundColor Yellow
|
|
||||||
$summary += [pscustomobject]@{
|
|
||||||
Name = $spec.Name
|
|
||||||
Updated = 0
|
|
||||||
Failed = 0
|
|
||||||
Skipped = 0
|
|
||||||
Total = 0
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
$updated = 0
|
|
||||||
$failed = 0
|
|
||||||
|
|
||||||
foreach ($target in $targets) {
|
|
||||||
try {
|
|
||||||
Copy-Item -Path $spec.Source -Destination $target.FullName -Force
|
|
||||||
# Set hidden attribute for .gitattributes and .gitignore files
|
|
||||||
if ($spec.Name -eq '.gitattributes' -or $spec.Name -eq '.gitignore') {
|
|
||||||
$file = Get-Item -LiteralPath $target.FullName -Force
|
|
||||||
$file.Attributes = $file.Attributes -bor [System.IO.FileAttributes]::Hidden
|
|
||||||
}
|
|
||||||
Write-Host "[OK] $($target.FullName)" -ForegroundColor Green
|
|
||||||
$updated++
|
|
||||||
|
|
||||||
$targetDir = $target.Directory.FullName
|
|
||||||
if (-not $touchedDirs.ContainsKey($targetDir)) {
|
|
||||||
$touchedDirs[$targetDir] = $true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "[FAIL] $($target.FullName)" -ForegroundColor Red
|
|
||||||
Write-Host " $($_.Exception.Message)" -ForegroundColor DarkRed
|
|
||||||
$failed++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$summary += [pscustomobject]@{
|
|
||||||
Name = $spec.Name
|
|
||||||
Updated = $updated
|
|
||||||
Failed = $failed
|
|
||||||
Skipped = 0
|
|
||||||
Total = @($targets).Count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "`n=== Summary ===" -ForegroundColor Cyan
|
|
||||||
foreach ($item in $summary) {
|
|
||||||
Write-Host ("{0,-22} Updated: {1,3} Failed: {2,3} Total: {3,3}" -f $item.Name, $item.Updated, $item.Failed, $item.Total)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($summary | Measure-Object -Property Failed -Sum).Sum -gt 0) {
|
|
||||||
Write-Host "Completed with errors." -ForegroundColor Yellow
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "All batch files refreshed successfully." -ForegroundColor Green
|
|
||||||
|
|
||||||
# Deploy ZipSeqArchv.bat and UnzipSeqArchv.bat to \Renders
|
|
||||||
Write-Host "`n=== Deploying ZipSeqArchv.bat and UnzipSeqArchv.bat to \Renders ===" -ForegroundColor Magenta
|
|
||||||
$rendersDir = Join-Path -Path $resolvedProject -ChildPath 'Renders'
|
|
||||||
if (-not (Test-Path -LiteralPath $rendersDir -PathType Container)) {
|
|
||||||
New-Item -Path $rendersDir -ItemType Directory -Force | Out-Null
|
|
||||||
Write-Host "Created Renders directory: $rendersDir" -ForegroundColor Cyan
|
|
||||||
}
|
|
||||||
$zipFiles = @(
|
|
||||||
@{ Name = 'ZipSeqArchv.bat'; Source = Join-Path -Path $structDir -ChildPath 'ZipSeqArchv.bat' },
|
|
||||||
@{ Name = 'UnzipSeqArchv.bat'; Source = Join-Path -Path $structDir -ChildPath 'UnzipSeqArchv.bat' }
|
|
||||||
)
|
|
||||||
foreach ($zipFile in $zipFiles) {
|
|
||||||
$targetPath = Join-Path -Path $rendersDir -ChildPath $zipFile.Name
|
|
||||||
try {
|
|
||||||
Copy-Item -Path $zipFile.Source -Destination $targetPath -Force
|
|
||||||
Write-Host "[OK] $targetPath" -ForegroundColor Green
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "[FAIL] $targetPath" -ForegroundColor Red
|
|
||||||
Write-Host " $($_.Exception.Message)" -ForegroundColor DarkRed
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Deploy .gitattributes and .gitignore to project root if they don't exist
|
|
||||||
Write-Host "`n=== Deploying .gitattributes and .gitignore to project root ===" -ForegroundColor Magenta
|
|
||||||
$gitFiles = @(
|
|
||||||
@{ Name = '.gitattributes'; Source = Join-Path -Path $structDir -ChildPath 'components\gitattributes' },
|
|
||||||
@{ Name = '.gitignore'; Source = Join-Path -Path $structDir -ChildPath 'components\gitignore' }
|
|
||||||
)
|
|
||||||
foreach ($gitFile in $gitFiles) {
|
|
||||||
$targetPath = Join-Path -Path $resolvedProject -ChildPath $gitFile.Name
|
|
||||||
try {
|
|
||||||
Copy-Item -Path $gitFile.Source -Destination $targetPath -Force
|
|
||||||
# Set hidden attribute on the file
|
|
||||||
$file = Get-Item -LiteralPath $targetPath -Force
|
|
||||||
$file.Attributes = $file.Attributes -bor [System.IO.FileAttributes]::Hidden
|
|
||||||
Write-Host "[OK] $targetPath" -ForegroundColor Green
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "[FAIL] $targetPath" -ForegroundColor Red
|
|
||||||
Write-Host " $($_.Exception.Message)" -ForegroundColor DarkRed
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Deploy config files to projectroot\.config\
|
|
||||||
Write-Host "`n=== Deploying config files to .config\ ===" -ForegroundColor Magenta
|
|
||||||
foreach ($asset in $configAssets) {
|
|
||||||
$targetPath = Join-Path -Path $projectConfigDir -ChildPath $asset.Name
|
|
||||||
try {
|
|
||||||
Copy-Item -Path $asset.Source -Destination $targetPath -Force
|
|
||||||
Write-Host "[OK] $targetPath" -ForegroundColor Green
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "[FAIL] $targetPath" -ForegroundColor Red
|
|
||||||
Write-Host " $($_.Exception.Message)" -ForegroundColor DarkRed
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "`nConfig files deployed successfully." -ForegroundColor Green
|
|
||||||
Write-Host "Deployment completed successfully." -ForegroundColor Green
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Host "No project path provided." -ForegroundColor Yellow
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
@echo off
|
|
||||||
setlocal EnableExtensions EnableDelayedExpansion
|
|
||||||
|
|
||||||
set "REN_DIR=%~dp0"
|
|
||||||
for %%I in ("%REN_DIR%..") do set "PROJ_ROOT=%%~fI"
|
|
||||||
|
|
||||||
set "CONFIG_DIR=%PROJ_ROOT%\.config"
|
|
||||||
set "CONFIG_PATH=%CONFIG_DIR%\config.json"
|
|
||||||
set "GET_STRUCT_DIR=%CONFIG_DIR%\GetStructDir.ps1"
|
|
||||||
|
|
||||||
if not exist "%CONFIG_PATH%" (
|
|
||||||
echo [ERROR] config.json not found at %CONFIG_PATH%
|
|
||||||
echo Please run ConfigLoader.ps1 to deploy helper files.
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
if not exist "%GET_STRUCT_DIR%" (
|
|
||||||
echo [ERROR] GetStructDir.ps1 not found at %GET_STRUCT_DIR%
|
|
||||||
echo Please run ConfigLoader.ps1 to deploy helper files.
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
for /f "usebackq delims=" %%I in (`powershell -NoProfile -ExecutionPolicy Bypass -Command ^
|
|
||||||
"Set-StrictMode -Version Latest; $structDir = & '%GET_STRUCT_DIR%' -ProjectRoot '%PROJ_ROOT%'; if (-not $structDir) { throw \"Failed to get structDir from GetStructDir.ps1\" }; $pyPath = Join-Path $structDir 'zip_sequences.py'; if (-not (Test-Path -LiteralPath $pyPath)) { throw \"zip_sequences.py not found at $pyPath\" }; Write-Output $pyPath"`) do set "PY_SCRIPT=%%I"
|
|
||||||
|
|
||||||
if not defined PY_SCRIPT (
|
|
||||||
echo [ERROR] Unable to resolve zip_sequences.py path from config.
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
pushd "%PROJ_ROOT%" >nul 2>&1
|
|
||||||
|
|
||||||
python "%PY_SCRIPT%" --mode expand --verbose %*
|
|
||||||
set "ERR=!ERRORLEVEL!"
|
|
||||||
|
|
||||||
if not "!ERR!"=="0" (
|
|
||||||
echo Failed to expand render sequence archives (exit code !ERR!).
|
|
||||||
)
|
|
||||||
|
|
||||||
popd >nul 2>&1
|
|
||||||
exit /b !ERR!
|
|
||||||
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
@echo off
|
|
||||||
setlocal EnableExtensions
|
|
||||||
|
|
||||||
set "script_dir=%~dp0"
|
|
||||||
set "current_dir=%CD%"
|
|
||||||
set "PROJ_ROOT="
|
|
||||||
|
|
||||||
REM First, check project level (one directory up from current) - most common case
|
|
||||||
for %%I in ("%current_dir%..") do set "project_level=%%~fI"
|
|
||||||
set "project_config=%project_level%\.config\config.json"
|
|
||||||
if exist "%project_config%" (
|
|
||||||
set "PROJ_ROOT=%project_level%"
|
|
||||||
)
|
|
||||||
|
|
||||||
REM If not found at project level, search up from current working directory
|
|
||||||
if not defined PROJ_ROOT (
|
|
||||||
for /f "usebackq delims=" %%I in (`powershell -NoProfile -ExecutionPolicy Bypass -Command "Set-StrictMode -Version Latest; $dir = '%current_dir%'; $found = $null; while ($dir -and -not $found) { $configPath = Join-Path $dir '.config\config.json'; if (Test-Path -LiteralPath $configPath) { $found = $dir; break }; $parent = Split-Path -Parent $dir; if ($parent -eq $dir) { break }; $dir = $parent }; if ($found) { Write-Output $found } else { Write-Output '' }"`) do set "PROJ_ROOT=%%I"
|
|
||||||
)
|
|
||||||
|
|
||||||
REM If still not found, try searching from script location
|
|
||||||
if not defined PROJ_ROOT (
|
|
||||||
for /f "usebackq delims=" %%I in (`powershell -NoProfile -ExecutionPolicy Bypass -Command "Set-StrictMode -Version Latest; $dir = '%script_dir%'; $found = $null; while ($dir -and -not $found) { $configPath = Join-Path $dir '.config\config.json'; if (Test-Path -LiteralPath $configPath) { $found = $dir; break }; $parent = Split-Path -Parent $dir; if ($parent -eq $dir) { break }; $dir = $parent }; if ($found) { Write-Output $found } else { Write-Output '' }"`) do set "PROJ_ROOT=%%I"
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Fallback: try original logic (script in 3 ProjectStructure)
|
|
||||||
if not defined PROJ_ROOT (
|
|
||||||
for %%I in ("%script_dir%..\..") do set "PROJ_ROOT=%%~fI"
|
|
||||||
)
|
|
||||||
|
|
||||||
set "CONFIG_DIR=%PROJ_ROOT%\.config"
|
|
||||||
set "CONFIG_PATH=%CONFIG_DIR%\config.json"
|
|
||||||
|
|
||||||
if not exist "%CONFIG_PATH%" (
|
|
||||||
echo [ERROR] config.json not found at %CONFIG_PATH%
|
|
||||||
if defined project_config (
|
|
||||||
echo Also checked: %project_config%
|
|
||||||
)
|
|
||||||
echo Please run ConfigLoader.ps1 to deploy helper files.
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
set "GET_STRUCT_DIR=%CONFIG_DIR%\GetStructDir.ps1"
|
|
||||||
|
|
||||||
if not exist "%GET_STRUCT_DIR%" (
|
|
||||||
echo [ERROR] GetStructDir.ps1 not found at %GET_STRUCT_DIR%
|
|
||||||
echo Please run ConfigLoader.ps1 to deploy helper files.
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
for /f "usebackq delims=" %%I in (`powershell -NoProfile -ExecutionPolicy Bypass -Command ^
|
|
||||||
"Set-StrictMode -Version Latest; $structDir = & '%GET_STRUCT_DIR%' -ProjectRoot '%PROJ_ROOT%'; if (-not $structDir) { throw \"Failed to get structDir from GetStructDir.ps1\" }; $ps1Path = Join-Path $structDir 'UpdateSequences.ps1'; if (-not (Test-Path -LiteralPath $ps1Path)) { throw \"UpdateSequences.ps1 not found at $ps1Path\" }; Write-Output $ps1Path"`) do set "ps1=%%I"
|
|
||||||
|
|
||||||
if not defined ps1 (
|
|
||||||
echo [ERROR] Unable to resolve UpdateSequences.ps1 path from config.
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
echo Running PowerShell update script...
|
|
||||||
powershell -NoProfile -ExecutionPolicy Bypass -File "%ps1%"
|
|
||||||
set "rc=%errorlevel%"
|
|
||||||
echo PowerShell exited with RC=%rc%
|
|
||||||
echo Done.
|
|
||||||
pause >nul
|
|
||||||
exit /b %rc%
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
@echo off
|
|
||||||
setlocal EnableExtensions EnableDelayedExpansion
|
|
||||||
|
|
||||||
set "REN_DIR=%~dp0"
|
|
||||||
for %%I in ("%REN_DIR%..") do set "PROJ_ROOT=%%~fI"
|
|
||||||
|
|
||||||
set "CONFIG_DIR=%PROJ_ROOT%\.config"
|
|
||||||
set "CONFIG_PATH=%CONFIG_DIR%\config.json"
|
|
||||||
set "GET_STRUCT_DIR=%CONFIG_DIR%\GetStructDir.ps1"
|
|
||||||
|
|
||||||
if not exist "%CONFIG_PATH%" (
|
|
||||||
echo [ERROR] config.json not found at %CONFIG_PATH%
|
|
||||||
echo Please run ConfigLoader.ps1 to deploy helper files.
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
if not exist "%GET_STRUCT_DIR%" (
|
|
||||||
echo [ERROR] GetStructDir.ps1 not found at %GET_STRUCT_DIR%
|
|
||||||
echo Please run ConfigLoader.ps1 to deploy helper files.
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
for /f "usebackq delims=" %%I in (`powershell -NoProfile -ExecutionPolicy Bypass -Command ^
|
|
||||||
"Set-StrictMode -Version Latest; $structDir = & '%GET_STRUCT_DIR%' -ProjectRoot '%PROJ_ROOT%'; if (-not $structDir) { throw \"Failed to get structDir from GetStructDir.ps1\" }; $pyPath = Join-Path $structDir 'zip_sequences.py'; if (-not (Test-Path -LiteralPath $pyPath)) { throw \"zip_sequences.py not found at $pyPath\" }; Write-Output $pyPath"`) do set "PY_SCRIPT=%%~I"
|
|
||||||
|
|
||||||
if not defined PY_SCRIPT (
|
|
||||||
echo [ERROR] Unable to resolve zip_sequences.py path from config.
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
pushd "%PROJ_ROOT%" >nul 2>&1
|
|
||||||
|
|
||||||
python "%PY_SCRIPT%" --verbose %*
|
|
||||||
set "ERR=!ERRORLEVEL!"
|
|
||||||
|
|
||||||
popd >nul 2>&1
|
|
||||||
|
|
||||||
if !ERR! NEQ 0 (
|
|
||||||
echo Failed to update render sequence archives ^(exit code !ERR!^).
|
|
||||||
exit /b !ERR!
|
|
||||||
)
|
|
||||||
|
|
||||||
exit /b 0
|
|
||||||
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"dailyFormat": "YYYY-MM-DD",
|
|
||||||
"structDir": "D:\\0 ProjectStructure",
|
|
||||||
"zipper": "7z",
|
|
||||||
"compression": 0,
|
|
||||||
"Max7zInst": 0
|
|
||||||
}
|
|
||||||
BIN
STL/SynologyD6_B.stl
Normal file
BIN
STL/SynologyD6_B.stl
Normal file
Binary file not shown.
BIN
STL/SynologyD6_C.stl
Normal file
BIN
STL/SynologyD6_C.stl
Normal file
Binary file not shown.
BIN
STL/SynologyD6_R.stl
Normal file
BIN
STL/SynologyD6_R.stl
Normal file
Binary file not shown.
BIN
STL/SynologyD6_S.stl
Normal file
BIN
STL/SynologyD6_S.stl
Normal file
Binary file not shown.
Reference in New Issue
Block a user