168 lines
6.7 KiB
PowerShell
168 lines
6.7 KiB
PowerShell
param(
|
|
[string]$InputRoot = "src/main/resources/assets/combatant/svg",
|
|
[string]$OutRoot = "build/generated/resources/svgMsdf/assets/combatant/svg/msdf",
|
|
[int]$Dimension = 64,
|
|
[int]$PxRange = 4,
|
|
[string]$Type = "mtsdf",
|
|
[string]$PreprocessorClasspath = "build/classes/java/main",
|
|
[string]$JavaExe = "java",
|
|
[switch]$Strict
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$repoRoot = (Resolve-Path "${PSScriptRoot}\..\..").Path
|
|
|
|
function Resolve-RepoPath {
|
|
param([string]$Path)
|
|
|
|
if ([System.IO.Path]::IsPathRooted($Path)) {
|
|
return [System.IO.Path]::GetFullPath($Path)
|
|
}
|
|
return [System.IO.Path]::GetFullPath((Join-Path $repoRoot $Path))
|
|
}
|
|
|
|
$inputRootPath = Resolve-RepoPath $InputRoot
|
|
$outRootPath = Resolve-RepoPath $OutRoot
|
|
$toolDir = Join-Path $repoRoot "tools/msdf"
|
|
$msdfgenPath = Join-Path $toolDir "msdfgen.exe"
|
|
$workRoot = Join-Path $repoRoot "build/tmp/svg-msdf"
|
|
|
|
function Get-Msdfgen {
|
|
if (Test-Path $msdfgenPath) { return $msdfgenPath }
|
|
|
|
$api = "https://api.github.com/repos/Chlumsky/msdfgen/releases/latest"
|
|
$release = Invoke-RestMethod -Uri $api -Headers @{ "User-Agent" = "CombatantSvgMsdfGen" }
|
|
$asset = $release.assets |
|
|
Where-Object { $_.name -match "win64" -and $_.name -match "\.zip$" -and $_.name -notmatch "openmp" } |
|
|
Select-Object -First 1
|
|
if (-not $asset) {
|
|
$asset = $release.assets |
|
|
Where-Object { $_.name -match "win" -and $_.name -match "\.zip$" -and $_.name -notmatch "openmp" } |
|
|
Select-Object -First 1
|
|
}
|
|
if (-not $asset) { throw "No Windows msdfgen zip found in latest release." }
|
|
|
|
New-Item -ItemType Directory -Force -Path $toolDir | Out-Null
|
|
$archivePath = Join-Path $toolDir $asset.name
|
|
Invoke-WebRequest -Uri $asset.browser_download_url -OutFile $archivePath -Headers @{ "User-Agent" = "CombatantSvgMsdfGen" }
|
|
|
|
$extractDir = Join-Path $toolDir ([System.IO.Path]::GetFileNameWithoutExtension($asset.name))
|
|
Expand-Archive -Path $archivePath -DestinationPath $extractDir -Force
|
|
$found = Get-ChildItem -Path $extractDir -Filter "msdfgen.exe" -Recurse | Select-Object -First 1
|
|
if (-not $found) { throw "msdfgen.exe not found after extraction." }
|
|
|
|
Copy-Item $found.FullName -Destination $msdfgenPath -Force
|
|
return $msdfgenPath
|
|
}
|
|
|
|
function Read-ViewBox {
|
|
param([string]$Path)
|
|
|
|
[xml]$xml = Get-Content -LiteralPath $Path -Raw
|
|
$root = $xml.DocumentElement
|
|
$viewBox = $root.GetAttribute("viewBox")
|
|
if ($viewBox) {
|
|
$parts = [regex]::Split($viewBox.Trim(), "[,\s]+") | Where-Object { $_ -ne "" }
|
|
if ($parts.Count -eq 4) {
|
|
return @{
|
|
X = [double]::Parse($parts[0], [Globalization.CultureInfo]::InvariantCulture)
|
|
Y = [double]::Parse($parts[1], [Globalization.CultureInfo]::InvariantCulture)
|
|
W = [double]::Parse($parts[2], [Globalization.CultureInfo]::InvariantCulture)
|
|
H = [double]::Parse($parts[3], [Globalization.CultureInfo]::InvariantCulture)
|
|
}
|
|
}
|
|
}
|
|
|
|
$w = $root.GetAttribute("width") -replace "[^0-9.+-]", ""
|
|
$h = $root.GetAttribute("height") -replace "[^0-9.+-]", ""
|
|
$width = if ($w) { [double]::Parse($w, [Globalization.CultureInfo]::InvariantCulture) } else { 24.0 }
|
|
$height = if ($h) { [double]::Parse($h, [Globalization.CultureInfo]::InvariantCulture) } else { 24.0 }
|
|
return @{ X = 0.0; Y = 0.0; W = $width; H = $height }
|
|
}
|
|
|
|
function Write-Metadata {
|
|
param(
|
|
[string]$Path,
|
|
[string]$SourceRelative,
|
|
[string]$TextureRelative,
|
|
[hashtable]$ViewBox
|
|
)
|
|
|
|
$metadata = [ordered]@{
|
|
type = $Type
|
|
width = $Dimension
|
|
height = $Dimension
|
|
pxRange = $PxRange
|
|
yOrigin = "top"
|
|
source = "combatant:svg/$SourceRelative"
|
|
texture = "combatant:svg/msdf/$TextureRelative"
|
|
viewBox = @($ViewBox.X, $ViewBox.Y, $ViewBox.W, $ViewBox.H)
|
|
}
|
|
$json = $metadata | ConvertTo-Json -Depth 4
|
|
[System.IO.File]::WriteAllText($Path, $json + [Environment]::NewLine, [System.Text.UTF8Encoding]::new($false))
|
|
}
|
|
|
|
if (-not (Test-Path $inputRootPath)) {
|
|
Write-Host "SVG input root not found: $inputRootPath" -ForegroundColor Yellow
|
|
exit 0
|
|
}
|
|
|
|
try {
|
|
$msdfgen = Get-Msdfgen
|
|
} catch {
|
|
if ($Strict) { throw }
|
|
Write-Host "msdfgen unavailable; skipping SVG MSDF generation: $($_.Exception.Message)" -ForegroundColor Yellow
|
|
exit 0
|
|
}
|
|
|
|
if (Test-Path $outRootPath) {
|
|
Remove-Item -LiteralPath $outRootPath -Recurse -Force
|
|
}
|
|
New-Item -ItemType Directory -Force -Path $outRootPath | Out-Null
|
|
New-Item -ItemType Directory -Force -Path $workRoot | Out-Null
|
|
|
|
$svgs = Get-ChildItem -Path $inputRootPath -Filter "*.svg" -Recurse
|
|
$inputRootFull = [System.IO.Path]::GetFullPath($inputRootPath).TrimEnd('\', '/') + [System.IO.Path]::DirectorySeparatorChar
|
|
$generated = 0
|
|
$skipped = 0
|
|
|
|
foreach ($svg in $svgs) {
|
|
$fileFull = [System.IO.Path]::GetFullPath($svg.FullName)
|
|
$relative = $fileFull.Substring($inputRootFull.Length).Replace('\', '/')
|
|
if ($relative.StartsWith("msdf/")) { continue }
|
|
|
|
$relativeNoExt = $relative.Substring(0, $relative.Length - 4)
|
|
$outPng = Join-Path $outRootPath ($relativeNoExt + ".png")
|
|
$outJson = Join-Path $outRootPath ($relativeNoExt + ".json")
|
|
$outlineSvg = Join-Path $workRoot ($relativeNoExt.Replace("/", "_") + ".outline.svg")
|
|
|
|
New-Item -ItemType Directory -Force -Path ([System.IO.Path]::GetDirectoryName($outPng)) | Out-Null
|
|
New-Item -ItemType Directory -Force -Path ([System.IO.Path]::GetDirectoryName($outlineSvg)) | Out-Null
|
|
|
|
try {
|
|
$viewBox = Read-ViewBox $svg.FullName
|
|
if ($viewBox.W -le 0 -or $viewBox.H -le 0) { throw "invalid viewBox" }
|
|
|
|
$preprocessOutput = & $JavaExe -cp $PreprocessorClasspath combatant.client.render.engine.svg.SvgMsdfPreprocessor $svg.FullName $outlineSvg 2>&1
|
|
if ($LASTEXITCODE -ne 0) { throw "svg preprocessor failed: $preprocessOutput" }
|
|
if (-not (Test-Path $outlineSvg)) { throw "outline svg was not produced" }
|
|
|
|
$scale = [Math]::Min($Dimension / $viewBox.W, $Dimension / $viewBox.H)
|
|
$translateX = -$viewBox.X
|
|
$translateY = -$viewBox.Y
|
|
|
|
$msdfgenOutput = & $msdfgen $Type -svg $outlineSvg -o $outPng -dimensions $Dimension $Dimension -pxrange $PxRange -scale $scale -translate $translateX $translateY 2>&1
|
|
if ($LASTEXITCODE -ne 0 -or -not (Test-Path $outPng)) { throw "msdfgen failed: $msdfgenOutput" }
|
|
|
|
Write-Metadata $outJson $relative ($relativeNoExt + ".png") $viewBox
|
|
$generated++
|
|
} catch {
|
|
$skipped++
|
|
$message = "Skipped ${relative}: $($_.Exception.Message)"
|
|
if ($Strict) { throw $message }
|
|
Write-Host $message -ForegroundColor Yellow
|
|
}
|
|
}
|
|
|
|
Write-Host "Generated $generated SVG MSDF assets, skipped $skipped." -ForegroundColor Green
|