Commit 04494308 authored by Henrik Tramberend's avatar Henrik Tramberend
Browse files

Merge branch 'master' of gitlab2.informatik.uni-wuerzburg.de:decker/decker

parents 94f61b16 a1890b19
......@@ -17,4 +17,3 @@ exclude-directories:
- users-guide
static-resource-dirs:
- test/static
- test/decks/geometry/static
......@@ -165,7 +165,7 @@ div.q-panel div.q-header button.q-check {
background-color: rgba(0, 0, 0, 0);
border: none;
border-radius: var(--border-radius);
/* border-radius: var(--border-radius); */
outline: none;
}
......@@ -192,7 +192,7 @@ div.q-panel div.q-header button.q-close {
background-color: rgba(0, 0, 0, 0);
border: none;
border-radius: var(--border-radius);
/* border-radius: var(--border-radius); */
outline: none;
}
......
input,
button,
textarea,
select {
div.exa-quest input,
div.exa-quest button,
div.exa-quest textarea,
div.exa-quest select {
color: black;
background-color: #efefef;
......@@ -17,10 +17,10 @@ select {
outline: none;
}
input,
select,
button,
textarea {
div.exa-quest input,
div.exa-quest select,
div.exa-quest button,
div.exa-quest textarea {
-webkit-appearance: none;
}
......
......@@ -19,8 +19,8 @@ export {
IsectLineCircle,
};
import "./d3.v6.min.js";
import { Clipper } from "./clip.js";
import "/support/vendor/d3.v6.min.js";
import { Clipper } from "/support/js/clip.js";
const defaults = {
point: { r: 8, opts: [] }, // one of [, "drag", "computed"]
......
......@@ -35,6 +35,7 @@ $endif$
<link rel="stylesheet" href="$decker-support-dir$/vendor/reveal/css/reveal.css">
<link rel="stylesheet" href="$decker-support-dir$/plugins/whiteboard/whiteboard.css">
<link rel="stylesheet" href="$decker-support-dir$/plugins/menu/menu.css">
<link rel="stylesheet" href="$decker-support-dir$/css/geometry.css">
$if(thebelab.enable)$
<link rel="stylesheet" href="$decker-support-dir$/plugins/thebelab/thebelab.css">
$endif$
......
import * as g from "./static/geometry.js";
import * as g from "/support/js/geometry.js";
let p1 = g.point(60, 60, "drag");
let p2 = g.point(540, 60);
......
---
template:
css: ./static/geometry.css
title: ES6 Modules in Code Blocks
zoom: false
---
# Code Blocks with a *`run`* class
......@@ -41,7 +40,7 @@ console.log("Hello", anchor);
```` {.markdown}
``` {.javascript .run}
import * as g from "./static/geometry.js";
import * as g from "/support/js/geometry.js";
let segment = g.bezier(
g.point(60, 60),
g.point(540, 60, "drag"),
......@@ -59,7 +58,7 @@ g.renderSvg(anchor, 600, 400, segment);
## {.left}
``` {.javascript .run}
import * as g from "./static/geometry.js";
import * as g from "/support/js/geometry.js";
let segment = g.bezier(
g.point(60, 60),
......@@ -101,7 +100,7 @@ width="100%"}
# Labels
``` {.javascript .run}
import * as g from "./static/geometry.js";
import * as g from "/support/js/geometry.js";
let p = g.point(100,350, "drag");
let q = g.point(300,350, "drag");
......@@ -169,7 +168,7 @@ g.renderSvg(anchor, 1200, 500, g.group(
# Infinite Line
``` {.javascript .run}
import * as g from "./static/geometry.js";
import * as g from "/support/js/geometry.js";
let p = g.point(100,150, "drag");
let q = g.point(400,150, "drag");
......
import * as g from "./static/geometry.js";
import * as g from "/support/js/geometry.js";
let center = g.point(300, 300, "drag");
let intersection = new g.IsectLineCircle(
......
import * as g from "./static/geometry.js";
let center = g.point(300, 300, "drag");
let intersection = new g.IsectLineCircle(
g.line(g.point(60, 60, "drag"), g.point(540, 60, "drag")),
g.circle(center, 200)
);
let root = g.group(
intersection.p2,
intersection.n2,
intersection.p1,
intersection,
g.line(center, intersection.p1)
// g.swtch2(intersection.result[0].point, g.text(250, 400, "Bang!"))
);
g.renderSvg(anchor, 1200, 600, root);
import * as g from "./static/geometry.js";
import * as g from "/support/js/geometry.js";
let surfaceAnchor = g.point(300, 230);
let surfaceNormal = g.vector(surfaceAnchor, 0, -200);
......
/*
* Copyright 2020 Kazimierz Pogoda
*
* This file is part of shader-web-background.
*
* shader-web-background is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* shader-web-background is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with shader-web-background. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* @fileoverview Public API of shader-web-background.js
*
* @externs
*/
"use strict";
const shaderWebBackground = {};
/**
* @typedef {
* function(!WebGLUniformLocation, (!WebGLTexture|!DoubleBuffer))
* }
*/
var TextureBinder;
/**
* @typedef {{
* gl: !WebGLRenderingContext,
* canvas: !HTMLCanvasElement,
* width: !number,
* height: !number,
* cssPixelRatio: !number,
* cssWidth: !number,
* cssHeight: !number,
* isOverShader: !function(!number, !number): !boolean,
* toShaderX: !function(!number): !number,
* toShaderY: !function(!number): !number,
* buffers: !Object<string, !DoubleBuffer>,
* texture: !TextureBinder,
* initHalfFloatRGBATexture: !function(!number, !number)
* }}
*/
var Context;
/**
* @typedef {
* function(!WebGLRenderingContext, !Context)
* }
*/
var TextureInitializer;
/**
* @typedef {
* function(!WebGLRenderingContext, !WebGLUniformLocation, Context=)
* }
*/
var UniformSetter;
/**
* @typedef {
* Object<string, !UniformSetter>
* }
*/
var UniformSetters;
/**
* @typedef {{
* texture: (TextureInitializer|undefined),
* uniforms: (UniformSetters|undefined)
* }}
*/
var Shader;
/**
* @typedef {
* function(!Error, !HTMLCanvasElement)
* }
*/
var ErrorHandler;
/**
* @typedef {{
* shaders: (!Object<string, !Shader>),
* canvas: (HTMLCanvasElement|undefined),
* onInit: (function(Context=)|undefined),
* onResize: (function(!number, !number, Context=)|undefined),
* onBeforeFrame: (function(Context=)|undefined),
* onAfterFrame: (function(Context=)|undefined),
* onError: (ErrorHandler|undefined)
* }}
*/
var Config;
shaderWebBackground.Error = class extends Error {}
/**
* Indicates misconfiguration.
*/
shaderWebBackground.ConfigError = class extends shaderWebBackground.Error {}
/**
* Indicates WebGL problems.
*/
shaderWebBackground.GlError = class extends shaderWebBackground.Error {}
/**
* Will start shading.
*
* @param {!Config} config
* @return {!Context} the shading context object
* @throws {shaderWebBackground.ConfigError}
* @throws {shaderWebBackground.GlError}
*/
shaderWebBackground.shade = function(config) {}
/*
* Copyright 2020 Kazimierz Pogoda
*
* This file is part of shader-web-background.
*
* shader-web-background is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* shader-web-background is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with shader-web-background. If not, see <https://www.gnu.org/licenses/>.
*/
"use strict";
const
VERTEX_SHADER_SCRIPT_TYPE = "x-shader/x-vertex",
FRAGMENT_SHADER_SCRIPT_TYPE = "x-shader/x-fragment",
CANVAS_ELEMENT_ID = "shader-web-background",
FALLBACK_CLASS = "shader-web-background-fallback",
VERTEX_ATTRIBUTE = "V",
DEFAULT_VERTEX_SHADER = "attribute vec2 V;void main(){gl_Position=vec4(V,0,1);}",
/** @type {!TextureInitializer} */
DEFAULT_TEXTURE_INITIALIZER = (gl, ctx) => {
ctx.initHalfFloatRGBATexture(ctx.width, ctx.height);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
},
/** @type {!ErrorHandler} */
DEFAULT_ON_ERROR = (error, canvas) => {
console.warn("shader-web-background cannot shade, adding fallback CSS classes");
document.documentElement.classList.add(FALLBACK_CLASS);
canvas.classList.add(FALLBACK_CLASS);
if (error instanceof shaderWebBackground.GlError) {
console.warn("Not sufficient WebGL support:", error);
} else {
throw error;
}
};
/**
* @param {*} condition
* @param {!string} message
*/
function check(condition, message) {
if (!condition) throw new shaderWebBackground.ConfigError(message);
}
/**
* @param {*} canvas
* @return {!HTMLCanvasElement}
*/
function checkIfCanvas(canvas) {
check(canvas instanceof HTMLCanvasElement, "config.canvas must be instance of canvas");
return /** @type {!HTMLCanvasElement} */ (canvas);
}
/**
* @return {!HTMLCanvasElement}
*/
function newBackgroundCanvas() {
const canvas =
/** @type {!HTMLCanvasElement} */
(document.createElement("canvas"));
const style = canvas.style;
canvas.id = CANVAS_ELEMENT_ID;
style.width = "100vw";
style.height = "100vh";
style.position = "fixed";
style.top = "0";
style.left = "0";
style.zIndex = -9999;
return canvas;
}
/**
* @param {!string} type
* @param {!string} id
* @return {!string}
*/
const scriptSpec = (type, id) => "<script type=\"" + type + "\" id=\"" + id + "\">";
/**
* @param {!Element} element
* @param {!string} type
* @param {!string} id
*/
function checkScript(element, type, id) {
check(
(element instanceof HTMLScriptElement)
&& (element.type === type),
"Shader source element of id \"" + id + "\" "
+ "should be of type: " + scriptSpec(type, id)
);
}
/**
* @param {!string} id
* @return {!string}
*/
function getFragmentShaderSource(id) {
const element = document.getElementById(id);
check(element, "Missing shader source: " + scriptSpec(FRAGMENT_SHADER_SCRIPT_TYPE, id));
checkScript(/** @type {!Element} */ (element), FRAGMENT_SHADER_SCRIPT_TYPE, id);
return element.text;
}
/**
* @param {!string} id
* @return {!string}
*/
function getVertexShaderSource(id) {
const vertexShaderId = id + "Vertex";
const element = document.getElementById(vertexShaderId);
if (element) {
checkScript(element, VERTEX_SHADER_SCRIPT_TYPE, vertexShaderId);
return element.text;
}
return DEFAULT_VERTEX_SHADER;
}
/**
* @param {!string} eventType
* @param {!function()} call
*/
function doOrWaitFor(eventType, call) {
if ((document.readyState !== "loading")) {
call();
} else {
window.addEventListener(eventType, call);
}
}
/**
* @typedef {{
* location: !WebGLUniformLocation,
* setter: !UniformSetter
* }}
*/
var Uniform;
class Renderer {
/**
* @param {!GlWrapper} glWrapper
* @param {!Context} context
* @param {!Program} program
* @param {!Array<!Uniform>} uniforms
*/
constructor(glWrapper, context, program, uniforms) {
this.program = program;
const gl = glWrapper.gl;
this.fillUniforms = () => {
for (const uniform of uniforms) {
uniform.setter(gl, uniform.location, context);
}
}
this.draw = () => {
glWrapper.drawQuad(program.vertexAttributeLocation);
glWrapper.unbindTextures();
}
}
render() {
this.program.draw(
this.fillUniforms,
this.draw
);
}
}
/**
* @param {!HTMLCanvasElement} canvas
* @param {!Object} contextAttrs
* @return {!GlWrapper}
* @throws {shaderWebBackground.GlError}
*/
function initCanvas(canvas, contextAttrs) {
try {
return new GlWrapper(canvas, contextAttrs);
} catch (/** @type {!Error} */ error) {
throw new shaderWebBackground.GlError(error.message);
}
}
/**
* @param {!HTMLCanvasElement} canvas
* @param {!Object<string, !Shader>} shaders
* @param {function(Context)|undefined} onInit
* @param {function(!number, !number, Context=)|undefined} onResize
* @param {function(Context)|undefined} onBeforeFrame
* @param {function(Context)|undefined} onAfterFrame
* @return {Context}
*/
function doShade(canvas, shaders, onInit, onResize, onBeforeFrame, onAfterFrame) {
// in the future it should be configurable as well
const contextAttrs = {
antialias: false,
depth: false,
alpha: false
};
const glWrapper = initCanvas(canvas, contextAttrs);
/**
* @param {!string} id
* @param {!string} vertexShaderSource
* @param {!string} fragmentShaderSource
* @return {!WebGLProgram}
* @throws {shaderWebBackground.ConfigError}
*/
function initProgram(id, vertexShaderSource, fragmentShaderSource) {
try {
return glWrapper.initProgram(id, vertexShaderSource, fragmentShaderSource)
} catch (/** @type {!Error} */ error) {
throw new shaderWebBackground.ConfigError(error.message);
}
}
/** @type {!Array<!Renderer>} */
const renderers = [];
/** @type {Context} */
const context = {
gl: glWrapper.gl,
canvas: canvas,
width: 0,
height: 0,
cssPixelRatio: 0,
cssWidth: 0,
cssHeight: 0,
/** @type {!function(!number, !number): !boolean} */
isOverShader: (x, y) => {
const rect = canvas.getBoundingClientRect();
return (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom);
},
/*
gl_FragCoord contains floating point values aligned with the middle of a pixel,
therefore we are adjust our coordinates by half to make them match
*/
/** @type {!function(!number): !number} */
toShaderX: (x) =>
(x - canvas.getBoundingClientRect().left)
* context.cssPixelRatio + .5,
/** @type {!function(!number): !number} */
toShaderY: (y) =>
(canvas.height - (y - canvas.getBoundingClientRect().top)
* context.cssPixelRatio) - .5,
/** @type {!function(): boolean} */
maybeResize: () => {
if ((context.cssWidth !== canvas.clientWidth)
|| (context.cssHeight !== canvas.clientHeight)
) {
context.resize();
return true;
}
return false;
},
/** @type {!function()} */
resize: () => {
const
pixelRatio = window.devicePixelRatio || 1,
cssWidth = canvas.clientWidth,
cssHeight = canvas.clientHeight,
width = Math.floor(cssWidth * pixelRatio),
height = Math.floor(cssHeight * pixelRatio);
canvas.width = width;
canvas.height = height;
context.width = width;
context.height = height;
context.cssPixelRatio = pixelRatio;
context.cssWidth = cssWidth;
context.cssHeight = cssHeight;
glWrapper.updateViewportSize();
for (const renderer of renderers) {
renderer.program.init(width, height);
}
},
/** @type {!TextureBinder} */
texture: (loc, tex) => glWrapper.bindTexture(loc, tex),
buffers: {},
/** @type {!function(!number, !number)} */
initHalfFloatRGBATexture: (width, height) => {
glWrapper.texImage2DHalfFloatRGBA(width, height);
}
}
const imageShaderIndex = Object.keys(shaders).length - 1;
let index = 0;
for (const id in shaders) {
if (index++ < imageShaderIndex) {
const textureInitializer = shaders[id].texture || DEFAULT_TEXTURE_INITIALIZER;
context.buffers[id] = glWrapper.newDoubleBuffer(() => {
textureInitializer(glWrapper.gl, context);
});
}
const program = glWrapper.wrapProgram(
id,
initProgram(id, getVertexShaderSource(id), getFragmentShaderSource(id)),
VERTEX_ATTRIBUTE,
context.buffers[id]
);
const uniformSetters =
(shaders[id].uniforms) || /** @type {!UniformSetters} */ ({});
var extraUniforms = Object.keys(uniformSetters);