Skip to content

Commit

Permalink
[pr] laser
Browse files Browse the repository at this point in the history
  • Loading branch information
dwelle committed Oct 2, 2023
1 parent 7053f84 commit b492fc9
Show file tree
Hide file tree
Showing 18 changed files with 482 additions and 18 deletions.
2 changes: 1 addition & 1 deletion excalidraw-app/data/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export type SocketUpdateDataSource = {
type: "MOUSE_LOCATION";
payload: {
socketId: string;
pointer: { x: number; y: number };
pointer: { x: number; y: number; tool: "pointer" | "laser" };
button: "down" | "up";
selectedElementIds: AppState["selectedElementIds"];
username: string;
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
},
"dependencies": {
"@braintree/sanitize-url": "6.0.2",
"@excalidraw/laser-pointer": "1.0.1",
"@excalidraw/random-username": "1.0.0",
"@radix-ui/react-popover": "1.0.3",
"@radix-ui/react-tabs": "1.0.2",
Expand Down
8 changes: 8 additions & 0 deletions src/appState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,11 @@ export const isHandToolActive = ({
}) => {
return activeTool.type === "hand";
};

export const isLaserToolActive = ({
activeTool,
}: {
activeTool: AppState["activeTool"];
}) => {
return activeTool.type === "laser";
};
23 changes: 22 additions & 1 deletion src/components/Actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ import {

import "./Actions.scss";
import DropdownMenu from "./dropdownMenu/DropdownMenu";
import { EmbedIcon, extraToolsIcon, frameToolIcon } from "./icons";
import {
EmbedIcon,
extraToolsIcon,
frameToolIcon,
laserPointerToolIcon,
} from "./icons";
import { KEYS } from "../keys";

export const SelectedShapeActions = ({
Expand Down Expand Up @@ -397,6 +402,22 @@ export const ShapesSwitcher = ({
>
{t("toolBar.embeddable")}
</DropdownMenu.Item>
<DropdownMenu.Item
onSelect={() => {
const nextActiveTool = updateActiveTool(appState, {
type: "laser",
});
setAppState({
activeTool: nextActiveTool,
multiElement: null,
selectedElementIds: {},
});
}}
icon={laserPointerToolIcon}
data-testid="toolbar-laser"
>
{t("toolBar.laser")}
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu>
)}
Expand Down
50 changes: 44 additions & 6 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ import {
SidebarName,
SidebarTabName,
KeyboardModifiersObject,
CollaboratorPointer,
} from "../types";
import {
debounce,
Expand Down Expand Up @@ -369,6 +370,8 @@ import { StaticCanvas, InteractiveCanvas } from "./canvases";
import { Renderer } from "../scene/Renderer";
import { ShapeCache } from "../scene/ShapeCache";
import { Emitter } from "../emitter";
import { LaserToolOverlay } from "./LaserTool/LaserTool";
import { LaserPathManager } from "./LaserTool/LaserPathManager";

const AppContext = React.createContext<AppClassProperties>(null!);
const AppPropsContext = React.createContext<AppProps>(null!);
Expand Down Expand Up @@ -496,6 +499,7 @@ class App extends React.Component<AppProps, AppState> {
lastPointerDown: React.PointerEvent<HTMLElement> | null = null;
lastPointerUp: React.PointerEvent<HTMLElement> | PointerEvent | null = null;
lastViewportPosition = { x: 0, y: 0 };
laserPathManager: LaserPathManager = new LaserPathManager(this);

onChangeEmitter = new Emitter<
[
Expand Down Expand Up @@ -1219,6 +1223,7 @@ class App extends React.Component<AppProps, AppState> {
onLockToggle={this.toggleLock}
onPenModeToggle={this.togglePenMode}
onHandToolToggle={this.onHandToolToggle}
onLaserToolToggle={this.onLaserToolToggle}
langCode={getLanguage().code}
renderCustomStats={renderCustomStats}
showExitZenModeBtn={
Expand All @@ -1237,12 +1242,14 @@ class App extends React.Component<AppProps, AppState> {
}
app={this}
renderTopRightUI={renderTopRightUI}
isCollaborating={this.props.isCollaborating}
>
{this.props.children}
</LayerUI>
<div className="excalidraw-textEditorContainer" />
<div className="excalidraw-contextMenuContainer" />
<div className="excalidraw-eye-dropper-container" />
<LaserToolOverlay manager={this.laserPathManager} />
{selectedElements.length === 1 &&
!this.state.contextMenu &&
this.state.showHyperlinkPopup && (
Expand Down Expand Up @@ -2652,6 +2659,16 @@ class App extends React.Component<AppProps, AppState> {
this.actionManager.executeAction(actionToggleHandTool);
};

onLaserToolToggle = () => {
this.setState((prevState) => ({
activeTool: updateActiveTool(prevState, {
type: "laser",
}),
multiElement: null,
selectedElementIds: {},
}));
};

/**
* Zooms on canvas viewport center
*/
Expand Down Expand Up @@ -3204,6 +3221,7 @@ class App extends React.Component<AppProps, AppState> {
| "eraser"
| "hand"
| "frame"
| "laser"
| "embeddable";
locked?: boolean;
}
Expand Down Expand Up @@ -4546,17 +4564,17 @@ class App extends React.Component<AppProps, AppState> {
return;
}

if (this.handleCanvasPanUsingWheelOrSpaceDrag(event)) {
return;
}

this.lastPointerDown = event;
this.setState({
lastPointerDownWith: event.pointerType,
cursorButton: "down",
});
this.savePointer(event.clientX, event.clientY, "down");

if (this.handleCanvasPanUsingWheelOrSpaceDrag(event)) {
return;
}

// only handle left mouse button or touch
if (
event.button !== POINTER_BUTTON.MAIN &&
Expand Down Expand Up @@ -4651,6 +4669,11 @@ class App extends React.Component<AppProps, AppState> {
}
} else if (this.state.activeTool.type === "frame") {
this.createFrameElementOnPointerDown(pointerDownState);
} else if (this.state.activeTool.type === "laser") {
this.laserPathManager.startPath(
pointerDownState.lastCoords.x,
pointerDownState.lastCoords.y,
);
} else if (
this.state.activeTool.type !== "eraser" &&
this.state.activeTool.type !== "hand"
Expand Down Expand Up @@ -5867,6 +5890,10 @@ class App extends React.Component<AppProps, AppState> {
return;
}

if (this.state.activeTool.type === "laser") {
this.laserPathManager.addPointToPath(pointerCoords.x, pointerCoords.y);
}

const [gridX, gridY] = getGridPoint(
pointerCoords.x,
pointerCoords.y,
Expand Down Expand Up @@ -7116,6 +7143,11 @@ class App extends React.Component<AppProps, AppState> {
: unbindLinearElements)(this.scene.getSelectedElements(this.state));
}

if (activeTool.type === "laser") {
this.laserPathManager.endPath();
return;
}

if (!activeTool.locked && activeTool.type !== "freedraw") {
resetCursor(this.interactiveCanvas);
this.setState({
Expand Down Expand Up @@ -8358,15 +8390,21 @@ class App extends React.Component<AppProps, AppState> {
if (!x || !y) {
return;
}
const pointer = viewportCoordsToSceneCoords(
const { x: vx, y: vy } = viewportCoordsToSceneCoords(
{ clientX: x, clientY: y },
this.state,
);

if (isNaN(pointer.x) || isNaN(pointer.y)) {
if (isNaN(vx) || isNaN(vy)) {
// sometimes the pointer goes off screen
}

const pointer: CollaboratorPointer = {
x: vx,
y: vy,
tool: this.state.activeTool.type === "laser" ? "laser" : "pointer",
};

this.props.onPointerUpdate?.({
pointer,
button,
Expand Down
Loading

0 comments on commit b492fc9

Please sign in to comment.