@wandelbots/wandelbots-js-react-components 2.32.0-pr.feature-robot-precondition-list.372.8ed54a6 → 2.32.0-pr.feature-robot-precondition-list.372.5d8a86e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ProgramControl.d.ts +6 -1
- package/dist/components/ProgramControl.d.ts.map +1 -1
- package/dist/components/ProgramStateIndicator.d.ts +1 -1
- package/dist/components/ProgramStateIndicator.d.ts.map +1 -1
- package/dist/components/RobotCard.d.ts +8 -6
- package/dist/components/RobotCard.d.ts.map +1 -1
- package/dist/components/robots/Robot.d.ts +3 -2
- package/dist/components/robots/Robot.d.ts.map +1 -1
- package/dist/index.cjs +43 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4740 -4713
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ProgramControl.tsx +20 -10
- package/src/components/ProgramStateIndicator.tsx +5 -5
- package/src/components/RobotCard.tsx +240 -179
- package/src/components/robots/Robot.tsx +5 -2
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Box,
|
|
3
|
+
Button,
|
|
4
|
+
Card,
|
|
5
|
+
Divider,
|
|
6
|
+
Typography,
|
|
7
|
+
useMediaQuery,
|
|
8
|
+
useTheme,
|
|
9
|
+
} from "@mui/material"
|
|
2
10
|
import { Bounds, useBounds } from "@react-three/drei"
|
|
3
11
|
import { Canvas } from "@react-three/fiber"
|
|
4
|
-
import type { DHParameter } from "@wandelbots/nova-api/v1"
|
|
5
12
|
import type {
|
|
6
13
|
ConnectedMotionGroup,
|
|
7
14
|
RobotControllerStateOperationModeEnum,
|
|
@@ -16,27 +23,30 @@ import { PresetEnvironment } from "./3d-viewport/PresetEnvironment"
|
|
|
16
23
|
import { CycleTimer } from "./CycleTimer"
|
|
17
24
|
import type { ProgramState } from "./ProgramControl"
|
|
18
25
|
import { ProgramStateIndicator } from "./ProgramStateIndicator"
|
|
19
|
-
import {
|
|
26
|
+
import { Robot } from "./robots/Robot"
|
|
20
27
|
|
|
21
28
|
// Component to refresh bounds when model renders
|
|
22
29
|
function BoundsRefresher({
|
|
23
30
|
modelRenderTrigger,
|
|
24
31
|
children,
|
|
32
|
+
isPortrait = false,
|
|
25
33
|
}: {
|
|
26
|
-
modelRenderTrigger
|
|
34
|
+
modelRenderTrigger: number
|
|
27
35
|
children: React.ReactNode
|
|
36
|
+
isPortrait?: boolean
|
|
28
37
|
}) {
|
|
29
|
-
const
|
|
38
|
+
const bounds = useBounds()
|
|
30
39
|
|
|
31
40
|
useEffect(() => {
|
|
32
|
-
if (modelRenderTrigger
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
41
|
+
if (modelRenderTrigger > 0) {
|
|
42
|
+
// For portrait mode, use more aggressive fitting
|
|
43
|
+
if (isPortrait) {
|
|
44
|
+
bounds.refresh().clip().fit()
|
|
45
|
+
} else {
|
|
46
|
+
bounds.refresh().clip().fit()
|
|
47
|
+
}
|
|
38
48
|
}
|
|
39
|
-
}, [modelRenderTrigger,
|
|
49
|
+
}, [modelRenderTrigger, bounds, isPortrait])
|
|
40
50
|
|
|
41
51
|
return <>{children}</>
|
|
42
52
|
}
|
|
@@ -58,11 +68,9 @@ export interface RobotCardProps {
|
|
|
58
68
|
onDriveToHomeRelease?: () => void
|
|
59
69
|
/** Connected motion group for the robot */
|
|
60
70
|
connectedMotionGroup: ConnectedMotionGroup
|
|
61
|
-
/** Custom robot component to render (optional, defaults to
|
|
71
|
+
/** Custom robot component to render (optional, defaults to Robot) */
|
|
62
72
|
robotComponent?: React.ComponentType<{
|
|
63
|
-
|
|
64
|
-
modelFromController: string
|
|
65
|
-
dhParameters: DHParameter[]
|
|
73
|
+
connectedMotionGroup: ConnectedMotionGroup
|
|
66
74
|
flangeRef?: React.Ref<Group>
|
|
67
75
|
postModelRender?: () => void
|
|
68
76
|
transparentColor?: string
|
|
@@ -95,7 +103,12 @@ export interface RobotCardProps {
|
|
|
95
103
|
* - Automatic layout switching based on aspect ratio:
|
|
96
104
|
* - Portrait mode: Vertical layout with robot in center
|
|
97
105
|
* - Landscape mode: Horizontal layout with robot on left, content on right (left-aligned)
|
|
98
|
-
* -
|
|
106
|
+
* - Responsive 3D robot rendering:
|
|
107
|
+
* - Scales dynamically with container size
|
|
108
|
+
* - Hides at very small sizes to preserve usability
|
|
109
|
+
* - Adaptive margin based on available space
|
|
110
|
+
* - Smart spacing and padding that reduces at smaller sizes
|
|
111
|
+
* - Minimum size constraints for usability while maximizing content density
|
|
99
112
|
* - Robot name displayed in Typography h6 at top-left
|
|
100
113
|
* - Program state indicator below the name
|
|
101
114
|
* - Auto-fitting 3D robot model that scales with container size
|
|
@@ -116,7 +129,7 @@ export const RobotCard = externalizeComponent(
|
|
|
116
129
|
onDriveToHomePress,
|
|
117
130
|
onDriveToHomeRelease,
|
|
118
131
|
connectedMotionGroup,
|
|
119
|
-
robotComponent: RobotComponent =
|
|
132
|
+
robotComponent: RobotComponent = Robot,
|
|
120
133
|
cycleTimerComponent: CycleTimerComponent = CycleTimer,
|
|
121
134
|
className,
|
|
122
135
|
}: RobotCardProps) => {
|
|
@@ -127,22 +140,31 @@ export const RobotCard = externalizeComponent(
|
|
|
127
140
|
const robotRef = useRef<Group>(null)
|
|
128
141
|
const cardRef = useRef<HTMLDivElement>(null)
|
|
129
142
|
const [isLandscape, setIsLandscape] = useState(false)
|
|
143
|
+
const [cardSize, setCardSize] = useState<{
|
|
144
|
+
width: number
|
|
145
|
+
height: number
|
|
146
|
+
}>({ width: 400, height: 600 })
|
|
130
147
|
const [modelRenderTrigger, setModelRenderTrigger] = useState(0)
|
|
131
148
|
|
|
132
|
-
//
|
|
149
|
+
// Responsive breakpoints
|
|
150
|
+
const isExtraSmall = useMediaQuery(theme.breakpoints.down("sm"))
|
|
151
|
+
const isSmall = useMediaQuery(theme.breakpoints.down("md"))
|
|
152
|
+
|
|
153
|
+
// Hook to detect aspect ratio and size changes
|
|
133
154
|
useEffect(() => {
|
|
134
|
-
const
|
|
155
|
+
const checkDimensions = () => {
|
|
135
156
|
if (cardRef.current) {
|
|
136
157
|
const { offsetWidth, offsetHeight } = cardRef.current
|
|
137
158
|
setIsLandscape(offsetWidth > offsetHeight)
|
|
159
|
+
setCardSize({ width: offsetWidth, height: offsetHeight })
|
|
138
160
|
}
|
|
139
161
|
}
|
|
140
162
|
|
|
141
163
|
// Initial check
|
|
142
|
-
|
|
164
|
+
checkDimensions()
|
|
143
165
|
|
|
144
166
|
// Set up ResizeObserver to watch for size changes
|
|
145
|
-
const resizeObserver = new ResizeObserver(
|
|
167
|
+
const resizeObserver = new ResizeObserver(checkDimensions)
|
|
146
168
|
if (cardRef.current) {
|
|
147
169
|
resizeObserver.observe(cardRef.current)
|
|
148
170
|
}
|
|
@@ -193,10 +215,36 @@ export const RobotCard = externalizeComponent(
|
|
|
193
215
|
[],
|
|
194
216
|
)
|
|
195
217
|
|
|
218
|
+
// Determine if robot should be hidden at small sizes to save space
|
|
219
|
+
// Less aggressive hiding for portrait mode since robot is in center
|
|
220
|
+
const shouldHideRobot = isLandscape
|
|
221
|
+
? cardSize.width < 350 || cardSize.height < 250 // Aggressive for landscape
|
|
222
|
+
: cardSize.width < 250 || cardSize.height < 180 // Less aggressive for portrait
|
|
223
|
+
|
|
224
|
+
// Calculate responsive robot scale based on card size and orientation
|
|
225
|
+
const getRobotScale = () => {
|
|
226
|
+
if (shouldHideRobot) return 0
|
|
227
|
+
|
|
228
|
+
if (isLandscape) {
|
|
229
|
+
// More aggressive scaling for landscape since robot is on side
|
|
230
|
+
if (cardSize.width < 450) return 0.8
|
|
231
|
+
if (cardSize.width < 550) return 0.9
|
|
232
|
+
return 1
|
|
233
|
+
} else {
|
|
234
|
+
// Less aggressive scaling for portrait since robot is central
|
|
235
|
+
if (cardSize.width < 300) return 0.8
|
|
236
|
+
if (cardSize.width < 400) return 0.9
|
|
237
|
+
return 1
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const robotScale = getRobotScale()
|
|
242
|
+
|
|
196
243
|
return (
|
|
197
244
|
<Card
|
|
198
245
|
ref={cardRef}
|
|
199
246
|
className={className}
|
|
247
|
+
elevation={5}
|
|
200
248
|
sx={{
|
|
201
249
|
width: "100%",
|
|
202
250
|
height: "100%",
|
|
@@ -204,9 +252,10 @@ export const RobotCard = externalizeComponent(
|
|
|
204
252
|
flexDirection: isLandscape ? "row" : "column",
|
|
205
253
|
position: "relative",
|
|
206
254
|
overflow: "hidden",
|
|
207
|
-
minWidth:
|
|
208
|
-
minHeight: isLandscape
|
|
209
|
-
|
|
255
|
+
minWidth: { xs: 180, sm: 220, md: 250 },
|
|
256
|
+
minHeight: isLandscape
|
|
257
|
+
? { xs: 160, sm: 200, md: 250 }
|
|
258
|
+
: { xs: 200, sm: 280, md: 350 },
|
|
210
259
|
border:
|
|
211
260
|
"1px solid var(--secondary-_states-outlinedBorder, #FFFFFF1F)",
|
|
212
261
|
borderRadius: "18px",
|
|
@@ -224,63 +273,65 @@ export const RobotCard = externalizeComponent(
|
|
|
224
273
|
minHeight: "100%",
|
|
225
274
|
maxHeight: "100%",
|
|
226
275
|
borderRadius: 1,
|
|
227
|
-
m: 2,
|
|
228
|
-
mr: 1,
|
|
276
|
+
m: { xs: 1.5, sm: 2, md: 3 },
|
|
277
|
+
mr: { xs: 0.75, sm: 1, md: 1.5 },
|
|
229
278
|
overflow: "hidden", // Prevent content from affecting container size
|
|
279
|
+
display: shouldHideRobot ? "none" : "block",
|
|
230
280
|
}}
|
|
231
281
|
>
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
<
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
</
|
|
265
|
-
</
|
|
266
|
-
</
|
|
267
|
-
|
|
282
|
+
{!shouldHideRobot && (
|
|
283
|
+
<Canvas
|
|
284
|
+
camera={{
|
|
285
|
+
position: [4, 4, 4], // Move camera further back for orthographic view
|
|
286
|
+
fov: 15, // Low FOV for near-orthographic projection
|
|
287
|
+
}}
|
|
288
|
+
shadows
|
|
289
|
+
frameloop="demand"
|
|
290
|
+
style={{
|
|
291
|
+
borderRadius: theme.shape.borderRadius,
|
|
292
|
+
width: "100%",
|
|
293
|
+
height: "100%",
|
|
294
|
+
background: "transparent",
|
|
295
|
+
position: "absolute",
|
|
296
|
+
top: 0,
|
|
297
|
+
left: 0,
|
|
298
|
+
}}
|
|
299
|
+
dpr={[1, 2]}
|
|
300
|
+
gl={{ alpha: true, antialias: true }}
|
|
301
|
+
>
|
|
302
|
+
<PresetEnvironment />
|
|
303
|
+
<Bounds fit clip observe margin={1}>
|
|
304
|
+
<BoundsRefresher
|
|
305
|
+
modelRenderTrigger={modelRenderTrigger}
|
|
306
|
+
isPortrait={false}
|
|
307
|
+
>
|
|
308
|
+
<group ref={robotRef} scale={robotScale}>
|
|
309
|
+
<RobotComponent
|
|
310
|
+
connectedMotionGroup={connectedMotionGroup}
|
|
311
|
+
postModelRender={handleModelRender}
|
|
312
|
+
/>
|
|
313
|
+
</group>
|
|
314
|
+
</BoundsRefresher>
|
|
315
|
+
</Bounds>
|
|
316
|
+
</Canvas>
|
|
317
|
+
)}
|
|
268
318
|
</Box>
|
|
269
319
|
|
|
270
320
|
{/* Content container on right */}
|
|
271
321
|
<Box
|
|
272
322
|
sx={{
|
|
273
|
-
flex: "1",
|
|
323
|
+
flex: shouldHideRobot ? "1" : "1",
|
|
274
324
|
display: "flex",
|
|
275
325
|
flexDirection: "column",
|
|
276
326
|
justifyContent: "flex-start",
|
|
327
|
+
width: shouldHideRobot ? "100%" : "50%",
|
|
277
328
|
}}
|
|
278
329
|
>
|
|
279
330
|
{/* Header section with robot name and program state */}
|
|
280
331
|
<Box
|
|
281
332
|
sx={{
|
|
282
|
-
p: 3,
|
|
283
|
-
pb: 2,
|
|
333
|
+
p: { xs: 1.5, sm: 2, md: 3 },
|
|
334
|
+
pb: { xs: 1, sm: 1.5, md: 2 },
|
|
284
335
|
textAlign: "left",
|
|
285
336
|
}}
|
|
286
337
|
>
|
|
@@ -297,7 +348,7 @@ export const RobotCard = externalizeComponent(
|
|
|
297
348
|
{/* Bottom section with runtime, cycle time, and button */}
|
|
298
349
|
<Box
|
|
299
350
|
sx={{
|
|
300
|
-
p: 3,
|
|
351
|
+
p: { xs: 1.5, sm: 2, md: 3 },
|
|
301
352
|
pt: 0,
|
|
302
353
|
flex: "1",
|
|
303
354
|
display: "flex",
|
|
@@ -330,8 +381,8 @@ export const RobotCard = externalizeComponent(
|
|
|
330
381
|
{/* Divider */}
|
|
331
382
|
<Divider
|
|
332
383
|
sx={{
|
|
333
|
-
mt:
|
|
334
|
-
mb:
|
|
384
|
+
mt: 1,
|
|
385
|
+
mb: 0,
|
|
335
386
|
borderColor: theme.palette.divider,
|
|
336
387
|
opacity: 0.5,
|
|
337
388
|
}}
|
|
@@ -344,8 +395,8 @@ export const RobotCard = externalizeComponent(
|
|
|
344
395
|
sx={{
|
|
345
396
|
display: "flex",
|
|
346
397
|
justifyContent: "flex-start",
|
|
347
|
-
mt: 2,
|
|
348
|
-
mb:
|
|
398
|
+
mt: { xs: 1, sm: 1.5, md: 2 },
|
|
399
|
+
mb: { xs: 0.5, sm: 0.75, md: 1 },
|
|
349
400
|
}}
|
|
350
401
|
>
|
|
351
402
|
<Button
|
|
@@ -353,7 +404,7 @@ export const RobotCard = externalizeComponent(
|
|
|
353
404
|
variant="contained"
|
|
354
405
|
color="secondary"
|
|
355
406
|
size="small"
|
|
356
|
-
disabled={
|
|
407
|
+
disabled={!driveToHomeEnabled}
|
|
357
408
|
onMouseDown={handleDriveToHomeMouseDown}
|
|
358
409
|
onMouseUp={handleDriveToHomeMouseUp}
|
|
359
410
|
onMouseLeave={handleDriveToHomeMouseLeave}
|
|
@@ -375,127 +426,137 @@ export const RobotCard = externalizeComponent(
|
|
|
375
426
|
) : (
|
|
376
427
|
<>
|
|
377
428
|
{/* Portrait Layout: Header, Robot, Footer */}
|
|
378
|
-
|
|
379
|
-
{/* Header section with robot name and program state */}
|
|
380
|
-
<Box sx={{ p: 3, pb: 1 }}>
|
|
381
|
-
<Typography variant="h6" component="h2" sx={{ mb: 1 }}>
|
|
382
|
-
{robotName}
|
|
383
|
-
</Typography>
|
|
384
|
-
<ProgramStateIndicator
|
|
385
|
-
programState={programState}
|
|
386
|
-
safetyState={safetyState}
|
|
387
|
-
operationMode={operationMode}
|
|
388
|
-
/>
|
|
389
|
-
</Box>
|
|
390
|
-
|
|
391
|
-
{/* 3D Robot viewport in center */}
|
|
392
429
|
<Box
|
|
393
430
|
sx={{
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
mx: 3,
|
|
399
|
-
mb: 1,
|
|
400
|
-
overflow: "hidden", // Prevent content from affecting container size
|
|
431
|
+
p: 3,
|
|
432
|
+
height: "100%",
|
|
433
|
+
display: "flex",
|
|
434
|
+
flexDirection: "column",
|
|
401
435
|
}}
|
|
402
436
|
>
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
position: "absolute",
|
|
415
|
-
top: 0,
|
|
416
|
-
left: 0,
|
|
417
|
-
}}
|
|
418
|
-
dpr={[1, 2]}
|
|
419
|
-
gl={{ alpha: true, antialias: true }}
|
|
420
|
-
>
|
|
421
|
-
<PresetEnvironment />
|
|
422
|
-
<Bounds fit clip observe margin={1.2}>
|
|
423
|
-
<BoundsRefresher modelRenderTrigger={modelRenderTrigger}>
|
|
424
|
-
<group ref={robotRef}>
|
|
425
|
-
<RobotComponent
|
|
426
|
-
rapidlyChangingMotionState={
|
|
427
|
-
connectedMotionGroup.rapidlyChangingMotionState
|
|
428
|
-
}
|
|
429
|
-
modelFromController={
|
|
430
|
-
connectedMotionGroup.modelFromController || ""
|
|
431
|
-
}
|
|
432
|
-
dhParameters={connectedMotionGroup.dhParameters || []}
|
|
433
|
-
postModelRender={handleModelRender}
|
|
434
|
-
/>
|
|
435
|
-
</group>
|
|
436
|
-
</BoundsRefresher>
|
|
437
|
-
</Bounds>
|
|
438
|
-
</Canvas>
|
|
439
|
-
</Box>
|
|
437
|
+
{/* Header section with robot name and program state */}
|
|
438
|
+
<Box>
|
|
439
|
+
<Typography variant="h6" component="h2" sx={{ mb: 1 }}>
|
|
440
|
+
{robotName}
|
|
441
|
+
</Typography>
|
|
442
|
+
<ProgramStateIndicator
|
|
443
|
+
programState={programState}
|
|
444
|
+
safetyState={safetyState}
|
|
445
|
+
operationMode={operationMode}
|
|
446
|
+
/>
|
|
447
|
+
</Box>
|
|
440
448
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
{/* Runtime display */}
|
|
444
|
-
<Typography
|
|
445
|
-
variant="body1"
|
|
449
|
+
{/* 3D Robot viewport in center */}
|
|
450
|
+
<Box
|
|
446
451
|
sx={{
|
|
447
|
-
|
|
448
|
-
|
|
452
|
+
flex: shouldHideRobot ? 0 : 1,
|
|
453
|
+
position: "relative",
|
|
454
|
+
minHeight: shouldHideRobot
|
|
455
|
+
? 0
|
|
456
|
+
: { xs: 120, sm: 150, md: 200 },
|
|
457
|
+
height: shouldHideRobot ? 0 : "auto",
|
|
458
|
+
borderRadius: 1,
|
|
459
|
+
overflow: "hidden",
|
|
460
|
+
display: shouldHideRobot ? "none" : "block",
|
|
449
461
|
}}
|
|
450
462
|
>
|
|
451
|
-
{
|
|
452
|
-
|
|
463
|
+
{!shouldHideRobot && (
|
|
464
|
+
<Canvas
|
|
465
|
+
camera={{
|
|
466
|
+
position: [3, 3, 3], // Closer camera position for portrait to make robot larger
|
|
467
|
+
fov: 20, // Slightly higher FOV for portrait to fill better
|
|
468
|
+
}}
|
|
469
|
+
shadows
|
|
470
|
+
frameloop="demand"
|
|
471
|
+
style={{
|
|
472
|
+
borderRadius: theme.shape.borderRadius,
|
|
473
|
+
width: "100%",
|
|
474
|
+
height: "100%",
|
|
475
|
+
background: "transparent",
|
|
476
|
+
position: "absolute",
|
|
477
|
+
top: 0,
|
|
478
|
+
left: 0,
|
|
479
|
+
}}
|
|
480
|
+
dpr={[1, 2]}
|
|
481
|
+
gl={{ alpha: true, antialias: true }}
|
|
482
|
+
>
|
|
483
|
+
<PresetEnvironment />
|
|
484
|
+
<Bounds fit observe margin={1}>
|
|
485
|
+
<BoundsRefresher
|
|
486
|
+
modelRenderTrigger={modelRenderTrigger}
|
|
487
|
+
isPortrait={true}
|
|
488
|
+
>
|
|
489
|
+
<group ref={robotRef} scale={robotScale}>
|
|
490
|
+
<RobotComponent
|
|
491
|
+
connectedMotionGroup={connectedMotionGroup}
|
|
492
|
+
postModelRender={handleModelRender}
|
|
493
|
+
/>
|
|
494
|
+
</group>
|
|
495
|
+
</BoundsRefresher>
|
|
496
|
+
</Bounds>
|
|
497
|
+
</Canvas>
|
|
498
|
+
)}
|
|
499
|
+
</Box>
|
|
453
500
|
|
|
454
|
-
{/*
|
|
455
|
-
<
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
501
|
+
{/* Bottom section with runtime, cycle time, and button */}
|
|
502
|
+
<Box>
|
|
503
|
+
{/* Runtime display */}
|
|
504
|
+
<Typography
|
|
505
|
+
variant="body1"
|
|
506
|
+
sx={{
|
|
507
|
+
mb: 0,
|
|
508
|
+
color: "var(--text-secondary, #FFFFFFB2)",
|
|
509
|
+
}}
|
|
510
|
+
>
|
|
511
|
+
{t("RobotCard.Runtime.lb")}
|
|
512
|
+
</Typography>
|
|
460
513
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
opacity: 0.5,
|
|
468
|
-
}}
|
|
469
|
-
/>
|
|
514
|
+
{/* Compact cycle time component directly below runtime */}
|
|
515
|
+
<CycleTimerComponent
|
|
516
|
+
variant="small"
|
|
517
|
+
compact
|
|
518
|
+
onCycleComplete={handleCycleComplete}
|
|
519
|
+
/>
|
|
470
520
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
sx={{
|
|
474
|
-
display: "flex",
|
|
475
|
-
justifyContent: "flex-start",
|
|
476
|
-
mt: 5,
|
|
477
|
-
mb: 2,
|
|
478
|
-
}}
|
|
479
|
-
>
|
|
480
|
-
<Button
|
|
481
|
-
ref={driveButtonRef}
|
|
482
|
-
variant="contained"
|
|
483
|
-
color="secondary"
|
|
484
|
-
size="small"
|
|
485
|
-
disabled={true}
|
|
486
|
-
onMouseDown={handleDriveToHomeMouseDown}
|
|
487
|
-
onMouseUp={handleDriveToHomeMouseUp}
|
|
488
|
-
onMouseLeave={handleDriveToHomeMouseLeave}
|
|
489
|
-
onTouchStart={handleDriveToHomeMouseDown}
|
|
490
|
-
onTouchEnd={handleDriveToHomeMouseUp}
|
|
521
|
+
{/* Divider */}
|
|
522
|
+
<Divider
|
|
491
523
|
sx={{
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
524
|
+
mt: 1,
|
|
525
|
+
mb: 0,
|
|
526
|
+
borderColor: theme.palette.divider,
|
|
527
|
+
opacity: 0.5,
|
|
528
|
+
}}
|
|
529
|
+
/>
|
|
530
|
+
|
|
531
|
+
{/* Drive to Home button with some space */}
|
|
532
|
+
<Box
|
|
533
|
+
sx={{
|
|
534
|
+
display: "flex",
|
|
535
|
+
justifyContent: "flex-start",
|
|
536
|
+
mt: { xs: 1, sm: 2, md: 5 },
|
|
537
|
+
mb: { xs: 0.5, sm: 0.75, md: 1 },
|
|
495
538
|
}}
|
|
496
539
|
>
|
|
497
|
-
|
|
498
|
-
|
|
540
|
+
<Button
|
|
541
|
+
ref={driveButtonRef}
|
|
542
|
+
variant="contained"
|
|
543
|
+
color="secondary"
|
|
544
|
+
size="small"
|
|
545
|
+
disabled={!driveToHomeEnabled}
|
|
546
|
+
onMouseDown={handleDriveToHomeMouseDown}
|
|
547
|
+
onMouseUp={handleDriveToHomeMouseUp}
|
|
548
|
+
onMouseLeave={handleDriveToHomeMouseLeave}
|
|
549
|
+
onTouchStart={handleDriveToHomeMouseDown}
|
|
550
|
+
onTouchEnd={handleDriveToHomeMouseUp}
|
|
551
|
+
sx={{
|
|
552
|
+
textTransform: "none",
|
|
553
|
+
px: 1.5,
|
|
554
|
+
py: 0.5,
|
|
555
|
+
}}
|
|
556
|
+
>
|
|
557
|
+
{t("RobotCard.DriveToHome.bt")}
|
|
558
|
+
</Button>
|
|
559
|
+
</Box>
|
|
499
560
|
</Box>
|
|
500
561
|
</Box>
|
|
501
562
|
</>
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ThreeElements } from "@react-three/fiber"
|
|
2
2
|
|
|
3
3
|
import type { ConnectedMotionGroup } from "@wandelbots/nova-js/v1"
|
|
4
4
|
import type { Group } from "three"
|
|
5
|
-
import { SupportedRobot } from "./SupportedRobot"
|
|
6
5
|
import { defaultGetModel } from "./robotModelLogic"
|
|
6
|
+
import { SupportedRobot } from "./SupportedRobot"
|
|
7
7
|
|
|
8
8
|
export type RobotProps = {
|
|
9
9
|
connectedMotionGroup: ConnectedMotionGroup
|
|
10
10
|
getModel?: (modelFromController: string) => string
|
|
11
11
|
flangeRef?: React.Ref<Group>
|
|
12
12
|
transparentColor?: string
|
|
13
|
+
postModelRender?: () => void
|
|
13
14
|
} & ThreeElements["group"]
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -28,6 +29,7 @@ export function Robot({
|
|
|
28
29
|
getModel = defaultGetModel,
|
|
29
30
|
flangeRef,
|
|
30
31
|
transparentColor,
|
|
32
|
+
postModelRender,
|
|
31
33
|
...props
|
|
32
34
|
}: RobotProps) {
|
|
33
35
|
if (!connectedMotionGroup.dhParameters) {
|
|
@@ -44,6 +46,7 @@ export function Robot({
|
|
|
44
46
|
getModel={getModel}
|
|
45
47
|
flangeRef={flangeRef}
|
|
46
48
|
transparentColor={transparentColor}
|
|
49
|
+
postModelRender={postModelRender}
|
|
47
50
|
{...props}
|
|
48
51
|
/>
|
|
49
52
|
)
|