Skip to content

Commit 7f55483

Browse files
authored
feat: update toolbar (#594)
1 parent 5a96a22 commit 7f55483

File tree

5 files changed

+209
-45
lines changed

5 files changed

+209
-45
lines changed

editor/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"@radix-ui/react-tabs": "^1.0.4",
7070
"@radix-ui/react-toggle": "^1.1.1",
7171
"@radix-ui/react-tooltip": "^1.0.7",
72+
"@radix-ui/react-radio-group": "^1.1.3",
7273
"@xterm/addon-fit": "^0.10.0",
7374
"@xterm/xterm": "^5.5.0",
7475
"assimpjs": "0.0.10",

editor/src/editor/layout/preview.tsx

Lines changed: 64 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import { Component, MouseEvent, ReactNode } from "react";
77
import { Grid } from "react-loader-spinner";
88

99
import { FaCheck } from "react-icons/fa6";
10-
import { GiWireframeGlobe } from "react-icons/gi";
1110
import { IoIosOptions, IoIosStats } from "react-icons/io";
11+
import { LuMove3D, LuRotate3D, LuScale3D } from "react-icons/lu";
12+
import { GiArrowCursor, GiWireframeGlobe } from "react-icons/gi";
1213

1314
import {
1415
AbstractEngine,
@@ -32,10 +33,11 @@ import {
3233
SceneLoaderFlags,
3334
} from "babylonjs";
3435

35-
import { Toggle } from "../../ui/shadcn/ui/toggle";
3636
import { Button } from "../../ui/shadcn/ui/button";
3737
import { Progress } from "../../ui/shadcn/ui/progress";
38+
import { Toggle } from "../../ui/shadcn/ui/toggle";
3839
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../ui/shadcn/ui/select";
40+
import { ToolbarRadioGroup, ToolbarRadioGroupItem } from "../../ui/shadcn/ui/toolbar-radio-group";
3941

4042
import { Editor } from "../main";
4143

@@ -56,10 +58,6 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel,
5658

5759
import { EditorCamera } from "../nodes/camera";
5860

59-
import { PositionIcon } from "../../ui/icons/position";
60-
import { RotationIcon } from "../../ui/icons/rotation";
61-
import { ScalingIcon } from "../../ui/icons/scaling";
62-
6361
import { SpinnerUIComponent } from "../../ui/spinner";
6462
import { Separator } from "../../ui/shadcn/ui/separator";
6563
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../../ui/shadcn/ui/tooltip";
@@ -761,33 +759,72 @@ export class EditorPreview extends Component<IEditorPreviewProps, IEditorPreview
761759
</SelectContent>
762760
</Select>
763761

764-
<Separator orientation="vertical" className="mx-2 h-[24px]" />
762+
<Separator orientation="vertical" className="mx-1 h-[24px]" />
763+
764+
<ToolbarRadioGroup
765+
value={this.state.activeGizmo === "none" ? "select" : this.state.activeGizmo}
766+
onValueChange={(value) => {
767+
if (value === "select") {
768+
this.setActiveGizmo("none");
769+
} else {
770+
this.setActiveGizmo(value as "position" | "rotation" | "scaling");
771+
}
772+
}}
773+
>
774+
<Tooltip>
775+
<TooltipTrigger asChild>
776+
<ToolbarRadioGroupItem value="select" className={this.state.activeGizmo === "none" ? "bg-primary/20" : ""}>
777+
<GiArrowCursor className="h-4 w-4" />
778+
</ToolbarRadioGroupItem>
779+
</TooltipTrigger>
780+
<TooltipContent>Select mode</TooltipContent>
781+
</Tooltip>
782+
<Tooltip>
783+
<TooltipTrigger asChild>
784+
<ToolbarRadioGroupItem value="position" className={this.state.activeGizmo === "position" ? "bg-primary/20" : ""}>
785+
<LuMove3D height={16} />
786+
</ToolbarRadioGroupItem>
787+
</TooltipTrigger>
788+
<TooltipContent>Toggle position gizmo</TooltipContent>
789+
</Tooltip>
790+
<Tooltip>
791+
<TooltipTrigger asChild>
792+
<ToolbarRadioGroupItem value="rotation" className={this.state.activeGizmo === "rotation" ? "bg-primary/20" : ""}>
793+
<LuRotate3D height={16} />
794+
</ToolbarRadioGroupItem>
795+
</TooltipTrigger>
796+
<TooltipContent>Toggle rotation gizmo</TooltipContent>
797+
</Tooltip>
798+
<Tooltip>
799+
<TooltipTrigger asChild>
800+
<ToolbarRadioGroupItem value="scaling" className={this.state.activeGizmo === "scaling" ? "bg-primary/20" : ""}>
801+
<LuScale3D height={16} />
802+
</ToolbarRadioGroupItem>
803+
</TooltipTrigger>
804+
<TooltipContent>Toggle scaling gizmo</TooltipContent>
805+
</Tooltip>
806+
</ToolbarRadioGroup>
807+
808+
<Separator orientation="vertical" className="mx-1 h-[24px]" />
765809

766810
<Tooltip>
767811
<TooltipTrigger asChild>
768-
<Toggle pressed={this.state.activeGizmo === "position"} onPressedChange={() => this.setActiveGizmo("position")}>
769-
<PositionIcon height={16} />
770-
</Toggle>
771-
</TooltipTrigger>
772-
<TooltipContent>Toggle position gizmo</TooltipContent>
773-
</Tooltip>
774-
<Tooltip>
775-
<TooltipTrigger asChild>
776-
<Toggle pressed={this.state.activeGizmo === "rotation"} onPressedChange={() => this.setActiveGizmo("rotation")}>
777-
<RotationIcon height={16} />
778-
</Toggle>
779-
</TooltipTrigger>
780-
<TooltipContent>Toggle rotation gizmo</TooltipContent>
781-
</Tooltip>
782-
<Tooltip>
783-
<TooltipTrigger asChild>
784-
<Toggle pressed={this.state.activeGizmo === "scaling"} onPressedChange={() => this.setActiveGizmo("scaling")}>
785-
<ScalingIcon height={16} />
812+
<Toggle
813+
className={this.scene?.forceWireframe ? "!px-2 !py-2 bg-primary/20" : "!px-2 !py-2"}
814+
pressed={this.scene?.forceWireframe}
815+
onPressedChange={() => {
816+
this.scene.forceWireframe = !this.scene.forceWireframe;
817+
this.forceUpdate();
818+
}}
819+
>
820+
<GiWireframeGlobe className="w-6 h-6 scale-125" strokeWidth={1} color="white" />
786821
</Toggle>
787822
</TooltipTrigger>
788-
<TooltipContent>Toggle scaling gizmo</TooltipContent>
823+
<TooltipContent>Toggle wireframe</TooltipContent>
789824
</Tooltip>
790825

826+
<Separator orientation="vertical" className="mx-1 h-[24px]" />
827+
791828
<Select
792829
value={this.gizmo?.getCoordinateMode().toString()}
793830
onValueChange={(v) => {
@@ -804,25 +841,7 @@ export class EditorPreview extends Component<IEditorPreviewProps, IEditorPreview
804841
</SelectContent>
805842
</Select>
806843

807-
<Separator orientation="vertical" className="mx-2 h-[24px]" />
808-
809-
<Tooltip>
810-
<TooltipTrigger asChild>
811-
<Toggle
812-
className="!px-2 !py-2"
813-
pressed={this.scene?.forceWireframe}
814-
onPressedChange={() => {
815-
this.scene.forceWireframe = !this.scene.forceWireframe;
816-
this.forceUpdate();
817-
}}
818-
>
819-
<GiWireframeGlobe className="w-6 h-6 scale-125" strokeWidth={1} color="white" />
820-
</Toggle>
821-
</TooltipTrigger>
822-
<TooltipContent>Toggle wireframe</TooltipContent>
823-
</Tooltip>
824-
825-
<Separator orientation="vertical" className="mx-2 h-[24px]" />
844+
<Separator orientation="vertical" className="mx-1 h-[24px]" />
826845

827846
<DropdownMenu>
828847
<DropdownMenuTrigger asChild>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"use client";
2+
3+
import * as React from "react";
4+
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
5+
import { CheckIcon } from "@radix-ui/react-icons";
6+
7+
import { cn } from "../../utils";
8+
9+
const RadioGroup = React.forwardRef<React.ElementRef<typeof RadioGroupPrimitive.Root>, React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>>(
10+
({ className, ...props }, ref) => {
11+
return <RadioGroupPrimitive.Root className={cn("grid gap-2", className)} {...props} ref={ref} />;
12+
}
13+
);
14+
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
15+
16+
const RadioGroupItem = React.forwardRef<React.ElementRef<typeof RadioGroupPrimitive.Item>, React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>>(
17+
({ className, ...props }, ref) => {
18+
return (
19+
<RadioGroupPrimitive.Item
20+
ref={ref}
21+
className={cn(
22+
"aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
23+
className
24+
)}
25+
{...props}
26+
>
27+
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
28+
<CheckIcon className="h-2.5 w-2.5" />
29+
</RadioGroupPrimitive.Indicator>
30+
</RadioGroupPrimitive.Item>
31+
);
32+
}
33+
);
34+
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
35+
36+
export { RadioGroup, RadioGroupItem };
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"use client";
2+
3+
import * as React from "react";
4+
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
5+
import { cn } from "../../utils";
6+
7+
const ToolbarRadioGroup = React.forwardRef<React.ElementRef<typeof RadioGroupPrimitive.Root>, React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>>(
8+
({ className, ...props }, ref) => {
9+
return <RadioGroupPrimitive.Root className={cn("flex items-center gap-1", className)} {...props} ref={ref} />;
10+
}
11+
);
12+
ToolbarRadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
13+
14+
const ToolbarRadioGroupItem = React.forwardRef<React.ElementRef<typeof RadioGroupPrimitive.Item>, React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>>(
15+
({ className, children, ...props }, ref) => {
16+
return (
17+
<RadioGroupPrimitive.Item
18+
ref={ref}
19+
className={cn(
20+
"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
21+
"h-9 w-9 px-0 py-0",
22+
"bg-transparent hover:bg-muted hover:text-muted-foreground",
23+
"data-[state=checked]:bg-accent data-[state=checked]:text-accent-foreground",
24+
"[&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
25+
className
26+
)}
27+
{...props}
28+
>
29+
{children}
30+
</RadioGroupPrimitive.Item>
31+
);
32+
}
33+
);
34+
ToolbarRadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
35+
36+
export { ToolbarRadioGroup, ToolbarRadioGroupItem };

yarn.lock

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2541,6 +2541,11 @@
25412541
resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.2.tgz#83f415c4425f21e3d27914c12b3272a32e3dae65"
25422542
integrity sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==
25432543

2544+
"@radix-ui/[email protected]":
2545+
version "1.1.3"
2546+
resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.3.tgz#e2dbc13bdc5e4168f4334f75832d7bdd3e2de5ba"
2547+
integrity sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==
2548+
25442549
"@radix-ui/react-alert-dialog@^1.0.5":
25452550
version "1.0.5"
25462551
resolved "https://registry.yarnpkg.com/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.0.5.tgz#70dd529cbf1e4bff386814d3776901fcaa131b8c"
@@ -2604,6 +2609,16 @@
26042609
"@radix-ui/react-primitive" "2.0.0"
26052610
"@radix-ui/react-slot" "1.1.0"
26062611

2612+
"@radix-ui/[email protected]":
2613+
version "1.1.7"
2614+
resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.7.tgz#d05c25ca9ac4695cc19ba91f42f686e3ea2d9aec"
2615+
integrity sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==
2616+
dependencies:
2617+
"@radix-ui/react-compose-refs" "1.1.2"
2618+
"@radix-ui/react-context" "1.1.2"
2619+
"@radix-ui/react-primitive" "2.1.3"
2620+
"@radix-ui/react-slot" "1.2.3"
2621+
26072622
"@radix-ui/[email protected]":
26082623
version "1.0.1"
26092624
resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz#7ed868b66946aa6030e580b1ffca386dd4d21989"
@@ -2694,6 +2709,11 @@
26942709
resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc"
26952710
integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==
26962711

2712+
"@radix-ui/[email protected]":
2713+
version "1.1.1"
2714+
resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.1.tgz#39e5a5769e676c753204b792fbe6cf508e550a14"
2715+
integrity sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==
2716+
26972717
"@radix-ui/[email protected]":
26982718
version "1.0.5"
26992719
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz#3f98425b82b9068dfbab5db5fff3df6ebf48b9d4"
@@ -2776,6 +2796,13 @@
27762796
"@babel/runtime" "^7.13.10"
27772797
"@radix-ui/react-use-layout-effect" "1.0.1"
27782798

2799+
"@radix-ui/[email protected]":
2800+
version "1.1.1"
2801+
resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.1.tgz#1404002e79a03fe062b7e3864aa01e24bd1471f7"
2802+
integrity sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==
2803+
dependencies:
2804+
"@radix-ui/react-use-layout-effect" "1.1.1"
2805+
27792806
"@radix-ui/react-label@^2.0.2":
27802807
version "2.0.2"
27812808
resolved "https://registry.yarnpkg.com/@radix-ui/react-label/-/react-label-2.0.2.tgz#9c72f1d334aac996fdc27b48a8bdddd82108fb6d"
@@ -2922,6 +2949,14 @@
29222949
"@radix-ui/react-compose-refs" "1.1.2"
29232950
"@radix-ui/react-use-layout-effect" "1.1.1"
29242951

2952+
"@radix-ui/[email protected]":
2953+
version "1.1.5"
2954+
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.5.tgz#5d8f28ac316c32f078afce2996839250c10693db"
2955+
integrity sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==
2956+
dependencies:
2957+
"@radix-ui/react-compose-refs" "1.1.2"
2958+
"@radix-ui/react-use-layout-effect" "1.1.1"
2959+
29252960
"@radix-ui/[email protected]":
29262961
version "1.0.3"
29272962
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz#d49ea0f3f0b2fe3ab1cb5667eb03e8b843b914d0"
@@ -2975,6 +3010,22 @@
29753010
"@radix-ui/react-context" "1.1.1"
29763011
"@radix-ui/react-primitive" "2.0.2"
29773012

3013+
"@radix-ui/react-radio-group@^1.1.3":
3014+
version "1.3.8"
3015+
resolved "https://registry.yarnpkg.com/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz#93f102b5b948d602c2f2adb1bc5c347cbaf64bd9"
3016+
integrity sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==
3017+
dependencies:
3018+
"@radix-ui/primitive" "1.1.3"
3019+
"@radix-ui/react-compose-refs" "1.1.2"
3020+
"@radix-ui/react-context" "1.1.2"
3021+
"@radix-ui/react-direction" "1.1.1"
3022+
"@radix-ui/react-presence" "1.1.5"
3023+
"@radix-ui/react-primitive" "2.1.3"
3024+
"@radix-ui/react-roving-focus" "1.1.11"
3025+
"@radix-ui/react-use-controllable-state" "1.2.2"
3026+
"@radix-ui/react-use-previous" "1.1.1"
3027+
"@radix-ui/react-use-size" "1.1.1"
3028+
29783029
"@radix-ui/[email protected]":
29793030
version "1.0.4"
29803031
resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz#e90c4a6a5f6ac09d3b8c1f5b5e81aab2f0db1974"
@@ -2991,6 +3042,21 @@
29913042
"@radix-ui/react-use-callback-ref" "1.0.1"
29923043
"@radix-ui/react-use-controllable-state" "1.0.1"
29933044

3045+
"@radix-ui/[email protected]":
3046+
version "1.1.11"
3047+
resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz#ef54384b7361afc6480dcf9907ef2fedb5080fd9"
3048+
integrity sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==
3049+
dependencies:
3050+
"@radix-ui/primitive" "1.1.3"
3051+
"@radix-ui/react-collection" "1.1.7"
3052+
"@radix-ui/react-compose-refs" "1.1.2"
3053+
"@radix-ui/react-context" "1.1.2"
3054+
"@radix-ui/react-direction" "1.1.1"
3055+
"@radix-ui/react-id" "1.1.1"
3056+
"@radix-ui/react-primitive" "2.1.3"
3057+
"@radix-ui/react-use-callback-ref" "1.1.1"
3058+
"@radix-ui/react-use-controllable-state" "1.2.2"
3059+
29943060
"@radix-ui/react-select@^2.0.0":
29953061
version "2.0.0"
29963062
resolved "https://registry.yarnpkg.com/@radix-ui/react-select/-/react-select-2.0.0.tgz#a3511792a51a7018d6559357323a7f52e0e38887"
@@ -3228,6 +3294,11 @@
32283294
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz#d4dd37b05520f1d996a384eb469320c2ada8377c"
32293295
integrity sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==
32303296

3297+
"@radix-ui/[email protected]":
3298+
version "1.1.1"
3299+
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz#1a1ad5568973d24051ed0af687766f6c7cb9b5b5"
3300+
integrity sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==
3301+
32313302
"@radix-ui/[email protected]":
32323303
version "1.0.1"
32333304
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz#fde50b3bb9fd08f4a1cd204572e5943c244fcec2"
@@ -4693,6 +4764,7 @@ babylonjs-editor-tools@latest:
46934764
"@radix-ui/react-menubar" "^1.0.4"
46944765
"@radix-ui/react-popover" "^1.0.7"
46954766
"@radix-ui/react-progress" "^1.0.3"
4767+
"@radix-ui/react-radio-group" "^1.1.3"
46964768
"@radix-ui/react-select" "^2.0.0"
46974769
"@radix-ui/react-separator" "^1.0.3"
46984770
"@radix-ui/react-slider" "^1.2.0"

0 commit comments

Comments
 (0)