Skip to content

Commit

Permalink
added highlighting to selected gui elements and worked on responsiven…
Browse files Browse the repository at this point in the history
…ess; not mobile-friendly
  • Loading branch information
99-Knots committed Jun 19, 2024
1 parent 0b272c0 commit 93a66d1
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 52 deletions.
1 change: 0 additions & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css">
</head>
<body>
<div>Editor Demo</div>
<div id="react-root"></div>
</body>
</html>
4 changes: 0 additions & 4 deletions src/components/GizmoManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,10 @@ export class GizmoManager {

this.positionGizmo = new PositionGizmo(this.layer, thickness ?? 1);
this.positionGizmo.scaleRatio = scale ?? 1;
//this.positionGizmo.onDragStartObservable.add(() => {setDragging(true)});
//this.positionGizmo.onDragEndObservable.add(() => {setDragging(false)})
this.initPositionGizmo();

this.rotationGizmo = new RotationGizmo(this.layer, undefined, undefined, thickness ?? 1);
this.rotationGizmo.scaleRatio = scale ?? 1;
//this.rotationGizmo.onDragStartObservable.add(() => {setDragging(true)});
//this.rotationGizmo.onDragEndObservable.add(() => {setDragging(false)})
this.initRotationGizmo();

this.boundingBoxGizmo = new CustomBoundingBoxGizmo(setDragging, Color3.Gray(), this.layer, this);
Expand Down
44 changes: 24 additions & 20 deletions src/components/canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const CanvasRenderer: React.ForwardRefRenderFunction<CanvasHandle, CanvasProps>

let isMoving = false;
let wasMoving = false;
let gizmoScale = 0.7;


React.useEffect(() => {
Expand Down Expand Up @@ -160,7 +161,7 @@ const CanvasRenderer: React.ForwardRefRenderFunction<CanvasHandle, CanvasProps>
}

const setupGizmo = async () => {
gizmo.current = new GizmoManager(setDragging, setRootPos, scene.current, 3.5, 1);
gizmo.current = new GizmoManager(setDragging, setRootPos, scene.current, 4.5, gizmoScale);
let inMultiselectMode = false;
let pressedTimestamp = 0;
const ray = new Ray(Vector3.Zero(), Vector3.Zero()) // necessary to ensure import of Ray
Expand Down Expand Up @@ -257,20 +258,23 @@ const CanvasRenderer: React.ForwardRefRenderFunction<CanvasHandle, CanvasProps>
}
React.useImperativeHandle(env, () => handle);

const r = 15;
const rInner = 15 * gizmoScale;
const r = rInner + 6;
const sectionAngle = 90/6;

// todo: maybe also use z-index to represent axis overlap in correct order?
return (
<div className="main">
<canvas className='babylon-canvas' ref={canvas} />
<SideMenu>
<canvas className='babylon-canvas' ref={canvas}>

</canvas>
<SideMenu buttonSize={5}>
<MenuOption onClick={()=>{Commands().undo(); setHiddenSelection(true), gizmo.current.removeAllNodes()}} icon="arrow-90deg-left"></MenuOption>
</SideMenu>
<MovingButton x={rootPos.x} y={rootPos.y} hidden={hiddenSelection} buttonSize={3}>
<RadialButton angle={sectionAngle*2} radius={r} onClick={() => {setGizmoMode(GizmoMode.Translate)}} icon="arrows-move"/>
<RadialButton angle={sectionAngle*3} radius={r} onClick={() => {setGizmoMode(GizmoMode.Rotate)}} icon="arrow-repeat"/>
<RadialButton angle={sectionAngle*4} radius={r} onClick={() => {setGizmoMode(GizmoMode.Scale)}} icon="bounding-box-circles"/>
<MovingButton x={rootPos.x} y={rootPos.y} hidden={hiddenSelection} buttonSize={3.5}>
<RadialButton angle={sectionAngle*2} radius={r} onClick={() => {setGizmoMode(GizmoMode.Translate)}} isSelected={gizmoMode==GizmoMode.Translate} icon="arrows-move"/>
<RadialButton angle={sectionAngle*3} radius={r} onClick={() => {setGizmoMode(GizmoMode.Rotate)}} isSelected={gizmoMode==GizmoMode.Rotate} icon="arrow-repeat"/>
<RadialButton angle={sectionAngle*4} radius={r} onClick={() => {setGizmoMode(GizmoMode.Scale)}} isSelected={gizmoMode==GizmoMode.Scale} icon="bounding-box-circles"/>
<ExpandableRadialButton inactive={gizmoMode!==GizmoMode.Translate} angle={sectionAngle*6} radius={r} onClick={setSnapDist} options={[{text: 'free', value: 0}, {text: '0.1m', value: 0.1}, {text: '0.2m', value: 0.2}, {text: '0.5m', value: 0.5}, {text: '1m', value: 1}, {text: '2m', value: 2}]}/>
<ExpandableRadialButton inactive={gizmoMode!==GizmoMode.Rotate} angle={sectionAngle*6} radius={r} onClick={setSnapAngle} options={[{text: 'free', value: 0}, {text: '15°', value: 15}, {text: '30°', value: 30}, {text: '45°', value: 45}, {text: '60°', value: 60}, {text: '90°', value: 90}]}/>
<RadialButton inactive={gizmoMode!==GizmoMode.Scale || !gizmoScaling} angle={sectionAngle*6} radius={r} onClick={()=>{setGizmoScaling(false)}} icon="align-start"/>
Expand All @@ -287,23 +291,23 @@ const CanvasRenderer: React.ForwardRefRenderFunction<CanvasHandle, CanvasProps>
<RadialButton angle={sectionAngle*10} radius={r} onClick={()=>{deleteNode()}} icon="trash3"/>
{(gizmoMode == GizmoMode.Translate )?
<>
<RadialButton angle={axesAngles.z + 180} color={'cyan'} radius={10} rotation={axesAngles.z + 180} onClick={()=>{gizmo.current.snapAlongAxis('z', true)}}>
<AxisMover dashed={true}/>
<RadialButton angle={axesAngles.z + 180} radius={rInner} rotation={axesAngles.z + 180} onClick={()=>{gizmo.current.snapAlongAxis('z', true)}}>
<AxisMover color={'cyan'} dashed={true}/>
</RadialButton>
<RadialButton angle={axesAngles.y +180} color={'lime'} radius={10} rotation={axesAngles.y + 180} onClick={()=>{gizmo.current.snapAlongAxis('y', true)}}>
<AxisMover dashed={true}/>
<RadialButton angle={axesAngles.y +180} radius={rInner} rotation={axesAngles.y + 180} onClick={()=>{gizmo.current.snapAlongAxis('y', true)}}>
<AxisMover color={'lime'} dashed={true}/>
</RadialButton>
<RadialButton angle={axesAngles.x + 180} color={'#ff8080'} radius={10} rotation={axesAngles.x + 180} onClick={()=>{gizmo.current.snapAlongAxis('x', true)}}>
<AxisMover dashed={true}/>
<RadialButton angle={axesAngles.x + 180} radius={rInner} rotation={axesAngles.x + 180} onClick={()=>{gizmo.current.snapAlongAxis('x', true)}}>
<AxisMover color={'crimson'} dashed={true}/>
</RadialButton>
<RadialButton angle={axesAngles.z} color={'cyan'} radius={10} rotation={axesAngles.z} onClick={()=>{gizmo.current.snapAlongAxis('z')}}>
<AxisMover/>
<RadialButton angle={axesAngles.z} radius={rInner} rotation={axesAngles.z} onClick={()=>{gizmo.current.snapAlongAxis('z')}}>
<AxisMover color={'cyan'}/>
</RadialButton>
<RadialButton angle={axesAngles.y} color={'lime'} radius={10} rotation={axesAngles.y} onClick={()=>{gizmo.current.snapAlongAxis('y')}}>
<AxisMover/>
<RadialButton angle={axesAngles.y} radius={rInner} rotation={axesAngles.y} onClick={()=>{gizmo.current.snapAlongAxis('y')}}>
<AxisMover color={'lime'}/>
</RadialButton>
<RadialButton angle={axesAngles.x} color={'#ff8080'} radius={10} rotation={axesAngles.x} onClick={()=>{gizmo.current.snapAlongAxis('x')}}>
<AxisMover/>
<RadialButton angle={axesAngles.x} radius={rInner} rotation={axesAngles.x} onClick={()=>{gizmo.current.snapAlongAxis('x')}}>
<AxisMover color={'crimson'}/>
</RadialButton>
</>
:
Expand Down
34 changes: 26 additions & 8 deletions src/style.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
:root {
font-size: clamp(1px, 1vh, 16px);
}

html, body {
width: 100%;
height:100%;
margin: 0px;
padding: 0px;
}

.main {
position: relative;
overflow: hidden;
width: 100%;
height: 100%;
}

#react-root {
height: 100%;
width: 100%;
}

.babylon-canvas {
Expand Down Expand Up @@ -40,7 +58,7 @@
margin: 0.5em;
user-select: none;
gap: 0.3em;
font-size: 150%;
/*font-size: 150%;*/
}

.gizmo-gui-center {
Expand Down Expand Up @@ -99,25 +117,25 @@
}

.selected {
background-color: lightgray;
color: darkslategray;
background-color: darkgray;
color: #393939;
}

.test2 {
overflow: hidden;
transition: max-width 1s, font-size 1s, outline-width 1s;
}

.outline {
outline: whitesmoke solid 0.5px
}

.width-hidden {
max-width: 0;
outline-width: 0px;
}

.outline {
outline: whitesmoke solid 0.5px
}

path.outline {
svg .outline {
outline: none;
color: whitesmoke;
}
Expand Down
42 changes: 24 additions & 18 deletions src/ui/multiSwitch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const MovingButton = (props: {
x: number,
y: number,
hidden: boolean,
buttonSize?: number;
buttonSize: number;
children?: React.ReactElement<IRadialButton>[]
}) => {

Expand All @@ -24,7 +24,7 @@ export const MovingButton = (props: {
}, {minAngle: Infinity, maxAngle: -Infinity});

return (
<div className="gizmo-gui-center" style={{top: props.y??0, left: props.x??0, display: props.hidden?"none":"block", fontSize: (props.buttonSize + 'vmin')?? undefined}}>
<div className="gizmo-gui-center" style={{top: props.y??0, left: props.x??0, display: props.hidden?"none":"block", fontSize: `${props.buttonSize}rem`}}>
<gizmoGuiContext.Provider value={props.buttonSize}>
<CircleCut radius={radius} angle1={minAngle} angle2={maxAngle}/>
{
Expand Down Expand Up @@ -52,7 +52,8 @@ interface IRadialButton {
children?: React.ReactNode,
rotation?: number,
color?: string,
inactive?: boolean
inactive?: boolean,
isSelected?: boolean,
}

interface IExRadial extends IRadialButton {
Expand All @@ -72,18 +73,18 @@ export const RadialButton = (props: IRadialButton) => {
<div
className={"gizmo-mode-switch gui outline centered round " + (props.inactive? "hidden" : "")}
style={{
top: -y +'vmin',
left: x + 'vmin',
top: -y +'rem',
left: x + 'rem',
color: props.color,
}}
onClick={props.onClick}
>
<span
className={"icon align " + (props.icon ? "bi bi-" + props.icon : "")}
className={"icon align " + (props.icon ? "bi bi-" + props.icon : "") + (props.isSelected? " selected" : "")}
style={{
transform: 'rotate(' + props.rotation + 'deg)',
height: buttonSize + 'vmin',
minWidth: buttonSize + 'vmin',
height: buttonSize + 'rem',
minWidth: buttonSize + 'rem',
flexShrink: 0,
fontSize: props.text? buttonSize/(props.text.length-1) : undefined,
}}
Expand All @@ -95,13 +96,18 @@ export const RadialButton = (props: IRadialButton) => {
)
}

export const AxisMover = (props:{dashed?: boolean}) => {
export const AxisMover = (props:{dashed?: boolean, color?: string}) => {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16">
<g strokeDasharray={props.dashed? "1, 2": ""} strokeLinejoin="round" strokeLinecap="round" strokeWidth="1.3" stroke="currentColor" fillRule="evenodd" >
<path d="M8,15 v-11"/>
<g className="outline" strokeDasharray={props.dashed? "1, 2": ""} strokeLinejoin="round" strokeLinecap="round" strokeWidth="1.7" stroke="currentColor" fillRule="evenodd" >
<path d="M8,14 v-10"/>
<path d="M5,7 l3,-3 m3,3 l-3,-3"/>
<path d="M1,2 h14"/>
<path d="M1.5,2 h13"/>
</g>
<g strokeDasharray={props.dashed? "1, 2": ""} strokeLinejoin="round" strokeLinecap="round" strokeWidth="1" stroke={props.color} fillRule="evenodd" >
<path d="M8,14 v-10"/>
<path d="M5,7 l3,-3 m3,3 l-3,-3"/>
<path d="M1.5,2 h13"/>
</g>
</svg>
)
Expand All @@ -117,7 +123,7 @@ const CircleCut = (props:{angle1: number, angle2: number, radius: number}) =>{
let y2 = Math.cos(Math.PI/180 * props.angle2)*props.radius;

return (
<svg style={{transform: `translate(0vmin, -${props.radius}vmin)`}} xmlns="http://www.w3.org/2000/svg" width={2*props.radius + "vmin"} height={2*props.radius +"vmin"} viewBox={`0 0 ${props.radius*2} ${props.radius*2}`}>
<svg style={{transform: `translate(0rem, -${props.radius}rem)`}} xmlns="http://www.w3.org/2000/svg" width={2*props.radius + "rem"} height={2*props.radius +"rem"} viewBox={`0 0 ${props.radius*2} ${props.radius*2}`}>
<g strokeLinecap="round" stroke="currentColor" fill="none">
<path strokeWidth={width+0.1} className="outline" d={`M${x1} ${props.radius-y1} A${props.radius} ${props.radius} 0 0 1 ${x2} ${props.radius-y2}`}/>
<path strokeWidth={width} d={`M${x1} ${props.radius-y1} A${props.radius} ${props.radius} 0 0 1 ${x2} ${props.radius-y2}`}/>
Expand All @@ -142,7 +148,7 @@ const Option = (props: {
}, [props.selectedIndex, props.index])

return (
<div className={"test2 align outline " + (isSelected? "selected" : "") + (!(isSelected||props.visible)? " width-hidden" : "")} onClick={props.onClick} style={{maxWidth: (props.visible? size*5: (isSelected)? size : 0) + "vmin" , minWidth: isSelected? size + "vmin" : 0, fontSize: isSelected&&!props.visible? size*0.45 + "vmin" : undefined}}>
<div className={"test2 align outline " + (isSelected? "selected" : "") + (!(isSelected||props.visible)? " width-hidden" : "")} onClick={props.onClick} style={{maxWidth: (props.visible? size*5: (isSelected)? size : 0) + "rem" , minWidth: isSelected? size + "rem" : 0, fontSize: isSelected&&!props.visible? `${size*0.45}rem` : undefined}}>
<div className="test">{props.text}</div>
</div>
)
Expand All @@ -161,11 +167,11 @@ export const ExpandableRadialButton = (props: IExRadial ) => {

return (
<div
className={"gizmo-mode-switch gui centered round " + (props.inactive? "hidden" : "")}
className={"gizmo-mode-switch gui outline centered round " + (props.inactive? "hidden" : "")}
style={{
top: -y +'vmin',
left: x + 'vmin',
height: buttonSize + "vmin" ,
top: -y +'rem',
left: x + 'rem',
height: buttonSize + "rem" ,
color: props.color,
}}
onMouseEnter={() => {setIsExpanded(true)}}
Expand Down
3 changes: 2 additions & 1 deletion src/ui/sideMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from "react";

export const SideMenu = ( props: {
buttonSize: number,
children?: React.ReactNode,
}) => {
return(
<div className="side-menu">
<div className="side-menu" style={{fontSize: `${props.buttonSize*0.66}vmax`}}>
{props.children}
</div>
)
Expand Down

0 comments on commit 93a66d1

Please sign in to comment.