Treppen 2D-Plansymbol + Pure-Transform fuer hidden Layer
Frontend: - 2D-Plansymbol pro Treppe (Tritte/Lauflinie/Aussenlinie/Bruchsymbol) mit per-Treppe-Toggles in Properties-Panel - 'Obere Stufen gestrichelt'-Toggle splittet Tritte/Aussenlinie an Schnittebene; Lauflinie hat zwei Pfeile bei Bruch - Wand-Polyline-Grips fuer alle Vertices (nicht nur Enden) - PopupMenu unterstuetzt Divider + Checkbox-Items Backend: - Eigener Layer 41_Treppen_2D fuer Plansymbol, Layer-Default schwarz - Aussenlinie-Polygone folgen der Bruch-Diagonale (kein Versatz mehr) - Linetype-Fallback laedt Dashed bei Bedarf nach - Tritten-immer-an (Toggle entfernt), Z auf Geschoss-OKFF - TREPPEN/RAEUME Layer-Migration auf Capital-Case (Treppen/Raeume) - Selection-Partnership: treppe_2d_symbol pairs in axis + volume Pure-Transform fuer Treppen-Move: - treppe_2d_symbol + treppe_volume in VOLUME_TYPES → cascade-Support - Phase 1.5 Volume-only-Detection: wenn Source unbewegt aber Volumes uniform translated → synthetisiere canonical aus Avg-Delta der bewegten Volumes (unbewegte rausgefiltert sonst Verzerrung) - Hidden-inclusive ObjectEnumerator in Snapshot + Apply-Loop damit hidden treppe_axis auf 40_Treppen mit-transformiert wird - Properties-Fallback im _send_state findet hidden Sources via expliziter Iteration → Panel zeigt Treppe auch bei 3D-Layer aus - Dimensionen-Panel skipt on_select/idle waehrend UT_ACTIVE oder Partnership-Cascade → keine Flicker beim Drag mehr
This commit is contained in:
+57
-5
@@ -6,7 +6,7 @@ import { BarToggle, BarButton, BarCombo } from './components/BarControls'
|
||||
import {
|
||||
onMessage, notifyReady,
|
||||
createWall, createDecke, createDach,
|
||||
createFenster, createTuer, createAussparung, createTreppe,
|
||||
createFenster, createTuer, createAussparung, createTreppe, setTreppe2DShow,
|
||||
createStuetze, createTraeger, createRaum, createStempel,
|
||||
openSwisstopo, openSwisstopoDialog, openOsmDialog,
|
||||
updateElement, deleteElement, openElementeUebersicht, openElementeProperties,
|
||||
@@ -136,9 +136,15 @@ function PopupMenu({ items, onClose }) {
|
||||
zIndex: 100,
|
||||
minWidth: 140,
|
||||
}}>
|
||||
{items.map((it, i) => (
|
||||
{items.map((it, i) => it._divider ? (
|
||||
<div key={i} style={{
|
||||
height: 1, margin: '4px 2px',
|
||||
background: 'var(--border)', opacity: 0.6,
|
||||
}} />
|
||||
) : (
|
||||
<button key={i}
|
||||
onClick={(e) => { e.stopPropagation(); it.onClick(); onClose() }}
|
||||
onClick={(e) => { e.stopPropagation(); it.onClick();
|
||||
if (!it.keepOpen) onClose() }}
|
||||
disabled={it.disabled}
|
||||
title={it.hint || ''}
|
||||
style={{
|
||||
@@ -157,7 +163,10 @@ function PopupMenu({ items, onClose }) {
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.background = 'transparent'
|
||||
}}>
|
||||
{it.icon && <Icon name={it.icon} size={12}
|
||||
{it.checked !== undefined ? (
|
||||
<Icon name={it.checked ? 'check_box' : 'check_box_outline_blank'}
|
||||
size={12} style={{ color: 'var(--accent)' }} />
|
||||
) : it.icon && <Icon name={it.icon} size={12}
|
||||
style={{ color: 'var(--accent)' }} />}
|
||||
<span style={{ flex: 1 }}>{it.label}</span>
|
||||
{it.badge && (
|
||||
@@ -331,7 +340,7 @@ function ElementListRow({ el, meta }) {
|
||||
}
|
||||
|
||||
|
||||
function NeuesElementSection({ noGeschoss, activeName, elementsCount }) {
|
||||
function NeuesElementSection({ noGeschoss, activeName, elementsCount, treppe2DShow }) {
|
||||
const [treppeMenuOpen, setTreppeMenuOpen] = useState(false)
|
||||
const [stuetzeMenuOpen, setStuetzeMenuOpen] = useState(false)
|
||||
const [traegerMenuOpen, setTraegerMenuOpen] = useState(false)
|
||||
@@ -348,6 +357,7 @@ function NeuesElementSection({ noGeschoss, activeName, elementsCount }) {
|
||||
const openStuetzeMenu = (e) => { e.preventDefault(); setStuetzeMenuOpen(true) }
|
||||
const openTraegerMenu = (e) => { e.preventDefault(); setTraegerMenuOpen(true) }
|
||||
|
||||
const treppe2DOn = treppe2DShow !== false
|
||||
const treppeItems = [
|
||||
{ icon: 'stairs', label: 'Gerade Treppe',
|
||||
hint: 'Lauflinie mit 2 Punkten',
|
||||
@@ -358,6 +368,10 @@ function NeuesElementSection({ noGeschoss, activeName, elementsCount }) {
|
||||
{ icon: 'rotate_right', label: 'Wendeltreppe',
|
||||
hint: '3 Punkte: Mittelpunkt, Start-Lauflinie, End-Lauflinie',
|
||||
onClick: () => createTreppe({ treppeArt: 'wendel' }) },
|
||||
{ _divider: true },
|
||||
{ checked: treppe2DOn, label: '2D-Plansymbol',
|
||||
hint: 'Trittlinien + Auf-Pfeil auf Schnittebene zeichnen',
|
||||
onClick: () => setTreppe2DShow(!treppe2DOn) },
|
||||
]
|
||||
|
||||
const profilItems = (factory) => [
|
||||
@@ -604,6 +618,7 @@ export default function ElementeApp() {
|
||||
noGeschoss={noGeschoss}
|
||||
activeName={activeName}
|
||||
elementsCount={elements.length}
|
||||
treppe2DShow={state.treppe2DShow}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2197,6 +2212,43 @@ function TreppeProperties({ treppe, geschosse, onUpdate, onDelete }) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 2D-Plansymbol Bestandteile */}
|
||||
<div style={{ height: 1, background: 'var(--border-light)', margin: '2px 0' }} />
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
|
||||
<span style={{ fontSize: 9, color: 'var(--text-muted)',
|
||||
letterSpacing: '0.06em', textTransform: 'uppercase' }}>
|
||||
2D-Plansymbol
|
||||
</span>
|
||||
{[
|
||||
['showLauflinie', 'Lauflinie'],
|
||||
['showAussen', 'Außenlinie'],
|
||||
['showBruch', 'Bruchsymbol'],
|
||||
].map(([key, label]) => {
|
||||
const on = treppe[key] !== false
|
||||
return (
|
||||
<label key={key} style={{
|
||||
display: 'flex', alignItems: 'center', gap: 6,
|
||||
fontSize: 11, cursor: 'pointer',
|
||||
}}>
|
||||
<input type="checkbox" checked={on}
|
||||
onChange={(e) => onUpdate({ [key]: e.target.checked })}
|
||||
style={{ accentColor: 'var(--accent)' }} />
|
||||
<span>{label}</span>
|
||||
</label>
|
||||
)
|
||||
})}
|
||||
<label style={{
|
||||
display: 'flex', alignItems: 'center', gap: 6,
|
||||
fontSize: 10, cursor: 'pointer',
|
||||
marginLeft: 18, color: 'var(--text-secondary)',
|
||||
}} title="Tritte und Außenlinie oberhalb der Schnittebene gestrichelt anzeigen">
|
||||
<input type="checkbox" checked={treppe.obereDashed !== false}
|
||||
onChange={(e) => onUpdate({ obereDashed: e.target.checked })}
|
||||
style={{ accentColor: 'var(--accent)' }} />
|
||||
<span>Obere Stufen gestrichelt</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{/* Schrittmass-Tabelle: H (editierbar), S, A, 2S+A mit on/off + range */}
|
||||
<div style={{
|
||||
display: 'flex', flexDirection: 'column', gap: 3,
|
||||
|
||||
@@ -389,6 +389,7 @@ export function createFenster(p) { send('CREATE_FENSTER', p || {}) }
|
||||
export function createTuer(p) { send('CREATE_TUER', p || {}) }
|
||||
export function createAussparung(p) { send('CREATE_AUSSPARUNG', p || {}) }
|
||||
export function createTreppe(p) { send('CREATE_TREPPE', p || {}) }
|
||||
export function setTreppe2DShow(on) { send('SET_TREPPE_2D_SHOW', { on: !!on }) }
|
||||
export function createStuetze(p) { send('CREATE_STUETZE', p || {}) }
|
||||
export function createTraeger(p) { send('CREATE_TRAEGER', p || {}) }
|
||||
export function createRaum(p) { send('CREATE_RAUM', p || {}) }
|
||||
|
||||
Reference in New Issue
Block a user