diff --git a/src/assets/or_gate.png b/src/assets/or_gate.png new file mode 100644 index 0000000..3a69c1c Binary files /dev/null and b/src/assets/or_gate.png differ diff --git a/src/assets/xor_gate.png b/src/assets/xor_gate.png new file mode 100644 index 0000000..0d29265 Binary files /dev/null and b/src/assets/xor_gate.png differ diff --git a/src/index.html b/src/index.html index 3dd054e..aa7287a 100644 --- a/src/index.html +++ b/src/index.html @@ -8,8 +8,8 @@ - - hello world + + loading \ No newline at end of file diff --git a/src/scss/base.scss b/src/scss/base.scss index 07789d8..8b88186 100644 --- a/src/scss/base.scss +++ b/src/scss/base.scss @@ -1,7 +1,7 @@ @import "./toastr.scss"; @import "./modal.scss"; -$mdc-theme-primary: orange / 2; +$mdc-theme-primary: orange; $mdc-theme-secondary: #feeae6; $mdc-theme-on-primary: white; $mdc-theme-surface: black; diff --git a/src/ts/common/activation/activationStore.ts b/src/ts/common/activation/activationStore.ts deleted file mode 100644 index 909b2c7..0000000 --- a/src/ts/common/activation/activationStore.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Singleton } from "@eix/utils"; -import { activationFunction, activationFunctionParam } from "./interfaces" -import { toActivationFunction } from "./toActivation"; - -@Singleton -export class FunctionStore { - functions = new Map() - - private storageKeyword: string - - constructor(name="activation") { - this.storageKeyword =`/${name}` - for (let i in localStorage) { - if (i.indexOf(this.storageKeyword) == 0) - this.register(i.substr(this.storageKeyword.length), localStorage[i]) - } - } - - register(name: string, activation: activationFunctionParam) { - this.functions.set(name, toActivationFunction(activation)) - localStorage[`${this.storageKeyword.substr(1)}/${name}`] = activation - } -} \ No newline at end of file diff --git a/src/ts/common/activation/index.ts b/src/ts/common/activation/index.ts deleted file mode 100644 index ed346eb..0000000 --- a/src/ts/common/activation/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./toActivation" \ No newline at end of file diff --git a/src/ts/common/activation/interfaces.ts b/src/ts/common/activation/interfaces.ts deleted file mode 100644 index a2ca08e..0000000 --- a/src/ts/common/activation/interfaces.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type activationInput = any[] -export type activationOutput = boolean -export type activationFunctionParam = ( (data:activationInput) => activationOutput ) | string -export type activationFunction = (data:activationInput) => activationOutput \ No newline at end of file diff --git a/src/ts/common/activation/toActivation.ts b/src/ts/common/activation/toActivation.ts deleted file mode 100644 index ef9a7e5..0000000 --- a/src/ts/common/activation/toActivation.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { activationFunctionParam, activationFunction } from "./interfaces"; - -export const toActivationFunction = (original: activationFunctionParam) => { - const stringified = (typeof original == "string") ? original : original.toString() - const final = new Function(`return ${stringified}`) as () => activationFunction - - return final() -} \ No newline at end of file diff --git a/src/ts/common/component/component.ts b/src/ts/common/component/component.ts index 30cc096..a3a8f97 100644 --- a/src/ts/common/component/component.ts +++ b/src/ts/common/component/component.ts @@ -11,6 +11,7 @@ import { alertOptions } from "../componentManager/alertOptions"; import { WireManager } from "../wires"; import { runCounter } from "./runCounter"; import { Material } from "./material"; +import { manager } from "../../main"; export class Component { private static store = new ComponentTemplateStore() @@ -76,9 +77,9 @@ export class Component { this.subscriptions.push(subscription) }) - this.activate() - this.material = new Material(data.material.mode, data.material.data) + + this.activate() } public dispose() { @@ -110,16 +111,29 @@ export class Component { } handleClick(e: MouseEvent) { - const mousePosition = Component.screen.getWorldPosition(e.clientX, e.clientY) + console.log(e.button) - this.mouserDelta = this.position.value.map((value, index) => - mousePosition[index] - value - ) - this.clicked = true - this.clickedChanges.next(this.clicked) + if (e.button === 0) { + const mousePosition = Component.screen.getWorldPosition(e.clientX, e.clientY) - this.activate(1) - this.activate(0) + this.mouserDelta = this.position.value.map((value, index) => + mousePosition[index] - value + ) + this.clicked = true + this.clickedChanges.next(this.clicked) + + this.activate(1) + this.activate(0) + } + + else if (e.button === 2){ + manager.components = manager.components.filter(val => val !== this) + manager.wireManager.wires + .filter(val => val.input.of === this || val.output.of === this) + .forEach(val => val.dispose()) + manager.wireManager.update.next(true) + manager.update() + } } handlePinClick(e: MouseEvent, pin: Pin) { diff --git a/src/ts/common/component/material.ts b/src/ts/common/component/material.ts index 8d5ce70..ac7ad1e 100644 --- a/src/ts/common/component/material.ts +++ b/src/ts/common/component/material.ts @@ -11,7 +11,9 @@ export class Material { private static images: { [key: string]: string } = { - and: require("../../../assets/and_gate.jpg") + and: require("../../../assets/and_gate.jpg"), + or: require("../../../assets/or_gate.png"), + xor: require("../../../assets/xor_gate.png") } private static cached = new Map() diff --git a/src/ts/common/componentManager/componentManager.ts b/src/ts/common/componentManager/componentManager.ts index 1fc07a3..0e4371f 100644 --- a/src/ts/common/componentManager/componentManager.ts +++ b/src/ts/common/componentManager/componentManager.ts @@ -26,13 +26,13 @@ export class ComponentManager { public svgs = new Subject() public placeholder = new BehaviorSubject("Create simulation") public barAlpha = new BehaviorSubject("0"); + public wireManager = new WireManager() private temporaryCommnad = "" private onTop: Component private clicked = false private screen = new Screen() - private wireManager = new WireManager() private templateStore = new ComponentTemplateStore() private settings = new Settings() private standard: { @@ -53,7 +53,7 @@ export class ComponentManager { private palleteEvent = new KeyboardInput("p") private shiftEvent = new KeyboardInput("shift") private refreshEvent = new KeyboardInput("r") - private clearEvent = new KeyboardInput("c") + private clearEvent = new KeyboardInput("delete") private upEvent = new KeyboardInput("up") private downEvent = new KeyboardInput("down") @@ -99,6 +99,17 @@ export class ComponentManager { public gates = this.templateStore.store.lsChanges public saves = this.store.lsChanges + public file: { + [key: string]: () => void + } = { + clear: () => this.clear(), + clean: () => this.smartClear(), + save: () => this.save(), + refresh: () => this.refresh(), + download: () => download(this,[],[]), + delete: () => this.delete(this.name) + } + constructor() { runCounter.increase() @@ -158,12 +169,6 @@ export class ComponentManager { this.inputMode = "command" this.placeholder.next("Command palette") } - else if (this.clearEvent.value) { - if (this.shiftEvent.value) - this.clear() - else - this.smartClear() - } else if (this.saveEvent.value) { this.save() } @@ -171,6 +176,12 @@ export class ComponentManager { this.refresh() } } + else if (this.clearEvent.value) { + if (this.shiftEvent.value) + this.clear() + else + this.smartClear() + } } }) diff --git a/src/ts/common/componentManager/componentTemplateStore.ts b/src/ts/common/componentManager/componentTemplateStore.ts index 4cba829..837179a 100644 --- a/src/ts/common/componentManager/componentTemplateStore.ts +++ b/src/ts/common/componentManager/componentTemplateStore.ts @@ -104,6 +104,32 @@ export class ComponentTemplateStore { data: "and" } }) + this.store.set("or", { + inputs: 2, + outputs: 1, + name: "or", + version: "1.0.0", + activation: ` + ctx.outputs[0].value = ctx.inputs[0].value || ctx.inputs[1].value + `.trim(), + material: { + mode: "standard_image", + data: "or" + } + }) + this.store.set("xor", { + inputs: 2, + outputs: 1, + name: "xor", + version: "1.0.0", + activation: ` + ctx.outputs[0].value = (ctx.inputs[0].value || ctx.inputs[1].value) && !(ctx.inputs[0].value && ctx.inputs[1].value) + `.trim(), + material: { + mode: "standard_image", + data: "xor" + } + }) this.store.set("true", { inputs: 0, outputs: 1, @@ -161,7 +187,7 @@ export class ComponentTemplateStore { onclick: ` ctx.outputs[0].memory.value = !ctx.outputs[0].memory.value if (ctx.outputs[0].memory.value) - ctx.color("#880000") + ctx.color("#550000") else ctx.color("red") ` diff --git a/src/ts/common/modals/modal.ts b/src/ts/common/modals/modal.ts index 9c42a97..9751c0c 100644 --- a/src/ts/common/modals/modal.ts +++ b/src/ts/common/modals/modal.ts @@ -36,12 +36,16 @@ export const modal = (options: Partial) => new Promise((res ${content}
- - + ${(no !== "") ? + html`` : no + } + ${(yes !== "") ? + html`` : yes + }
diff --git a/src/ts/common/wires/wire.ts b/src/ts/common/wires/wire.ts index 9f6d5c7..dd585f7 100644 --- a/src/ts/common/wires/wire.ts +++ b/src/ts/common/wires/wire.ts @@ -11,5 +11,7 @@ export class Wire { public dispose(){ this.output.unbind(this.input) this.input.pair = null + this.input.update() + this.output.update() } } \ No newline at end of file diff --git a/src/ts/common/wires/wireManager.ts b/src/ts/common/wires/wireManager.ts index 042d6e3..4b6ded8 100644 --- a/src/ts/common/wires/wireManager.ts +++ b/src/ts/common/wires/wireManager.ts @@ -51,6 +51,12 @@ export class WireManager { return true } + private remove(target: Wire) { + target.dispose() + this.wires = this.wires.filter(val => val !== target) + this.update.next(true) + } + get svg() { return this.wires.map(val => { const i = val.input.of @@ -61,6 +67,8 @@ export class WireManager { y1=${subscribe(i.piny(false,i.outputPins.indexOf(val.input)))} y2=${subscribe(o.piny(true,o.inputPins.indexOf(val.output)))} stroke=${subscribe(val.input.svgColor)} + stroke-width=10 + @click=${() => this.remove(val)} > `}) diff --git a/src/ts/main.ts b/src/ts/main.ts index 1a5170b..74e1a78 100644 --- a/src/ts/main.ts +++ b/src/ts/main.ts @@ -2,17 +2,47 @@ import { render, html, svg } from "lit-html" import { subscribe } from "lit-rx" import { Screen } from "./common/screen.ts"; import { Component } from "./common/component"; -import { FunctionStore } from "./common/activation/activationStore"; import { ComponentManager } from "./common/componentManager"; import { map } from "rxjs/operators"; import { MDCMenu } from '@material/menu'; +import { error } from "toastr" +import { modal } from "./common/modals"; const screen = new Screen() -const manager = new ComponentManager() +export const manager = new ComponentManager() manager.save() manager.update() +window.onerror = (message: string, url: string, lineNumber: number): boolean => { + error(message,"",{ + ...manager.alertOptions, + onclick: () => modal({ + no: "", + yes: "close", + title: "Error", + content: html` + + + + + + + + + + + + + +
Url:${url}
Message:${message}
Line:${lineNumber}
+ ` + }) + }) + + return true; +}; + const handleEvent = (e: T, func: (e: T) => any) => { if (manager.barAlpha.value == "0") func(e) @@ -75,6 +105,12 @@ render(html` Add logic gate + { + menus[2].open = true + }}> + + File + @@ -86,7 +122,7 @@ render(html` ${val} manager.delete(val)}> delete ` - ))))} + ))))} @@ -96,14 +132,29 @@ render(html` ` - ))))} + ))))} + + + +
+
`, document.body) -const menus = [new MDCMenu(document.querySelector('#saveMenu')), new MDCMenu(document.querySelector('#gateMenu'))] +const menus = [ + new MDCMenu(document.querySelector('#saveMenu')), + new MDCMenu(document.querySelector('#gateMenu')), + new MDCMenu(document.querySelector('#fileMenu')) +] menus.forEach(menu => menu.hoistMenuToBody()) menus[0].setAnchorElement(document.querySelector(`#openSimulation`)) menus[1].setAnchorElement(document.querySelector("#openGates")) +menus[2].setAnchorElement(document.querySelector("#openFile")) manager.update() \ No newline at end of file