better spawning

This commit is contained in:
Matei Adriel 2019-07-24 12:44:00 +03:00
parent 27b68dccec
commit 145730434d
10 changed files with 122 additions and 12 deletions

62
package-lock.json generated
View file

@ -1886,6 +1886,11 @@
"integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==", "integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==",
"dev": true "dev": true
}, },
"add-px-to-style": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/add-px-to-style/-/add-px-to-style-1.0.0.tgz",
"integrity": "sha1-0ME1RB+oAUqBN5BFMQlvZ/KPJjo="
},
"ajv": { "ajv": {
"version": "6.10.0", "version": "6.10.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
@ -3712,6 +3717,16 @@
"utila": "~0.4" "utila": "~0.4"
} }
}, },
"dom-css": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/dom-css/-/dom-css-2.1.0.tgz",
"integrity": "sha1-/bwtWgFdCj4YcuEUcrvQ57nmogI=",
"requires": {
"add-px-to-style": "1.0.0",
"prefix-style": "2.0.1",
"to-camel-case": "1.0.0"
}
},
"dom-helpers": { "dom-helpers": {
"version": "3.4.0", "version": "3.4.0",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
@ -7593,8 +7608,7 @@
"performance-now": { "performance-now": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
"dev": true
}, },
"pify": { "pify": {
"version": "2.3.0", "version": "2.3.0",
@ -8257,6 +8271,11 @@
"integrity": "sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ==", "integrity": "sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ==",
"dev": true "dev": true
}, },
"prefix-style": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/prefix-style/-/prefix-style-2.0.1.tgz",
"integrity": "sha1-ZrupqHDP2jCKXcIOhekSCTLJWgY="
},
"prepend-http": { "prepend-http": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
@ -8428,6 +8447,14 @@
"integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==",
"dev": true "dev": true
}, },
"raf": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
"requires": {
"performance-now": "^2.1.0"
}
},
"randombytes": { "randombytes": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@ -8484,6 +8511,16 @@
"scheduler": "^0.13.6" "scheduler": "^0.13.6"
} }
}, },
"react-custom-scrollbars": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz",
"integrity": "sha1-gw/ZUCkn6X6KeMIIaBOJmyqLZts=",
"requires": {
"dom-css": "^2.0.0",
"prop-types": "^15.5.10",
"raf": "^3.1.0"
}
},
"react-dom": { "react-dom": {
"version": "16.8.6", "version": "16.8.6",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.6.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.6.tgz",
@ -10060,12 +10097,25 @@
"integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
"dev": true "dev": true
}, },
"to-camel-case": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/to-camel-case/-/to-camel-case-1.0.0.tgz",
"integrity": "sha1-GlYFSy+daWKYzmamCJcyK29CPkY=",
"requires": {
"to-space-case": "^1.0.0"
}
},
"to-fast-properties": { "to-fast-properties": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
"dev": true "dev": true
}, },
"to-no-case": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz",
"integrity": "sha1-xyKQcWTvaxeBMsjmmTAhLRtKoWo="
},
"to-object-path": { "to-object-path": {
"version": "0.3.0", "version": "0.3.0",
"resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
@ -10108,6 +10158,14 @@
"repeat-string": "^1.6.1" "repeat-string": "^1.6.1"
} }
}, },
"to-space-case": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz",
"integrity": "sha1-sFLar7Gysp3HcM6gFj5ewOvJ/Bc=",
"requires": {
"to-no-case": "^1.0.0"
}
},
"toidentifier": { "toidentifier": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",

View file

@ -47,6 +47,7 @@
"keycode": "^2.2.0", "keycode": "^2.2.0",
"mainloop.js": "^1.0.4", "mainloop.js": "^1.0.4",
"react": "^16.8.6", "react": "^16.8.6",
"react-custom-scrollbars": "^4.2.1",
"react-dom": "^16.8.6", "react-dom": "^16.8.6",
"react-router-dom": "^5.0.1", "react-router-dom": "^5.0.1",
"react-toastify": "^5.3.2", "react-toastify": "^5.3.2",

View file

@ -2,17 +2,22 @@ import { Singleton } from '@eix-js/utils'
import { Observable, fromEvent, BehaviorSubject } from 'rxjs' import { Observable, fromEvent, BehaviorSubject } from 'rxjs'
import { map } from 'rxjs/operators' import { map } from 'rxjs/operators'
import { multiply } from '../../vector2/helpers/basic' import { multiply } from '../../vector2/helpers/basic'
import { sidebarWidth } from '../components/Sidebar'
@Singleton @Singleton
export class Screen { export class Screen {
public width = new BehaviorSubject<number>(window.innerWidth) private getWidth() {
return window.innerWidth - sidebarWidth
}
public width = new BehaviorSubject<number>(this.getWidth())
public height = new BehaviorSubject<number>(window.innerHeight) public height = new BehaviorSubject<number>(window.innerHeight)
public constructor() { public constructor() {
const resize = fromEvent(window, 'resize') const resize = fromEvent(window, 'resize')
resize resize
.pipe(map(() => window.innerWidth)) .pipe(map(() => this.getWidth()))
.subscribe(val => this.width.next(val)) .subscribe(val => this.width.next(val))
resize resize
.pipe(map(() => window.innerHeight)) .pipe(map(() => window.innerHeight))

View file

@ -9,7 +9,7 @@ import Language from './Language'
/** /**
* The width of the sidebar * The width of the sidebar
*/ */
const sidebarWidth = 240 export const sidebarWidth = 240
/** /**
* The z-index of the sidebar. * The z-index of the sidebar.

View file

@ -54,7 +54,7 @@ const LogicGateModal = () => {
key={index} key={index}
className="logic-gate-item" className="logic-gate-item"
onClick={() => { onClick={() => {
addGate(renderer.simulation, name) addGate(renderer, name)
}} }}
> >
<Icon className="lgi-icon logic-gate-item-type"> <Icon className="lgi-icon logic-gate-item-type">
@ -70,7 +70,7 @@ const LogicGateModal = () => {
href={randomItem(template.info)} href={randomItem(template.info)}
onClick={e => { onClick={e => {
e.stopPropagation() e.stopPropagation()
e.preventDefault() // e.preventDefault()
}} }}
> >
<Icon className="lgi-icon">info</Icon> <Icon className="lgi-icon">info</Icon>

View file

@ -0,0 +1,11 @@
import { InputStore } from '../../input/stores/InputStore'
import { open as logicGateModalIsOpen } from '../../logic-gates/components/LogicGateModal'
import { CreateSimulationStore } from '../../create-simulation/stores/CreateSimulationStore'
export const modalIsOpen = () => {
return (
InputStore.data.open.value ||
logicGateModalIsOpen.value ||
CreateSimulationStore.data.open.value
)
}

View file

@ -2,12 +2,34 @@ import { templateStore } from '../../saving/stores/templateStore'
import { SimulationError } from '../../errors/classes/SimulationError' import { SimulationError } from '../../errors/classes/SimulationError'
import { Simulation } from '../classes/Simulation' import { Simulation } from '../classes/Simulation'
import { Gate } from '../classes/Gate' import { Gate } from '../classes/Gate'
import { add, relativeTo, multiply } from '../../vector2/helpers/basic'
import { SimulationRenderer } from '../../simulationRenderer/classes/SimulationRenderer'
import { DefaultGateTemplate } from '../constants'
import { vector2 } from '../../../common/math/classes/Transform'
export const addGate = (simulation: Simulation, templateName: string) => { export const addGate = (renderer: SimulationRenderer, templateName: string) => {
const template = templateStore.get(templateName) const template = templateStore.get(templateName)
if (!template) if (!template)
throw new SimulationError(`Cannot find template ${templateName}`) throw new SimulationError(`Cannot find template ${templateName}`)
simulation.push(new Gate(template)) const gate = new Gate(template)
const gateScale =
template.shape && template.shape.scale
? (template.shape.scale as vector2)
: DefaultGateTemplate.shape.scale
const origin = relativeTo(
multiply(gateScale, 0.5),
relativeTo(renderer.camera.transform.position, renderer.screen.center)
)
const scalarOffset = renderer.options.spawning.spawnOffset
const offset = multiply([scalarOffset, scalarOffset], renderer.spawnCount)
gate.transform.position = add(origin, offset)
renderer.simulation.push(gate)
renderer.spawnCount++
} }

View file

@ -26,8 +26,8 @@ import merge from 'deepmerge'
import { wireConnectedToGate } from '../helpers/wireConnectedToGate' import { wireConnectedToGate } from '../helpers/wireConnectedToGate'
import { updateMouse, handleScroll } from '../helpers/scaleCanvas' import { updateMouse, handleScroll } from '../helpers/scaleCanvas'
import { RefObject } from 'react' import { RefObject } from 'react'
import { Singleton } from '@eix-js/utils'
import { dumpSimulation } from '../../saving/helpers/dumpSimulation' import { dumpSimulation } from '../../saving/helpers/dumpSimulation'
import { modalIsOpen } from '../../modals/helpers/modalIsOpen'
export class SimulationRenderer { export class SimulationRenderer {
public mouseDownOutput = new Subject<MouseEventInfo>() public mouseDownOutput = new Subject<MouseEventInfo>()
@ -48,6 +48,9 @@ export class SimulationRenderer {
private mouseState = 0b00 private mouseState = 0b00
private gateSelectionOffset: vector2 = [0, 0] private gateSelectionOffset: vector2 = [0, 0]
// this is used for spawning gates
public spawnCount = 0
public selectedPins: SelectedPins = { public selectedPins: SelectedPins = {
start: null, start: null,
end: null end: null
@ -204,6 +207,8 @@ export class SimulationRenderer {
this.camera.transform.position, this.camera.transform.position,
invert(offset) invert(offset)
) )
this.spawnCount = 0
} }
this.lastMousePosition = this.camera.toWordPostition(event.position) this.lastMousePosition = this.camera.toWordPostition(event.position)
@ -218,9 +223,11 @@ export class SimulationRenderer {
public updateWheelListener() { public updateWheelListener() {
if (this.ref.current) { if (this.ref.current) {
this.ref.current.addEventListener('wheel', event => { this.ref.current.addEventListener('wheel', event => {
event.preventDefault() if (!modalIsOpen()) {
event.preventDefault()
handleScroll(event, this.camera) handleScroll(event, this.camera)
}
}) })
} }
} }

View file

@ -23,6 +23,9 @@ export const defaultSimulationRendererOptions: SimulationRendererOptions = {
wires: { wires: {
temporaryWireColor: `rgba(128,128,128,0.5)`, temporaryWireColor: `rgba(128,128,128,0.5)`,
curvePointOffset: 100 curvePointOffset: 100
},
spawning: {
spawnOffset: 30
} }
} }

View file

@ -21,4 +21,7 @@ export interface SimulationRendererOptions {
temporaryWireColor: string temporaryWireColor: string
curvePointOffset: number curvePointOffset: number
} }
spawning: {
spawnOffset: number
}
} }