diff --git a/.gitignore b/.gitignore
index 5a70b9ba4e..012eda4639 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ typings
*.swo
webpack-stats.json
analyze.json
+stats.json
src/components/base
.vscode
todo
@@ -15,6 +16,7 @@ how_to_add_a_new_language.txt
.DS_Store
/.alm/
package-lock.json
+report.*.json
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000000..43c97e719a
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+package-lock=false
diff --git a/Gulpfile.js b/Gulpfile.js
index 855631d21b..7f7d48b081 100644
--- a/Gulpfile.js
+++ b/Gulpfile.js
@@ -161,7 +161,7 @@ function min_styl(done) {
function background_webpack(done) {
function spawn_webpack() {
let env = process.env;
- let webpack = spawn('node', ['node_modules/webpack/bin/webpack.js', '--watch', '--progress', '--colors'], { stdio: 'inherit' })
+ let webpack = spawn('npm', ['run', 'webpack-watch'], { stdio: 'inherit' })
webpack.on('exit', spawn_webpack);
}
diff --git a/Makefile b/Makefile
index be9d3e6e06..ffd989b2a2 100644
--- a/Makefile
+++ b/Makefile
@@ -3,35 +3,35 @@ PATH:=node_modules/.bin/:$(PATH)
dev: node_modules
- NODE_PATH=$(NODE_PATH) PATH=$(PATH) supervisor -w Gulpfile.js,webpack.config.js,tsconfig.json supervisor -w Gulpfile.js -x gulp --
+ npm run dev
node_modules:
npm install yarn
- npm install supervisor
- NODE_PATH=$(NODE_PATH) PATH=$(PATH) yarn install
+ npm run yarn install
pretty prettier:
npm run prettytsx
npm run prettyts
lint tslint:
- NODE_PATH=$(NODE_PATH) PATH=$(PATH) tslint --project tsconfig.json
+ npm run tslint -- --project tsconfig.json
min: minjs mincss
mincss:
- NODE_PATH=$(NODE_PATH) PATH=$(PATH) gulp min_styl
+ npm run gulp min_styl
@echo 'gzipped ogs.min.css: ' `gzip -9 dist/ogs.min.css -c | wc -c`
minjs:
- NODE_PATH=$(NODE_PATH) PATH=$(PATH) PRODUCTION=true webpack --optimize-minimize --devtool=source-map --display-modules
+ npm run webpack -- --mode production --optimize-minimize --devtool=source-map --display-modules
@echo 'gzipped ogs.min.js: ' `gzip -9 dist/ogs.min.js -c | wc -c`
@echo 'gzipped vendor.min.js: ' `gzip -9 dist/vendor.min.js -c | wc -c`
analyze:
- #NODE_PATH=$(NODE_PATH) PATH=$(PATH) PRODUCTION=true webpack --optimize-minimize --devtool=source-map --profile --json > analyze.json
- #npm run webpack-bundle-analyzer dist/ analyze.json
- npm run webpack-bundle-analyzer analyze.json dist/
+ ANALYZE=true npm run analyze
+
+#NODE_PATH=$(NODE_PATH) PATH=$(PATH) PRODUCTION=true webpack --optimize-minimize --devtool=source-map --profile --json > analyze.json
+#npm run webpack-bundle-analyzer dist/ analyze.json
.PHONY: dev lint tslint min minjs mincss
diff --git a/package.json b/package.json
index 12875915fd..3c20b91e74 100644
--- a/package.json
+++ b/package.json
@@ -5,11 +5,15 @@
"license": "AGPL-3.0",
"private": true,
"scripts": {
- "dev": "gulp",
+ "dev": "supervisor -w Gulpfile.js,webpack.config.js,tsconfig.json supervisor -w Gulpfile.js -x gulp --",
"prettytsx": "prettier --write 'src/**/*.tsx'",
"prettyts": "prettier --write 'src/**/*.ts'",
"webpack": "webpack",
- "webpack-bundle-analyzer": "webpack-bundle-analyzer"
+ "webpack-watch": "webpack --watch --progress --colors",
+ "yarn": "yarn",
+ "tslint": "tslint",
+ "gulp": "gulp",
+ "analyze": "webpack --mode production --profile --optimize-minimize --devtool=source-map"
},
"browserslist": [
"defaults"
@@ -40,7 +44,7 @@
"tslint": "^5.20.0",
"typescript": "^3.6.3",
"webpack": "^4.41.0",
- "webpack-bundle-analyzer": "",
+ "webpack-bundle-analyzer": "^3.5.2",
"webpack-cli": "^3.3.9",
"xgettext-js": "^1.1.0",
"yarn": "^1.19.0"
@@ -66,7 +70,7 @@
"jsonwebtoken": "^8.5.1",
"markdown-it": "^8.4.2",
"moment": "^2.24.0",
- "ogs-goban": "file:../ogs-goban",
+ "goban": "file:../goban",
"prop-types": "^15.5.0",
"query-string": "^5.0.1",
"react": "^16.9.0",
@@ -84,10 +88,8 @@
"react-virtualized": "^9.21.0",
"redux": "^3.7.2",
"sanitize-html": "^1.14.1",
- "slugify": "^1.3.4",
"ts-md5": "^1.2.5",
"valid-url": "^1.0.9",
- "webpack-bundle-analyzer": "^3.4.1",
"whatwg-fetch": "^3.0.0"
}
}
diff --git a/src/lib/configure-goban.ts b/src/lib/configure-goban.ts
new file mode 100644
index 0000000000..ccae749a8c
--- /dev/null
+++ b/src/lib/configure-goban.ts
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2012-2019 Online-Go.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import * as preferences from "preferences";
+import * as data from "data";
+import {get_clock_drift, get_network_latency, termination_socket} from 'sockets';
+import {current_language} from "translate";
+import {Goban, GoEngine, sfx, GoThemes} from 'goban';
+
+window['Goban'] = Goban;
+window['GoThemes'] = GoThemes;
+window['GoEngine'] = GoEngine;
+window['sfx'] = sfx;
+
+data.setDefault("custom.black", "#000000");
+data.setDefault("custom.white", "#FFFFFF");
+data.setDefault("custom.board", "#DCB35C");
+data.setDefault("custom.line", "#000000");
+
+export function configure_goban() {
+ Goban.setHooks({
+ defaultConfig: () => {
+ return {
+ server_socket : termination_socket,
+ player_id : (data.get("user").anonymous ? 0 : data.get("user").id),
+ };
+ },
+
+ getCoordinateDisplaySystem: ():'A1'|'1-1' => {
+ switch (preferences.get('board-labeling')) {
+ case 'A1':
+ return 'A1';
+ case '1-1':
+ return '1-1';
+ default: // auto
+ switch (current_language) {
+ case 'ko':
+ case 'ja':
+ case 'zh-cn':
+ return '1-1';
+ default:
+ return 'A1';
+ }
+ }
+ },
+
+ isAnalysisDisabled: (goban:Goban, perGameSettingAppliesToNonPlayers = false):boolean => {
+ // The player's preference setting to always disable analysis overrides the per-game setting for
+ // their own games.
+ if (preferences.get("always-disable-analysis") && goban.isParticipatingPlayer()) {
+ return true;
+ }
+
+ // If the user hasn't enabled the always-disable-analysis option (or they do not participate in this game),
+ // we check the per-game setting.
+ if (perGameSettingAppliesToNonPlayers) {
+ // This is used for the SGF download which is disabled even for users that are not
+ // participating in the game (or not signed in)
+ return goban.engine.config.original_disable_analysis;
+ } else {
+ return goban.engine.config.disable_analysis;
+ }
+ },
+
+ getClockDrift: ():number => get_clock_drift(),
+ getNetworkLatency: ():number => get_network_latency(),
+ getLocation: ():string => window.location.pathname,
+ getShowMoveNumbers: ():boolean => !!preferences.get("show-move-numbers"),
+ getShowVariationMoveNumbers: ():boolean => preferences.get("show-variation-move-numbers"),
+ getMoveTreeNumbering: ():string => preferences.get("move-tree-numbering"),
+ getCDNReleaseBase: ():string => data.get('config.cdn_release'),
+ getSoundEnabled: ():boolean => !!preferences.get('sound-enabled'),
+ getSoundVolume: ():number => preferences.get('sound-volume') as number,
+
+ watchSelectedThemes: (cb) => preferences.watchSelectedThemes(cb),
+ getSelectedThemes: () => preferences.getSelectedThemes(),
+
+ discBlackStoneColor: ():string => data.get("custom.black"),
+ discBlackTextColor: ():string => data.get("custom.white"),
+ discWhiteStoneColor: ():string => data.get("custom.white"),
+ discWhiteTextColor: ():string => data.get("custom.black"),
+ plainBoardColor: ():string => data.get("custom.board"),
+ plainBoardLineColor: ():string => data.get("custom.line"),
+ });
+}
diff --git a/src/lib/goban-themes/board_plain.ts b/src/lib/goban-themes/board_plain.ts
deleted file mode 100644
index f54bdb1386..0000000000
--- a/src/lib/goban-themes/board_plain.ts
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2012-2019 Online-Go.com
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import { GoTheme } from "ogs-goban";
-import {_} from "../translate";
-import * as data from "data";
-
-data.setDefault("custom.board", "#DCB35C");
-data.setDefault("custom.line", "#000000");
-
-// Converts a six-digit hex string to rgba() notation
-function hexToRgba(raw: string, alpha: number = 1): string {
- let hex = raw.replace("#", "");
- if (hex.length !== 6) {
- return raw;
- }
- let r = parseInt(`0x${hex.substr(0, 2)}`);
- let g = parseInt(`0x${hex.substr(2, 2)}`);
- let b = parseInt(`0x${hex.substr(4, 2)}`);
- return `rgba(${r}, ${g}, ${b}, ${alpha})`;
-}
-
-export default function(GoThemes) {
-
- class Plain extends GoTheme {
- sort() { return 0; }
- getBackgroundCSS() {
- return {
- "background-color": data.get("custom.board"),
- "background-image": ""
- };
- }
- getLineColor() { return data.get("custom.line"); }
- getFadedLineColor() { return hexToRgba(data.get("custom.line"), 0.5); }
- getStarColor() { return data.get("custom.line"); }
- getFadedStarColor() { return hexToRgba(data.get("custom.line"), 0.5); }
- getBlankTextColor() { return data.get("custom.line"); }
- getLabelTextColor() { return hexToRgba(data.get("custom.line"), 0.75); }
- }
-
-
- _("Plain"); // ensure translation exists
- GoThemes["board"]["Plain"] = Plain;
-
- class Night extends GoTheme {
- sort() {
- return 100;
- }
- getBackgroundCSS() {
- return {
- "background-color": "#444444",
- "background-image": ""
- };
- }
- getLineColor() { return "#555555"; }
- getFadedLineColor() { return "#333333"; }
- getStarColor() { return "#555555"; }
- getFadedStarColor() { return "#333333"; }
- getBlankTextColor() { return "#777777"; }
- getLabelTextColor() { return "#555555"; }
- }
-
- _("Night Play"); // ensure translation exists
- GoThemes["board"]["Night Play"] = Night;
-
-
-
- class HNG extends GoTheme {
- static C = "#00193E";
- static C2 = "#004C75";
- sort() { return 105; }
- getBackgroundCSS() {
- return {
- "background-color": "#00e7fc",
- "background-image": ""
- };
- }
- getLineColor() { return HNG.C; }
- getFadedLineColor() { return "#00AFBF"; }
- getStarColor() { return HNG.C; }
- getFadedStarColor() { return "#00AFBF"; }
- getBlankTextColor() { return HNG.C2; }
- getLabelTextColor() { return HNG.C2; }
- }
-
- _("HNG"); // ensure translation exists
- GoThemes["board"]["HNG"] = HNG;
-
-
-
- class HNGNight extends GoTheme {
- static C = "#007591";
- sort() { return 105; }
- getBackgroundCSS() {
- return {
- "background-color": "#090C1F",
- "background-image": ""
- };
- }
- getLineColor() { return HNGNight.C; }
- getFadedLineColor() { return "#4481B5"; }
- getStarColor() { return HNGNight.C; }
- getFadedStarColor() { return "#4481B5"; }
- getBlankTextColor() { return "#3591DE"; }
- getLabelTextColor() { return "#4481B5"; }
- }
-
- _("HNG Night"); // ensure translation exists
- GoThemes["board"]["HNG Night"] = HNGNight;
-
-
- class Book extends GoTheme {
- sort() {
- return 110;
- }
- getBackgroundCSS() {
- return {
- "background-color": "#ffffff",
- "background-image": ""
- };
- }
- getLineColor() { return "#555555"; }
- getFadedLineColor() { return "#999999"; }
- getStarColor() { return "#555555"; }
- getFadedStarColor() { return "#999999"; }
- getBlankTextColor() { return "#000000"; }
- getLabelTextColor() { return "#555555"; }
- }
-
-
- _("Book"); // ensure translation exists
- GoThemes["board"]["Book"] = Book;
-}
diff --git a/src/lib/goban-themes/board_woods.ts b/src/lib/goban-themes/board_woods.ts
deleted file mode 100644
index 73fdfe2deb..0000000000
--- a/src/lib/goban-themes/board_woods.ts
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 2012-2019 Online-Go.com
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import { Goban, GoTheme } from "ogs-goban";
-import {_} from "../translate";
-
-
-export default function(GoThemes) {
- class Kaya extends GoTheme {
- sort() { return 10; }
- getBackgroundCSS() {
- return {
- "background-color": "#DCB35C",
- "background-image": "url('" + Goban.getCDNReleaseBase() + "/img/kaya.jpg')"
- };
- }
- getLineColor() { return "#000000"; }
- getFadedLineColor() { return "#888888"; }
- getStarColor() { return "#000000"; }
- getFadedStarColor() { return "#888888"; }
- getBlankTextColor() { return "#000000"; }
- getLabelTextColor() { return "#444444"; }
- }
-
- _("Kaya"); // ensure translation
- GoThemes["board"]["Kaya"] = Kaya;
-
-
- class RedOak extends GoTheme {
- sort() { return 20; }
- getBackgroundCSS() {
- return {
- "background-color": "#DCB35C",
- "background-image": "url('" + Goban.getCDNReleaseBase() + "/img/oak.jpg')"
- };
- }
- getLineColor() { return "#000000"; }
- getFadedLineColor() { return "#888888"; }
- getStarColor() { return "#000000"; }
- getFadedStarColor() { return "#888888"; }
- getBlankTextColor() { return "#000000"; }
- getLabelTextColor() { return "#000000"; }
- }
-
-
- _("Red Oak"); // ensure translation
- GoThemes["board"]["Red Oak"] = RedOak;
-
-
-
- class Persimmon extends GoTheme {
- sort() { return 30; }
- getBackgroundCSS() {
- return {
- "background-color": "#DCB35C",
- "background-image": "url('" + Goban.getCDNReleaseBase() + "/img/persimmon.jpg')"
- };
- }
- getLineColor() { return "#000000"; }
- getFadedLineColor() { return "#888888"; }
- getStarColor() { return "#000000"; }
- getFadedStarColor() { return "#888888"; }
- getBlankTextColor() { return "#000000"; }
- getLabelTextColor() { return "#000000"; }
- }
-
-
- _("Persimmon"); // ensure translation
- GoThemes["board"]["Persimmon"] = Persimmon;
-
-
- class BlackWalnut extends GoTheme {
- sort() { return 40; }
- getBackgroundCSS() {
- return {
- "background-color": "#DCB35C",
- "background-image": "url('" + Goban.getCDNReleaseBase() + "/img/black_walnut.jpg')"
- };
- }
- getLineColor() { return "#000000"; }
- getFadedLineColor() { return "#4A2F24"; }
- getStarColor() { return "#000000"; }
- getFadedStarColor() { return "#4A2F24"; }
- getBlankTextColor() { return "#000000"; }
- getLabelTextColor() { return "#000000"; }
- }
-
-
- _("Black Walnut"); // ensure translation
- GoThemes["board"]["Black Walnut"] = BlackWalnut;
-
-
- class Granite extends GoTheme {
- sort() { return 40; }
- getBackgroundCSS() {
- return {
- "background-color": "#DCB35C",
- "background-image": "url('" + Goban.getCDNReleaseBase() + "/img/granite.jpg')"
- };
- }
- getLineColor() { return "#cccccc"; }
- getFadedLineColor() { return "#888888"; }
- getStarColor() { return "#cccccc"; }
- getFadedStarColor() { return "#888888"; }
- getBlankTextColor() { return "#cccccc"; }
- getLabelTextColor() { return "#cccccc"; }
- }
-
-
- _("Granite"); // ensure translation
- GoThemes["board"]["Granite"] = Granite;
-}
diff --git a/src/lib/goban-themes/disc.ts b/src/lib/goban-themes/disc.ts
deleted file mode 100644
index e5a7c8db8f..0000000000
--- a/src/lib/goban-themes/disc.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2012-2019 Online-Go.com
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import { GoTheme } from "ogs-goban";
-import {_} from "../translate";
-import * as data from "data";
-
-data.setDefault("custom.black", "#000000");
-data.setDefault("custom.white", "#FFFFFF");
-
-export default function(GoThemes) {
- class Stone extends GoTheme {
- sort() { return 0; }
-
- placePlainStone(ctx, cx, cy, radius, color) {
- let lineWidth = radius * 0.10;
- if (lineWidth < 0.3) {
- lineWidth = 0;
- }
- ctx.fillStyle = color;
- ctx.strokeStyle = this.parent ? this.parent.getLineColor() : this.getLineColor();
- if (lineWidth > 0) {
- ctx.lineWidth = lineWidth;
- }
- ctx.beginPath();
- ctx.arc(cx, cy, radius - lineWidth / 2, 0.001, 2 * Math.PI, false); /* 0.001 to workaround fucked up chrome bug */
- if (lineWidth > 0) {
- ctx.stroke();
- }
- ctx.fill();
- }
- }
-
- class Black extends Stone {
- preRenderBlack(radius, seed): any {
- return true;
- }
-
- placeBlackStone(ctx, shadow_ctx, stone, cx, cy, radius) {
- this.placePlainStone(ctx, cx, cy, radius, this.getBlackStoneColor());
- }
-
- public getBlackStoneColor() {
- return data.get("custom.black");
- }
-
- public getBlackTextColor() {
- return data.get("custom.white");
- }
- }
-
- class White extends Stone {
- preRenderWhite(radius, seed): any {
- return true;
- }
-
- placeWhiteStone(ctx, shadow_ctx, stone, cx, cy, radius) {
- this.placePlainStone(ctx, cx, cy, radius, this.getWhiteStoneColor());
- }
-
- public getWhiteStoneColor() {
- return data.get("custom.white");
- }
-
- public getWhiteTextColor() {
- return data.get("custom.black");
- }
- }
-
- GoThemes["black"]["Plain"] = Black;
- GoThemes["white"]["Plain"] = White;
-
-}
diff --git a/src/lib/goban-themes/rendered_stones.ts b/src/lib/goban-themes/rendered_stones.ts
deleted file mode 100644
index 28b178647e..0000000000
--- a/src/lib/goban-themes/rendered_stones.ts
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * Copyright 2012-2019 Online-Go.com
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import { GoTheme, deviceCanvasScalingRatio } from "ogs-goban";
-import {_} from "../translate";
-
-/**
- * Converts an RGB color value to HSL. Conversion formula
- * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
- * Assumes r, g, and b are contained in the set [0, 255] and
- * returns h, s, and l in the set [0, 1].
- *
- * @param Number r The red color value
- * @param Number g The green color value
- * @param Number b The blue color value
- * @return Array The HSL representation
- */
-function rgbToHsl(r, g, b) {
- r /= 255;
- g /= 255;
- b /= 255;
- let max = Math.max(r, g, b);
- let min = Math.min(r, g, b);
- let h;
- let s;
- let l = (max + min) / 2;
-
- if (max === min) {
- h = s = 0; // achromatic
- } else {
- let d = max - min;
- s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
- switch (max) {
- case r: h = (g - b) / d + (g < b ? 6 : 0); break;
- case g: h = (b - r) / d + 2; break;
- case b: h = (r - g) / d + 4; break;
- }
- h /= 6;
- }
-
- return [h, s, l];
-}
-
-/**
- * Converts an HSL color value to RGB. Conversion formula
- * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
- * Assumes h, s, and l are contained in the set [0, 1] and
- * returns r, g, and b in the set [0, 255].
- *
- * @param Number h The hue
- * @param Number s The saturation
- * @param Number l The lightness
- * @return Array The RGB representation
- */
-
-
-
-function hue2rgb(p, q, t) {
- if (t < 0) { t += 1; }
- if (t > 1) { t -= 1; }
- if (t < 1 / 6) { return p + (q - p) * 6 * t; }
- if (t < 1 / 2) { return q; }
- if (t < 2 / 3) { return p + (q - p) * (2 / 3 - t) * 6; }
- return p;
-}
-function hslToRgb(h, s, l) {
- let r;
- let g;
- let b;
-
- if (s === 0) {
- r = g = b = l; // achromatic
- } else {
- let q = l < 0.5 ? l * (1 + s) : l + s - l * s;
- let p = 2 * l - q;
- r = hue2rgb(p, q, h + 1 / 3);
- g = hue2rgb(p, q, h);
- b = hue2rgb(p, q, h - 1 / 3);
- }
-
- return [Math.min(255, r * 255), Math.min(255, g * 255), Math.min(255, b * 255)];
-}
-
-function add(A, B) {
- return [A[0] + B[0], A[1] + B[1], A[2] + B[2]];
-}
-function dot(A, B) {
- return A[0] * B[0] + A[1] * B[1] + A[2] * B[2];
-}
-function scale(A, x) {
- return [A[0] * x, A[1] * x, A[2] * x];
-}
-function length(A) {
- return Math.sqrt(dot(A, A));
-}
-function normalized(A) {
- return scale(A, 1 / length(A));
-}
-function stone_normal(x, y, radius) {
- let z = Math.sqrt(Math.max(0, radius * radius - x * x - y * y));
-
- let ret = normalized([x, y, z]);
- z = ret[2];
- ret[2] = z * z * (3 - 2 * z); /* scurve3 */
- //ret[2] = z*z*z*(z*(z*6-15)+10); /* scurve5 */
-
- return ret;
-}
-function square_size(radius, scaled) {
- return 2 * Math.ceil(radius) + (scaled ? 0 : 1);
-}
-function stone_center_in_square(radius, scaled) {
- return Math.ceil(radius) + (scaled ? 0 : 0.5);
-}
-function copyAlpha(ctx, width, height) {
- if (width <= 0 || height <= 0) {
- throw ("Invalid width/height given: " + (width + "x" + height));
- }
-
- let image = ctx.getImageData(0, 0, width, height);
- let ret = new Array(width * height);
- let idx = 0;
- let i = 0;
- for (let y = 0; y < height; ++y) {
- for (let x = 0; x < width; ++x) {
- ret[i] = image.data[idx + 3];
- idx += 4;
- ++i;
- }
- }
- return ret;
-}
-function pasteAlpha(ctx, alpha, width, height) {
- let image = ctx.getImageData(0, 0, width, height);
- let idx = 0;
- let i = 0;
-
- for (let y = 0; y < height; ++y) {
- for (let x = 0; x < width; ++x) {
- image.data[idx + 3] = alpha[i];
- idx += 4;
- ++i;
- }
- }
- ctx.putImageData(image, 0, 0);
-}
-function applyPhongShading(ctx, ss, center, radius, ambient, specular_hardness, diffuse_light_distance, specular_light_distance, light) {
- let image = ctx.getImageData(0, 0, ss, ss);
-
- let r2 = (radius + 1) * (radius + 1); /* alpha will save us from overrunning the image*/
- let look = [0, 0, 1];
-
- let idx = 0;
- let normal_idx = 0;
- for (let y = -center; y < ss - center; ++y) {
- for (let x = -center; x < ss - center; ++x) {
- let xxyy = x * x + y * y;
- if (xxyy < r2) {
- let r = image.data[idx];
- let g = image.data[idx + 1];
- let b = image.data[idx + 2];
-
- let N = stone_normal(x, y, radius);
- let diffuse_intensity = dot(N, light) / diffuse_light_distance;
- let H = normalized(add(light, look));
- let specular_intensity = Math.pow( dot(N, H), specular_hardness) / specular_light_distance;
-
- let hsl = rgbToHsl(r, g, b);
- hsl[2] = Math.min(1, hsl[2] * (ambient + diffuse_intensity) + (diffuse_intensity * 0.5) + specular_intensity);
- let rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
-
- image.data[idx] = rgb[0];
- image.data[idx + 1] = rgb[1];
- image.data[idx + 2] = rgb[2];
- }
-
- idx += 4;
- ++normal_idx;
- }
- }
-
- ctx.putImageData(image, 0, 0);
-}
-function clearAboveColor(ctx, width, height, r, g, b) {
- let image = ctx.getImageData(0, 0, width, height);
-
- let idx = 0;
- for (let y = 0; y < height; ++y) {
- for (let x = 0; x < width; ++x) {
- if (image.data[idx + 0] > r && image.data[idx + 1] > g && image.data[idx + 2] > b) {
- image.data[idx + 0] = 0;
- image.data[idx + 1] = 0;
- image.data[idx + 2] = 0;
- image.data[idx + 3] = 0;
- }
-
- idx += 4;
- }
- }
-
- ctx.putImageData(image, 0, 0);
-}
-function preRenderStone(radius, seed, options) {
-
- let dcsr = deviceCanvasScalingRatio();
- radius *= dcsr;
-
- let ss = square_size(radius, dcsr !== 1.0);
- let center = stone_center_in_square(radius, dcsr !== 1.0);
- let sss = radius * 2.5; /* Shadow square size */
-
- let stone;
- let shadow;
- let ctx;
- let shadow_ctx;
- if (typeof($) !== "undefined") {
- stone = $("