@@ -11,8 +11,10 @@
|
||||
import HelpView from "../components/HelpView.svelte";
|
||||
import { getGraphManager, getGraphState } from "../graph-state.svelte";
|
||||
import { HTML } from "@threlte/extras";
|
||||
import { FileDropEventManager, MouseEventManager } from "./events";
|
||||
import { maxZoom, minZoom } from "./constants";
|
||||
import Debug from "../debug/Debug.svelte";
|
||||
import { FileDropEventManager } from "./drop.events";
|
||||
import { MouseEventManager } from "./mouse.events";
|
||||
|
||||
const {
|
||||
keymap,
|
||||
@@ -174,9 +176,18 @@
|
||||
|
||||
{#each graph.edges as edge}
|
||||
{@const [x1, y1, x2, y2] = getEdgePosition(edge)}
|
||||
<EdgeEl z={graphState.cameraPosition[2]} {x1} {y1} {x2} {y2} />
|
||||
<EdgeEl
|
||||
id={graph.getEdgeId(edge)}
|
||||
z={graphState.cameraPosition[2]}
|
||||
{x1}
|
||||
{y1}
|
||||
{x2}
|
||||
{y2}
|
||||
/>
|
||||
{/each}
|
||||
|
||||
<Debug />
|
||||
|
||||
<HTML transform={false}>
|
||||
<div
|
||||
role="tree"
|
||||
|
||||
107
app/src/lib/graph-interface/graph/drop.events.ts
Normal file
107
app/src/lib/graph-interface/graph/drop.events.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { GraphSchema, type NodeId } from '@nodarium/types';
|
||||
import type { GraphManager } from '../graph-manager.svelte';
|
||||
import type { GraphState } from '../graph-state.svelte';
|
||||
|
||||
export class FileDropEventManager {
|
||||
constructor(
|
||||
private graph: GraphManager,
|
||||
private state: GraphState
|
||||
) { }
|
||||
|
||||
handleFileDrop(event: DragEvent) {
|
||||
event.preventDefault();
|
||||
this.state.isDragging = false;
|
||||
if (!event.dataTransfer) return;
|
||||
const nodeId = event.dataTransfer.getData('data/node-id') as NodeId;
|
||||
let mx = event.clientX - this.state.rect.x;
|
||||
let my = event.clientY - this.state.rect.y;
|
||||
|
||||
if (nodeId) {
|
||||
let nodeOffsetX = event.dataTransfer.getData('data/node-offset-x');
|
||||
let nodeOffsetY = event.dataTransfer.getData('data/node-offset-y');
|
||||
if (nodeOffsetX && nodeOffsetY) {
|
||||
mx += parseInt(nodeOffsetX);
|
||||
my += parseInt(nodeOffsetY);
|
||||
}
|
||||
|
||||
let props = {};
|
||||
let rawNodeProps = event.dataTransfer.getData('data/node-props');
|
||||
if (rawNodeProps) {
|
||||
try {
|
||||
props = JSON.parse(rawNodeProps);
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
const pos = this.state.projectScreenToWorld(mx, my);
|
||||
this.graph.registry.load([nodeId]).then(() => {
|
||||
this.graph.createNode({
|
||||
type: nodeId,
|
||||
props,
|
||||
position: pos
|
||||
});
|
||||
});
|
||||
} else if (event.dataTransfer.files.length) {
|
||||
const file = event.dataTransfer.files[0];
|
||||
|
||||
if (file.type === 'application/wasm') {
|
||||
const reader = new FileReader();
|
||||
reader.onload = async (e) => {
|
||||
const buffer = e.target?.result;
|
||||
if (buffer?.constructor === ArrayBuffer) {
|
||||
const nodeType = await this.graph.registry.register(buffer);
|
||||
|
||||
this.graph.createNode({
|
||||
type: nodeType.id,
|
||||
props: {},
|
||||
position: this.state.projectScreenToWorld(mx, my)
|
||||
});
|
||||
}
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
} else if (file.type === 'application/json') {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
const buffer = e.target?.result as ArrayBuffer;
|
||||
if (buffer) {
|
||||
const state = GraphSchema.parse(JSON.parse(buffer.toString()));
|
||||
this.graph.load(state);
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleMouseLeave() {
|
||||
this.state.isDragging = false;
|
||||
this.state.isPanning = false;
|
||||
}
|
||||
|
||||
handleDragEnter(e: DragEvent) {
|
||||
e.preventDefault();
|
||||
this.state.isDragging = true;
|
||||
this.state.isPanning = false;
|
||||
}
|
||||
|
||||
handleDragOver(e: DragEvent) {
|
||||
e.preventDefault();
|
||||
this.state.isDragging = true;
|
||||
this.state.isPanning = false;
|
||||
}
|
||||
|
||||
handleDragEnd(e: DragEvent) {
|
||||
e.preventDefault();
|
||||
this.state.isDragging = true;
|
||||
this.state.isPanning = false;
|
||||
}
|
||||
|
||||
getEventListenerProps() {
|
||||
return {
|
||||
ondragenter: (ev: DragEvent) => this.handleDragEnter(ev),
|
||||
ondragover: (ev: DragEvent) => this.handleDragOver(ev),
|
||||
ondragexit: (ev: DragEvent) => this.handleDragEnd(ev),
|
||||
ondrop: (ev: DragEvent) => this.handleFileDrop(ev),
|
||||
onmouseleave: () => this.handleMouseLeave()
|
||||
};
|
||||
}
|
||||
}
|
||||
110
app/src/lib/graph-interface/graph/edge.events.ts
Normal file
110
app/src/lib/graph-interface/graph/edge.events.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import type { Box } from '@nodarium/types';
|
||||
import type { GraphManager } from '../graph-manager.svelte';
|
||||
import type { GraphState } from '../graph-state.svelte';
|
||||
import { distanceFromPointToSegment } from '../helpers';
|
||||
|
||||
export class EdgeInteractionManager {
|
||||
constructor(
|
||||
private graph: GraphManager,
|
||||
private state: GraphState
|
||||
) { }
|
||||
|
||||
private MIN_DISTANCE = 3;
|
||||
|
||||
private _boundingBoxes = new Map<string, Box>();
|
||||
|
||||
handleMouseDown() {
|
||||
this._boundingBoxes.clear();
|
||||
|
||||
const possibleEdges = this.graph
|
||||
.getPossibleDropOnEdges(this.state.activeNodeId)
|
||||
.map(e => this.graph.getEdgeId(e));
|
||||
|
||||
const edges = this.state.getEdges();
|
||||
for (const edge of edges) {
|
||||
const edgeId = edge[0];
|
||||
if (!possibleEdges.includes(edgeId)) {
|
||||
edges.delete(edgeId);
|
||||
}
|
||||
}
|
||||
|
||||
for (const [edgeId, data] of edges) {
|
||||
const points = data.points;
|
||||
let minX = points[0].x + data.x1;
|
||||
let maxX = points[0].x + data.x1;
|
||||
let minY = points[0].z + data.y1;
|
||||
let maxY = points[0].z + data.y1;
|
||||
|
||||
// Iterate through all points to find the true bounds
|
||||
for (let i = 0; i < points.length; i++) {
|
||||
const x = data.x1 + points[i].x;
|
||||
const y = data.y1 + points[i].z;
|
||||
if (x < minX) minX = x;
|
||||
if (x > maxX) maxX = x;
|
||||
if (y < minY) minY = y;
|
||||
if (y > maxY) maxY = y;
|
||||
}
|
||||
|
||||
const boundingBox = {
|
||||
minX: minX - this.MIN_DISTANCE,
|
||||
maxX: maxX + this.MIN_DISTANCE,
|
||||
minY: minY - this.MIN_DISTANCE,
|
||||
maxY: maxY + this.MIN_DISTANCE
|
||||
};
|
||||
|
||||
this._boundingBoxes.set(edgeId, boundingBox);
|
||||
}
|
||||
}
|
||||
|
||||
handleMouseMove() {
|
||||
const [mouseX, mouseY] = this.state.mousePosition;
|
||||
const hoveredEdgeIds: string[] = [];
|
||||
|
||||
const edges = this.state.getEdges();
|
||||
|
||||
// Check if mouse is inside any bounding box
|
||||
for (const [edgeId, box] of this._boundingBoxes) {
|
||||
const isInside = mouseX >= box.minX
|
||||
&& mouseX <= box.maxX
|
||||
&& mouseY >= box.minY
|
||||
&& mouseY <= box.maxY;
|
||||
|
||||
if (isInside) {
|
||||
hoveredEdgeIds.push(edgeId);
|
||||
}
|
||||
}
|
||||
|
||||
let hoveredEdgeId: string | null = null;
|
||||
let hoveredEdgeDistance = Infinity;
|
||||
|
||||
const DENSITY = 10; // higher DENSITY = less points checked (yes density might not be the best name :-)
|
||||
for (const edgeId of hoveredEdgeIds) {
|
||||
const edge = edges.get(edgeId)!;
|
||||
for (let i = 0; i < edge.points.length - DENSITY; i += DENSITY) {
|
||||
const pointAx = edge.points[i].x + edge.x1;
|
||||
const pointAy = edge.points[i].z + edge.y1;
|
||||
const pointBx = edge.points[i + DENSITY].x + edge.x1;
|
||||
const pointBy = edge.points[i + DENSITY].z + edge.y1;
|
||||
const distance = distanceFromPointToSegment(pointAx, pointAy, pointBx, pointBy, mouseX, mouseY);
|
||||
if (distance < this.MIN_DISTANCE) {
|
||||
if (distance < hoveredEdgeDistance) {
|
||||
hoveredEdgeDistance = distance;
|
||||
hoveredEdgeId = edgeId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.state.hoveredEdgeId = hoveredEdgeId;
|
||||
}
|
||||
|
||||
handleMouseUp() {
|
||||
if (this.state.hoveredEdgeId) {
|
||||
const edge = this.graph.getEdgeById(this.state.hoveredEdgeId);
|
||||
if (edge) {
|
||||
this.graph.dropNodeOnEdge(this.state.activeNodeId, edge);
|
||||
}
|
||||
this.state.hoveredEdgeId = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,144 +1,18 @@
|
||||
import { GraphSchema, type NodeId, type NodeInstance } from "@nodarium/types";
|
||||
import type { GraphManager } from "../graph-manager.svelte";
|
||||
import type { GraphState } from "../graph-state.svelte";
|
||||
import { animate, lerp } from "$lib/helpers";
|
||||
import { snapToGrid as snapPointToGrid } from "../helpers";
|
||||
import { maxZoom, minZoom, zoomSpeed } from "./constants";
|
||||
|
||||
|
||||
export class FileDropEventManager {
|
||||
|
||||
constructor(
|
||||
private graph: GraphManager,
|
||||
private state: GraphState
|
||||
) { }
|
||||
|
||||
handleFileDrop(event: DragEvent) {
|
||||
event.preventDefault();
|
||||
this.state.isDragging = false;
|
||||
if (!event.dataTransfer) return;
|
||||
const nodeId = event.dataTransfer.getData("data/node-id") as NodeId;
|
||||
let mx = event.clientX - this.state.rect.x;
|
||||
let my = event.clientY - this.state.rect.y;
|
||||
|
||||
if (nodeId) {
|
||||
let nodeOffsetX = event.dataTransfer.getData("data/node-offset-x");
|
||||
let nodeOffsetY = event.dataTransfer.getData("data/node-offset-y");
|
||||
if (nodeOffsetX && nodeOffsetY) {
|
||||
mx += parseInt(nodeOffsetX);
|
||||
my += parseInt(nodeOffsetY);
|
||||
}
|
||||
|
||||
let props = {};
|
||||
let rawNodeProps = event.dataTransfer.getData("data/node-props");
|
||||
if (rawNodeProps) {
|
||||
try {
|
||||
props = JSON.parse(rawNodeProps);
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
const pos = this.state.projectScreenToWorld(mx, my);
|
||||
this.graph.registry.load([nodeId]).then(() => {
|
||||
this.graph.createNode({
|
||||
type: nodeId,
|
||||
props,
|
||||
position: pos,
|
||||
});
|
||||
});
|
||||
} else if (event.dataTransfer.files.length) {
|
||||
const file = event.dataTransfer.files[0];
|
||||
|
||||
if (file.type === "application/wasm") {
|
||||
const reader = new FileReader();
|
||||
reader.onload = async (e) => {
|
||||
const buffer = e.target?.result;
|
||||
if (buffer?.constructor === ArrayBuffer) {
|
||||
const nodeType = await this.graph.registry.register(buffer);
|
||||
|
||||
this.graph.createNode({
|
||||
type: nodeType.id,
|
||||
props: {},
|
||||
position: this.state.projectScreenToWorld(mx, my),
|
||||
});
|
||||
}
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
} else if (file.type === "application/json") {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
const buffer = e.target?.result as ArrayBuffer;
|
||||
if (buffer) {
|
||||
const state = GraphSchema.parse(JSON.parse(buffer.toString()));
|
||||
this.graph.load(state);
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleMouseLeave() {
|
||||
this.state.isDragging = false;
|
||||
this.state.isPanning = false;
|
||||
}
|
||||
|
||||
handleDragEnter(e: DragEvent) {
|
||||
e.preventDefault();
|
||||
this.state.isDragging = true;
|
||||
this.state.isPanning = false;
|
||||
}
|
||||
|
||||
handleDragOver(e: DragEvent) {
|
||||
e.preventDefault();
|
||||
this.state.isDragging = true;
|
||||
this.state.isPanning = false;
|
||||
}
|
||||
|
||||
handleDragEnd(e: DragEvent) {
|
||||
e.preventDefault();
|
||||
this.state.isDragging = true;
|
||||
this.state.isPanning = false;
|
||||
}
|
||||
|
||||
getEventListenerProps() {
|
||||
return {
|
||||
ondragenter: (ev: DragEvent) => this.handleDragEnter(ev),
|
||||
ondragover: (ev: DragEvent) => this.handleDragOver(ev),
|
||||
ondragexit: (ev: DragEvent) => this.handleDragEnd(ev),
|
||||
ondrop: (ev: DragEvent) => this.handleFileDrop(ev),
|
||||
onmouseleave: () => this.handleMouseLeave(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class EdgeInteractionManager {
|
||||
constructor(
|
||||
private graph: GraphManager,
|
||||
private state: GraphState) { };
|
||||
|
||||
handleMouseDown() {
|
||||
const edges = this.graph.edges;
|
||||
console.log(edges)
|
||||
}
|
||||
|
||||
handleMouseMove() {
|
||||
}
|
||||
|
||||
handleMouseUp() {
|
||||
}
|
||||
}
|
||||
|
||||
import { animate, lerp } from '$lib/helpers';
|
||||
import { type NodeInstance } from '@nodarium/types';
|
||||
import type { GraphManager } from '../graph-manager.svelte';
|
||||
import type { GraphState } from '../graph-state.svelte';
|
||||
import { snapToGrid as snapPointToGrid } from '../helpers';
|
||||
import { maxZoom, minZoom, zoomSpeed } from './constants';
|
||||
import { EdgeInteractionManager } from './edge.events';
|
||||
|
||||
export class MouseEventManager {
|
||||
|
||||
edgeInteractionManager: EdgeInteractionManager
|
||||
edgeInteractionManager: EdgeInteractionManager;
|
||||
|
||||
constructor(
|
||||
private graph: GraphManager,
|
||||
private state: GraphState
|
||||
) {
|
||||
|
||||
this.edgeInteractionManager = new EdgeInteractionManager(graph, state);
|
||||
}
|
||||
|
||||
@@ -167,25 +41,23 @@ export class MouseEventManager {
|
||||
const snapLevel = this.state.getSnapLevel();
|
||||
activeNode.position[0] = snapPointToGrid(
|
||||
activeNode?.state?.x ?? activeNode.position[0],
|
||||
5 / snapLevel,
|
||||
5 / snapLevel
|
||||
);
|
||||
activeNode.position[1] = snapPointToGrid(
|
||||
activeNode?.state?.y ?? activeNode.position[1],
|
||||
5 / snapLevel,
|
||||
5 / snapLevel
|
||||
);
|
||||
} else {
|
||||
activeNode.position[0] = activeNode?.state?.x ?? activeNode.position[0];
|
||||
activeNode.position[1] = activeNode?.state?.y ?? activeNode.position[1];
|
||||
}
|
||||
const nodes = [
|
||||
...[...(this.state.selectedNodes?.values() || [])].map((id) =>
|
||||
this.graph.getNode(id),
|
||||
),
|
||||
...[...(this.state.selectedNodes?.values() || [])].map((id) => this.graph.getNode(id))
|
||||
] as NodeInstance[];
|
||||
|
||||
const vec = [
|
||||
activeNode.position[0] - (activeNode?.state.x || 0),
|
||||
activeNode.position[1] - (activeNode?.state.y || 0),
|
||||
activeNode.position[1] - (activeNode?.state.y || 0)
|
||||
];
|
||||
|
||||
for (const node of nodes) {
|
||||
@@ -201,9 +73,9 @@ export class MouseEventManager {
|
||||
animate(500, (a: number) => {
|
||||
for (const node of nodes) {
|
||||
if (
|
||||
node?.state &&
|
||||
node.state["x"] !== undefined &&
|
||||
node.state["y"] !== undefined
|
||||
node?.state
|
||||
&& node.state['x'] !== undefined
|
||||
&& node.state['y'] !== undefined
|
||||
) {
|
||||
node.state.x = lerp(node.state.x, node.position[0], a);
|
||||
node.state.y = lerp(node.state.y, node.position[1], a);
|
||||
@@ -217,24 +89,24 @@ export class MouseEventManager {
|
||||
this.graph.save();
|
||||
} else if (this.state.hoveredSocket && this.state.activeSocket) {
|
||||
if (
|
||||
typeof this.state.hoveredSocket.index === "number" &&
|
||||
typeof this.state.activeSocket.index === "string"
|
||||
typeof this.state.hoveredSocket.index === 'number'
|
||||
&& typeof this.state.activeSocket.index === 'string'
|
||||
) {
|
||||
this.graph.createEdge(
|
||||
this.state.hoveredSocket.node,
|
||||
this.state.hoveredSocket.index || 0,
|
||||
this.state.activeSocket.node,
|
||||
this.state.activeSocket.index,
|
||||
this.state.activeSocket.index
|
||||
);
|
||||
} else if (
|
||||
typeof this.state.activeSocket.index == "number" &&
|
||||
typeof this.state.hoveredSocket.index === "string"
|
||||
typeof this.state.activeSocket.index == 'number'
|
||||
&& typeof this.state.hoveredSocket.index === 'string'
|
||||
) {
|
||||
this.graph.createEdge(
|
||||
this.state.activeSocket.node,
|
||||
this.state.activeSocket.index || 0,
|
||||
this.state.hoveredSocket.node,
|
||||
this.state.hoveredSocket.index,
|
||||
this.state.hoveredSocket.index
|
||||
);
|
||||
}
|
||||
this.graph.save();
|
||||
@@ -242,18 +114,18 @@ export class MouseEventManager {
|
||||
// Handle automatic adding of nodes on ctrl+mouseUp
|
||||
this.state.edgeEndPosition = [
|
||||
this.state.mousePosition[0],
|
||||
this.state.mousePosition[1],
|
||||
this.state.mousePosition[1]
|
||||
];
|
||||
|
||||
if (typeof this.state.activeSocket.index === "number") {
|
||||
if (typeof this.state.activeSocket.index === 'number') {
|
||||
this.state.addMenuPosition = [
|
||||
this.state.mousePosition[0],
|
||||
this.state.mousePosition[1] - 25 / this.state.cameraPosition[2],
|
||||
this.state.mousePosition[1] - 25 / this.state.cameraPosition[2]
|
||||
];
|
||||
} else {
|
||||
this.state.addMenuPosition = [
|
||||
this.state.mousePosition[0] - 155 / this.state.cameraPosition[2],
|
||||
this.state.mousePosition[1] - 25 / this.state.cameraPosition[2],
|
||||
this.state.mousePosition[1] - 25 / this.state.cameraPosition[2]
|
||||
];
|
||||
}
|
||||
return;
|
||||
@@ -261,11 +133,11 @@ export class MouseEventManager {
|
||||
|
||||
// check if camera moved
|
||||
if (
|
||||
clickedNodeId === -1 &&
|
||||
!this.state.boxSelection &&
|
||||
this.state.cameraDown[0] === this.state.cameraPosition[0] &&
|
||||
this.state.cameraDown[1] === this.state.cameraPosition[1] &&
|
||||
this.state.isBodyFocused()
|
||||
clickedNodeId === -1
|
||||
&& !this.state.boxSelection
|
||||
&& this.state.cameraDown[0] === this.state.cameraPosition[0]
|
||||
&& this.state.cameraDown[1] === this.state.cameraPosition[1]
|
||||
&& this.state.isBodyFocused()
|
||||
) {
|
||||
this.state.activeNodeId = -1;
|
||||
this.state.clearSelection();
|
||||
@@ -279,16 +151,15 @@ export class MouseEventManager {
|
||||
this.state.addMenuPosition = null;
|
||||
}
|
||||
|
||||
|
||||
handleMouseDown(event: MouseEvent) {
|
||||
if (this.state.mouseDown) return;
|
||||
this.state.edgeEndPosition = null;
|
||||
|
||||
if (event.target instanceof HTMLElement) {
|
||||
if (
|
||||
event.target.nodeName !== "CANVAS" &&
|
||||
!event.target.classList.contains("node") &&
|
||||
!event.target.classList.contains("content")
|
||||
event.target.nodeName !== 'CANVAS'
|
||||
&& !event.target.classList.contains('node')
|
||||
&& !event.target.classList.contains('content')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -310,7 +181,7 @@ export class MouseEventManager {
|
||||
this.state.activeNodeId = clickedNodeId;
|
||||
// if the selected node is the same as the clicked node
|
||||
} else if (this.state.activeNodeId === clickedNodeId) {
|
||||
//$activeNodeId = -1;
|
||||
// $activeNodeId = -1;
|
||||
// if the clicked node is different from the selected node and secondary
|
||||
} else if (event.ctrlKey) {
|
||||
this.state.selectedNodes.add(this.state.activeNodeId);
|
||||
@@ -358,7 +229,6 @@ export class MouseEventManager {
|
||||
this.state.edgeEndPosition = null;
|
||||
}
|
||||
|
||||
|
||||
handleMouseMove(event: MouseEvent) {
|
||||
let mx = event.clientX - this.state.rect.x;
|
||||
let my = event.clientY - this.state.rect.y;
|
||||
@@ -374,8 +244,8 @@ export class MouseEventManager {
|
||||
let _socket;
|
||||
for (const socket of this.state.possibleSockets) {
|
||||
const dist = Math.sqrt(
|
||||
(socket.position[0] - this.state.mousePosition[0]) ** 2 +
|
||||
(socket.position[1] - this.state.mousePosition[1]) ** 2,
|
||||
(socket.position[0] - this.state.mousePosition[0]) ** 2
|
||||
+ (socket.position[1] - this.state.mousePosition[1]) ** 2
|
||||
);
|
||||
if (dist < smallestDist) {
|
||||
smallestDist = dist;
|
||||
@@ -398,7 +268,7 @@ export class MouseEventManager {
|
||||
event.stopPropagation();
|
||||
const mouseD = this.state.projectScreenToWorld(
|
||||
this.state.mouseDown[0],
|
||||
this.state.mouseDown[1],
|
||||
this.state.mouseDown[1]
|
||||
);
|
||||
const x1 = Math.min(mouseD[0], this.state.mousePosition[0]);
|
||||
const x2 = Math.max(mouseD[0], this.state.mousePosition[0]);
|
||||
@@ -429,10 +299,8 @@ export class MouseEventManager {
|
||||
const oldX = node.state.downX || 0;
|
||||
const oldY = node.state.downY || 0;
|
||||
|
||||
let newX =
|
||||
oldX + (mx - this.state.mouseDown[0]) / this.state.cameraPosition[2];
|
||||
let newY =
|
||||
oldY + (my - this.state.mouseDown[1]) / this.state.cameraPosition[2];
|
||||
let newX = oldX + (mx - this.state.mouseDown[0]) / this.state.cameraPosition[2];
|
||||
let newY = oldY + (my - this.state.mouseDown[1]) / this.state.cameraPosition[2];
|
||||
|
||||
if (event.ctrlKey) {
|
||||
const snapLevel = this.state.getSnapLevel();
|
||||
@@ -472,23 +340,19 @@ export class MouseEventManager {
|
||||
|
||||
// here we are handling panning of camera
|
||||
this.state.isPanning = true;
|
||||
let newX =
|
||||
this.state.cameraDown[0] -
|
||||
(mx - this.state.mouseDown[0]) / this.state.cameraPosition[2];
|
||||
let newY =
|
||||
this.state.cameraDown[1] -
|
||||
(my - this.state.mouseDown[1]) / this.state.cameraPosition[2];
|
||||
let newX = this.state.cameraDown[0]
|
||||
- (mx - this.state.mouseDown[0]) / this.state.cameraPosition[2];
|
||||
let newY = this.state.cameraDown[1]
|
||||
- (my - this.state.mouseDown[1]) / this.state.cameraPosition[2];
|
||||
|
||||
this.state.cameraPosition[0] = newX;
|
||||
this.state.cameraPosition[1] = newY;
|
||||
}
|
||||
|
||||
|
||||
handleMouseScroll(event: WheelEvent) {
|
||||
const bodyIsFocused =
|
||||
document.activeElement === document.body ||
|
||||
document.activeElement === this.state.wrapper ||
|
||||
document?.activeElement?.id === "graph";
|
||||
const bodyIsFocused = document.activeElement === document.body
|
||||
|| document.activeElement === this.state.wrapper
|
||||
|| document?.activeElement?.id === 'graph';
|
||||
if (!bodyIsFocused) return;
|
||||
|
||||
// Define zoom speed and clamp it between -1 and 1
|
||||
@@ -503,21 +367,19 @@ export class MouseEventManager {
|
||||
maxZoom,
|
||||
isNegative
|
||||
? this.state.cameraPosition[2] / delta
|
||||
: this.state.cameraPosition[2] * delta,
|
||||
),
|
||||
: this.state.cameraPosition[2] * delta
|
||||
)
|
||||
);
|
||||
|
||||
// Calculate the ratio of the new zoom to the original zoom
|
||||
const zoomRatio = newZoom / this.state.cameraPosition[2];
|
||||
|
||||
// Update camera position and zoom level
|
||||
this.state.cameraPosition[0] = this.state.mousePosition[0] -
|
||||
(this.state.mousePosition[0] - this.state.cameraPosition[0]) /
|
||||
zoomRatio;
|
||||
this.state.cameraPosition[1] = this.state.mousePosition[1] -
|
||||
(this.state.mousePosition[1] - this.state.cameraPosition[1]) /
|
||||
zoomRatio,
|
||||
this.state.cameraPosition[2] = newZoom;
|
||||
this.state.cameraPosition[0] = this.state.mousePosition[0]
|
||||
- (this.state.mousePosition[0] - this.state.cameraPosition[0])
|
||||
/ zoomRatio;
|
||||
this.state.cameraPosition[1] = this.state.mousePosition[1]
|
||||
- (this.state.mousePosition[1] - this.state.cameraPosition[1])
|
||||
/ zoomRatio, this.state.cameraPosition[2] = newZoom;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user