<# .SYNOPSIS Déploie l'extension « Iso-couches par nuances de gris » dans Inkscape. .DESCRIPTION Copie gray_iso_layers.inx, gray_iso_layers.py, gray_iso_layers_core.py, le schéma de l'onglet « Help » (images\parameters_en.png), celui de l'onglet « Depth » (images\depth_en.png) et les traductions compilées (locale\\LC_MESSAGES\grayisolayers.mo) dans un sous-dossier dédié du répertoire des extensions utilisateur d'Inkscape (Inkscape explore récursivement ce répertoire). Refuse de s'exécuter si Inkscape est ouvert : les extensions ne sont chargées qu'au démarrage. .PARAMETER ExtensionsDir Répertoire des extensions Inkscape. Par défaut : %APPDATA%\inkscape\extensions .PARAMETER FolderName Nom du sous-dossier de l'extension. Par défaut : GrayIsoLayers .PARAMETER Depth Installe aussi de quoi calculer les cartes de profondeur, dans %LOCALAPPDATA%\GrayIsoLayers : un environnement Python (onnxruntime-directml, numpy, pillow) et les deux modèles (MiDaS small, Depth Anything V2 Small, environ 165 Mo à télécharger). Le Python d'Inkscape ne peut pas charger onnxruntime : il faut un Python 3 installé sur la machine. .PARAMETER Python Python qui crée l'environnement de -Depth. Par défaut : « python » du PATH, sinon le lanceur « py ». À indiquer si le Python trouvé est trop récent pour onnxruntime. .PARAMETER Uninstall Supprime le sous-dossier de l'extension au lieu de le créer, ainsi que %LOCALAPPDATA%\GrayIsoLayers (environnement, modèles, cache). .PARAMETER Force Déploie même si Inkscape est en cours d'exécution. .EXAMPLE .\deploy.ps1 .\deploy.ps1 -Depth .\deploy.ps1 -Uninstall .\deploy.ps1 -FolderName 'autre-nom' #> [CmdletBinding()] param( [string] $ExtensionsDir = (Join-Path $env:APPDATA 'inkscape\extensions'), [string] $FolderName = 'GrayIsoLayers', [switch] $Depth, [string] $Python, [switch] $Uninstall, [switch] $Force ) $ErrorActionPreference = 'Stop' $files = @('gray_iso_layers.inx', 'gray_iso_layers.py', 'gray_iso_layers_core.py', 'gray_iso_layers_depth.py', 'depth_estimate.py', 'images\parameters_en.png', 'images\depth_en.png') $localeDir = 'locale' $source = $PSScriptRoot $destination = Join-Path $ExtensionsDir $FolderName # Cartes de profondeur : environnement Python, modèles et cache, hors du # dossier des extensions (Inkscape le parcourt en entier au démarrage). # Mêmes noms que dans gray_iso_layers_depth.py. $dataDir = Join-Path $env:LOCALAPPDATA 'GrayIsoLayers' $packages = @('onnxruntime-directml', 'numpy', 'pillow') $models = [ordered]@{ 'midas_v21_small_256.onnx' = 'https://github.com/isl-org/MiDaS/releases/download/v2_1/model-small.onnx' 'depth_anything_v2_small.onnx' = 'https://huggingface.co/onnx-community/depth-anything-v2-small/resolve/main/onnx/model.onnx' } # --- Inkscape doit être fermé : les extensions sont lues au démarrage --------- $running = Get-Process -Name 'inkscape' -ErrorAction SilentlyContinue if ($running -and -not $Force) { Write-Error "Inkscape est ouvert. Fermez-le puis relancez le script (ou utilisez -Force)." exit 1 } # --- Désinstallation --------------------------------------------------------- if ($Uninstall) { if (Test-Path -LiteralPath $destination) { Remove-Item -LiteralPath $destination -Recurse -Force Write-Host "Supprimé : $destination" -ForegroundColor Green } else { Write-Host "Rien à supprimer : $destination n'existe pas." -ForegroundColor Yellow } if (Test-Path -LiteralPath $dataDir) { Remove-Item -LiteralPath $dataDir -Recurse -Force Write-Host "Supprimé : $dataDir" -ForegroundColor Green } exit 0 } # --- Vérification des sources ------------------------------------------------ $missing = $files | Where-Object { -not (Test-Path -LiteralPath (Join-Path $source $_)) } if (-not (Test-Path -LiteralPath (Join-Path $source $localeDir))) { $missing = @($missing) + "$localeDir\ (lancer : python i18n.py)" } if ($missing) { Write-Error "Fichier(s) introuvable(s) dans $source : $($missing -join ', ')" exit 1 } # --- Copie ------------------------------------------------------------------- if (-not (Test-Path -LiteralPath $destination)) { New-Item -ItemType Directory -Path $destination -Force | Out-Null Write-Host "Dossier créé : $destination" } foreach ($file in $files) { $from = Join-Path $source $file $to = Join-Path $destination $file $action = if (Test-Path -LiteralPath $to) { 'remplacé' } else { 'copié ' } New-Item -ItemType Directory -Path (Split-Path $to) -Force | Out-Null Copy-Item -LiteralPath $from -Destination $to -Force Write-Host " $action $file" } # Traductions : le dossier est remplacé en entier (langue retirée => supprimée) $localeTo = Join-Path $destination $localeDir if (Test-Path -LiteralPath $localeTo) { Remove-Item -LiteralPath $localeTo -Recurse -Force } Copy-Item -LiteralPath (Join-Path $source $localeDir) -Destination $localeTo -Recurse $languages = Get-ChildItem -LiteralPath $localeTo -Directory | ForEach-Object Name Write-Host " copié $localeDir\ ($($languages -join ', '))" # Le cache Python d'une version précédente peut masquer les fichiers copiés $pycache = Join-Path $destination '__pycache__' if (Test-Path -LiteralPath $pycache) { Remove-Item -LiteralPath $pycache -Recurse -Force } # --- Cartes de profondeur ---------------------------------------------------- if ($Depth) { Write-Host "" Write-Host "Cartes de profondeur : $dataDir" $venvPython = Join-Path $dataDir 'venv\Scripts\python.exe' if (-not (Test-Path -LiteralPath $venvPython)) { # « python » avant le lanceur « py » : ce dernier prend la version la # plus récente, parfois une préversion pour laquelle onnxruntime # n'est pas encore publié. $command = @() if ($Python) { $command = @($Python) } elseif (Get-Command python -ErrorAction SilentlyContinue) { $command = @((Get-Command python).Source) } elseif (Get-Command py -ErrorAction SilentlyContinue) { $command = @((Get-Command py).Source, '-3') } if ($command.Count -eq 0) { Write-Error "Aucun Python 3 trouvé (python ou py) : installez-le depuis python.org, ou indiquez-le avec -Python." exit 1 } $arguments = @($command | Select-Object -Skip 1) + @('-m', 'venv', (Join-Path $dataDir 'venv')) & $command[0] $arguments if ($LASTEXITCODE -ne 0 -or -not (Test-Path -LiteralPath $venvPython)) { Write-Error "Création de l'environnement Python impossible avec $($command -join ' ')." exit 1 } Write-Host " créé venv\" } & $venvPython -m pip install --quiet --disable-pip-version-check --upgrade @packages if ($LASTEXITCODE -ne 0) { Write-Error "Installation de $($packages -join ', ') impossible." exit 1 } Write-Host " installé $($packages -join ', ')" $modelsDir = Join-Path $dataDir 'models' New-Item -ItemType Directory -Path $modelsDir -Force | Out-Null foreach ($name in $models.Keys) { $to = Join-Path $modelsDir $name if (Test-Path -LiteralPath $to) { Write-Host " présent models\$name" continue } # Téléchargement dans un fichier provisoire : un modèle tronqué par une # coupure ne passe pas pour un modèle installé. $partial = "$to.part" $previous = $ProgressPreference $ProgressPreference = 'SilentlyContinue' # la barre ralentit beaucoup PowerShell 5.1 try { Invoke-WebRequest -Uri $models[$name] -OutFile $partial -UseBasicParsing } finally { $ProgressPreference = $previous } Move-Item -LiteralPath $partial -Destination $to -Force $size = [math]::Round((Get-Item -LiteralPath $to).Length / 1MB) Write-Host " téléchargé models\$name ($size Mo)" } } Write-Host "" Write-Host "Extension déployée dans $destination" -ForegroundColor Green Write-Host "Redémarrez Inkscape, puis : Extensions > AlexDesign > Iso-couches par nuances de gris..."