From 4e9d0393ec4dce0a6cf429bc844251a91cf7bc7c Mon Sep 17 00:00:00 2001 From: David Meincke Date: Tue, 22 Mar 2022 21:13:56 +0100 Subject: [PATCH] added canvas renderer --- codeeditor-app/elements/app-root/app-root.ts | 2 +- .../elements/code-editor/code-editor.ts | 62 ++++++++++++++-- .../code-editor/injects/editor-init.txt | 6 +- .../notification-bubble.ts | 2 +- .../notification-bubbles.ts | 2 +- .../elements/output-frame/output-frame.ts | 2 +- outputframe-app/app.html | 1 + outputframe-app/app.less | 7 +- outputframe-app/boot.ts | 20 ++++- .../elements/render-canvas/render-canvas.less | 20 +++++ .../elements/render-canvas/render-canvas.ts | 73 +++++++++++++++++++ outputframe-app/injects/dom-helpers.ts | 29 ++++++++ {codeeditor-app/elements => shared}/_base.ts | 0 13 files changed, 212 insertions(+), 14 deletions(-) create mode 100644 outputframe-app/elements/render-canvas/render-canvas.less create mode 100644 outputframe-app/elements/render-canvas/render-canvas.ts create mode 100644 outputframe-app/injects/dom-helpers.ts rename {codeeditor-app/elements => shared}/_base.ts (100%) diff --git a/codeeditor-app/elements/app-root/app-root.ts b/codeeditor-app/elements/app-root/app-root.ts index fca92ba..884f20d 100644 --- a/codeeditor-app/elements/app-root/app-root.ts +++ b/codeeditor-app/elements/app-root/app-root.ts @@ -1,4 +1,4 @@ -import { BaseElement } from "../_base"; +import { BaseElement } from "../../../shared/_base"; import './app-root.less'; export class AppRoot extends BaseElement { diff --git a/codeeditor-app/elements/code-editor/code-editor.ts b/codeeditor-app/elements/code-editor/code-editor.ts index 23d4398..e872862 100644 --- a/codeeditor-app/elements/code-editor/code-editor.ts +++ b/codeeditor-app/elements/code-editor/code-editor.ts @@ -1,4 +1,4 @@ -import { BaseElement } from "../_base"; +import { BaseElement } from "../../../shared/_base"; import './code-editor.less'; import * as monaco from 'monaco-editor'; import { OutputFrame } from "../output-frame/output-frame"; @@ -10,7 +10,7 @@ export class CodeEditor extends BaseElement { onInit(): void { - + this.initWorkers(); @@ -32,24 +32,72 @@ export class CodeEditor extends BaseElement { suggestions: [ { label: 'for', - kind: monaco.languages.CompletionItemKind.Function, - insertText: 'for (let i = 0; i < array.length; i++) {\n\n}', + kind: monaco.languages.CompletionItemKind.Snippet, + insertText: 'for (let i = 0; i < ${1:array}.length; i++) {\n\t$0\n}', range: null, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet }, { label: 'forr', + kind: monaco.languages.CompletionItemKind.Snippet, + insertText: 'for (var i = ${1:array}.length - 1; i >= 0; i--) {\n\t$0\n}', + range: null, + insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet + }, + { + label: 'rect', + detail: "details", kind: monaco.languages.CompletionItemKind.Function, - insertText: 'for (var i = array.length - 1; i >= 0; i--) {\n\n}', + insertText: 'rect(${1:x}, ${2:y}, ${3:width}, ${4:height})', + range: null, + insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet + }, + { + label: 'box', + detail: "details", + kind: monaco.languages.CompletionItemKind.Function, + insertText: 'box(${1:x}, ${2:y}, ${3:width}, ${4:height})', + range: null, + insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet + }, + { + label: 'width', + detail: "gets the width of the canvas", + kind: monaco.languages.CompletionItemKind.Function, + insertText: 'width()', + range: null, + insertTextRules: monaco.languages.CompletionItemInsertTextRule.KeepWhitespace + }, + { + label: 'height', + detail: "gets the height of the canvas", + kind: monaco.languages.CompletionItemKind.Function, + insertText: 'height()', + range: null, + insertTextRules: monaco.languages.CompletionItemInsertTextRule.KeepWhitespace + }, + { + label: 'center', + detail: "gets the center of the canvas", + kind: monaco.languages.CompletionItemKind.Function, + insertText: 'center()', + range: null, + insertTextRules: monaco.languages.CompletionItemInsertTextRule.KeepWhitespace + }, + { + label: 'rand', + detail: "gets a random number between two numbers", + kind: monaco.languages.CompletionItemKind.Function, + insertText: 'rand(${1:from}, ${1:to})', range: null, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet } ] } ) - }); + }); + - editor.onDidChangeModelContent((e) => { this.input = editor.getValue(); this.outputFrame.setScript(this.input); diff --git a/codeeditor-app/elements/code-editor/injects/editor-init.txt b/codeeditor-app/elements/code-editor/injects/editor-init.txt index b6a8b43..c1a6dca 100644 --- a/codeeditor-app/elements/code-editor/injects/editor-init.txt +++ b/codeeditor-app/elements/code-editor/injects/editor-init.txt @@ -13,4 +13,8 @@ while (i < 10) { var obj = { hello: true, moto: "enabled" }; -console.log(obj); \ No newline at end of file +console.log(obj); + +rect(10, 10, 100, 100); +rect(rand(10, 30), rand(10, 30), 100, 100); +rect(30, 30, 100, 100); \ No newline at end of file diff --git a/codeeditor-app/elements/notification-bubbles/notification-bubble.ts b/codeeditor-app/elements/notification-bubbles/notification-bubble.ts index d497ec7..c94a0a6 100644 --- a/codeeditor-app/elements/notification-bubbles/notification-bubble.ts +++ b/codeeditor-app/elements/notification-bubbles/notification-bubble.ts @@ -1,4 +1,4 @@ -import { BaseElement } from "../_base"; +import { BaseElement } from "../../../shared/_base"; import './notification-bubble.less'; export class NotificationBubble extends BaseElement { diff --git a/codeeditor-app/elements/notification-bubbles/notification-bubbles.ts b/codeeditor-app/elements/notification-bubbles/notification-bubbles.ts index 9575ca1..dc6a479 100644 --- a/codeeditor-app/elements/notification-bubbles/notification-bubbles.ts +++ b/codeeditor-app/elements/notification-bubbles/notification-bubbles.ts @@ -1,5 +1,5 @@ import { messageListener } from "../../../shared/message-listener"; -import { BaseElement } from "../_base"; +import { BaseElement } from "../../../shared/_base"; import { NotificationBubble } from "./notification-bubble"; import './notification-bubbles.less'; diff --git a/codeeditor-app/elements/output-frame/output-frame.ts b/codeeditor-app/elements/output-frame/output-frame.ts index bd850f0..0b42933 100644 --- a/codeeditor-app/elements/output-frame/output-frame.ts +++ b/codeeditor-app/elements/output-frame/output-frame.ts @@ -1,4 +1,4 @@ -import { BaseElement } from "../_base"; +import { BaseElement } from "../../../shared/_base"; import './output-frame.less'; import { NotificationBubbles } from "../notification-bubbles/notification-bubbles"; import { GetOutputFrameUrl } from "../../../shared/url-helpers"; diff --git a/outputframe-app/app.html b/outputframe-app/app.html index e69de29..bafbd18 100644 --- a/outputframe-app/app.html +++ b/outputframe-app/app.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/outputframe-app/app.less b/outputframe-app/app.less index 643672f..56693a1 100644 --- a/outputframe-app/app.less +++ b/outputframe-app/app.less @@ -5,7 +5,12 @@ html, body { overflow: hidden; } +*, *::before, *::after { + box-sizing: border-box; +} + body { font-family: "Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif; - padding: 10px; + + background-color: #e3e3e3; } \ No newline at end of file diff --git a/outputframe-app/boot.ts b/outputframe-app/boot.ts index 777ba65..3a1696a 100644 --- a/outputframe-app/boot.ts +++ b/outputframe-app/boot.ts @@ -5,9 +5,14 @@ import { setOnErrorListener } from './injects/on-error'; import { createScript } from '../shared/create-script'; import { messageListener } from '../shared/message-listener'; import { postMessage, postResponseMessage } from '../shared/post-message'; +import { RenderCanvas } from './elements/render-canvas/render-canvas'; +import { getCenter, getHeight, getRandom, getWidth, rect } from './injects/dom-helpers'; +window.customElements.define('render-canvas', RenderCanvas); + document.body.innerHTML += bootHtml; + watchConsole((type, value) => { postMessage(parent, type, value); }); @@ -19,4 +24,17 @@ messageListener((type, value, id) => { }); setOnErrorListener((type, value) => { postMessage(parent, type, value); -}); \ No newline at end of file +}); + +//@ts-ignore +window.rect = rect; +//@ts-ignore +window.box = rect; +//@ts-ignore +window.width = getWidth; +//@ts-ignore +window.height = getHeight; +//@ts-ignore +window.center = getCenter; +//@ts-ignore +window.rand = getRandom; \ No newline at end of file diff --git a/outputframe-app/elements/render-canvas/render-canvas.less b/outputframe-app/elements/render-canvas/render-canvas.less new file mode 100644 index 0000000..82ea2c5 --- /dev/null +++ b/outputframe-app/elements/render-canvas/render-canvas.less @@ -0,0 +1,20 @@ +render-canvas { + width: 100%; + height: 100%; + display: block; + position: absolute; + left: 0; + top: 0; + bottom: 0; + right: 0; + overflow: hidden; +} + +render-canvas canvas { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + border: 1px solid #c2c2c2; + background-color: white; +} \ No newline at end of file diff --git a/outputframe-app/elements/render-canvas/render-canvas.ts b/outputframe-app/elements/render-canvas/render-canvas.ts new file mode 100644 index 0000000..c8ecf26 --- /dev/null +++ b/outputframe-app/elements/render-canvas/render-canvas.ts @@ -0,0 +1,73 @@ +import { BaseElement } from '../../../shared/_base'; +import './render-canvas.less'; + +export class RenderCanvas extends BaseElement { + public canvas: HTMLCanvasElement | null = null; + public ctx: CanvasRenderingContext2D | null = null; + public width: number = 0; + public height: number = 0; + public units = { + width: 400, + heigt: 400 + } + + onInit(): void { + this.canvas = document.createElement("canvas"); + this.ctx = this.canvas.getContext("2d"); + this.appendChild(this.canvas); + + window.addEventListener("resize", () => { + this.handleCanvasResize(); + }); + + this.handleCanvasResize(); + } + + private handleCanvasResize() { + if (this.parentElement && this.canvas) { + this.width = this.parentElement.clientWidth; + this.height = this.parentElement.clientHeight; + + this.canvas.style.width = this.width + "px"; + this.canvas.style.height = this.width + "px"; + this.canvas.setAttribute("width", this.width.toString()); + this.canvas.setAttribute("height", this.width.toString()); + } + } + + drawPoly(points: { x: number, y: number }[]) { + if (this.ctx) { + this.ctx.fillStyle = "rgba(0,0,0,0)"; + this.ctx.strokeStyle = "rgba(0,0,0,1)"; + this.ctx.beginPath(); + + for (var i = 0; i < points.length; i++) { + var point = points[i]; + + if (i === 0) { + this.ctx.moveTo(this.unitsToPx(point.x), this.unitsToPx(point.y)); + } + else { + this.ctx.lineTo(this.unitsToPx(point.x), this.unitsToPx(point.y)); + } + } + + this.ctx.closePath(); + this.ctx.fill(); + this.ctx.stroke(); + } + } + + drawRect(x: number, y: number, width: number, height: number) { + this.drawPoly([{ x: x, y: y }, { x: x + width, y: y }, { x: x + width, y: y + height }, { x: x, y: y + height }]); + } + + unitsToPx(unitNumber: number) { + var newPPU = (this.width / this.units.width); + return unitNumber * newPPU; + } + + onUpdate(): void { + console.log("APP ROOT UPDATE"); + } +} \ No newline at end of file diff --git a/outputframe-app/injects/dom-helpers.ts b/outputframe-app/injects/dom-helpers.ts new file mode 100644 index 0000000..58aac7b --- /dev/null +++ b/outputframe-app/injects/dom-helpers.ts @@ -0,0 +1,29 @@ +import { RenderCanvas } from "../elements/render-canvas/render-canvas"; + +export function clear() { + +} + +export function rect(x: number, y: number, width: number, height: number): void { + var renderCanvas = document.getElementsByTagName("render-canvas")[0]; + renderCanvas.drawRect(x, y, width, height); +} + +export function getWidth(): number { + var renderCanvas = document.getElementsByTagName("render-canvas")[0]; + return renderCanvas.units.width; +} + +export function getHeight(): number { + var renderCanvas = document.getElementsByTagName("render-canvas")[0]; + return renderCanvas.units.heigt; +} + +export function getCenter(): number { + var renderCanvas = document.getElementsByTagName("render-canvas")[0]; + return renderCanvas.units.heigt / 2; +} + +export function getRandom(min: number, max: number): number { + return Math.floor(Math.random() * (max - min + 1) + min); +} \ No newline at end of file diff --git a/codeeditor-app/elements/_base.ts b/shared/_base.ts similarity index 100% rename from codeeditor-app/elements/_base.ts rename to shared/_base.ts