Random-Schraffur modellraum-verankert + Motiv-Editor fuer Custom-Linien

Random-Verankerung (Bugfix): die Streu-Striche haengen nicht mehr an der
Polygon-Bounding-Box, sondern an einem absoluten Modellraum-Gitter
(hashCell aus absoluten Zell-Indizes + hatch.seed). Beim Vergroessern der
Flaeche bleiben bestehende Striche stehen, am Rand kommen neue dazu, die
Dichte bleibt konstant, Verschieben wandert nicht; 'Neu wuerfeln' (neuer
Seed) verschiebt das ganze Feld. Alle Renderpfade ziehen aus derselben
Funktion. Verankerungs- und Verschiebe-Dichte-Test ergaenzt.

Motiv-Editor: neuer wiederverwendbarer MotifEditor (Punkte setzen/ziehen in
einer Einheitszelle, Live-Loop-Vorschau). LineStyle.kind 'custom' + motif
(points/length), additiv durchgereicht (analog zigzag) und in allen
Renderpfaden gekachelt (motifPoints, Verallgemeinerung von zigzagPoints).
ResourceManager-Umschalter Vollinie/Strich/Zickzack/Motiv, LineSwatch-
Vorschau. Insgesamt 5 neue Tests, 113 gruen.
This commit is contained in:
2026-07-04 01:09:00 +02:00
parent b4dd396768
commit 3d1fa40402
15 changed files with 714 additions and 58 deletions
+82
View File
@@ -2253,6 +2253,88 @@ body {
padding: 0 8px;
}
/* ── Motiv-Editor (Custom-Linie / Kachel-Motiv) ─────────────────────────── */
.motif-editor {
display: flex;
flex-direction: column;
gap: 8px;
width: 100%;
}
.motif-canvas {
width: 100%;
height: auto;
background: var(--input);
border: 1px solid var(--border);
border-radius: 6px;
touch-action: none;
cursor: crosshair;
}
.motif-frame {
fill: none;
stroke: var(--border);
stroke-width: 1;
}
.motif-grid {
stroke: var(--border);
stroke-width: 0.5;
opacity: 0.5;
}
.motif-axis {
stroke: var(--ink-2);
stroke-width: 0.75;
stroke-dasharray: 3 3;
opacity: 0.7;
}
.motif-path {
stroke: var(--accent-light);
stroke-width: 1.75;
stroke-linejoin: round;
stroke-linecap: round;
}
.motif-handle {
fill: var(--input);
stroke: var(--accent-light);
stroke-width: 1.5;
cursor: grab;
}
.motif-handle:hover {
fill: var(--accent-light);
}
.motif-handle.is-drag {
fill: var(--accent-light);
cursor: grabbing;
}
.motif-controls {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.motif-len {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: var(--ink-2);
}
.motif-len input {
width: 62px;
}
.motif-hint {
font-size: 11px;
color: var(--ink-2);
opacity: 0.85;
flex: 1 1 120px;
line-height: 1.3;
}
.motif-preview {
width: 100%;
height: auto;
background: var(--input);
border: 1px solid var(--border);
border-radius: 6px;
}
/* Löschen-Knopf (Mülleimer in der letzten Spalte, zentriert). */
.res-delete {
flex: 0 0 auto;