feat(simulation): add worker-gated 3d polygon workspace

This commit is contained in:
DCCONSTRUCTIONS
2026-07-24 21:03:41 +03:00
parent 1995dfdf68
commit 6cc40282e0
10 changed files with 731 additions and 139 deletions
@@ -166,8 +166,13 @@
flex-direction: column;
}
.polygon-live-map {
min-height: 15rem;
.polygon-rover-scene {
min-height: 19rem;
}
.polygon-rover-scene__frames small,
.polygon-rover-scene__help {
display: none;
}
.polygon-run-event-list article {
+125 -49
View File
@@ -138,84 +138,160 @@
gap: 0.75rem;
}
.polygon-live-map {
.polygon-rover-scene {
position: relative;
overflow: hidden;
min-height: 19rem;
min-height: 25rem;
border: 1px solid var(--station-hairline);
border-radius: 1rem;
background:
radial-gradient(circle at 48% 46%, rgb(var(--nodedc-accent-rgb) / 0.055), transparent 45%),
rgb(255 255 255 / 0.018);
radial-gradient(circle at 62% 28%, rgb(var(--nodedc-accent-rgb) / 0.13), transparent 42%),
linear-gradient(155deg, #0d1722, #070c12 70%);
}
.polygon-live-map svg {
.polygon-rover-scene--loading {
display: grid;
place-items: center;
color: var(--nodedc-text-muted);
font-size: 0.62rem;
}
.polygon-rover-scene__viewport,
.polygon-rover-scene__viewport canvas {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.polygon-live-map pattern path {
fill: none;
stroke: rgb(255 255 255 / 0.045);
stroke-width: 0.25;
.polygon-rover-scene__viewport canvas {
cursor: grab;
touch-action: none;
}
.polygon-live-map text {
fill: var(--nodedc-text-muted);
font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
font-size: 3px;
.polygon-rover-scene__viewport canvas:active {
cursor: grabbing;
}
.polygon-live-axis-x,
.polygon-live-axis-y {
stroke: rgb(255 255 255 / 0.28);
stroke-width: 0.45;
}
.polygon-live-trajectory {
fill: none;
stroke: rgb(var(--nodedc-accent-rgb) / 0.58);
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 0.65;
}
.polygon-live-rover {
fill: rgb(var(--nodedc-accent-rgb));
stroke: rgb(var(--nodedc-on-accent-rgb));
stroke-width: 0.35;
}
.polygon-live-map > div {
.polygon-rover-scene__toolbar,
.polygon-rover-scene__help,
.polygon-rover-scene__frames,
.polygon-rover-scene__idle {
position: absolute;
top: 50%;
left: 50%;
display: grid;
width: min(22rem, 76%);
gap: 0.35rem;
text-align: center;
transform: translate(-50%, -50%);
z-index: 2;
}
.polygon-live-map > div strong {
.polygon-rover-scene__toolbar {
top: 0.75rem;
left: 0.75rem;
display: flex;
gap: 0.4rem;
}
.polygon-rover-scene__toolbar button {
border: 1px solid rgb(255 255 255 / 0.14);
border-radius: 999px;
background: rgb(7 12 18 / 0.76);
color: var(--nodedc-text-secondary);
padding: 0.38rem 0.62rem;
font: inherit;
font-size: 0.54rem;
line-height: 1;
backdrop-filter: blur(16px);
cursor: pointer;
}
.polygon-rover-scene__toolbar button:hover {
border-color: rgb(var(--nodedc-accent-rgb) / 0.5);
color: var(--nodedc-text-primary);
font-size: 0.78rem;
}
.polygon-live-map > div span,
.polygon-live-map > small {
.polygon-rover-scene__help {
bottom: 0.75rem;
left: 0.75rem;
display: flex;
flex-wrap: wrap;
gap: 0.6rem;
}
.polygon-rover-scene__help span,
.polygon-rover-scene__frames,
.polygon-rover-scene__frames small {
color: var(--nodedc-text-muted);
font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
font-size: 0.58rem;
line-height: 1.45;
}
.polygon-live-map > small {
position: absolute;
right: 0.8rem;
.polygon-rover-scene__frames {
right: 0.75rem;
bottom: 0.7rem;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
display: flex;
align-items: center;
gap: 0.45rem;
}
.polygon-rover-scene__frames span {
display: inline-flex;
align-items: center;
gap: 0.2rem;
}
.polygon-rover-scene__frames i {
width: 0.36rem;
height: 0.36rem;
border-radius: 50%;
background: #fff;
}
.polygon-rover-scene__frames i[data-axis="east"] {
background: #ff5f6d;
}
.polygon-rover-scene__frames i[data-axis="north"] {
background: #4ee19b;
}
.polygon-rover-scene__frames i[data-axis="up"] {
background: #5d9cff;
}
.polygon-rover-scene__frames small {
margin-left: 0.2rem;
}
.polygon-rover-scene__idle {
top: 4.1rem;
right: 0.8rem;
display: grid;
max-width: min(18rem, 52%);
gap: 0.2rem;
border: 1px solid rgb(255 255 255 / 0.09);
border-radius: 0.72rem;
background: rgb(7 12 18 / 0.58);
padding: 0.55rem 0.7rem;
text-align: right;
backdrop-filter: blur(14px);
pointer-events: none;
}
.polygon-rover-scene__idle strong {
color: var(--nodedc-text-primary);
font-size: 0.68rem;
}
.polygon-rover-scene__idle span,
.polygon-rover-scene__error {
color: var(--nodedc-text-muted);
font-size: 0.56rem;
line-height: 1.45;
}
.polygon-rover-scene__error {
position: absolute;
inset: 50% auto auto 50%;
margin: 0;
transform: translate(-50%, -50%);
}
.polygon-live-telemetry {