Skip to content

Commit 196440a

Browse files
authored
Merge pull request #8 from MetacityTools/help
Adding help panel for mouse controls
2 parents a98fb04 + af59818 commit 196440a

File tree

8 files changed

+219
-22
lines changed

8 files changed

+219
-22
lines changed

src/Components/Editor/Canvas/Canvas.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,19 @@ export function Canvas(props: { canvasRef: React.RefObject<HTMLCanvasElement> })
3636
ctx.select(object as EditorModel, submodelIDs, toggle, extend);
3737
}
3838

39+
const handleWheel = (event: WheelEvent) => {
40+
event.preventDefault();
41+
};
42+
43+
React.useEffect(() => {
44+
const canvas = props.canvasRef.current;
45+
if (!canvas) return;
46+
canvas.addEventListener('wheel', handleWheel);
47+
return () => {
48+
canvas.removeEventListener('wheel', handleWheel);
49+
};
50+
}, [props.canvasRef]);
51+
3952
return (
4053
<canvas
4154
ref={props.canvasRef}

src/Components/Editor/Editor.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { ContextComponent, ViewContextComponent } from './Context';
99
import { SidePanel } from './SidePanel/SidePanel';
1010
import { ProcessingScreen } from './Utils/Processing';
1111
import { SpashScreen } from './Utils/Splash';
12+
import { HelpPanel } from './ViewControls/Help';
1213
import { ViewControls } from './ViewControls/ViewControls';
1314

1415
export function ModelEditor() {
@@ -20,6 +21,7 @@ export function ModelEditor() {
2021
<Allotment.Pane minSize={200} className="bg-neutral-100">
2122
<ViewControls />
2223
<CanvasWrapper />
24+
<HelpPanel />
2325
</Allotment.Pane>
2426
<Allotment.Pane
2527
minSize={200}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import clsx from 'clsx';
2+
import React from 'react';
3+
4+
import { MouseLeft, MouseRight, MouseWheel } from '@elements/Icons';
5+
6+
function HelpItem(props: { children: React.ReactNode; last?: boolean }) {
7+
return (
8+
<div className={clsx('flex flex-col pr-2', !props.last && ' border-r')}>
9+
{props.children}
10+
</div>
11+
);
12+
}
13+
14+
export function HelpPanel() {
15+
return (
16+
<div className="absolute bottom-4 left-4 bg-white shadow-even text-md py-2 px-4 rounded-md flex flex-row space-x-4 text-xl">
17+
<div className="flex space-x-2 items-center">
18+
<MouseLeft />
19+
<HelpItem>
20+
<div className="text-xs text-neutral-500">Drag</div>
21+
<div className="text-xs">Pan</div>
22+
</HelpItem>
23+
<MouseLeft />
24+
<HelpItem>
25+
<div className="text-xs text-neutral-500">Click</div>
26+
<div className="text-xs">Select</div>
27+
</HelpItem>
28+
<MouseLeft />
29+
<HelpItem>
30+
<div className="text-xs text-neutral-500">Shift + Drag</div>
31+
<div className="text-xs">Range Select</div>
32+
</HelpItem>
33+
<MouseLeft />
34+
<HelpItem>
35+
<div className="text-xs text-neutral-500">Ctrl + Drag</div>
36+
<div className="text-xs">Rotate</div>
37+
</HelpItem>
38+
<MouseRight />
39+
<HelpItem>
40+
<div className="text-xs text-neutral-500">Drag</div>
41+
<div className="text-xs">Rotate</div>
42+
</HelpItem>
43+
<MouseWheel />
44+
<HelpItem last>
45+
<div className="text-xs text-neutral-500">Wheel</div>
46+
<div className="text-xs">Zoom</div>
47+
</HelpItem>
48+
</div>
49+
</div>
50+
);
51+
}

src/Elements/Icons.tsx

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,81 @@ export function TriangleFull(props: IconProps) {
114114
</svg>
115115
);
116116
}
117+
118+
export function MouseLeft(props: IconProps) {
119+
return (
120+
<svg
121+
{...props}
122+
stroke="currentColor"
123+
fill="currentColor"
124+
strokeWidth="0"
125+
viewBox="0 0 16 16"
126+
height="1em"
127+
width="1em"
128+
xmlns="http://www.w3.org/2000/svg"
129+
>
130+
<path
131+
d="M 13 6.487 L 3 6.487 L 3 10.8 C 3 13.645 5.22 15.987 8 15.987 C 10.78 15.987 13 13.645 13 10.799 L 13 6.487 Z"
132+
style={{ fillOpacity: 0.3 }}
133+
></path>
134+
<path
135+
d="M 8.5 0.013 L 8.5 5.487 L 13 5.487 L 13 5.175 C 13 2.502 11.042 0.273 8.5 0.013 Z"
136+
style={{ fillOpacity: 0.3 }}
137+
></path>
138+
<path d="M 7.5 0.013 C 4.958 0.273 3 2.502 3 5.175 L 3 5.487 L 7.5 5.487 L 7.5 0.013 Z"></path>
139+
</svg>
140+
);
141+
}
142+
143+
export function MouseRight(props: IconProps) {
144+
return (
145+
<svg
146+
{...props}
147+
stroke="currentColor"
148+
fill="currentColor"
149+
strokeWidth="0"
150+
viewBox="0 0 16 16"
151+
height="1em"
152+
width="1em"
153+
xmlns="http://www.w3.org/2000/svg"
154+
>
155+
<path
156+
d="M 13 6.487 L 3 6.487 L 3 10.8 C 3 13.645 5.22 15.987 8 15.987 C 10.78 15.987 13 13.645 13 10.799 L 13 6.487 Z"
157+
style={{ fillOpacity: 0.3 }}
158+
></path>
159+
<path d="M 8.5 0.013 L 8.5 5.487 L 13 5.487 L 13 5.175 C 13 2.502 11.042 0.273 8.5 0.013 Z"></path>
160+
<path
161+
d="M 7.5 0.013 C 4.958 0.273 3 2.502 3 5.175 L 3 5.487 L 7.5 5.487 L 7.5 0.013 Z"
162+
style={{ fillOpacity: 0.3 }}
163+
></path>
164+
</svg>
165+
);
166+
}
167+
168+
export function MouseWheel(props: IconProps) {
169+
return (
170+
<svg
171+
{...props}
172+
stroke="currentColor"
173+
fill="currentColor"
174+
strokeWidth="0"
175+
viewBox="0 0 16 16"
176+
height="1em"
177+
width="1em"
178+
xmlns="http://www.w3.org/2000/svg"
179+
>
180+
<path
181+
d="M 13 6.487 L 3 6.487 L 3 10.8 C 3 13.645 5.22 15.987 8 15.987 C 10.78 15.987 13 13.645 13 10.799 L 13 6.487 Z"
182+
style={{ fillOpacity: 0.3 }}
183+
></path>
184+
<path
185+
d="M 8.5 0.013 L 8.5 5.487 L 13 5.487 L 13 5.175 C 13 2.502 11.042 0.273 8.5 0.013 Z"
186+
style={{ fillOpacity: 0.3 }}
187+
></path>
188+
<path
189+
d="M 7.5 0.013 C 4.958 0.273 3 2.502 3 5.175 L 3 5.487 L 7.5 5.487 L 7.5 0.013 Z"
190+
style={{ fillOpacity: 0.3 }}
191+
></path>
192+
</svg>
193+
);
194+
}

src/Elements/Input.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export function Input(props: React.InputHTMLAttributes<HTMLInputElement>) {
66
return (
77
<input
88
{...props}
9-
className={clsx(className, 'focus:bg-amber-100 outline-none')}
9+
className={clsx(className, 'bg-white bg-opacity-50 focus:bg-amber-100 outline-none')}
1010
onKeyDown={(e) => e.stopPropagation()}
1111
onClick={(e) => e.stopPropagation()}
1212
/>

src/bananagl/bananagl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ProjectionType } from './camera/camera';
1+
import { ProjectionType } from './camera/cameraInterface';
22
import { CameraView } from './camera/cameraLock';
33
import { Attribute, ElementAttribute, InstancedAttribute } from './models/attribute';
44
import { Attributes } from './models/attributes';

src/bananagl/camera/camera.ts

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,9 @@
1-
import { mat4, quat, vec2, vec3, vec4 } from 'gl-matrix';
1+
import { mat4, quat, vec2, vec3 } from 'gl-matrix';
22

33
import { Ray } from '@bananagl/picking/ray';
44
import { UniformValue } from '@bananagl/shaders/shader';
55

6-
export enum ProjectionType {
7-
PERSPECTIVE,
8-
ORTHOGRAPHIC,
9-
}
10-
11-
const EPSILON = 0.000001;
12-
13-
export interface CameraOptions {
14-
position?: vec3;
15-
target?: vec3;
16-
up?: vec3;
17-
right?: vec3;
18-
projectionType?: ProjectionType;
19-
fovYRadian?: number;
20-
width?: number;
21-
height?: number;
22-
near?: number;
23-
far?: number;
24-
}
6+
import { CameraOptions, ProjectionType } from './cameraInterface';
257

268
export class Camera {
279
position: vec3;
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { vec3 } from 'gl-matrix';
2+
3+
/**
4+
* An enumeration of the types of projections that can be used for rendering a scene.
5+
*/
6+
export enum ProjectionType {
7+
/**
8+
* A perspective projection, which simulates the way objects appear smaller as they move farther away.
9+
*/
10+
PERSPECTIVE,
11+
12+
/**
13+
* An orthographic projection, which maintains the relative size of objects regardless of their distance from the camera.
14+
*/
15+
ORTHOGRAPHIC,
16+
}
17+
18+
/**
19+
* An interface representing the options that can be passed to a `Camera` constructor.
20+
*/
21+
export interface CameraOptions {
22+
/**
23+
* The position of the camera in 3D space.
24+
*/
25+
position?: vec3;
26+
27+
/**
28+
* The point in 3D space that the camera is looking at.
29+
*/
30+
target?: vec3;
31+
32+
/**
33+
* The up vector of the camera.
34+
*/
35+
up?: vec3;
36+
37+
/**
38+
* The right vector of the camera.
39+
*/
40+
right?: vec3;
41+
42+
/**
43+
* The type of projection to use for rendering the scene.
44+
*/
45+
projectionType?: ProjectionType;
46+
47+
/**
48+
* The vertical field of view angle in radians.
49+
*/
50+
fovYRadian?: number;
51+
52+
/**
53+
* The width of the viewport in pixels.
54+
*/
55+
width?: number;
56+
57+
/**
58+
* The height of the viewport in pixels.
59+
*/
60+
height?: number;
61+
62+
/**
63+
* The distance to the near clipping plane.
64+
*/
65+
near?: number;
66+
67+
/**
68+
* The distance to the far clipping plane.
69+
*/
70+
far?: number;
71+
}

0 commit comments

Comments
 (0)