2 Commits
Author SHA1 Message Date
fototeddyandClaude Sonnet 5 b23e96615e App1/App2-Icons als primäres und Alternate-Icon einbinden
Vier neue AppIcon-Asset-Kataloge angelegt (App1/App2, jeweils Standard-
und TestFlight-Variante), aus den bereitgestellten 1024×1024-Vorlagen
(bereits randlos, ohne Alphakanal – nur noch skaliert).

Verdrahtet für den aktuellen TestFlight-Build:
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-App1-Testflight (primär)
- ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = AppIcon-App2-Testflight
- ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES, damit auch die
  noch unverdrahteten App1/App2-Sets (für den finalen Store-Build) mit
  ins Bundle kommen, statt vom Compiler als ungenutzt verworfen zu werden

Fürs finale Release genügt es, ASSETCATALOG_COMPILER_APPICON_NAME auf
AppIcon-App1 und die Alternate-Liste auf AppIcon-App2 umzustellen – die
TestFlight-Varianten sollen Betatester optisch von der echten Version
unterscheiden.

Nur das Haupt-App-Target ist betroffen; Watch- und Complication-Icon
bleiben unverändert. Build (App + Watch) und Tests grün.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-08 17:14:22 +02:00
fototeddyandClaude Sonnet 5 0b3bf5e815 Neue California-Fahrzeuggrafik einbauen, eigene Heckansicht ergänzt
Seiten- und Heckansicht kamen als weiß gefüllte Vorlage ohne Alphakanal
(Tools/California Side.png, Tools/California Back.png). Dafür ein neues
Werkzeug ergänzt, das den weißen Grund in echte Transparenz übersetzt
(mit weichem statt hartem Schwellwert, um Kanten nicht auszufransen),
danach wie gewohnt durch make-vehicle-art.swift geschickt.

California hatte bisher keine eigene Heckansicht und griff ersatzweise
auf die von Vanster zurück – jetzt eigenes CaliforniaRear-Imageset,
VehicleGraphicStyle.rearImageName entsprechend angepasst. Seiten- und
Heckbild sind quadratisch (1254×1254), passend zu den bestehenden
Seitenverhältnissen (sideAspect/rearAspect = 1) – keine Anpassung dort
nötig.

