diff --git a/package-lock.json b/package-lock.json index 60dd848..1389a32 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5609,11 +5609,6 @@ "invert-kv": "^1.0.0" } }, - "line-intersect": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/line-intersect/-/line-intersect-2.2.1.tgz", - "integrity": "sha512-uOPErCqtEnHYsnesl56XmKm9nWF27kOqZCuibJEkyAJ23FHsKmOHo8FPT6SRAp2h3wzvyXJNjbPsq9FF5x29vw==" - }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", diff --git a/package.json b/package.json index 1b2115b..caedf60 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "dependencies": { "@eix-js/utils": "0.0.6", "deepmerge": "^4.0.0", - "line-intersect": "^2.2.1", "mainloop.js": "^1.0.4", "react": "^16.8.6", "react-dom": "^16.8.6", diff --git a/src/modules/simulation/classes/Camera.ts b/src/modules/simulation/classes/Camera.ts index 1c0aee5..13c3112 100644 --- a/src/modules/simulation/classes/Camera.ts +++ b/src/modules/simulation/classes/Camera.ts @@ -1,13 +1,21 @@ import { Transform, vector2 } from './Transform' import { Screen } from '../../core/classes/Screen' +import { relativeTo } from '../../vector2/helpers/basic' export class Camera { private screen = new Screen() public transform = new Transform([0, 0], [this.screen.x, this.screen.y]) + public constructor() { + this.screen.height.subscribe(value => { + this.transform.height = value + }) + this.screen.width.subscribe(value => { + this.transform.width = value + }) + } + public toWordPostition(position: vector2) { - return position.map( - (value, index) => value + this.transform.position[index] - ) as vector2 + return relativeTo(this.transform.position, position) } } diff --git a/src/modules/simulation/classes/MouseManager.ts b/src/modules/simulation/classes/MouseManager.ts index b4e3fcf..fd11066 100644 --- a/src/modules/simulation/classes/MouseManager.ts +++ b/src/modules/simulation/classes/MouseManager.ts @@ -46,7 +46,10 @@ export class MouseManager { } public getDirection() { - return clamp(-1, 1, this.total / this.history.length) + if (this.history.length) { + return clamp(-1, 1, this.total / this.history.length) + } + return 0 } public update(maybeAgain = true) { diff --git a/src/modules/simulation/classes/SimulationRenderer.ts b/src/modules/simulation/classes/SimulationRenderer.ts index 36972a4..d4adcac 100644 --- a/src/modules/simulation/classes/SimulationRenderer.ts +++ b/src/modules/simulation/classes/SimulationRenderer.ts @@ -9,6 +9,7 @@ import { renderGate } from '../helpers/renderGate' import { renderGateShadow } from '../helpers/renderGateShadow' import { MouseManager } from './MouseManager' import { Screen } from '../../core/classes/Screen' +import { relativeTo, add, invert } from '../../vector2/helpers/basic' export interface SimulationRendererOptions { shadows: { @@ -27,7 +28,7 @@ export const defaultSimulationRendererOptions: SimulationRendererOptions = { enabled: true, color: 'rgba(0,0,0,0.3)', gateHeight: 10, - lightHeight: 50 + lightHeight: 100 }, dnd: { rotation: Math.PI / 12 // 7.5 degrees @@ -41,9 +42,13 @@ export class SimulationRenderer { public mouseMoveOutput = new Subject() public selectedGate: number | null = null - public selectOffset: vector2 = [0, 0] + public lastMousePosition: vector2 = [0, 0] public movedSelection = false + // first bit = dragging + // second bit = moving around + private mouseState = 0b00 + private options: SimulationRendererOptions private mouseManager = new MouseManager(this.mouseMoveOutput) private screen = new Screen() @@ -71,10 +76,11 @@ export class SimulationRenderer { if (pointInSquare(worldPosition, transform)) { this.mouseManager.clear(worldPosition[0]) + this.mouseState |= 1 this.movedSelection = false this.selectedGate = id - this.selectOffset = worldPosition.map( + this.lastMousePosition = worldPosition.map( (position, index) => position - transform.position[index] ) as vector2 @@ -84,8 +90,13 @@ export class SimulationRenderer { if (gateNode) { return this.simulation.gates.moveOnTop(gateNode) } + + return } } + + this.lastMousePosition = worldPosition + this.mouseState |= 2 }) this.mouseUpOutput.subscribe(event => { @@ -97,34 +108,56 @@ export class SimulationRenderer { } this.selectedGate = null + this.mouseState &= 0 } + + this.mouseState &= 0b00 }) this.mouseMoveOutput.subscribe(event => { - if (this.selectedGate !== null) { + const worldPosition = this.camera.toWordPostition(event.position) + + if (this.mouseState & 1 && this.selectedGate !== null) { const gate = this.getGateById(this.selectedGate) if (!gate || !gate.data) return const transform = gate.data.transform - const worldPosition = this.camera.toWordPostition( - event.position - ) - transform.x = worldPosition[0] - this.selectOffset[0] - transform.y = worldPosition[1] - this.selectOffset[1] + transform.x = worldPosition[0] - this.lastMousePosition[0] + transform.y = worldPosition[1] - this.lastMousePosition[1] if (!this.movedSelection) { this.movedSelection = true } } + + if ((this.mouseState >> 1) & 1) { + const offset = invert( + relativeTo(this.lastMousePosition, worldPosition) + ) + + this.camera.transform.position = add( + this.camera.transform.position, + invert(offset) + ) + + this.lastMousePosition = this.camera.toWordPostition( + event.position + ) + } }) } public render(ctx: CanvasRenderingContext2D) { this.clear(ctx) - const center = this.screen.center + ctx.translate(...this.camera.transform.position) + + const center = relativeTo( + this.camera.transform.position, + this.screen.center + ) // render gates for (const gate of this.simulation.gates) { @@ -140,11 +173,12 @@ export class SimulationRenderer { renderGate(ctx, gate) } + + ctx.translate(...invert(this.camera.transform.position)) } public clear(ctx: CanvasRenderingContext2D) { - const boundingBox = this.camera.transform.getBoundingBox() - ctx.clearRect(...boundingBox) + ctx.clearRect(0, 0, ...this.camera.transform.scale) } public getGateById(id: number) { @@ -159,6 +193,9 @@ export class SimulationRenderer { selected.transform.rotation = this.mouseManager.getDirection() * this.options.dnd.rotation } else { + if (selected) { + selected.transform.rotation = 0 + } this.mouseManager.update() } } diff --git a/src/modules/simulation/classes/Transform.ts b/src/modules/simulation/classes/Transform.ts index 1f1c604..0ae15cb 100644 --- a/src/modules/simulation/classes/Transform.ts +++ b/src/modules/simulation/classes/Transform.ts @@ -1,4 +1,3 @@ -import { BehaviorSubject } from 'rxjs' import { allCombinations } from '../helpers/allCombinations' import { rotateAroundVector } from '../../vector2/helpers/rotate' @@ -98,4 +97,12 @@ export class Transform { set y(value: number) { this.position = [this.x, value] } + + set width(value: number) { + this.scale = [value, this.height] + } + + set height(value: number) { + this.scale = [this.width, value] + } } diff --git a/src/modules/simulation/helpers/renderGateShadow.ts b/src/modules/simulation/helpers/renderGateShadow.ts index 3cd83ea..2e15b82 100644 --- a/src/modules/simulation/helpers/renderGateShadow.ts +++ b/src/modules/simulation/helpers/renderGateShadow.ts @@ -1,41 +1,7 @@ import { Gate } from '../classes/Gate' import { projectPointOnPlane } from './projectPoint' import { drawPolygon } from './drawPolygon' -import { vector3, vector2, vector4, vector8 } from '../classes/Transform' -import { checkIntersection } from 'line-intersect' -import { reverseArray } from './reverseArray' -import { minVector, maxVector } from '../../vector2/helpers/minmaxVector' -import { relativeTo } from '../../vector2/helpers/basic' - -export const pointRecivesLight = ( - points: vector2[], //this needs to have an even length - light: vector3, - index: number -) => { - const point = points[index] - const oposittePoint = points[(index + points.length / 2) % points.length] - - const edgesToCheck = [ - [oposittePoint, points[(index + 1) % points.length]], - [oposittePoint, points[index === 0 ? points.length - 1 : index - 1]] - ].map(points => points.flat() as vector4) - - for (const edge of edgesToCheck) { - const intersectionCheckParameters = [ - [light[0], light[1]], - point, - edge - ].flat() as vector8 - - const result = checkIntersection(...intersectionCheckParameters).type - - if (result === 'intersecting') { - return false - } - } - - return true -} +import { vector3 } from '../classes/Transform' export const renderGateShadow = ( ctx: CanvasRenderingContext2D, @@ -47,66 +13,9 @@ export const renderGateShadow = ( ctx.fillStyle = color const points = gate.transform.getPoints() - const exposedPoints = points.filter((point, index) => - pointRecivesLight(points, light, index) - ) - - let includedPoints = [...points] - - if (exposedPoints.length === 4) { - return - } - - if (exposedPoints.length === 3) { - const minimum = minVector( - ...exposedPoints.map(point => - relativeTo(point, light.slice(0, 2) as vector2) - ) - ) - - includedPoints.splice(includedPoints.indexOf(exposedPoints[minimum]), 1) - } - - if (includedPoints.length === 3) { - const maximum = maxVector( - ...includedPoints.map(point => - relativeTo(point, light.slice(0, 2) as vector2) - ) - ) - - const otherIndices = [(maximum + 1) % 3, (maximum + 2) % 3] - const newIndices = [otherIndices[0], maximum, otherIndices[1]] - - includedPoints = newIndices.map(index => includedPoints[index]) - } - - let projections = includedPoints.map(point => - // ts doesnt let me do [...point, gateHeight] + const projections = points.map(point => projectPointOnPlane([point[0], point[1], gateHeight], light) ) - if (exposedPoints.length === 2) { - const toProject = includedPoints.filter( - point => exposedPoints.indexOf(point) === -1 - ) - - projections = toProject.map(point => - projectPointOnPlane([point[0], point[1], gateHeight], light) - ) - - includedPoints = reverseArray(exposedPoints) - - const firstIncludedIndex = points.indexOf(toProject[0]) - const firstExposedPointIndex = points.indexOf(includedPoints[0]) - - if ((firstIncludedIndex + 2) % 4 === firstExposedPointIndex % 4) { - const temporary = includedPoints[0] - includedPoints[0] = includedPoints[1] - includedPoints[1] = temporary - } - } - - const polygon = [includedPoints, reverseArray(projections)].flat() - - drawPolygon(ctx, polygon) + drawPolygon(ctx, projections) } diff --git a/tsconfig.json b/tsconfig.json index 56cbcf8..20fb5c4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,5 @@ { "compilerOptions": { - "baseUrl": ".", - "paths": { "*": ["types/*"] }, "moduleResolution": "node", "esModuleInterop": true, "jsx": "preserve", diff --git a/types/line-intersect.d.ts b/types/line-intersect.d.ts deleted file mode 100644 index 899d62d..0000000 --- a/types/line-intersect.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -export const checkIntersection: ( - x1: number, - y1: number, - x2: number, - y2: number, - x3: number, - y3: number, - x4: number, - y4: number -) => { - type: 'colinear' | 'parallel' | 'none' | 'intersecting' -} -export const colinearPointWithinSegment: any