Build und Tests grün.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 21:31:42 +02:00
15 changed files with 143 additions and 7 deletions
+2 -3
View File
@@ -26,11 +26,10 @@ enum VehicleGraphicStyle: String, CaseIterable, Identifiable, Codable, Sendable
}
}
/// Für California liegt noch keine eigene Heckansicht vor, deshalb
/// vorerst die von Vanster.
var rearImageName: String {
switch self {
case .vanster, .california: return "VansterRear"
case .vanster: return "VansterRear"
case .california: return "CaliforniaRear"
}
}
+19 -2
View File
@@ -38,5 +38,22 @@ sips --resampleHeight 600 heckansicht.png --out /tmp/rear.png
Jedes Fahrzeug-Grafikset (siehe `VehicleGraphicStyle`) hat sein eigenes
Bildpaar `<Name>Side`/`<Name>Rear`. Hat die Vorlage schon einen
transparenten Hintergrund, geht die Quelldatei direkt ins Skript. Liegt sie
auf weißem Grund, muss der Rand vorher weg – sonst wird die ganze Fläche
mitgefärbt.
auf weißem Grund, muss der Rand vorher weg – siehe `remove-white-background.swift`.
## remove-white-background.swift
Vorstufe zu `make-vehicle-art.swift`, wenn die Vorlage auf weißem statt
transparentem Grund liegt (kein Alphakanal). Ohne diesen Schritt hielte
`make-vehicle-art` die ganze Fläche für Zeichnung und färbte den Hintergrund
mit ein.
Reines Weiß wird voll durchsichtig, alles andere bleibt stehen; ein weicher
Übergang statt einer harten Schwelle vermeidet gezackte Kanten an
kantengeglätteten Linien.
```bash
swiftc -O -o /tmp/remove-white-background Tools/remove-white-background.swift
swiftc -O -o /tmp/make-vehicle-art Tools/make-vehicle-art.swift
/tmp/remove-white-background seitenansicht.png /tmp/seite-transparent.png
/tmp/make-vehicle-art /tmp/seite-transparent.png VanControl/Assets.xcassets/CaliforniaSide.imageset/CaliforniaSide.png
```
+62
View File
@@ -0,0 +1,62 @@
import AppKit
import CoreGraphics
import Foundation
// Vorlagen kommen manchmal auf weißem statt transparentem Grund. Ohne
// Alphakanal hielte `make-vehicle-art.swift` die ganze Fläche für Zeichnung
// und färbte den Hintergrund mit ein. Dieses Werkzeug macht daraus einen
// echten Alphakanal: reines Weiß wird voll durchsichtig, alles andere bleibt
// stehen. Ein weicher Übergang statt einer harten Schwelle verhindert
// gezackte Kanten an den (leicht kantengeglätteten) Linien.
let arguments = CommandLine.arguments
guard arguments.count >= 3,
let source = NSImage(contentsOfFile: arguments[1]),
let image = source.cgImage(forProposedRect: nil, context: nil, hints: nil) else {
print("Quelle nicht lesbar"); exit(1)
}
let width = image.width, height = image.height
let bytesPerRow = width * 4
var pixels = [UInt8](repeating: 0, count: bytesPerRow * height)
guard let context = CGContext(data: &pixels, width: width, height: height,
bitsPerComponent: 8, bytesPerRow: bytesPerRow,
space: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else {
print("Puffer nicht anlegbar"); exit(1)
}
context.draw(image, in: CGRect(x: 0, y: 0, width: width, height: height))
/// Unterhalb davon gilt ein Pixel als reiner Hintergrund, oberhalb als
/// sicher Zeichnung. Dazwischen wird linear zwischen 0 und voller Deckkraft
/// überblendet, damit Kanten nicht ausgefranst wirken.
let whiteFloor = 230.0
let whiteCeiling = 250.0
for index in stride(from: 0, to: pixels.count, by: 4) {
// Quelle ist opak (kein Alphakanal), also stehen hier die Rohfarben.
let r = Double(pixels[index])
let g = Double(pixels[index + 1])
let b = Double(pixels[index + 2])
let whiteness = min(r, g, b)
let t = min(1, max(0, (whiteness - whiteFloor) / (whiteCeiling - whiteFloor)))
let alpha = 1 - t
guard alpha > 0.004 else {
pixels[index] = 0; pixels[index + 1] = 0; pixels[index + 2] = 0; pixels[index + 3] = 0
continue
}
// Premultipliziert ablegen.
pixels[index] = UInt8(r * alpha)
pixels[index + 1] = UInt8(g * alpha)
pixels[index + 2] = UInt8(b * alpha)
pixels[index + 3] = UInt8(alpha * 255)
}
guard let result = context.makeImage() else { print("Bild leer"); exit(1) }
let rep = NSBitmapImageRep(cgImage: result)
guard let png = rep.representation(using: .png, properties: [:]) else {
print("PNG nicht erzeugbar"); exit(1)
}
try png.write(to: URL(fileURLWithPath: arguments[2]))
print("\(arguments[2]): fertig")
+6 -2
View File
@@ -496,8 +496,10 @@
AA0000000000000000000014 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "AppIcon-App2-Testflight";
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-App1-Testflight";
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "";
@@ -529,8 +531,10 @@
AA0000000000000000000015 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "AppIcon-App2-Testflight";
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-App1-Testflight";
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "";
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

@@ -0,0 +1,11 @@
{
"images" : [
{
"filename" : "AppIcon-App1-Testflight-1024.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : { "author" : "xcode", "version" : 1 }
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

@@ -0,0 +1,11 @@
{
"images" : [
{
"filename" : "AppIcon-App1-1024.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : { "author" : "xcode", "version" : 1 }
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

@@ -0,0 +1,11 @@
{
"images" : [
{
"filename" : "AppIcon-App2-Testflight-1024.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : { "author" : "xcode", "version" : 1 }
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

@@ -0,0 +1,11 @@
{
"images" : [
{
"filename" : "AppIcon-App2-1024.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : { "author" : "xcode", "version" : 1 }
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

@@ -0,0 +1,10 @@
{
"images" : [
{
"filename" : "CaliforniaRear.png",
"idiom" : "universal"
}
],
"info" : { "author" : "xcode", "version" : 1 },
"properties" : { "template-rendering-intent" : "template" }
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 341 KiB

After

Width:  |  Height:  |  Size: 323 KiB