diff --git a/09dc86cf0c6ab1c2c094.js b/09dc86cf0c6ab1c2c094.js new file mode 100644 index 000000000..4ecc5e3dc --- /dev/null +++ b/09dc86cf0c6ab1c2c094.js @@ -0,0 +1,4441 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "../../node_modules/dat.gui/build/dat.gui.module.js": +/*!**********************************************************!*\ + !*** ../../node_modules/dat.gui/build/dat.gui.module.js ***! + \**********************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ GUI: () => (/* binding */ GUI$1), +/* harmony export */ color: () => (/* binding */ color), +/* harmony export */ controllers: () => (/* binding */ controllers), +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), +/* harmony export */ dom: () => (/* binding */ dom$1), +/* harmony export */ gui: () => (/* binding */ gui) +/* harmony export */ }); +/** + * dat-gui JavaScript Controller Library + * https://github.com/dataarts/dat.gui + * + * Copyright 2011 Data Arts Team, Google Creative Lab + * + * 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 + */ + +function ___$insertStyle(css) { + if (!css) { + return; + } + if (typeof window === 'undefined') { + return; + } + + var style = document.createElement('style'); + + style.setAttribute('type', 'text/css'); + style.innerHTML = css; + document.head.appendChild(style); + + return css; +} + +function colorToString (color, forceCSSHex) { + var colorFormat = color.__state.conversionName.toString(); + var r = Math.round(color.r); + var g = Math.round(color.g); + var b = Math.round(color.b); + var a = color.a; + var h = Math.round(color.h); + var s = color.s.toFixed(1); + var v = color.v.toFixed(1); + if (forceCSSHex || colorFormat === 'THREE_CHAR_HEX' || colorFormat === 'SIX_CHAR_HEX') { + var str = color.hex.toString(16); + while (str.length < 6) { + str = '0' + str; + } + return '#' + str; + } else if (colorFormat === 'CSS_RGB') { + return 'rgb(' + r + ',' + g + ',' + b + ')'; + } else if (colorFormat === 'CSS_RGBA') { + return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; + } else if (colorFormat === 'HEX') { + return '0x' + color.hex.toString(16); + } else if (colorFormat === 'RGB_ARRAY') { + return '[' + r + ',' + g + ',' + b + ']'; + } else if (colorFormat === 'RGBA_ARRAY') { + return '[' + r + ',' + g + ',' + b + ',' + a + ']'; + } else if (colorFormat === 'RGB_OBJ') { + return '{r:' + r + ',g:' + g + ',b:' + b + '}'; + } else if (colorFormat === 'RGBA_OBJ') { + return '{r:' + r + ',g:' + g + ',b:' + b + ',a:' + a + '}'; + } else if (colorFormat === 'HSV_OBJ') { + return '{h:' + h + ',s:' + s + ',v:' + v + '}'; + } else if (colorFormat === 'HSVA_OBJ') { + return '{h:' + h + ',s:' + s + ',v:' + v + ',a:' + a + '}'; + } + return 'unknown format'; +} + +var ARR_EACH = Array.prototype.forEach; +var ARR_SLICE = Array.prototype.slice; +var Common = { + BREAK: {}, + extend: function extend(target) { + this.each(ARR_SLICE.call(arguments, 1), function (obj) { + var keys = this.isObject(obj) ? Object.keys(obj) : []; + keys.forEach(function (key) { + if (!this.isUndefined(obj[key])) { + target[key] = obj[key]; + } + }.bind(this)); + }, this); + return target; + }, + defaults: function defaults(target) { + this.each(ARR_SLICE.call(arguments, 1), function (obj) { + var keys = this.isObject(obj) ? Object.keys(obj) : []; + keys.forEach(function (key) { + if (this.isUndefined(target[key])) { + target[key] = obj[key]; + } + }.bind(this)); + }, this); + return target; + }, + compose: function compose() { + var toCall = ARR_SLICE.call(arguments); + return function () { + var args = ARR_SLICE.call(arguments); + for (var i = toCall.length - 1; i >= 0; i--) { + args = [toCall[i].apply(this, args)]; + } + return args[0]; + }; + }, + each: function each(obj, itr, scope) { + if (!obj) { + return; + } + if (ARR_EACH && obj.forEach && obj.forEach === ARR_EACH) { + obj.forEach(itr, scope); + } else if (obj.length === obj.length + 0) { + var key = void 0; + var l = void 0; + for (key = 0, l = obj.length; key < l; key++) { + if (key in obj && itr.call(scope, obj[key], key) === this.BREAK) { + return; + } + } + } else { + for (var _key in obj) { + if (itr.call(scope, obj[_key], _key) === this.BREAK) { + return; + } + } + } + }, + defer: function defer(fnc) { + setTimeout(fnc, 0); + }, + debounce: function debounce(func, threshold, callImmediately) { + var timeout = void 0; + return function () { + var obj = this; + var args = arguments; + function delayed() { + timeout = null; + if (!callImmediately) func.apply(obj, args); + } + var callNow = callImmediately || !timeout; + clearTimeout(timeout); + timeout = setTimeout(delayed, threshold); + if (callNow) { + func.apply(obj, args); + } + }; + }, + toArray: function toArray(obj) { + if (obj.toArray) return obj.toArray(); + return ARR_SLICE.call(obj); + }, + isUndefined: function isUndefined(obj) { + return obj === undefined; + }, + isNull: function isNull(obj) { + return obj === null; + }, + isNaN: function (_isNaN) { + function isNaN(_x) { + return _isNaN.apply(this, arguments); + } + isNaN.toString = function () { + return _isNaN.toString(); + }; + return isNaN; + }(function (obj) { + return isNaN(obj); + }), + isArray: Array.isArray || function (obj) { + return obj.constructor === Array; + }, + isObject: function isObject(obj) { + return obj === Object(obj); + }, + isNumber: function isNumber(obj) { + return obj === obj + 0; + }, + isString: function isString(obj) { + return obj === obj + ''; + }, + isBoolean: function isBoolean(obj) { + return obj === false || obj === true; + }, + isFunction: function isFunction(obj) { + return obj instanceof Function; + } +}; + +var INTERPRETATIONS = [ +{ + litmus: Common.isString, + conversions: { + THREE_CHAR_HEX: { + read: function read(original) { + var test = original.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i); + if (test === null) { + return false; + } + return { + space: 'HEX', + hex: parseInt('0x' + test[1].toString() + test[1].toString() + test[2].toString() + test[2].toString() + test[3].toString() + test[3].toString(), 0) + }; + }, + write: colorToString + }, + SIX_CHAR_HEX: { + read: function read(original) { + var test = original.match(/^#([A-F0-9]{6})$/i); + if (test === null) { + return false; + } + return { + space: 'HEX', + hex: parseInt('0x' + test[1].toString(), 0) + }; + }, + write: colorToString + }, + CSS_RGB: { + read: function read(original) { + var test = original.match(/^rgb\(\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*\)/); + if (test === null) { + return false; + } + return { + space: 'RGB', + r: parseFloat(test[1]), + g: parseFloat(test[2]), + b: parseFloat(test[3]) + }; + }, + write: colorToString + }, + CSS_RGBA: { + read: function read(original) { + var test = original.match(/^rgba\(\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*\)/); + if (test === null) { + return false; + } + return { + space: 'RGB', + r: parseFloat(test[1]), + g: parseFloat(test[2]), + b: parseFloat(test[3]), + a: parseFloat(test[4]) + }; + }, + write: colorToString + } + } +}, +{ + litmus: Common.isNumber, + conversions: { + HEX: { + read: function read(original) { + return { + space: 'HEX', + hex: original, + conversionName: 'HEX' + }; + }, + write: function write(color) { + return color.hex; + } + } + } +}, +{ + litmus: Common.isArray, + conversions: { + RGB_ARRAY: { + read: function read(original) { + if (original.length !== 3) { + return false; + } + return { + space: 'RGB', + r: original[0], + g: original[1], + b: original[2] + }; + }, + write: function write(color) { + return [color.r, color.g, color.b]; + } + }, + RGBA_ARRAY: { + read: function read(original) { + if (original.length !== 4) return false; + return { + space: 'RGB', + r: original[0], + g: original[1], + b: original[2], + a: original[3] + }; + }, + write: function write(color) { + return [color.r, color.g, color.b, color.a]; + } + } + } +}, +{ + litmus: Common.isObject, + conversions: { + RGBA_OBJ: { + read: function read(original) { + if (Common.isNumber(original.r) && Common.isNumber(original.g) && Common.isNumber(original.b) && Common.isNumber(original.a)) { + return { + space: 'RGB', + r: original.r, + g: original.g, + b: original.b, + a: original.a + }; + } + return false; + }, + write: function write(color) { + return { + r: color.r, + g: color.g, + b: color.b, + a: color.a + }; + } + }, + RGB_OBJ: { + read: function read(original) { + if (Common.isNumber(original.r) && Common.isNumber(original.g) && Common.isNumber(original.b)) { + return { + space: 'RGB', + r: original.r, + g: original.g, + b: original.b + }; + } + return false; + }, + write: function write(color) { + return { + r: color.r, + g: color.g, + b: color.b + }; + } + }, + HSVA_OBJ: { + read: function read(original) { + if (Common.isNumber(original.h) && Common.isNumber(original.s) && Common.isNumber(original.v) && Common.isNumber(original.a)) { + return { + space: 'HSV', + h: original.h, + s: original.s, + v: original.v, + a: original.a + }; + } + return false; + }, + write: function write(color) { + return { + h: color.h, + s: color.s, + v: color.v, + a: color.a + }; + } + }, + HSV_OBJ: { + read: function read(original) { + if (Common.isNumber(original.h) && Common.isNumber(original.s) && Common.isNumber(original.v)) { + return { + space: 'HSV', + h: original.h, + s: original.s, + v: original.v + }; + } + return false; + }, + write: function write(color) { + return { + h: color.h, + s: color.s, + v: color.v + }; + } + } + } +}]; +var result = void 0; +var toReturn = void 0; +var interpret = function interpret() { + toReturn = false; + var original = arguments.length > 1 ? Common.toArray(arguments) : arguments[0]; + Common.each(INTERPRETATIONS, function (family) { + if (family.litmus(original)) { + Common.each(family.conversions, function (conversion, conversionName) { + result = conversion.read(original); + if (toReturn === false && result !== false) { + toReturn = result; + result.conversionName = conversionName; + result.conversion = conversion; + return Common.BREAK; + } + }); + return Common.BREAK; + } + }); + return toReturn; +}; + +var tmpComponent = void 0; +var ColorMath = { + hsv_to_rgb: function hsv_to_rgb(h, s, v) { + var hi = Math.floor(h / 60) % 6; + var f = h / 60 - Math.floor(h / 60); + var p = v * (1.0 - s); + var q = v * (1.0 - f * s); + var t = v * (1.0 - (1.0 - f) * s); + var c = [[v, t, p], [q, v, p], [p, v, t], [p, q, v], [t, p, v], [v, p, q]][hi]; + return { + r: c[0] * 255, + g: c[1] * 255, + b: c[2] * 255 + }; + }, + rgb_to_hsv: function rgb_to_hsv(r, g, b) { + var min = Math.min(r, g, b); + var max = Math.max(r, g, b); + var delta = max - min; + var h = void 0; + var s = void 0; + if (max !== 0) { + s = delta / max; + } else { + return { + h: NaN, + s: 0, + v: 0 + }; + } + if (r === max) { + h = (g - b) / delta; + } else if (g === max) { + h = 2 + (b - r) / delta; + } else { + h = 4 + (r - g) / delta; + } + h /= 6; + if (h < 0) { + h += 1; + } + return { + h: h * 360, + s: s, + v: max / 255 + }; + }, + rgb_to_hex: function rgb_to_hex(r, g, b) { + var hex = this.hex_with_component(0, 2, r); + hex = this.hex_with_component(hex, 1, g); + hex = this.hex_with_component(hex, 0, b); + return hex; + }, + component_from_hex: function component_from_hex(hex, componentIndex) { + return hex >> componentIndex * 8 & 0xFF; + }, + hex_with_component: function hex_with_component(hex, componentIndex, value) { + return value << (tmpComponent = componentIndex * 8) | hex & ~(0xFF << tmpComponent); + } +}; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; +} : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; +}; + + + + + + + + + + + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; + +var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; +}(); + + + + + + + +var get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); + + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + + if (getter === undefined) { + return undefined; + } + + return getter.call(receiver); + } +}; + +var inherits = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; +}; + + + + + + + + + + + +var possibleConstructorReturn = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && (typeof call === "object" || typeof call === "function") ? call : self; +}; + +var Color = function () { + function Color() { + classCallCheck(this, Color); + this.__state = interpret.apply(this, arguments); + if (this.__state === false) { + throw new Error('Failed to interpret color arguments'); + } + this.__state.a = this.__state.a || 1; + } + createClass(Color, [{ + key: 'toString', + value: function toString() { + return colorToString(this); + } + }, { + key: 'toHexString', + value: function toHexString() { + return colorToString(this, true); + } + }, { + key: 'toOriginal', + value: function toOriginal() { + return this.__state.conversion.write(this); + } + }]); + return Color; +}(); +function defineRGBComponent(target, component, componentHexIndex) { + Object.defineProperty(target, component, { + get: function get$$1() { + if (this.__state.space === 'RGB') { + return this.__state[component]; + } + Color.recalculateRGB(this, component, componentHexIndex); + return this.__state[component]; + }, + set: function set$$1(v) { + if (this.__state.space !== 'RGB') { + Color.recalculateRGB(this, component, componentHexIndex); + this.__state.space = 'RGB'; + } + this.__state[component] = v; + } + }); +} +function defineHSVComponent(target, component) { + Object.defineProperty(target, component, { + get: function get$$1() { + if (this.__state.space === 'HSV') { + return this.__state[component]; + } + Color.recalculateHSV(this); + return this.__state[component]; + }, + set: function set$$1(v) { + if (this.__state.space !== 'HSV') { + Color.recalculateHSV(this); + this.__state.space = 'HSV'; + } + this.__state[component] = v; + } + }); +} +Color.recalculateRGB = function (color, component, componentHexIndex) { + if (color.__state.space === 'HEX') { + color.__state[component] = ColorMath.component_from_hex(color.__state.hex, componentHexIndex); + } else if (color.__state.space === 'HSV') { + Common.extend(color.__state, ColorMath.hsv_to_rgb(color.__state.h, color.__state.s, color.__state.v)); + } else { + throw new Error('Corrupted color state'); + } +}; +Color.recalculateHSV = function (color) { + var result = ColorMath.rgb_to_hsv(color.r, color.g, color.b); + Common.extend(color.__state, { + s: result.s, + v: result.v + }); + if (!Common.isNaN(result.h)) { + color.__state.h = result.h; + } else if (Common.isUndefined(color.__state.h)) { + color.__state.h = 0; + } +}; +Color.COMPONENTS = ['r', 'g', 'b', 'h', 's', 'v', 'hex', 'a']; +defineRGBComponent(Color.prototype, 'r', 2); +defineRGBComponent(Color.prototype, 'g', 1); +defineRGBComponent(Color.prototype, 'b', 0); +defineHSVComponent(Color.prototype, 'h'); +defineHSVComponent(Color.prototype, 's'); +defineHSVComponent(Color.prototype, 'v'); +Object.defineProperty(Color.prototype, 'a', { + get: function get$$1() { + return this.__state.a; + }, + set: function set$$1(v) { + this.__state.a = v; + } +}); +Object.defineProperty(Color.prototype, 'hex', { + get: function get$$1() { + if (this.__state.space !== 'HEX') { + this.__state.hex = ColorMath.rgb_to_hex(this.r, this.g, this.b); + this.__state.space = 'HEX'; + } + return this.__state.hex; + }, + set: function set$$1(v) { + this.__state.space = 'HEX'; + this.__state.hex = v; + } +}); + +var Controller = function () { + function Controller(object, property) { + classCallCheck(this, Controller); + this.initialValue = object[property]; + this.domElement = document.createElement('div'); + this.object = object; + this.property = property; + this.__onChange = undefined; + this.__onFinishChange = undefined; + } + createClass(Controller, [{ + key: 'onChange', + value: function onChange(fnc) { + this.__onChange = fnc; + return this; + } + }, { + key: 'onFinishChange', + value: function onFinishChange(fnc) { + this.__onFinishChange = fnc; + return this; + } + }, { + key: 'setValue', + value: function setValue(newValue) { + this.object[this.property] = newValue; + if (this.__onChange) { + this.__onChange.call(this, newValue); + } + this.updateDisplay(); + return this; + } + }, { + key: 'getValue', + value: function getValue() { + return this.object[this.property]; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + return this; + } + }, { + key: 'isModified', + value: function isModified() { + return this.initialValue !== this.getValue(); + } + }]); + return Controller; +}(); + +var EVENT_MAP = { + HTMLEvents: ['change'], + MouseEvents: ['click', 'mousemove', 'mousedown', 'mouseup', 'mouseover'], + KeyboardEvents: ['keydown'] +}; +var EVENT_MAP_INV = {}; +Common.each(EVENT_MAP, function (v, k) { + Common.each(v, function (e) { + EVENT_MAP_INV[e] = k; + }); +}); +var CSS_VALUE_PIXELS = /(\d+(\.\d+)?)px/; +function cssValueToPixels(val) { + if (val === '0' || Common.isUndefined(val)) { + return 0; + } + var match = val.match(CSS_VALUE_PIXELS); + if (!Common.isNull(match)) { + return parseFloat(match[1]); + } + return 0; +} +var dom = { + makeSelectable: function makeSelectable(elem, selectable) { + if (elem === undefined || elem.style === undefined) return; + elem.onselectstart = selectable ? function () { + return false; + } : function () {}; + elem.style.MozUserSelect = selectable ? 'auto' : 'none'; + elem.style.KhtmlUserSelect = selectable ? 'auto' : 'none'; + elem.unselectable = selectable ? 'on' : 'off'; + }, + makeFullscreen: function makeFullscreen(elem, hor, vert) { + var vertical = vert; + var horizontal = hor; + if (Common.isUndefined(horizontal)) { + horizontal = true; + } + if (Common.isUndefined(vertical)) { + vertical = true; + } + elem.style.position = 'absolute'; + if (horizontal) { + elem.style.left = 0; + elem.style.right = 0; + } + if (vertical) { + elem.style.top = 0; + elem.style.bottom = 0; + } + }, + fakeEvent: function fakeEvent(elem, eventType, pars, aux) { + var params = pars || {}; + var className = EVENT_MAP_INV[eventType]; + if (!className) { + throw new Error('Event type ' + eventType + ' not supported.'); + } + var evt = document.createEvent(className); + switch (className) { + case 'MouseEvents': + { + var clientX = params.x || params.clientX || 0; + var clientY = params.y || params.clientY || 0; + evt.initMouseEvent(eventType, params.bubbles || false, params.cancelable || true, window, params.clickCount || 1, 0, + 0, + clientX, + clientY, + false, false, false, false, 0, null); + break; + } + case 'KeyboardEvents': + { + var init = evt.initKeyboardEvent || evt.initKeyEvent; + Common.defaults(params, { + cancelable: true, + ctrlKey: false, + altKey: false, + shiftKey: false, + metaKey: false, + keyCode: undefined, + charCode: undefined + }); + init(eventType, params.bubbles || false, params.cancelable, window, params.ctrlKey, params.altKey, params.shiftKey, params.metaKey, params.keyCode, params.charCode); + break; + } + default: + { + evt.initEvent(eventType, params.bubbles || false, params.cancelable || true); + break; + } + } + Common.defaults(evt, aux); + elem.dispatchEvent(evt); + }, + bind: function bind(elem, event, func, newBool) { + var bool = newBool || false; + if (elem.addEventListener) { + elem.addEventListener(event, func, bool); + } else if (elem.attachEvent) { + elem.attachEvent('on' + event, func); + } + return dom; + }, + unbind: function unbind(elem, event, func, newBool) { + var bool = newBool || false; + if (elem.removeEventListener) { + elem.removeEventListener(event, func, bool); + } else if (elem.detachEvent) { + elem.detachEvent('on' + event, func); + } + return dom; + }, + addClass: function addClass(elem, className) { + if (elem.className === undefined) { + elem.className = className; + } else if (elem.className !== className) { + var classes = elem.className.split(/ +/); + if (classes.indexOf(className) === -1) { + classes.push(className); + elem.className = classes.join(' ').replace(/^\s+/, '').replace(/\s+$/, ''); + } + } + return dom; + }, + removeClass: function removeClass(elem, className) { + if (className) { + if (elem.className === className) { + elem.removeAttribute('class'); + } else { + var classes = elem.className.split(/ +/); + var index = classes.indexOf(className); + if (index !== -1) { + classes.splice(index, 1); + elem.className = classes.join(' '); + } + } + } else { + elem.className = undefined; + } + return dom; + }, + hasClass: function hasClass(elem, className) { + return new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)').test(elem.className) || false; + }, + getWidth: function getWidth(elem) { + var style = getComputedStyle(elem); + return cssValueToPixels(style['border-left-width']) + cssValueToPixels(style['border-right-width']) + cssValueToPixels(style['padding-left']) + cssValueToPixels(style['padding-right']) + cssValueToPixels(style.width); + }, + getHeight: function getHeight(elem) { + var style = getComputedStyle(elem); + return cssValueToPixels(style['border-top-width']) + cssValueToPixels(style['border-bottom-width']) + cssValueToPixels(style['padding-top']) + cssValueToPixels(style['padding-bottom']) + cssValueToPixels(style.height); + }, + getOffset: function getOffset(el) { + var elem = el; + var offset = { left: 0, top: 0 }; + if (elem.offsetParent) { + do { + offset.left += elem.offsetLeft; + offset.top += elem.offsetTop; + elem = elem.offsetParent; + } while (elem); + } + return offset; + }, + isActive: function isActive(elem) { + return elem === document.activeElement && (elem.type || elem.href); + } +}; + +var BooleanController = function (_Controller) { + inherits(BooleanController, _Controller); + function BooleanController(object, property) { + classCallCheck(this, BooleanController); + var _this2 = possibleConstructorReturn(this, (BooleanController.__proto__ || Object.getPrototypeOf(BooleanController)).call(this, object, property)); + var _this = _this2; + _this2.__prev = _this2.getValue(); + _this2.__checkbox = document.createElement('input'); + _this2.__checkbox.setAttribute('type', 'checkbox'); + function onChange() { + _this.setValue(!_this.__prev); + } + dom.bind(_this2.__checkbox, 'change', onChange, false); + _this2.domElement.appendChild(_this2.__checkbox); + _this2.updateDisplay(); + return _this2; + } + createClass(BooleanController, [{ + key: 'setValue', + value: function setValue(v) { + var toReturn = get(BooleanController.prototype.__proto__ || Object.getPrototypeOf(BooleanController.prototype), 'setValue', this).call(this, v); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + this.__prev = this.getValue(); + return toReturn; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + if (this.getValue() === true) { + this.__checkbox.setAttribute('checked', 'checked'); + this.__checkbox.checked = true; + this.__prev = true; + } else { + this.__checkbox.checked = false; + this.__prev = false; + } + return get(BooleanController.prototype.__proto__ || Object.getPrototypeOf(BooleanController.prototype), 'updateDisplay', this).call(this); + } + }]); + return BooleanController; +}(Controller); + +var OptionController = function (_Controller) { + inherits(OptionController, _Controller); + function OptionController(object, property, opts) { + classCallCheck(this, OptionController); + var _this2 = possibleConstructorReturn(this, (OptionController.__proto__ || Object.getPrototypeOf(OptionController)).call(this, object, property)); + var options = opts; + var _this = _this2; + _this2.__select = document.createElement('select'); + if (Common.isArray(options)) { + var map = {}; + Common.each(options, function (element) { + map[element] = element; + }); + options = map; + } + Common.each(options, function (value, key) { + var opt = document.createElement('option'); + opt.innerHTML = key; + opt.setAttribute('value', value); + _this.__select.appendChild(opt); + }); + _this2.updateDisplay(); + dom.bind(_this2.__select, 'change', function () { + var desiredValue = this.options[this.selectedIndex].value; + _this.setValue(desiredValue); + }); + _this2.domElement.appendChild(_this2.__select); + return _this2; + } + createClass(OptionController, [{ + key: 'setValue', + value: function setValue(v) { + var toReturn = get(OptionController.prototype.__proto__ || Object.getPrototypeOf(OptionController.prototype), 'setValue', this).call(this, v); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + return toReturn; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + if (dom.isActive(this.__select)) return this; + this.__select.value = this.getValue(); + return get(OptionController.prototype.__proto__ || Object.getPrototypeOf(OptionController.prototype), 'updateDisplay', this).call(this); + } + }]); + return OptionController; +}(Controller); + +var StringController = function (_Controller) { + inherits(StringController, _Controller); + function StringController(object, property) { + classCallCheck(this, StringController); + var _this2 = possibleConstructorReturn(this, (StringController.__proto__ || Object.getPrototypeOf(StringController)).call(this, object, property)); + var _this = _this2; + function onChange() { + _this.setValue(_this.__input.value); + } + function onBlur() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + _this2.__input = document.createElement('input'); + _this2.__input.setAttribute('type', 'text'); + dom.bind(_this2.__input, 'keyup', onChange); + dom.bind(_this2.__input, 'change', onChange); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + this.blur(); + } + }); + _this2.updateDisplay(); + _this2.domElement.appendChild(_this2.__input); + return _this2; + } + createClass(StringController, [{ + key: 'updateDisplay', + value: function updateDisplay() { + if (!dom.isActive(this.__input)) { + this.__input.value = this.getValue(); + } + return get(StringController.prototype.__proto__ || Object.getPrototypeOf(StringController.prototype), 'updateDisplay', this).call(this); + } + }]); + return StringController; +}(Controller); + +function numDecimals(x) { + var _x = x.toString(); + if (_x.indexOf('.') > -1) { + return _x.length - _x.indexOf('.') - 1; + } + return 0; +} +var NumberController = function (_Controller) { + inherits(NumberController, _Controller); + function NumberController(object, property, params) { + classCallCheck(this, NumberController); + var _this = possibleConstructorReturn(this, (NumberController.__proto__ || Object.getPrototypeOf(NumberController)).call(this, object, property)); + var _params = params || {}; + _this.__min = _params.min; + _this.__max = _params.max; + _this.__step = _params.step; + if (Common.isUndefined(_this.__step)) { + if (_this.initialValue === 0) { + _this.__impliedStep = 1; + } else { + _this.__impliedStep = Math.pow(10, Math.floor(Math.log(Math.abs(_this.initialValue)) / Math.LN10)) / 10; + } + } else { + _this.__impliedStep = _this.__step; + } + _this.__precision = numDecimals(_this.__impliedStep); + return _this; + } + createClass(NumberController, [{ + key: 'setValue', + value: function setValue(v) { + var _v = v; + if (this.__min !== undefined && _v < this.__min) { + _v = this.__min; + } else if (this.__max !== undefined && _v > this.__max) { + _v = this.__max; + } + if (this.__step !== undefined && _v % this.__step !== 0) { + _v = Math.round(_v / this.__step) * this.__step; + } + return get(NumberController.prototype.__proto__ || Object.getPrototypeOf(NumberController.prototype), 'setValue', this).call(this, _v); + } + }, { + key: 'min', + value: function min(minValue) { + this.__min = minValue; + return this; + } + }, { + key: 'max', + value: function max(maxValue) { + this.__max = maxValue; + return this; + } + }, { + key: 'step', + value: function step(stepValue) { + this.__step = stepValue; + this.__impliedStep = stepValue; + this.__precision = numDecimals(stepValue); + return this; + } + }]); + return NumberController; +}(Controller); + +function roundToDecimal(value, decimals) { + var tenTo = Math.pow(10, decimals); + return Math.round(value * tenTo) / tenTo; +} +var NumberControllerBox = function (_NumberController) { + inherits(NumberControllerBox, _NumberController); + function NumberControllerBox(object, property, params) { + classCallCheck(this, NumberControllerBox); + var _this2 = possibleConstructorReturn(this, (NumberControllerBox.__proto__ || Object.getPrototypeOf(NumberControllerBox)).call(this, object, property, params)); + _this2.__truncationSuspended = false; + var _this = _this2; + var prevY = void 0; + function onChange() { + var attempted = parseFloat(_this.__input.value); + if (!Common.isNaN(attempted)) { + _this.setValue(attempted); + } + } + function onFinish() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + function onBlur() { + onFinish(); + } + function onMouseDrag(e) { + var diff = prevY - e.clientY; + _this.setValue(_this.getValue() + diff * _this.__impliedStep); + prevY = e.clientY; + } + function onMouseUp() { + dom.unbind(window, 'mousemove', onMouseDrag); + dom.unbind(window, 'mouseup', onMouseUp); + onFinish(); + } + function onMouseDown(e) { + dom.bind(window, 'mousemove', onMouseDrag); + dom.bind(window, 'mouseup', onMouseUp); + prevY = e.clientY; + } + _this2.__input = document.createElement('input'); + _this2.__input.setAttribute('type', 'text'); + dom.bind(_this2.__input, 'change', onChange); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__input, 'mousedown', onMouseDown); + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + _this.__truncationSuspended = true; + this.blur(); + _this.__truncationSuspended = false; + onFinish(); + } + }); + _this2.updateDisplay(); + _this2.domElement.appendChild(_this2.__input); + return _this2; + } + createClass(NumberControllerBox, [{ + key: 'updateDisplay', + value: function updateDisplay() { + this.__input.value = this.__truncationSuspended ? this.getValue() : roundToDecimal(this.getValue(), this.__precision); + return get(NumberControllerBox.prototype.__proto__ || Object.getPrototypeOf(NumberControllerBox.prototype), 'updateDisplay', this).call(this); + } + }]); + return NumberControllerBox; +}(NumberController); + +function map(v, i1, i2, o1, o2) { + return o1 + (o2 - o1) * ((v - i1) / (i2 - i1)); +} +var NumberControllerSlider = function (_NumberController) { + inherits(NumberControllerSlider, _NumberController); + function NumberControllerSlider(object, property, min, max, step) { + classCallCheck(this, NumberControllerSlider); + var _this2 = possibleConstructorReturn(this, (NumberControllerSlider.__proto__ || Object.getPrototypeOf(NumberControllerSlider)).call(this, object, property, { min: min, max: max, step: step })); + var _this = _this2; + _this2.__background = document.createElement('div'); + _this2.__foreground = document.createElement('div'); + dom.bind(_this2.__background, 'mousedown', onMouseDown); + dom.bind(_this2.__background, 'touchstart', onTouchStart); + dom.addClass(_this2.__background, 'slider'); + dom.addClass(_this2.__foreground, 'slider-fg'); + function onMouseDown(e) { + document.activeElement.blur(); + dom.bind(window, 'mousemove', onMouseDrag); + dom.bind(window, 'mouseup', onMouseUp); + onMouseDrag(e); + } + function onMouseDrag(e) { + e.preventDefault(); + var bgRect = _this.__background.getBoundingClientRect(); + _this.setValue(map(e.clientX, bgRect.left, bgRect.right, _this.__min, _this.__max)); + return false; + } + function onMouseUp() { + dom.unbind(window, 'mousemove', onMouseDrag); + dom.unbind(window, 'mouseup', onMouseUp); + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + function onTouchStart(e) { + if (e.touches.length !== 1) { + return; + } + dom.bind(window, 'touchmove', onTouchMove); + dom.bind(window, 'touchend', onTouchEnd); + onTouchMove(e); + } + function onTouchMove(e) { + var clientX = e.touches[0].clientX; + var bgRect = _this.__background.getBoundingClientRect(); + _this.setValue(map(clientX, bgRect.left, bgRect.right, _this.__min, _this.__max)); + } + function onTouchEnd() { + dom.unbind(window, 'touchmove', onTouchMove); + dom.unbind(window, 'touchend', onTouchEnd); + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + _this2.updateDisplay(); + _this2.__background.appendChild(_this2.__foreground); + _this2.domElement.appendChild(_this2.__background); + return _this2; + } + createClass(NumberControllerSlider, [{ + key: 'updateDisplay', + value: function updateDisplay() { + var pct = (this.getValue() - this.__min) / (this.__max - this.__min); + this.__foreground.style.width = pct * 100 + '%'; + return get(NumberControllerSlider.prototype.__proto__ || Object.getPrototypeOf(NumberControllerSlider.prototype), 'updateDisplay', this).call(this); + } + }]); + return NumberControllerSlider; +}(NumberController); + +var FunctionController = function (_Controller) { + inherits(FunctionController, _Controller); + function FunctionController(object, property, text) { + classCallCheck(this, FunctionController); + var _this2 = possibleConstructorReturn(this, (FunctionController.__proto__ || Object.getPrototypeOf(FunctionController)).call(this, object, property)); + var _this = _this2; + _this2.__button = document.createElement('div'); + _this2.__button.innerHTML = text === undefined ? 'Fire' : text; + dom.bind(_this2.__button, 'click', function (e) { + e.preventDefault(); + _this.fire(); + return false; + }); + dom.addClass(_this2.__button, 'button'); + _this2.domElement.appendChild(_this2.__button); + return _this2; + } + createClass(FunctionController, [{ + key: 'fire', + value: function fire() { + if (this.__onChange) { + this.__onChange.call(this); + } + this.getValue().call(this.object); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + } + }]); + return FunctionController; +}(Controller); + +var ColorController = function (_Controller) { + inherits(ColorController, _Controller); + function ColorController(object, property) { + classCallCheck(this, ColorController); + var _this2 = possibleConstructorReturn(this, (ColorController.__proto__ || Object.getPrototypeOf(ColorController)).call(this, object, property)); + _this2.__color = new Color(_this2.getValue()); + _this2.__temp = new Color(0); + var _this = _this2; + _this2.domElement = document.createElement('div'); + dom.makeSelectable(_this2.domElement, false); + _this2.__selector = document.createElement('div'); + _this2.__selector.className = 'selector'; + _this2.__saturation_field = document.createElement('div'); + _this2.__saturation_field.className = 'saturation-field'; + _this2.__field_knob = document.createElement('div'); + _this2.__field_knob.className = 'field-knob'; + _this2.__field_knob_border = '2px solid '; + _this2.__hue_knob = document.createElement('div'); + _this2.__hue_knob.className = 'hue-knob'; + _this2.__hue_field = document.createElement('div'); + _this2.__hue_field.className = 'hue-field'; + _this2.__input = document.createElement('input'); + _this2.__input.type = 'text'; + _this2.__input_textShadow = '0 1px 1px '; + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + onBlur.call(this); + } + }); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__selector, 'mousedown', function () { + dom.addClass(this, 'drag').bind(window, 'mouseup', function () { + dom.removeClass(_this.__selector, 'drag'); + }); + }); + dom.bind(_this2.__selector, 'touchstart', function () { + dom.addClass(this, 'drag').bind(window, 'touchend', function () { + dom.removeClass(_this.__selector, 'drag'); + }); + }); + var valueField = document.createElement('div'); + Common.extend(_this2.__selector.style, { + width: '122px', + height: '102px', + padding: '3px', + backgroundColor: '#222', + boxShadow: '0px 1px 3px rgba(0,0,0,0.3)' + }); + Common.extend(_this2.__field_knob.style, { + position: 'absolute', + width: '12px', + height: '12px', + border: _this2.__field_knob_border + (_this2.__color.v < 0.5 ? '#fff' : '#000'), + boxShadow: '0px 1px 3px rgba(0,0,0,0.5)', + borderRadius: '12px', + zIndex: 1 + }); + Common.extend(_this2.__hue_knob.style, { + position: 'absolute', + width: '15px', + height: '2px', + borderRight: '4px solid #fff', + zIndex: 1 + }); + Common.extend(_this2.__saturation_field.style, { + width: '100px', + height: '100px', + border: '1px solid #555', + marginRight: '3px', + display: 'inline-block', + cursor: 'pointer' + }); + Common.extend(valueField.style, { + width: '100%', + height: '100%', + background: 'none' + }); + linearGradient(valueField, 'top', 'rgba(0,0,0,0)', '#000'); + Common.extend(_this2.__hue_field.style, { + width: '15px', + height: '100px', + border: '1px solid #555', + cursor: 'ns-resize', + position: 'absolute', + top: '3px', + right: '3px' + }); + hueGradient(_this2.__hue_field); + Common.extend(_this2.__input.style, { + outline: 'none', + textAlign: 'center', + color: '#fff', + border: 0, + fontWeight: 'bold', + textShadow: _this2.__input_textShadow + 'rgba(0,0,0,0.7)' + }); + dom.bind(_this2.__saturation_field, 'mousedown', fieldDown); + dom.bind(_this2.__saturation_field, 'touchstart', fieldDown); + dom.bind(_this2.__field_knob, 'mousedown', fieldDown); + dom.bind(_this2.__field_knob, 'touchstart', fieldDown); + dom.bind(_this2.__hue_field, 'mousedown', fieldDownH); + dom.bind(_this2.__hue_field, 'touchstart', fieldDownH); + function fieldDown(e) { + setSV(e); + dom.bind(window, 'mousemove', setSV); + dom.bind(window, 'touchmove', setSV); + dom.bind(window, 'mouseup', fieldUpSV); + dom.bind(window, 'touchend', fieldUpSV); + } + function fieldDownH(e) { + setH(e); + dom.bind(window, 'mousemove', setH); + dom.bind(window, 'touchmove', setH); + dom.bind(window, 'mouseup', fieldUpH); + dom.bind(window, 'touchend', fieldUpH); + } + function fieldUpSV() { + dom.unbind(window, 'mousemove', setSV); + dom.unbind(window, 'touchmove', setSV); + dom.unbind(window, 'mouseup', fieldUpSV); + dom.unbind(window, 'touchend', fieldUpSV); + onFinish(); + } + function fieldUpH() { + dom.unbind(window, 'mousemove', setH); + dom.unbind(window, 'touchmove', setH); + dom.unbind(window, 'mouseup', fieldUpH); + dom.unbind(window, 'touchend', fieldUpH); + onFinish(); + } + function onBlur() { + var i = interpret(this.value); + if (i !== false) { + _this.__color.__state = i; + _this.setValue(_this.__color.toOriginal()); + } else { + this.value = _this.__color.toString(); + } + } + function onFinish() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.__color.toOriginal()); + } + } + _this2.__saturation_field.appendChild(valueField); + _this2.__selector.appendChild(_this2.__field_knob); + _this2.__selector.appendChild(_this2.__saturation_field); + _this2.__selector.appendChild(_this2.__hue_field); + _this2.__hue_field.appendChild(_this2.__hue_knob); + _this2.domElement.appendChild(_this2.__input); + _this2.domElement.appendChild(_this2.__selector); + _this2.updateDisplay(); + function setSV(e) { + if (e.type.indexOf('touch') === -1) { + e.preventDefault(); + } + var fieldRect = _this.__saturation_field.getBoundingClientRect(); + var _ref = e.touches && e.touches[0] || e, + clientX = _ref.clientX, + clientY = _ref.clientY; + var s = (clientX - fieldRect.left) / (fieldRect.right - fieldRect.left); + var v = 1 - (clientY - fieldRect.top) / (fieldRect.bottom - fieldRect.top); + if (v > 1) { + v = 1; + } else if (v < 0) { + v = 0; + } + if (s > 1) { + s = 1; + } else if (s < 0) { + s = 0; + } + _this.__color.v = v; + _this.__color.s = s; + _this.setValue(_this.__color.toOriginal()); + return false; + } + function setH(e) { + if (e.type.indexOf('touch') === -1) { + e.preventDefault(); + } + var fieldRect = _this.__hue_field.getBoundingClientRect(); + var _ref2 = e.touches && e.touches[0] || e, + clientY = _ref2.clientY; + var h = 1 - (clientY - fieldRect.top) / (fieldRect.bottom - fieldRect.top); + if (h > 1) { + h = 1; + } else if (h < 0) { + h = 0; + } + _this.__color.h = h * 360; + _this.setValue(_this.__color.toOriginal()); + return false; + } + return _this2; + } + createClass(ColorController, [{ + key: 'updateDisplay', + value: function updateDisplay() { + var i = interpret(this.getValue()); + if (i !== false) { + var mismatch = false; + Common.each(Color.COMPONENTS, function (component) { + if (!Common.isUndefined(i[component]) && !Common.isUndefined(this.__color.__state[component]) && i[component] !== this.__color.__state[component]) { + mismatch = true; + return {}; + } + }, this); + if (mismatch) { + Common.extend(this.__color.__state, i); + } + } + Common.extend(this.__temp.__state, this.__color.__state); + this.__temp.a = 1; + var flip = this.__color.v < 0.5 || this.__color.s > 0.5 ? 255 : 0; + var _flip = 255 - flip; + Common.extend(this.__field_knob.style, { + marginLeft: 100 * this.__color.s - 7 + 'px', + marginTop: 100 * (1 - this.__color.v) - 7 + 'px', + backgroundColor: this.__temp.toHexString(), + border: this.__field_knob_border + 'rgb(' + flip + ',' + flip + ',' + flip + ')' + }); + this.__hue_knob.style.marginTop = (1 - this.__color.h / 360) * 100 + 'px'; + this.__temp.s = 1; + this.__temp.v = 1; + linearGradient(this.__saturation_field, 'left', '#fff', this.__temp.toHexString()); + this.__input.value = this.__color.toString(); + Common.extend(this.__input.style, { + backgroundColor: this.__color.toHexString(), + color: 'rgb(' + flip + ',' + flip + ',' + flip + ')', + textShadow: this.__input_textShadow + 'rgba(' + _flip + ',' + _flip + ',' + _flip + ',.7)' + }); + } + }]); + return ColorController; +}(Controller); +var vendors = ['-moz-', '-o-', '-webkit-', '-ms-', '']; +function linearGradient(elem, x, a, b) { + elem.style.background = ''; + Common.each(vendors, function (vendor) { + elem.style.cssText += 'background: ' + vendor + 'linear-gradient(' + x + ', ' + a + ' 0%, ' + b + ' 100%); '; + }); +} +function hueGradient(elem) { + elem.style.background = ''; + elem.style.cssText += 'background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);'; + elem.style.cssText += 'background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; +} + +var css = { + load: function load(url, indoc) { + var doc = indoc || document; + var link = doc.createElement('link'); + link.type = 'text/css'; + link.rel = 'stylesheet'; + link.href = url; + doc.getElementsByTagName('head')[0].appendChild(link); + }, + inject: function inject(cssContent, indoc) { + var doc = indoc || document; + var injected = document.createElement('style'); + injected.type = 'text/css'; + injected.innerHTML = cssContent; + var head = doc.getElementsByTagName('head')[0]; + try { + head.appendChild(injected); + } catch (e) { + } + } +}; + +var saveDialogContents = "
\n\n Here's the new load parameter for your GUI's constructor:\n\n \n\n
\n\n Automatically save\n values to localStorage on exit.\n\n
The values saved to localStorage will\n override those passed to dat.GUI's constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n\n
\n\n
\n\n
"; + +var ControllerFactory = function ControllerFactory(object, property) { + var initialValue = object[property]; + if (Common.isArray(arguments[2]) || Common.isObject(arguments[2])) { + return new OptionController(object, property, arguments[2]); + } + if (Common.isNumber(initialValue)) { + if (Common.isNumber(arguments[2]) && Common.isNumber(arguments[3])) { + if (Common.isNumber(arguments[4])) { + return new NumberControllerSlider(object, property, arguments[2], arguments[3], arguments[4]); + } + return new NumberControllerSlider(object, property, arguments[2], arguments[3]); + } + if (Common.isNumber(arguments[4])) { + return new NumberControllerBox(object, property, { min: arguments[2], max: arguments[3], step: arguments[4] }); + } + return new NumberControllerBox(object, property, { min: arguments[2], max: arguments[3] }); + } + if (Common.isString(initialValue)) { + return new StringController(object, property); + } + if (Common.isFunction(initialValue)) { + return new FunctionController(object, property, ''); + } + if (Common.isBoolean(initialValue)) { + return new BooleanController(object, property); + } + return null; +}; + +function requestAnimationFrame(callback) { + setTimeout(callback, 1000 / 60); +} +var requestAnimationFrame$1 = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || requestAnimationFrame; + +var CenteredDiv = function () { + function CenteredDiv() { + classCallCheck(this, CenteredDiv); + this.backgroundElement = document.createElement('div'); + Common.extend(this.backgroundElement.style, { + backgroundColor: 'rgba(0,0,0,0.8)', + top: 0, + left: 0, + display: 'none', + zIndex: '1000', + opacity: 0, + WebkitTransition: 'opacity 0.2s linear', + transition: 'opacity 0.2s linear' + }); + dom.makeFullscreen(this.backgroundElement); + this.backgroundElement.style.position = 'fixed'; + this.domElement = document.createElement('div'); + Common.extend(this.domElement.style, { + position: 'fixed', + display: 'none', + zIndex: '1001', + opacity: 0, + WebkitTransition: '-webkit-transform 0.2s ease-out, opacity 0.2s linear', + transition: 'transform 0.2s ease-out, opacity 0.2s linear' + }); + document.body.appendChild(this.backgroundElement); + document.body.appendChild(this.domElement); + var _this = this; + dom.bind(this.backgroundElement, 'click', function () { + _this.hide(); + }); + } + createClass(CenteredDiv, [{ + key: 'show', + value: function show() { + var _this = this; + this.backgroundElement.style.display = 'block'; + this.domElement.style.display = 'block'; + this.domElement.style.opacity = 0; + this.domElement.style.webkitTransform = 'scale(1.1)'; + this.layout(); + Common.defer(function () { + _this.backgroundElement.style.opacity = 1; + _this.domElement.style.opacity = 1; + _this.domElement.style.webkitTransform = 'scale(1)'; + }); + } + }, { + key: 'hide', + value: function hide() { + var _this = this; + var hide = function hide() { + _this.domElement.style.display = 'none'; + _this.backgroundElement.style.display = 'none'; + dom.unbind(_this.domElement, 'webkitTransitionEnd', hide); + dom.unbind(_this.domElement, 'transitionend', hide); + dom.unbind(_this.domElement, 'oTransitionEnd', hide); + }; + dom.bind(this.domElement, 'webkitTransitionEnd', hide); + dom.bind(this.domElement, 'transitionend', hide); + dom.bind(this.domElement, 'oTransitionEnd', hide); + this.backgroundElement.style.opacity = 0; + this.domElement.style.opacity = 0; + this.domElement.style.webkitTransform = 'scale(1.1)'; + } + }, { + key: 'layout', + value: function layout() { + this.domElement.style.left = window.innerWidth / 2 - dom.getWidth(this.domElement) / 2 + 'px'; + this.domElement.style.top = window.innerHeight / 2 - dom.getHeight(this.domElement) / 2 + 'px'; + } + }]); + return CenteredDiv; +}(); + +var styleSheet = ___$insertStyle(".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity .1s linear;-o-transition:opacity .1s linear;-moz-transition:opacity .1s linear;transition:opacity .1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1 !important}.dg.main:hover .close-button,.dg.main .close-button.drag{opacity:1}.dg.main .close-button{-webkit-transition:opacity .1s linear;-o-transition:opacity .1s linear;-moz-transition:opacity .1s linear;transition:opacity .1s linear;border:0;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button.close-top{position:relative}.dg.main .close-button.close-bottom{position:absolute}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-y:visible}.dg.a.has-save>ul.close-top{margin-top:0}.dg.a.has-save>ul.close-bottom{margin-top:27px}.dg.a.has-save>ul.closed{margin-top:0}.dg.a .save-row{top:0;z-index:1002}.dg.a .save-row.close-top{position:relative}.dg.a .save-row.close-bottom{position:fixed}.dg li{-webkit-transition:height .1s ease-out;-o-transition:height .1s ease-out;-moz-transition:height .1s ease-out;transition:height .1s ease-out;-webkit-transition:overflow .1s linear;-o-transition:overflow .1s linear;-moz-transition:overflow .1s linear;transition:overflow .1s linear}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid rgba(0,0,0,0)}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li>*{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px;overflow:hidden}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .cr.function .property-name{width:100%}.dg .c{float:left;width:60%;position:relative}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:7px}.dg .c select{margin-top:5px}.dg .cr.function,.dg .cr.function .property-name,.dg .cr.function *,.dg .cr.boolean,.dg .cr.boolean *{cursor:pointer}.dg .cr.color{overflow:visible}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0px 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco, monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px 'Lucida Grande', sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px 4px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid rgba(255,255,255,0.2)}.dg .closed li.title{background-image:url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==)}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.color{border-left:3px solid}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2FA1D6}.dg .cr.number input[type=text]{color:#2FA1D6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.function:hover,.dg .cr.boolean:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2FA1D6;max-width:100%}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}\n"); + +css.inject(styleSheet); +var CSS_NAMESPACE = 'dg'; +var HIDE_KEY_CODE = 72; +var CLOSE_BUTTON_HEIGHT = 20; +var DEFAULT_DEFAULT_PRESET_NAME = 'Default'; +var SUPPORTS_LOCAL_STORAGE = function () { + try { + return !!window.localStorage; + } catch (e) { + return false; + } +}(); +var SAVE_DIALOGUE = void 0; +var autoPlaceVirgin = true; +var autoPlaceContainer = void 0; +var hide = false; +var hideableGuis = []; +var GUI = function GUI(pars) { + var _this = this; + var params = pars || {}; + this.domElement = document.createElement('div'); + this.__ul = document.createElement('ul'); + this.domElement.appendChild(this.__ul); + dom.addClass(this.domElement, CSS_NAMESPACE); + this.__folders = {}; + this.__controllers = []; + this.__rememberedObjects = []; + this.__rememberedObjectIndecesToControllers = []; + this.__listening = []; + params = Common.defaults(params, { + closeOnTop: false, + autoPlace: true, + width: GUI.DEFAULT_WIDTH + }); + params = Common.defaults(params, { + resizable: params.autoPlace, + hideable: params.autoPlace + }); + if (!Common.isUndefined(params.load)) { + if (params.preset) { + params.load.preset = params.preset; + } + } else { + params.load = { preset: DEFAULT_DEFAULT_PRESET_NAME }; + } + if (Common.isUndefined(params.parent) && params.hideable) { + hideableGuis.push(this); + } + params.resizable = Common.isUndefined(params.parent) && params.resizable; + if (params.autoPlace && Common.isUndefined(params.scrollable)) { + params.scrollable = true; + } + var useLocalStorage = SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(this, 'isLocal')) === 'true'; + var saveToLocalStorage = void 0; + var titleRow = void 0; + Object.defineProperties(this, + { + parent: { + get: function get$$1() { + return params.parent; + } + }, + scrollable: { + get: function get$$1() { + return params.scrollable; + } + }, + autoPlace: { + get: function get$$1() { + return params.autoPlace; + } + }, + closeOnTop: { + get: function get$$1() { + return params.closeOnTop; + } + }, + preset: { + get: function get$$1() { + if (_this.parent) { + return _this.getRoot().preset; + } + return params.load.preset; + }, + set: function set$$1(v) { + if (_this.parent) { + _this.getRoot().preset = v; + } else { + params.load.preset = v; + } + setPresetSelectIndex(this); + _this.revert(); + } + }, + width: { + get: function get$$1() { + return params.width; + }, + set: function set$$1(v) { + params.width = v; + setWidth(_this, v); + } + }, + name: { + get: function get$$1() { + return params.name; + }, + set: function set$$1(v) { + params.name = v; + if (titleRow) { + titleRow.innerHTML = params.name; + } + } + }, + closed: { + get: function get$$1() { + return params.closed; + }, + set: function set$$1(v) { + params.closed = v; + if (params.closed) { + dom.addClass(_this.__ul, GUI.CLASS_CLOSED); + } else { + dom.removeClass(_this.__ul, GUI.CLASS_CLOSED); + } + this.onResize(); + if (_this.__closeButton) { + _this.__closeButton.innerHTML = v ? GUI.TEXT_OPEN : GUI.TEXT_CLOSED; + } + } + }, + load: { + get: function get$$1() { + return params.load; + } + }, + useLocalStorage: { + get: function get$$1() { + return useLocalStorage; + }, + set: function set$$1(bool) { + if (SUPPORTS_LOCAL_STORAGE) { + useLocalStorage = bool; + if (bool) { + dom.bind(window, 'unload', saveToLocalStorage); + } else { + dom.unbind(window, 'unload', saveToLocalStorage); + } + localStorage.setItem(getLocalStorageHash(_this, 'isLocal'), bool); + } + } + } + }); + if (Common.isUndefined(params.parent)) { + this.closed = params.closed || false; + dom.addClass(this.domElement, GUI.CLASS_MAIN); + dom.makeSelectable(this.domElement, false); + if (SUPPORTS_LOCAL_STORAGE) { + if (useLocalStorage) { + _this.useLocalStorage = true; + var savedGui = localStorage.getItem(getLocalStorageHash(this, 'gui')); + if (savedGui) { + params.load = JSON.parse(savedGui); + } + } + } + this.__closeButton = document.createElement('div'); + this.__closeButton.innerHTML = GUI.TEXT_CLOSED; + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_BUTTON); + if (params.closeOnTop) { + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_TOP); + this.domElement.insertBefore(this.__closeButton, this.domElement.childNodes[0]); + } else { + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_BOTTOM); + this.domElement.appendChild(this.__closeButton); + } + dom.bind(this.__closeButton, 'click', function () { + _this.closed = !_this.closed; + }); + } else { + if (params.closed === undefined) { + params.closed = true; + } + var titleRowName = document.createTextNode(params.name); + dom.addClass(titleRowName, 'controller-name'); + titleRow = addRow(_this, titleRowName); + var onClickTitle = function onClickTitle(e) { + e.preventDefault(); + _this.closed = !_this.closed; + return false; + }; + dom.addClass(this.__ul, GUI.CLASS_CLOSED); + dom.addClass(titleRow, 'title'); + dom.bind(titleRow, 'click', onClickTitle); + if (!params.closed) { + this.closed = false; + } + } + if (params.autoPlace) { + if (Common.isUndefined(params.parent)) { + if (autoPlaceVirgin) { + autoPlaceContainer = document.createElement('div'); + dom.addClass(autoPlaceContainer, CSS_NAMESPACE); + dom.addClass(autoPlaceContainer, GUI.CLASS_AUTO_PLACE_CONTAINER); + document.body.appendChild(autoPlaceContainer); + autoPlaceVirgin = false; + } + autoPlaceContainer.appendChild(this.domElement); + dom.addClass(this.domElement, GUI.CLASS_AUTO_PLACE); + } + if (!this.parent) { + setWidth(_this, params.width); + } + } + this.__resizeHandler = function () { + _this.onResizeDebounced(); + }; + dom.bind(window, 'resize', this.__resizeHandler); + dom.bind(this.__ul, 'webkitTransitionEnd', this.__resizeHandler); + dom.bind(this.__ul, 'transitionend', this.__resizeHandler); + dom.bind(this.__ul, 'oTransitionEnd', this.__resizeHandler); + this.onResize(); + if (params.resizable) { + addResizeHandle(this); + } + saveToLocalStorage = function saveToLocalStorage() { + if (SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(_this, 'isLocal')) === 'true') { + localStorage.setItem(getLocalStorageHash(_this, 'gui'), JSON.stringify(_this.getSaveObject())); + } + }; + this.saveToLocalStorageIfPossible = saveToLocalStorage; + function resetWidth() { + var root = _this.getRoot(); + root.width += 1; + Common.defer(function () { + root.width -= 1; + }); + } + if (!params.parent) { + resetWidth(); + } +}; +GUI.toggleHide = function () { + hide = !hide; + Common.each(hideableGuis, function (gui) { + gui.domElement.style.display = hide ? 'none' : ''; + }); +}; +GUI.CLASS_AUTO_PLACE = 'a'; +GUI.CLASS_AUTO_PLACE_CONTAINER = 'ac'; +GUI.CLASS_MAIN = 'main'; +GUI.CLASS_CONTROLLER_ROW = 'cr'; +GUI.CLASS_TOO_TALL = 'taller-than-window'; +GUI.CLASS_CLOSED = 'closed'; +GUI.CLASS_CLOSE_BUTTON = 'close-button'; +GUI.CLASS_CLOSE_TOP = 'close-top'; +GUI.CLASS_CLOSE_BOTTOM = 'close-bottom'; +GUI.CLASS_DRAG = 'drag'; +GUI.DEFAULT_WIDTH = 245; +GUI.TEXT_CLOSED = 'Close Controls'; +GUI.TEXT_OPEN = 'Open Controls'; +GUI._keydownHandler = function (e) { + if (document.activeElement.type !== 'text' && (e.which === HIDE_KEY_CODE || e.keyCode === HIDE_KEY_CODE)) { + GUI.toggleHide(); + } +}; +dom.bind(window, 'keydown', GUI._keydownHandler, false); +Common.extend(GUI.prototype, +{ + add: function add(object, property) { + return _add(this, object, property, { + factoryArgs: Array.prototype.slice.call(arguments, 2) + }); + }, + addColor: function addColor(object, property) { + return _add(this, object, property, { + color: true + }); + }, + remove: function remove(controller) { + this.__ul.removeChild(controller.__li); + this.__controllers.splice(this.__controllers.indexOf(controller), 1); + var _this = this; + Common.defer(function () { + _this.onResize(); + }); + }, + destroy: function destroy() { + if (this.parent) { + throw new Error('Only the root GUI should be removed with .destroy(). ' + 'For subfolders, use gui.removeFolder(folder) instead.'); + } + if (this.autoPlace) { + autoPlaceContainer.removeChild(this.domElement); + } + var _this = this; + Common.each(this.__folders, function (subfolder) { + _this.removeFolder(subfolder); + }); + dom.unbind(window, 'keydown', GUI._keydownHandler, false); + removeListeners(this); + }, + addFolder: function addFolder(name) { + if (this.__folders[name] !== undefined) { + throw new Error('You already have a folder in this GUI by the' + ' name "' + name + '"'); + } + var newGuiParams = { name: name, parent: this }; + newGuiParams.autoPlace = this.autoPlace; + if (this.load && + this.load.folders && + this.load.folders[name]) { + newGuiParams.closed = this.load.folders[name].closed; + newGuiParams.load = this.load.folders[name]; + } + var gui = new GUI(newGuiParams); + this.__folders[name] = gui; + var li = addRow(this, gui.domElement); + dom.addClass(li, 'folder'); + return gui; + }, + removeFolder: function removeFolder(folder) { + this.__ul.removeChild(folder.domElement.parentElement); + delete this.__folders[folder.name]; + if (this.load && + this.load.folders && + this.load.folders[folder.name]) { + delete this.load.folders[folder.name]; + } + removeListeners(folder); + var _this = this; + Common.each(folder.__folders, function (subfolder) { + folder.removeFolder(subfolder); + }); + Common.defer(function () { + _this.onResize(); + }); + }, + open: function open() { + this.closed = false; + }, + close: function close() { + this.closed = true; + }, + hide: function hide() { + this.domElement.style.display = 'none'; + }, + show: function show() { + this.domElement.style.display = ''; + }, + onResize: function onResize() { + var root = this.getRoot(); + if (root.scrollable) { + var top = dom.getOffset(root.__ul).top; + var h = 0; + Common.each(root.__ul.childNodes, function (node) { + if (!(root.autoPlace && node === root.__save_row)) { + h += dom.getHeight(node); + } + }); + if (window.innerHeight - top - CLOSE_BUTTON_HEIGHT < h) { + dom.addClass(root.domElement, GUI.CLASS_TOO_TALL); + root.__ul.style.height = window.innerHeight - top - CLOSE_BUTTON_HEIGHT + 'px'; + } else { + dom.removeClass(root.domElement, GUI.CLASS_TOO_TALL); + root.__ul.style.height = 'auto'; + } + } + if (root.__resize_handle) { + Common.defer(function () { + root.__resize_handle.style.height = root.__ul.offsetHeight + 'px'; + }); + } + if (root.__closeButton) { + root.__closeButton.style.width = root.width + 'px'; + } + }, + onResizeDebounced: Common.debounce(function () { + this.onResize(); + }, 50), + remember: function remember() { + if (Common.isUndefined(SAVE_DIALOGUE)) { + SAVE_DIALOGUE = new CenteredDiv(); + SAVE_DIALOGUE.domElement.innerHTML = saveDialogContents; + } + if (this.parent) { + throw new Error('You can only call remember on a top level GUI.'); + } + var _this = this; + Common.each(Array.prototype.slice.call(arguments), function (object) { + if (_this.__rememberedObjects.length === 0) { + addSaveMenu(_this); + } + if (_this.__rememberedObjects.indexOf(object) === -1) { + _this.__rememberedObjects.push(object); + } + }); + if (this.autoPlace) { + setWidth(this, this.width); + } + }, + getRoot: function getRoot() { + var gui = this; + while (gui.parent) { + gui = gui.parent; + } + return gui; + }, + getSaveObject: function getSaveObject() { + var toReturn = this.load; + toReturn.closed = this.closed; + if (this.__rememberedObjects.length > 0) { + toReturn.preset = this.preset; + if (!toReturn.remembered) { + toReturn.remembered = {}; + } + toReturn.remembered[this.preset] = getCurrentPreset(this); + } + toReturn.folders = {}; + Common.each(this.__folders, function (element, key) { + toReturn.folders[key] = element.getSaveObject(); + }); + return toReturn; + }, + save: function save() { + if (!this.load.remembered) { + this.load.remembered = {}; + } + this.load.remembered[this.preset] = getCurrentPreset(this); + markPresetModified(this, false); + this.saveToLocalStorageIfPossible(); + }, + saveAs: function saveAs(presetName) { + if (!this.load.remembered) { + this.load.remembered = {}; + this.load.remembered[DEFAULT_DEFAULT_PRESET_NAME] = getCurrentPreset(this, true); + } + this.load.remembered[presetName] = getCurrentPreset(this); + this.preset = presetName; + addPresetOption(this, presetName, true); + this.saveToLocalStorageIfPossible(); + }, + revert: function revert(gui) { + Common.each(this.__controllers, function (controller) { + if (!this.getRoot().load.remembered) { + controller.setValue(controller.initialValue); + } else { + recallSavedValue(gui || this.getRoot(), controller); + } + if (controller.__onFinishChange) { + controller.__onFinishChange.call(controller, controller.getValue()); + } + }, this); + Common.each(this.__folders, function (folder) { + folder.revert(folder); + }); + if (!gui) { + markPresetModified(this.getRoot(), false); + } + }, + listen: function listen(controller) { + var init = this.__listening.length === 0; + this.__listening.push(controller); + if (init) { + updateDisplays(this.__listening); + } + }, + updateDisplay: function updateDisplay() { + Common.each(this.__controllers, function (controller) { + controller.updateDisplay(); + }); + Common.each(this.__folders, function (folder) { + folder.updateDisplay(); + }); + } +}); +function addRow(gui, newDom, liBefore) { + var li = document.createElement('li'); + if (newDom) { + li.appendChild(newDom); + } + if (liBefore) { + gui.__ul.insertBefore(li, liBefore); + } else { + gui.__ul.appendChild(li); + } + gui.onResize(); + return li; +} +function removeListeners(gui) { + dom.unbind(window, 'resize', gui.__resizeHandler); + if (gui.saveToLocalStorageIfPossible) { + dom.unbind(window, 'unload', gui.saveToLocalStorageIfPossible); + } +} +function markPresetModified(gui, modified) { + var opt = gui.__preset_select[gui.__preset_select.selectedIndex]; + if (modified) { + opt.innerHTML = opt.value + '*'; + } else { + opt.innerHTML = opt.value; + } +} +function augmentController(gui, li, controller) { + controller.__li = li; + controller.__gui = gui; + Common.extend(controller, { + options: function options(_options) { + if (arguments.length > 1) { + var nextSibling = controller.__li.nextElementSibling; + controller.remove(); + return _add(gui, controller.object, controller.property, { + before: nextSibling, + factoryArgs: [Common.toArray(arguments)] + }); + } + if (Common.isArray(_options) || Common.isObject(_options)) { + var _nextSibling = controller.__li.nextElementSibling; + controller.remove(); + return _add(gui, controller.object, controller.property, { + before: _nextSibling, + factoryArgs: [_options] + }); + } + }, + name: function name(_name) { + controller.__li.firstElementChild.firstElementChild.innerHTML = _name; + return controller; + }, + listen: function listen() { + controller.__gui.listen(controller); + return controller; + }, + remove: function remove() { + controller.__gui.remove(controller); + return controller; + } + }); + if (controller instanceof NumberControllerSlider) { + var box = new NumberControllerBox(controller.object, controller.property, { min: controller.__min, max: controller.__max, step: controller.__step }); + Common.each(['updateDisplay', 'onChange', 'onFinishChange', 'step', 'min', 'max'], function (method) { + var pc = controller[method]; + var pb = box[method]; + controller[method] = box[method] = function () { + var args = Array.prototype.slice.call(arguments); + pb.apply(box, args); + return pc.apply(controller, args); + }; + }); + dom.addClass(li, 'has-slider'); + controller.domElement.insertBefore(box.domElement, controller.domElement.firstElementChild); + } else if (controller instanceof NumberControllerBox) { + var r = function r(returned) { + if (Common.isNumber(controller.__min) && Common.isNumber(controller.__max)) { + var oldName = controller.__li.firstElementChild.firstElementChild.innerHTML; + var wasListening = controller.__gui.__listening.indexOf(controller) > -1; + controller.remove(); + var newController = _add(gui, controller.object, controller.property, { + before: controller.__li.nextElementSibling, + factoryArgs: [controller.__min, controller.__max, controller.__step] + }); + newController.name(oldName); + if (wasListening) newController.listen(); + return newController; + } + return returned; + }; + controller.min = Common.compose(r, controller.min); + controller.max = Common.compose(r, controller.max); + } else if (controller instanceof BooleanController) { + dom.bind(li, 'click', function () { + dom.fakeEvent(controller.__checkbox, 'click'); + }); + dom.bind(controller.__checkbox, 'click', function (e) { + e.stopPropagation(); + }); + } else if (controller instanceof FunctionController) { + dom.bind(li, 'click', function () { + dom.fakeEvent(controller.__button, 'click'); + }); + dom.bind(li, 'mouseover', function () { + dom.addClass(controller.__button, 'hover'); + }); + dom.bind(li, 'mouseout', function () { + dom.removeClass(controller.__button, 'hover'); + }); + } else if (controller instanceof ColorController) { + dom.addClass(li, 'color'); + controller.updateDisplay = Common.compose(function (val) { + li.style.borderLeftColor = controller.__color.toString(); + return val; + }, controller.updateDisplay); + controller.updateDisplay(); + } + controller.setValue = Common.compose(function (val) { + if (gui.getRoot().__preset_select && controller.isModified()) { + markPresetModified(gui.getRoot(), true); + } + return val; + }, controller.setValue); +} +function recallSavedValue(gui, controller) { + var root = gui.getRoot(); + var matchedIndex = root.__rememberedObjects.indexOf(controller.object); + if (matchedIndex !== -1) { + var controllerMap = root.__rememberedObjectIndecesToControllers[matchedIndex]; + if (controllerMap === undefined) { + controllerMap = {}; + root.__rememberedObjectIndecesToControllers[matchedIndex] = controllerMap; + } + controllerMap[controller.property] = controller; + if (root.load && root.load.remembered) { + var presetMap = root.load.remembered; + var preset = void 0; + if (presetMap[gui.preset]) { + preset = presetMap[gui.preset]; + } else if (presetMap[DEFAULT_DEFAULT_PRESET_NAME]) { + preset = presetMap[DEFAULT_DEFAULT_PRESET_NAME]; + } else { + return; + } + if (preset[matchedIndex] && preset[matchedIndex][controller.property] !== undefined) { + var value = preset[matchedIndex][controller.property]; + controller.initialValue = value; + controller.setValue(value); + } + } + } +} +function _add(gui, object, property, params) { + if (object[property] === undefined) { + throw new Error('Object "' + object + '" has no property "' + property + '"'); + } + var controller = void 0; + if (params.color) { + controller = new ColorController(object, property); + } else { + var factoryArgs = [object, property].concat(params.factoryArgs); + controller = ControllerFactory.apply(gui, factoryArgs); + } + if (params.before instanceof Controller) { + params.before = params.before.__li; + } + recallSavedValue(gui, controller); + dom.addClass(controller.domElement, 'c'); + var name = document.createElement('span'); + dom.addClass(name, 'property-name'); + name.innerHTML = controller.property; + var container = document.createElement('div'); + container.appendChild(name); + container.appendChild(controller.domElement); + var li = addRow(gui, container, params.before); + dom.addClass(li, GUI.CLASS_CONTROLLER_ROW); + if (controller instanceof ColorController) { + dom.addClass(li, 'color'); + } else { + dom.addClass(li, _typeof(controller.getValue())); + } + augmentController(gui, li, controller); + gui.__controllers.push(controller); + return controller; +} +function getLocalStorageHash(gui, key) { + return document.location.href + '.' + key; +} +function addPresetOption(gui, name, setSelected) { + var opt = document.createElement('option'); + opt.innerHTML = name; + opt.value = name; + gui.__preset_select.appendChild(opt); + if (setSelected) { + gui.__preset_select.selectedIndex = gui.__preset_select.length - 1; + } +} +function showHideExplain(gui, explain) { + explain.style.display = gui.useLocalStorage ? 'block' : 'none'; +} +function addSaveMenu(gui) { + var div = gui.__save_row = document.createElement('li'); + dom.addClass(gui.domElement, 'has-save'); + gui.__ul.insertBefore(div, gui.__ul.firstChild); + dom.addClass(div, 'save-row'); + var gears = document.createElement('span'); + gears.innerHTML = ' '; + dom.addClass(gears, 'button gears'); + var button = document.createElement('span'); + button.innerHTML = 'Save'; + dom.addClass(button, 'button'); + dom.addClass(button, 'save'); + var button2 = document.createElement('span'); + button2.innerHTML = 'New'; + dom.addClass(button2, 'button'); + dom.addClass(button2, 'save-as'); + var button3 = document.createElement('span'); + button3.innerHTML = 'Revert'; + dom.addClass(button3, 'button'); + dom.addClass(button3, 'revert'); + var select = gui.__preset_select = document.createElement('select'); + if (gui.load && gui.load.remembered) { + Common.each(gui.load.remembered, function (value, key) { + addPresetOption(gui, key, key === gui.preset); + }); + } else { + addPresetOption(gui, DEFAULT_DEFAULT_PRESET_NAME, false); + } + dom.bind(select, 'change', function () { + for (var index = 0; index < gui.__preset_select.length; index++) { + gui.__preset_select[index].innerHTML = gui.__preset_select[index].value; + } + gui.preset = this.value; + }); + div.appendChild(select); + div.appendChild(gears); + div.appendChild(button); + div.appendChild(button2); + div.appendChild(button3); + if (SUPPORTS_LOCAL_STORAGE) { + var explain = document.getElementById('dg-local-explain'); + var localStorageCheckBox = document.getElementById('dg-local-storage'); + var saveLocally = document.getElementById('dg-save-locally'); + saveLocally.style.display = 'block'; + if (localStorage.getItem(getLocalStorageHash(gui, 'isLocal')) === 'true') { + localStorageCheckBox.setAttribute('checked', 'checked'); + } + showHideExplain(gui, explain); + dom.bind(localStorageCheckBox, 'change', function () { + gui.useLocalStorage = !gui.useLocalStorage; + showHideExplain(gui, explain); + }); + } + var newConstructorTextArea = document.getElementById('dg-new-constructor'); + dom.bind(newConstructorTextArea, 'keydown', function (e) { + if (e.metaKey && (e.which === 67 || e.keyCode === 67)) { + SAVE_DIALOGUE.hide(); + } + }); + dom.bind(gears, 'click', function () { + newConstructorTextArea.innerHTML = JSON.stringify(gui.getSaveObject(), undefined, 2); + SAVE_DIALOGUE.show(); + newConstructorTextArea.focus(); + newConstructorTextArea.select(); + }); + dom.bind(button, 'click', function () { + gui.save(); + }); + dom.bind(button2, 'click', function () { + var presetName = prompt('Enter a new preset name.'); + if (presetName) { + gui.saveAs(presetName); + } + }); + dom.bind(button3, 'click', function () { + gui.revert(); + }); +} +function addResizeHandle(gui) { + var pmouseX = void 0; + gui.__resize_handle = document.createElement('div'); + Common.extend(gui.__resize_handle.style, { + width: '6px', + marginLeft: '-3px', + height: '200px', + cursor: 'ew-resize', + position: 'absolute' + }); + function drag(e) { + e.preventDefault(); + gui.width += pmouseX - e.clientX; + gui.onResize(); + pmouseX = e.clientX; + return false; + } + function dragStop() { + dom.removeClass(gui.__closeButton, GUI.CLASS_DRAG); + dom.unbind(window, 'mousemove', drag); + dom.unbind(window, 'mouseup', dragStop); + } + function dragStart(e) { + e.preventDefault(); + pmouseX = e.clientX; + dom.addClass(gui.__closeButton, GUI.CLASS_DRAG); + dom.bind(window, 'mousemove', drag); + dom.bind(window, 'mouseup', dragStop); + return false; + } + dom.bind(gui.__resize_handle, 'mousedown', dragStart); + dom.bind(gui.__closeButton, 'mousedown', dragStart); + gui.domElement.insertBefore(gui.__resize_handle, gui.domElement.firstElementChild); +} +function setWidth(gui, w) { + gui.domElement.style.width = w + 'px'; + if (gui.__save_row && gui.autoPlace) { + gui.__save_row.style.width = w + 'px'; + } + if (gui.__closeButton) { + gui.__closeButton.style.width = w + 'px'; + } +} +function getCurrentPreset(gui, useInitialValues) { + var toReturn = {}; + Common.each(gui.__rememberedObjects, function (val, index) { + var savedValues = {}; + var controllerMap = gui.__rememberedObjectIndecesToControllers[index]; + Common.each(controllerMap, function (controller, property) { + savedValues[property] = useInitialValues ? controller.initialValue : controller.getValue(); + }); + toReturn[index] = savedValues; + }); + return toReturn; +} +function setPresetSelectIndex(gui) { + for (var index = 0; index < gui.__preset_select.length; index++) { + if (gui.__preset_select[index].value === gui.preset) { + gui.__preset_select.selectedIndex = index; + } + } +} +function updateDisplays(controllerArray) { + if (controllerArray.length !== 0) { + requestAnimationFrame$1.call(window, function () { + updateDisplays(controllerArray); + }); + } + Common.each(controllerArray, function (c) { + c.updateDisplay(); + }); +} + +var color = { + Color: Color, + math: ColorMath, + interpret: interpret +}; +var controllers = { + Controller: Controller, + BooleanController: BooleanController, + OptionController: OptionController, + StringController: StringController, + NumberController: NumberController, + NumberControllerBox: NumberControllerBox, + NumberControllerSlider: NumberControllerSlider, + FunctionController: FunctionController, + ColorController: ColorController +}; +var dom$1 = { dom: dom }; +var gui = { GUI: GUI }; +var GUI$1 = GUI; +var index = { + color: color, + controllers: controllers, + dom: dom$1, + gui: gui, + GUI: GUI$1 +}; + + +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (index); +//# sourceMappingURL=dat.gui.module.js.map + + +/***/ }), + +/***/ "../../node_modules/park-miller/index.js": +/*!***********************************************!*\ + !*** ../../node_modules/park-miller/index.js ***! + \***********************************************/ +/***/ ((module) => { + + +const MAX_INT32 = 2147483647; +const MINSTD = 16807; + +class ParkMiller { + constructor(seed) { + if (!Number.isInteger(seed)) { + throw new TypeError('Expected `seed` to be a `integer`'); + } + + this._seed = seed % MAX_INT32; + + if (this._seed <= 0) { + this._seed += (MAX_INT32 - 1); + } + } + + integer() { + this._seed *= MINSTD; + this._seed %= MAX_INT32; + return this._seed; + } + + integerInRange(min, max) { + return Math.round(this.floatInRange(min, max)); + } + + float() { + return (this.integer() - 1) / (MAX_INT32 - 1); + } + + floatInRange(min, max) { + return min + ((max - min) * this.float()); + } + + boolean() { + return this.integer() % 2 === 0; + } +} + +module.exports = ParkMiller; + + +/***/ }), + +/***/ "./canvas.ts": +/*!*******************!*\ + !*** ./canvas.ts ***! + \*******************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createCanvas: () => (/* binding */ createCanvas), +/* harmony export */ drawOptions: () => (/* binding */ drawOptions) +/* harmony export */ }); +/* harmony import */ var _snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/draw/drawWorld */ "../draw/drawWorld.ts"); + +const drawOptions = { + sizeDotBorderRadius: 2, + sizeCell: 16, + sizeDot: 12, + colorDotBorder: "#1b1f230a", + colorDots: { + 1: "#9be9a8", + 2: "#40c463", + 3: "#30a14e", + 4: "#216e39", + }, + colorEmpty: "#ebedf0", + colorSnake: "purple", + dark: { + colorEmpty: "#161b22", + colorDots: { 1: "#01311f", 2: "#034525", 3: "#0f6d31", 4: "#00c647" }, + }, +}; +const getPointedCell = (canvas) => ({ pageX, pageY }) => { + const { left, top } = canvas.getBoundingClientRect(); + const x = Math.floor((pageX - left) / drawOptions.sizeCell) - 1; + const y = Math.floor((pageY - top) / drawOptions.sizeCell) - 2; + return { x, y }; +}; +const createCanvas = ({ width, height, }) => { + const canvas = document.createElement("canvas"); + const upscale = 2; + const w = drawOptions.sizeCell * (width + 4); + const h = drawOptions.sizeCell * (height + 4) + 200; + canvas.width = w * upscale; + canvas.height = h * upscale; + canvas.style.width = w + "px"; + canvas.style.height = h + "px"; + canvas.style.display = "block"; + // canvas.style.pointerEvents = "none"; + const cellInfo = document.createElement("div"); + cellInfo.style.height = "20px"; + document.body.appendChild(cellInfo); + document.body.appendChild(canvas); + canvas.addEventListener("mousemove", (e) => { + const { x, y } = getPointedCell(canvas)(e); + cellInfo.innerText = [x, y] + .map((u) => u.toString().padStart(2, " ")) + .join(" / "); + }); + const ctx = canvas.getContext("2d"); + ctx.scale(upscale, upscale); + const draw = (grid, snake, stack) => { + ctx.clearRect(0, 0, 9999, 9999); + (0,_snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__.drawWorld)(ctx, grid, null, snake, stack, drawOptions); + }; + const drawLerp = (grid, snake0, snake1, stack, k) => { + ctx.clearRect(0, 0, 9999, 9999); + (0,_snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__.drawLerpWorld)(ctx, grid, null, snake0, snake1, stack, k, drawOptions); + }; + const highlightCell = (x, y, color = "orange") => { + ctx.fillStyle = color; + ctx.beginPath(); + ctx.fillRect((1 + x + 0.5) * 16 - 2, (2 + y + 0.5) * 16 - 2, 4, 4); + }; + return { + draw, + drawLerp, + highlightCell, + canvas, + getPointedCell: getPointedCell(canvas), + ctx, + }; +}; + + +/***/ }), + +/***/ "./menu.ts": +/*!*****************!*\ + !*** ./menu.ts ***! + \*****************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ gui: () => (/* binding */ gui) +/* harmony export */ }); +/* harmony import */ var dat_gui__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! dat.gui */ "../../node_modules/dat.gui/build/dat.gui.module.js"); +/* harmony import */ var _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/__fixtures__/grid */ "../types/__fixtures__/grid.ts"); +/* harmony import */ var _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/__fixtures__/snake */ "../types/__fixtures__/snake.ts"); +/* harmony import */ var _sample__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sample */ "./sample.ts"); + + + + +const demos = __webpack_require__(/*! ./demo.json */ "./demo.json"); +const gui = new dat_gui__WEBPACK_IMPORTED_MODULE_0__.GUI(); +const config = { + snake: Object.entries(_snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__).find(([_, s]) => s === _sample__WEBPACK_IMPORTED_MODULE_3__.snake)[0], + grid: Object.entries(_snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__).find(([_, s]) => s === _sample__WEBPACK_IMPORTED_MODULE_3__.grid)[0], + demo: demos[0], +}; +{ + const d = window.location.pathname.match(/(\w+)\.html/); + if (d && demos.includes(d[1])) + config.demo = d[1]; +} +const onChange = () => { + const search = new URLSearchParams({ + snake: config.snake, + grid: config.grid, + }).toString(); + const url = new URL(config.demo + ".html?" + search, window.location.href).toString(); + window.location.href = url; +}; +gui.add(config, "demo", demos).onChange(onChange); +gui.add(config, "grid", Object.keys(_snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__)).onChange(onChange); +gui.add(config, "snake", Object.keys(_snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__)).onChange(onChange); + + +/***/ }), + +/***/ "./sample.ts": +/*!*******************!*\ + !*** ./sample.ts ***! + \*******************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ grid: () => (/* binding */ grid), +/* harmony export */ snake: () => (/* binding */ snake) +/* harmony export */ }); +/* harmony import */ var _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/__fixtures__/grid */ "../types/__fixtures__/grid.ts"); +/* harmony import */ var _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/__fixtures__/snake */ "../types/__fixtures__/snake.ts"); + + +const sp = new URLSearchParams(window.location.search); +const gLabel = sp.get("grid") || "simple"; +const sLabel = sp.get("snake") || "snake3"; +//@ts-ignore +const grid = _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__[gLabel] || _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__.simple; +//@ts-ignore +const snake = _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__[sLabel] || _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__.snake3; + + +/***/ }), + +/***/ "../draw/drawGrid.ts": +/*!***************************!*\ + !*** ../draw/drawGrid.ts ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawGrid: () => (/* binding */ drawGrid) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _pathRoundedRect__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./pathRoundedRect */ "../draw/pathRoundedRect.ts"); + + +const drawGrid = (ctx, grid, cells, o) => { + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + if (!cells || cells.some((c) => c.x === x && c.y === y)) { + const c = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + // @ts-ignore + const color = !c ? o.colorEmpty : o.colorDots[c]; + ctx.save(); + ctx.translate(x * o.sizeCell + (o.sizeCell - o.sizeDot) / 2, y * o.sizeCell + (o.sizeCell - o.sizeDot) / 2); + ctx.fillStyle = color; + ctx.strokeStyle = o.colorDotBorder; + ctx.lineWidth = 1; + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_1__.pathRoundedRect)(ctx, o.sizeDot, o.sizeDot, o.sizeDotBorderRadius); + ctx.fill(); + ctx.stroke(); + ctx.closePath(); + ctx.restore(); + } + } +}; + + +/***/ }), + +/***/ "../draw/drawSnake.ts": +/*!****************************!*\ + !*** ../draw/drawSnake.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawSnake: () => (/* binding */ drawSnake), +/* harmony export */ drawSnakeLerp: () => (/* binding */ drawSnakeLerp) +/* harmony export */ }); +/* harmony import */ var _pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./pathRoundedRect */ "../draw/pathRoundedRect.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); + + +const drawSnake = (ctx, snake, o) => { + const cells = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.snakeToCells)(snake); + for (let i = 0; i < cells.length; i++) { + const u = (i + 1) * 0.6; + ctx.save(); + ctx.fillStyle = o.colorSnake; + ctx.translate(cells[i].x * o.sizeCell + u, cells[i].y * o.sizeCell + u); + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__.pathRoundedRect)(ctx, o.sizeCell - u * 2, o.sizeCell - u * 2, (o.sizeCell - u * 2) * 0.25); + ctx.fill(); + ctx.restore(); + } +}; +const lerp = (k, a, b) => (1 - k) * a + k * b; +const clamp = (x, a, b) => Math.max(a, Math.min(b, x)); +const drawSnakeLerp = (ctx, snake0, snake1, k, o) => { + const m = 0.8; + const n = snake0.length / 2; + for (let i = 0; i < n; i++) { + const u = (i + 1) * 0.6 * (o.sizeCell / 16); + const a = (1 - m) * (i / Math.max(n - 1, 1)); + const ki = clamp((k - a) / m, 0, 1); + const x = lerp(ki, snake0[i * 2 + 0], snake1[i * 2 + 0]) - 2; + const y = lerp(ki, snake0[i * 2 + 1], snake1[i * 2 + 1]) - 2; + ctx.save(); + ctx.fillStyle = o.colorSnake; + ctx.translate(x * o.sizeCell + u, y * o.sizeCell + u); + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__.pathRoundedRect)(ctx, o.sizeCell - u * 2, o.sizeCell - u * 2, (o.sizeCell - u * 2) * 0.25); + ctx.fill(); + ctx.restore(); + } +}; + + +/***/ }), + +/***/ "../draw/drawWorld.ts": +/*!****************************!*\ + !*** ../draw/drawWorld.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawLerpWorld: () => (/* binding */ drawLerpWorld), +/* harmony export */ drawStack: () => (/* binding */ drawStack), +/* harmony export */ drawWorld: () => (/* binding */ drawWorld), +/* harmony export */ getCanvasWorldSize: () => (/* binding */ getCanvasWorldSize) +/* harmony export */ }); +/* harmony import */ var _drawGrid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./drawGrid */ "../draw/drawGrid.ts"); +/* harmony import */ var _drawSnake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./drawSnake */ "../draw/drawSnake.ts"); + + +const drawStack = (ctx, stack, max, width, o) => { + ctx.save(); + const m = width / max; + for (let i = 0; i < stack.length; i++) { + // @ts-ignore + ctx.fillStyle = o.colorDots[stack[i]]; + ctx.fillRect(i * m, 0, m + width * 0.005, 10); + } + ctx.restore(); +}; +const drawWorld = (ctx, grid, cells, snake, stack, o) => { + ctx.save(); + ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); + (0,_drawGrid__WEBPACK_IMPORTED_MODULE_0__.drawGrid)(ctx, grid, cells, o); + (0,_drawSnake__WEBPACK_IMPORTED_MODULE_1__.drawSnake)(ctx, snake, o); + ctx.restore(); + ctx.save(); + ctx.translate(o.sizeCell, (grid.height + 4) * o.sizeCell); + const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length); + drawStack(ctx, stack, max, grid.width * o.sizeCell, o); + ctx.restore(); + // ctx.save(); + // ctx.translate(o.sizeCell + 100, (grid.height + 4) * o.sizeCell + 100); + // ctx.scale(0.6, 0.6); + // drawCircleStack(ctx, stack, o); + // ctx.restore(); +}; +const drawLerpWorld = (ctx, grid, cells, snake0, snake1, stack, k, o) => { + ctx.save(); + ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); + (0,_drawGrid__WEBPACK_IMPORTED_MODULE_0__.drawGrid)(ctx, grid, cells, o); + (0,_drawSnake__WEBPACK_IMPORTED_MODULE_1__.drawSnakeLerp)(ctx, snake0, snake1, k, o); + ctx.translate(0, (grid.height + 2) * o.sizeCell); + const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length); + drawStack(ctx, stack, max, grid.width * o.sizeCell, o); + ctx.restore(); +}; +const getCanvasWorldSize = (grid, o) => { + const width = o.sizeCell * (grid.width + 2); + const height = o.sizeCell * (grid.height + 4) + 30; + return { width, height }; +}; + + +/***/ }), + +/***/ "../draw/pathRoundedRect.ts": +/*!**********************************!*\ + !*** ../draw/pathRoundedRect.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ pathRoundedRect: () => (/* binding */ pathRoundedRect) +/* harmony export */ }); +const pathRoundedRect = (ctx, width, height, borderRadius) => { + ctx.moveTo(borderRadius, 0); + ctx.arcTo(width, 0, width, height, borderRadius); + ctx.arcTo(width, height, 0, height, borderRadius); + ctx.arcTo(0, height, 0, 0, borderRadius); + ctx.arcTo(0, 0, width, 0, borderRadius); +}; + + +/***/ }), + +/***/ "../solver/clearCleanColoredLayer.ts": +/*!*******************************************!*\ + !*** ../solver/clearCleanColoredLayer.ts ***! + \*******************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ clearCleanColoredLayer: () => (/* binding */ clearCleanColoredLayer), +/* harmony export */ getTunnellablePoints: () => (/* binding */ getTunnellablePoints) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); +/* harmony import */ var _getBestTunnel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./getBestTunnel */ "../solver/getBestTunnel.ts"); +/* harmony import */ var _outside__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./outside */ "../solver/outside.ts"); + + + + + +const clearCleanColoredLayer = (grid, outside, snake0, color) => { + const snakeN = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getSnakeLength)(snake0); + const points = getTunnellablePoints(grid, outside, snakeN, color); + const chain = [snake0]; + while (points.length) { + const path = getPathToNextPoint(grid, chain[0], color, points); + path.pop(); + for (const snake of path) + setEmptySafe(grid, (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake)); + chain.unshift(...path); + } + (0,_outside__WEBPACK_IMPORTED_MODULE_4__.fillOutside)(outside, grid); + chain.pop(); + return chain; +}; +const unwrap = (m) => !m ? [] : [m.snake, ...unwrap(m.parent)]; +const getPathToNextPoint = (grid, snake0, color, points) => { + const closeList = []; + const openList = [{ snake: snake0 }]; + while (openList.length) { + const o = openList.shift(); + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(o.snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(o.snake); + const i = points.findIndex((p) => p.x === x && p.y === y); + if (i >= 0) { + points.splice(i, 1); + return unwrap(o); + } + for (const { x: dx, y: dy } of _snk_types_point__WEBPACK_IMPORTED_MODULE_2__.around4) { + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInsideLarge)(grid, 2, x + dx, y + dy) && + !(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.snakeWillSelfCollide)(o.snake, dx, dy) && + getColorSafe(grid, x + dx, y + dy) <= color) { + const snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.nextSnake)(o.snake, dx, dy); + if (!closeList.some((s0) => (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.snakeEquals)(s0, snake))) { + closeList.push(snake); + openList.push({ snake, parent: o }); + } + } + } + } +}; +/** + * get all cells that are tunnellable + */ +const getTunnellablePoints = (grid, outside, snakeN, color) => { + const points = []; + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + const c = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + if (!(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)(c) && + c <= color && + !points.some((p) => p.x === x && p.y === y)) { + const tunnel = (0,_getBestTunnel__WEBPACK_IMPORTED_MODULE_3__.getBestTunnel)(grid, outside, x, y, color, snakeN); + if (tunnel) + for (const p of tunnel) + if (!isEmptySafe(grid, p.x, p.y)) + points.push(p); + } + } + return points; +}; +const getColorSafe = (grid, x, y) => (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) ? (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) : 0; +const setEmptySafe = (grid, x, y) => { + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y)) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); +}; +const isEmptySafe = (grid, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) && (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y)); + + +/***/ }), + +/***/ "../solver/clearResidualColoredLayer.ts": +/*!**********************************************!*\ + !*** ../solver/clearResidualColoredLayer.ts ***! + \**********************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ clearResidualColoredLayer: () => (/* binding */ clearResidualColoredLayer), +/* harmony export */ getPriority: () => (/* binding */ getPriority), +/* harmony export */ getTunnellablePoints: () => (/* binding */ getTunnellablePoints) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _getBestTunnel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./getBestTunnel */ "../solver/getBestTunnel.ts"); +/* harmony import */ var _outside__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./outside */ "../solver/outside.ts"); +/* harmony import */ var _tunnel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./tunnel */ "../solver/tunnel.ts"); +/* harmony import */ var _getPathTo__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./getPathTo */ "../solver/getPathTo.ts"); + + + + + + +const clearResidualColoredLayer = (grid, outside, snake0, color) => { + const snakeN = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getSnakeLength)(snake0); + const tunnels = getTunnellablePoints(grid, outside, snakeN, color); + // sort + tunnels.sort((a, b) => b.priority - a.priority); + const chain = [snake0]; + while (tunnels.length) { + // get the best next tunnel + let t = getNextTunnel(tunnels, chain[0]); + // goes to the start of the tunnel + chain.unshift(...(0,_getPathTo__WEBPACK_IMPORTED_MODULE_5__.getPathTo)(grid, chain[0], t[0].x, t[0].y)); + // goes to the end of the tunnel + chain.unshift(...(0,_tunnel__WEBPACK_IMPORTED_MODULE_4__.getTunnelPath)(chain[0], t)); + // update grid + for (const { x, y } of t) + setEmptySafe(grid, x, y); + // update outside + (0,_outside__WEBPACK_IMPORTED_MODULE_3__.fillOutside)(outside, grid); + // update tunnels + for (let i = tunnels.length; i--;) + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, tunnels[i].x, tunnels[i].y))) + tunnels.splice(i, 1); + else { + const t = tunnels[i]; + const tunnel = (0,_getBestTunnel__WEBPACK_IMPORTED_MODULE_2__.getBestTunnel)(grid, outside, t.x, t.y, color, snakeN); + if (!tunnel) + tunnels.splice(i, 1); + else { + t.tunnel = tunnel; + t.priority = getPriority(grid, color, tunnel); + } + } + // re-sort + tunnels.sort((a, b) => b.priority - a.priority); + } + chain.pop(); + return chain; +}; +const getNextTunnel = (ts, snake) => { + let minDistance = Infinity; + let closestTunnel = null; + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake); + const priority = ts[0].priority; + for (let i = 0; ts[i] && ts[i].priority === priority; i++) { + const t = ts[i].tunnel; + const d = distanceSq(t[0].x, t[0].y, x, y); + if (d < minDistance) { + minDistance = d; + closestTunnel = t; + } + } + return closestTunnel; +}; +/** + * get all the tunnels for all the cells accessible + */ +const getTunnellablePoints = (grid, outside, snakeN, color) => { + const points = []; + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + const c = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + if (!(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)(c) && c < color) { + const tunnel = (0,_getBestTunnel__WEBPACK_IMPORTED_MODULE_2__.getBestTunnel)(grid, outside, x, y, color, snakeN); + if (tunnel) { + const priority = getPriority(grid, color, tunnel); + points.push({ x, y, priority, tunnel }); + } + } + } + return points; +}; +/** + * get the score of the tunnel + * prioritize tunnel with maximum color smaller than and with minimum + * with some tweaks + */ +const getPriority = (grid, color, tunnel) => { + let nColor = 0; + let nLess = 0; + for (let i = 0; i < tunnel.length; i++) { + const { x, y } = tunnel[i]; + const c = getColorSafe(grid, x, y); + if (!(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)(c) && i === tunnel.findIndex((p) => p.x === x && p.y === y)) { + if (c === color) + nColor += 1; + else + nLess += color - c; + } + } + if (nColor === 0) + return 99999; + return nLess / nColor; +}; +const distanceSq = (ax, ay, bx, by) => (ax - bx) ** 2 + (ay - by) ** 2; +const getColorSafe = (grid, x, y) => (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) ? (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) : 0; +const setEmptySafe = (grid, x, y) => { + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y)) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); +}; + + +/***/ }), + +/***/ "../solver/getBestRoute.ts": +/*!*********************************!*\ + !*** ../solver/getBestRoute.ts ***! + \*********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getBestRoute: () => (/* binding */ getBestRoute) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _outside__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./outside */ "../solver/outside.ts"); +/* harmony import */ var _clearResidualColoredLayer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./clearResidualColoredLayer */ "../solver/clearResidualColoredLayer.ts"); +/* harmony import */ var _clearCleanColoredLayer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./clearCleanColoredLayer */ "../solver/clearCleanColoredLayer.ts"); + + + + +const getBestRoute = (grid0, snake0) => { + const grid = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.copyGrid)(grid0); + const outside = (0,_outside__WEBPACK_IMPORTED_MODULE_1__.createOutside)(grid); + const chain = [snake0]; + for (const color of extractColors(grid)) { + if (color > 1) + chain.unshift(...(0,_clearResidualColoredLayer__WEBPACK_IMPORTED_MODULE_2__.clearResidualColoredLayer)(grid, outside, chain[0], color)); + chain.unshift(...(0,_clearCleanColoredLayer__WEBPACK_IMPORTED_MODULE_3__.clearCleanColoredLayer)(grid, outside, chain[0], color)); + } + return chain.reverse(); +}; +const extractColors = (grid) => { + // @ts-ignore + let maxColor = Math.max(...grid.data); + return Array.from({ length: maxColor }, (_, i) => (i + 1)); +}; + + +/***/ }), + +/***/ "../solver/getBestTunnel.ts": +/*!**********************************!*\ + !*** ../solver/getBestTunnel.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getBestTunnel: () => (/* binding */ getBestTunnel) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); +/* harmony import */ var _utils_sortPush__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils/sortPush */ "../solver/utils/sortPush.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _outside__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./outside */ "../solver/outside.ts"); +/* harmony import */ var _tunnel__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./tunnel */ "../solver/tunnel.ts"); + + + + + + +const getColorSafe = (grid, x, y) => (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) ? (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) : 0; +const setEmptySafe = (grid, x, y) => { + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y)) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); +}; +const unwrap = (m) => !m + ? [] + : [...unwrap(m.parent), { x: (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadX)(m.snake), y: (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadY)(m.snake) }]; +/** + * returns the path to reach the outside which contains the least color cell + */ +const getSnakeEscapePath = (grid, outside, snake0, color) => { + const openList = [{ snake: snake0, w: 0 }]; + const closeList = []; + while (openList[0]) { + const o = openList.shift(); + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadX)(o.snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadY)(o.snake); + if ((0,_outside__WEBPACK_IMPORTED_MODULE_4__.isOutside)(outside, x, y)) + return unwrap(o); + for (const a of _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4) { + const c = getColorSafe(grid, x + a.x, y + a.y); + if (c <= color && !(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.snakeWillSelfCollide)(o.snake, a.x, a.y)) { + const snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.nextSnake)(o.snake, a.x, a.y); + if (!closeList.some((s0) => (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.snakeEquals)(s0, snake))) { + const w = o.w + 1 + +(c === color) * 1000; + (0,_utils_sortPush__WEBPACK_IMPORTED_MODULE_2__.sortPush)(openList, { snake, w, parent: o }, (a, b) => a.w - b.w); + closeList.push(snake); + } + } + } + } + return null; +}; +/** + * compute the best tunnel to get to the cell and back to the outside ( best = less usage of ) + * + * notice that it's one of the best tunnels, more with the same score could exist + */ +const getBestTunnel = (grid, outside, x, y, color, snakeN) => { + const c = { x, y }; + const snake0 = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.createSnakeFromCells)(Array.from({ length: snakeN }, () => c)); + const one = getSnakeEscapePath(grid, outside, snake0, color); + if (!one) + return null; + // get the position of the snake if it was going to leave the x,y cell + const snakeICells = one.slice(0, snakeN); + while (snakeICells.length < snakeN) + snakeICells.push(snakeICells[snakeICells.length - 1]); + const snakeI = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.createSnakeFromCells)(snakeICells); + // remove from the grid the colors that one eat + const gridI = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.copyGrid)(grid); + for (const { x, y } of one) + setEmptySafe(gridI, x, y); + const two = getSnakeEscapePath(gridI, outside, snakeI, color); + if (!two) + return null; + one.shift(); + one.reverse(); + one.push(...two); + (0,_tunnel__WEBPACK_IMPORTED_MODULE_5__.trimTunnelStart)(grid, one); + (0,_tunnel__WEBPACK_IMPORTED_MODULE_5__.trimTunnelEnd)(grid, one); + return one; +}; + + +/***/ }), + +/***/ "../solver/getPathTo.ts": +/*!******************************!*\ + !*** ../solver/getPathTo.ts ***! + \******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getPathTo: () => (/* binding */ getPathTo) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _utils_sortPush__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./utils/sortPush */ "../solver/utils/sortPush.ts"); + + + + +/** + * starting from snake0, get to the cell x,y + * return the snake chain (reversed) + */ +const getPathTo = (grid, snake0, x, y) => { + const openList = [{ snake: snake0, w: 0 }]; + const closeList = []; + while (openList.length) { + const c = openList.shift(); + const cx = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.getHeadX)(c.snake); + const cy = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.getHeadY)(c.snake); + for (let i = 0; i < _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4.length; i++) { + const { x: dx, y: dy } = _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4[i]; + const nx = cx + dx; + const ny = cy + dy; + if (nx === x && ny === y) { + // unwrap + const path = [(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.nextSnake)(c.snake, dx, dy)]; + let e = c; + while (e.parent) { + path.push(e.snake); + e = e.parent; + } + return path; + } + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInsideLarge)(grid, 2, nx, ny) && + !(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.snakeWillSelfCollide)(c.snake, dx, dy) && + (!(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, nx, ny) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, nx, ny)))) { + const nsnake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.nextSnake)(c.snake, dx, dy); + if (!closeList.some((s) => (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.snakeEquals)(nsnake, s))) { + const w = c.w + 1; + const h = Math.abs(nx - x) + Math.abs(ny - y); + const f = w + h; + const o = { snake: nsnake, parent: c, w, h, f }; + (0,_utils_sortPush__WEBPACK_IMPORTED_MODULE_3__.sortPush)(openList, o, (a, b) => a.f - b.f); + closeList.push(nsnake); + } + } + } + } +}; + + +/***/ }), + +/***/ "../solver/getPathToPose.ts": +/*!**********************************!*\ + !*** ../solver/getPathToPose.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getPathToPose: () => (/* binding */ getPathToPose) +/* harmony export */ }); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _tunnel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./tunnel */ "../solver/tunnel.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); +/* harmony import */ var _utils_sortPush__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./utils/sortPush */ "../solver/utils/sortPush.ts"); + + + + + +const isEmptySafe = (grid, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_1__.isInside)(grid, x, y) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_1__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_1__.getColor)(grid, x, y)); +const getPathToPose = (snake0, target, grid) => { + if ((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.snakeEquals)(snake0, target)) + return []; + const targetCells = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.snakeToCells)(target).reverse(); + const snakeN = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getSnakeLength)(snake0); + const box = { + min: { + x: Math.min((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(snake0), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(target)) - snakeN - 1, + y: Math.min((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(snake0), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(target)) - snakeN - 1, + }, + max: { + x: Math.max((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(snake0), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(target)) + snakeN + 1, + y: Math.max((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(snake0), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(target)) + snakeN + 1, + }, + }; + const [t0, ...forbidden] = targetCells; + forbidden.slice(0, 3); + const openList = [{ snake: snake0, w: 0 }]; + const closeList = []; + while (openList.length) { + const o = openList.shift(); + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(o.snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(o.snake); + if (x === t0.x && y === t0.y) { + const path = []; + let e = o; + while (e) { + path.push(e.snake); + e = e.parent; + } + path.unshift(...(0,_tunnel__WEBPACK_IMPORTED_MODULE_2__.getTunnelPath)(path[0], targetCells)); + path.pop(); + path.reverse(); + return path; + } + for (let i = 0; i < _snk_types_point__WEBPACK_IMPORTED_MODULE_3__.around4.length; i++) { + const { x: dx, y: dy } = _snk_types_point__WEBPACK_IMPORTED_MODULE_3__.around4[i]; + const nx = x + dx; + const ny = y + dy; + if (!(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.snakeWillSelfCollide)(o.snake, dx, dy) && + (!grid || isEmptySafe(grid, nx, ny)) && + (grid + ? (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_1__.isInsideLarge)(grid, 2, nx, ny) + : box.min.x <= nx && + nx <= box.max.x && + box.min.y <= ny && + ny <= box.max.y) && + !forbidden.some((p) => p.x === nx && p.y === ny)) { + const snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.nextSnake)(o.snake, dx, dy); + if (!closeList.some((s) => (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.snakeEquals)(snake, s))) { + const w = o.w + 1; + const h = Math.abs(nx - x) + Math.abs(ny - y); + const f = w + h; + (0,_utils_sortPush__WEBPACK_IMPORTED_MODULE_4__.sortPush)(openList, { f, w, snake, parent: o }, (a, b) => a.f - b.f); + closeList.push(snake); + } + } + } + } +}; + + +/***/ }), + +/***/ "../solver/outside.ts": +/*!****************************!*\ + !*** ../solver/outside.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createOutside: () => (/* binding */ createOutside), +/* harmony export */ fillOutside: () => (/* binding */ fillOutside), +/* harmony export */ isOutside: () => (/* binding */ isOutside) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); + + +const createOutside = (grid, color = 0) => { + const outside = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.createEmptyGrid)(grid.width, grid.height); + for (let x = outside.width; x--;) + for (let y = outside.height; y--;) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(outside, x, y, 1); + fillOutside(outside, grid, color); + return outside; +}; +const fillOutside = (outside, grid, color = 0) => { + let changed = true; + while (changed) { + changed = false; + for (let x = outside.width; x--;) + for (let y = outside.height; y--;) + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) <= color && + !isOutside(outside, x, y) && + _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4.some((a) => isOutside(outside, x + a.x, y + a.y))) { + changed = true; + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(outside, x, y); + } + } + return outside; +}; +const isOutside = (outside, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(outside, x, y) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(outside, x, y)); + + +/***/ }), + +/***/ "../solver/tunnel.ts": +/*!***************************!*\ + !*** ../solver/tunnel.ts ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getTunnelPath: () => (/* binding */ getTunnelPath), +/* harmony export */ trimTunnelEnd: () => (/* binding */ trimTunnelEnd), +/* harmony export */ trimTunnelStart: () => (/* binding */ trimTunnelStart), +/* harmony export */ updateTunnel: () => (/* binding */ updateTunnel) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); + + +/** + * get the sequence of snake to cross the tunnel + */ +const getTunnelPath = (snake0, tunnel) => { + const chain = []; + let snake = snake0; + for (let i = 1; i < tunnel.length; i++) { + const dx = tunnel[i].x - (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake); + const dy = tunnel[i].y - (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake); + snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.nextSnake)(snake, dx, dy); + chain.unshift(snake); + } + return chain; +}; +/** + * assuming the grid change and the colors got deleted, update the tunnel + */ +const updateTunnel = (grid, tunnel, toDelete) => { + while (tunnel.length) { + const { x, y } = tunnel[0]; + if (isEmptySafe(grid, x, y) || + toDelete.some((p) => p.x === x && p.y === y)) { + tunnel.shift(); + } + else + break; + } + while (tunnel.length) { + const { x, y } = tunnel[tunnel.length - 1]; + if (isEmptySafe(grid, x, y) || + toDelete.some((p) => p.x === x && p.y === y)) { + tunnel.pop(); + } + else + break; + } +}; +const isEmptySafe = (grid, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y)); +/** + * remove empty cell from start + */ +const trimTunnelStart = (grid, tunnel) => { + while (tunnel.length) { + const { x, y } = tunnel[0]; + if (isEmptySafe(grid, x, y)) + tunnel.shift(); + else + break; + } +}; +/** + * remove empty cell from end + */ +const trimTunnelEnd = (grid, tunnel) => { + while (tunnel.length) { + const i = tunnel.length - 1; + const { x, y } = tunnel[i]; + if (isEmptySafe(grid, x, y) || + tunnel.findIndex((p) => p.x === x && p.y === y) < i) + tunnel.pop(); + else + break; + } +}; + + +/***/ }), + +/***/ "../solver/utils/sortPush.ts": +/*!***********************************!*\ + !*** ../solver/utils/sortPush.ts ***! + \***********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ sortPush: () => (/* binding */ sortPush) +/* harmony export */ }); +const sortPush = (arr, x, sortFn) => { + let a = 0; + let b = arr.length; + if (arr.length === 0 || sortFn(x, arr[a]) <= 0) { + arr.unshift(x); + return; + } + while (b - a > 1) { + const e = Math.ceil((a + b) / 2); + const s = sortFn(x, arr[e]); + if (s === 0) + a = b = e; + else if (s > 0) + a = e; + else + b = e; + } + const e = Math.ceil((a + b) / 2); + arr.splice(e, 0, x); +}; + + +/***/ }), + +/***/ "../svg-creator/css-utils.ts": +/*!***********************************!*\ + !*** ../svg-creator/css-utils.ts ***! + \***********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createAnimation: () => (/* binding */ createAnimation), +/* harmony export */ minifyCss: () => (/* binding */ minifyCss) +/* harmony export */ }); +const percent = (x) => parseFloat((x * 100).toFixed(2)).toString() + "%"; +const mergeKeyFrames = (keyframes) => { + var _a; + const s = new Map(); + for (const { t, style } of keyframes) { + s.set(style, [...((_a = s.get(style)) !== null && _a !== void 0 ? _a : []), t]); + } + return Array.from(s.entries()) + .map(([style, ts]) => ({ style, ts })) + .sort((a, b) => a.ts[0] - b.ts[0]); +}; +/** + * generate the keyframe animation from a list of keyframe + */ +const createAnimation = (name, keyframes) => `@keyframes ${name}{` + + mergeKeyFrames(keyframes) + .map(({ style, ts }) => ts.map(percent).join(",") + `{${style}}`) + .join("") + + "}"; +/** + * remove white spaces + */ +const minifyCss = (css) => css + .replace(/\s+/g, " ") + .replace(/.\s+[,;:{}()]/g, (a) => a.replace(/\s+/g, "")) + .replace(/[,;:{}()]\s+./g, (a) => a.replace(/\s+/g, "")) + .replace(/.\s+[,;:{}()]/g, (a) => a.replace(/\s+/g, "")) + .replace(/[,;:{}()]\s+./g, (a) => a.replace(/\s+/g, "")) + .replace(/\;\s*\}/g, "}") + .trim(); + + +/***/ }), + +/***/ "../svg-creator/grid.ts": +/*!******************************!*\ + !*** ../svg-creator/grid.ts ***! + \******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createGrid: () => (/* binding */ createGrid) +/* harmony export */ }); +/* harmony import */ var _css_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./css-utils */ "../svg-creator/css-utils.ts"); +/* harmony import */ var _xml_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./xml-utils */ "../svg-creator/xml-utils.ts"); + + +const createGrid = (cells, { sizeDotBorderRadius, sizeDot, sizeCell }, duration) => { + const svgElements = []; + const styles = [ + `.c{ + shape-rendering: geometricPrecision; + fill: var(--ce); + stroke-width: 1px; + stroke: var(--cb); + animation: none ${duration}ms linear infinite; + width: ${sizeDot}px; + height: ${sizeDot}px; + }`, + ]; + let i = 0; + for (const { x, y, color, t } of cells) { + const id = t && "c" + (i++).toString(36); + const m = (sizeCell - sizeDot) / 2; + if (t !== null && id) { + const animationName = id; + styles.push((0,_css_utils__WEBPACK_IMPORTED_MODULE_0__.createAnimation)(animationName, [ + { t: t - 0.0001, style: `fill:var(--c${color})` }, + { t: t + 0.0001, style: `fill:var(--ce)` }, + { t: 1, style: `fill:var(--ce)` }, + ]), `.c.${id}{ + fill: var(--c${color}); + animation-name: ${animationName} + }`); + } + svgElements.push((0,_xml_utils__WEBPACK_IMPORTED_MODULE_1__.h)("rect", { + class: ["c", id].filter(Boolean).join(" "), + x: x * sizeCell + m, + y: y * sizeCell + m, + rx: sizeDotBorderRadius, + ry: sizeDotBorderRadius, + })); + } + return { svgElements, styles }; +}; + + +/***/ }), + +/***/ "../svg-creator/index.ts": +/*!*******************************!*\ + !*** ../svg-creator/index.ts ***! + \*******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createSvg: () => (/* binding */ createSvg) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./snake */ "../svg-creator/snake.ts"); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./grid */ "../svg-creator/grid.ts"); +/* harmony import */ var _stack__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./stack */ "../svg-creator/stack.ts"); +/* harmony import */ var _xml_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./xml-utils */ "../svg-creator/xml-utils.ts"); +/* harmony import */ var _css_utils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./css-utils */ "../svg-creator/css-utils.ts"); + + + + + + + +const getCellsFromGrid = ({ width, height }) => Array.from({ length: width }, (_, x) => Array.from({ length: height }, (_, y) => ({ x, y }))).flat(); +const createLivingCells = (grid0, chain, cells) => { + const livingCells = (cells !== null && cells !== void 0 ? cells : getCellsFromGrid(grid0)).map(({ x, y }) => ({ + x, + y, + t: null, + color: (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid0, x, y), + })); + const grid = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.copyGrid)(grid0); + for (let i = 0; i < chain.length; i++) { + const snake = chain[i]; + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake); + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) && !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y))) { + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); + const cell = livingCells.find((c) => c.x === x && c.y === y); + cell.t = i / chain.length; + } + } + return livingCells; +}; +const createSvg = (grid, cells, chain, drawOptions, animationOptions) => { + const width = (grid.width + 2) * drawOptions.sizeCell; + const height = (grid.height + 5) * drawOptions.sizeCell; + const duration = animationOptions.frameDuration * chain.length; + const livingCells = createLivingCells(grid, chain, cells); + const elements = [ + (0,_grid__WEBPACK_IMPORTED_MODULE_3__.createGrid)(livingCells, drawOptions, duration), + (0,_stack__WEBPACK_IMPORTED_MODULE_4__.createStack)(livingCells, drawOptions, grid.width * drawOptions.sizeCell, (grid.height + 2) * drawOptions.sizeCell, duration), + (0,_snake__WEBPACK_IMPORTED_MODULE_2__.createSnake)(chain, drawOptions, duration), + ]; + const viewBox = [ + -drawOptions.sizeCell, + -drawOptions.sizeCell * 2, + width, + height, + ].join(" "); + const style = generateColorVar(drawOptions) + + elements + .map((e) => e.styles) + .flat() + .join("\n"); + const svg = [ + (0,_xml_utils__WEBPACK_IMPORTED_MODULE_5__.h)("svg", { + viewBox, + width, + height, + xmlns: "http://www.w3.org/2000/svg", + }).replace("/>", ">"), + "", + "Generated with https://github.com/Platane/snk", + "", + "", + ...elements.map((e) => e.svgElements).flat(), + "", + ].join(""); + return optimizeSvg(svg); +}; +const optimizeCss = (css) => (0,_css_utils__WEBPACK_IMPORTED_MODULE_6__.minifyCss)(css); +const optimizeSvg = (svg) => svg; +const generateColorVar = (drawOptions) => ` + :root { + --cb: ${drawOptions.colorDotBorder}; + --cs: ${drawOptions.colorSnake}; + --ce: ${drawOptions.colorEmpty}; + ${Object.entries(drawOptions.colorDots) + .map(([i, color]) => `--c${i}:${color};`) + .join("")} + } + ` + + (drawOptions.dark + ? ` + @media (prefers-color-scheme: dark) { + :root { + --cb: ${drawOptions.dark.colorDotBorder || drawOptions.colorDotBorder}; + --cs: ${drawOptions.dark.colorSnake || drawOptions.colorSnake}; + --ce: ${drawOptions.dark.colorEmpty}; + ${Object.entries(drawOptions.dark.colorDots) + .map(([i, color]) => `--c${i}:${color};`) + .join("")} + } + } +` + : ""); + + +/***/ }), + +/***/ "../svg-creator/snake.ts": +/*!*******************************!*\ + !*** ../svg-creator/snake.ts ***! + \*******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createSnake: () => (/* binding */ createSnake) +/* harmony export */ }); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _xml_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./xml-utils */ "../svg-creator/xml-utils.ts"); +/* harmony import */ var _css_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./css-utils */ "../svg-creator/css-utils.ts"); + + + +const lerp = (k, a, b) => (1 - k) * a + k * b; +const createSnake = (chain, { sizeCell, sizeDot }, duration) => { + const snakeN = chain[0] ? (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getSnakeLength)(chain[0]) : 0; + const snakeParts = Array.from({ length: snakeN }, () => []); + for (const snake of chain) { + const cells = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.snakeToCells)(snake); + for (let i = cells.length; i--;) + snakeParts[i].push(cells[i]); + } + const svgElements = snakeParts.map((_, i, { length }) => { + // compute snake part size + const dMin = sizeDot * 0.8; + const dMax = sizeCell * 0.9; + const iMax = Math.min(4, length); + const u = (1 - Math.min(i, iMax) / iMax) ** 2; + const s = lerp(u, dMin, dMax); + const m = (sizeCell - s) / 2; + const r = Math.min(4.5, (4 * s) / sizeDot); + return (0,_xml_utils__WEBPACK_IMPORTED_MODULE_1__.h)("rect", { + class: `s s${i}`, + x: m.toFixed(1), + y: m.toFixed(1), + width: s.toFixed(1), + height: s.toFixed(1), + rx: r.toFixed(1), + ry: r.toFixed(1), + }); + }); + const transform = ({ x, y }) => `transform:translate(${x * sizeCell}px,${y * sizeCell}px)`; + const styles = [ + `.s{ + shape-rendering: geometricPrecision; + fill: var(--cs); + animation: none linear ${duration}ms infinite + }`, + ...snakeParts.map((positions, i) => { + const id = `s${i}`; + const animationName = id; + const keyframes = removeInterpolatedPositions(positions.map((tr, i, { length }) => ({ ...tr, t: i / length }))).map(({ t, ...p }) => ({ t, style: transform(p) })); + return [ + (0,_css_utils__WEBPACK_IMPORTED_MODULE_2__.createAnimation)(animationName, keyframes), + `.s.${id}{ + ${transform(positions[0])}; + animation-name: ${animationName} + }`, + ]; + }), + ].flat(); + return { svgElements, styles }; +}; +const removeInterpolatedPositions = (arr) => arr.filter((u, i, arr) => { + if (i - 1 < 0 || i + 1 >= arr.length) + return true; + const a = arr[i - 1]; + const b = arr[i + 1]; + const ex = (a.x + b.x) / 2; + const ey = (a.y + b.y) / 2; + // return true; + return !(Math.abs(ex - u.x) < 0.01 && Math.abs(ey - u.y) < 0.01); +}); + + +/***/ }), + +/***/ "../svg-creator/stack.ts": +/*!*******************************!*\ + !*** ../svg-creator/stack.ts ***! + \*******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createStack: () => (/* binding */ createStack) +/* harmony export */ }); +/* harmony import */ var _css_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./css-utils */ "../svg-creator/css-utils.ts"); +/* harmony import */ var _xml_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./xml-utils */ "../svg-creator/xml-utils.ts"); + + +const createStack = (cells, { sizeDot }, width, y, duration) => { + const svgElements = []; + const styles = [ + `.u{ + transform-origin: 0 0; + transform: scale(0,1); + animation: none linear ${duration}ms infinite; + }`, + ]; + const stack = cells + .slice() + .filter((a) => a.t !== null) + .sort((a, b) => a.t - b.t); + const blocks = []; + stack.forEach(({ color, t }) => { + const latest = blocks[blocks.length - 1]; + if ((latest === null || latest === void 0 ? void 0 : latest.color) === color) + latest.ts.push(t); + else + blocks.push({ color, ts: [t] }); + }); + const m = width / stack.length; + let i = 0; + let nx = 0; + for (const { color, ts } of blocks) { + const id = "u" + (i++).toString(36); + const animationName = id; + const x = (nx * m).toFixed(1); + nx += ts.length; + svgElements.push((0,_xml_utils__WEBPACK_IMPORTED_MODULE_1__.h)("rect", { + class: `u ${id}`, + height: sizeDot, + width: (ts.length * m + 0.6).toFixed(1), + x, + y, + })); + styles.push((0,_css_utils__WEBPACK_IMPORTED_MODULE_0__.createAnimation)(animationName, [ + ...ts + .map((t, i, { length }) => [ + { scale: i / length, t: t - 0.0001 }, + { scale: (i + 1) / length, t: t + 0.0001 }, + ]) + .flat(), + { scale: 1, t: 1 }, + ].map(({ scale, t }) => ({ + t, + style: `transform:scale(${scale.toFixed(3)},1)`, + }))), `.u.${id} { + fill: var(--c${color}); + animation-name: ${animationName}; + transform-origin: ${x}px 0 + } + `); + } + return { svgElements, styles }; +}; + + +/***/ }), + +/***/ "../svg-creator/xml-utils.ts": +/*!***********************************!*\ + !*** ../svg-creator/xml-utils.ts ***! + \***********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ h: () => (/* binding */ h), +/* harmony export */ toAttribute: () => (/* binding */ toAttribute) +/* harmony export */ }); +const h = (element, attributes) => `<${element} ${toAttribute(attributes)}/>`; +const toAttribute = (o) => Object.entries(o) + .filter(([, value]) => value !== null) + .map(([name, value]) => `${name}="${value}"`) + .join(" "); + + +/***/ }), + +/***/ "../types/__fixtures__/createFromAscii.ts": +/*!************************************************!*\ + !*** ../types/__fixtures__/createFromAscii.ts ***! + \************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createFromAscii: () => (/* binding */ createFromAscii) +/* harmony export */ }); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../grid */ "../types/grid.ts"); + +const createFromAscii = (ascii) => { + const a = ascii.split("\n"); + if (a[0] === "") + a.shift(); + const height = a.length; + const width = Math.max(...a.map((r) => r.length)); + const grid = (0,_grid__WEBPACK_IMPORTED_MODULE_0__.createEmptyGrid)(width, height); + for (let x = width; x--;) + for (let y = height; y--;) { + const c = a[y][x]; + const color = (c === "#" && 3) || (c === "@" && 2) || (c === "." && 1) || +c; + if (c) + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(grid, x, y, color); + } + return grid; +}; + + +/***/ }), + +/***/ "../types/__fixtures__/grid.ts": +/*!*************************************!*\ + !*** ../types/__fixtures__/grid.ts ***! + \*************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ closedO: () => (/* binding */ closedO), +/* harmony export */ closedP: () => (/* binding */ closedP), +/* harmony export */ closedU: () => (/* binding */ closedU), +/* harmony export */ corner: () => (/* binding */ corner), +/* harmony export */ empty: () => (/* binding */ empty), +/* harmony export */ enclaveBorder: () => (/* binding */ enclaveBorder), +/* harmony export */ enclaveK: () => (/* binding */ enclaveK), +/* harmony export */ enclaveM: () => (/* binding */ enclaveM), +/* harmony export */ enclaveN: () => (/* binding */ enclaveN), +/* harmony export */ enclaveU: () => (/* binding */ enclaveU), +/* harmony export */ realistic: () => (/* binding */ realistic), +/* harmony export */ realisticFull: () => (/* binding */ realisticFull), +/* harmony export */ simple: () => (/* binding */ simple), +/* harmony export */ small: () => (/* binding */ small), +/* harmony export */ smallFull: () => (/* binding */ smallFull), +/* harmony export */ smallPacked: () => (/* binding */ smallPacked), +/* harmony export */ tunnels: () => (/* binding */ tunnels) +/* harmony export */ }); +/* harmony import */ var park_miller__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! park-miller */ "../../node_modules/park-miller/index.js"); +/* harmony import */ var park_miller__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(park_miller__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../grid */ "../types/grid.ts"); +/* harmony import */ var _randomlyFillGrid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../randomlyFillGrid */ "../types/randomlyFillGrid.ts"); +/* harmony import */ var _createFromAscii__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./createFromAscii */ "../types/__fixtures__/createFromAscii.ts"); + + + + +const colors = [1, 2, 3]; +// empty small grid +const empty = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +// empty small grid with a unique color at the middle +const simple = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(simple, 2, 2, 1); +// empty small grid with color at each corner +const corner = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 0, 4, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 4, 0, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 4, 4, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 0, 0, 1); +const enclaveN = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #.# + # + +`); +const enclaveBorder = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + #.# + # + +`); +const enclaveM = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### + # # + # . # + # # + # # +`); +const enclaveK = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + # .# + # # + # # + # # +`); +const enclaveU = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + #..# + #..# + #.# + # # . +`); +const closedP = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### + ##.# + ## # + ## +`); +const closedU = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + #..# + #..# + #.# + ### +`); +const closedO = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ####### + # # + # . # + # # + ####### +`); +const tunnels = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### ### ### + #.# #.# #.# + #.# ### # # +`); +const createRandom = (width, height, emptyP) => { + const grid = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(width, height); + const pm = new (park_miller__WEBPACK_IMPORTED_MODULE_0___default())(10); + const random = pm.integerInRange.bind(pm); + (0,_randomlyFillGrid__WEBPACK_IMPORTED_MODULE_2__.randomlyFillGrid)(grid, { colors, emptyP }, random); + return grid; +}; +// small realistic +const small = createRandom(10, 7, 3); +const smallPacked = createRandom(10, 7, 1); +const smallFull = createRandom(10, 7, 0); +// small realistic +const realistic = createRandom(52, 7, 3); +const realisticFull = createRandom(52, 7, 0); + + +/***/ }), + +/***/ "../types/__fixtures__/snake.ts": +/*!**************************************!*\ + !*** ../types/__fixtures__/snake.ts ***! + \**************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ snake1: () => (/* binding */ snake1), +/* harmony export */ snake3: () => (/* binding */ snake3), +/* harmony export */ snake4: () => (/* binding */ snake4), +/* harmony export */ snake5: () => (/* binding */ snake5), +/* harmony export */ snake9: () => (/* binding */ snake9) +/* harmony export */ }); +/* harmony import */ var _snake__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../snake */ "../types/snake.ts"); + +const create = (length) => (0,_snake__WEBPACK_IMPORTED_MODULE_0__.createSnakeFromCells)(Array.from({ length }, (_, i) => ({ x: i, y: -1 }))); +const snake1 = create(1); +const snake3 = create(3); +const snake4 = create(4); +const snake5 = create(5); +const snake9 = create(9); + + +/***/ }), + +/***/ "../types/grid.ts": +/*!************************!*\ + !*** ../types/grid.ts ***! + \************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copyGrid: () => (/* binding */ copyGrid), +/* harmony export */ createEmptyGrid: () => (/* binding */ createEmptyGrid), +/* harmony export */ getColor: () => (/* binding */ getColor), +/* harmony export */ gridEquals: () => (/* binding */ gridEquals), +/* harmony export */ isEmpty: () => (/* binding */ isEmpty), +/* harmony export */ isGridEmpty: () => (/* binding */ isGridEmpty), +/* harmony export */ isInside: () => (/* binding */ isInside), +/* harmony export */ isInsideLarge: () => (/* binding */ isInsideLarge), +/* harmony export */ setColor: () => (/* binding */ setColor), +/* harmony export */ setColorEmpty: () => (/* binding */ setColorEmpty) +/* harmony export */ }); +const isInside = (grid, x, y) => x >= 0 && y >= 0 && x < grid.width && y < grid.height; +const isInsideLarge = (grid, m, x, y) => x >= -m && y >= -m && x < grid.width + m && y < grid.height + m; +const copyGrid = ({ width, height, data }) => ({ + width, + height, + data: Uint8Array.from(data), +}); +const getIndex = (grid, x, y) => x * grid.height + y; +const getColor = (grid, x, y) => grid.data[getIndex(grid, x, y)]; +const isEmpty = (color) => color === 0; +const setColor = (grid, x, y, color) => { + grid.data[getIndex(grid, x, y)] = color || 0; +}; +const setColorEmpty = (grid, x, y) => { + setColor(grid, x, y, 0); +}; +/** + * return true if the grid is empty + */ +const isGridEmpty = (grid) => grid.data.every((x) => x === 0); +const gridEquals = (a, b) => a.data.every((_, i) => a.data[i] === b.data[i]); +const createEmptyGrid = (width, height) => ({ + width, + height, + data: new Uint8Array(width * height), +}); + + +/***/ }), + +/***/ "../types/point.ts": +/*!*************************!*\ + !*** ../types/point.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ around4: () => (/* binding */ around4), +/* harmony export */ pointEquals: () => (/* binding */ pointEquals) +/* harmony export */ }); +const around4 = [ + { x: 1, y: 0 }, + { x: 0, y: -1 }, + { x: -1, y: 0 }, + { x: 0, y: 1 }, +]; +const pointEquals = (a, b) => a.x === b.x && a.y === b.y; + + +/***/ }), + +/***/ "../types/randomlyFillGrid.ts": +/*!************************************!*\ + !*** ../types/randomlyFillGrid.ts ***! + \************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ randomlyFillGrid: () => (/* binding */ randomlyFillGrid) +/* harmony export */ }); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./grid */ "../types/grid.ts"); + +const defaultRand = (a, b) => Math.floor(Math.random() * (b - a + 1)) + a; +const randomlyFillGrid = (grid, { colors = [1, 2, 3], emptyP = 2, } = {}, rand = defaultRand) => { + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + const k = rand(-emptyP, colors.length - 1); + if (k >= 0) + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(grid, x, y, colors[k]); + else + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); + } +}; + + +/***/ }), + +/***/ "../types/snake.ts": +/*!*************************!*\ + !*** ../types/snake.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copySnake: () => (/* binding */ copySnake), +/* harmony export */ createSnakeFromCells: () => (/* binding */ createSnakeFromCells), +/* harmony export */ getHeadX: () => (/* binding */ getHeadX), +/* harmony export */ getHeadY: () => (/* binding */ getHeadY), +/* harmony export */ getSnakeLength: () => (/* binding */ getSnakeLength), +/* harmony export */ nextSnake: () => (/* binding */ nextSnake), +/* harmony export */ snakeEquals: () => (/* binding */ snakeEquals), +/* harmony export */ snakeToCells: () => (/* binding */ snakeToCells), +/* harmony export */ snakeWillSelfCollide: () => (/* binding */ snakeWillSelfCollide) +/* harmony export */ }); +const getHeadX = (snake) => snake[0] - 2; +const getHeadY = (snake) => snake[1] - 2; +const getSnakeLength = (snake) => snake.length / 2; +const copySnake = (snake) => snake.slice(); +const snakeEquals = (a, b) => { + for (let i = 0; i < a.length; i++) + if (a[i] !== b[i]) + return false; + return true; +}; +/** + * return a copy of the next snake, considering that dx, dy is the direction + */ +const nextSnake = (snake, dx, dy) => { + const copy = new Uint8Array(snake.length); + for (let i = 2; i < snake.length; i++) + copy[i] = snake[i - 2]; + copy[0] = snake[0] + dx; + copy[1] = snake[1] + dy; + return copy; +}; +/** + * return true if the next snake will collide with itself + */ +const snakeWillSelfCollide = (snake, dx, dy) => { + const nx = snake[0] + dx; + const ny = snake[1] + dy; + for (let i = 2; i < snake.length - 2; i += 2) + if (snake[i + 0] === nx && snake[i + 1] === ny) + return true; + return false; +}; +const snakeToCells = (snake) => Array.from({ length: snake.length / 2 }, (_, i) => ({ + x: snake[i * 2 + 0] - 2, + y: snake[i * 2 + 1] - 2, +})); +const createSnakeFromCells = (points) => { + const snake = new Uint8Array(points.length * 2); + for (let i = points.length; i--;) { + snake[i * 2 + 0] = points[i].x + 2; + snake[i * 2 + 1] = points[i].y + 2; + } + return snake; +}; + + +/***/ }), + +/***/ "./demo.json": +/*!*******************!*\ + !*** ./demo.json ***! + \*******************/ +/***/ ((module) => { + +module.exports = JSON.parse('["interactive","getBestRoute","getBestTunnel","outside","getPathToPose","getPathTo","svg"]'); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ (() => { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = (module) => { +/******/ var getter = module && module.__esModule ? +/******/ () => (module['default']) : +/******/ () => (module); +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +/*!*********************!*\ + !*** ./demo.svg.ts ***! + \*********************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _menu__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./menu */ "./menu.ts"); +/* harmony import */ var _snk_solver_getBestRoute__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/solver/getBestRoute */ "../solver/getBestRoute.ts"); +/* harmony import */ var _snk_svg_creator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/svg-creator */ "../svg-creator/index.ts"); +/* harmony import */ var _sample__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sample */ "./sample.ts"); +/* harmony import */ var _canvas__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./canvas */ "./canvas.ts"); +/* harmony import */ var _snk_solver_getPathToPose__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @snk/solver/getPathToPose */ "../solver/getPathToPose.ts"); + + + + + + +const chain = (0,_snk_solver_getBestRoute__WEBPACK_IMPORTED_MODULE_1__.getBestRoute)(_sample__WEBPACK_IMPORTED_MODULE_3__.grid, _sample__WEBPACK_IMPORTED_MODULE_3__.snake); +chain.push(...(0,_snk_solver_getPathToPose__WEBPACK_IMPORTED_MODULE_5__.getPathToPose)(chain.slice(-1)[0], _sample__WEBPACK_IMPORTED_MODULE_3__.snake)); +(async () => { + const svg = await (0,_snk_svg_creator__WEBPACK_IMPORTED_MODULE_2__.createSvg)(_sample__WEBPACK_IMPORTED_MODULE_3__.grid, null, chain, _canvas__WEBPACK_IMPORTED_MODULE_4__.drawOptions, { + frameDuration: 200, + }); + const container = document.createElement("div"); + container.innerHTML = svg; + document.body.appendChild(container); +})(); + +})(); + +/******/ })() +; \ No newline at end of file diff --git a/0e9b4657eed0a04b8c79.js b/0e9b4657eed0a04b8c79.js new file mode 100644 index 000000000..774682a16 --- /dev/null +++ b/0e9b4657eed0a04b8c79.js @@ -0,0 +1,3612 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "../../node_modules/dat.gui/build/dat.gui.module.js": +/*!**********************************************************!*\ + !*** ../../node_modules/dat.gui/build/dat.gui.module.js ***! + \**********************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ GUI: () => (/* binding */ GUI$1), +/* harmony export */ color: () => (/* binding */ color), +/* harmony export */ controllers: () => (/* binding */ controllers), +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), +/* harmony export */ dom: () => (/* binding */ dom$1), +/* harmony export */ gui: () => (/* binding */ gui) +/* harmony export */ }); +/** + * dat-gui JavaScript Controller Library + * https://github.com/dataarts/dat.gui + * + * Copyright 2011 Data Arts Team, Google Creative Lab + * + * 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 + */ + +function ___$insertStyle(css) { + if (!css) { + return; + } + if (typeof window === 'undefined') { + return; + } + + var style = document.createElement('style'); + + style.setAttribute('type', 'text/css'); + style.innerHTML = css; + document.head.appendChild(style); + + return css; +} + +function colorToString (color, forceCSSHex) { + var colorFormat = color.__state.conversionName.toString(); + var r = Math.round(color.r); + var g = Math.round(color.g); + var b = Math.round(color.b); + var a = color.a; + var h = Math.round(color.h); + var s = color.s.toFixed(1); + var v = color.v.toFixed(1); + if (forceCSSHex || colorFormat === 'THREE_CHAR_HEX' || colorFormat === 'SIX_CHAR_HEX') { + var str = color.hex.toString(16); + while (str.length < 6) { + str = '0' + str; + } + return '#' + str; + } else if (colorFormat === 'CSS_RGB') { + return 'rgb(' + r + ',' + g + ',' + b + ')'; + } else if (colorFormat === 'CSS_RGBA') { + return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; + } else if (colorFormat === 'HEX') { + return '0x' + color.hex.toString(16); + } else if (colorFormat === 'RGB_ARRAY') { + return '[' + r + ',' + g + ',' + b + ']'; + } else if (colorFormat === 'RGBA_ARRAY') { + return '[' + r + ',' + g + ',' + b + ',' + a + ']'; + } else if (colorFormat === 'RGB_OBJ') { + return '{r:' + r + ',g:' + g + ',b:' + b + '}'; + } else if (colorFormat === 'RGBA_OBJ') { + return '{r:' + r + ',g:' + g + ',b:' + b + ',a:' + a + '}'; + } else if (colorFormat === 'HSV_OBJ') { + return '{h:' + h + ',s:' + s + ',v:' + v + '}'; + } else if (colorFormat === 'HSVA_OBJ') { + return '{h:' + h + ',s:' + s + ',v:' + v + ',a:' + a + '}'; + } + return 'unknown format'; +} + +var ARR_EACH = Array.prototype.forEach; +var ARR_SLICE = Array.prototype.slice; +var Common = { + BREAK: {}, + extend: function extend(target) { + this.each(ARR_SLICE.call(arguments, 1), function (obj) { + var keys = this.isObject(obj) ? Object.keys(obj) : []; + keys.forEach(function (key) { + if (!this.isUndefined(obj[key])) { + target[key] = obj[key]; + } + }.bind(this)); + }, this); + return target; + }, + defaults: function defaults(target) { + this.each(ARR_SLICE.call(arguments, 1), function (obj) { + var keys = this.isObject(obj) ? Object.keys(obj) : []; + keys.forEach(function (key) { + if (this.isUndefined(target[key])) { + target[key] = obj[key]; + } + }.bind(this)); + }, this); + return target; + }, + compose: function compose() { + var toCall = ARR_SLICE.call(arguments); + return function () { + var args = ARR_SLICE.call(arguments); + for (var i = toCall.length - 1; i >= 0; i--) { + args = [toCall[i].apply(this, args)]; + } + return args[0]; + }; + }, + each: function each(obj, itr, scope) { + if (!obj) { + return; + } + if (ARR_EACH && obj.forEach && obj.forEach === ARR_EACH) { + obj.forEach(itr, scope); + } else if (obj.length === obj.length + 0) { + var key = void 0; + var l = void 0; + for (key = 0, l = obj.length; key < l; key++) { + if (key in obj && itr.call(scope, obj[key], key) === this.BREAK) { + return; + } + } + } else { + for (var _key in obj) { + if (itr.call(scope, obj[_key], _key) === this.BREAK) { + return; + } + } + } + }, + defer: function defer(fnc) { + setTimeout(fnc, 0); + }, + debounce: function debounce(func, threshold, callImmediately) { + var timeout = void 0; + return function () { + var obj = this; + var args = arguments; + function delayed() { + timeout = null; + if (!callImmediately) func.apply(obj, args); + } + var callNow = callImmediately || !timeout; + clearTimeout(timeout); + timeout = setTimeout(delayed, threshold); + if (callNow) { + func.apply(obj, args); + } + }; + }, + toArray: function toArray(obj) { + if (obj.toArray) return obj.toArray(); + return ARR_SLICE.call(obj); + }, + isUndefined: function isUndefined(obj) { + return obj === undefined; + }, + isNull: function isNull(obj) { + return obj === null; + }, + isNaN: function (_isNaN) { + function isNaN(_x) { + return _isNaN.apply(this, arguments); + } + isNaN.toString = function () { + return _isNaN.toString(); + }; + return isNaN; + }(function (obj) { + return isNaN(obj); + }), + isArray: Array.isArray || function (obj) { + return obj.constructor === Array; + }, + isObject: function isObject(obj) { + return obj === Object(obj); + }, + isNumber: function isNumber(obj) { + return obj === obj + 0; + }, + isString: function isString(obj) { + return obj === obj + ''; + }, + isBoolean: function isBoolean(obj) { + return obj === false || obj === true; + }, + isFunction: function isFunction(obj) { + return obj instanceof Function; + } +}; + +var INTERPRETATIONS = [ +{ + litmus: Common.isString, + conversions: { + THREE_CHAR_HEX: { + read: function read(original) { + var test = original.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i); + if (test === null) { + return false; + } + return { + space: 'HEX', + hex: parseInt('0x' + test[1].toString() + test[1].toString() + test[2].toString() + test[2].toString() + test[3].toString() + test[3].toString(), 0) + }; + }, + write: colorToString + }, + SIX_CHAR_HEX: { + read: function read(original) { + var test = original.match(/^#([A-F0-9]{6})$/i); + if (test === null) { + return false; + } + return { + space: 'HEX', + hex: parseInt('0x' + test[1].toString(), 0) + }; + }, + write: colorToString + }, + CSS_RGB: { + read: function read(original) { + var test = original.match(/^rgb\(\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*\)/); + if (test === null) { + return false; + } + return { + space: 'RGB', + r: parseFloat(test[1]), + g: parseFloat(test[2]), + b: parseFloat(test[3]) + }; + }, + write: colorToString + }, + CSS_RGBA: { + read: function read(original) { + var test = original.match(/^rgba\(\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*\)/); + if (test === null) { + return false; + } + return { + space: 'RGB', + r: parseFloat(test[1]), + g: parseFloat(test[2]), + b: parseFloat(test[3]), + a: parseFloat(test[4]) + }; + }, + write: colorToString + } + } +}, +{ + litmus: Common.isNumber, + conversions: { + HEX: { + read: function read(original) { + return { + space: 'HEX', + hex: original, + conversionName: 'HEX' + }; + }, + write: function write(color) { + return color.hex; + } + } + } +}, +{ + litmus: Common.isArray, + conversions: { + RGB_ARRAY: { + read: function read(original) { + if (original.length !== 3) { + return false; + } + return { + space: 'RGB', + r: original[0], + g: original[1], + b: original[2] + }; + }, + write: function write(color) { + return [color.r, color.g, color.b]; + } + }, + RGBA_ARRAY: { + read: function read(original) { + if (original.length !== 4) return false; + return { + space: 'RGB', + r: original[0], + g: original[1], + b: original[2], + a: original[3] + }; + }, + write: function write(color) { + return [color.r, color.g, color.b, color.a]; + } + } + } +}, +{ + litmus: Common.isObject, + conversions: { + RGBA_OBJ: { + read: function read(original) { + if (Common.isNumber(original.r) && Common.isNumber(original.g) && Common.isNumber(original.b) && Common.isNumber(original.a)) { + return { + space: 'RGB', + r: original.r, + g: original.g, + b: original.b, + a: original.a + }; + } + return false; + }, + write: function write(color) { + return { + r: color.r, + g: color.g, + b: color.b, + a: color.a + }; + } + }, + RGB_OBJ: { + read: function read(original) { + if (Common.isNumber(original.r) && Common.isNumber(original.g) && Common.isNumber(original.b)) { + return { + space: 'RGB', + r: original.r, + g: original.g, + b: original.b + }; + } + return false; + }, + write: function write(color) { + return { + r: color.r, + g: color.g, + b: color.b + }; + } + }, + HSVA_OBJ: { + read: function read(original) { + if (Common.isNumber(original.h) && Common.isNumber(original.s) && Common.isNumber(original.v) && Common.isNumber(original.a)) { + return { + space: 'HSV', + h: original.h, + s: original.s, + v: original.v, + a: original.a + }; + } + return false; + }, + write: function write(color) { + return { + h: color.h, + s: color.s, + v: color.v, + a: color.a + }; + } + }, + HSV_OBJ: { + read: function read(original) { + if (Common.isNumber(original.h) && Common.isNumber(original.s) && Common.isNumber(original.v)) { + return { + space: 'HSV', + h: original.h, + s: original.s, + v: original.v + }; + } + return false; + }, + write: function write(color) { + return { + h: color.h, + s: color.s, + v: color.v + }; + } + } + } +}]; +var result = void 0; +var toReturn = void 0; +var interpret = function interpret() { + toReturn = false; + var original = arguments.length > 1 ? Common.toArray(arguments) : arguments[0]; + Common.each(INTERPRETATIONS, function (family) { + if (family.litmus(original)) { + Common.each(family.conversions, function (conversion, conversionName) { + result = conversion.read(original); + if (toReturn === false && result !== false) { + toReturn = result; + result.conversionName = conversionName; + result.conversion = conversion; + return Common.BREAK; + } + }); + return Common.BREAK; + } + }); + return toReturn; +}; + +var tmpComponent = void 0; +var ColorMath = { + hsv_to_rgb: function hsv_to_rgb(h, s, v) { + var hi = Math.floor(h / 60) % 6; + var f = h / 60 - Math.floor(h / 60); + var p = v * (1.0 - s); + var q = v * (1.0 - f * s); + var t = v * (1.0 - (1.0 - f) * s); + var c = [[v, t, p], [q, v, p], [p, v, t], [p, q, v], [t, p, v], [v, p, q]][hi]; + return { + r: c[0] * 255, + g: c[1] * 255, + b: c[2] * 255 + }; + }, + rgb_to_hsv: function rgb_to_hsv(r, g, b) { + var min = Math.min(r, g, b); + var max = Math.max(r, g, b); + var delta = max - min; + var h = void 0; + var s = void 0; + if (max !== 0) { + s = delta / max; + } else { + return { + h: NaN, + s: 0, + v: 0 + }; + } + if (r === max) { + h = (g - b) / delta; + } else if (g === max) { + h = 2 + (b - r) / delta; + } else { + h = 4 + (r - g) / delta; + } + h /= 6; + if (h < 0) { + h += 1; + } + return { + h: h * 360, + s: s, + v: max / 255 + }; + }, + rgb_to_hex: function rgb_to_hex(r, g, b) { + var hex = this.hex_with_component(0, 2, r); + hex = this.hex_with_component(hex, 1, g); + hex = this.hex_with_component(hex, 0, b); + return hex; + }, + component_from_hex: function component_from_hex(hex, componentIndex) { + return hex >> componentIndex * 8 & 0xFF; + }, + hex_with_component: function hex_with_component(hex, componentIndex, value) { + return value << (tmpComponent = componentIndex * 8) | hex & ~(0xFF << tmpComponent); + } +}; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; +} : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; +}; + + + + + + + + + + + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; + +var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; +}(); + + + + + + + +var get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); + + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + + if (getter === undefined) { + return undefined; + } + + return getter.call(receiver); + } +}; + +var inherits = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; +}; + + + + + + + + + + + +var possibleConstructorReturn = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && (typeof call === "object" || typeof call === "function") ? call : self; +}; + +var Color = function () { + function Color() { + classCallCheck(this, Color); + this.__state = interpret.apply(this, arguments); + if (this.__state === false) { + throw new Error('Failed to interpret color arguments'); + } + this.__state.a = this.__state.a || 1; + } + createClass(Color, [{ + key: 'toString', + value: function toString() { + return colorToString(this); + } + }, { + key: 'toHexString', + value: function toHexString() { + return colorToString(this, true); + } + }, { + key: 'toOriginal', + value: function toOriginal() { + return this.__state.conversion.write(this); + } + }]); + return Color; +}(); +function defineRGBComponent(target, component, componentHexIndex) { + Object.defineProperty(target, component, { + get: function get$$1() { + if (this.__state.space === 'RGB') { + return this.__state[component]; + } + Color.recalculateRGB(this, component, componentHexIndex); + return this.__state[component]; + }, + set: function set$$1(v) { + if (this.__state.space !== 'RGB') { + Color.recalculateRGB(this, component, componentHexIndex); + this.__state.space = 'RGB'; + } + this.__state[component] = v; + } + }); +} +function defineHSVComponent(target, component) { + Object.defineProperty(target, component, { + get: function get$$1() { + if (this.__state.space === 'HSV') { + return this.__state[component]; + } + Color.recalculateHSV(this); + return this.__state[component]; + }, + set: function set$$1(v) { + if (this.__state.space !== 'HSV') { + Color.recalculateHSV(this); + this.__state.space = 'HSV'; + } + this.__state[component] = v; + } + }); +} +Color.recalculateRGB = function (color, component, componentHexIndex) { + if (color.__state.space === 'HEX') { + color.__state[component] = ColorMath.component_from_hex(color.__state.hex, componentHexIndex); + } else if (color.__state.space === 'HSV') { + Common.extend(color.__state, ColorMath.hsv_to_rgb(color.__state.h, color.__state.s, color.__state.v)); + } else { + throw new Error('Corrupted color state'); + } +}; +Color.recalculateHSV = function (color) { + var result = ColorMath.rgb_to_hsv(color.r, color.g, color.b); + Common.extend(color.__state, { + s: result.s, + v: result.v + }); + if (!Common.isNaN(result.h)) { + color.__state.h = result.h; + } else if (Common.isUndefined(color.__state.h)) { + color.__state.h = 0; + } +}; +Color.COMPONENTS = ['r', 'g', 'b', 'h', 's', 'v', 'hex', 'a']; +defineRGBComponent(Color.prototype, 'r', 2); +defineRGBComponent(Color.prototype, 'g', 1); +defineRGBComponent(Color.prototype, 'b', 0); +defineHSVComponent(Color.prototype, 'h'); +defineHSVComponent(Color.prototype, 's'); +defineHSVComponent(Color.prototype, 'v'); +Object.defineProperty(Color.prototype, 'a', { + get: function get$$1() { + return this.__state.a; + }, + set: function set$$1(v) { + this.__state.a = v; + } +}); +Object.defineProperty(Color.prototype, 'hex', { + get: function get$$1() { + if (this.__state.space !== 'HEX') { + this.__state.hex = ColorMath.rgb_to_hex(this.r, this.g, this.b); + this.__state.space = 'HEX'; + } + return this.__state.hex; + }, + set: function set$$1(v) { + this.__state.space = 'HEX'; + this.__state.hex = v; + } +}); + +var Controller = function () { + function Controller(object, property) { + classCallCheck(this, Controller); + this.initialValue = object[property]; + this.domElement = document.createElement('div'); + this.object = object; + this.property = property; + this.__onChange = undefined; + this.__onFinishChange = undefined; + } + createClass(Controller, [{ + key: 'onChange', + value: function onChange(fnc) { + this.__onChange = fnc; + return this; + } + }, { + key: 'onFinishChange', + value: function onFinishChange(fnc) { + this.__onFinishChange = fnc; + return this; + } + }, { + key: 'setValue', + value: function setValue(newValue) { + this.object[this.property] = newValue; + if (this.__onChange) { + this.__onChange.call(this, newValue); + } + this.updateDisplay(); + return this; + } + }, { + key: 'getValue', + value: function getValue() { + return this.object[this.property]; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + return this; + } + }, { + key: 'isModified', + value: function isModified() { + return this.initialValue !== this.getValue(); + } + }]); + return Controller; +}(); + +var EVENT_MAP = { + HTMLEvents: ['change'], + MouseEvents: ['click', 'mousemove', 'mousedown', 'mouseup', 'mouseover'], + KeyboardEvents: ['keydown'] +}; +var EVENT_MAP_INV = {}; +Common.each(EVENT_MAP, function (v, k) { + Common.each(v, function (e) { + EVENT_MAP_INV[e] = k; + }); +}); +var CSS_VALUE_PIXELS = /(\d+(\.\d+)?)px/; +function cssValueToPixels(val) { + if (val === '0' || Common.isUndefined(val)) { + return 0; + } + var match = val.match(CSS_VALUE_PIXELS); + if (!Common.isNull(match)) { + return parseFloat(match[1]); + } + return 0; +} +var dom = { + makeSelectable: function makeSelectable(elem, selectable) { + if (elem === undefined || elem.style === undefined) return; + elem.onselectstart = selectable ? function () { + return false; + } : function () {}; + elem.style.MozUserSelect = selectable ? 'auto' : 'none'; + elem.style.KhtmlUserSelect = selectable ? 'auto' : 'none'; + elem.unselectable = selectable ? 'on' : 'off'; + }, + makeFullscreen: function makeFullscreen(elem, hor, vert) { + var vertical = vert; + var horizontal = hor; + if (Common.isUndefined(horizontal)) { + horizontal = true; + } + if (Common.isUndefined(vertical)) { + vertical = true; + } + elem.style.position = 'absolute'; + if (horizontal) { + elem.style.left = 0; + elem.style.right = 0; + } + if (vertical) { + elem.style.top = 0; + elem.style.bottom = 0; + } + }, + fakeEvent: function fakeEvent(elem, eventType, pars, aux) { + var params = pars || {}; + var className = EVENT_MAP_INV[eventType]; + if (!className) { + throw new Error('Event type ' + eventType + ' not supported.'); + } + var evt = document.createEvent(className); + switch (className) { + case 'MouseEvents': + { + var clientX = params.x || params.clientX || 0; + var clientY = params.y || params.clientY || 0; + evt.initMouseEvent(eventType, params.bubbles || false, params.cancelable || true, window, params.clickCount || 1, 0, + 0, + clientX, + clientY, + false, false, false, false, 0, null); + break; + } + case 'KeyboardEvents': + { + var init = evt.initKeyboardEvent || evt.initKeyEvent; + Common.defaults(params, { + cancelable: true, + ctrlKey: false, + altKey: false, + shiftKey: false, + metaKey: false, + keyCode: undefined, + charCode: undefined + }); + init(eventType, params.bubbles || false, params.cancelable, window, params.ctrlKey, params.altKey, params.shiftKey, params.metaKey, params.keyCode, params.charCode); + break; + } + default: + { + evt.initEvent(eventType, params.bubbles || false, params.cancelable || true); + break; + } + } + Common.defaults(evt, aux); + elem.dispatchEvent(evt); + }, + bind: function bind(elem, event, func, newBool) { + var bool = newBool || false; + if (elem.addEventListener) { + elem.addEventListener(event, func, bool); + } else if (elem.attachEvent) { + elem.attachEvent('on' + event, func); + } + return dom; + }, + unbind: function unbind(elem, event, func, newBool) { + var bool = newBool || false; + if (elem.removeEventListener) { + elem.removeEventListener(event, func, bool); + } else if (elem.detachEvent) { + elem.detachEvent('on' + event, func); + } + return dom; + }, + addClass: function addClass(elem, className) { + if (elem.className === undefined) { + elem.className = className; + } else if (elem.className !== className) { + var classes = elem.className.split(/ +/); + if (classes.indexOf(className) === -1) { + classes.push(className); + elem.className = classes.join(' ').replace(/^\s+/, '').replace(/\s+$/, ''); + } + } + return dom; + }, + removeClass: function removeClass(elem, className) { + if (className) { + if (elem.className === className) { + elem.removeAttribute('class'); + } else { + var classes = elem.className.split(/ +/); + var index = classes.indexOf(className); + if (index !== -1) { + classes.splice(index, 1); + elem.className = classes.join(' '); + } + } + } else { + elem.className = undefined; + } + return dom; + }, + hasClass: function hasClass(elem, className) { + return new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)').test(elem.className) || false; + }, + getWidth: function getWidth(elem) { + var style = getComputedStyle(elem); + return cssValueToPixels(style['border-left-width']) + cssValueToPixels(style['border-right-width']) + cssValueToPixels(style['padding-left']) + cssValueToPixels(style['padding-right']) + cssValueToPixels(style.width); + }, + getHeight: function getHeight(elem) { + var style = getComputedStyle(elem); + return cssValueToPixels(style['border-top-width']) + cssValueToPixels(style['border-bottom-width']) + cssValueToPixels(style['padding-top']) + cssValueToPixels(style['padding-bottom']) + cssValueToPixels(style.height); + }, + getOffset: function getOffset(el) { + var elem = el; + var offset = { left: 0, top: 0 }; + if (elem.offsetParent) { + do { + offset.left += elem.offsetLeft; + offset.top += elem.offsetTop; + elem = elem.offsetParent; + } while (elem); + } + return offset; + }, + isActive: function isActive(elem) { + return elem === document.activeElement && (elem.type || elem.href); + } +}; + +var BooleanController = function (_Controller) { + inherits(BooleanController, _Controller); + function BooleanController(object, property) { + classCallCheck(this, BooleanController); + var _this2 = possibleConstructorReturn(this, (BooleanController.__proto__ || Object.getPrototypeOf(BooleanController)).call(this, object, property)); + var _this = _this2; + _this2.__prev = _this2.getValue(); + _this2.__checkbox = document.createElement('input'); + _this2.__checkbox.setAttribute('type', 'checkbox'); + function onChange() { + _this.setValue(!_this.__prev); + } + dom.bind(_this2.__checkbox, 'change', onChange, false); + _this2.domElement.appendChild(_this2.__checkbox); + _this2.updateDisplay(); + return _this2; + } + createClass(BooleanController, [{ + key: 'setValue', + value: function setValue(v) { + var toReturn = get(BooleanController.prototype.__proto__ || Object.getPrototypeOf(BooleanController.prototype), 'setValue', this).call(this, v); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + this.__prev = this.getValue(); + return toReturn; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + if (this.getValue() === true) { + this.__checkbox.setAttribute('checked', 'checked'); + this.__checkbox.checked = true; + this.__prev = true; + } else { + this.__checkbox.checked = false; + this.__prev = false; + } + return get(BooleanController.prototype.__proto__ || Object.getPrototypeOf(BooleanController.prototype), 'updateDisplay', this).call(this); + } + }]); + return BooleanController; +}(Controller); + +var OptionController = function (_Controller) { + inherits(OptionController, _Controller); + function OptionController(object, property, opts) { + classCallCheck(this, OptionController); + var _this2 = possibleConstructorReturn(this, (OptionController.__proto__ || Object.getPrototypeOf(OptionController)).call(this, object, property)); + var options = opts; + var _this = _this2; + _this2.__select = document.createElement('select'); + if (Common.isArray(options)) { + var map = {}; + Common.each(options, function (element) { + map[element] = element; + }); + options = map; + } + Common.each(options, function (value, key) { + var opt = document.createElement('option'); + opt.innerHTML = key; + opt.setAttribute('value', value); + _this.__select.appendChild(opt); + }); + _this2.updateDisplay(); + dom.bind(_this2.__select, 'change', function () { + var desiredValue = this.options[this.selectedIndex].value; + _this.setValue(desiredValue); + }); + _this2.domElement.appendChild(_this2.__select); + return _this2; + } + createClass(OptionController, [{ + key: 'setValue', + value: function setValue(v) { + var toReturn = get(OptionController.prototype.__proto__ || Object.getPrototypeOf(OptionController.prototype), 'setValue', this).call(this, v); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + return toReturn; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + if (dom.isActive(this.__select)) return this; + this.__select.value = this.getValue(); + return get(OptionController.prototype.__proto__ || Object.getPrototypeOf(OptionController.prototype), 'updateDisplay', this).call(this); + } + }]); + return OptionController; +}(Controller); + +var StringController = function (_Controller) { + inherits(StringController, _Controller); + function StringController(object, property) { + classCallCheck(this, StringController); + var _this2 = possibleConstructorReturn(this, (StringController.__proto__ || Object.getPrototypeOf(StringController)).call(this, object, property)); + var _this = _this2; + function onChange() { + _this.setValue(_this.__input.value); + } + function onBlur() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + _this2.__input = document.createElement('input'); + _this2.__input.setAttribute('type', 'text'); + dom.bind(_this2.__input, 'keyup', onChange); + dom.bind(_this2.__input, 'change', onChange); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + this.blur(); + } + }); + _this2.updateDisplay(); + _this2.domElement.appendChild(_this2.__input); + return _this2; + } + createClass(StringController, [{ + key: 'updateDisplay', + value: function updateDisplay() { + if (!dom.isActive(this.__input)) { + this.__input.value = this.getValue(); + } + return get(StringController.prototype.__proto__ || Object.getPrototypeOf(StringController.prototype), 'updateDisplay', this).call(this); + } + }]); + return StringController; +}(Controller); + +function numDecimals(x) { + var _x = x.toString(); + if (_x.indexOf('.') > -1) { + return _x.length - _x.indexOf('.') - 1; + } + return 0; +} +var NumberController = function (_Controller) { + inherits(NumberController, _Controller); + function NumberController(object, property, params) { + classCallCheck(this, NumberController); + var _this = possibleConstructorReturn(this, (NumberController.__proto__ || Object.getPrototypeOf(NumberController)).call(this, object, property)); + var _params = params || {}; + _this.__min = _params.min; + _this.__max = _params.max; + _this.__step = _params.step; + if (Common.isUndefined(_this.__step)) { + if (_this.initialValue === 0) { + _this.__impliedStep = 1; + } else { + _this.__impliedStep = Math.pow(10, Math.floor(Math.log(Math.abs(_this.initialValue)) / Math.LN10)) / 10; + } + } else { + _this.__impliedStep = _this.__step; + } + _this.__precision = numDecimals(_this.__impliedStep); + return _this; + } + createClass(NumberController, [{ + key: 'setValue', + value: function setValue(v) { + var _v = v; + if (this.__min !== undefined && _v < this.__min) { + _v = this.__min; + } else if (this.__max !== undefined && _v > this.__max) { + _v = this.__max; + } + if (this.__step !== undefined && _v % this.__step !== 0) { + _v = Math.round(_v / this.__step) * this.__step; + } + return get(NumberController.prototype.__proto__ || Object.getPrototypeOf(NumberController.prototype), 'setValue', this).call(this, _v); + } + }, { + key: 'min', + value: function min(minValue) { + this.__min = minValue; + return this; + } + }, { + key: 'max', + value: function max(maxValue) { + this.__max = maxValue; + return this; + } + }, { + key: 'step', + value: function step(stepValue) { + this.__step = stepValue; + this.__impliedStep = stepValue; + this.__precision = numDecimals(stepValue); + return this; + } + }]); + return NumberController; +}(Controller); + +function roundToDecimal(value, decimals) { + var tenTo = Math.pow(10, decimals); + return Math.round(value * tenTo) / tenTo; +} +var NumberControllerBox = function (_NumberController) { + inherits(NumberControllerBox, _NumberController); + function NumberControllerBox(object, property, params) { + classCallCheck(this, NumberControllerBox); + var _this2 = possibleConstructorReturn(this, (NumberControllerBox.__proto__ || Object.getPrototypeOf(NumberControllerBox)).call(this, object, property, params)); + _this2.__truncationSuspended = false; + var _this = _this2; + var prevY = void 0; + function onChange() { + var attempted = parseFloat(_this.__input.value); + if (!Common.isNaN(attempted)) { + _this.setValue(attempted); + } + } + function onFinish() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + function onBlur() { + onFinish(); + } + function onMouseDrag(e) { + var diff = prevY - e.clientY; + _this.setValue(_this.getValue() + diff * _this.__impliedStep); + prevY = e.clientY; + } + function onMouseUp() { + dom.unbind(window, 'mousemove', onMouseDrag); + dom.unbind(window, 'mouseup', onMouseUp); + onFinish(); + } + function onMouseDown(e) { + dom.bind(window, 'mousemove', onMouseDrag); + dom.bind(window, 'mouseup', onMouseUp); + prevY = e.clientY; + } + _this2.__input = document.createElement('input'); + _this2.__input.setAttribute('type', 'text'); + dom.bind(_this2.__input, 'change', onChange); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__input, 'mousedown', onMouseDown); + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + _this.__truncationSuspended = true; + this.blur(); + _this.__truncationSuspended = false; + onFinish(); + } + }); + _this2.updateDisplay(); + _this2.domElement.appendChild(_this2.__input); + return _this2; + } + createClass(NumberControllerBox, [{ + key: 'updateDisplay', + value: function updateDisplay() { + this.__input.value = this.__truncationSuspended ? this.getValue() : roundToDecimal(this.getValue(), this.__precision); + return get(NumberControllerBox.prototype.__proto__ || Object.getPrototypeOf(NumberControllerBox.prototype), 'updateDisplay', this).call(this); + } + }]); + return NumberControllerBox; +}(NumberController); + +function map(v, i1, i2, o1, o2) { + return o1 + (o2 - o1) * ((v - i1) / (i2 - i1)); +} +var NumberControllerSlider = function (_NumberController) { + inherits(NumberControllerSlider, _NumberController); + function NumberControllerSlider(object, property, min, max, step) { + classCallCheck(this, NumberControllerSlider); + var _this2 = possibleConstructorReturn(this, (NumberControllerSlider.__proto__ || Object.getPrototypeOf(NumberControllerSlider)).call(this, object, property, { min: min, max: max, step: step })); + var _this = _this2; + _this2.__background = document.createElement('div'); + _this2.__foreground = document.createElement('div'); + dom.bind(_this2.__background, 'mousedown', onMouseDown); + dom.bind(_this2.__background, 'touchstart', onTouchStart); + dom.addClass(_this2.__background, 'slider'); + dom.addClass(_this2.__foreground, 'slider-fg'); + function onMouseDown(e) { + document.activeElement.blur(); + dom.bind(window, 'mousemove', onMouseDrag); + dom.bind(window, 'mouseup', onMouseUp); + onMouseDrag(e); + } + function onMouseDrag(e) { + e.preventDefault(); + var bgRect = _this.__background.getBoundingClientRect(); + _this.setValue(map(e.clientX, bgRect.left, bgRect.right, _this.__min, _this.__max)); + return false; + } + function onMouseUp() { + dom.unbind(window, 'mousemove', onMouseDrag); + dom.unbind(window, 'mouseup', onMouseUp); + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + function onTouchStart(e) { + if (e.touches.length !== 1) { + return; + } + dom.bind(window, 'touchmove', onTouchMove); + dom.bind(window, 'touchend', onTouchEnd); + onTouchMove(e); + } + function onTouchMove(e) { + var clientX = e.touches[0].clientX; + var bgRect = _this.__background.getBoundingClientRect(); + _this.setValue(map(clientX, bgRect.left, bgRect.right, _this.__min, _this.__max)); + } + function onTouchEnd() { + dom.unbind(window, 'touchmove', onTouchMove); + dom.unbind(window, 'touchend', onTouchEnd); + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + _this2.updateDisplay(); + _this2.__background.appendChild(_this2.__foreground); + _this2.domElement.appendChild(_this2.__background); + return _this2; + } + createClass(NumberControllerSlider, [{ + key: 'updateDisplay', + value: function updateDisplay() { + var pct = (this.getValue() - this.__min) / (this.__max - this.__min); + this.__foreground.style.width = pct * 100 + '%'; + return get(NumberControllerSlider.prototype.__proto__ || Object.getPrototypeOf(NumberControllerSlider.prototype), 'updateDisplay', this).call(this); + } + }]); + return NumberControllerSlider; +}(NumberController); + +var FunctionController = function (_Controller) { + inherits(FunctionController, _Controller); + function FunctionController(object, property, text) { + classCallCheck(this, FunctionController); + var _this2 = possibleConstructorReturn(this, (FunctionController.__proto__ || Object.getPrototypeOf(FunctionController)).call(this, object, property)); + var _this = _this2; + _this2.__button = document.createElement('div'); + _this2.__button.innerHTML = text === undefined ? 'Fire' : text; + dom.bind(_this2.__button, 'click', function (e) { + e.preventDefault(); + _this.fire(); + return false; + }); + dom.addClass(_this2.__button, 'button'); + _this2.domElement.appendChild(_this2.__button); + return _this2; + } + createClass(FunctionController, [{ + key: 'fire', + value: function fire() { + if (this.__onChange) { + this.__onChange.call(this); + } + this.getValue().call(this.object); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + } + }]); + return FunctionController; +}(Controller); + +var ColorController = function (_Controller) { + inherits(ColorController, _Controller); + function ColorController(object, property) { + classCallCheck(this, ColorController); + var _this2 = possibleConstructorReturn(this, (ColorController.__proto__ || Object.getPrototypeOf(ColorController)).call(this, object, property)); + _this2.__color = new Color(_this2.getValue()); + _this2.__temp = new Color(0); + var _this = _this2; + _this2.domElement = document.createElement('div'); + dom.makeSelectable(_this2.domElement, false); + _this2.__selector = document.createElement('div'); + _this2.__selector.className = 'selector'; + _this2.__saturation_field = document.createElement('div'); + _this2.__saturation_field.className = 'saturation-field'; + _this2.__field_knob = document.createElement('div'); + _this2.__field_knob.className = 'field-knob'; + _this2.__field_knob_border = '2px solid '; + _this2.__hue_knob = document.createElement('div'); + _this2.__hue_knob.className = 'hue-knob'; + _this2.__hue_field = document.createElement('div'); + _this2.__hue_field.className = 'hue-field'; + _this2.__input = document.createElement('input'); + _this2.__input.type = 'text'; + _this2.__input_textShadow = '0 1px 1px '; + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + onBlur.call(this); + } + }); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__selector, 'mousedown', function () { + dom.addClass(this, 'drag').bind(window, 'mouseup', function () { + dom.removeClass(_this.__selector, 'drag'); + }); + }); + dom.bind(_this2.__selector, 'touchstart', function () { + dom.addClass(this, 'drag').bind(window, 'touchend', function () { + dom.removeClass(_this.__selector, 'drag'); + }); + }); + var valueField = document.createElement('div'); + Common.extend(_this2.__selector.style, { + width: '122px', + height: '102px', + padding: '3px', + backgroundColor: '#222', + boxShadow: '0px 1px 3px rgba(0,0,0,0.3)' + }); + Common.extend(_this2.__field_knob.style, { + position: 'absolute', + width: '12px', + height: '12px', + border: _this2.__field_knob_border + (_this2.__color.v < 0.5 ? '#fff' : '#000'), + boxShadow: '0px 1px 3px rgba(0,0,0,0.5)', + borderRadius: '12px', + zIndex: 1 + }); + Common.extend(_this2.__hue_knob.style, { + position: 'absolute', + width: '15px', + height: '2px', + borderRight: '4px solid #fff', + zIndex: 1 + }); + Common.extend(_this2.__saturation_field.style, { + width: '100px', + height: '100px', + border: '1px solid #555', + marginRight: '3px', + display: 'inline-block', + cursor: 'pointer' + }); + Common.extend(valueField.style, { + width: '100%', + height: '100%', + background: 'none' + }); + linearGradient(valueField, 'top', 'rgba(0,0,0,0)', '#000'); + Common.extend(_this2.__hue_field.style, { + width: '15px', + height: '100px', + border: '1px solid #555', + cursor: 'ns-resize', + position: 'absolute', + top: '3px', + right: '3px' + }); + hueGradient(_this2.__hue_field); + Common.extend(_this2.__input.style, { + outline: 'none', + textAlign: 'center', + color: '#fff', + border: 0, + fontWeight: 'bold', + textShadow: _this2.__input_textShadow + 'rgba(0,0,0,0.7)' + }); + dom.bind(_this2.__saturation_field, 'mousedown', fieldDown); + dom.bind(_this2.__saturation_field, 'touchstart', fieldDown); + dom.bind(_this2.__field_knob, 'mousedown', fieldDown); + dom.bind(_this2.__field_knob, 'touchstart', fieldDown); + dom.bind(_this2.__hue_field, 'mousedown', fieldDownH); + dom.bind(_this2.__hue_field, 'touchstart', fieldDownH); + function fieldDown(e) { + setSV(e); + dom.bind(window, 'mousemove', setSV); + dom.bind(window, 'touchmove', setSV); + dom.bind(window, 'mouseup', fieldUpSV); + dom.bind(window, 'touchend', fieldUpSV); + } + function fieldDownH(e) { + setH(e); + dom.bind(window, 'mousemove', setH); + dom.bind(window, 'touchmove', setH); + dom.bind(window, 'mouseup', fieldUpH); + dom.bind(window, 'touchend', fieldUpH); + } + function fieldUpSV() { + dom.unbind(window, 'mousemove', setSV); + dom.unbind(window, 'touchmove', setSV); + dom.unbind(window, 'mouseup', fieldUpSV); + dom.unbind(window, 'touchend', fieldUpSV); + onFinish(); + } + function fieldUpH() { + dom.unbind(window, 'mousemove', setH); + dom.unbind(window, 'touchmove', setH); + dom.unbind(window, 'mouseup', fieldUpH); + dom.unbind(window, 'touchend', fieldUpH); + onFinish(); + } + function onBlur() { + var i = interpret(this.value); + if (i !== false) { + _this.__color.__state = i; + _this.setValue(_this.__color.toOriginal()); + } else { + this.value = _this.__color.toString(); + } + } + function onFinish() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.__color.toOriginal()); + } + } + _this2.__saturation_field.appendChild(valueField); + _this2.__selector.appendChild(_this2.__field_knob); + _this2.__selector.appendChild(_this2.__saturation_field); + _this2.__selector.appendChild(_this2.__hue_field); + _this2.__hue_field.appendChild(_this2.__hue_knob); + _this2.domElement.appendChild(_this2.__input); + _this2.domElement.appendChild(_this2.__selector); + _this2.updateDisplay(); + function setSV(e) { + if (e.type.indexOf('touch') === -1) { + e.preventDefault(); + } + var fieldRect = _this.__saturation_field.getBoundingClientRect(); + var _ref = e.touches && e.touches[0] || e, + clientX = _ref.clientX, + clientY = _ref.clientY; + var s = (clientX - fieldRect.left) / (fieldRect.right - fieldRect.left); + var v = 1 - (clientY - fieldRect.top) / (fieldRect.bottom - fieldRect.top); + if (v > 1) { + v = 1; + } else if (v < 0) { + v = 0; + } + if (s > 1) { + s = 1; + } else if (s < 0) { + s = 0; + } + _this.__color.v = v; + _this.__color.s = s; + _this.setValue(_this.__color.toOriginal()); + return false; + } + function setH(e) { + if (e.type.indexOf('touch') === -1) { + e.preventDefault(); + } + var fieldRect = _this.__hue_field.getBoundingClientRect(); + var _ref2 = e.touches && e.touches[0] || e, + clientY = _ref2.clientY; + var h = 1 - (clientY - fieldRect.top) / (fieldRect.bottom - fieldRect.top); + if (h > 1) { + h = 1; + } else if (h < 0) { + h = 0; + } + _this.__color.h = h * 360; + _this.setValue(_this.__color.toOriginal()); + return false; + } + return _this2; + } + createClass(ColorController, [{ + key: 'updateDisplay', + value: function updateDisplay() { + var i = interpret(this.getValue()); + if (i !== false) { + var mismatch = false; + Common.each(Color.COMPONENTS, function (component) { + if (!Common.isUndefined(i[component]) && !Common.isUndefined(this.__color.__state[component]) && i[component] !== this.__color.__state[component]) { + mismatch = true; + return {}; + } + }, this); + if (mismatch) { + Common.extend(this.__color.__state, i); + } + } + Common.extend(this.__temp.__state, this.__color.__state); + this.__temp.a = 1; + var flip = this.__color.v < 0.5 || this.__color.s > 0.5 ? 255 : 0; + var _flip = 255 - flip; + Common.extend(this.__field_knob.style, { + marginLeft: 100 * this.__color.s - 7 + 'px', + marginTop: 100 * (1 - this.__color.v) - 7 + 'px', + backgroundColor: this.__temp.toHexString(), + border: this.__field_knob_border + 'rgb(' + flip + ',' + flip + ',' + flip + ')' + }); + this.__hue_knob.style.marginTop = (1 - this.__color.h / 360) * 100 + 'px'; + this.__temp.s = 1; + this.__temp.v = 1; + linearGradient(this.__saturation_field, 'left', '#fff', this.__temp.toHexString()); + this.__input.value = this.__color.toString(); + Common.extend(this.__input.style, { + backgroundColor: this.__color.toHexString(), + color: 'rgb(' + flip + ',' + flip + ',' + flip + ')', + textShadow: this.__input_textShadow + 'rgba(' + _flip + ',' + _flip + ',' + _flip + ',.7)' + }); + } + }]); + return ColorController; +}(Controller); +var vendors = ['-moz-', '-o-', '-webkit-', '-ms-', '']; +function linearGradient(elem, x, a, b) { + elem.style.background = ''; + Common.each(vendors, function (vendor) { + elem.style.cssText += 'background: ' + vendor + 'linear-gradient(' + x + ', ' + a + ' 0%, ' + b + ' 100%); '; + }); +} +function hueGradient(elem) { + elem.style.background = ''; + elem.style.cssText += 'background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);'; + elem.style.cssText += 'background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; +} + +var css = { + load: function load(url, indoc) { + var doc = indoc || document; + var link = doc.createElement('link'); + link.type = 'text/css'; + link.rel = 'stylesheet'; + link.href = url; + doc.getElementsByTagName('head')[0].appendChild(link); + }, + inject: function inject(cssContent, indoc) { + var doc = indoc || document; + var injected = document.createElement('style'); + injected.type = 'text/css'; + injected.innerHTML = cssContent; + var head = doc.getElementsByTagName('head')[0]; + try { + head.appendChild(injected); + } catch (e) { + } + } +}; + +var saveDialogContents = "
\n\n Here's the new load parameter for your GUI's constructor:\n\n \n\n
\n\n Automatically save\n values to localStorage on exit.\n\n
The values saved to localStorage will\n override those passed to dat.GUI's constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n\n
\n\n
\n\n
"; + +var ControllerFactory = function ControllerFactory(object, property) { + var initialValue = object[property]; + if (Common.isArray(arguments[2]) || Common.isObject(arguments[2])) { + return new OptionController(object, property, arguments[2]); + } + if (Common.isNumber(initialValue)) { + if (Common.isNumber(arguments[2]) && Common.isNumber(arguments[3])) { + if (Common.isNumber(arguments[4])) { + return new NumberControllerSlider(object, property, arguments[2], arguments[3], arguments[4]); + } + return new NumberControllerSlider(object, property, arguments[2], arguments[3]); + } + if (Common.isNumber(arguments[4])) { + return new NumberControllerBox(object, property, { min: arguments[2], max: arguments[3], step: arguments[4] }); + } + return new NumberControllerBox(object, property, { min: arguments[2], max: arguments[3] }); + } + if (Common.isString(initialValue)) { + return new StringController(object, property); + } + if (Common.isFunction(initialValue)) { + return new FunctionController(object, property, ''); + } + if (Common.isBoolean(initialValue)) { + return new BooleanController(object, property); + } + return null; +}; + +function requestAnimationFrame(callback) { + setTimeout(callback, 1000 / 60); +} +var requestAnimationFrame$1 = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || requestAnimationFrame; + +var CenteredDiv = function () { + function CenteredDiv() { + classCallCheck(this, CenteredDiv); + this.backgroundElement = document.createElement('div'); + Common.extend(this.backgroundElement.style, { + backgroundColor: 'rgba(0,0,0,0.8)', + top: 0, + left: 0, + display: 'none', + zIndex: '1000', + opacity: 0, + WebkitTransition: 'opacity 0.2s linear', + transition: 'opacity 0.2s linear' + }); + dom.makeFullscreen(this.backgroundElement); + this.backgroundElement.style.position = 'fixed'; + this.domElement = document.createElement('div'); + Common.extend(this.domElement.style, { + position: 'fixed', + display: 'none', + zIndex: '1001', + opacity: 0, + WebkitTransition: '-webkit-transform 0.2s ease-out, opacity 0.2s linear', + transition: 'transform 0.2s ease-out, opacity 0.2s linear' + }); + document.body.appendChild(this.backgroundElement); + document.body.appendChild(this.domElement); + var _this = this; + dom.bind(this.backgroundElement, 'click', function () { + _this.hide(); + }); + } + createClass(CenteredDiv, [{ + key: 'show', + value: function show() { + var _this = this; + this.backgroundElement.style.display = 'block'; + this.domElement.style.display = 'block'; + this.domElement.style.opacity = 0; + this.domElement.style.webkitTransform = 'scale(1.1)'; + this.layout(); + Common.defer(function () { + _this.backgroundElement.style.opacity = 1; + _this.domElement.style.opacity = 1; + _this.domElement.style.webkitTransform = 'scale(1)'; + }); + } + }, { + key: 'hide', + value: function hide() { + var _this = this; + var hide = function hide() { + _this.domElement.style.display = 'none'; + _this.backgroundElement.style.display = 'none'; + dom.unbind(_this.domElement, 'webkitTransitionEnd', hide); + dom.unbind(_this.domElement, 'transitionend', hide); + dom.unbind(_this.domElement, 'oTransitionEnd', hide); + }; + dom.bind(this.domElement, 'webkitTransitionEnd', hide); + dom.bind(this.domElement, 'transitionend', hide); + dom.bind(this.domElement, 'oTransitionEnd', hide); + this.backgroundElement.style.opacity = 0; + this.domElement.style.opacity = 0; + this.domElement.style.webkitTransform = 'scale(1.1)'; + } + }, { + key: 'layout', + value: function layout() { + this.domElement.style.left = window.innerWidth / 2 - dom.getWidth(this.domElement) / 2 + 'px'; + this.domElement.style.top = window.innerHeight / 2 - dom.getHeight(this.domElement) / 2 + 'px'; + } + }]); + return CenteredDiv; +}(); + +var styleSheet = ___$insertStyle(".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity .1s linear;-o-transition:opacity .1s linear;-moz-transition:opacity .1s linear;transition:opacity .1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1 !important}.dg.main:hover .close-button,.dg.main .close-button.drag{opacity:1}.dg.main .close-button{-webkit-transition:opacity .1s linear;-o-transition:opacity .1s linear;-moz-transition:opacity .1s linear;transition:opacity .1s linear;border:0;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button.close-top{position:relative}.dg.main .close-button.close-bottom{position:absolute}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-y:visible}.dg.a.has-save>ul.close-top{margin-top:0}.dg.a.has-save>ul.close-bottom{margin-top:27px}.dg.a.has-save>ul.closed{margin-top:0}.dg.a .save-row{top:0;z-index:1002}.dg.a .save-row.close-top{position:relative}.dg.a .save-row.close-bottom{position:fixed}.dg li{-webkit-transition:height .1s ease-out;-o-transition:height .1s ease-out;-moz-transition:height .1s ease-out;transition:height .1s ease-out;-webkit-transition:overflow .1s linear;-o-transition:overflow .1s linear;-moz-transition:overflow .1s linear;transition:overflow .1s linear}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid rgba(0,0,0,0)}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li>*{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px;overflow:hidden}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .cr.function .property-name{width:100%}.dg .c{float:left;width:60%;position:relative}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:7px}.dg .c select{margin-top:5px}.dg .cr.function,.dg .cr.function .property-name,.dg .cr.function *,.dg .cr.boolean,.dg .cr.boolean *{cursor:pointer}.dg .cr.color{overflow:visible}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0px 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco, monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px 'Lucida Grande', sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px 4px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid rgba(255,255,255,0.2)}.dg .closed li.title{background-image:url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==)}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.color{border-left:3px solid}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2FA1D6}.dg .cr.number input[type=text]{color:#2FA1D6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.function:hover,.dg .cr.boolean:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2FA1D6;max-width:100%}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}\n"); + +css.inject(styleSheet); +var CSS_NAMESPACE = 'dg'; +var HIDE_KEY_CODE = 72; +var CLOSE_BUTTON_HEIGHT = 20; +var DEFAULT_DEFAULT_PRESET_NAME = 'Default'; +var SUPPORTS_LOCAL_STORAGE = function () { + try { + return !!window.localStorage; + } catch (e) { + return false; + } +}(); +var SAVE_DIALOGUE = void 0; +var autoPlaceVirgin = true; +var autoPlaceContainer = void 0; +var hide = false; +var hideableGuis = []; +var GUI = function GUI(pars) { + var _this = this; + var params = pars || {}; + this.domElement = document.createElement('div'); + this.__ul = document.createElement('ul'); + this.domElement.appendChild(this.__ul); + dom.addClass(this.domElement, CSS_NAMESPACE); + this.__folders = {}; + this.__controllers = []; + this.__rememberedObjects = []; + this.__rememberedObjectIndecesToControllers = []; + this.__listening = []; + params = Common.defaults(params, { + closeOnTop: false, + autoPlace: true, + width: GUI.DEFAULT_WIDTH + }); + params = Common.defaults(params, { + resizable: params.autoPlace, + hideable: params.autoPlace + }); + if (!Common.isUndefined(params.load)) { + if (params.preset) { + params.load.preset = params.preset; + } + } else { + params.load = { preset: DEFAULT_DEFAULT_PRESET_NAME }; + } + if (Common.isUndefined(params.parent) && params.hideable) { + hideableGuis.push(this); + } + params.resizable = Common.isUndefined(params.parent) && params.resizable; + if (params.autoPlace && Common.isUndefined(params.scrollable)) { + params.scrollable = true; + } + var useLocalStorage = SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(this, 'isLocal')) === 'true'; + var saveToLocalStorage = void 0; + var titleRow = void 0; + Object.defineProperties(this, + { + parent: { + get: function get$$1() { + return params.parent; + } + }, + scrollable: { + get: function get$$1() { + return params.scrollable; + } + }, + autoPlace: { + get: function get$$1() { + return params.autoPlace; + } + }, + closeOnTop: { + get: function get$$1() { + return params.closeOnTop; + } + }, + preset: { + get: function get$$1() { + if (_this.parent) { + return _this.getRoot().preset; + } + return params.load.preset; + }, + set: function set$$1(v) { + if (_this.parent) { + _this.getRoot().preset = v; + } else { + params.load.preset = v; + } + setPresetSelectIndex(this); + _this.revert(); + } + }, + width: { + get: function get$$1() { + return params.width; + }, + set: function set$$1(v) { + params.width = v; + setWidth(_this, v); + } + }, + name: { + get: function get$$1() { + return params.name; + }, + set: function set$$1(v) { + params.name = v; + if (titleRow) { + titleRow.innerHTML = params.name; + } + } + }, + closed: { + get: function get$$1() { + return params.closed; + }, + set: function set$$1(v) { + params.closed = v; + if (params.closed) { + dom.addClass(_this.__ul, GUI.CLASS_CLOSED); + } else { + dom.removeClass(_this.__ul, GUI.CLASS_CLOSED); + } + this.onResize(); + if (_this.__closeButton) { + _this.__closeButton.innerHTML = v ? GUI.TEXT_OPEN : GUI.TEXT_CLOSED; + } + } + }, + load: { + get: function get$$1() { + return params.load; + } + }, + useLocalStorage: { + get: function get$$1() { + return useLocalStorage; + }, + set: function set$$1(bool) { + if (SUPPORTS_LOCAL_STORAGE) { + useLocalStorage = bool; + if (bool) { + dom.bind(window, 'unload', saveToLocalStorage); + } else { + dom.unbind(window, 'unload', saveToLocalStorage); + } + localStorage.setItem(getLocalStorageHash(_this, 'isLocal'), bool); + } + } + } + }); + if (Common.isUndefined(params.parent)) { + this.closed = params.closed || false; + dom.addClass(this.domElement, GUI.CLASS_MAIN); + dom.makeSelectable(this.domElement, false); + if (SUPPORTS_LOCAL_STORAGE) { + if (useLocalStorage) { + _this.useLocalStorage = true; + var savedGui = localStorage.getItem(getLocalStorageHash(this, 'gui')); + if (savedGui) { + params.load = JSON.parse(savedGui); + } + } + } + this.__closeButton = document.createElement('div'); + this.__closeButton.innerHTML = GUI.TEXT_CLOSED; + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_BUTTON); + if (params.closeOnTop) { + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_TOP); + this.domElement.insertBefore(this.__closeButton, this.domElement.childNodes[0]); + } else { + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_BOTTOM); + this.domElement.appendChild(this.__closeButton); + } + dom.bind(this.__closeButton, 'click', function () { + _this.closed = !_this.closed; + }); + } else { + if (params.closed === undefined) { + params.closed = true; + } + var titleRowName = document.createTextNode(params.name); + dom.addClass(titleRowName, 'controller-name'); + titleRow = addRow(_this, titleRowName); + var onClickTitle = function onClickTitle(e) { + e.preventDefault(); + _this.closed = !_this.closed; + return false; + }; + dom.addClass(this.__ul, GUI.CLASS_CLOSED); + dom.addClass(titleRow, 'title'); + dom.bind(titleRow, 'click', onClickTitle); + if (!params.closed) { + this.closed = false; + } + } + if (params.autoPlace) { + if (Common.isUndefined(params.parent)) { + if (autoPlaceVirgin) { + autoPlaceContainer = document.createElement('div'); + dom.addClass(autoPlaceContainer, CSS_NAMESPACE); + dom.addClass(autoPlaceContainer, GUI.CLASS_AUTO_PLACE_CONTAINER); + document.body.appendChild(autoPlaceContainer); + autoPlaceVirgin = false; + } + autoPlaceContainer.appendChild(this.domElement); + dom.addClass(this.domElement, GUI.CLASS_AUTO_PLACE); + } + if (!this.parent) { + setWidth(_this, params.width); + } + } + this.__resizeHandler = function () { + _this.onResizeDebounced(); + }; + dom.bind(window, 'resize', this.__resizeHandler); + dom.bind(this.__ul, 'webkitTransitionEnd', this.__resizeHandler); + dom.bind(this.__ul, 'transitionend', this.__resizeHandler); + dom.bind(this.__ul, 'oTransitionEnd', this.__resizeHandler); + this.onResize(); + if (params.resizable) { + addResizeHandle(this); + } + saveToLocalStorage = function saveToLocalStorage() { + if (SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(_this, 'isLocal')) === 'true') { + localStorage.setItem(getLocalStorageHash(_this, 'gui'), JSON.stringify(_this.getSaveObject())); + } + }; + this.saveToLocalStorageIfPossible = saveToLocalStorage; + function resetWidth() { + var root = _this.getRoot(); + root.width += 1; + Common.defer(function () { + root.width -= 1; + }); + } + if (!params.parent) { + resetWidth(); + } +}; +GUI.toggleHide = function () { + hide = !hide; + Common.each(hideableGuis, function (gui) { + gui.domElement.style.display = hide ? 'none' : ''; + }); +}; +GUI.CLASS_AUTO_PLACE = 'a'; +GUI.CLASS_AUTO_PLACE_CONTAINER = 'ac'; +GUI.CLASS_MAIN = 'main'; +GUI.CLASS_CONTROLLER_ROW = 'cr'; +GUI.CLASS_TOO_TALL = 'taller-than-window'; +GUI.CLASS_CLOSED = 'closed'; +GUI.CLASS_CLOSE_BUTTON = 'close-button'; +GUI.CLASS_CLOSE_TOP = 'close-top'; +GUI.CLASS_CLOSE_BOTTOM = 'close-bottom'; +GUI.CLASS_DRAG = 'drag'; +GUI.DEFAULT_WIDTH = 245; +GUI.TEXT_CLOSED = 'Close Controls'; +GUI.TEXT_OPEN = 'Open Controls'; +GUI._keydownHandler = function (e) { + if (document.activeElement.type !== 'text' && (e.which === HIDE_KEY_CODE || e.keyCode === HIDE_KEY_CODE)) { + GUI.toggleHide(); + } +}; +dom.bind(window, 'keydown', GUI._keydownHandler, false); +Common.extend(GUI.prototype, +{ + add: function add(object, property) { + return _add(this, object, property, { + factoryArgs: Array.prototype.slice.call(arguments, 2) + }); + }, + addColor: function addColor(object, property) { + return _add(this, object, property, { + color: true + }); + }, + remove: function remove(controller) { + this.__ul.removeChild(controller.__li); + this.__controllers.splice(this.__controllers.indexOf(controller), 1); + var _this = this; + Common.defer(function () { + _this.onResize(); + }); + }, + destroy: function destroy() { + if (this.parent) { + throw new Error('Only the root GUI should be removed with .destroy(). ' + 'For subfolders, use gui.removeFolder(folder) instead.'); + } + if (this.autoPlace) { + autoPlaceContainer.removeChild(this.domElement); + } + var _this = this; + Common.each(this.__folders, function (subfolder) { + _this.removeFolder(subfolder); + }); + dom.unbind(window, 'keydown', GUI._keydownHandler, false); + removeListeners(this); + }, + addFolder: function addFolder(name) { + if (this.__folders[name] !== undefined) { + throw new Error('You already have a folder in this GUI by the' + ' name "' + name + '"'); + } + var newGuiParams = { name: name, parent: this }; + newGuiParams.autoPlace = this.autoPlace; + if (this.load && + this.load.folders && + this.load.folders[name]) { + newGuiParams.closed = this.load.folders[name].closed; + newGuiParams.load = this.load.folders[name]; + } + var gui = new GUI(newGuiParams); + this.__folders[name] = gui; + var li = addRow(this, gui.domElement); + dom.addClass(li, 'folder'); + return gui; + }, + removeFolder: function removeFolder(folder) { + this.__ul.removeChild(folder.domElement.parentElement); + delete this.__folders[folder.name]; + if (this.load && + this.load.folders && + this.load.folders[folder.name]) { + delete this.load.folders[folder.name]; + } + removeListeners(folder); + var _this = this; + Common.each(folder.__folders, function (subfolder) { + folder.removeFolder(subfolder); + }); + Common.defer(function () { + _this.onResize(); + }); + }, + open: function open() { + this.closed = false; + }, + close: function close() { + this.closed = true; + }, + hide: function hide() { + this.domElement.style.display = 'none'; + }, + show: function show() { + this.domElement.style.display = ''; + }, + onResize: function onResize() { + var root = this.getRoot(); + if (root.scrollable) { + var top = dom.getOffset(root.__ul).top; + var h = 0; + Common.each(root.__ul.childNodes, function (node) { + if (!(root.autoPlace && node === root.__save_row)) { + h += dom.getHeight(node); + } + }); + if (window.innerHeight - top - CLOSE_BUTTON_HEIGHT < h) { + dom.addClass(root.domElement, GUI.CLASS_TOO_TALL); + root.__ul.style.height = window.innerHeight - top - CLOSE_BUTTON_HEIGHT + 'px'; + } else { + dom.removeClass(root.domElement, GUI.CLASS_TOO_TALL); + root.__ul.style.height = 'auto'; + } + } + if (root.__resize_handle) { + Common.defer(function () { + root.__resize_handle.style.height = root.__ul.offsetHeight + 'px'; + }); + } + if (root.__closeButton) { + root.__closeButton.style.width = root.width + 'px'; + } + }, + onResizeDebounced: Common.debounce(function () { + this.onResize(); + }, 50), + remember: function remember() { + if (Common.isUndefined(SAVE_DIALOGUE)) { + SAVE_DIALOGUE = new CenteredDiv(); + SAVE_DIALOGUE.domElement.innerHTML = saveDialogContents; + } + if (this.parent) { + throw new Error('You can only call remember on a top level GUI.'); + } + var _this = this; + Common.each(Array.prototype.slice.call(arguments), function (object) { + if (_this.__rememberedObjects.length === 0) { + addSaveMenu(_this); + } + if (_this.__rememberedObjects.indexOf(object) === -1) { + _this.__rememberedObjects.push(object); + } + }); + if (this.autoPlace) { + setWidth(this, this.width); + } + }, + getRoot: function getRoot() { + var gui = this; + while (gui.parent) { + gui = gui.parent; + } + return gui; + }, + getSaveObject: function getSaveObject() { + var toReturn = this.load; + toReturn.closed = this.closed; + if (this.__rememberedObjects.length > 0) { + toReturn.preset = this.preset; + if (!toReturn.remembered) { + toReturn.remembered = {}; + } + toReturn.remembered[this.preset] = getCurrentPreset(this); + } + toReturn.folders = {}; + Common.each(this.__folders, function (element, key) { + toReturn.folders[key] = element.getSaveObject(); + }); + return toReturn; + }, + save: function save() { + if (!this.load.remembered) { + this.load.remembered = {}; + } + this.load.remembered[this.preset] = getCurrentPreset(this); + markPresetModified(this, false); + this.saveToLocalStorageIfPossible(); + }, + saveAs: function saveAs(presetName) { + if (!this.load.remembered) { + this.load.remembered = {}; + this.load.remembered[DEFAULT_DEFAULT_PRESET_NAME] = getCurrentPreset(this, true); + } + this.load.remembered[presetName] = getCurrentPreset(this); + this.preset = presetName; + addPresetOption(this, presetName, true); + this.saveToLocalStorageIfPossible(); + }, + revert: function revert(gui) { + Common.each(this.__controllers, function (controller) { + if (!this.getRoot().load.remembered) { + controller.setValue(controller.initialValue); + } else { + recallSavedValue(gui || this.getRoot(), controller); + } + if (controller.__onFinishChange) { + controller.__onFinishChange.call(controller, controller.getValue()); + } + }, this); + Common.each(this.__folders, function (folder) { + folder.revert(folder); + }); + if (!gui) { + markPresetModified(this.getRoot(), false); + } + }, + listen: function listen(controller) { + var init = this.__listening.length === 0; + this.__listening.push(controller); + if (init) { + updateDisplays(this.__listening); + } + }, + updateDisplay: function updateDisplay() { + Common.each(this.__controllers, function (controller) { + controller.updateDisplay(); + }); + Common.each(this.__folders, function (folder) { + folder.updateDisplay(); + }); + } +}); +function addRow(gui, newDom, liBefore) { + var li = document.createElement('li'); + if (newDom) { + li.appendChild(newDom); + } + if (liBefore) { + gui.__ul.insertBefore(li, liBefore); + } else { + gui.__ul.appendChild(li); + } + gui.onResize(); + return li; +} +function removeListeners(gui) { + dom.unbind(window, 'resize', gui.__resizeHandler); + if (gui.saveToLocalStorageIfPossible) { + dom.unbind(window, 'unload', gui.saveToLocalStorageIfPossible); + } +} +function markPresetModified(gui, modified) { + var opt = gui.__preset_select[gui.__preset_select.selectedIndex]; + if (modified) { + opt.innerHTML = opt.value + '*'; + } else { + opt.innerHTML = opt.value; + } +} +function augmentController(gui, li, controller) { + controller.__li = li; + controller.__gui = gui; + Common.extend(controller, { + options: function options(_options) { + if (arguments.length > 1) { + var nextSibling = controller.__li.nextElementSibling; + controller.remove(); + return _add(gui, controller.object, controller.property, { + before: nextSibling, + factoryArgs: [Common.toArray(arguments)] + }); + } + if (Common.isArray(_options) || Common.isObject(_options)) { + var _nextSibling = controller.__li.nextElementSibling; + controller.remove(); + return _add(gui, controller.object, controller.property, { + before: _nextSibling, + factoryArgs: [_options] + }); + } + }, + name: function name(_name) { + controller.__li.firstElementChild.firstElementChild.innerHTML = _name; + return controller; + }, + listen: function listen() { + controller.__gui.listen(controller); + return controller; + }, + remove: function remove() { + controller.__gui.remove(controller); + return controller; + } + }); + if (controller instanceof NumberControllerSlider) { + var box = new NumberControllerBox(controller.object, controller.property, { min: controller.__min, max: controller.__max, step: controller.__step }); + Common.each(['updateDisplay', 'onChange', 'onFinishChange', 'step', 'min', 'max'], function (method) { + var pc = controller[method]; + var pb = box[method]; + controller[method] = box[method] = function () { + var args = Array.prototype.slice.call(arguments); + pb.apply(box, args); + return pc.apply(controller, args); + }; + }); + dom.addClass(li, 'has-slider'); + controller.domElement.insertBefore(box.domElement, controller.domElement.firstElementChild); + } else if (controller instanceof NumberControllerBox) { + var r = function r(returned) { + if (Common.isNumber(controller.__min) && Common.isNumber(controller.__max)) { + var oldName = controller.__li.firstElementChild.firstElementChild.innerHTML; + var wasListening = controller.__gui.__listening.indexOf(controller) > -1; + controller.remove(); + var newController = _add(gui, controller.object, controller.property, { + before: controller.__li.nextElementSibling, + factoryArgs: [controller.__min, controller.__max, controller.__step] + }); + newController.name(oldName); + if (wasListening) newController.listen(); + return newController; + } + return returned; + }; + controller.min = Common.compose(r, controller.min); + controller.max = Common.compose(r, controller.max); + } else if (controller instanceof BooleanController) { + dom.bind(li, 'click', function () { + dom.fakeEvent(controller.__checkbox, 'click'); + }); + dom.bind(controller.__checkbox, 'click', function (e) { + e.stopPropagation(); + }); + } else if (controller instanceof FunctionController) { + dom.bind(li, 'click', function () { + dom.fakeEvent(controller.__button, 'click'); + }); + dom.bind(li, 'mouseover', function () { + dom.addClass(controller.__button, 'hover'); + }); + dom.bind(li, 'mouseout', function () { + dom.removeClass(controller.__button, 'hover'); + }); + } else if (controller instanceof ColorController) { + dom.addClass(li, 'color'); + controller.updateDisplay = Common.compose(function (val) { + li.style.borderLeftColor = controller.__color.toString(); + return val; + }, controller.updateDisplay); + controller.updateDisplay(); + } + controller.setValue = Common.compose(function (val) { + if (gui.getRoot().__preset_select && controller.isModified()) { + markPresetModified(gui.getRoot(), true); + } + return val; + }, controller.setValue); +} +function recallSavedValue(gui, controller) { + var root = gui.getRoot(); + var matchedIndex = root.__rememberedObjects.indexOf(controller.object); + if (matchedIndex !== -1) { + var controllerMap = root.__rememberedObjectIndecesToControllers[matchedIndex]; + if (controllerMap === undefined) { + controllerMap = {}; + root.__rememberedObjectIndecesToControllers[matchedIndex] = controllerMap; + } + controllerMap[controller.property] = controller; + if (root.load && root.load.remembered) { + var presetMap = root.load.remembered; + var preset = void 0; + if (presetMap[gui.preset]) { + preset = presetMap[gui.preset]; + } else if (presetMap[DEFAULT_DEFAULT_PRESET_NAME]) { + preset = presetMap[DEFAULT_DEFAULT_PRESET_NAME]; + } else { + return; + } + if (preset[matchedIndex] && preset[matchedIndex][controller.property] !== undefined) { + var value = preset[matchedIndex][controller.property]; + controller.initialValue = value; + controller.setValue(value); + } + } + } +} +function _add(gui, object, property, params) { + if (object[property] === undefined) { + throw new Error('Object "' + object + '" has no property "' + property + '"'); + } + var controller = void 0; + if (params.color) { + controller = new ColorController(object, property); + } else { + var factoryArgs = [object, property].concat(params.factoryArgs); + controller = ControllerFactory.apply(gui, factoryArgs); + } + if (params.before instanceof Controller) { + params.before = params.before.__li; + } + recallSavedValue(gui, controller); + dom.addClass(controller.domElement, 'c'); + var name = document.createElement('span'); + dom.addClass(name, 'property-name'); + name.innerHTML = controller.property; + var container = document.createElement('div'); + container.appendChild(name); + container.appendChild(controller.domElement); + var li = addRow(gui, container, params.before); + dom.addClass(li, GUI.CLASS_CONTROLLER_ROW); + if (controller instanceof ColorController) { + dom.addClass(li, 'color'); + } else { + dom.addClass(li, _typeof(controller.getValue())); + } + augmentController(gui, li, controller); + gui.__controllers.push(controller); + return controller; +} +function getLocalStorageHash(gui, key) { + return document.location.href + '.' + key; +} +function addPresetOption(gui, name, setSelected) { + var opt = document.createElement('option'); + opt.innerHTML = name; + opt.value = name; + gui.__preset_select.appendChild(opt); + if (setSelected) { + gui.__preset_select.selectedIndex = gui.__preset_select.length - 1; + } +} +function showHideExplain(gui, explain) { + explain.style.display = gui.useLocalStorage ? 'block' : 'none'; +} +function addSaveMenu(gui) { + var div = gui.__save_row = document.createElement('li'); + dom.addClass(gui.domElement, 'has-save'); + gui.__ul.insertBefore(div, gui.__ul.firstChild); + dom.addClass(div, 'save-row'); + var gears = document.createElement('span'); + gears.innerHTML = ' '; + dom.addClass(gears, 'button gears'); + var button = document.createElement('span'); + button.innerHTML = 'Save'; + dom.addClass(button, 'button'); + dom.addClass(button, 'save'); + var button2 = document.createElement('span'); + button2.innerHTML = 'New'; + dom.addClass(button2, 'button'); + dom.addClass(button2, 'save-as'); + var button3 = document.createElement('span'); + button3.innerHTML = 'Revert'; + dom.addClass(button3, 'button'); + dom.addClass(button3, 'revert'); + var select = gui.__preset_select = document.createElement('select'); + if (gui.load && gui.load.remembered) { + Common.each(gui.load.remembered, function (value, key) { + addPresetOption(gui, key, key === gui.preset); + }); + } else { + addPresetOption(gui, DEFAULT_DEFAULT_PRESET_NAME, false); + } + dom.bind(select, 'change', function () { + for (var index = 0; index < gui.__preset_select.length; index++) { + gui.__preset_select[index].innerHTML = gui.__preset_select[index].value; + } + gui.preset = this.value; + }); + div.appendChild(select); + div.appendChild(gears); + div.appendChild(button); + div.appendChild(button2); + div.appendChild(button3); + if (SUPPORTS_LOCAL_STORAGE) { + var explain = document.getElementById('dg-local-explain'); + var localStorageCheckBox = document.getElementById('dg-local-storage'); + var saveLocally = document.getElementById('dg-save-locally'); + saveLocally.style.display = 'block'; + if (localStorage.getItem(getLocalStorageHash(gui, 'isLocal')) === 'true') { + localStorageCheckBox.setAttribute('checked', 'checked'); + } + showHideExplain(gui, explain); + dom.bind(localStorageCheckBox, 'change', function () { + gui.useLocalStorage = !gui.useLocalStorage; + showHideExplain(gui, explain); + }); + } + var newConstructorTextArea = document.getElementById('dg-new-constructor'); + dom.bind(newConstructorTextArea, 'keydown', function (e) { + if (e.metaKey && (e.which === 67 || e.keyCode === 67)) { + SAVE_DIALOGUE.hide(); + } + }); + dom.bind(gears, 'click', function () { + newConstructorTextArea.innerHTML = JSON.stringify(gui.getSaveObject(), undefined, 2); + SAVE_DIALOGUE.show(); + newConstructorTextArea.focus(); + newConstructorTextArea.select(); + }); + dom.bind(button, 'click', function () { + gui.save(); + }); + dom.bind(button2, 'click', function () { + var presetName = prompt('Enter a new preset name.'); + if (presetName) { + gui.saveAs(presetName); + } + }); + dom.bind(button3, 'click', function () { + gui.revert(); + }); +} +function addResizeHandle(gui) { + var pmouseX = void 0; + gui.__resize_handle = document.createElement('div'); + Common.extend(gui.__resize_handle.style, { + width: '6px', + marginLeft: '-3px', + height: '200px', + cursor: 'ew-resize', + position: 'absolute' + }); + function drag(e) { + e.preventDefault(); + gui.width += pmouseX - e.clientX; + gui.onResize(); + pmouseX = e.clientX; + return false; + } + function dragStop() { + dom.removeClass(gui.__closeButton, GUI.CLASS_DRAG); + dom.unbind(window, 'mousemove', drag); + dom.unbind(window, 'mouseup', dragStop); + } + function dragStart(e) { + e.preventDefault(); + pmouseX = e.clientX; + dom.addClass(gui.__closeButton, GUI.CLASS_DRAG); + dom.bind(window, 'mousemove', drag); + dom.bind(window, 'mouseup', dragStop); + return false; + } + dom.bind(gui.__resize_handle, 'mousedown', dragStart); + dom.bind(gui.__closeButton, 'mousedown', dragStart); + gui.domElement.insertBefore(gui.__resize_handle, gui.domElement.firstElementChild); +} +function setWidth(gui, w) { + gui.domElement.style.width = w + 'px'; + if (gui.__save_row && gui.autoPlace) { + gui.__save_row.style.width = w + 'px'; + } + if (gui.__closeButton) { + gui.__closeButton.style.width = w + 'px'; + } +} +function getCurrentPreset(gui, useInitialValues) { + var toReturn = {}; + Common.each(gui.__rememberedObjects, function (val, index) { + var savedValues = {}; + var controllerMap = gui.__rememberedObjectIndecesToControllers[index]; + Common.each(controllerMap, function (controller, property) { + savedValues[property] = useInitialValues ? controller.initialValue : controller.getValue(); + }); + toReturn[index] = savedValues; + }); + return toReturn; +} +function setPresetSelectIndex(gui) { + for (var index = 0; index < gui.__preset_select.length; index++) { + if (gui.__preset_select[index].value === gui.preset) { + gui.__preset_select.selectedIndex = index; + } + } +} +function updateDisplays(controllerArray) { + if (controllerArray.length !== 0) { + requestAnimationFrame$1.call(window, function () { + updateDisplays(controllerArray); + }); + } + Common.each(controllerArray, function (c) { + c.updateDisplay(); + }); +} + +var color = { + Color: Color, + math: ColorMath, + interpret: interpret +}; +var controllers = { + Controller: Controller, + BooleanController: BooleanController, + OptionController: OptionController, + StringController: StringController, + NumberController: NumberController, + NumberControllerBox: NumberControllerBox, + NumberControllerSlider: NumberControllerSlider, + FunctionController: FunctionController, + ColorController: ColorController +}; +var dom$1 = { dom: dom }; +var gui = { GUI: GUI }; +var GUI$1 = GUI; +var index = { + color: color, + controllers: controllers, + dom: dom$1, + gui: gui, + GUI: GUI$1 +}; + + +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (index); +//# sourceMappingURL=dat.gui.module.js.map + + +/***/ }), + +/***/ "../../node_modules/park-miller/index.js": +/*!***********************************************!*\ + !*** ../../node_modules/park-miller/index.js ***! + \***********************************************/ +/***/ ((module) => { + + +const MAX_INT32 = 2147483647; +const MINSTD = 16807; + +class ParkMiller { + constructor(seed) { + if (!Number.isInteger(seed)) { + throw new TypeError('Expected `seed` to be a `integer`'); + } + + this._seed = seed % MAX_INT32; + + if (this._seed <= 0) { + this._seed += (MAX_INT32 - 1); + } + } + + integer() { + this._seed *= MINSTD; + this._seed %= MAX_INT32; + return this._seed; + } + + integerInRange(min, max) { + return Math.round(this.floatInRange(min, max)); + } + + float() { + return (this.integer() - 1) / (MAX_INT32 - 1); + } + + floatInRange(min, max) { + return min + ((max - min) * this.float()); + } + + boolean() { + return this.integer() % 2 === 0; + } +} + +module.exports = ParkMiller; + + +/***/ }), + +/***/ "./canvas.ts": +/*!*******************!*\ + !*** ./canvas.ts ***! + \*******************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createCanvas: () => (/* binding */ createCanvas), +/* harmony export */ drawOptions: () => (/* binding */ drawOptions) +/* harmony export */ }); +/* harmony import */ var _snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/draw/drawWorld */ "../draw/drawWorld.ts"); + +const drawOptions = { + sizeDotBorderRadius: 2, + sizeCell: 16, + sizeDot: 12, + colorDotBorder: "#1b1f230a", + colorDots: { + 1: "#9be9a8", + 2: "#40c463", + 3: "#30a14e", + 4: "#216e39", + }, + colorEmpty: "#ebedf0", + colorSnake: "purple", + dark: { + colorEmpty: "#161b22", + colorDots: { 1: "#01311f", 2: "#034525", 3: "#0f6d31", 4: "#00c647" }, + }, +}; +const getPointedCell = (canvas) => ({ pageX, pageY }) => { + const { left, top } = canvas.getBoundingClientRect(); + const x = Math.floor((pageX - left) / drawOptions.sizeCell) - 1; + const y = Math.floor((pageY - top) / drawOptions.sizeCell) - 2; + return { x, y }; +}; +const createCanvas = ({ width, height, }) => { + const canvas = document.createElement("canvas"); + const upscale = 2; + const w = drawOptions.sizeCell * (width + 4); + const h = drawOptions.sizeCell * (height + 4) + 200; + canvas.width = w * upscale; + canvas.height = h * upscale; + canvas.style.width = w + "px"; + canvas.style.height = h + "px"; + canvas.style.display = "block"; + // canvas.style.pointerEvents = "none"; + const cellInfo = document.createElement("div"); + cellInfo.style.height = "20px"; + document.body.appendChild(cellInfo); + document.body.appendChild(canvas); + canvas.addEventListener("mousemove", (e) => { + const { x, y } = getPointedCell(canvas)(e); + cellInfo.innerText = [x, y] + .map((u) => u.toString().padStart(2, " ")) + .join(" / "); + }); + const ctx = canvas.getContext("2d"); + ctx.scale(upscale, upscale); + const draw = (grid, snake, stack) => { + ctx.clearRect(0, 0, 9999, 9999); + (0,_snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__.drawWorld)(ctx, grid, null, snake, stack, drawOptions); + }; + const drawLerp = (grid, snake0, snake1, stack, k) => { + ctx.clearRect(0, 0, 9999, 9999); + (0,_snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__.drawLerpWorld)(ctx, grid, null, snake0, snake1, stack, k, drawOptions); + }; + const highlightCell = (x, y, color = "orange") => { + ctx.fillStyle = color; + ctx.beginPath(); + ctx.fillRect((1 + x + 0.5) * 16 - 2, (2 + y + 0.5) * 16 - 2, 4, 4); + }; + return { + draw, + drawLerp, + highlightCell, + canvas, + getPointedCell: getPointedCell(canvas), + ctx, + }; +}; + + +/***/ }), + +/***/ "./menu.ts": +/*!*****************!*\ + !*** ./menu.ts ***! + \*****************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ gui: () => (/* binding */ gui) +/* harmony export */ }); +/* harmony import */ var dat_gui__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! dat.gui */ "../../node_modules/dat.gui/build/dat.gui.module.js"); +/* harmony import */ var _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/__fixtures__/grid */ "../types/__fixtures__/grid.ts"); +/* harmony import */ var _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/__fixtures__/snake */ "../types/__fixtures__/snake.ts"); +/* harmony import */ var _sample__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sample */ "./sample.ts"); + + + + +const demos = __webpack_require__(/*! ./demo.json */ "./demo.json"); +const gui = new dat_gui__WEBPACK_IMPORTED_MODULE_0__.GUI(); +const config = { + snake: Object.entries(_snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__).find(([_, s]) => s === _sample__WEBPACK_IMPORTED_MODULE_3__.snake)[0], + grid: Object.entries(_snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__).find(([_, s]) => s === _sample__WEBPACK_IMPORTED_MODULE_3__.grid)[0], + demo: demos[0], +}; +{ + const d = window.location.pathname.match(/(\w+)\.html/); + if (d && demos.includes(d[1])) + config.demo = d[1]; +} +const onChange = () => { + const search = new URLSearchParams({ + snake: config.snake, + grid: config.grid, + }).toString(); + const url = new URL(config.demo + ".html?" + search, window.location.href).toString(); + window.location.href = url; +}; +gui.add(config, "demo", demos).onChange(onChange); +gui.add(config, "grid", Object.keys(_snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__)).onChange(onChange); +gui.add(config, "snake", Object.keys(_snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__)).onChange(onChange); + + +/***/ }), + +/***/ "./sample.ts": +/*!*******************!*\ + !*** ./sample.ts ***! + \*******************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ grid: () => (/* binding */ grid), +/* harmony export */ snake: () => (/* binding */ snake) +/* harmony export */ }); +/* harmony import */ var _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/__fixtures__/grid */ "../types/__fixtures__/grid.ts"); +/* harmony import */ var _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/__fixtures__/snake */ "../types/__fixtures__/snake.ts"); + + +const sp = new URLSearchParams(window.location.search); +const gLabel = sp.get("grid") || "simple"; +const sLabel = sp.get("snake") || "snake3"; +//@ts-ignore +const grid = _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__[gLabel] || _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__.simple; +//@ts-ignore +const snake = _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__[sLabel] || _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__.snake3; + + +/***/ }), + +/***/ "../draw/drawGrid.ts": +/*!***************************!*\ + !*** ../draw/drawGrid.ts ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawGrid: () => (/* binding */ drawGrid) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _pathRoundedRect__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./pathRoundedRect */ "../draw/pathRoundedRect.ts"); + + +const drawGrid = (ctx, grid, cells, o) => { + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + if (!cells || cells.some((c) => c.x === x && c.y === y)) { + const c = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + // @ts-ignore + const color = !c ? o.colorEmpty : o.colorDots[c]; + ctx.save(); + ctx.translate(x * o.sizeCell + (o.sizeCell - o.sizeDot) / 2, y * o.sizeCell + (o.sizeCell - o.sizeDot) / 2); + ctx.fillStyle = color; + ctx.strokeStyle = o.colorDotBorder; + ctx.lineWidth = 1; + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_1__.pathRoundedRect)(ctx, o.sizeDot, o.sizeDot, o.sizeDotBorderRadius); + ctx.fill(); + ctx.stroke(); + ctx.closePath(); + ctx.restore(); + } + } +}; + + +/***/ }), + +/***/ "../draw/drawSnake.ts": +/*!****************************!*\ + !*** ../draw/drawSnake.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawSnake: () => (/* binding */ drawSnake), +/* harmony export */ drawSnakeLerp: () => (/* binding */ drawSnakeLerp) +/* harmony export */ }); +/* harmony import */ var _pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./pathRoundedRect */ "../draw/pathRoundedRect.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); + + +const drawSnake = (ctx, snake, o) => { + const cells = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.snakeToCells)(snake); + for (let i = 0; i < cells.length; i++) { + const u = (i + 1) * 0.6; + ctx.save(); + ctx.fillStyle = o.colorSnake; + ctx.translate(cells[i].x * o.sizeCell + u, cells[i].y * o.sizeCell + u); + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__.pathRoundedRect)(ctx, o.sizeCell - u * 2, o.sizeCell - u * 2, (o.sizeCell - u * 2) * 0.25); + ctx.fill(); + ctx.restore(); + } +}; +const lerp = (k, a, b) => (1 - k) * a + k * b; +const clamp = (x, a, b) => Math.max(a, Math.min(b, x)); +const drawSnakeLerp = (ctx, snake0, snake1, k, o) => { + const m = 0.8; + const n = snake0.length / 2; + for (let i = 0; i < n; i++) { + const u = (i + 1) * 0.6 * (o.sizeCell / 16); + const a = (1 - m) * (i / Math.max(n - 1, 1)); + const ki = clamp((k - a) / m, 0, 1); + const x = lerp(ki, snake0[i * 2 + 0], snake1[i * 2 + 0]) - 2; + const y = lerp(ki, snake0[i * 2 + 1], snake1[i * 2 + 1]) - 2; + ctx.save(); + ctx.fillStyle = o.colorSnake; + ctx.translate(x * o.sizeCell + u, y * o.sizeCell + u); + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__.pathRoundedRect)(ctx, o.sizeCell - u * 2, o.sizeCell - u * 2, (o.sizeCell - u * 2) * 0.25); + ctx.fill(); + ctx.restore(); + } +}; + + +/***/ }), + +/***/ "../draw/drawWorld.ts": +/*!****************************!*\ + !*** ../draw/drawWorld.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawLerpWorld: () => (/* binding */ drawLerpWorld), +/* harmony export */ drawStack: () => (/* binding */ drawStack), +/* harmony export */ drawWorld: () => (/* binding */ drawWorld), +/* harmony export */ getCanvasWorldSize: () => (/* binding */ getCanvasWorldSize) +/* harmony export */ }); +/* harmony import */ var _drawGrid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./drawGrid */ "../draw/drawGrid.ts"); +/* harmony import */ var _drawSnake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./drawSnake */ "../draw/drawSnake.ts"); + + +const drawStack = (ctx, stack, max, width, o) => { + ctx.save(); + const m = width / max; + for (let i = 0; i < stack.length; i++) { + // @ts-ignore + ctx.fillStyle = o.colorDots[stack[i]]; + ctx.fillRect(i * m, 0, m + width * 0.005, 10); + } + ctx.restore(); +}; +const drawWorld = (ctx, grid, cells, snake, stack, o) => { + ctx.save(); + ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); + (0,_drawGrid__WEBPACK_IMPORTED_MODULE_0__.drawGrid)(ctx, grid, cells, o); + (0,_drawSnake__WEBPACK_IMPORTED_MODULE_1__.drawSnake)(ctx, snake, o); + ctx.restore(); + ctx.save(); + ctx.translate(o.sizeCell, (grid.height + 4) * o.sizeCell); + const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length); + drawStack(ctx, stack, max, grid.width * o.sizeCell, o); + ctx.restore(); + // ctx.save(); + // ctx.translate(o.sizeCell + 100, (grid.height + 4) * o.sizeCell + 100); + // ctx.scale(0.6, 0.6); + // drawCircleStack(ctx, stack, o); + // ctx.restore(); +}; +const drawLerpWorld = (ctx, grid, cells, snake0, snake1, stack, k, o) => { + ctx.save(); + ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); + (0,_drawGrid__WEBPACK_IMPORTED_MODULE_0__.drawGrid)(ctx, grid, cells, o); + (0,_drawSnake__WEBPACK_IMPORTED_MODULE_1__.drawSnakeLerp)(ctx, snake0, snake1, k, o); + ctx.translate(0, (grid.height + 2) * o.sizeCell); + const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length); + drawStack(ctx, stack, max, grid.width * o.sizeCell, o); + ctx.restore(); +}; +const getCanvasWorldSize = (grid, o) => { + const width = o.sizeCell * (grid.width + 2); + const height = o.sizeCell * (grid.height + 4) + 30; + return { width, height }; +}; + + +/***/ }), + +/***/ "../draw/pathRoundedRect.ts": +/*!**********************************!*\ + !*** ../draw/pathRoundedRect.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ pathRoundedRect: () => (/* binding */ pathRoundedRect) +/* harmony export */ }); +const pathRoundedRect = (ctx, width, height, borderRadius) => { + ctx.moveTo(borderRadius, 0); + ctx.arcTo(width, 0, width, height, borderRadius); + ctx.arcTo(width, height, 0, height, borderRadius); + ctx.arcTo(0, height, 0, 0, borderRadius); + ctx.arcTo(0, 0, width, 0, borderRadius); +}; + + +/***/ }), + +/***/ "../solver/getPathToPose.ts": +/*!**********************************!*\ + !*** ../solver/getPathToPose.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getPathToPose: () => (/* binding */ getPathToPose) +/* harmony export */ }); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _tunnel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./tunnel */ "../solver/tunnel.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); +/* harmony import */ var _utils_sortPush__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./utils/sortPush */ "../solver/utils/sortPush.ts"); + + + + + +const isEmptySafe = (grid, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_1__.isInside)(grid, x, y) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_1__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_1__.getColor)(grid, x, y)); +const getPathToPose = (snake0, target, grid) => { + if ((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.snakeEquals)(snake0, target)) + return []; + const targetCells = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.snakeToCells)(target).reverse(); + const snakeN = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getSnakeLength)(snake0); + const box = { + min: { + x: Math.min((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(snake0), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(target)) - snakeN - 1, + y: Math.min((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(snake0), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(target)) - snakeN - 1, + }, + max: { + x: Math.max((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(snake0), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(target)) + snakeN + 1, + y: Math.max((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(snake0), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(target)) + snakeN + 1, + }, + }; + const [t0, ...forbidden] = targetCells; + forbidden.slice(0, 3); + const openList = [{ snake: snake0, w: 0 }]; + const closeList = []; + while (openList.length) { + const o = openList.shift(); + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(o.snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(o.snake); + if (x === t0.x && y === t0.y) { + const path = []; + let e = o; + while (e) { + path.push(e.snake); + e = e.parent; + } + path.unshift(...(0,_tunnel__WEBPACK_IMPORTED_MODULE_2__.getTunnelPath)(path[0], targetCells)); + path.pop(); + path.reverse(); + return path; + } + for (let i = 0; i < _snk_types_point__WEBPACK_IMPORTED_MODULE_3__.around4.length; i++) { + const { x: dx, y: dy } = _snk_types_point__WEBPACK_IMPORTED_MODULE_3__.around4[i]; + const nx = x + dx; + const ny = y + dy; + if (!(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.snakeWillSelfCollide)(o.snake, dx, dy) && + (!grid || isEmptySafe(grid, nx, ny)) && + (grid + ? (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_1__.isInsideLarge)(grid, 2, nx, ny) + : box.min.x <= nx && + nx <= box.max.x && + box.min.y <= ny && + ny <= box.max.y) && + !forbidden.some((p) => p.x === nx && p.y === ny)) { + const snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.nextSnake)(o.snake, dx, dy); + if (!closeList.some((s) => (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.snakeEquals)(snake, s))) { + const w = o.w + 1; + const h = Math.abs(nx - x) + Math.abs(ny - y); + const f = w + h; + (0,_utils_sortPush__WEBPACK_IMPORTED_MODULE_4__.sortPush)(openList, { f, w, snake, parent: o }, (a, b) => a.f - b.f); + closeList.push(snake); + } + } + } + } +}; + + +/***/ }), + +/***/ "../solver/tunnel.ts": +/*!***************************!*\ + !*** ../solver/tunnel.ts ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getTunnelPath: () => (/* binding */ getTunnelPath), +/* harmony export */ trimTunnelEnd: () => (/* binding */ trimTunnelEnd), +/* harmony export */ trimTunnelStart: () => (/* binding */ trimTunnelStart), +/* harmony export */ updateTunnel: () => (/* binding */ updateTunnel) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); + + +/** + * get the sequence of snake to cross the tunnel + */ +const getTunnelPath = (snake0, tunnel) => { + const chain = []; + let snake = snake0; + for (let i = 1; i < tunnel.length; i++) { + const dx = tunnel[i].x - (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake); + const dy = tunnel[i].y - (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake); + snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.nextSnake)(snake, dx, dy); + chain.unshift(snake); + } + return chain; +}; +/** + * assuming the grid change and the colors got deleted, update the tunnel + */ +const updateTunnel = (grid, tunnel, toDelete) => { + while (tunnel.length) { + const { x, y } = tunnel[0]; + if (isEmptySafe(grid, x, y) || + toDelete.some((p) => p.x === x && p.y === y)) { + tunnel.shift(); + } + else + break; + } + while (tunnel.length) { + const { x, y } = tunnel[tunnel.length - 1]; + if (isEmptySafe(grid, x, y) || + toDelete.some((p) => p.x === x && p.y === y)) { + tunnel.pop(); + } + else + break; + } +}; +const isEmptySafe = (grid, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y)); +/** + * remove empty cell from start + */ +const trimTunnelStart = (grid, tunnel) => { + while (tunnel.length) { + const { x, y } = tunnel[0]; + if (isEmptySafe(grid, x, y)) + tunnel.shift(); + else + break; + } +}; +/** + * remove empty cell from end + */ +const trimTunnelEnd = (grid, tunnel) => { + while (tunnel.length) { + const i = tunnel.length - 1; + const { x, y } = tunnel[i]; + if (isEmptySafe(grid, x, y) || + tunnel.findIndex((p) => p.x === x && p.y === y) < i) + tunnel.pop(); + else + break; + } +}; + + +/***/ }), + +/***/ "../solver/utils/sortPush.ts": +/*!***********************************!*\ + !*** ../solver/utils/sortPush.ts ***! + \***********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ sortPush: () => (/* binding */ sortPush) +/* harmony export */ }); +const sortPush = (arr, x, sortFn) => { + let a = 0; + let b = arr.length; + if (arr.length === 0 || sortFn(x, arr[a]) <= 0) { + arr.unshift(x); + return; + } + while (b - a > 1) { + const e = Math.ceil((a + b) / 2); + const s = sortFn(x, arr[e]); + if (s === 0) + a = b = e; + else if (s > 0) + a = e; + else + b = e; + } + const e = Math.ceil((a + b) / 2); + arr.splice(e, 0, x); +}; + + +/***/ }), + +/***/ "../types/__fixtures__/createFromAscii.ts": +/*!************************************************!*\ + !*** ../types/__fixtures__/createFromAscii.ts ***! + \************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createFromAscii: () => (/* binding */ createFromAscii) +/* harmony export */ }); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../grid */ "../types/grid.ts"); + +const createFromAscii = (ascii) => { + const a = ascii.split("\n"); + if (a[0] === "") + a.shift(); + const height = a.length; + const width = Math.max(...a.map((r) => r.length)); + const grid = (0,_grid__WEBPACK_IMPORTED_MODULE_0__.createEmptyGrid)(width, height); + for (let x = width; x--;) + for (let y = height; y--;) { + const c = a[y][x]; + const color = (c === "#" && 3) || (c === "@" && 2) || (c === "." && 1) || +c; + if (c) + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(grid, x, y, color); + } + return grid; +}; + + +/***/ }), + +/***/ "../types/__fixtures__/grid.ts": +/*!*************************************!*\ + !*** ../types/__fixtures__/grid.ts ***! + \*************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ closedO: () => (/* binding */ closedO), +/* harmony export */ closedP: () => (/* binding */ closedP), +/* harmony export */ closedU: () => (/* binding */ closedU), +/* harmony export */ corner: () => (/* binding */ corner), +/* harmony export */ empty: () => (/* binding */ empty), +/* harmony export */ enclaveBorder: () => (/* binding */ enclaveBorder), +/* harmony export */ enclaveK: () => (/* binding */ enclaveK), +/* harmony export */ enclaveM: () => (/* binding */ enclaveM), +/* harmony export */ enclaveN: () => (/* binding */ enclaveN), +/* harmony export */ enclaveU: () => (/* binding */ enclaveU), +/* harmony export */ realistic: () => (/* binding */ realistic), +/* harmony export */ realisticFull: () => (/* binding */ realisticFull), +/* harmony export */ simple: () => (/* binding */ simple), +/* harmony export */ small: () => (/* binding */ small), +/* harmony export */ smallFull: () => (/* binding */ smallFull), +/* harmony export */ smallPacked: () => (/* binding */ smallPacked), +/* harmony export */ tunnels: () => (/* binding */ tunnels) +/* harmony export */ }); +/* harmony import */ var park_miller__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! park-miller */ "../../node_modules/park-miller/index.js"); +/* harmony import */ var park_miller__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(park_miller__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../grid */ "../types/grid.ts"); +/* harmony import */ var _randomlyFillGrid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../randomlyFillGrid */ "../types/randomlyFillGrid.ts"); +/* harmony import */ var _createFromAscii__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./createFromAscii */ "../types/__fixtures__/createFromAscii.ts"); + + + + +const colors = [1, 2, 3]; +// empty small grid +const empty = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +// empty small grid with a unique color at the middle +const simple = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(simple, 2, 2, 1); +// empty small grid with color at each corner +const corner = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 0, 4, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 4, 0, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 4, 4, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 0, 0, 1); +const enclaveN = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #.# + # + +`); +const enclaveBorder = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + #.# + # + +`); +const enclaveM = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### + # # + # . # + # # + # # +`); +const enclaveK = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + # .# + # # + # # + # # +`); +const enclaveU = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + #..# + #..# + #.# + # # . +`); +const closedP = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### + ##.# + ## # + ## +`); +const closedU = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + #..# + #..# + #.# + ### +`); +const closedO = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ####### + # # + # . # + # # + ####### +`); +const tunnels = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### ### ### + #.# #.# #.# + #.# ### # # +`); +const createRandom = (width, height, emptyP) => { + const grid = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(width, height); + const pm = new (park_miller__WEBPACK_IMPORTED_MODULE_0___default())(10); + const random = pm.integerInRange.bind(pm); + (0,_randomlyFillGrid__WEBPACK_IMPORTED_MODULE_2__.randomlyFillGrid)(grid, { colors, emptyP }, random); + return grid; +}; +// small realistic +const small = createRandom(10, 7, 3); +const smallPacked = createRandom(10, 7, 1); +const smallFull = createRandom(10, 7, 0); +// small realistic +const realistic = createRandom(52, 7, 3); +const realisticFull = createRandom(52, 7, 0); + + +/***/ }), + +/***/ "../types/__fixtures__/snake.ts": +/*!**************************************!*\ + !*** ../types/__fixtures__/snake.ts ***! + \**************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ snake1: () => (/* binding */ snake1), +/* harmony export */ snake3: () => (/* binding */ snake3), +/* harmony export */ snake4: () => (/* binding */ snake4), +/* harmony export */ snake5: () => (/* binding */ snake5), +/* harmony export */ snake9: () => (/* binding */ snake9) +/* harmony export */ }); +/* harmony import */ var _snake__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../snake */ "../types/snake.ts"); + +const create = (length) => (0,_snake__WEBPACK_IMPORTED_MODULE_0__.createSnakeFromCells)(Array.from({ length }, (_, i) => ({ x: i, y: -1 }))); +const snake1 = create(1); +const snake3 = create(3); +const snake4 = create(4); +const snake5 = create(5); +const snake9 = create(9); + + +/***/ }), + +/***/ "../types/grid.ts": +/*!************************!*\ + !*** ../types/grid.ts ***! + \************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copyGrid: () => (/* binding */ copyGrid), +/* harmony export */ createEmptyGrid: () => (/* binding */ createEmptyGrid), +/* harmony export */ getColor: () => (/* binding */ getColor), +/* harmony export */ gridEquals: () => (/* binding */ gridEquals), +/* harmony export */ isEmpty: () => (/* binding */ isEmpty), +/* harmony export */ isGridEmpty: () => (/* binding */ isGridEmpty), +/* harmony export */ isInside: () => (/* binding */ isInside), +/* harmony export */ isInsideLarge: () => (/* binding */ isInsideLarge), +/* harmony export */ setColor: () => (/* binding */ setColor), +/* harmony export */ setColorEmpty: () => (/* binding */ setColorEmpty) +/* harmony export */ }); +const isInside = (grid, x, y) => x >= 0 && y >= 0 && x < grid.width && y < grid.height; +const isInsideLarge = (grid, m, x, y) => x >= -m && y >= -m && x < grid.width + m && y < grid.height + m; +const copyGrid = ({ width, height, data }) => ({ + width, + height, + data: Uint8Array.from(data), +}); +const getIndex = (grid, x, y) => x * grid.height + y; +const getColor = (grid, x, y) => grid.data[getIndex(grid, x, y)]; +const isEmpty = (color) => color === 0; +const setColor = (grid, x, y, color) => { + grid.data[getIndex(grid, x, y)] = color || 0; +}; +const setColorEmpty = (grid, x, y) => { + setColor(grid, x, y, 0); +}; +/** + * return true if the grid is empty + */ +const isGridEmpty = (grid) => grid.data.every((x) => x === 0); +const gridEquals = (a, b) => a.data.every((_, i) => a.data[i] === b.data[i]); +const createEmptyGrid = (width, height) => ({ + width, + height, + data: new Uint8Array(width * height), +}); + + +/***/ }), + +/***/ "../types/point.ts": +/*!*************************!*\ + !*** ../types/point.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ around4: () => (/* binding */ around4), +/* harmony export */ pointEquals: () => (/* binding */ pointEquals) +/* harmony export */ }); +const around4 = [ + { x: 1, y: 0 }, + { x: 0, y: -1 }, + { x: -1, y: 0 }, + { x: 0, y: 1 }, +]; +const pointEquals = (a, b) => a.x === b.x && a.y === b.y; + + +/***/ }), + +/***/ "../types/randomlyFillGrid.ts": +/*!************************************!*\ + !*** ../types/randomlyFillGrid.ts ***! + \************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ randomlyFillGrid: () => (/* binding */ randomlyFillGrid) +/* harmony export */ }); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./grid */ "../types/grid.ts"); + +const defaultRand = (a, b) => Math.floor(Math.random() * (b - a + 1)) + a; +const randomlyFillGrid = (grid, { colors = [1, 2, 3], emptyP = 2, } = {}, rand = defaultRand) => { + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + const k = rand(-emptyP, colors.length - 1); + if (k >= 0) + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(grid, x, y, colors[k]); + else + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); + } +}; + + +/***/ }), + +/***/ "../types/snake.ts": +/*!*************************!*\ + !*** ../types/snake.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copySnake: () => (/* binding */ copySnake), +/* harmony export */ createSnakeFromCells: () => (/* binding */ createSnakeFromCells), +/* harmony export */ getHeadX: () => (/* binding */ getHeadX), +/* harmony export */ getHeadY: () => (/* binding */ getHeadY), +/* harmony export */ getSnakeLength: () => (/* binding */ getSnakeLength), +/* harmony export */ nextSnake: () => (/* binding */ nextSnake), +/* harmony export */ snakeEquals: () => (/* binding */ snakeEquals), +/* harmony export */ snakeToCells: () => (/* binding */ snakeToCells), +/* harmony export */ snakeWillSelfCollide: () => (/* binding */ snakeWillSelfCollide) +/* harmony export */ }); +const getHeadX = (snake) => snake[0] - 2; +const getHeadY = (snake) => snake[1] - 2; +const getSnakeLength = (snake) => snake.length / 2; +const copySnake = (snake) => snake.slice(); +const snakeEquals = (a, b) => { + for (let i = 0; i < a.length; i++) + if (a[i] !== b[i]) + return false; + return true; +}; +/** + * return a copy of the next snake, considering that dx, dy is the direction + */ +const nextSnake = (snake, dx, dy) => { + const copy = new Uint8Array(snake.length); + for (let i = 2; i < snake.length; i++) + copy[i] = snake[i - 2]; + copy[0] = snake[0] + dx; + copy[1] = snake[1] + dy; + return copy; +}; +/** + * return true if the next snake will collide with itself + */ +const snakeWillSelfCollide = (snake, dx, dy) => { + const nx = snake[0] + dx; + const ny = snake[1] + dy; + for (let i = 2; i < snake.length - 2; i += 2) + if (snake[i + 0] === nx && snake[i + 1] === ny) + return true; + return false; +}; +const snakeToCells = (snake) => Array.from({ length: snake.length / 2 }, (_, i) => ({ + x: snake[i * 2 + 0] - 2, + y: snake[i * 2 + 1] - 2, +})); +const createSnakeFromCells = (points) => { + const snake = new Uint8Array(points.length * 2); + for (let i = points.length; i--;) { + snake[i * 2 + 0] = points[i].x + 2; + snake[i * 2 + 1] = points[i].y + 2; + } + return snake; +}; + + +/***/ }), + +/***/ "./demo.json": +/*!*******************!*\ + !*** ./demo.json ***! + \*******************/ +/***/ ((module) => { + +module.exports = JSON.parse('["interactive","getBestRoute","getBestTunnel","outside","getPathToPose","getPathTo","svg"]'); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ (() => { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = (module) => { +/******/ var getter = module && module.__esModule ? +/******/ () => (module['default']) : +/******/ () => (module); +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +/*!*******************************!*\ + !*** ./demo.getPathToPose.ts ***! + \*******************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _menu__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./menu */ "./menu.ts"); +/* harmony import */ var _canvas__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./canvas */ "./canvas.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _sample__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sample */ "./sample.ts"); +/* harmony import */ var _snk_solver_getPathToPose__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @snk/solver/getPathToPose */ "../solver/getPathToPose.ts"); + + + + + +const { canvas, ctx, draw, highlightCell } = (0,_canvas__WEBPACK_IMPORTED_MODULE_1__.createCanvas)(_sample__WEBPACK_IMPORTED_MODULE_3__.grid); +canvas.style.pointerEvents = "auto"; +const target = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.createSnakeFromCells)((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.snakeToCells)(_sample__WEBPACK_IMPORTED_MODULE_3__.snake).map((p) => ({ ...p, x: p.x - 1 }))); +let chain = [_sample__WEBPACK_IMPORTED_MODULE_3__.snake, ...(0,_snk_solver_getPathToPose__WEBPACK_IMPORTED_MODULE_4__.getPathToPose)(_sample__WEBPACK_IMPORTED_MODULE_3__.snake, target)]; +let i = 0; +const onChange = () => { + ctx.clearRect(0, 0, 9999, 9999); + draw(_sample__WEBPACK_IMPORTED_MODULE_3__.grid, chain[i], []); + chain + .map(_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.snakeToCells) + .flat() + .forEach(({ x, y }) => highlightCell(x, y)); +}; +onChange(); +const inputI = document.createElement("input"); +inputI.type = "range"; +inputI.value = 0; +inputI.max = chain ? chain.length - 1 : 0; +inputI.step = 1; +inputI.min = 0; +inputI.style.width = "90%"; +inputI.style.padding = "20px 0"; +inputI.addEventListener("input", () => { + i = +inputI.value; + onChange(); +}); +document.body.append(inputI); + +})(); + +/******/ })() +; \ No newline at end of file diff --git a/24fd40492b60de555876.js b/24fd40492b60de555876.js new file mode 100644 index 000000000..4f3ac4bf1 --- /dev/null +++ b/24fd40492b60de555876.js @@ -0,0 +1,3692 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "../../node_modules/dat.gui/build/dat.gui.module.js": +/*!**********************************************************!*\ + !*** ../../node_modules/dat.gui/build/dat.gui.module.js ***! + \**********************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ GUI: () => (/* binding */ GUI$1), +/* harmony export */ color: () => (/* binding */ color), +/* harmony export */ controllers: () => (/* binding */ controllers), +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), +/* harmony export */ dom: () => (/* binding */ dom$1), +/* harmony export */ gui: () => (/* binding */ gui) +/* harmony export */ }); +/** + * dat-gui JavaScript Controller Library + * https://github.com/dataarts/dat.gui + * + * Copyright 2011 Data Arts Team, Google Creative Lab + * + * 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 + */ + +function ___$insertStyle(css) { + if (!css) { + return; + } + if (typeof window === 'undefined') { + return; + } + + var style = document.createElement('style'); + + style.setAttribute('type', 'text/css'); + style.innerHTML = css; + document.head.appendChild(style); + + return css; +} + +function colorToString (color, forceCSSHex) { + var colorFormat = color.__state.conversionName.toString(); + var r = Math.round(color.r); + var g = Math.round(color.g); + var b = Math.round(color.b); + var a = color.a; + var h = Math.round(color.h); + var s = color.s.toFixed(1); + var v = color.v.toFixed(1); + if (forceCSSHex || colorFormat === 'THREE_CHAR_HEX' || colorFormat === 'SIX_CHAR_HEX') { + var str = color.hex.toString(16); + while (str.length < 6) { + str = '0' + str; + } + return '#' + str; + } else if (colorFormat === 'CSS_RGB') { + return 'rgb(' + r + ',' + g + ',' + b + ')'; + } else if (colorFormat === 'CSS_RGBA') { + return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; + } else if (colorFormat === 'HEX') { + return '0x' + color.hex.toString(16); + } else if (colorFormat === 'RGB_ARRAY') { + return '[' + r + ',' + g + ',' + b + ']'; + } else if (colorFormat === 'RGBA_ARRAY') { + return '[' + r + ',' + g + ',' + b + ',' + a + ']'; + } else if (colorFormat === 'RGB_OBJ') { + return '{r:' + r + ',g:' + g + ',b:' + b + '}'; + } else if (colorFormat === 'RGBA_OBJ') { + return '{r:' + r + ',g:' + g + ',b:' + b + ',a:' + a + '}'; + } else if (colorFormat === 'HSV_OBJ') { + return '{h:' + h + ',s:' + s + ',v:' + v + '}'; + } else if (colorFormat === 'HSVA_OBJ') { + return '{h:' + h + ',s:' + s + ',v:' + v + ',a:' + a + '}'; + } + return 'unknown format'; +} + +var ARR_EACH = Array.prototype.forEach; +var ARR_SLICE = Array.prototype.slice; +var Common = { + BREAK: {}, + extend: function extend(target) { + this.each(ARR_SLICE.call(arguments, 1), function (obj) { + var keys = this.isObject(obj) ? Object.keys(obj) : []; + keys.forEach(function (key) { + if (!this.isUndefined(obj[key])) { + target[key] = obj[key]; + } + }.bind(this)); + }, this); + return target; + }, + defaults: function defaults(target) { + this.each(ARR_SLICE.call(arguments, 1), function (obj) { + var keys = this.isObject(obj) ? Object.keys(obj) : []; + keys.forEach(function (key) { + if (this.isUndefined(target[key])) { + target[key] = obj[key]; + } + }.bind(this)); + }, this); + return target; + }, + compose: function compose() { + var toCall = ARR_SLICE.call(arguments); + return function () { + var args = ARR_SLICE.call(arguments); + for (var i = toCall.length - 1; i >= 0; i--) { + args = [toCall[i].apply(this, args)]; + } + return args[0]; + }; + }, + each: function each(obj, itr, scope) { + if (!obj) { + return; + } + if (ARR_EACH && obj.forEach && obj.forEach === ARR_EACH) { + obj.forEach(itr, scope); + } else if (obj.length === obj.length + 0) { + var key = void 0; + var l = void 0; + for (key = 0, l = obj.length; key < l; key++) { + if (key in obj && itr.call(scope, obj[key], key) === this.BREAK) { + return; + } + } + } else { + for (var _key in obj) { + if (itr.call(scope, obj[_key], _key) === this.BREAK) { + return; + } + } + } + }, + defer: function defer(fnc) { + setTimeout(fnc, 0); + }, + debounce: function debounce(func, threshold, callImmediately) { + var timeout = void 0; + return function () { + var obj = this; + var args = arguments; + function delayed() { + timeout = null; + if (!callImmediately) func.apply(obj, args); + } + var callNow = callImmediately || !timeout; + clearTimeout(timeout); + timeout = setTimeout(delayed, threshold); + if (callNow) { + func.apply(obj, args); + } + }; + }, + toArray: function toArray(obj) { + if (obj.toArray) return obj.toArray(); + return ARR_SLICE.call(obj); + }, + isUndefined: function isUndefined(obj) { + return obj === undefined; + }, + isNull: function isNull(obj) { + return obj === null; + }, + isNaN: function (_isNaN) { + function isNaN(_x) { + return _isNaN.apply(this, arguments); + } + isNaN.toString = function () { + return _isNaN.toString(); + }; + return isNaN; + }(function (obj) { + return isNaN(obj); + }), + isArray: Array.isArray || function (obj) { + return obj.constructor === Array; + }, + isObject: function isObject(obj) { + return obj === Object(obj); + }, + isNumber: function isNumber(obj) { + return obj === obj + 0; + }, + isString: function isString(obj) { + return obj === obj + ''; + }, + isBoolean: function isBoolean(obj) { + return obj === false || obj === true; + }, + isFunction: function isFunction(obj) { + return obj instanceof Function; + } +}; + +var INTERPRETATIONS = [ +{ + litmus: Common.isString, + conversions: { + THREE_CHAR_HEX: { + read: function read(original) { + var test = original.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i); + if (test === null) { + return false; + } + return { + space: 'HEX', + hex: parseInt('0x' + test[1].toString() + test[1].toString() + test[2].toString() + test[2].toString() + test[3].toString() + test[3].toString(), 0) + }; + }, + write: colorToString + }, + SIX_CHAR_HEX: { + read: function read(original) { + var test = original.match(/^#([A-F0-9]{6})$/i); + if (test === null) { + return false; + } + return { + space: 'HEX', + hex: parseInt('0x' + test[1].toString(), 0) + }; + }, + write: colorToString + }, + CSS_RGB: { + read: function read(original) { + var test = original.match(/^rgb\(\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*\)/); + if (test === null) { + return false; + } + return { + space: 'RGB', + r: parseFloat(test[1]), + g: parseFloat(test[2]), + b: parseFloat(test[3]) + }; + }, + write: colorToString + }, + CSS_RGBA: { + read: function read(original) { + var test = original.match(/^rgba\(\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*\)/); + if (test === null) { + return false; + } + return { + space: 'RGB', + r: parseFloat(test[1]), + g: parseFloat(test[2]), + b: parseFloat(test[3]), + a: parseFloat(test[4]) + }; + }, + write: colorToString + } + } +}, +{ + litmus: Common.isNumber, + conversions: { + HEX: { + read: function read(original) { + return { + space: 'HEX', + hex: original, + conversionName: 'HEX' + }; + }, + write: function write(color) { + return color.hex; + } + } + } +}, +{ + litmus: Common.isArray, + conversions: { + RGB_ARRAY: { + read: function read(original) { + if (original.length !== 3) { + return false; + } + return { + space: 'RGB', + r: original[0], + g: original[1], + b: original[2] + }; + }, + write: function write(color) { + return [color.r, color.g, color.b]; + } + }, + RGBA_ARRAY: { + read: function read(original) { + if (original.length !== 4) return false; + return { + space: 'RGB', + r: original[0], + g: original[1], + b: original[2], + a: original[3] + }; + }, + write: function write(color) { + return [color.r, color.g, color.b, color.a]; + } + } + } +}, +{ + litmus: Common.isObject, + conversions: { + RGBA_OBJ: { + read: function read(original) { + if (Common.isNumber(original.r) && Common.isNumber(original.g) && Common.isNumber(original.b) && Common.isNumber(original.a)) { + return { + space: 'RGB', + r: original.r, + g: original.g, + b: original.b, + a: original.a + }; + } + return false; + }, + write: function write(color) { + return { + r: color.r, + g: color.g, + b: color.b, + a: color.a + }; + } + }, + RGB_OBJ: { + read: function read(original) { + if (Common.isNumber(original.r) && Common.isNumber(original.g) && Common.isNumber(original.b)) { + return { + space: 'RGB', + r: original.r, + g: original.g, + b: original.b + }; + } + return false; + }, + write: function write(color) { + return { + r: color.r, + g: color.g, + b: color.b + }; + } + }, + HSVA_OBJ: { + read: function read(original) { + if (Common.isNumber(original.h) && Common.isNumber(original.s) && Common.isNumber(original.v) && Common.isNumber(original.a)) { + return { + space: 'HSV', + h: original.h, + s: original.s, + v: original.v, + a: original.a + }; + } + return false; + }, + write: function write(color) { + return { + h: color.h, + s: color.s, + v: color.v, + a: color.a + }; + } + }, + HSV_OBJ: { + read: function read(original) { + if (Common.isNumber(original.h) && Common.isNumber(original.s) && Common.isNumber(original.v)) { + return { + space: 'HSV', + h: original.h, + s: original.s, + v: original.v + }; + } + return false; + }, + write: function write(color) { + return { + h: color.h, + s: color.s, + v: color.v + }; + } + } + } +}]; +var result = void 0; +var toReturn = void 0; +var interpret = function interpret() { + toReturn = false; + var original = arguments.length > 1 ? Common.toArray(arguments) : arguments[0]; + Common.each(INTERPRETATIONS, function (family) { + if (family.litmus(original)) { + Common.each(family.conversions, function (conversion, conversionName) { + result = conversion.read(original); + if (toReturn === false && result !== false) { + toReturn = result; + result.conversionName = conversionName; + result.conversion = conversion; + return Common.BREAK; + } + }); + return Common.BREAK; + } + }); + return toReturn; +}; + +var tmpComponent = void 0; +var ColorMath = { + hsv_to_rgb: function hsv_to_rgb(h, s, v) { + var hi = Math.floor(h / 60) % 6; + var f = h / 60 - Math.floor(h / 60); + var p = v * (1.0 - s); + var q = v * (1.0 - f * s); + var t = v * (1.0 - (1.0 - f) * s); + var c = [[v, t, p], [q, v, p], [p, v, t], [p, q, v], [t, p, v], [v, p, q]][hi]; + return { + r: c[0] * 255, + g: c[1] * 255, + b: c[2] * 255 + }; + }, + rgb_to_hsv: function rgb_to_hsv(r, g, b) { + var min = Math.min(r, g, b); + var max = Math.max(r, g, b); + var delta = max - min; + var h = void 0; + var s = void 0; + if (max !== 0) { + s = delta / max; + } else { + return { + h: NaN, + s: 0, + v: 0 + }; + } + if (r === max) { + h = (g - b) / delta; + } else if (g === max) { + h = 2 + (b - r) / delta; + } else { + h = 4 + (r - g) / delta; + } + h /= 6; + if (h < 0) { + h += 1; + } + return { + h: h * 360, + s: s, + v: max / 255 + }; + }, + rgb_to_hex: function rgb_to_hex(r, g, b) { + var hex = this.hex_with_component(0, 2, r); + hex = this.hex_with_component(hex, 1, g); + hex = this.hex_with_component(hex, 0, b); + return hex; + }, + component_from_hex: function component_from_hex(hex, componentIndex) { + return hex >> componentIndex * 8 & 0xFF; + }, + hex_with_component: function hex_with_component(hex, componentIndex, value) { + return value << (tmpComponent = componentIndex * 8) | hex & ~(0xFF << tmpComponent); + } +}; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; +} : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; +}; + + + + + + + + + + + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; + +var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; +}(); + + + + + + + +var get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); + + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + + if (getter === undefined) { + return undefined; + } + + return getter.call(receiver); + } +}; + +var inherits = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; +}; + + + + + + + + + + + +var possibleConstructorReturn = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && (typeof call === "object" || typeof call === "function") ? call : self; +}; + +var Color = function () { + function Color() { + classCallCheck(this, Color); + this.__state = interpret.apply(this, arguments); + if (this.__state === false) { + throw new Error('Failed to interpret color arguments'); + } + this.__state.a = this.__state.a || 1; + } + createClass(Color, [{ + key: 'toString', + value: function toString() { + return colorToString(this); + } + }, { + key: 'toHexString', + value: function toHexString() { + return colorToString(this, true); + } + }, { + key: 'toOriginal', + value: function toOriginal() { + return this.__state.conversion.write(this); + } + }]); + return Color; +}(); +function defineRGBComponent(target, component, componentHexIndex) { + Object.defineProperty(target, component, { + get: function get$$1() { + if (this.__state.space === 'RGB') { + return this.__state[component]; + } + Color.recalculateRGB(this, component, componentHexIndex); + return this.__state[component]; + }, + set: function set$$1(v) { + if (this.__state.space !== 'RGB') { + Color.recalculateRGB(this, component, componentHexIndex); + this.__state.space = 'RGB'; + } + this.__state[component] = v; + } + }); +} +function defineHSVComponent(target, component) { + Object.defineProperty(target, component, { + get: function get$$1() { + if (this.__state.space === 'HSV') { + return this.__state[component]; + } + Color.recalculateHSV(this); + return this.__state[component]; + }, + set: function set$$1(v) { + if (this.__state.space !== 'HSV') { + Color.recalculateHSV(this); + this.__state.space = 'HSV'; + } + this.__state[component] = v; + } + }); +} +Color.recalculateRGB = function (color, component, componentHexIndex) { + if (color.__state.space === 'HEX') { + color.__state[component] = ColorMath.component_from_hex(color.__state.hex, componentHexIndex); + } else if (color.__state.space === 'HSV') { + Common.extend(color.__state, ColorMath.hsv_to_rgb(color.__state.h, color.__state.s, color.__state.v)); + } else { + throw new Error('Corrupted color state'); + } +}; +Color.recalculateHSV = function (color) { + var result = ColorMath.rgb_to_hsv(color.r, color.g, color.b); + Common.extend(color.__state, { + s: result.s, + v: result.v + }); + if (!Common.isNaN(result.h)) { + color.__state.h = result.h; + } else if (Common.isUndefined(color.__state.h)) { + color.__state.h = 0; + } +}; +Color.COMPONENTS = ['r', 'g', 'b', 'h', 's', 'v', 'hex', 'a']; +defineRGBComponent(Color.prototype, 'r', 2); +defineRGBComponent(Color.prototype, 'g', 1); +defineRGBComponent(Color.prototype, 'b', 0); +defineHSVComponent(Color.prototype, 'h'); +defineHSVComponent(Color.prototype, 's'); +defineHSVComponent(Color.prototype, 'v'); +Object.defineProperty(Color.prototype, 'a', { + get: function get$$1() { + return this.__state.a; + }, + set: function set$$1(v) { + this.__state.a = v; + } +}); +Object.defineProperty(Color.prototype, 'hex', { + get: function get$$1() { + if (this.__state.space !== 'HEX') { + this.__state.hex = ColorMath.rgb_to_hex(this.r, this.g, this.b); + this.__state.space = 'HEX'; + } + return this.__state.hex; + }, + set: function set$$1(v) { + this.__state.space = 'HEX'; + this.__state.hex = v; + } +}); + +var Controller = function () { + function Controller(object, property) { + classCallCheck(this, Controller); + this.initialValue = object[property]; + this.domElement = document.createElement('div'); + this.object = object; + this.property = property; + this.__onChange = undefined; + this.__onFinishChange = undefined; + } + createClass(Controller, [{ + key: 'onChange', + value: function onChange(fnc) { + this.__onChange = fnc; + return this; + } + }, { + key: 'onFinishChange', + value: function onFinishChange(fnc) { + this.__onFinishChange = fnc; + return this; + } + }, { + key: 'setValue', + value: function setValue(newValue) { + this.object[this.property] = newValue; + if (this.__onChange) { + this.__onChange.call(this, newValue); + } + this.updateDisplay(); + return this; + } + }, { + key: 'getValue', + value: function getValue() { + return this.object[this.property]; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + return this; + } + }, { + key: 'isModified', + value: function isModified() { + return this.initialValue !== this.getValue(); + } + }]); + return Controller; +}(); + +var EVENT_MAP = { + HTMLEvents: ['change'], + MouseEvents: ['click', 'mousemove', 'mousedown', 'mouseup', 'mouseover'], + KeyboardEvents: ['keydown'] +}; +var EVENT_MAP_INV = {}; +Common.each(EVENT_MAP, function (v, k) { + Common.each(v, function (e) { + EVENT_MAP_INV[e] = k; + }); +}); +var CSS_VALUE_PIXELS = /(\d+(\.\d+)?)px/; +function cssValueToPixels(val) { + if (val === '0' || Common.isUndefined(val)) { + return 0; + } + var match = val.match(CSS_VALUE_PIXELS); + if (!Common.isNull(match)) { + return parseFloat(match[1]); + } + return 0; +} +var dom = { + makeSelectable: function makeSelectable(elem, selectable) { + if (elem === undefined || elem.style === undefined) return; + elem.onselectstart = selectable ? function () { + return false; + } : function () {}; + elem.style.MozUserSelect = selectable ? 'auto' : 'none'; + elem.style.KhtmlUserSelect = selectable ? 'auto' : 'none'; + elem.unselectable = selectable ? 'on' : 'off'; + }, + makeFullscreen: function makeFullscreen(elem, hor, vert) { + var vertical = vert; + var horizontal = hor; + if (Common.isUndefined(horizontal)) { + horizontal = true; + } + if (Common.isUndefined(vertical)) { + vertical = true; + } + elem.style.position = 'absolute'; + if (horizontal) { + elem.style.left = 0; + elem.style.right = 0; + } + if (vertical) { + elem.style.top = 0; + elem.style.bottom = 0; + } + }, + fakeEvent: function fakeEvent(elem, eventType, pars, aux) { + var params = pars || {}; + var className = EVENT_MAP_INV[eventType]; + if (!className) { + throw new Error('Event type ' + eventType + ' not supported.'); + } + var evt = document.createEvent(className); + switch (className) { + case 'MouseEvents': + { + var clientX = params.x || params.clientX || 0; + var clientY = params.y || params.clientY || 0; + evt.initMouseEvent(eventType, params.bubbles || false, params.cancelable || true, window, params.clickCount || 1, 0, + 0, + clientX, + clientY, + false, false, false, false, 0, null); + break; + } + case 'KeyboardEvents': + { + var init = evt.initKeyboardEvent || evt.initKeyEvent; + Common.defaults(params, { + cancelable: true, + ctrlKey: false, + altKey: false, + shiftKey: false, + metaKey: false, + keyCode: undefined, + charCode: undefined + }); + init(eventType, params.bubbles || false, params.cancelable, window, params.ctrlKey, params.altKey, params.shiftKey, params.metaKey, params.keyCode, params.charCode); + break; + } + default: + { + evt.initEvent(eventType, params.bubbles || false, params.cancelable || true); + break; + } + } + Common.defaults(evt, aux); + elem.dispatchEvent(evt); + }, + bind: function bind(elem, event, func, newBool) { + var bool = newBool || false; + if (elem.addEventListener) { + elem.addEventListener(event, func, bool); + } else if (elem.attachEvent) { + elem.attachEvent('on' + event, func); + } + return dom; + }, + unbind: function unbind(elem, event, func, newBool) { + var bool = newBool || false; + if (elem.removeEventListener) { + elem.removeEventListener(event, func, bool); + } else if (elem.detachEvent) { + elem.detachEvent('on' + event, func); + } + return dom; + }, + addClass: function addClass(elem, className) { + if (elem.className === undefined) { + elem.className = className; + } else if (elem.className !== className) { + var classes = elem.className.split(/ +/); + if (classes.indexOf(className) === -1) { + classes.push(className); + elem.className = classes.join(' ').replace(/^\s+/, '').replace(/\s+$/, ''); + } + } + return dom; + }, + removeClass: function removeClass(elem, className) { + if (className) { + if (elem.className === className) { + elem.removeAttribute('class'); + } else { + var classes = elem.className.split(/ +/); + var index = classes.indexOf(className); + if (index !== -1) { + classes.splice(index, 1); + elem.className = classes.join(' '); + } + } + } else { + elem.className = undefined; + } + return dom; + }, + hasClass: function hasClass(elem, className) { + return new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)').test(elem.className) || false; + }, + getWidth: function getWidth(elem) { + var style = getComputedStyle(elem); + return cssValueToPixels(style['border-left-width']) + cssValueToPixels(style['border-right-width']) + cssValueToPixels(style['padding-left']) + cssValueToPixels(style['padding-right']) + cssValueToPixels(style.width); + }, + getHeight: function getHeight(elem) { + var style = getComputedStyle(elem); + return cssValueToPixels(style['border-top-width']) + cssValueToPixels(style['border-bottom-width']) + cssValueToPixels(style['padding-top']) + cssValueToPixels(style['padding-bottom']) + cssValueToPixels(style.height); + }, + getOffset: function getOffset(el) { + var elem = el; + var offset = { left: 0, top: 0 }; + if (elem.offsetParent) { + do { + offset.left += elem.offsetLeft; + offset.top += elem.offsetTop; + elem = elem.offsetParent; + } while (elem); + } + return offset; + }, + isActive: function isActive(elem) { + return elem === document.activeElement && (elem.type || elem.href); + } +}; + +var BooleanController = function (_Controller) { + inherits(BooleanController, _Controller); + function BooleanController(object, property) { + classCallCheck(this, BooleanController); + var _this2 = possibleConstructorReturn(this, (BooleanController.__proto__ || Object.getPrototypeOf(BooleanController)).call(this, object, property)); + var _this = _this2; + _this2.__prev = _this2.getValue(); + _this2.__checkbox = document.createElement('input'); + _this2.__checkbox.setAttribute('type', 'checkbox'); + function onChange() { + _this.setValue(!_this.__prev); + } + dom.bind(_this2.__checkbox, 'change', onChange, false); + _this2.domElement.appendChild(_this2.__checkbox); + _this2.updateDisplay(); + return _this2; + } + createClass(BooleanController, [{ + key: 'setValue', + value: function setValue(v) { + var toReturn = get(BooleanController.prototype.__proto__ || Object.getPrototypeOf(BooleanController.prototype), 'setValue', this).call(this, v); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + this.__prev = this.getValue(); + return toReturn; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + if (this.getValue() === true) { + this.__checkbox.setAttribute('checked', 'checked'); + this.__checkbox.checked = true; + this.__prev = true; + } else { + this.__checkbox.checked = false; + this.__prev = false; + } + return get(BooleanController.prototype.__proto__ || Object.getPrototypeOf(BooleanController.prototype), 'updateDisplay', this).call(this); + } + }]); + return BooleanController; +}(Controller); + +var OptionController = function (_Controller) { + inherits(OptionController, _Controller); + function OptionController(object, property, opts) { + classCallCheck(this, OptionController); + var _this2 = possibleConstructorReturn(this, (OptionController.__proto__ || Object.getPrototypeOf(OptionController)).call(this, object, property)); + var options = opts; + var _this = _this2; + _this2.__select = document.createElement('select'); + if (Common.isArray(options)) { + var map = {}; + Common.each(options, function (element) { + map[element] = element; + }); + options = map; + } + Common.each(options, function (value, key) { + var opt = document.createElement('option'); + opt.innerHTML = key; + opt.setAttribute('value', value); + _this.__select.appendChild(opt); + }); + _this2.updateDisplay(); + dom.bind(_this2.__select, 'change', function () { + var desiredValue = this.options[this.selectedIndex].value; + _this.setValue(desiredValue); + }); + _this2.domElement.appendChild(_this2.__select); + return _this2; + } + createClass(OptionController, [{ + key: 'setValue', + value: function setValue(v) { + var toReturn = get(OptionController.prototype.__proto__ || Object.getPrototypeOf(OptionController.prototype), 'setValue', this).call(this, v); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + return toReturn; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + if (dom.isActive(this.__select)) return this; + this.__select.value = this.getValue(); + return get(OptionController.prototype.__proto__ || Object.getPrototypeOf(OptionController.prototype), 'updateDisplay', this).call(this); + } + }]); + return OptionController; +}(Controller); + +var StringController = function (_Controller) { + inherits(StringController, _Controller); + function StringController(object, property) { + classCallCheck(this, StringController); + var _this2 = possibleConstructorReturn(this, (StringController.__proto__ || Object.getPrototypeOf(StringController)).call(this, object, property)); + var _this = _this2; + function onChange() { + _this.setValue(_this.__input.value); + } + function onBlur() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + _this2.__input = document.createElement('input'); + _this2.__input.setAttribute('type', 'text'); + dom.bind(_this2.__input, 'keyup', onChange); + dom.bind(_this2.__input, 'change', onChange); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + this.blur(); + } + }); + _this2.updateDisplay(); + _this2.domElement.appendChild(_this2.__input); + return _this2; + } + createClass(StringController, [{ + key: 'updateDisplay', + value: function updateDisplay() { + if (!dom.isActive(this.__input)) { + this.__input.value = this.getValue(); + } + return get(StringController.prototype.__proto__ || Object.getPrototypeOf(StringController.prototype), 'updateDisplay', this).call(this); + } + }]); + return StringController; +}(Controller); + +function numDecimals(x) { + var _x = x.toString(); + if (_x.indexOf('.') > -1) { + return _x.length - _x.indexOf('.') - 1; + } + return 0; +} +var NumberController = function (_Controller) { + inherits(NumberController, _Controller); + function NumberController(object, property, params) { + classCallCheck(this, NumberController); + var _this = possibleConstructorReturn(this, (NumberController.__proto__ || Object.getPrototypeOf(NumberController)).call(this, object, property)); + var _params = params || {}; + _this.__min = _params.min; + _this.__max = _params.max; + _this.__step = _params.step; + if (Common.isUndefined(_this.__step)) { + if (_this.initialValue === 0) { + _this.__impliedStep = 1; + } else { + _this.__impliedStep = Math.pow(10, Math.floor(Math.log(Math.abs(_this.initialValue)) / Math.LN10)) / 10; + } + } else { + _this.__impliedStep = _this.__step; + } + _this.__precision = numDecimals(_this.__impliedStep); + return _this; + } + createClass(NumberController, [{ + key: 'setValue', + value: function setValue(v) { + var _v = v; + if (this.__min !== undefined && _v < this.__min) { + _v = this.__min; + } else if (this.__max !== undefined && _v > this.__max) { + _v = this.__max; + } + if (this.__step !== undefined && _v % this.__step !== 0) { + _v = Math.round(_v / this.__step) * this.__step; + } + return get(NumberController.prototype.__proto__ || Object.getPrototypeOf(NumberController.prototype), 'setValue', this).call(this, _v); + } + }, { + key: 'min', + value: function min(minValue) { + this.__min = minValue; + return this; + } + }, { + key: 'max', + value: function max(maxValue) { + this.__max = maxValue; + return this; + } + }, { + key: 'step', + value: function step(stepValue) { + this.__step = stepValue; + this.__impliedStep = stepValue; + this.__precision = numDecimals(stepValue); + return this; + } + }]); + return NumberController; +}(Controller); + +function roundToDecimal(value, decimals) { + var tenTo = Math.pow(10, decimals); + return Math.round(value * tenTo) / tenTo; +} +var NumberControllerBox = function (_NumberController) { + inherits(NumberControllerBox, _NumberController); + function NumberControllerBox(object, property, params) { + classCallCheck(this, NumberControllerBox); + var _this2 = possibleConstructorReturn(this, (NumberControllerBox.__proto__ || Object.getPrototypeOf(NumberControllerBox)).call(this, object, property, params)); + _this2.__truncationSuspended = false; + var _this = _this2; + var prevY = void 0; + function onChange() { + var attempted = parseFloat(_this.__input.value); + if (!Common.isNaN(attempted)) { + _this.setValue(attempted); + } + } + function onFinish() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + function onBlur() { + onFinish(); + } + function onMouseDrag(e) { + var diff = prevY - e.clientY; + _this.setValue(_this.getValue() + diff * _this.__impliedStep); + prevY = e.clientY; + } + function onMouseUp() { + dom.unbind(window, 'mousemove', onMouseDrag); + dom.unbind(window, 'mouseup', onMouseUp); + onFinish(); + } + function onMouseDown(e) { + dom.bind(window, 'mousemove', onMouseDrag); + dom.bind(window, 'mouseup', onMouseUp); + prevY = e.clientY; + } + _this2.__input = document.createElement('input'); + _this2.__input.setAttribute('type', 'text'); + dom.bind(_this2.__input, 'change', onChange); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__input, 'mousedown', onMouseDown); + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + _this.__truncationSuspended = true; + this.blur(); + _this.__truncationSuspended = false; + onFinish(); + } + }); + _this2.updateDisplay(); + _this2.domElement.appendChild(_this2.__input); + return _this2; + } + createClass(NumberControllerBox, [{ + key: 'updateDisplay', + value: function updateDisplay() { + this.__input.value = this.__truncationSuspended ? this.getValue() : roundToDecimal(this.getValue(), this.__precision); + return get(NumberControllerBox.prototype.__proto__ || Object.getPrototypeOf(NumberControllerBox.prototype), 'updateDisplay', this).call(this); + } + }]); + return NumberControllerBox; +}(NumberController); + +function map(v, i1, i2, o1, o2) { + return o1 + (o2 - o1) * ((v - i1) / (i2 - i1)); +} +var NumberControllerSlider = function (_NumberController) { + inherits(NumberControllerSlider, _NumberController); + function NumberControllerSlider(object, property, min, max, step) { + classCallCheck(this, NumberControllerSlider); + var _this2 = possibleConstructorReturn(this, (NumberControllerSlider.__proto__ || Object.getPrototypeOf(NumberControllerSlider)).call(this, object, property, { min: min, max: max, step: step })); + var _this = _this2; + _this2.__background = document.createElement('div'); + _this2.__foreground = document.createElement('div'); + dom.bind(_this2.__background, 'mousedown', onMouseDown); + dom.bind(_this2.__background, 'touchstart', onTouchStart); + dom.addClass(_this2.__background, 'slider'); + dom.addClass(_this2.__foreground, 'slider-fg'); + function onMouseDown(e) { + document.activeElement.blur(); + dom.bind(window, 'mousemove', onMouseDrag); + dom.bind(window, 'mouseup', onMouseUp); + onMouseDrag(e); + } + function onMouseDrag(e) { + e.preventDefault(); + var bgRect = _this.__background.getBoundingClientRect(); + _this.setValue(map(e.clientX, bgRect.left, bgRect.right, _this.__min, _this.__max)); + return false; + } + function onMouseUp() { + dom.unbind(window, 'mousemove', onMouseDrag); + dom.unbind(window, 'mouseup', onMouseUp); + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + function onTouchStart(e) { + if (e.touches.length !== 1) { + return; + } + dom.bind(window, 'touchmove', onTouchMove); + dom.bind(window, 'touchend', onTouchEnd); + onTouchMove(e); + } + function onTouchMove(e) { + var clientX = e.touches[0].clientX; + var bgRect = _this.__background.getBoundingClientRect(); + _this.setValue(map(clientX, bgRect.left, bgRect.right, _this.__min, _this.__max)); + } + function onTouchEnd() { + dom.unbind(window, 'touchmove', onTouchMove); + dom.unbind(window, 'touchend', onTouchEnd); + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + _this2.updateDisplay(); + _this2.__background.appendChild(_this2.__foreground); + _this2.domElement.appendChild(_this2.__background); + return _this2; + } + createClass(NumberControllerSlider, [{ + key: 'updateDisplay', + value: function updateDisplay() { + var pct = (this.getValue() - this.__min) / (this.__max - this.__min); + this.__foreground.style.width = pct * 100 + '%'; + return get(NumberControllerSlider.prototype.__proto__ || Object.getPrototypeOf(NumberControllerSlider.prototype), 'updateDisplay', this).call(this); + } + }]); + return NumberControllerSlider; +}(NumberController); + +var FunctionController = function (_Controller) { + inherits(FunctionController, _Controller); + function FunctionController(object, property, text) { + classCallCheck(this, FunctionController); + var _this2 = possibleConstructorReturn(this, (FunctionController.__proto__ || Object.getPrototypeOf(FunctionController)).call(this, object, property)); + var _this = _this2; + _this2.__button = document.createElement('div'); + _this2.__button.innerHTML = text === undefined ? 'Fire' : text; + dom.bind(_this2.__button, 'click', function (e) { + e.preventDefault(); + _this.fire(); + return false; + }); + dom.addClass(_this2.__button, 'button'); + _this2.domElement.appendChild(_this2.__button); + return _this2; + } + createClass(FunctionController, [{ + key: 'fire', + value: function fire() { + if (this.__onChange) { + this.__onChange.call(this); + } + this.getValue().call(this.object); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + } + }]); + return FunctionController; +}(Controller); + +var ColorController = function (_Controller) { + inherits(ColorController, _Controller); + function ColorController(object, property) { + classCallCheck(this, ColorController); + var _this2 = possibleConstructorReturn(this, (ColorController.__proto__ || Object.getPrototypeOf(ColorController)).call(this, object, property)); + _this2.__color = new Color(_this2.getValue()); + _this2.__temp = new Color(0); + var _this = _this2; + _this2.domElement = document.createElement('div'); + dom.makeSelectable(_this2.domElement, false); + _this2.__selector = document.createElement('div'); + _this2.__selector.className = 'selector'; + _this2.__saturation_field = document.createElement('div'); + _this2.__saturation_field.className = 'saturation-field'; + _this2.__field_knob = document.createElement('div'); + _this2.__field_knob.className = 'field-knob'; + _this2.__field_knob_border = '2px solid '; + _this2.__hue_knob = document.createElement('div'); + _this2.__hue_knob.className = 'hue-knob'; + _this2.__hue_field = document.createElement('div'); + _this2.__hue_field.className = 'hue-field'; + _this2.__input = document.createElement('input'); + _this2.__input.type = 'text'; + _this2.__input_textShadow = '0 1px 1px '; + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + onBlur.call(this); + } + }); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__selector, 'mousedown', function () { + dom.addClass(this, 'drag').bind(window, 'mouseup', function () { + dom.removeClass(_this.__selector, 'drag'); + }); + }); + dom.bind(_this2.__selector, 'touchstart', function () { + dom.addClass(this, 'drag').bind(window, 'touchend', function () { + dom.removeClass(_this.__selector, 'drag'); + }); + }); + var valueField = document.createElement('div'); + Common.extend(_this2.__selector.style, { + width: '122px', + height: '102px', + padding: '3px', + backgroundColor: '#222', + boxShadow: '0px 1px 3px rgba(0,0,0,0.3)' + }); + Common.extend(_this2.__field_knob.style, { + position: 'absolute', + width: '12px', + height: '12px', + border: _this2.__field_knob_border + (_this2.__color.v < 0.5 ? '#fff' : '#000'), + boxShadow: '0px 1px 3px rgba(0,0,0,0.5)', + borderRadius: '12px', + zIndex: 1 + }); + Common.extend(_this2.__hue_knob.style, { + position: 'absolute', + width: '15px', + height: '2px', + borderRight: '4px solid #fff', + zIndex: 1 + }); + Common.extend(_this2.__saturation_field.style, { + width: '100px', + height: '100px', + border: '1px solid #555', + marginRight: '3px', + display: 'inline-block', + cursor: 'pointer' + }); + Common.extend(valueField.style, { + width: '100%', + height: '100%', + background: 'none' + }); + linearGradient(valueField, 'top', 'rgba(0,0,0,0)', '#000'); + Common.extend(_this2.__hue_field.style, { + width: '15px', + height: '100px', + border: '1px solid #555', + cursor: 'ns-resize', + position: 'absolute', + top: '3px', + right: '3px' + }); + hueGradient(_this2.__hue_field); + Common.extend(_this2.__input.style, { + outline: 'none', + textAlign: 'center', + color: '#fff', + border: 0, + fontWeight: 'bold', + textShadow: _this2.__input_textShadow + 'rgba(0,0,0,0.7)' + }); + dom.bind(_this2.__saturation_field, 'mousedown', fieldDown); + dom.bind(_this2.__saturation_field, 'touchstart', fieldDown); + dom.bind(_this2.__field_knob, 'mousedown', fieldDown); + dom.bind(_this2.__field_knob, 'touchstart', fieldDown); + dom.bind(_this2.__hue_field, 'mousedown', fieldDownH); + dom.bind(_this2.__hue_field, 'touchstart', fieldDownH); + function fieldDown(e) { + setSV(e); + dom.bind(window, 'mousemove', setSV); + dom.bind(window, 'touchmove', setSV); + dom.bind(window, 'mouseup', fieldUpSV); + dom.bind(window, 'touchend', fieldUpSV); + } + function fieldDownH(e) { + setH(e); + dom.bind(window, 'mousemove', setH); + dom.bind(window, 'touchmove', setH); + dom.bind(window, 'mouseup', fieldUpH); + dom.bind(window, 'touchend', fieldUpH); + } + function fieldUpSV() { + dom.unbind(window, 'mousemove', setSV); + dom.unbind(window, 'touchmove', setSV); + dom.unbind(window, 'mouseup', fieldUpSV); + dom.unbind(window, 'touchend', fieldUpSV); + onFinish(); + } + function fieldUpH() { + dom.unbind(window, 'mousemove', setH); + dom.unbind(window, 'touchmove', setH); + dom.unbind(window, 'mouseup', fieldUpH); + dom.unbind(window, 'touchend', fieldUpH); + onFinish(); + } + function onBlur() { + var i = interpret(this.value); + if (i !== false) { + _this.__color.__state = i; + _this.setValue(_this.__color.toOriginal()); + } else { + this.value = _this.__color.toString(); + } + } + function onFinish() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.__color.toOriginal()); + } + } + _this2.__saturation_field.appendChild(valueField); + _this2.__selector.appendChild(_this2.__field_knob); + _this2.__selector.appendChild(_this2.__saturation_field); + _this2.__selector.appendChild(_this2.__hue_field); + _this2.__hue_field.appendChild(_this2.__hue_knob); + _this2.domElement.appendChild(_this2.__input); + _this2.domElement.appendChild(_this2.__selector); + _this2.updateDisplay(); + function setSV(e) { + if (e.type.indexOf('touch') === -1) { + e.preventDefault(); + } + var fieldRect = _this.__saturation_field.getBoundingClientRect(); + var _ref = e.touches && e.touches[0] || e, + clientX = _ref.clientX, + clientY = _ref.clientY; + var s = (clientX - fieldRect.left) / (fieldRect.right - fieldRect.left); + var v = 1 - (clientY - fieldRect.top) / (fieldRect.bottom - fieldRect.top); + if (v > 1) { + v = 1; + } else if (v < 0) { + v = 0; + } + if (s > 1) { + s = 1; + } else if (s < 0) { + s = 0; + } + _this.__color.v = v; + _this.__color.s = s; + _this.setValue(_this.__color.toOriginal()); + return false; + } + function setH(e) { + if (e.type.indexOf('touch') === -1) { + e.preventDefault(); + } + var fieldRect = _this.__hue_field.getBoundingClientRect(); + var _ref2 = e.touches && e.touches[0] || e, + clientY = _ref2.clientY; + var h = 1 - (clientY - fieldRect.top) / (fieldRect.bottom - fieldRect.top); + if (h > 1) { + h = 1; + } else if (h < 0) { + h = 0; + } + _this.__color.h = h * 360; + _this.setValue(_this.__color.toOriginal()); + return false; + } + return _this2; + } + createClass(ColorController, [{ + key: 'updateDisplay', + value: function updateDisplay() { + var i = interpret(this.getValue()); + if (i !== false) { + var mismatch = false; + Common.each(Color.COMPONENTS, function (component) { + if (!Common.isUndefined(i[component]) && !Common.isUndefined(this.__color.__state[component]) && i[component] !== this.__color.__state[component]) { + mismatch = true; + return {}; + } + }, this); + if (mismatch) { + Common.extend(this.__color.__state, i); + } + } + Common.extend(this.__temp.__state, this.__color.__state); + this.__temp.a = 1; + var flip = this.__color.v < 0.5 || this.__color.s > 0.5 ? 255 : 0; + var _flip = 255 - flip; + Common.extend(this.__field_knob.style, { + marginLeft: 100 * this.__color.s - 7 + 'px', + marginTop: 100 * (1 - this.__color.v) - 7 + 'px', + backgroundColor: this.__temp.toHexString(), + border: this.__field_knob_border + 'rgb(' + flip + ',' + flip + ',' + flip + ')' + }); + this.__hue_knob.style.marginTop = (1 - this.__color.h / 360) * 100 + 'px'; + this.__temp.s = 1; + this.__temp.v = 1; + linearGradient(this.__saturation_field, 'left', '#fff', this.__temp.toHexString()); + this.__input.value = this.__color.toString(); + Common.extend(this.__input.style, { + backgroundColor: this.__color.toHexString(), + color: 'rgb(' + flip + ',' + flip + ',' + flip + ')', + textShadow: this.__input_textShadow + 'rgba(' + _flip + ',' + _flip + ',' + _flip + ',.7)' + }); + } + }]); + return ColorController; +}(Controller); +var vendors = ['-moz-', '-o-', '-webkit-', '-ms-', '']; +function linearGradient(elem, x, a, b) { + elem.style.background = ''; + Common.each(vendors, function (vendor) { + elem.style.cssText += 'background: ' + vendor + 'linear-gradient(' + x + ', ' + a + ' 0%, ' + b + ' 100%); '; + }); +} +function hueGradient(elem) { + elem.style.background = ''; + elem.style.cssText += 'background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);'; + elem.style.cssText += 'background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; +} + +var css = { + load: function load(url, indoc) { + var doc = indoc || document; + var link = doc.createElement('link'); + link.type = 'text/css'; + link.rel = 'stylesheet'; + link.href = url; + doc.getElementsByTagName('head')[0].appendChild(link); + }, + inject: function inject(cssContent, indoc) { + var doc = indoc || document; + var injected = document.createElement('style'); + injected.type = 'text/css'; + injected.innerHTML = cssContent; + var head = doc.getElementsByTagName('head')[0]; + try { + head.appendChild(injected); + } catch (e) { + } + } +}; + +var saveDialogContents = "
\n\n Here's the new load parameter for your GUI's constructor:\n\n \n\n
\n\n Automatically save\n values to localStorage on exit.\n\n
The values saved to localStorage will\n override those passed to dat.GUI's constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n\n
\n\n
\n\n
"; + +var ControllerFactory = function ControllerFactory(object, property) { + var initialValue = object[property]; + if (Common.isArray(arguments[2]) || Common.isObject(arguments[2])) { + return new OptionController(object, property, arguments[2]); + } + if (Common.isNumber(initialValue)) { + if (Common.isNumber(arguments[2]) && Common.isNumber(arguments[3])) { + if (Common.isNumber(arguments[4])) { + return new NumberControllerSlider(object, property, arguments[2], arguments[3], arguments[4]); + } + return new NumberControllerSlider(object, property, arguments[2], arguments[3]); + } + if (Common.isNumber(arguments[4])) { + return new NumberControllerBox(object, property, { min: arguments[2], max: arguments[3], step: arguments[4] }); + } + return new NumberControllerBox(object, property, { min: arguments[2], max: arguments[3] }); + } + if (Common.isString(initialValue)) { + return new StringController(object, property); + } + if (Common.isFunction(initialValue)) { + return new FunctionController(object, property, ''); + } + if (Common.isBoolean(initialValue)) { + return new BooleanController(object, property); + } + return null; +}; + +function requestAnimationFrame(callback) { + setTimeout(callback, 1000 / 60); +} +var requestAnimationFrame$1 = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || requestAnimationFrame; + +var CenteredDiv = function () { + function CenteredDiv() { + classCallCheck(this, CenteredDiv); + this.backgroundElement = document.createElement('div'); + Common.extend(this.backgroundElement.style, { + backgroundColor: 'rgba(0,0,0,0.8)', + top: 0, + left: 0, + display: 'none', + zIndex: '1000', + opacity: 0, + WebkitTransition: 'opacity 0.2s linear', + transition: 'opacity 0.2s linear' + }); + dom.makeFullscreen(this.backgroundElement); + this.backgroundElement.style.position = 'fixed'; + this.domElement = document.createElement('div'); + Common.extend(this.domElement.style, { + position: 'fixed', + display: 'none', + zIndex: '1001', + opacity: 0, + WebkitTransition: '-webkit-transform 0.2s ease-out, opacity 0.2s linear', + transition: 'transform 0.2s ease-out, opacity 0.2s linear' + }); + document.body.appendChild(this.backgroundElement); + document.body.appendChild(this.domElement); + var _this = this; + dom.bind(this.backgroundElement, 'click', function () { + _this.hide(); + }); + } + createClass(CenteredDiv, [{ + key: 'show', + value: function show() { + var _this = this; + this.backgroundElement.style.display = 'block'; + this.domElement.style.display = 'block'; + this.domElement.style.opacity = 0; + this.domElement.style.webkitTransform = 'scale(1.1)'; + this.layout(); + Common.defer(function () { + _this.backgroundElement.style.opacity = 1; + _this.domElement.style.opacity = 1; + _this.domElement.style.webkitTransform = 'scale(1)'; + }); + } + }, { + key: 'hide', + value: function hide() { + var _this = this; + var hide = function hide() { + _this.domElement.style.display = 'none'; + _this.backgroundElement.style.display = 'none'; + dom.unbind(_this.domElement, 'webkitTransitionEnd', hide); + dom.unbind(_this.domElement, 'transitionend', hide); + dom.unbind(_this.domElement, 'oTransitionEnd', hide); + }; + dom.bind(this.domElement, 'webkitTransitionEnd', hide); + dom.bind(this.domElement, 'transitionend', hide); + dom.bind(this.domElement, 'oTransitionEnd', hide); + this.backgroundElement.style.opacity = 0; + this.domElement.style.opacity = 0; + this.domElement.style.webkitTransform = 'scale(1.1)'; + } + }, { + key: 'layout', + value: function layout() { + this.domElement.style.left = window.innerWidth / 2 - dom.getWidth(this.domElement) / 2 + 'px'; + this.domElement.style.top = window.innerHeight / 2 - dom.getHeight(this.domElement) / 2 + 'px'; + } + }]); + return CenteredDiv; +}(); + +var styleSheet = ___$insertStyle(".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity .1s linear;-o-transition:opacity .1s linear;-moz-transition:opacity .1s linear;transition:opacity .1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1 !important}.dg.main:hover .close-button,.dg.main .close-button.drag{opacity:1}.dg.main .close-button{-webkit-transition:opacity .1s linear;-o-transition:opacity .1s linear;-moz-transition:opacity .1s linear;transition:opacity .1s linear;border:0;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button.close-top{position:relative}.dg.main .close-button.close-bottom{position:absolute}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-y:visible}.dg.a.has-save>ul.close-top{margin-top:0}.dg.a.has-save>ul.close-bottom{margin-top:27px}.dg.a.has-save>ul.closed{margin-top:0}.dg.a .save-row{top:0;z-index:1002}.dg.a .save-row.close-top{position:relative}.dg.a .save-row.close-bottom{position:fixed}.dg li{-webkit-transition:height .1s ease-out;-o-transition:height .1s ease-out;-moz-transition:height .1s ease-out;transition:height .1s ease-out;-webkit-transition:overflow .1s linear;-o-transition:overflow .1s linear;-moz-transition:overflow .1s linear;transition:overflow .1s linear}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid rgba(0,0,0,0)}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li>*{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px;overflow:hidden}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .cr.function .property-name{width:100%}.dg .c{float:left;width:60%;position:relative}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:7px}.dg .c select{margin-top:5px}.dg .cr.function,.dg .cr.function .property-name,.dg .cr.function *,.dg .cr.boolean,.dg .cr.boolean *{cursor:pointer}.dg .cr.color{overflow:visible}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0px 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco, monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px 'Lucida Grande', sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px 4px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid rgba(255,255,255,0.2)}.dg .closed li.title{background-image:url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==)}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.color{border-left:3px solid}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2FA1D6}.dg .cr.number input[type=text]{color:#2FA1D6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.function:hover,.dg .cr.boolean:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2FA1D6;max-width:100%}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}\n"); + +css.inject(styleSheet); +var CSS_NAMESPACE = 'dg'; +var HIDE_KEY_CODE = 72; +var CLOSE_BUTTON_HEIGHT = 20; +var DEFAULT_DEFAULT_PRESET_NAME = 'Default'; +var SUPPORTS_LOCAL_STORAGE = function () { + try { + return !!window.localStorage; + } catch (e) { + return false; + } +}(); +var SAVE_DIALOGUE = void 0; +var autoPlaceVirgin = true; +var autoPlaceContainer = void 0; +var hide = false; +var hideableGuis = []; +var GUI = function GUI(pars) { + var _this = this; + var params = pars || {}; + this.domElement = document.createElement('div'); + this.__ul = document.createElement('ul'); + this.domElement.appendChild(this.__ul); + dom.addClass(this.domElement, CSS_NAMESPACE); + this.__folders = {}; + this.__controllers = []; + this.__rememberedObjects = []; + this.__rememberedObjectIndecesToControllers = []; + this.__listening = []; + params = Common.defaults(params, { + closeOnTop: false, + autoPlace: true, + width: GUI.DEFAULT_WIDTH + }); + params = Common.defaults(params, { + resizable: params.autoPlace, + hideable: params.autoPlace + }); + if (!Common.isUndefined(params.load)) { + if (params.preset) { + params.load.preset = params.preset; + } + } else { + params.load = { preset: DEFAULT_DEFAULT_PRESET_NAME }; + } + if (Common.isUndefined(params.parent) && params.hideable) { + hideableGuis.push(this); + } + params.resizable = Common.isUndefined(params.parent) && params.resizable; + if (params.autoPlace && Common.isUndefined(params.scrollable)) { + params.scrollable = true; + } + var useLocalStorage = SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(this, 'isLocal')) === 'true'; + var saveToLocalStorage = void 0; + var titleRow = void 0; + Object.defineProperties(this, + { + parent: { + get: function get$$1() { + return params.parent; + } + }, + scrollable: { + get: function get$$1() { + return params.scrollable; + } + }, + autoPlace: { + get: function get$$1() { + return params.autoPlace; + } + }, + closeOnTop: { + get: function get$$1() { + return params.closeOnTop; + } + }, + preset: { + get: function get$$1() { + if (_this.parent) { + return _this.getRoot().preset; + } + return params.load.preset; + }, + set: function set$$1(v) { + if (_this.parent) { + _this.getRoot().preset = v; + } else { + params.load.preset = v; + } + setPresetSelectIndex(this); + _this.revert(); + } + }, + width: { + get: function get$$1() { + return params.width; + }, + set: function set$$1(v) { + params.width = v; + setWidth(_this, v); + } + }, + name: { + get: function get$$1() { + return params.name; + }, + set: function set$$1(v) { + params.name = v; + if (titleRow) { + titleRow.innerHTML = params.name; + } + } + }, + closed: { + get: function get$$1() { + return params.closed; + }, + set: function set$$1(v) { + params.closed = v; + if (params.closed) { + dom.addClass(_this.__ul, GUI.CLASS_CLOSED); + } else { + dom.removeClass(_this.__ul, GUI.CLASS_CLOSED); + } + this.onResize(); + if (_this.__closeButton) { + _this.__closeButton.innerHTML = v ? GUI.TEXT_OPEN : GUI.TEXT_CLOSED; + } + } + }, + load: { + get: function get$$1() { + return params.load; + } + }, + useLocalStorage: { + get: function get$$1() { + return useLocalStorage; + }, + set: function set$$1(bool) { + if (SUPPORTS_LOCAL_STORAGE) { + useLocalStorage = bool; + if (bool) { + dom.bind(window, 'unload', saveToLocalStorage); + } else { + dom.unbind(window, 'unload', saveToLocalStorage); + } + localStorage.setItem(getLocalStorageHash(_this, 'isLocal'), bool); + } + } + } + }); + if (Common.isUndefined(params.parent)) { + this.closed = params.closed || false; + dom.addClass(this.domElement, GUI.CLASS_MAIN); + dom.makeSelectable(this.domElement, false); + if (SUPPORTS_LOCAL_STORAGE) { + if (useLocalStorage) { + _this.useLocalStorage = true; + var savedGui = localStorage.getItem(getLocalStorageHash(this, 'gui')); + if (savedGui) { + params.load = JSON.parse(savedGui); + } + } + } + this.__closeButton = document.createElement('div'); + this.__closeButton.innerHTML = GUI.TEXT_CLOSED; + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_BUTTON); + if (params.closeOnTop) { + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_TOP); + this.domElement.insertBefore(this.__closeButton, this.domElement.childNodes[0]); + } else { + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_BOTTOM); + this.domElement.appendChild(this.__closeButton); + } + dom.bind(this.__closeButton, 'click', function () { + _this.closed = !_this.closed; + }); + } else { + if (params.closed === undefined) { + params.closed = true; + } + var titleRowName = document.createTextNode(params.name); + dom.addClass(titleRowName, 'controller-name'); + titleRow = addRow(_this, titleRowName); + var onClickTitle = function onClickTitle(e) { + e.preventDefault(); + _this.closed = !_this.closed; + return false; + }; + dom.addClass(this.__ul, GUI.CLASS_CLOSED); + dom.addClass(titleRow, 'title'); + dom.bind(titleRow, 'click', onClickTitle); + if (!params.closed) { + this.closed = false; + } + } + if (params.autoPlace) { + if (Common.isUndefined(params.parent)) { + if (autoPlaceVirgin) { + autoPlaceContainer = document.createElement('div'); + dom.addClass(autoPlaceContainer, CSS_NAMESPACE); + dom.addClass(autoPlaceContainer, GUI.CLASS_AUTO_PLACE_CONTAINER); + document.body.appendChild(autoPlaceContainer); + autoPlaceVirgin = false; + } + autoPlaceContainer.appendChild(this.domElement); + dom.addClass(this.domElement, GUI.CLASS_AUTO_PLACE); + } + if (!this.parent) { + setWidth(_this, params.width); + } + } + this.__resizeHandler = function () { + _this.onResizeDebounced(); + }; + dom.bind(window, 'resize', this.__resizeHandler); + dom.bind(this.__ul, 'webkitTransitionEnd', this.__resizeHandler); + dom.bind(this.__ul, 'transitionend', this.__resizeHandler); + dom.bind(this.__ul, 'oTransitionEnd', this.__resizeHandler); + this.onResize(); + if (params.resizable) { + addResizeHandle(this); + } + saveToLocalStorage = function saveToLocalStorage() { + if (SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(_this, 'isLocal')) === 'true') { + localStorage.setItem(getLocalStorageHash(_this, 'gui'), JSON.stringify(_this.getSaveObject())); + } + }; + this.saveToLocalStorageIfPossible = saveToLocalStorage; + function resetWidth() { + var root = _this.getRoot(); + root.width += 1; + Common.defer(function () { + root.width -= 1; + }); + } + if (!params.parent) { + resetWidth(); + } +}; +GUI.toggleHide = function () { + hide = !hide; + Common.each(hideableGuis, function (gui) { + gui.domElement.style.display = hide ? 'none' : ''; + }); +}; +GUI.CLASS_AUTO_PLACE = 'a'; +GUI.CLASS_AUTO_PLACE_CONTAINER = 'ac'; +GUI.CLASS_MAIN = 'main'; +GUI.CLASS_CONTROLLER_ROW = 'cr'; +GUI.CLASS_TOO_TALL = 'taller-than-window'; +GUI.CLASS_CLOSED = 'closed'; +GUI.CLASS_CLOSE_BUTTON = 'close-button'; +GUI.CLASS_CLOSE_TOP = 'close-top'; +GUI.CLASS_CLOSE_BOTTOM = 'close-bottom'; +GUI.CLASS_DRAG = 'drag'; +GUI.DEFAULT_WIDTH = 245; +GUI.TEXT_CLOSED = 'Close Controls'; +GUI.TEXT_OPEN = 'Open Controls'; +GUI._keydownHandler = function (e) { + if (document.activeElement.type !== 'text' && (e.which === HIDE_KEY_CODE || e.keyCode === HIDE_KEY_CODE)) { + GUI.toggleHide(); + } +}; +dom.bind(window, 'keydown', GUI._keydownHandler, false); +Common.extend(GUI.prototype, +{ + add: function add(object, property) { + return _add(this, object, property, { + factoryArgs: Array.prototype.slice.call(arguments, 2) + }); + }, + addColor: function addColor(object, property) { + return _add(this, object, property, { + color: true + }); + }, + remove: function remove(controller) { + this.__ul.removeChild(controller.__li); + this.__controllers.splice(this.__controllers.indexOf(controller), 1); + var _this = this; + Common.defer(function () { + _this.onResize(); + }); + }, + destroy: function destroy() { + if (this.parent) { + throw new Error('Only the root GUI should be removed with .destroy(). ' + 'For subfolders, use gui.removeFolder(folder) instead.'); + } + if (this.autoPlace) { + autoPlaceContainer.removeChild(this.domElement); + } + var _this = this; + Common.each(this.__folders, function (subfolder) { + _this.removeFolder(subfolder); + }); + dom.unbind(window, 'keydown', GUI._keydownHandler, false); + removeListeners(this); + }, + addFolder: function addFolder(name) { + if (this.__folders[name] !== undefined) { + throw new Error('You already have a folder in this GUI by the' + ' name "' + name + '"'); + } + var newGuiParams = { name: name, parent: this }; + newGuiParams.autoPlace = this.autoPlace; + if (this.load && + this.load.folders && + this.load.folders[name]) { + newGuiParams.closed = this.load.folders[name].closed; + newGuiParams.load = this.load.folders[name]; + } + var gui = new GUI(newGuiParams); + this.__folders[name] = gui; + var li = addRow(this, gui.domElement); + dom.addClass(li, 'folder'); + return gui; + }, + removeFolder: function removeFolder(folder) { + this.__ul.removeChild(folder.domElement.parentElement); + delete this.__folders[folder.name]; + if (this.load && + this.load.folders && + this.load.folders[folder.name]) { + delete this.load.folders[folder.name]; + } + removeListeners(folder); + var _this = this; + Common.each(folder.__folders, function (subfolder) { + folder.removeFolder(subfolder); + }); + Common.defer(function () { + _this.onResize(); + }); + }, + open: function open() { + this.closed = false; + }, + close: function close() { + this.closed = true; + }, + hide: function hide() { + this.domElement.style.display = 'none'; + }, + show: function show() { + this.domElement.style.display = ''; + }, + onResize: function onResize() { + var root = this.getRoot(); + if (root.scrollable) { + var top = dom.getOffset(root.__ul).top; + var h = 0; + Common.each(root.__ul.childNodes, function (node) { + if (!(root.autoPlace && node === root.__save_row)) { + h += dom.getHeight(node); + } + }); + if (window.innerHeight - top - CLOSE_BUTTON_HEIGHT < h) { + dom.addClass(root.domElement, GUI.CLASS_TOO_TALL); + root.__ul.style.height = window.innerHeight - top - CLOSE_BUTTON_HEIGHT + 'px'; + } else { + dom.removeClass(root.domElement, GUI.CLASS_TOO_TALL); + root.__ul.style.height = 'auto'; + } + } + if (root.__resize_handle) { + Common.defer(function () { + root.__resize_handle.style.height = root.__ul.offsetHeight + 'px'; + }); + } + if (root.__closeButton) { + root.__closeButton.style.width = root.width + 'px'; + } + }, + onResizeDebounced: Common.debounce(function () { + this.onResize(); + }, 50), + remember: function remember() { + if (Common.isUndefined(SAVE_DIALOGUE)) { + SAVE_DIALOGUE = new CenteredDiv(); + SAVE_DIALOGUE.domElement.innerHTML = saveDialogContents; + } + if (this.parent) { + throw new Error('You can only call remember on a top level GUI.'); + } + var _this = this; + Common.each(Array.prototype.slice.call(arguments), function (object) { + if (_this.__rememberedObjects.length === 0) { + addSaveMenu(_this); + } + if (_this.__rememberedObjects.indexOf(object) === -1) { + _this.__rememberedObjects.push(object); + } + }); + if (this.autoPlace) { + setWidth(this, this.width); + } + }, + getRoot: function getRoot() { + var gui = this; + while (gui.parent) { + gui = gui.parent; + } + return gui; + }, + getSaveObject: function getSaveObject() { + var toReturn = this.load; + toReturn.closed = this.closed; + if (this.__rememberedObjects.length > 0) { + toReturn.preset = this.preset; + if (!toReturn.remembered) { + toReturn.remembered = {}; + } + toReturn.remembered[this.preset] = getCurrentPreset(this); + } + toReturn.folders = {}; + Common.each(this.__folders, function (element, key) { + toReturn.folders[key] = element.getSaveObject(); + }); + return toReturn; + }, + save: function save() { + if (!this.load.remembered) { + this.load.remembered = {}; + } + this.load.remembered[this.preset] = getCurrentPreset(this); + markPresetModified(this, false); + this.saveToLocalStorageIfPossible(); + }, + saveAs: function saveAs(presetName) { + if (!this.load.remembered) { + this.load.remembered = {}; + this.load.remembered[DEFAULT_DEFAULT_PRESET_NAME] = getCurrentPreset(this, true); + } + this.load.remembered[presetName] = getCurrentPreset(this); + this.preset = presetName; + addPresetOption(this, presetName, true); + this.saveToLocalStorageIfPossible(); + }, + revert: function revert(gui) { + Common.each(this.__controllers, function (controller) { + if (!this.getRoot().load.remembered) { + controller.setValue(controller.initialValue); + } else { + recallSavedValue(gui || this.getRoot(), controller); + } + if (controller.__onFinishChange) { + controller.__onFinishChange.call(controller, controller.getValue()); + } + }, this); + Common.each(this.__folders, function (folder) { + folder.revert(folder); + }); + if (!gui) { + markPresetModified(this.getRoot(), false); + } + }, + listen: function listen(controller) { + var init = this.__listening.length === 0; + this.__listening.push(controller); + if (init) { + updateDisplays(this.__listening); + } + }, + updateDisplay: function updateDisplay() { + Common.each(this.__controllers, function (controller) { + controller.updateDisplay(); + }); + Common.each(this.__folders, function (folder) { + folder.updateDisplay(); + }); + } +}); +function addRow(gui, newDom, liBefore) { + var li = document.createElement('li'); + if (newDom) { + li.appendChild(newDom); + } + if (liBefore) { + gui.__ul.insertBefore(li, liBefore); + } else { + gui.__ul.appendChild(li); + } + gui.onResize(); + return li; +} +function removeListeners(gui) { + dom.unbind(window, 'resize', gui.__resizeHandler); + if (gui.saveToLocalStorageIfPossible) { + dom.unbind(window, 'unload', gui.saveToLocalStorageIfPossible); + } +} +function markPresetModified(gui, modified) { + var opt = gui.__preset_select[gui.__preset_select.selectedIndex]; + if (modified) { + opt.innerHTML = opt.value + '*'; + } else { + opt.innerHTML = opt.value; + } +} +function augmentController(gui, li, controller) { + controller.__li = li; + controller.__gui = gui; + Common.extend(controller, { + options: function options(_options) { + if (arguments.length > 1) { + var nextSibling = controller.__li.nextElementSibling; + controller.remove(); + return _add(gui, controller.object, controller.property, { + before: nextSibling, + factoryArgs: [Common.toArray(arguments)] + }); + } + if (Common.isArray(_options) || Common.isObject(_options)) { + var _nextSibling = controller.__li.nextElementSibling; + controller.remove(); + return _add(gui, controller.object, controller.property, { + before: _nextSibling, + factoryArgs: [_options] + }); + } + }, + name: function name(_name) { + controller.__li.firstElementChild.firstElementChild.innerHTML = _name; + return controller; + }, + listen: function listen() { + controller.__gui.listen(controller); + return controller; + }, + remove: function remove() { + controller.__gui.remove(controller); + return controller; + } + }); + if (controller instanceof NumberControllerSlider) { + var box = new NumberControllerBox(controller.object, controller.property, { min: controller.__min, max: controller.__max, step: controller.__step }); + Common.each(['updateDisplay', 'onChange', 'onFinishChange', 'step', 'min', 'max'], function (method) { + var pc = controller[method]; + var pb = box[method]; + controller[method] = box[method] = function () { + var args = Array.prototype.slice.call(arguments); + pb.apply(box, args); + return pc.apply(controller, args); + }; + }); + dom.addClass(li, 'has-slider'); + controller.domElement.insertBefore(box.domElement, controller.domElement.firstElementChild); + } else if (controller instanceof NumberControllerBox) { + var r = function r(returned) { + if (Common.isNumber(controller.__min) && Common.isNumber(controller.__max)) { + var oldName = controller.__li.firstElementChild.firstElementChild.innerHTML; + var wasListening = controller.__gui.__listening.indexOf(controller) > -1; + controller.remove(); + var newController = _add(gui, controller.object, controller.property, { + before: controller.__li.nextElementSibling, + factoryArgs: [controller.__min, controller.__max, controller.__step] + }); + newController.name(oldName); + if (wasListening) newController.listen(); + return newController; + } + return returned; + }; + controller.min = Common.compose(r, controller.min); + controller.max = Common.compose(r, controller.max); + } else if (controller instanceof BooleanController) { + dom.bind(li, 'click', function () { + dom.fakeEvent(controller.__checkbox, 'click'); + }); + dom.bind(controller.__checkbox, 'click', function (e) { + e.stopPropagation(); + }); + } else if (controller instanceof FunctionController) { + dom.bind(li, 'click', function () { + dom.fakeEvent(controller.__button, 'click'); + }); + dom.bind(li, 'mouseover', function () { + dom.addClass(controller.__button, 'hover'); + }); + dom.bind(li, 'mouseout', function () { + dom.removeClass(controller.__button, 'hover'); + }); + } else if (controller instanceof ColorController) { + dom.addClass(li, 'color'); + controller.updateDisplay = Common.compose(function (val) { + li.style.borderLeftColor = controller.__color.toString(); + return val; + }, controller.updateDisplay); + controller.updateDisplay(); + } + controller.setValue = Common.compose(function (val) { + if (gui.getRoot().__preset_select && controller.isModified()) { + markPresetModified(gui.getRoot(), true); + } + return val; + }, controller.setValue); +} +function recallSavedValue(gui, controller) { + var root = gui.getRoot(); + var matchedIndex = root.__rememberedObjects.indexOf(controller.object); + if (matchedIndex !== -1) { + var controllerMap = root.__rememberedObjectIndecesToControllers[matchedIndex]; + if (controllerMap === undefined) { + controllerMap = {}; + root.__rememberedObjectIndecesToControllers[matchedIndex] = controllerMap; + } + controllerMap[controller.property] = controller; + if (root.load && root.load.remembered) { + var presetMap = root.load.remembered; + var preset = void 0; + if (presetMap[gui.preset]) { + preset = presetMap[gui.preset]; + } else if (presetMap[DEFAULT_DEFAULT_PRESET_NAME]) { + preset = presetMap[DEFAULT_DEFAULT_PRESET_NAME]; + } else { + return; + } + if (preset[matchedIndex] && preset[matchedIndex][controller.property] !== undefined) { + var value = preset[matchedIndex][controller.property]; + controller.initialValue = value; + controller.setValue(value); + } + } + } +} +function _add(gui, object, property, params) { + if (object[property] === undefined) { + throw new Error('Object "' + object + '" has no property "' + property + '"'); + } + var controller = void 0; + if (params.color) { + controller = new ColorController(object, property); + } else { + var factoryArgs = [object, property].concat(params.factoryArgs); + controller = ControllerFactory.apply(gui, factoryArgs); + } + if (params.before instanceof Controller) { + params.before = params.before.__li; + } + recallSavedValue(gui, controller); + dom.addClass(controller.domElement, 'c'); + var name = document.createElement('span'); + dom.addClass(name, 'property-name'); + name.innerHTML = controller.property; + var container = document.createElement('div'); + container.appendChild(name); + container.appendChild(controller.domElement); + var li = addRow(gui, container, params.before); + dom.addClass(li, GUI.CLASS_CONTROLLER_ROW); + if (controller instanceof ColorController) { + dom.addClass(li, 'color'); + } else { + dom.addClass(li, _typeof(controller.getValue())); + } + augmentController(gui, li, controller); + gui.__controllers.push(controller); + return controller; +} +function getLocalStorageHash(gui, key) { + return document.location.href + '.' + key; +} +function addPresetOption(gui, name, setSelected) { + var opt = document.createElement('option'); + opt.innerHTML = name; + opt.value = name; + gui.__preset_select.appendChild(opt); + if (setSelected) { + gui.__preset_select.selectedIndex = gui.__preset_select.length - 1; + } +} +function showHideExplain(gui, explain) { + explain.style.display = gui.useLocalStorage ? 'block' : 'none'; +} +function addSaveMenu(gui) { + var div = gui.__save_row = document.createElement('li'); + dom.addClass(gui.domElement, 'has-save'); + gui.__ul.insertBefore(div, gui.__ul.firstChild); + dom.addClass(div, 'save-row'); + var gears = document.createElement('span'); + gears.innerHTML = ' '; + dom.addClass(gears, 'button gears'); + var button = document.createElement('span'); + button.innerHTML = 'Save'; + dom.addClass(button, 'button'); + dom.addClass(button, 'save'); + var button2 = document.createElement('span'); + button2.innerHTML = 'New'; + dom.addClass(button2, 'button'); + dom.addClass(button2, 'save-as'); + var button3 = document.createElement('span'); + button3.innerHTML = 'Revert'; + dom.addClass(button3, 'button'); + dom.addClass(button3, 'revert'); + var select = gui.__preset_select = document.createElement('select'); + if (gui.load && gui.load.remembered) { + Common.each(gui.load.remembered, function (value, key) { + addPresetOption(gui, key, key === gui.preset); + }); + } else { + addPresetOption(gui, DEFAULT_DEFAULT_PRESET_NAME, false); + } + dom.bind(select, 'change', function () { + for (var index = 0; index < gui.__preset_select.length; index++) { + gui.__preset_select[index].innerHTML = gui.__preset_select[index].value; + } + gui.preset = this.value; + }); + div.appendChild(select); + div.appendChild(gears); + div.appendChild(button); + div.appendChild(button2); + div.appendChild(button3); + if (SUPPORTS_LOCAL_STORAGE) { + var explain = document.getElementById('dg-local-explain'); + var localStorageCheckBox = document.getElementById('dg-local-storage'); + var saveLocally = document.getElementById('dg-save-locally'); + saveLocally.style.display = 'block'; + if (localStorage.getItem(getLocalStorageHash(gui, 'isLocal')) === 'true') { + localStorageCheckBox.setAttribute('checked', 'checked'); + } + showHideExplain(gui, explain); + dom.bind(localStorageCheckBox, 'change', function () { + gui.useLocalStorage = !gui.useLocalStorage; + showHideExplain(gui, explain); + }); + } + var newConstructorTextArea = document.getElementById('dg-new-constructor'); + dom.bind(newConstructorTextArea, 'keydown', function (e) { + if (e.metaKey && (e.which === 67 || e.keyCode === 67)) { + SAVE_DIALOGUE.hide(); + } + }); + dom.bind(gears, 'click', function () { + newConstructorTextArea.innerHTML = JSON.stringify(gui.getSaveObject(), undefined, 2); + SAVE_DIALOGUE.show(); + newConstructorTextArea.focus(); + newConstructorTextArea.select(); + }); + dom.bind(button, 'click', function () { + gui.save(); + }); + dom.bind(button2, 'click', function () { + var presetName = prompt('Enter a new preset name.'); + if (presetName) { + gui.saveAs(presetName); + } + }); + dom.bind(button3, 'click', function () { + gui.revert(); + }); +} +function addResizeHandle(gui) { + var pmouseX = void 0; + gui.__resize_handle = document.createElement('div'); + Common.extend(gui.__resize_handle.style, { + width: '6px', + marginLeft: '-3px', + height: '200px', + cursor: 'ew-resize', + position: 'absolute' + }); + function drag(e) { + e.preventDefault(); + gui.width += pmouseX - e.clientX; + gui.onResize(); + pmouseX = e.clientX; + return false; + } + function dragStop() { + dom.removeClass(gui.__closeButton, GUI.CLASS_DRAG); + dom.unbind(window, 'mousemove', drag); + dom.unbind(window, 'mouseup', dragStop); + } + function dragStart(e) { + e.preventDefault(); + pmouseX = e.clientX; + dom.addClass(gui.__closeButton, GUI.CLASS_DRAG); + dom.bind(window, 'mousemove', drag); + dom.bind(window, 'mouseup', dragStop); + return false; + } + dom.bind(gui.__resize_handle, 'mousedown', dragStart); + dom.bind(gui.__closeButton, 'mousedown', dragStart); + gui.domElement.insertBefore(gui.__resize_handle, gui.domElement.firstElementChild); +} +function setWidth(gui, w) { + gui.domElement.style.width = w + 'px'; + if (gui.__save_row && gui.autoPlace) { + gui.__save_row.style.width = w + 'px'; + } + if (gui.__closeButton) { + gui.__closeButton.style.width = w + 'px'; + } +} +function getCurrentPreset(gui, useInitialValues) { + var toReturn = {}; + Common.each(gui.__rememberedObjects, function (val, index) { + var savedValues = {}; + var controllerMap = gui.__rememberedObjectIndecesToControllers[index]; + Common.each(controllerMap, function (controller, property) { + savedValues[property] = useInitialValues ? controller.initialValue : controller.getValue(); + }); + toReturn[index] = savedValues; + }); + return toReturn; +} +function setPresetSelectIndex(gui) { + for (var index = 0; index < gui.__preset_select.length; index++) { + if (gui.__preset_select[index].value === gui.preset) { + gui.__preset_select.selectedIndex = index; + } + } +} +function updateDisplays(controllerArray) { + if (controllerArray.length !== 0) { + requestAnimationFrame$1.call(window, function () { + updateDisplays(controllerArray); + }); + } + Common.each(controllerArray, function (c) { + c.updateDisplay(); + }); +} + +var color = { + Color: Color, + math: ColorMath, + interpret: interpret +}; +var controllers = { + Controller: Controller, + BooleanController: BooleanController, + OptionController: OptionController, + StringController: StringController, + NumberController: NumberController, + NumberControllerBox: NumberControllerBox, + NumberControllerSlider: NumberControllerSlider, + FunctionController: FunctionController, + ColorController: ColorController +}; +var dom$1 = { dom: dom }; +var gui = { GUI: GUI }; +var GUI$1 = GUI; +var index = { + color: color, + controllers: controllers, + dom: dom$1, + gui: gui, + GUI: GUI$1 +}; + + +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (index); +//# sourceMappingURL=dat.gui.module.js.map + + +/***/ }), + +/***/ "../../node_modules/park-miller/index.js": +/*!***********************************************!*\ + !*** ../../node_modules/park-miller/index.js ***! + \***********************************************/ +/***/ ((module) => { + + +const MAX_INT32 = 2147483647; +const MINSTD = 16807; + +class ParkMiller { + constructor(seed) { + if (!Number.isInteger(seed)) { + throw new TypeError('Expected `seed` to be a `integer`'); + } + + this._seed = seed % MAX_INT32; + + if (this._seed <= 0) { + this._seed += (MAX_INT32 - 1); + } + } + + integer() { + this._seed *= MINSTD; + this._seed %= MAX_INT32; + return this._seed; + } + + integerInRange(min, max) { + return Math.round(this.floatInRange(min, max)); + } + + float() { + return (this.integer() - 1) / (MAX_INT32 - 1); + } + + floatInRange(min, max) { + return min + ((max - min) * this.float()); + } + + boolean() { + return this.integer() % 2 === 0; + } +} + +module.exports = ParkMiller; + + +/***/ }), + +/***/ "./canvas.ts": +/*!*******************!*\ + !*** ./canvas.ts ***! + \*******************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createCanvas: () => (/* binding */ createCanvas), +/* harmony export */ drawOptions: () => (/* binding */ drawOptions) +/* harmony export */ }); +/* harmony import */ var _snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/draw/drawWorld */ "../draw/drawWorld.ts"); + +const drawOptions = { + sizeDotBorderRadius: 2, + sizeCell: 16, + sizeDot: 12, + colorDotBorder: "#1b1f230a", + colorDots: { + 1: "#9be9a8", + 2: "#40c463", + 3: "#30a14e", + 4: "#216e39", + }, + colorEmpty: "#ebedf0", + colorSnake: "purple", + dark: { + colorEmpty: "#161b22", + colorDots: { 1: "#01311f", 2: "#034525", 3: "#0f6d31", 4: "#00c647" }, + }, +}; +const getPointedCell = (canvas) => ({ pageX, pageY }) => { + const { left, top } = canvas.getBoundingClientRect(); + const x = Math.floor((pageX - left) / drawOptions.sizeCell) - 1; + const y = Math.floor((pageY - top) / drawOptions.sizeCell) - 2; + return { x, y }; +}; +const createCanvas = ({ width, height, }) => { + const canvas = document.createElement("canvas"); + const upscale = 2; + const w = drawOptions.sizeCell * (width + 4); + const h = drawOptions.sizeCell * (height + 4) + 200; + canvas.width = w * upscale; + canvas.height = h * upscale; + canvas.style.width = w + "px"; + canvas.style.height = h + "px"; + canvas.style.display = "block"; + // canvas.style.pointerEvents = "none"; + const cellInfo = document.createElement("div"); + cellInfo.style.height = "20px"; + document.body.appendChild(cellInfo); + document.body.appendChild(canvas); + canvas.addEventListener("mousemove", (e) => { + const { x, y } = getPointedCell(canvas)(e); + cellInfo.innerText = [x, y] + .map((u) => u.toString().padStart(2, " ")) + .join(" / "); + }); + const ctx = canvas.getContext("2d"); + ctx.scale(upscale, upscale); + const draw = (grid, snake, stack) => { + ctx.clearRect(0, 0, 9999, 9999); + (0,_snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__.drawWorld)(ctx, grid, null, snake, stack, drawOptions); + }; + const drawLerp = (grid, snake0, snake1, stack, k) => { + ctx.clearRect(0, 0, 9999, 9999); + (0,_snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__.drawLerpWorld)(ctx, grid, null, snake0, snake1, stack, k, drawOptions); + }; + const highlightCell = (x, y, color = "orange") => { + ctx.fillStyle = color; + ctx.beginPath(); + ctx.fillRect((1 + x + 0.5) * 16 - 2, (2 + y + 0.5) * 16 - 2, 4, 4); + }; + return { + draw, + drawLerp, + highlightCell, + canvas, + getPointedCell: getPointedCell(canvas), + ctx, + }; +}; + + +/***/ }), + +/***/ "./menu.ts": +/*!*****************!*\ + !*** ./menu.ts ***! + \*****************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ gui: () => (/* binding */ gui) +/* harmony export */ }); +/* harmony import */ var dat_gui__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! dat.gui */ "../../node_modules/dat.gui/build/dat.gui.module.js"); +/* harmony import */ var _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/__fixtures__/grid */ "../types/__fixtures__/grid.ts"); +/* harmony import */ var _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/__fixtures__/snake */ "../types/__fixtures__/snake.ts"); +/* harmony import */ var _sample__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sample */ "./sample.ts"); + + + + +const demos = __webpack_require__(/*! ./demo.json */ "./demo.json"); +const gui = new dat_gui__WEBPACK_IMPORTED_MODULE_0__.GUI(); +const config = { + snake: Object.entries(_snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__).find(([_, s]) => s === _sample__WEBPACK_IMPORTED_MODULE_3__.snake)[0], + grid: Object.entries(_snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__).find(([_, s]) => s === _sample__WEBPACK_IMPORTED_MODULE_3__.grid)[0], + demo: demos[0], +}; +{ + const d = window.location.pathname.match(/(\w+)\.html/); + if (d && demos.includes(d[1])) + config.demo = d[1]; +} +const onChange = () => { + const search = new URLSearchParams({ + snake: config.snake, + grid: config.grid, + }).toString(); + const url = new URL(config.demo + ".html?" + search, window.location.href).toString(); + window.location.href = url; +}; +gui.add(config, "demo", demos).onChange(onChange); +gui.add(config, "grid", Object.keys(_snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__)).onChange(onChange); +gui.add(config, "snake", Object.keys(_snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__)).onChange(onChange); + + +/***/ }), + +/***/ "./sample.ts": +/*!*******************!*\ + !*** ./sample.ts ***! + \*******************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ grid: () => (/* binding */ grid), +/* harmony export */ snake: () => (/* binding */ snake) +/* harmony export */ }); +/* harmony import */ var _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/__fixtures__/grid */ "../types/__fixtures__/grid.ts"); +/* harmony import */ var _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/__fixtures__/snake */ "../types/__fixtures__/snake.ts"); + + +const sp = new URLSearchParams(window.location.search); +const gLabel = sp.get("grid") || "simple"; +const sLabel = sp.get("snake") || "snake3"; +//@ts-ignore +const grid = _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__[gLabel] || _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__.simple; +//@ts-ignore +const snake = _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__[sLabel] || _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__.snake3; + + +/***/ }), + +/***/ "../draw/drawGrid.ts": +/*!***************************!*\ + !*** ../draw/drawGrid.ts ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawGrid: () => (/* binding */ drawGrid) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _pathRoundedRect__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./pathRoundedRect */ "../draw/pathRoundedRect.ts"); + + +const drawGrid = (ctx, grid, cells, o) => { + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + if (!cells || cells.some((c) => c.x === x && c.y === y)) { + const c = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + // @ts-ignore + const color = !c ? o.colorEmpty : o.colorDots[c]; + ctx.save(); + ctx.translate(x * o.sizeCell + (o.sizeCell - o.sizeDot) / 2, y * o.sizeCell + (o.sizeCell - o.sizeDot) / 2); + ctx.fillStyle = color; + ctx.strokeStyle = o.colorDotBorder; + ctx.lineWidth = 1; + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_1__.pathRoundedRect)(ctx, o.sizeDot, o.sizeDot, o.sizeDotBorderRadius); + ctx.fill(); + ctx.stroke(); + ctx.closePath(); + ctx.restore(); + } + } +}; + + +/***/ }), + +/***/ "../draw/drawSnake.ts": +/*!****************************!*\ + !*** ../draw/drawSnake.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawSnake: () => (/* binding */ drawSnake), +/* harmony export */ drawSnakeLerp: () => (/* binding */ drawSnakeLerp) +/* harmony export */ }); +/* harmony import */ var _pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./pathRoundedRect */ "../draw/pathRoundedRect.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); + + +const drawSnake = (ctx, snake, o) => { + const cells = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.snakeToCells)(snake); + for (let i = 0; i < cells.length; i++) { + const u = (i + 1) * 0.6; + ctx.save(); + ctx.fillStyle = o.colorSnake; + ctx.translate(cells[i].x * o.sizeCell + u, cells[i].y * o.sizeCell + u); + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__.pathRoundedRect)(ctx, o.sizeCell - u * 2, o.sizeCell - u * 2, (o.sizeCell - u * 2) * 0.25); + ctx.fill(); + ctx.restore(); + } +}; +const lerp = (k, a, b) => (1 - k) * a + k * b; +const clamp = (x, a, b) => Math.max(a, Math.min(b, x)); +const drawSnakeLerp = (ctx, snake0, snake1, k, o) => { + const m = 0.8; + const n = snake0.length / 2; + for (let i = 0; i < n; i++) { + const u = (i + 1) * 0.6 * (o.sizeCell / 16); + const a = (1 - m) * (i / Math.max(n - 1, 1)); + const ki = clamp((k - a) / m, 0, 1); + const x = lerp(ki, snake0[i * 2 + 0], snake1[i * 2 + 0]) - 2; + const y = lerp(ki, snake0[i * 2 + 1], snake1[i * 2 + 1]) - 2; + ctx.save(); + ctx.fillStyle = o.colorSnake; + ctx.translate(x * o.sizeCell + u, y * o.sizeCell + u); + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__.pathRoundedRect)(ctx, o.sizeCell - u * 2, o.sizeCell - u * 2, (o.sizeCell - u * 2) * 0.25); + ctx.fill(); + ctx.restore(); + } +}; + + +/***/ }), + +/***/ "../draw/drawWorld.ts": +/*!****************************!*\ + !*** ../draw/drawWorld.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawLerpWorld: () => (/* binding */ drawLerpWorld), +/* harmony export */ drawStack: () => (/* binding */ drawStack), +/* harmony export */ drawWorld: () => (/* binding */ drawWorld), +/* harmony export */ getCanvasWorldSize: () => (/* binding */ getCanvasWorldSize) +/* harmony export */ }); +/* harmony import */ var _drawGrid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./drawGrid */ "../draw/drawGrid.ts"); +/* harmony import */ var _drawSnake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./drawSnake */ "../draw/drawSnake.ts"); + + +const drawStack = (ctx, stack, max, width, o) => { + ctx.save(); + const m = width / max; + for (let i = 0; i < stack.length; i++) { + // @ts-ignore + ctx.fillStyle = o.colorDots[stack[i]]; + ctx.fillRect(i * m, 0, m + width * 0.005, 10); + } + ctx.restore(); +}; +const drawWorld = (ctx, grid, cells, snake, stack, o) => { + ctx.save(); + ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); + (0,_drawGrid__WEBPACK_IMPORTED_MODULE_0__.drawGrid)(ctx, grid, cells, o); + (0,_drawSnake__WEBPACK_IMPORTED_MODULE_1__.drawSnake)(ctx, snake, o); + ctx.restore(); + ctx.save(); + ctx.translate(o.sizeCell, (grid.height + 4) * o.sizeCell); + const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length); + drawStack(ctx, stack, max, grid.width * o.sizeCell, o); + ctx.restore(); + // ctx.save(); + // ctx.translate(o.sizeCell + 100, (grid.height + 4) * o.sizeCell + 100); + // ctx.scale(0.6, 0.6); + // drawCircleStack(ctx, stack, o); + // ctx.restore(); +}; +const drawLerpWorld = (ctx, grid, cells, snake0, snake1, stack, k, o) => { + ctx.save(); + ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); + (0,_drawGrid__WEBPACK_IMPORTED_MODULE_0__.drawGrid)(ctx, grid, cells, o); + (0,_drawSnake__WEBPACK_IMPORTED_MODULE_1__.drawSnakeLerp)(ctx, snake0, snake1, k, o); + ctx.translate(0, (grid.height + 2) * o.sizeCell); + const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length); + drawStack(ctx, stack, max, grid.width * o.sizeCell, o); + ctx.restore(); +}; +const getCanvasWorldSize = (grid, o) => { + const width = o.sizeCell * (grid.width + 2); + const height = o.sizeCell * (grid.height + 4) + 30; + return { width, height }; +}; + + +/***/ }), + +/***/ "../draw/pathRoundedRect.ts": +/*!**********************************!*\ + !*** ../draw/pathRoundedRect.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ pathRoundedRect: () => (/* binding */ pathRoundedRect) +/* harmony export */ }); +const pathRoundedRect = (ctx, width, height, borderRadius) => { + ctx.moveTo(borderRadius, 0); + ctx.arcTo(width, 0, width, height, borderRadius); + ctx.arcTo(width, height, 0, height, borderRadius); + ctx.arcTo(0, height, 0, 0, borderRadius); + ctx.arcTo(0, 0, width, 0, borderRadius); +}; + + +/***/ }), + +/***/ "../solver/getBestTunnel.ts": +/*!**********************************!*\ + !*** ../solver/getBestTunnel.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getBestTunnel: () => (/* binding */ getBestTunnel) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); +/* harmony import */ var _utils_sortPush__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils/sortPush */ "../solver/utils/sortPush.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _outside__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./outside */ "../solver/outside.ts"); +/* harmony import */ var _tunnel__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./tunnel */ "../solver/tunnel.ts"); + + + + + + +const getColorSafe = (grid, x, y) => (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) ? (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) : 0; +const setEmptySafe = (grid, x, y) => { + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y)) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); +}; +const unwrap = (m) => !m + ? [] + : [...unwrap(m.parent), { x: (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadX)(m.snake), y: (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadY)(m.snake) }]; +/** + * returns the path to reach the outside which contains the least color cell + */ +const getSnakeEscapePath = (grid, outside, snake0, color) => { + const openList = [{ snake: snake0, w: 0 }]; + const closeList = []; + while (openList[0]) { + const o = openList.shift(); + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadX)(o.snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadY)(o.snake); + if ((0,_outside__WEBPACK_IMPORTED_MODULE_4__.isOutside)(outside, x, y)) + return unwrap(o); + for (const a of _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4) { + const c = getColorSafe(grid, x + a.x, y + a.y); + if (c <= color && !(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.snakeWillSelfCollide)(o.snake, a.x, a.y)) { + const snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.nextSnake)(o.snake, a.x, a.y); + if (!closeList.some((s0) => (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.snakeEquals)(s0, snake))) { + const w = o.w + 1 + +(c === color) * 1000; + (0,_utils_sortPush__WEBPACK_IMPORTED_MODULE_2__.sortPush)(openList, { snake, w, parent: o }, (a, b) => a.w - b.w); + closeList.push(snake); + } + } + } + } + return null; +}; +/** + * compute the best tunnel to get to the cell and back to the outside ( best = less usage of ) + * + * notice that it's one of the best tunnels, more with the same score could exist + */ +const getBestTunnel = (grid, outside, x, y, color, snakeN) => { + const c = { x, y }; + const snake0 = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.createSnakeFromCells)(Array.from({ length: snakeN }, () => c)); + const one = getSnakeEscapePath(grid, outside, snake0, color); + if (!one) + return null; + // get the position of the snake if it was going to leave the x,y cell + const snakeICells = one.slice(0, snakeN); + while (snakeICells.length < snakeN) + snakeICells.push(snakeICells[snakeICells.length - 1]); + const snakeI = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.createSnakeFromCells)(snakeICells); + // remove from the grid the colors that one eat + const gridI = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.copyGrid)(grid); + for (const { x, y } of one) + setEmptySafe(gridI, x, y); + const two = getSnakeEscapePath(gridI, outside, snakeI, color); + if (!two) + return null; + one.shift(); + one.reverse(); + one.push(...two); + (0,_tunnel__WEBPACK_IMPORTED_MODULE_5__.trimTunnelStart)(grid, one); + (0,_tunnel__WEBPACK_IMPORTED_MODULE_5__.trimTunnelEnd)(grid, one); + return one; +}; + + +/***/ }), + +/***/ "../solver/outside.ts": +/*!****************************!*\ + !*** ../solver/outside.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createOutside: () => (/* binding */ createOutside), +/* harmony export */ fillOutside: () => (/* binding */ fillOutside), +/* harmony export */ isOutside: () => (/* binding */ isOutside) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); + + +const createOutside = (grid, color = 0) => { + const outside = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.createEmptyGrid)(grid.width, grid.height); + for (let x = outside.width; x--;) + for (let y = outside.height; y--;) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(outside, x, y, 1); + fillOutside(outside, grid, color); + return outside; +}; +const fillOutside = (outside, grid, color = 0) => { + let changed = true; + while (changed) { + changed = false; + for (let x = outside.width; x--;) + for (let y = outside.height; y--;) + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) <= color && + !isOutside(outside, x, y) && + _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4.some((a) => isOutside(outside, x + a.x, y + a.y))) { + changed = true; + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(outside, x, y); + } + } + return outside; +}; +const isOutside = (outside, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(outside, x, y) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(outside, x, y)); + + +/***/ }), + +/***/ "../solver/tunnel.ts": +/*!***************************!*\ + !*** ../solver/tunnel.ts ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getTunnelPath: () => (/* binding */ getTunnelPath), +/* harmony export */ trimTunnelEnd: () => (/* binding */ trimTunnelEnd), +/* harmony export */ trimTunnelStart: () => (/* binding */ trimTunnelStart), +/* harmony export */ updateTunnel: () => (/* binding */ updateTunnel) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); + + +/** + * get the sequence of snake to cross the tunnel + */ +const getTunnelPath = (snake0, tunnel) => { + const chain = []; + let snake = snake0; + for (let i = 1; i < tunnel.length; i++) { + const dx = tunnel[i].x - (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake); + const dy = tunnel[i].y - (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake); + snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.nextSnake)(snake, dx, dy); + chain.unshift(snake); + } + return chain; +}; +/** + * assuming the grid change and the colors got deleted, update the tunnel + */ +const updateTunnel = (grid, tunnel, toDelete) => { + while (tunnel.length) { + const { x, y } = tunnel[0]; + if (isEmptySafe(grid, x, y) || + toDelete.some((p) => p.x === x && p.y === y)) { + tunnel.shift(); + } + else + break; + } + while (tunnel.length) { + const { x, y } = tunnel[tunnel.length - 1]; + if (isEmptySafe(grid, x, y) || + toDelete.some((p) => p.x === x && p.y === y)) { + tunnel.pop(); + } + else + break; + } +}; +const isEmptySafe = (grid, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y)); +/** + * remove empty cell from start + */ +const trimTunnelStart = (grid, tunnel) => { + while (tunnel.length) { + const { x, y } = tunnel[0]; + if (isEmptySafe(grid, x, y)) + tunnel.shift(); + else + break; + } +}; +/** + * remove empty cell from end + */ +const trimTunnelEnd = (grid, tunnel) => { + while (tunnel.length) { + const i = tunnel.length - 1; + const { x, y } = tunnel[i]; + if (isEmptySafe(grid, x, y) || + tunnel.findIndex((p) => p.x === x && p.y === y) < i) + tunnel.pop(); + else + break; + } +}; + + +/***/ }), + +/***/ "../solver/utils/sortPush.ts": +/*!***********************************!*\ + !*** ../solver/utils/sortPush.ts ***! + \***********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ sortPush: () => (/* binding */ sortPush) +/* harmony export */ }); +const sortPush = (arr, x, sortFn) => { + let a = 0; + let b = arr.length; + if (arr.length === 0 || sortFn(x, arr[a]) <= 0) { + arr.unshift(x); + return; + } + while (b - a > 1) { + const e = Math.ceil((a + b) / 2); + const s = sortFn(x, arr[e]); + if (s === 0) + a = b = e; + else if (s > 0) + a = e; + else + b = e; + } + const e = Math.ceil((a + b) / 2); + arr.splice(e, 0, x); +}; + + +/***/ }), + +/***/ "../types/__fixtures__/createFromAscii.ts": +/*!************************************************!*\ + !*** ../types/__fixtures__/createFromAscii.ts ***! + \************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createFromAscii: () => (/* binding */ createFromAscii) +/* harmony export */ }); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../grid */ "../types/grid.ts"); + +const createFromAscii = (ascii) => { + const a = ascii.split("\n"); + if (a[0] === "") + a.shift(); + const height = a.length; + const width = Math.max(...a.map((r) => r.length)); + const grid = (0,_grid__WEBPACK_IMPORTED_MODULE_0__.createEmptyGrid)(width, height); + for (let x = width; x--;) + for (let y = height; y--;) { + const c = a[y][x]; + const color = (c === "#" && 3) || (c === "@" && 2) || (c === "." && 1) || +c; + if (c) + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(grid, x, y, color); + } + return grid; +}; + + +/***/ }), + +/***/ "../types/__fixtures__/grid.ts": +/*!*************************************!*\ + !*** ../types/__fixtures__/grid.ts ***! + \*************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ closedO: () => (/* binding */ closedO), +/* harmony export */ closedP: () => (/* binding */ closedP), +/* harmony export */ closedU: () => (/* binding */ closedU), +/* harmony export */ corner: () => (/* binding */ corner), +/* harmony export */ empty: () => (/* binding */ empty), +/* harmony export */ enclaveBorder: () => (/* binding */ enclaveBorder), +/* harmony export */ enclaveK: () => (/* binding */ enclaveK), +/* harmony export */ enclaveM: () => (/* binding */ enclaveM), +/* harmony export */ enclaveN: () => (/* binding */ enclaveN), +/* harmony export */ enclaveU: () => (/* binding */ enclaveU), +/* harmony export */ realistic: () => (/* binding */ realistic), +/* harmony export */ realisticFull: () => (/* binding */ realisticFull), +/* harmony export */ simple: () => (/* binding */ simple), +/* harmony export */ small: () => (/* binding */ small), +/* harmony export */ smallFull: () => (/* binding */ smallFull), +/* harmony export */ smallPacked: () => (/* binding */ smallPacked), +/* harmony export */ tunnels: () => (/* binding */ tunnels) +/* harmony export */ }); +/* harmony import */ var park_miller__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! park-miller */ "../../node_modules/park-miller/index.js"); +/* harmony import */ var park_miller__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(park_miller__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../grid */ "../types/grid.ts"); +/* harmony import */ var _randomlyFillGrid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../randomlyFillGrid */ "../types/randomlyFillGrid.ts"); +/* harmony import */ var _createFromAscii__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./createFromAscii */ "../types/__fixtures__/createFromAscii.ts"); + + + + +const colors = [1, 2, 3]; +// empty small grid +const empty = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +// empty small grid with a unique color at the middle +const simple = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(simple, 2, 2, 1); +// empty small grid with color at each corner +const corner = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 0, 4, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 4, 0, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 4, 4, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 0, 0, 1); +const enclaveN = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #.# + # + +`); +const enclaveBorder = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + #.# + # + +`); +const enclaveM = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### + # # + # . # + # # + # # +`); +const enclaveK = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + # .# + # # + # # + # # +`); +const enclaveU = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + #..# + #..# + #.# + # # . +`); +const closedP = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### + ##.# + ## # + ## +`); +const closedU = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + #..# + #..# + #.# + ### +`); +const closedO = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ####### + # # + # . # + # # + ####### +`); +const tunnels = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### ### ### + #.# #.# #.# + #.# ### # # +`); +const createRandom = (width, height, emptyP) => { + const grid = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(width, height); + const pm = new (park_miller__WEBPACK_IMPORTED_MODULE_0___default())(10); + const random = pm.integerInRange.bind(pm); + (0,_randomlyFillGrid__WEBPACK_IMPORTED_MODULE_2__.randomlyFillGrid)(grid, { colors, emptyP }, random); + return grid; +}; +// small realistic +const small = createRandom(10, 7, 3); +const smallPacked = createRandom(10, 7, 1); +const smallFull = createRandom(10, 7, 0); +// small realistic +const realistic = createRandom(52, 7, 3); +const realisticFull = createRandom(52, 7, 0); + + +/***/ }), + +/***/ "../types/__fixtures__/snake.ts": +/*!**************************************!*\ + !*** ../types/__fixtures__/snake.ts ***! + \**************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ snake1: () => (/* binding */ snake1), +/* harmony export */ snake3: () => (/* binding */ snake3), +/* harmony export */ snake4: () => (/* binding */ snake4), +/* harmony export */ snake5: () => (/* binding */ snake5), +/* harmony export */ snake9: () => (/* binding */ snake9) +/* harmony export */ }); +/* harmony import */ var _snake__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../snake */ "../types/snake.ts"); + +const create = (length) => (0,_snake__WEBPACK_IMPORTED_MODULE_0__.createSnakeFromCells)(Array.from({ length }, (_, i) => ({ x: i, y: -1 }))); +const snake1 = create(1); +const snake3 = create(3); +const snake4 = create(4); +const snake5 = create(5); +const snake9 = create(9); + + +/***/ }), + +/***/ "../types/grid.ts": +/*!************************!*\ + !*** ../types/grid.ts ***! + \************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copyGrid: () => (/* binding */ copyGrid), +/* harmony export */ createEmptyGrid: () => (/* binding */ createEmptyGrid), +/* harmony export */ getColor: () => (/* binding */ getColor), +/* harmony export */ gridEquals: () => (/* binding */ gridEquals), +/* harmony export */ isEmpty: () => (/* binding */ isEmpty), +/* harmony export */ isGridEmpty: () => (/* binding */ isGridEmpty), +/* harmony export */ isInside: () => (/* binding */ isInside), +/* harmony export */ isInsideLarge: () => (/* binding */ isInsideLarge), +/* harmony export */ setColor: () => (/* binding */ setColor), +/* harmony export */ setColorEmpty: () => (/* binding */ setColorEmpty) +/* harmony export */ }); +const isInside = (grid, x, y) => x >= 0 && y >= 0 && x < grid.width && y < grid.height; +const isInsideLarge = (grid, m, x, y) => x >= -m && y >= -m && x < grid.width + m && y < grid.height + m; +const copyGrid = ({ width, height, data }) => ({ + width, + height, + data: Uint8Array.from(data), +}); +const getIndex = (grid, x, y) => x * grid.height + y; +const getColor = (grid, x, y) => grid.data[getIndex(grid, x, y)]; +const isEmpty = (color) => color === 0; +const setColor = (grid, x, y, color) => { + grid.data[getIndex(grid, x, y)] = color || 0; +}; +const setColorEmpty = (grid, x, y) => { + setColor(grid, x, y, 0); +}; +/** + * return true if the grid is empty + */ +const isGridEmpty = (grid) => grid.data.every((x) => x === 0); +const gridEquals = (a, b) => a.data.every((_, i) => a.data[i] === b.data[i]); +const createEmptyGrid = (width, height) => ({ + width, + height, + data: new Uint8Array(width * height), +}); + + +/***/ }), + +/***/ "../types/point.ts": +/*!*************************!*\ + !*** ../types/point.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ around4: () => (/* binding */ around4), +/* harmony export */ pointEquals: () => (/* binding */ pointEquals) +/* harmony export */ }); +const around4 = [ + { x: 1, y: 0 }, + { x: 0, y: -1 }, + { x: -1, y: 0 }, + { x: 0, y: 1 }, +]; +const pointEquals = (a, b) => a.x === b.x && a.y === b.y; + + +/***/ }), + +/***/ "../types/randomlyFillGrid.ts": +/*!************************************!*\ + !*** ../types/randomlyFillGrid.ts ***! + \************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ randomlyFillGrid: () => (/* binding */ randomlyFillGrid) +/* harmony export */ }); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./grid */ "../types/grid.ts"); + +const defaultRand = (a, b) => Math.floor(Math.random() * (b - a + 1)) + a; +const randomlyFillGrid = (grid, { colors = [1, 2, 3], emptyP = 2, } = {}, rand = defaultRand) => { + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + const k = rand(-emptyP, colors.length - 1); + if (k >= 0) + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(grid, x, y, colors[k]); + else + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); + } +}; + + +/***/ }), + +/***/ "../types/snake.ts": +/*!*************************!*\ + !*** ../types/snake.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copySnake: () => (/* binding */ copySnake), +/* harmony export */ createSnakeFromCells: () => (/* binding */ createSnakeFromCells), +/* harmony export */ getHeadX: () => (/* binding */ getHeadX), +/* harmony export */ getHeadY: () => (/* binding */ getHeadY), +/* harmony export */ getSnakeLength: () => (/* binding */ getSnakeLength), +/* harmony export */ nextSnake: () => (/* binding */ nextSnake), +/* harmony export */ snakeEquals: () => (/* binding */ snakeEquals), +/* harmony export */ snakeToCells: () => (/* binding */ snakeToCells), +/* harmony export */ snakeWillSelfCollide: () => (/* binding */ snakeWillSelfCollide) +/* harmony export */ }); +const getHeadX = (snake) => snake[0] - 2; +const getHeadY = (snake) => snake[1] - 2; +const getSnakeLength = (snake) => snake.length / 2; +const copySnake = (snake) => snake.slice(); +const snakeEquals = (a, b) => { + for (let i = 0; i < a.length; i++) + if (a[i] !== b[i]) + return false; + return true; +}; +/** + * return a copy of the next snake, considering that dx, dy is the direction + */ +const nextSnake = (snake, dx, dy) => { + const copy = new Uint8Array(snake.length); + for (let i = 2; i < snake.length; i++) + copy[i] = snake[i - 2]; + copy[0] = snake[0] + dx; + copy[1] = snake[1] + dy; + return copy; +}; +/** + * return true if the next snake will collide with itself + */ +const snakeWillSelfCollide = (snake, dx, dy) => { + const nx = snake[0] + dx; + const ny = snake[1] + dy; + for (let i = 2; i < snake.length - 2; i += 2) + if (snake[i + 0] === nx && snake[i + 1] === ny) + return true; + return false; +}; +const snakeToCells = (snake) => Array.from({ length: snake.length / 2 }, (_, i) => ({ + x: snake[i * 2 + 0] - 2, + y: snake[i * 2 + 1] - 2, +})); +const createSnakeFromCells = (points) => { + const snake = new Uint8Array(points.length * 2); + for (let i = points.length; i--;) { + snake[i * 2 + 0] = points[i].x + 2; + snake[i * 2 + 1] = points[i].y + 2; + } + return snake; +}; + + +/***/ }), + +/***/ "./demo.json": +/*!*******************!*\ + !*** ./demo.json ***! + \*******************/ +/***/ ((module) => { + +module.exports = JSON.parse('["interactive","getBestRoute","getBestTunnel","outside","getPathToPose","getPathTo","svg"]'); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ (() => { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = (module) => { +/******/ var getter = module && module.__esModule ? +/******/ () => (module['default']) : +/******/ () => (module); +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +/*!*******************************!*\ + !*** ./demo.getBestTunnel.ts ***! + \*******************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _menu__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./menu */ "./menu.ts"); +/* harmony import */ var _canvas__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./canvas */ "./canvas.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _sample__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sample */ "./sample.ts"); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_solver_getBestTunnel__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @snk/solver/getBestTunnel */ "../solver/getBestTunnel.ts"); +/* harmony import */ var _snk_solver_outside__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @snk/solver/outside */ "../solver/outside.ts"); +var _a, _b; + + + + + + + +const { canvas, ctx, draw, highlightCell } = (0,_canvas__WEBPACK_IMPORTED_MODULE_1__.createCanvas)(_sample__WEBPACK_IMPORTED_MODULE_3__.grid); +document.body.appendChild(canvas); +const ones = []; +for (let x = 0; x < _sample__WEBPACK_IMPORTED_MODULE_3__.grid.width; x++) + for (let y = 0; y < _sample__WEBPACK_IMPORTED_MODULE_3__.grid.height; y++) + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_4__.getColor)(_sample__WEBPACK_IMPORTED_MODULE_3__.grid, x, y) === 1) + ones.push({ x, y }); +const tunnels = ones.map(({ x, y }) => ({ + x, + y, + tunnel: (0,_snk_solver_getBestTunnel__WEBPACK_IMPORTED_MODULE_5__.getBestTunnel)(_sample__WEBPACK_IMPORTED_MODULE_3__.grid, (0,_snk_solver_outside__WEBPACK_IMPORTED_MODULE_6__.createOutside)(_sample__WEBPACK_IMPORTED_MODULE_3__.grid), x, y, 3, (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.getSnakeLength)(_sample__WEBPACK_IMPORTED_MODULE_3__.snake)), +})); +const onChange = () => { + const k = +inputK.value; + const i = +inputI.value; + ctx.clearRect(0, 0, 9999, 9999); + if (!tunnels[k]) + return; + const { x, y, tunnel } = tunnels[k]; + draw(_sample__WEBPACK_IMPORTED_MODULE_3__.grid, _sample__WEBPACK_IMPORTED_MODULE_3__.snake, []); + highlightCell(x, y, "red"); + if (tunnel) { + tunnel.forEach(({ x, y }) => highlightCell(x, y)); + highlightCell(x, y, "red"); + highlightCell(tunnel[i].x, tunnel[i].y, "blue"); + } +}; +const inputK = document.createElement("input"); +inputK.type = "range"; +inputK.value = 0; +inputK.step = 1; +inputK.min = 0; +inputK.max = tunnels ? tunnels.length - 1 : 0; +inputK.style.width = "90%"; +inputK.style.padding = "20px 0"; +inputK.addEventListener("input", () => { + var _a, _b; + inputI.value = 0; + inputI.max = (((_b = (_a = tunnels[+inputK.value]) === null || _a === void 0 ? void 0 : _a.tunnel) === null || _b === void 0 ? void 0 : _b.length) || 1) - 1; + onChange(); +}); +document.body.append(inputK); +const inputI = document.createElement("input"); +inputI.type = "range"; +inputI.value = 0; +inputI.step = 1; +inputI.min = 0; +inputI.max = (((_b = (_a = tunnels[+inputK.value]) === null || _a === void 0 ? void 0 : _a.tunnel) === null || _b === void 0 ? void 0 : _b.length) || 1) - 1; +inputI.style.width = "90%"; +inputI.style.padding = "20px 0"; +inputI.addEventListener("input", onChange); +document.body.append(inputI); +onChange(); + +})(); + +/******/ })() +; \ No newline at end of file diff --git a/6813e0ec53a4391ce255.js b/6813e0ec53a4391ce255.js new file mode 100644 index 000000000..e9db81550 --- /dev/null +++ b/6813e0ec53a4391ce255.js @@ -0,0 +1,1273 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "../action/palettes.ts": +/*!*****************************!*\ + !*** ../action/palettes.ts ***! + \*****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ basePalettes: () => (/* binding */ basePalettes), +/* harmony export */ palettes: () => (/* binding */ palettes) +/* harmony export */ }); +const basePalettes = { + "github-light": { + colorDotBorder: "#1b1f230a", + colorDots: ["#ebedf0", "#9be9a8", "#40c463", "#30a14e", "#216e39"], + colorEmpty: "#ebedf0", + colorSnake: "purple", + }, + "github-dark": { + colorDotBorder: "#1b1f230a", + colorEmpty: "#161b22", + colorDots: ["#161b22", "#01311f", "#034525", "#0f6d31", "#00c647"], + colorSnake: "purple", + }, +}; +// aliases +const palettes = { ...basePalettes }; +palettes["github"] = palettes["github-light"]; +palettes["default"] = palettes["github"]; + + +/***/ }), + +/***/ "../action/userContributionToGrid.ts": +/*!*******************************************!*\ + !*** ../action/userContributionToGrid.ts ***! + \*******************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ userContributionToGrid: () => (/* binding */ userContributionToGrid) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); + +const userContributionToGrid = (cells) => { + const width = Math.max(0, ...cells.map((c) => c.x)) + 1; + const height = Math.max(0, ...cells.map((c) => c.y)) + 1; + const grid = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.createEmptyGrid)(width, height); + for (const c of cells) { + if (c.level > 0) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(grid, c.x, c.y, c.level); + else + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, c.x, c.y); + } + return grid; +}; + + +/***/ }), + +/***/ "./springUtils.ts": +/*!************************!*\ + !*** ./springUtils.ts ***! + \************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ clamp: () => (/* binding */ clamp), +/* harmony export */ isStable: () => (/* binding */ isStable), +/* harmony export */ isStableAndBound: () => (/* binding */ isStableAndBound), +/* harmony export */ stepSpring: () => (/* binding */ stepSpring) +/* harmony export */ }); +const epsilon = 0.01; +const clamp = (a, b) => (x) => Math.max(a, Math.min(b, x)); +/** + * step the spring, mutate the state to reflect the state at t+dt + * + */ +const stepSpringOne = (s, { tension, friction, maxVelocity = Infinity, }, target, dt = 1 / 60) => { + const a = -tension * (s.x - target) - friction * s.v; + s.v += a * dt; + s.v = clamp(-maxVelocity / dt, maxVelocity / dt)(s.v); + s.x += s.v * dt; +}; +/** + * return true if the spring is to be considered in a stable state + * ( close enough to the target and with a small enough velocity ) + */ +const isStable = (s, target, dt = 1 / 60) => Math.abs(s.x - target) < epsilon && Math.abs(s.v * dt) < epsilon; +const isStableAndBound = (s, target, dt) => { + const stable = isStable(s, target, dt); + if (stable) { + s.x = target; + s.v = 0; + } + return stable; +}; +const stepSpring = (s, params, target, dt = 1 / 60) => { + const interval = 1 / 60; + while (dt > 0) { + stepSpringOne(s, params, target, Math.min(interval, dt)); + // eslint-disable-next-line no-param-reassign + dt -= interval; + } +}; + + +/***/ }), + +/***/ "./worker-utils.ts": +/*!*************************!*\ + !*** ./worker-utils.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createRpcClient: () => (/* binding */ createRpcClient), +/* harmony export */ createRpcServer: () => (/* binding */ createRpcServer) +/* harmony export */ }); +const symbol = "worker-rpc__"; +const createRpcServer = (api) => self.addEventListener("message", async (event) => { + var _a; + if (((_a = event.data) === null || _a === void 0 ? void 0 : _a.symbol) === symbol) { + try { + const res = await api[event.data.methodName](...event.data.args); + self.postMessage({ symbol, key: event.data.key, res }); + } + catch (error) { + postMessage({ symbol, key: event.data.key, error: error.message }); + } + } +}); +const createRpcClient = (worker) => { + const originalTerminate = worker.terminate; + worker.terminate = () => { + worker.dispatchEvent(new Event("terminate")); + originalTerminate.call(worker); + }; + return new Proxy({}, { + get: (_, methodName) => (...args) => new Promise((resolve, reject) => { + const key = Math.random().toString(); + const onTerminate = () => { + worker.removeEventListener("terminate", onTerminate); + worker.removeEventListener("message", onMessageHandler); + reject(new Error("worker terminated")); + }; + const onMessageHandler = (event) => { + var _a; + if (((_a = event.data) === null || _a === void 0 ? void 0 : _a.symbol) === symbol && event.data.key === key) { + if (event.data.error) + reject(event.data.error); + else if (event.data.res) + resolve(event.data.res); + worker.removeEventListener("terminate", onTerminate); + worker.removeEventListener("message", onMessageHandler); + } + }; + worker.addEventListener("message", onMessageHandler); + worker.addEventListener("terminate", onTerminate); + worker.postMessage({ symbol, key, methodName, args }); + }), + }); +}; + + +/***/ }), + +/***/ "../draw/drawGrid.ts": +/*!***************************!*\ + !*** ../draw/drawGrid.ts ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawGrid: () => (/* binding */ drawGrid) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _pathRoundedRect__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./pathRoundedRect */ "../draw/pathRoundedRect.ts"); + + +const drawGrid = (ctx, grid, cells, o) => { + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + if (!cells || cells.some((c) => c.x === x && c.y === y)) { + const c = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + // @ts-ignore + const color = !c ? o.colorEmpty : o.colorDots[c]; + ctx.save(); + ctx.translate(x * o.sizeCell + (o.sizeCell - o.sizeDot) / 2, y * o.sizeCell + (o.sizeCell - o.sizeDot) / 2); + ctx.fillStyle = color; + ctx.strokeStyle = o.colorDotBorder; + ctx.lineWidth = 1; + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_1__.pathRoundedRect)(ctx, o.sizeDot, o.sizeDot, o.sizeDotBorderRadius); + ctx.fill(); + ctx.stroke(); + ctx.closePath(); + ctx.restore(); + } + } +}; + + +/***/ }), + +/***/ "../draw/drawSnake.ts": +/*!****************************!*\ + !*** ../draw/drawSnake.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawSnake: () => (/* binding */ drawSnake), +/* harmony export */ drawSnakeLerp: () => (/* binding */ drawSnakeLerp) +/* harmony export */ }); +/* harmony import */ var _pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./pathRoundedRect */ "../draw/pathRoundedRect.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); + + +const drawSnake = (ctx, snake, o) => { + const cells = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.snakeToCells)(snake); + for (let i = 0; i < cells.length; i++) { + const u = (i + 1) * 0.6; + ctx.save(); + ctx.fillStyle = o.colorSnake; + ctx.translate(cells[i].x * o.sizeCell + u, cells[i].y * o.sizeCell + u); + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__.pathRoundedRect)(ctx, o.sizeCell - u * 2, o.sizeCell - u * 2, (o.sizeCell - u * 2) * 0.25); + ctx.fill(); + ctx.restore(); + } +}; +const lerp = (k, a, b) => (1 - k) * a + k * b; +const clamp = (x, a, b) => Math.max(a, Math.min(b, x)); +const drawSnakeLerp = (ctx, snake0, snake1, k, o) => { + const m = 0.8; + const n = snake0.length / 2; + for (let i = 0; i < n; i++) { + const u = (i + 1) * 0.6 * (o.sizeCell / 16); + const a = (1 - m) * (i / Math.max(n - 1, 1)); + const ki = clamp((k - a) / m, 0, 1); + const x = lerp(ki, snake0[i * 2 + 0], snake1[i * 2 + 0]) - 2; + const y = lerp(ki, snake0[i * 2 + 1], snake1[i * 2 + 1]) - 2; + ctx.save(); + ctx.fillStyle = o.colorSnake; + ctx.translate(x * o.sizeCell + u, y * o.sizeCell + u); + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__.pathRoundedRect)(ctx, o.sizeCell - u * 2, o.sizeCell - u * 2, (o.sizeCell - u * 2) * 0.25); + ctx.fill(); + ctx.restore(); + } +}; + + +/***/ }), + +/***/ "../draw/drawWorld.ts": +/*!****************************!*\ + !*** ../draw/drawWorld.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawLerpWorld: () => (/* binding */ drawLerpWorld), +/* harmony export */ drawStack: () => (/* binding */ drawStack), +/* harmony export */ drawWorld: () => (/* binding */ drawWorld), +/* harmony export */ getCanvasWorldSize: () => (/* binding */ getCanvasWorldSize) +/* harmony export */ }); +/* harmony import */ var _drawGrid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./drawGrid */ "../draw/drawGrid.ts"); +/* harmony import */ var _drawSnake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./drawSnake */ "../draw/drawSnake.ts"); + + +const drawStack = (ctx, stack, max, width, o) => { + ctx.save(); + const m = width / max; + for (let i = 0; i < stack.length; i++) { + // @ts-ignore + ctx.fillStyle = o.colorDots[stack[i]]; + ctx.fillRect(i * m, 0, m + width * 0.005, 10); + } + ctx.restore(); +}; +const drawWorld = (ctx, grid, cells, snake, stack, o) => { + ctx.save(); + ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); + (0,_drawGrid__WEBPACK_IMPORTED_MODULE_0__.drawGrid)(ctx, grid, cells, o); + (0,_drawSnake__WEBPACK_IMPORTED_MODULE_1__.drawSnake)(ctx, snake, o); + ctx.restore(); + ctx.save(); + ctx.translate(o.sizeCell, (grid.height + 4) * o.sizeCell); + const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length); + drawStack(ctx, stack, max, grid.width * o.sizeCell, o); + ctx.restore(); + // ctx.save(); + // ctx.translate(o.sizeCell + 100, (grid.height + 4) * o.sizeCell + 100); + // ctx.scale(0.6, 0.6); + // drawCircleStack(ctx, stack, o); + // ctx.restore(); +}; +const drawLerpWorld = (ctx, grid, cells, snake0, snake1, stack, k, o) => { + ctx.save(); + ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); + (0,_drawGrid__WEBPACK_IMPORTED_MODULE_0__.drawGrid)(ctx, grid, cells, o); + (0,_drawSnake__WEBPACK_IMPORTED_MODULE_1__.drawSnakeLerp)(ctx, snake0, snake1, k, o); + ctx.translate(0, (grid.height + 2) * o.sizeCell); + const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length); + drawStack(ctx, stack, max, grid.width * o.sizeCell, o); + ctx.restore(); +}; +const getCanvasWorldSize = (grid, o) => { + const width = o.sizeCell * (grid.width + 2); + const height = o.sizeCell * (grid.height + 4) + 30; + return { width, height }; +}; + + +/***/ }), + +/***/ "../draw/pathRoundedRect.ts": +/*!**********************************!*\ + !*** ../draw/pathRoundedRect.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ pathRoundedRect: () => (/* binding */ pathRoundedRect) +/* harmony export */ }); +const pathRoundedRect = (ctx, width, height, borderRadius) => { + ctx.moveTo(borderRadius, 0); + ctx.arcTo(width, 0, width, height, borderRadius); + ctx.arcTo(width, height, 0, height, borderRadius); + ctx.arcTo(0, height, 0, 0, borderRadius); + ctx.arcTo(0, 0, width, 0, borderRadius); +}; + + +/***/ }), + +/***/ "../solver/step.ts": +/*!*************************!*\ + !*** ../solver/step.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ step: () => (/* binding */ step) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); + + +const step = (grid, stack, snake) => { + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake); + const color = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) && !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)(color)) { + stack.push(color); + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); + } +}; + + +/***/ }), + +/***/ "../svg-creator/css-utils.ts": +/*!***********************************!*\ + !*** ../svg-creator/css-utils.ts ***! + \***********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createAnimation: () => (/* binding */ createAnimation), +/* harmony export */ minifyCss: () => (/* binding */ minifyCss) +/* harmony export */ }); +const percent = (x) => parseFloat((x * 100).toFixed(2)).toString() + "%"; +const mergeKeyFrames = (keyframes) => { + var _a; + const s = new Map(); + for (const { t, style } of keyframes) { + s.set(style, [...((_a = s.get(style)) !== null && _a !== void 0 ? _a : []), t]); + } + return Array.from(s.entries()) + .map(([style, ts]) => ({ style, ts })) + .sort((a, b) => a.ts[0] - b.ts[0]); +}; +/** + * generate the keyframe animation from a list of keyframe + */ +const createAnimation = (name, keyframes) => `@keyframes ${name}{` + + mergeKeyFrames(keyframes) + .map(({ style, ts }) => ts.map(percent).join(",") + `{${style}}`) + .join("") + + "}"; +/** + * remove white spaces + */ +const minifyCss = (css) => css + .replace(/\s+/g, " ") + .replace(/.\s+[,;:{}()]/g, (a) => a.replace(/\s+/g, "")) + .replace(/[,;:{}()]\s+./g, (a) => a.replace(/\s+/g, "")) + .replace(/.\s+[,;:{}()]/g, (a) => a.replace(/\s+/g, "")) + .replace(/[,;:{}()]\s+./g, (a) => a.replace(/\s+/g, "")) + .replace(/\;\s*\}/g, "}") + .trim(); + + +/***/ }), + +/***/ "../svg-creator/grid.ts": +/*!******************************!*\ + !*** ../svg-creator/grid.ts ***! + \******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createGrid: () => (/* binding */ createGrid) +/* harmony export */ }); +/* harmony import */ var _css_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./css-utils */ "../svg-creator/css-utils.ts"); +/* harmony import */ var _xml_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./xml-utils */ "../svg-creator/xml-utils.ts"); + + +const createGrid = (cells, { sizeDotBorderRadius, sizeDot, sizeCell }, duration) => { + const svgElements = []; + const styles = [ + `.c{ + shape-rendering: geometricPrecision; + fill: var(--ce); + stroke-width: 1px; + stroke: var(--cb); + animation: none ${duration}ms linear infinite; + width: ${sizeDot}px; + height: ${sizeDot}px; + }`, + ]; + let i = 0; + for (const { x, y, color, t } of cells) { + const id = t && "c" + (i++).toString(36); + const m = (sizeCell - sizeDot) / 2; + if (t !== null && id) { + const animationName = id; + styles.push((0,_css_utils__WEBPACK_IMPORTED_MODULE_0__.createAnimation)(animationName, [ + { t: t - 0.0001, style: `fill:var(--c${color})` }, + { t: t + 0.0001, style: `fill:var(--ce)` }, + { t: 1, style: `fill:var(--ce)` }, + ]), `.c.${id}{ + fill: var(--c${color}); + animation-name: ${animationName} + }`); + } + svgElements.push((0,_xml_utils__WEBPACK_IMPORTED_MODULE_1__.h)("rect", { + class: ["c", id].filter(Boolean).join(" "), + x: x * sizeCell + m, + y: y * sizeCell + m, + rx: sizeDotBorderRadius, + ry: sizeDotBorderRadius, + })); + } + return { svgElements, styles }; +}; + + +/***/ }), + +/***/ "../svg-creator/index.ts": +/*!*******************************!*\ + !*** ../svg-creator/index.ts ***! + \*******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createSvg: () => (/* binding */ createSvg) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./snake */ "../svg-creator/snake.ts"); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./grid */ "../svg-creator/grid.ts"); +/* harmony import */ var _stack__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./stack */ "../svg-creator/stack.ts"); +/* harmony import */ var _xml_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./xml-utils */ "../svg-creator/xml-utils.ts"); +/* harmony import */ var _css_utils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./css-utils */ "../svg-creator/css-utils.ts"); + + + + + + + +const getCellsFromGrid = ({ width, height }) => Array.from({ length: width }, (_, x) => Array.from({ length: height }, (_, y) => ({ x, y }))).flat(); +const createLivingCells = (grid0, chain, cells) => { + const livingCells = (cells !== null && cells !== void 0 ? cells : getCellsFromGrid(grid0)).map(({ x, y }) => ({ + x, + y, + t: null, + color: (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid0, x, y), + })); + const grid = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.copyGrid)(grid0); + for (let i = 0; i < chain.length; i++) { + const snake = chain[i]; + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake); + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) && !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y))) { + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); + const cell = livingCells.find((c) => c.x === x && c.y === y); + cell.t = i / chain.length; + } + } + return livingCells; +}; +const createSvg = (grid, cells, chain, drawOptions, animationOptions) => { + const width = (grid.width + 2) * drawOptions.sizeCell; + const height = (grid.height + 5) * drawOptions.sizeCell; + const duration = animationOptions.frameDuration * chain.length; + const livingCells = createLivingCells(grid, chain, cells); + const elements = [ + (0,_grid__WEBPACK_IMPORTED_MODULE_3__.createGrid)(livingCells, drawOptions, duration), + (0,_stack__WEBPACK_IMPORTED_MODULE_4__.createStack)(livingCells, drawOptions, grid.width * drawOptions.sizeCell, (grid.height + 2) * drawOptions.sizeCell, duration), + (0,_snake__WEBPACK_IMPORTED_MODULE_2__.createSnake)(chain, drawOptions, duration), + ]; + const viewBox = [ + -drawOptions.sizeCell, + -drawOptions.sizeCell * 2, + width, + height, + ].join(" "); + const style = generateColorVar(drawOptions) + + elements + .map((e) => e.styles) + .flat() + .join("\n"); + const svg = [ + (0,_xml_utils__WEBPACK_IMPORTED_MODULE_5__.h)("svg", { + viewBox, + width, + height, + xmlns: "http://www.w3.org/2000/svg", + }).replace("/>", ">"), + "", + "Generated with https://github.com/Platane/snk", + "", + "", + ...elements.map((e) => e.svgElements).flat(), + "", + ].join(""); + return optimizeSvg(svg); +}; +const optimizeCss = (css) => (0,_css_utils__WEBPACK_IMPORTED_MODULE_6__.minifyCss)(css); +const optimizeSvg = (svg) => svg; +const generateColorVar = (drawOptions) => ` + :root { + --cb: ${drawOptions.colorDotBorder}; + --cs: ${drawOptions.colorSnake}; + --ce: ${drawOptions.colorEmpty}; + ${Object.entries(drawOptions.colorDots) + .map(([i, color]) => `--c${i}:${color};`) + .join("")} + } + ` + + (drawOptions.dark + ? ` + @media (prefers-color-scheme: dark) { + :root { + --cb: ${drawOptions.dark.colorDotBorder || drawOptions.colorDotBorder}; + --cs: ${drawOptions.dark.colorSnake || drawOptions.colorSnake}; + --ce: ${drawOptions.dark.colorEmpty}; + ${Object.entries(drawOptions.dark.colorDots) + .map(([i, color]) => `--c${i}:${color};`) + .join("")} + } + } +` + : ""); + + +/***/ }), + +/***/ "../svg-creator/snake.ts": +/*!*******************************!*\ + !*** ../svg-creator/snake.ts ***! + \*******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createSnake: () => (/* binding */ createSnake) +/* harmony export */ }); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _xml_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./xml-utils */ "../svg-creator/xml-utils.ts"); +/* harmony import */ var _css_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./css-utils */ "../svg-creator/css-utils.ts"); + + + +const lerp = (k, a, b) => (1 - k) * a + k * b; +const createSnake = (chain, { sizeCell, sizeDot }, duration) => { + const snakeN = chain[0] ? (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getSnakeLength)(chain[0]) : 0; + const snakeParts = Array.from({ length: snakeN }, () => []); + for (const snake of chain) { + const cells = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.snakeToCells)(snake); + for (let i = cells.length; i--;) + snakeParts[i].push(cells[i]); + } + const svgElements = snakeParts.map((_, i, { length }) => { + // compute snake part size + const dMin = sizeDot * 0.8; + const dMax = sizeCell * 0.9; + const iMax = Math.min(4, length); + const u = (1 - Math.min(i, iMax) / iMax) ** 2; + const s = lerp(u, dMin, dMax); + const m = (sizeCell - s) / 2; + const r = Math.min(4.5, (4 * s) / sizeDot); + return (0,_xml_utils__WEBPACK_IMPORTED_MODULE_1__.h)("rect", { + class: `s s${i}`, + x: m.toFixed(1), + y: m.toFixed(1), + width: s.toFixed(1), + height: s.toFixed(1), + rx: r.toFixed(1), + ry: r.toFixed(1), + }); + }); + const transform = ({ x, y }) => `transform:translate(${x * sizeCell}px,${y * sizeCell}px)`; + const styles = [ + `.s{ + shape-rendering: geometricPrecision; + fill: var(--cs); + animation: none linear ${duration}ms infinite + }`, + ...snakeParts.map((positions, i) => { + const id = `s${i}`; + const animationName = id; + const keyframes = removeInterpolatedPositions(positions.map((tr, i, { length }) => ({ ...tr, t: i / length }))).map(({ t, ...p }) => ({ t, style: transform(p) })); + return [ + (0,_css_utils__WEBPACK_IMPORTED_MODULE_2__.createAnimation)(animationName, keyframes), + `.s.${id}{ + ${transform(positions[0])}; + animation-name: ${animationName} + }`, + ]; + }), + ].flat(); + return { svgElements, styles }; +}; +const removeInterpolatedPositions = (arr) => arr.filter((u, i, arr) => { + if (i - 1 < 0 || i + 1 >= arr.length) + return true; + const a = arr[i - 1]; + const b = arr[i + 1]; + const ex = (a.x + b.x) / 2; + const ey = (a.y + b.y) / 2; + // return true; + return !(Math.abs(ex - u.x) < 0.01 && Math.abs(ey - u.y) < 0.01); +}); + + +/***/ }), + +/***/ "../svg-creator/stack.ts": +/*!*******************************!*\ + !*** ../svg-creator/stack.ts ***! + \*******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createStack: () => (/* binding */ createStack) +/* harmony export */ }); +/* harmony import */ var _css_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./css-utils */ "../svg-creator/css-utils.ts"); +/* harmony import */ var _xml_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./xml-utils */ "../svg-creator/xml-utils.ts"); + + +const createStack = (cells, { sizeDot }, width, y, duration) => { + const svgElements = []; + const styles = [ + `.u{ + transform-origin: 0 0; + transform: scale(0,1); + animation: none linear ${duration}ms infinite; + }`, + ]; + const stack = cells + .slice() + .filter((a) => a.t !== null) + .sort((a, b) => a.t - b.t); + const blocks = []; + stack.forEach(({ color, t }) => { + const latest = blocks[blocks.length - 1]; + if ((latest === null || latest === void 0 ? void 0 : latest.color) === color) + latest.ts.push(t); + else + blocks.push({ color, ts: [t] }); + }); + const m = width / stack.length; + let i = 0; + let nx = 0; + for (const { color, ts } of blocks) { + const id = "u" + (i++).toString(36); + const animationName = id; + const x = (nx * m).toFixed(1); + nx += ts.length; + svgElements.push((0,_xml_utils__WEBPACK_IMPORTED_MODULE_1__.h)("rect", { + class: `u ${id}`, + height: sizeDot, + width: (ts.length * m + 0.6).toFixed(1), + x, + y, + })); + styles.push((0,_css_utils__WEBPACK_IMPORTED_MODULE_0__.createAnimation)(animationName, [ + ...ts + .map((t, i, { length }) => [ + { scale: i / length, t: t - 0.0001 }, + { scale: (i + 1) / length, t: t + 0.0001 }, + ]) + .flat(), + { scale: 1, t: 1 }, + ].map(({ scale, t }) => ({ + t, + style: `transform:scale(${scale.toFixed(3)},1)`, + }))), `.u.${id} { + fill: var(--c${color}); + animation-name: ${animationName}; + transform-origin: ${x}px 0 + } + `); + } + return { svgElements, styles }; +}; + + +/***/ }), + +/***/ "../svg-creator/xml-utils.ts": +/*!***********************************!*\ + !*** ../svg-creator/xml-utils.ts ***! + \***********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ h: () => (/* binding */ h), +/* harmony export */ toAttribute: () => (/* binding */ toAttribute) +/* harmony export */ }); +const h = (element, attributes) => `<${element} ${toAttribute(attributes)}/>`; +const toAttribute = (o) => Object.entries(o) + .filter(([, value]) => value !== null) + .map(([name, value]) => `${name}="${value}"`) + .join(" "); + + +/***/ }), + +/***/ "../types/grid.ts": +/*!************************!*\ + !*** ../types/grid.ts ***! + \************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copyGrid: () => (/* binding */ copyGrid), +/* harmony export */ createEmptyGrid: () => (/* binding */ createEmptyGrid), +/* harmony export */ getColor: () => (/* binding */ getColor), +/* harmony export */ gridEquals: () => (/* binding */ gridEquals), +/* harmony export */ isEmpty: () => (/* binding */ isEmpty), +/* harmony export */ isGridEmpty: () => (/* binding */ isGridEmpty), +/* harmony export */ isInside: () => (/* binding */ isInside), +/* harmony export */ isInsideLarge: () => (/* binding */ isInsideLarge), +/* harmony export */ setColor: () => (/* binding */ setColor), +/* harmony export */ setColorEmpty: () => (/* binding */ setColorEmpty) +/* harmony export */ }); +const isInside = (grid, x, y) => x >= 0 && y >= 0 && x < grid.width && y < grid.height; +const isInsideLarge = (grid, m, x, y) => x >= -m && y >= -m && x < grid.width + m && y < grid.height + m; +const copyGrid = ({ width, height, data }) => ({ + width, + height, + data: Uint8Array.from(data), +}); +const getIndex = (grid, x, y) => x * grid.height + y; +const getColor = (grid, x, y) => grid.data[getIndex(grid, x, y)]; +const isEmpty = (color) => color === 0; +const setColor = (grid, x, y, color) => { + grid.data[getIndex(grid, x, y)] = color || 0; +}; +const setColorEmpty = (grid, x, y) => { + setColor(grid, x, y, 0); +}; +/** + * return true if the grid is empty + */ +const isGridEmpty = (grid) => grid.data.every((x) => x === 0); +const gridEquals = (a, b) => a.data.every((_, i) => a.data[i] === b.data[i]); +const createEmptyGrid = (width, height) => ({ + width, + height, + data: new Uint8Array(width * height), +}); + + +/***/ }), + +/***/ "../types/snake.ts": +/*!*************************!*\ + !*** ../types/snake.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copySnake: () => (/* binding */ copySnake), +/* harmony export */ createSnakeFromCells: () => (/* binding */ createSnakeFromCells), +/* harmony export */ getHeadX: () => (/* binding */ getHeadX), +/* harmony export */ getHeadY: () => (/* binding */ getHeadY), +/* harmony export */ getSnakeLength: () => (/* binding */ getSnakeLength), +/* harmony export */ nextSnake: () => (/* binding */ nextSnake), +/* harmony export */ snakeEquals: () => (/* binding */ snakeEquals), +/* harmony export */ snakeToCells: () => (/* binding */ snakeToCells), +/* harmony export */ snakeWillSelfCollide: () => (/* binding */ snakeWillSelfCollide) +/* harmony export */ }); +const getHeadX = (snake) => snake[0] - 2; +const getHeadY = (snake) => snake[1] - 2; +const getSnakeLength = (snake) => snake.length / 2; +const copySnake = (snake) => snake.slice(); +const snakeEquals = (a, b) => { + for (let i = 0; i < a.length; i++) + if (a[i] !== b[i]) + return false; + return true; +}; +/** + * return a copy of the next snake, considering that dx, dy is the direction + */ +const nextSnake = (snake, dx, dy) => { + const copy = new Uint8Array(snake.length); + for (let i = 2; i < snake.length; i++) + copy[i] = snake[i - 2]; + copy[0] = snake[0] + dx; + copy[1] = snake[1] + dy; + return copy; +}; +/** + * return true if the next snake will collide with itself + */ +const snakeWillSelfCollide = (snake, dx, dy) => { + const nx = snake[0] + dx; + const ny = snake[1] + dy; + for (let i = 2; i < snake.length - 2; i += 2) + if (snake[i + 0] === nx && snake[i + 1] === ny) + return true; + return false; +}; +const snakeToCells = (snake) => Array.from({ length: snake.length / 2 }, (_, i) => ({ + x: snake[i * 2 + 0] - 2, + y: snake[i * 2 + 1] - 2, +})); +const createSnakeFromCells = (points) => { + const snake = new Uint8Array(points.length * 2); + for (let i = points.length; i--;) { + snake[i * 2 + 0] = points[i].x + 2; + snake[i * 2 + 1] = points[i].y + 2; + } + return snake; +}; + + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = __webpack_modules__; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/get javascript chunk filename */ +/******/ (() => { +/******/ // This function allow to reference async chunks +/******/ __webpack_require__.u = (chunkId) => { +/******/ // return url for filenames based on template +/******/ return "" + "d290bb7f144da7140603" + ".js"; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/global */ +/******/ (() => { +/******/ __webpack_require__.g = (function() { +/******/ if (typeof globalThis === 'object') return globalThis; +/******/ try { +/******/ return this || new Function('return this')(); +/******/ } catch (e) { +/******/ if (typeof window === 'object') return window; +/******/ } +/******/ })(); +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/publicPath */ +/******/ (() => { +/******/ var scriptUrl; +/******/ if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + ""; +/******/ var document = __webpack_require__.g.document; +/******/ if (!scriptUrl && document) { +/******/ if (document.currentScript) +/******/ scriptUrl = document.currentScript.src; +/******/ if (!scriptUrl) { +/******/ var scripts = document.getElementsByTagName("script"); +/******/ if(scripts.length) { +/******/ var i = scripts.length - 1; +/******/ while (i > -1 && !scriptUrl) scriptUrl = scripts[i--].src; +/******/ } +/******/ } +/******/ } +/******/ // When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration +/******/ // or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic. +/******/ if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser"); +/******/ scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/"); +/******/ __webpack_require__.p = scriptUrl; +/******/ })(); +/******/ +/******/ /* webpack/runtime/jsonp chunk loading */ +/******/ (() => { +/******/ __webpack_require__.b = document.baseURI || self.location.href; +/******/ +/******/ // object to store loaded and loading chunks +/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched +/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded +/******/ var installedChunks = { +/******/ "interactive": 0 +/******/ }; +/******/ +/******/ // no chunk on demand loading +/******/ +/******/ // no prefetching +/******/ +/******/ // no preloaded +/******/ +/******/ // no HMR +/******/ +/******/ // no HMR manifest +/******/ +/******/ // no on chunks loaded +/******/ +/******/ // no jsonp function +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +/*!*****************************!*\ + !*** ./demo.interactive.ts ***! + \*****************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_solver_step__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/solver/step */ "../solver/step.ts"); +/* harmony import */ var _springUtils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./springUtils */ "./springUtils.ts"); +/* harmony import */ var _snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @snk/draw/drawWorld */ "../draw/drawWorld.ts"); +/* harmony import */ var _snk_action_userContributionToGrid__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @snk/action/userContributionToGrid */ "../action/userContributionToGrid.ts"); +/* harmony import */ var _snk_svg_creator__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @snk/svg-creator */ "../svg-creator/index.ts"); +/* harmony import */ var _worker_utils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./worker-utils */ "./worker-utils.ts"); +/* harmony import */ var _snk_action_palettes__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @snk/action/palettes */ "../action/palettes.ts"); + + + + + + + + +const createForm = ({ onSubmit, onChangeUserName, }) => { + const form = document.createElement("form"); + form.style.position = "relative"; + form.style.display = "flex"; + form.style.flexDirection = "row"; + const input = document.createElement("input"); + input.addEventListener("input", () => onChangeUserName(input.value)); + input.style.padding = "16px"; + input.placeholder = "github user"; + const submit = document.createElement("button"); + submit.style.padding = "16px"; + submit.type = "submit"; + submit.innerText = "ok"; + const label = document.createElement("label"); + label.style.position = "absolute"; + label.style.textAlign = "center"; + label.style.top = "60px"; + label.style.left = "0"; + label.style.right = "0"; + form.appendChild(input); + form.appendChild(submit); + document.body.appendChild(form); + form.addEventListener("submit", (event) => { + event.preventDefault(); + onSubmit(input.value) + .finally(() => { + clearTimeout(timeout); + }) + .catch((err) => { + label.innerText = "error :("; + throw err; + }); + input.disabled = true; + submit.disabled = true; + form.appendChild(label); + label.innerText = "loading ..."; + const timeout = setTimeout(() => { + label.innerText = "loading ( it might take a while ) ... "; + }, 5000); + }); + // + // dispose + const dispose = () => { + document.body.removeChild(form); + }; + return { dispose }; +}; +const clamp = (x, a, b) => Math.max(a, Math.min(b, x)); +const createGithubProfile = () => { + const container = document.createElement("div"); + container.style.padding = "20px"; + container.style.opacity = "0"; + container.style.display = "flex"; + container.style.flexDirection = "column"; + container.style.height = "120px"; + container.style.alignItems = "flex-start"; + const image = document.createElement("img"); + image.style.width = "100px"; + image.style.height = "100px"; + image.style.borderRadius = "50px"; + const name = document.createElement("a"); + name.style.padding = "4px 0 0 0"; + document.body.appendChild(container); + container.appendChild(image); + container.appendChild(name); + image.addEventListener("load", () => { + container.style.opacity = "1"; + }); + const onChangeUser = (userName) => { + container.style.opacity = "0"; + name.innerText = userName; + name.href = `https://github.com/${userName}`; + image.src = `https://github.com/${userName}.png`; + }; + const dispose = () => { + document.body.removeChild(container); + }; + return { dispose, onChangeUser }; +}; +const createViewer = ({ grid0, chain, cells, }) => { + const drawOptions = { + sizeDotBorderRadius: 2, + sizeCell: 16, + sizeDot: 12, + ..._snk_action_palettes__WEBPACK_IMPORTED_MODULE_7__.basePalettes["github-light"], + }; + // + // canvas + const canvas = document.createElement("canvas"); + const { width, height } = (0,_snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_3__.getCanvasWorldSize)(grid0, drawOptions); + canvas.width = width; + canvas.height = height; + const w = Math.min(width, window.innerWidth); + const h = (height / width) * w; + canvas.style.width = w + "px"; + canvas.style.height = h + "px"; + canvas.style.pointerEvents = "none"; + document.body.appendChild(canvas); + // + // draw + let animationFrame; + const spring = { x: 0, v: 0, target: 0 }; + const springParams = { tension: 120, friction: 20, maxVelocity: 50 }; + const ctx = canvas.getContext("2d"); + const loop = () => { + cancelAnimationFrame(animationFrame); + (0,_springUtils__WEBPACK_IMPORTED_MODULE_2__.stepSpring)(spring, springParams, spring.target); + const stable = (0,_springUtils__WEBPACK_IMPORTED_MODULE_2__.isStableAndBound)(spring, spring.target); + const grid = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.copyGrid)(grid0); + const stack = []; + for (let i = 0; i < Math.min(chain.length, spring.x); i++) + (0,_snk_solver_step__WEBPACK_IMPORTED_MODULE_1__.step)(grid, stack, chain[i]); + const snake0 = chain[clamp(Math.floor(spring.x), 0, chain.length - 1)]; + const snake1 = chain[clamp(Math.ceil(spring.x), 0, chain.length - 1)]; + const k = spring.x % 1; + ctx.clearRect(0, 0, 9999, 9999); + (0,_snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_3__.drawLerpWorld)(ctx, grid, cells, snake0, snake1, stack, k, drawOptions); + if (!stable) + animationFrame = requestAnimationFrame(loop); + }; + loop(); + // + // controls + const input = document.createElement("input"); + input.type = "range"; + input.value = "0"; + input.step = "1"; + input.min = "0"; + input.max = "" + chain.length; + input.style.width = "calc( 100% - 20px )"; + input.addEventListener("input", () => { + spring.target = +input.value; + cancelAnimationFrame(animationFrame); + animationFrame = requestAnimationFrame(loop); + }); + const onClickBackground = (e) => { + if (e.target === document.body || e.target === document.body.parentElement) + input.focus(); + }; + window.addEventListener("click", onClickBackground); + document.body.append(input); + // + const schemaSelect = document.createElement("select"); + schemaSelect.style.margin = "10px"; + schemaSelect.style.alignSelf = "flex-start"; + schemaSelect.value = "github-light"; + schemaSelect.addEventListener("change", () => { + var _a, _b; + Object.assign(drawOptions, _snk_action_palettes__WEBPACK_IMPORTED_MODULE_7__.basePalettes[schemaSelect.value]); + svgString = (0,_snk_svg_creator__WEBPACK_IMPORTED_MODULE_5__.createSvg)(grid0, cells, chain, drawOptions, { + frameDuration: 100, + }); + const svgImageUri = `data:image/*;charset=utf-8;base64,${btoa(svgString)}`; + svgLink.href = svgImageUri; + if (schemaSelect.value.includes("dark")) + (_a = document.body.parentElement) === null || _a === void 0 ? void 0 : _a.classList.add("dark-mode"); + else + (_b = document.body.parentElement) === null || _b === void 0 ? void 0 : _b.classList.remove("dark-mode"); + loop(); + }); + for (const name of Object.keys(_snk_action_palettes__WEBPACK_IMPORTED_MODULE_7__.basePalettes)) { + const option = document.createElement("option"); + option.value = name; + option.innerText = name; + schemaSelect.appendChild(option); + } + document.body.append(schemaSelect); + // + // dark mode + const style = document.createElement("style"); + style.innerText = ` + html { transition:background-color 180ms } + a { transition:color 180ms } + html.dark-mode{ background-color:#0d1117 } + html.dark-mode a{ color:rgb(201, 209, 217) } + `; + document.head.append(style); + // + // svg + const svgLink = document.createElement("a"); + let svgString = (0,_snk_svg_creator__WEBPACK_IMPORTED_MODULE_5__.createSvg)(grid0, cells, chain, drawOptions, { + frameDuration: 100, + }); + const svgImageUri = `data:image/*;charset=utf-8;base64,${btoa(svgString)}`; + svgLink.href = svgImageUri; + svgLink.innerText = "github-user-contribution.svg"; + svgLink.download = "github-user-contribution.svg"; + svgLink.addEventListener("click", (e) => { + var _a; + const w = window.open(""); + w.document.write((((_a = document.body.parentElement) === null || _a === void 0 ? void 0 : _a.classList.contains("dark-mode")) + ? "" + : "") + + `` + + svgString + + ""); + e.preventDefault(); + }); + svgLink.style.padding = "20px"; + svgLink.style.paddingTop = "60px"; + svgLink.style.alignSelf = "flex-start"; + document.body.append(svgLink); + // + // dispose + const dispose = () => { + window.removeEventListener("click", onClickBackground); + cancelAnimationFrame(animationFrame); + document.body.removeChild(canvas); + document.body.removeChild(input); + document.body.removeChild(svgLink); + }; + return { dispose }; +}; +const onSubmit = async (userName) => { + const res = await fetch("https://snk-one.vercel.app/api/github-user-contribution/" + userName); + const cells = (await res.json()); + const grid = (0,_snk_action_userContributionToGrid__WEBPACK_IMPORTED_MODULE_4__.userContributionToGrid)(cells); + const chain = await getChain(grid); + dispose(); + createViewer({ grid0: grid, chain, cells }); +}; +const worker = new Worker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u("demo_interactive_worker_ts"), __webpack_require__.b)); +const { getChain } = (0,_worker_utils__WEBPACK_IMPORTED_MODULE_6__.createRpcClient)(worker); +const profile = createGithubProfile(); +const { dispose } = createForm({ + onSubmit, + onChangeUserName: profile.onChangeUser, +}); +document.body.style.margin = "0"; +document.body.style.display = "flex"; +document.body.style.flexDirection = "column"; +document.body.style.alignItems = "center"; +document.body.style.justifyContent = "center"; +document.body.style.height = "100%"; +document.body.style.width = "100%"; +document.body.style.position = "absolute"; + +})(); + +/******/ })() +; \ No newline at end of file diff --git a/c5480514c5d475fdc8d1.js b/c5480514c5d475fdc8d1.js new file mode 100644 index 000000000..5b07bc353 --- /dev/null +++ b/c5480514c5d475fdc8d1.js @@ -0,0 +1,3453 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "../../node_modules/dat.gui/build/dat.gui.module.js": +/*!**********************************************************!*\ + !*** ../../node_modules/dat.gui/build/dat.gui.module.js ***! + \**********************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ GUI: () => (/* binding */ GUI$1), +/* harmony export */ color: () => (/* binding */ color), +/* harmony export */ controllers: () => (/* binding */ controllers), +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), +/* harmony export */ dom: () => (/* binding */ dom$1), +/* harmony export */ gui: () => (/* binding */ gui) +/* harmony export */ }); +/** + * dat-gui JavaScript Controller Library + * https://github.com/dataarts/dat.gui + * + * Copyright 2011 Data Arts Team, Google Creative Lab + * + * 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 + */ + +function ___$insertStyle(css) { + if (!css) { + return; + } + if (typeof window === 'undefined') { + return; + } + + var style = document.createElement('style'); + + style.setAttribute('type', 'text/css'); + style.innerHTML = css; + document.head.appendChild(style); + + return css; +} + +function colorToString (color, forceCSSHex) { + var colorFormat = color.__state.conversionName.toString(); + var r = Math.round(color.r); + var g = Math.round(color.g); + var b = Math.round(color.b); + var a = color.a; + var h = Math.round(color.h); + var s = color.s.toFixed(1); + var v = color.v.toFixed(1); + if (forceCSSHex || colorFormat === 'THREE_CHAR_HEX' || colorFormat === 'SIX_CHAR_HEX') { + var str = color.hex.toString(16); + while (str.length < 6) { + str = '0' + str; + } + return '#' + str; + } else if (colorFormat === 'CSS_RGB') { + return 'rgb(' + r + ',' + g + ',' + b + ')'; + } else if (colorFormat === 'CSS_RGBA') { + return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; + } else if (colorFormat === 'HEX') { + return '0x' + color.hex.toString(16); + } else if (colorFormat === 'RGB_ARRAY') { + return '[' + r + ',' + g + ',' + b + ']'; + } else if (colorFormat === 'RGBA_ARRAY') { + return '[' + r + ',' + g + ',' + b + ',' + a + ']'; + } else if (colorFormat === 'RGB_OBJ') { + return '{r:' + r + ',g:' + g + ',b:' + b + '}'; + } else if (colorFormat === 'RGBA_OBJ') { + return '{r:' + r + ',g:' + g + ',b:' + b + ',a:' + a + '}'; + } else if (colorFormat === 'HSV_OBJ') { + return '{h:' + h + ',s:' + s + ',v:' + v + '}'; + } else if (colorFormat === 'HSVA_OBJ') { + return '{h:' + h + ',s:' + s + ',v:' + v + ',a:' + a + '}'; + } + return 'unknown format'; +} + +var ARR_EACH = Array.prototype.forEach; +var ARR_SLICE = Array.prototype.slice; +var Common = { + BREAK: {}, + extend: function extend(target) { + this.each(ARR_SLICE.call(arguments, 1), function (obj) { + var keys = this.isObject(obj) ? Object.keys(obj) : []; + keys.forEach(function (key) { + if (!this.isUndefined(obj[key])) { + target[key] = obj[key]; + } + }.bind(this)); + }, this); + return target; + }, + defaults: function defaults(target) { + this.each(ARR_SLICE.call(arguments, 1), function (obj) { + var keys = this.isObject(obj) ? Object.keys(obj) : []; + keys.forEach(function (key) { + if (this.isUndefined(target[key])) { + target[key] = obj[key]; + } + }.bind(this)); + }, this); + return target; + }, + compose: function compose() { + var toCall = ARR_SLICE.call(arguments); + return function () { + var args = ARR_SLICE.call(arguments); + for (var i = toCall.length - 1; i >= 0; i--) { + args = [toCall[i].apply(this, args)]; + } + return args[0]; + }; + }, + each: function each(obj, itr, scope) { + if (!obj) { + return; + } + if (ARR_EACH && obj.forEach && obj.forEach === ARR_EACH) { + obj.forEach(itr, scope); + } else if (obj.length === obj.length + 0) { + var key = void 0; + var l = void 0; + for (key = 0, l = obj.length; key < l; key++) { + if (key in obj && itr.call(scope, obj[key], key) === this.BREAK) { + return; + } + } + } else { + for (var _key in obj) { + if (itr.call(scope, obj[_key], _key) === this.BREAK) { + return; + } + } + } + }, + defer: function defer(fnc) { + setTimeout(fnc, 0); + }, + debounce: function debounce(func, threshold, callImmediately) { + var timeout = void 0; + return function () { + var obj = this; + var args = arguments; + function delayed() { + timeout = null; + if (!callImmediately) func.apply(obj, args); + } + var callNow = callImmediately || !timeout; + clearTimeout(timeout); + timeout = setTimeout(delayed, threshold); + if (callNow) { + func.apply(obj, args); + } + }; + }, + toArray: function toArray(obj) { + if (obj.toArray) return obj.toArray(); + return ARR_SLICE.call(obj); + }, + isUndefined: function isUndefined(obj) { + return obj === undefined; + }, + isNull: function isNull(obj) { + return obj === null; + }, + isNaN: function (_isNaN) { + function isNaN(_x) { + return _isNaN.apply(this, arguments); + } + isNaN.toString = function () { + return _isNaN.toString(); + }; + return isNaN; + }(function (obj) { + return isNaN(obj); + }), + isArray: Array.isArray || function (obj) { + return obj.constructor === Array; + }, + isObject: function isObject(obj) { + return obj === Object(obj); + }, + isNumber: function isNumber(obj) { + return obj === obj + 0; + }, + isString: function isString(obj) { + return obj === obj + ''; + }, + isBoolean: function isBoolean(obj) { + return obj === false || obj === true; + }, + isFunction: function isFunction(obj) { + return obj instanceof Function; + } +}; + +var INTERPRETATIONS = [ +{ + litmus: Common.isString, + conversions: { + THREE_CHAR_HEX: { + read: function read(original) { + var test = original.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i); + if (test === null) { + return false; + } + return { + space: 'HEX', + hex: parseInt('0x' + test[1].toString() + test[1].toString() + test[2].toString() + test[2].toString() + test[3].toString() + test[3].toString(), 0) + }; + }, + write: colorToString + }, + SIX_CHAR_HEX: { + read: function read(original) { + var test = original.match(/^#([A-F0-9]{6})$/i); + if (test === null) { + return false; + } + return { + space: 'HEX', + hex: parseInt('0x' + test[1].toString(), 0) + }; + }, + write: colorToString + }, + CSS_RGB: { + read: function read(original) { + var test = original.match(/^rgb\(\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*\)/); + if (test === null) { + return false; + } + return { + space: 'RGB', + r: parseFloat(test[1]), + g: parseFloat(test[2]), + b: parseFloat(test[3]) + }; + }, + write: colorToString + }, + CSS_RGBA: { + read: function read(original) { + var test = original.match(/^rgba\(\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*\)/); + if (test === null) { + return false; + } + return { + space: 'RGB', + r: parseFloat(test[1]), + g: parseFloat(test[2]), + b: parseFloat(test[3]), + a: parseFloat(test[4]) + }; + }, + write: colorToString + } + } +}, +{ + litmus: Common.isNumber, + conversions: { + HEX: { + read: function read(original) { + return { + space: 'HEX', + hex: original, + conversionName: 'HEX' + }; + }, + write: function write(color) { + return color.hex; + } + } + } +}, +{ + litmus: Common.isArray, + conversions: { + RGB_ARRAY: { + read: function read(original) { + if (original.length !== 3) { + return false; + } + return { + space: 'RGB', + r: original[0], + g: original[1], + b: original[2] + }; + }, + write: function write(color) { + return [color.r, color.g, color.b]; + } + }, + RGBA_ARRAY: { + read: function read(original) { + if (original.length !== 4) return false; + return { + space: 'RGB', + r: original[0], + g: original[1], + b: original[2], + a: original[3] + }; + }, + write: function write(color) { + return [color.r, color.g, color.b, color.a]; + } + } + } +}, +{ + litmus: Common.isObject, + conversions: { + RGBA_OBJ: { + read: function read(original) { + if (Common.isNumber(original.r) && Common.isNumber(original.g) && Common.isNumber(original.b) && Common.isNumber(original.a)) { + return { + space: 'RGB', + r: original.r, + g: original.g, + b: original.b, + a: original.a + }; + } + return false; + }, + write: function write(color) { + return { + r: color.r, + g: color.g, + b: color.b, + a: color.a + }; + } + }, + RGB_OBJ: { + read: function read(original) { + if (Common.isNumber(original.r) && Common.isNumber(original.g) && Common.isNumber(original.b)) { + return { + space: 'RGB', + r: original.r, + g: original.g, + b: original.b + }; + } + return false; + }, + write: function write(color) { + return { + r: color.r, + g: color.g, + b: color.b + }; + } + }, + HSVA_OBJ: { + read: function read(original) { + if (Common.isNumber(original.h) && Common.isNumber(original.s) && Common.isNumber(original.v) && Common.isNumber(original.a)) { + return { + space: 'HSV', + h: original.h, + s: original.s, + v: original.v, + a: original.a + }; + } + return false; + }, + write: function write(color) { + return { + h: color.h, + s: color.s, + v: color.v, + a: color.a + }; + } + }, + HSV_OBJ: { + read: function read(original) { + if (Common.isNumber(original.h) && Common.isNumber(original.s) && Common.isNumber(original.v)) { + return { + space: 'HSV', + h: original.h, + s: original.s, + v: original.v + }; + } + return false; + }, + write: function write(color) { + return { + h: color.h, + s: color.s, + v: color.v + }; + } + } + } +}]; +var result = void 0; +var toReturn = void 0; +var interpret = function interpret() { + toReturn = false; + var original = arguments.length > 1 ? Common.toArray(arguments) : arguments[0]; + Common.each(INTERPRETATIONS, function (family) { + if (family.litmus(original)) { + Common.each(family.conversions, function (conversion, conversionName) { + result = conversion.read(original); + if (toReturn === false && result !== false) { + toReturn = result; + result.conversionName = conversionName; + result.conversion = conversion; + return Common.BREAK; + } + }); + return Common.BREAK; + } + }); + return toReturn; +}; + +var tmpComponent = void 0; +var ColorMath = { + hsv_to_rgb: function hsv_to_rgb(h, s, v) { + var hi = Math.floor(h / 60) % 6; + var f = h / 60 - Math.floor(h / 60); + var p = v * (1.0 - s); + var q = v * (1.0 - f * s); + var t = v * (1.0 - (1.0 - f) * s); + var c = [[v, t, p], [q, v, p], [p, v, t], [p, q, v], [t, p, v], [v, p, q]][hi]; + return { + r: c[0] * 255, + g: c[1] * 255, + b: c[2] * 255 + }; + }, + rgb_to_hsv: function rgb_to_hsv(r, g, b) { + var min = Math.min(r, g, b); + var max = Math.max(r, g, b); + var delta = max - min; + var h = void 0; + var s = void 0; + if (max !== 0) { + s = delta / max; + } else { + return { + h: NaN, + s: 0, + v: 0 + }; + } + if (r === max) { + h = (g - b) / delta; + } else if (g === max) { + h = 2 + (b - r) / delta; + } else { + h = 4 + (r - g) / delta; + } + h /= 6; + if (h < 0) { + h += 1; + } + return { + h: h * 360, + s: s, + v: max / 255 + }; + }, + rgb_to_hex: function rgb_to_hex(r, g, b) { + var hex = this.hex_with_component(0, 2, r); + hex = this.hex_with_component(hex, 1, g); + hex = this.hex_with_component(hex, 0, b); + return hex; + }, + component_from_hex: function component_from_hex(hex, componentIndex) { + return hex >> componentIndex * 8 & 0xFF; + }, + hex_with_component: function hex_with_component(hex, componentIndex, value) { + return value << (tmpComponent = componentIndex * 8) | hex & ~(0xFF << tmpComponent); + } +}; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; +} : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; +}; + + + + + + + + + + + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; + +var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; +}(); + + + + + + + +var get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); + + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + + if (getter === undefined) { + return undefined; + } + + return getter.call(receiver); + } +}; + +var inherits = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; +}; + + + + + + + + + + + +var possibleConstructorReturn = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && (typeof call === "object" || typeof call === "function") ? call : self; +}; + +var Color = function () { + function Color() { + classCallCheck(this, Color); + this.__state = interpret.apply(this, arguments); + if (this.__state === false) { + throw new Error('Failed to interpret color arguments'); + } + this.__state.a = this.__state.a || 1; + } + createClass(Color, [{ + key: 'toString', + value: function toString() { + return colorToString(this); + } + }, { + key: 'toHexString', + value: function toHexString() { + return colorToString(this, true); + } + }, { + key: 'toOriginal', + value: function toOriginal() { + return this.__state.conversion.write(this); + } + }]); + return Color; +}(); +function defineRGBComponent(target, component, componentHexIndex) { + Object.defineProperty(target, component, { + get: function get$$1() { + if (this.__state.space === 'RGB') { + return this.__state[component]; + } + Color.recalculateRGB(this, component, componentHexIndex); + return this.__state[component]; + }, + set: function set$$1(v) { + if (this.__state.space !== 'RGB') { + Color.recalculateRGB(this, component, componentHexIndex); + this.__state.space = 'RGB'; + } + this.__state[component] = v; + } + }); +} +function defineHSVComponent(target, component) { + Object.defineProperty(target, component, { + get: function get$$1() { + if (this.__state.space === 'HSV') { + return this.__state[component]; + } + Color.recalculateHSV(this); + return this.__state[component]; + }, + set: function set$$1(v) { + if (this.__state.space !== 'HSV') { + Color.recalculateHSV(this); + this.__state.space = 'HSV'; + } + this.__state[component] = v; + } + }); +} +Color.recalculateRGB = function (color, component, componentHexIndex) { + if (color.__state.space === 'HEX') { + color.__state[component] = ColorMath.component_from_hex(color.__state.hex, componentHexIndex); + } else if (color.__state.space === 'HSV') { + Common.extend(color.__state, ColorMath.hsv_to_rgb(color.__state.h, color.__state.s, color.__state.v)); + } else { + throw new Error('Corrupted color state'); + } +}; +Color.recalculateHSV = function (color) { + var result = ColorMath.rgb_to_hsv(color.r, color.g, color.b); + Common.extend(color.__state, { + s: result.s, + v: result.v + }); + if (!Common.isNaN(result.h)) { + color.__state.h = result.h; + } else if (Common.isUndefined(color.__state.h)) { + color.__state.h = 0; + } +}; +Color.COMPONENTS = ['r', 'g', 'b', 'h', 's', 'v', 'hex', 'a']; +defineRGBComponent(Color.prototype, 'r', 2); +defineRGBComponent(Color.prototype, 'g', 1); +defineRGBComponent(Color.prototype, 'b', 0); +defineHSVComponent(Color.prototype, 'h'); +defineHSVComponent(Color.prototype, 's'); +defineHSVComponent(Color.prototype, 'v'); +Object.defineProperty(Color.prototype, 'a', { + get: function get$$1() { + return this.__state.a; + }, + set: function set$$1(v) { + this.__state.a = v; + } +}); +Object.defineProperty(Color.prototype, 'hex', { + get: function get$$1() { + if (this.__state.space !== 'HEX') { + this.__state.hex = ColorMath.rgb_to_hex(this.r, this.g, this.b); + this.__state.space = 'HEX'; + } + return this.__state.hex; + }, + set: function set$$1(v) { + this.__state.space = 'HEX'; + this.__state.hex = v; + } +}); + +var Controller = function () { + function Controller(object, property) { + classCallCheck(this, Controller); + this.initialValue = object[property]; + this.domElement = document.createElement('div'); + this.object = object; + this.property = property; + this.__onChange = undefined; + this.__onFinishChange = undefined; + } + createClass(Controller, [{ + key: 'onChange', + value: function onChange(fnc) { + this.__onChange = fnc; + return this; + } + }, { + key: 'onFinishChange', + value: function onFinishChange(fnc) { + this.__onFinishChange = fnc; + return this; + } + }, { + key: 'setValue', + value: function setValue(newValue) { + this.object[this.property] = newValue; + if (this.__onChange) { + this.__onChange.call(this, newValue); + } + this.updateDisplay(); + return this; + } + }, { + key: 'getValue', + value: function getValue() { + return this.object[this.property]; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + return this; + } + }, { + key: 'isModified', + value: function isModified() { + return this.initialValue !== this.getValue(); + } + }]); + return Controller; +}(); + +var EVENT_MAP = { + HTMLEvents: ['change'], + MouseEvents: ['click', 'mousemove', 'mousedown', 'mouseup', 'mouseover'], + KeyboardEvents: ['keydown'] +}; +var EVENT_MAP_INV = {}; +Common.each(EVENT_MAP, function (v, k) { + Common.each(v, function (e) { + EVENT_MAP_INV[e] = k; + }); +}); +var CSS_VALUE_PIXELS = /(\d+(\.\d+)?)px/; +function cssValueToPixels(val) { + if (val === '0' || Common.isUndefined(val)) { + return 0; + } + var match = val.match(CSS_VALUE_PIXELS); + if (!Common.isNull(match)) { + return parseFloat(match[1]); + } + return 0; +} +var dom = { + makeSelectable: function makeSelectable(elem, selectable) { + if (elem === undefined || elem.style === undefined) return; + elem.onselectstart = selectable ? function () { + return false; + } : function () {}; + elem.style.MozUserSelect = selectable ? 'auto' : 'none'; + elem.style.KhtmlUserSelect = selectable ? 'auto' : 'none'; + elem.unselectable = selectable ? 'on' : 'off'; + }, + makeFullscreen: function makeFullscreen(elem, hor, vert) { + var vertical = vert; + var horizontal = hor; + if (Common.isUndefined(horizontal)) { + horizontal = true; + } + if (Common.isUndefined(vertical)) { + vertical = true; + } + elem.style.position = 'absolute'; + if (horizontal) { + elem.style.left = 0; + elem.style.right = 0; + } + if (vertical) { + elem.style.top = 0; + elem.style.bottom = 0; + } + }, + fakeEvent: function fakeEvent(elem, eventType, pars, aux) { + var params = pars || {}; + var className = EVENT_MAP_INV[eventType]; + if (!className) { + throw new Error('Event type ' + eventType + ' not supported.'); + } + var evt = document.createEvent(className); + switch (className) { + case 'MouseEvents': + { + var clientX = params.x || params.clientX || 0; + var clientY = params.y || params.clientY || 0; + evt.initMouseEvent(eventType, params.bubbles || false, params.cancelable || true, window, params.clickCount || 1, 0, + 0, + clientX, + clientY, + false, false, false, false, 0, null); + break; + } + case 'KeyboardEvents': + { + var init = evt.initKeyboardEvent || evt.initKeyEvent; + Common.defaults(params, { + cancelable: true, + ctrlKey: false, + altKey: false, + shiftKey: false, + metaKey: false, + keyCode: undefined, + charCode: undefined + }); + init(eventType, params.bubbles || false, params.cancelable, window, params.ctrlKey, params.altKey, params.shiftKey, params.metaKey, params.keyCode, params.charCode); + break; + } + default: + { + evt.initEvent(eventType, params.bubbles || false, params.cancelable || true); + break; + } + } + Common.defaults(evt, aux); + elem.dispatchEvent(evt); + }, + bind: function bind(elem, event, func, newBool) { + var bool = newBool || false; + if (elem.addEventListener) { + elem.addEventListener(event, func, bool); + } else if (elem.attachEvent) { + elem.attachEvent('on' + event, func); + } + return dom; + }, + unbind: function unbind(elem, event, func, newBool) { + var bool = newBool || false; + if (elem.removeEventListener) { + elem.removeEventListener(event, func, bool); + } else if (elem.detachEvent) { + elem.detachEvent('on' + event, func); + } + return dom; + }, + addClass: function addClass(elem, className) { + if (elem.className === undefined) { + elem.className = className; + } else if (elem.className !== className) { + var classes = elem.className.split(/ +/); + if (classes.indexOf(className) === -1) { + classes.push(className); + elem.className = classes.join(' ').replace(/^\s+/, '').replace(/\s+$/, ''); + } + } + return dom; + }, + removeClass: function removeClass(elem, className) { + if (className) { + if (elem.className === className) { + elem.removeAttribute('class'); + } else { + var classes = elem.className.split(/ +/); + var index = classes.indexOf(className); + if (index !== -1) { + classes.splice(index, 1); + elem.className = classes.join(' '); + } + } + } else { + elem.className = undefined; + } + return dom; + }, + hasClass: function hasClass(elem, className) { + return new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)').test(elem.className) || false; + }, + getWidth: function getWidth(elem) { + var style = getComputedStyle(elem); + return cssValueToPixels(style['border-left-width']) + cssValueToPixels(style['border-right-width']) + cssValueToPixels(style['padding-left']) + cssValueToPixels(style['padding-right']) + cssValueToPixels(style.width); + }, + getHeight: function getHeight(elem) { + var style = getComputedStyle(elem); + return cssValueToPixels(style['border-top-width']) + cssValueToPixels(style['border-bottom-width']) + cssValueToPixels(style['padding-top']) + cssValueToPixels(style['padding-bottom']) + cssValueToPixels(style.height); + }, + getOffset: function getOffset(el) { + var elem = el; + var offset = { left: 0, top: 0 }; + if (elem.offsetParent) { + do { + offset.left += elem.offsetLeft; + offset.top += elem.offsetTop; + elem = elem.offsetParent; + } while (elem); + } + return offset; + }, + isActive: function isActive(elem) { + return elem === document.activeElement && (elem.type || elem.href); + } +}; + +var BooleanController = function (_Controller) { + inherits(BooleanController, _Controller); + function BooleanController(object, property) { + classCallCheck(this, BooleanController); + var _this2 = possibleConstructorReturn(this, (BooleanController.__proto__ || Object.getPrototypeOf(BooleanController)).call(this, object, property)); + var _this = _this2; + _this2.__prev = _this2.getValue(); + _this2.__checkbox = document.createElement('input'); + _this2.__checkbox.setAttribute('type', 'checkbox'); + function onChange() { + _this.setValue(!_this.__prev); + } + dom.bind(_this2.__checkbox, 'change', onChange, false); + _this2.domElement.appendChild(_this2.__checkbox); + _this2.updateDisplay(); + return _this2; + } + createClass(BooleanController, [{ + key: 'setValue', + value: function setValue(v) { + var toReturn = get(BooleanController.prototype.__proto__ || Object.getPrototypeOf(BooleanController.prototype), 'setValue', this).call(this, v); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + this.__prev = this.getValue(); + return toReturn; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + if (this.getValue() === true) { + this.__checkbox.setAttribute('checked', 'checked'); + this.__checkbox.checked = true; + this.__prev = true; + } else { + this.__checkbox.checked = false; + this.__prev = false; + } + return get(BooleanController.prototype.__proto__ || Object.getPrototypeOf(BooleanController.prototype), 'updateDisplay', this).call(this); + } + }]); + return BooleanController; +}(Controller); + +var OptionController = function (_Controller) { + inherits(OptionController, _Controller); + function OptionController(object, property, opts) { + classCallCheck(this, OptionController); + var _this2 = possibleConstructorReturn(this, (OptionController.__proto__ || Object.getPrototypeOf(OptionController)).call(this, object, property)); + var options = opts; + var _this = _this2; + _this2.__select = document.createElement('select'); + if (Common.isArray(options)) { + var map = {}; + Common.each(options, function (element) { + map[element] = element; + }); + options = map; + } + Common.each(options, function (value, key) { + var opt = document.createElement('option'); + opt.innerHTML = key; + opt.setAttribute('value', value); + _this.__select.appendChild(opt); + }); + _this2.updateDisplay(); + dom.bind(_this2.__select, 'change', function () { + var desiredValue = this.options[this.selectedIndex].value; + _this.setValue(desiredValue); + }); + _this2.domElement.appendChild(_this2.__select); + return _this2; + } + createClass(OptionController, [{ + key: 'setValue', + value: function setValue(v) { + var toReturn = get(OptionController.prototype.__proto__ || Object.getPrototypeOf(OptionController.prototype), 'setValue', this).call(this, v); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + return toReturn; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + if (dom.isActive(this.__select)) return this; + this.__select.value = this.getValue(); + return get(OptionController.prototype.__proto__ || Object.getPrototypeOf(OptionController.prototype), 'updateDisplay', this).call(this); + } + }]); + return OptionController; +}(Controller); + +var StringController = function (_Controller) { + inherits(StringController, _Controller); + function StringController(object, property) { + classCallCheck(this, StringController); + var _this2 = possibleConstructorReturn(this, (StringController.__proto__ || Object.getPrototypeOf(StringController)).call(this, object, property)); + var _this = _this2; + function onChange() { + _this.setValue(_this.__input.value); + } + function onBlur() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + _this2.__input = document.createElement('input'); + _this2.__input.setAttribute('type', 'text'); + dom.bind(_this2.__input, 'keyup', onChange); + dom.bind(_this2.__input, 'change', onChange); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + this.blur(); + } + }); + _this2.updateDisplay(); + _this2.domElement.appendChild(_this2.__input); + return _this2; + } + createClass(StringController, [{ + key: 'updateDisplay', + value: function updateDisplay() { + if (!dom.isActive(this.__input)) { + this.__input.value = this.getValue(); + } + return get(StringController.prototype.__proto__ || Object.getPrototypeOf(StringController.prototype), 'updateDisplay', this).call(this); + } + }]); + return StringController; +}(Controller); + +function numDecimals(x) { + var _x = x.toString(); + if (_x.indexOf('.') > -1) { + return _x.length - _x.indexOf('.') - 1; + } + return 0; +} +var NumberController = function (_Controller) { + inherits(NumberController, _Controller); + function NumberController(object, property, params) { + classCallCheck(this, NumberController); + var _this = possibleConstructorReturn(this, (NumberController.__proto__ || Object.getPrototypeOf(NumberController)).call(this, object, property)); + var _params = params || {}; + _this.__min = _params.min; + _this.__max = _params.max; + _this.__step = _params.step; + if (Common.isUndefined(_this.__step)) { + if (_this.initialValue === 0) { + _this.__impliedStep = 1; + } else { + _this.__impliedStep = Math.pow(10, Math.floor(Math.log(Math.abs(_this.initialValue)) / Math.LN10)) / 10; + } + } else { + _this.__impliedStep = _this.__step; + } + _this.__precision = numDecimals(_this.__impliedStep); + return _this; + } + createClass(NumberController, [{ + key: 'setValue', + value: function setValue(v) { + var _v = v; + if (this.__min !== undefined && _v < this.__min) { + _v = this.__min; + } else if (this.__max !== undefined && _v > this.__max) { + _v = this.__max; + } + if (this.__step !== undefined && _v % this.__step !== 0) { + _v = Math.round(_v / this.__step) * this.__step; + } + return get(NumberController.prototype.__proto__ || Object.getPrototypeOf(NumberController.prototype), 'setValue', this).call(this, _v); + } + }, { + key: 'min', + value: function min(minValue) { + this.__min = minValue; + return this; + } + }, { + key: 'max', + value: function max(maxValue) { + this.__max = maxValue; + return this; + } + }, { + key: 'step', + value: function step(stepValue) { + this.__step = stepValue; + this.__impliedStep = stepValue; + this.__precision = numDecimals(stepValue); + return this; + } + }]); + return NumberController; +}(Controller); + +function roundToDecimal(value, decimals) { + var tenTo = Math.pow(10, decimals); + return Math.round(value * tenTo) / tenTo; +} +var NumberControllerBox = function (_NumberController) { + inherits(NumberControllerBox, _NumberController); + function NumberControllerBox(object, property, params) { + classCallCheck(this, NumberControllerBox); + var _this2 = possibleConstructorReturn(this, (NumberControllerBox.__proto__ || Object.getPrototypeOf(NumberControllerBox)).call(this, object, property, params)); + _this2.__truncationSuspended = false; + var _this = _this2; + var prevY = void 0; + function onChange() { + var attempted = parseFloat(_this.__input.value); + if (!Common.isNaN(attempted)) { + _this.setValue(attempted); + } + } + function onFinish() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + function onBlur() { + onFinish(); + } + function onMouseDrag(e) { + var diff = prevY - e.clientY; + _this.setValue(_this.getValue() + diff * _this.__impliedStep); + prevY = e.clientY; + } + function onMouseUp() { + dom.unbind(window, 'mousemove', onMouseDrag); + dom.unbind(window, 'mouseup', onMouseUp); + onFinish(); + } + function onMouseDown(e) { + dom.bind(window, 'mousemove', onMouseDrag); + dom.bind(window, 'mouseup', onMouseUp); + prevY = e.clientY; + } + _this2.__input = document.createElement('input'); + _this2.__input.setAttribute('type', 'text'); + dom.bind(_this2.__input, 'change', onChange); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__input, 'mousedown', onMouseDown); + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + _this.__truncationSuspended = true; + this.blur(); + _this.__truncationSuspended = false; + onFinish(); + } + }); + _this2.updateDisplay(); + _this2.domElement.appendChild(_this2.__input); + return _this2; + } + createClass(NumberControllerBox, [{ + key: 'updateDisplay', + value: function updateDisplay() { + this.__input.value = this.__truncationSuspended ? this.getValue() : roundToDecimal(this.getValue(), this.__precision); + return get(NumberControllerBox.prototype.__proto__ || Object.getPrototypeOf(NumberControllerBox.prototype), 'updateDisplay', this).call(this); + } + }]); + return NumberControllerBox; +}(NumberController); + +function map(v, i1, i2, o1, o2) { + return o1 + (o2 - o1) * ((v - i1) / (i2 - i1)); +} +var NumberControllerSlider = function (_NumberController) { + inherits(NumberControllerSlider, _NumberController); + function NumberControllerSlider(object, property, min, max, step) { + classCallCheck(this, NumberControllerSlider); + var _this2 = possibleConstructorReturn(this, (NumberControllerSlider.__proto__ || Object.getPrototypeOf(NumberControllerSlider)).call(this, object, property, { min: min, max: max, step: step })); + var _this = _this2; + _this2.__background = document.createElement('div'); + _this2.__foreground = document.createElement('div'); + dom.bind(_this2.__background, 'mousedown', onMouseDown); + dom.bind(_this2.__background, 'touchstart', onTouchStart); + dom.addClass(_this2.__background, 'slider'); + dom.addClass(_this2.__foreground, 'slider-fg'); + function onMouseDown(e) { + document.activeElement.blur(); + dom.bind(window, 'mousemove', onMouseDrag); + dom.bind(window, 'mouseup', onMouseUp); + onMouseDrag(e); + } + function onMouseDrag(e) { + e.preventDefault(); + var bgRect = _this.__background.getBoundingClientRect(); + _this.setValue(map(e.clientX, bgRect.left, bgRect.right, _this.__min, _this.__max)); + return false; + } + function onMouseUp() { + dom.unbind(window, 'mousemove', onMouseDrag); + dom.unbind(window, 'mouseup', onMouseUp); + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + function onTouchStart(e) { + if (e.touches.length !== 1) { + return; + } + dom.bind(window, 'touchmove', onTouchMove); + dom.bind(window, 'touchend', onTouchEnd); + onTouchMove(e); + } + function onTouchMove(e) { + var clientX = e.touches[0].clientX; + var bgRect = _this.__background.getBoundingClientRect(); + _this.setValue(map(clientX, bgRect.left, bgRect.right, _this.__min, _this.__max)); + } + function onTouchEnd() { + dom.unbind(window, 'touchmove', onTouchMove); + dom.unbind(window, 'touchend', onTouchEnd); + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + _this2.updateDisplay(); + _this2.__background.appendChild(_this2.__foreground); + _this2.domElement.appendChild(_this2.__background); + return _this2; + } + createClass(NumberControllerSlider, [{ + key: 'updateDisplay', + value: function updateDisplay() { + var pct = (this.getValue() - this.__min) / (this.__max - this.__min); + this.__foreground.style.width = pct * 100 + '%'; + return get(NumberControllerSlider.prototype.__proto__ || Object.getPrototypeOf(NumberControllerSlider.prototype), 'updateDisplay', this).call(this); + } + }]); + return NumberControllerSlider; +}(NumberController); + +var FunctionController = function (_Controller) { + inherits(FunctionController, _Controller); + function FunctionController(object, property, text) { + classCallCheck(this, FunctionController); + var _this2 = possibleConstructorReturn(this, (FunctionController.__proto__ || Object.getPrototypeOf(FunctionController)).call(this, object, property)); + var _this = _this2; + _this2.__button = document.createElement('div'); + _this2.__button.innerHTML = text === undefined ? 'Fire' : text; + dom.bind(_this2.__button, 'click', function (e) { + e.preventDefault(); + _this.fire(); + return false; + }); + dom.addClass(_this2.__button, 'button'); + _this2.domElement.appendChild(_this2.__button); + return _this2; + } + createClass(FunctionController, [{ + key: 'fire', + value: function fire() { + if (this.__onChange) { + this.__onChange.call(this); + } + this.getValue().call(this.object); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + } + }]); + return FunctionController; +}(Controller); + +var ColorController = function (_Controller) { + inherits(ColorController, _Controller); + function ColorController(object, property) { + classCallCheck(this, ColorController); + var _this2 = possibleConstructorReturn(this, (ColorController.__proto__ || Object.getPrototypeOf(ColorController)).call(this, object, property)); + _this2.__color = new Color(_this2.getValue()); + _this2.__temp = new Color(0); + var _this = _this2; + _this2.domElement = document.createElement('div'); + dom.makeSelectable(_this2.domElement, false); + _this2.__selector = document.createElement('div'); + _this2.__selector.className = 'selector'; + _this2.__saturation_field = document.createElement('div'); + _this2.__saturation_field.className = 'saturation-field'; + _this2.__field_knob = document.createElement('div'); + _this2.__field_knob.className = 'field-knob'; + _this2.__field_knob_border = '2px solid '; + _this2.__hue_knob = document.createElement('div'); + _this2.__hue_knob.className = 'hue-knob'; + _this2.__hue_field = document.createElement('div'); + _this2.__hue_field.className = 'hue-field'; + _this2.__input = document.createElement('input'); + _this2.__input.type = 'text'; + _this2.__input_textShadow = '0 1px 1px '; + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + onBlur.call(this); + } + }); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__selector, 'mousedown', function () { + dom.addClass(this, 'drag').bind(window, 'mouseup', function () { + dom.removeClass(_this.__selector, 'drag'); + }); + }); + dom.bind(_this2.__selector, 'touchstart', function () { + dom.addClass(this, 'drag').bind(window, 'touchend', function () { + dom.removeClass(_this.__selector, 'drag'); + }); + }); + var valueField = document.createElement('div'); + Common.extend(_this2.__selector.style, { + width: '122px', + height: '102px', + padding: '3px', + backgroundColor: '#222', + boxShadow: '0px 1px 3px rgba(0,0,0,0.3)' + }); + Common.extend(_this2.__field_knob.style, { + position: 'absolute', + width: '12px', + height: '12px', + border: _this2.__field_knob_border + (_this2.__color.v < 0.5 ? '#fff' : '#000'), + boxShadow: '0px 1px 3px rgba(0,0,0,0.5)', + borderRadius: '12px', + zIndex: 1 + }); + Common.extend(_this2.__hue_knob.style, { + position: 'absolute', + width: '15px', + height: '2px', + borderRight: '4px solid #fff', + zIndex: 1 + }); + Common.extend(_this2.__saturation_field.style, { + width: '100px', + height: '100px', + border: '1px solid #555', + marginRight: '3px', + display: 'inline-block', + cursor: 'pointer' + }); + Common.extend(valueField.style, { + width: '100%', + height: '100%', + background: 'none' + }); + linearGradient(valueField, 'top', 'rgba(0,0,0,0)', '#000'); + Common.extend(_this2.__hue_field.style, { + width: '15px', + height: '100px', + border: '1px solid #555', + cursor: 'ns-resize', + position: 'absolute', + top: '3px', + right: '3px' + }); + hueGradient(_this2.__hue_field); + Common.extend(_this2.__input.style, { + outline: 'none', + textAlign: 'center', + color: '#fff', + border: 0, + fontWeight: 'bold', + textShadow: _this2.__input_textShadow + 'rgba(0,0,0,0.7)' + }); + dom.bind(_this2.__saturation_field, 'mousedown', fieldDown); + dom.bind(_this2.__saturation_field, 'touchstart', fieldDown); + dom.bind(_this2.__field_knob, 'mousedown', fieldDown); + dom.bind(_this2.__field_knob, 'touchstart', fieldDown); + dom.bind(_this2.__hue_field, 'mousedown', fieldDownH); + dom.bind(_this2.__hue_field, 'touchstart', fieldDownH); + function fieldDown(e) { + setSV(e); + dom.bind(window, 'mousemove', setSV); + dom.bind(window, 'touchmove', setSV); + dom.bind(window, 'mouseup', fieldUpSV); + dom.bind(window, 'touchend', fieldUpSV); + } + function fieldDownH(e) { + setH(e); + dom.bind(window, 'mousemove', setH); + dom.bind(window, 'touchmove', setH); + dom.bind(window, 'mouseup', fieldUpH); + dom.bind(window, 'touchend', fieldUpH); + } + function fieldUpSV() { + dom.unbind(window, 'mousemove', setSV); + dom.unbind(window, 'touchmove', setSV); + dom.unbind(window, 'mouseup', fieldUpSV); + dom.unbind(window, 'touchend', fieldUpSV); + onFinish(); + } + function fieldUpH() { + dom.unbind(window, 'mousemove', setH); + dom.unbind(window, 'touchmove', setH); + dom.unbind(window, 'mouseup', fieldUpH); + dom.unbind(window, 'touchend', fieldUpH); + onFinish(); + } + function onBlur() { + var i = interpret(this.value); + if (i !== false) { + _this.__color.__state = i; + _this.setValue(_this.__color.toOriginal()); + } else { + this.value = _this.__color.toString(); + } + } + function onFinish() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.__color.toOriginal()); + } + } + _this2.__saturation_field.appendChild(valueField); + _this2.__selector.appendChild(_this2.__field_knob); + _this2.__selector.appendChild(_this2.__saturation_field); + _this2.__selector.appendChild(_this2.__hue_field); + _this2.__hue_field.appendChild(_this2.__hue_knob); + _this2.domElement.appendChild(_this2.__input); + _this2.domElement.appendChild(_this2.__selector); + _this2.updateDisplay(); + function setSV(e) { + if (e.type.indexOf('touch') === -1) { + e.preventDefault(); + } + var fieldRect = _this.__saturation_field.getBoundingClientRect(); + var _ref = e.touches && e.touches[0] || e, + clientX = _ref.clientX, + clientY = _ref.clientY; + var s = (clientX - fieldRect.left) / (fieldRect.right - fieldRect.left); + var v = 1 - (clientY - fieldRect.top) / (fieldRect.bottom - fieldRect.top); + if (v > 1) { + v = 1; + } else if (v < 0) { + v = 0; + } + if (s > 1) { + s = 1; + } else if (s < 0) { + s = 0; + } + _this.__color.v = v; + _this.__color.s = s; + _this.setValue(_this.__color.toOriginal()); + return false; + } + function setH(e) { + if (e.type.indexOf('touch') === -1) { + e.preventDefault(); + } + var fieldRect = _this.__hue_field.getBoundingClientRect(); + var _ref2 = e.touches && e.touches[0] || e, + clientY = _ref2.clientY; + var h = 1 - (clientY - fieldRect.top) / (fieldRect.bottom - fieldRect.top); + if (h > 1) { + h = 1; + } else if (h < 0) { + h = 0; + } + _this.__color.h = h * 360; + _this.setValue(_this.__color.toOriginal()); + return false; + } + return _this2; + } + createClass(ColorController, [{ + key: 'updateDisplay', + value: function updateDisplay() { + var i = interpret(this.getValue()); + if (i !== false) { + var mismatch = false; + Common.each(Color.COMPONENTS, function (component) { + if (!Common.isUndefined(i[component]) && !Common.isUndefined(this.__color.__state[component]) && i[component] !== this.__color.__state[component]) { + mismatch = true; + return {}; + } + }, this); + if (mismatch) { + Common.extend(this.__color.__state, i); + } + } + Common.extend(this.__temp.__state, this.__color.__state); + this.__temp.a = 1; + var flip = this.__color.v < 0.5 || this.__color.s > 0.5 ? 255 : 0; + var _flip = 255 - flip; + Common.extend(this.__field_knob.style, { + marginLeft: 100 * this.__color.s - 7 + 'px', + marginTop: 100 * (1 - this.__color.v) - 7 + 'px', + backgroundColor: this.__temp.toHexString(), + border: this.__field_knob_border + 'rgb(' + flip + ',' + flip + ',' + flip + ')' + }); + this.__hue_knob.style.marginTop = (1 - this.__color.h / 360) * 100 + 'px'; + this.__temp.s = 1; + this.__temp.v = 1; + linearGradient(this.__saturation_field, 'left', '#fff', this.__temp.toHexString()); + this.__input.value = this.__color.toString(); + Common.extend(this.__input.style, { + backgroundColor: this.__color.toHexString(), + color: 'rgb(' + flip + ',' + flip + ',' + flip + ')', + textShadow: this.__input_textShadow + 'rgba(' + _flip + ',' + _flip + ',' + _flip + ',.7)' + }); + } + }]); + return ColorController; +}(Controller); +var vendors = ['-moz-', '-o-', '-webkit-', '-ms-', '']; +function linearGradient(elem, x, a, b) { + elem.style.background = ''; + Common.each(vendors, function (vendor) { + elem.style.cssText += 'background: ' + vendor + 'linear-gradient(' + x + ', ' + a + ' 0%, ' + b + ' 100%); '; + }); +} +function hueGradient(elem) { + elem.style.background = ''; + elem.style.cssText += 'background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);'; + elem.style.cssText += 'background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; +} + +var css = { + load: function load(url, indoc) { + var doc = indoc || document; + var link = doc.createElement('link'); + link.type = 'text/css'; + link.rel = 'stylesheet'; + link.href = url; + doc.getElementsByTagName('head')[0].appendChild(link); + }, + inject: function inject(cssContent, indoc) { + var doc = indoc || document; + var injected = document.createElement('style'); + injected.type = 'text/css'; + injected.innerHTML = cssContent; + var head = doc.getElementsByTagName('head')[0]; + try { + head.appendChild(injected); + } catch (e) { + } + } +}; + +var saveDialogContents = "
\n\n Here's the new load parameter for your GUI's constructor:\n\n \n\n
\n\n Automatically save\n values to localStorage on exit.\n\n
The values saved to localStorage will\n override those passed to dat.GUI's constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n\n
\n\n
\n\n
"; + +var ControllerFactory = function ControllerFactory(object, property) { + var initialValue = object[property]; + if (Common.isArray(arguments[2]) || Common.isObject(arguments[2])) { + return new OptionController(object, property, arguments[2]); + } + if (Common.isNumber(initialValue)) { + if (Common.isNumber(arguments[2]) && Common.isNumber(arguments[3])) { + if (Common.isNumber(arguments[4])) { + return new NumberControllerSlider(object, property, arguments[2], arguments[3], arguments[4]); + } + return new NumberControllerSlider(object, property, arguments[2], arguments[3]); + } + if (Common.isNumber(arguments[4])) { + return new NumberControllerBox(object, property, { min: arguments[2], max: arguments[3], step: arguments[4] }); + } + return new NumberControllerBox(object, property, { min: arguments[2], max: arguments[3] }); + } + if (Common.isString(initialValue)) { + return new StringController(object, property); + } + if (Common.isFunction(initialValue)) { + return new FunctionController(object, property, ''); + } + if (Common.isBoolean(initialValue)) { + return new BooleanController(object, property); + } + return null; +}; + +function requestAnimationFrame(callback) { + setTimeout(callback, 1000 / 60); +} +var requestAnimationFrame$1 = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || requestAnimationFrame; + +var CenteredDiv = function () { + function CenteredDiv() { + classCallCheck(this, CenteredDiv); + this.backgroundElement = document.createElement('div'); + Common.extend(this.backgroundElement.style, { + backgroundColor: 'rgba(0,0,0,0.8)', + top: 0, + left: 0, + display: 'none', + zIndex: '1000', + opacity: 0, + WebkitTransition: 'opacity 0.2s linear', + transition: 'opacity 0.2s linear' + }); + dom.makeFullscreen(this.backgroundElement); + this.backgroundElement.style.position = 'fixed'; + this.domElement = document.createElement('div'); + Common.extend(this.domElement.style, { + position: 'fixed', + display: 'none', + zIndex: '1001', + opacity: 0, + WebkitTransition: '-webkit-transform 0.2s ease-out, opacity 0.2s linear', + transition: 'transform 0.2s ease-out, opacity 0.2s linear' + }); + document.body.appendChild(this.backgroundElement); + document.body.appendChild(this.domElement); + var _this = this; + dom.bind(this.backgroundElement, 'click', function () { + _this.hide(); + }); + } + createClass(CenteredDiv, [{ + key: 'show', + value: function show() { + var _this = this; + this.backgroundElement.style.display = 'block'; + this.domElement.style.display = 'block'; + this.domElement.style.opacity = 0; + this.domElement.style.webkitTransform = 'scale(1.1)'; + this.layout(); + Common.defer(function () { + _this.backgroundElement.style.opacity = 1; + _this.domElement.style.opacity = 1; + _this.domElement.style.webkitTransform = 'scale(1)'; + }); + } + }, { + key: 'hide', + value: function hide() { + var _this = this; + var hide = function hide() { + _this.domElement.style.display = 'none'; + _this.backgroundElement.style.display = 'none'; + dom.unbind(_this.domElement, 'webkitTransitionEnd', hide); + dom.unbind(_this.domElement, 'transitionend', hide); + dom.unbind(_this.domElement, 'oTransitionEnd', hide); + }; + dom.bind(this.domElement, 'webkitTransitionEnd', hide); + dom.bind(this.domElement, 'transitionend', hide); + dom.bind(this.domElement, 'oTransitionEnd', hide); + this.backgroundElement.style.opacity = 0; + this.domElement.style.opacity = 0; + this.domElement.style.webkitTransform = 'scale(1.1)'; + } + }, { + key: 'layout', + value: function layout() { + this.domElement.style.left = window.innerWidth / 2 - dom.getWidth(this.domElement) / 2 + 'px'; + this.domElement.style.top = window.innerHeight / 2 - dom.getHeight(this.domElement) / 2 + 'px'; + } + }]); + return CenteredDiv; +}(); + +var styleSheet = ___$insertStyle(".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity .1s linear;-o-transition:opacity .1s linear;-moz-transition:opacity .1s linear;transition:opacity .1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1 !important}.dg.main:hover .close-button,.dg.main .close-button.drag{opacity:1}.dg.main .close-button{-webkit-transition:opacity .1s linear;-o-transition:opacity .1s linear;-moz-transition:opacity .1s linear;transition:opacity .1s linear;border:0;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button.close-top{position:relative}.dg.main .close-button.close-bottom{position:absolute}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-y:visible}.dg.a.has-save>ul.close-top{margin-top:0}.dg.a.has-save>ul.close-bottom{margin-top:27px}.dg.a.has-save>ul.closed{margin-top:0}.dg.a .save-row{top:0;z-index:1002}.dg.a .save-row.close-top{position:relative}.dg.a .save-row.close-bottom{position:fixed}.dg li{-webkit-transition:height .1s ease-out;-o-transition:height .1s ease-out;-moz-transition:height .1s ease-out;transition:height .1s ease-out;-webkit-transition:overflow .1s linear;-o-transition:overflow .1s linear;-moz-transition:overflow .1s linear;transition:overflow .1s linear}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid rgba(0,0,0,0)}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li>*{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px;overflow:hidden}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .cr.function .property-name{width:100%}.dg .c{float:left;width:60%;position:relative}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:7px}.dg .c select{margin-top:5px}.dg .cr.function,.dg .cr.function .property-name,.dg .cr.function *,.dg .cr.boolean,.dg .cr.boolean *{cursor:pointer}.dg .cr.color{overflow:visible}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0px 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco, monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px 'Lucida Grande', sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px 4px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid rgba(255,255,255,0.2)}.dg .closed li.title{background-image:url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==)}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.color{border-left:3px solid}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2FA1D6}.dg .cr.number input[type=text]{color:#2FA1D6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.function:hover,.dg .cr.boolean:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2FA1D6;max-width:100%}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}\n"); + +css.inject(styleSheet); +var CSS_NAMESPACE = 'dg'; +var HIDE_KEY_CODE = 72; +var CLOSE_BUTTON_HEIGHT = 20; +var DEFAULT_DEFAULT_PRESET_NAME = 'Default'; +var SUPPORTS_LOCAL_STORAGE = function () { + try { + return !!window.localStorage; + } catch (e) { + return false; + } +}(); +var SAVE_DIALOGUE = void 0; +var autoPlaceVirgin = true; +var autoPlaceContainer = void 0; +var hide = false; +var hideableGuis = []; +var GUI = function GUI(pars) { + var _this = this; + var params = pars || {}; + this.domElement = document.createElement('div'); + this.__ul = document.createElement('ul'); + this.domElement.appendChild(this.__ul); + dom.addClass(this.domElement, CSS_NAMESPACE); + this.__folders = {}; + this.__controllers = []; + this.__rememberedObjects = []; + this.__rememberedObjectIndecesToControllers = []; + this.__listening = []; + params = Common.defaults(params, { + closeOnTop: false, + autoPlace: true, + width: GUI.DEFAULT_WIDTH + }); + params = Common.defaults(params, { + resizable: params.autoPlace, + hideable: params.autoPlace + }); + if (!Common.isUndefined(params.load)) { + if (params.preset) { + params.load.preset = params.preset; + } + } else { + params.load = { preset: DEFAULT_DEFAULT_PRESET_NAME }; + } + if (Common.isUndefined(params.parent) && params.hideable) { + hideableGuis.push(this); + } + params.resizable = Common.isUndefined(params.parent) && params.resizable; + if (params.autoPlace && Common.isUndefined(params.scrollable)) { + params.scrollable = true; + } + var useLocalStorage = SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(this, 'isLocal')) === 'true'; + var saveToLocalStorage = void 0; + var titleRow = void 0; + Object.defineProperties(this, + { + parent: { + get: function get$$1() { + return params.parent; + } + }, + scrollable: { + get: function get$$1() { + return params.scrollable; + } + }, + autoPlace: { + get: function get$$1() { + return params.autoPlace; + } + }, + closeOnTop: { + get: function get$$1() { + return params.closeOnTop; + } + }, + preset: { + get: function get$$1() { + if (_this.parent) { + return _this.getRoot().preset; + } + return params.load.preset; + }, + set: function set$$1(v) { + if (_this.parent) { + _this.getRoot().preset = v; + } else { + params.load.preset = v; + } + setPresetSelectIndex(this); + _this.revert(); + } + }, + width: { + get: function get$$1() { + return params.width; + }, + set: function set$$1(v) { + params.width = v; + setWidth(_this, v); + } + }, + name: { + get: function get$$1() { + return params.name; + }, + set: function set$$1(v) { + params.name = v; + if (titleRow) { + titleRow.innerHTML = params.name; + } + } + }, + closed: { + get: function get$$1() { + return params.closed; + }, + set: function set$$1(v) { + params.closed = v; + if (params.closed) { + dom.addClass(_this.__ul, GUI.CLASS_CLOSED); + } else { + dom.removeClass(_this.__ul, GUI.CLASS_CLOSED); + } + this.onResize(); + if (_this.__closeButton) { + _this.__closeButton.innerHTML = v ? GUI.TEXT_OPEN : GUI.TEXT_CLOSED; + } + } + }, + load: { + get: function get$$1() { + return params.load; + } + }, + useLocalStorage: { + get: function get$$1() { + return useLocalStorage; + }, + set: function set$$1(bool) { + if (SUPPORTS_LOCAL_STORAGE) { + useLocalStorage = bool; + if (bool) { + dom.bind(window, 'unload', saveToLocalStorage); + } else { + dom.unbind(window, 'unload', saveToLocalStorage); + } + localStorage.setItem(getLocalStorageHash(_this, 'isLocal'), bool); + } + } + } + }); + if (Common.isUndefined(params.parent)) { + this.closed = params.closed || false; + dom.addClass(this.domElement, GUI.CLASS_MAIN); + dom.makeSelectable(this.domElement, false); + if (SUPPORTS_LOCAL_STORAGE) { + if (useLocalStorage) { + _this.useLocalStorage = true; + var savedGui = localStorage.getItem(getLocalStorageHash(this, 'gui')); + if (savedGui) { + params.load = JSON.parse(savedGui); + } + } + } + this.__closeButton = document.createElement('div'); + this.__closeButton.innerHTML = GUI.TEXT_CLOSED; + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_BUTTON); + if (params.closeOnTop) { + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_TOP); + this.domElement.insertBefore(this.__closeButton, this.domElement.childNodes[0]); + } else { + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_BOTTOM); + this.domElement.appendChild(this.__closeButton); + } + dom.bind(this.__closeButton, 'click', function () { + _this.closed = !_this.closed; + }); + } else { + if (params.closed === undefined) { + params.closed = true; + } + var titleRowName = document.createTextNode(params.name); + dom.addClass(titleRowName, 'controller-name'); + titleRow = addRow(_this, titleRowName); + var onClickTitle = function onClickTitle(e) { + e.preventDefault(); + _this.closed = !_this.closed; + return false; + }; + dom.addClass(this.__ul, GUI.CLASS_CLOSED); + dom.addClass(titleRow, 'title'); + dom.bind(titleRow, 'click', onClickTitle); + if (!params.closed) { + this.closed = false; + } + } + if (params.autoPlace) { + if (Common.isUndefined(params.parent)) { + if (autoPlaceVirgin) { + autoPlaceContainer = document.createElement('div'); + dom.addClass(autoPlaceContainer, CSS_NAMESPACE); + dom.addClass(autoPlaceContainer, GUI.CLASS_AUTO_PLACE_CONTAINER); + document.body.appendChild(autoPlaceContainer); + autoPlaceVirgin = false; + } + autoPlaceContainer.appendChild(this.domElement); + dom.addClass(this.domElement, GUI.CLASS_AUTO_PLACE); + } + if (!this.parent) { + setWidth(_this, params.width); + } + } + this.__resizeHandler = function () { + _this.onResizeDebounced(); + }; + dom.bind(window, 'resize', this.__resizeHandler); + dom.bind(this.__ul, 'webkitTransitionEnd', this.__resizeHandler); + dom.bind(this.__ul, 'transitionend', this.__resizeHandler); + dom.bind(this.__ul, 'oTransitionEnd', this.__resizeHandler); + this.onResize(); + if (params.resizable) { + addResizeHandle(this); + } + saveToLocalStorage = function saveToLocalStorage() { + if (SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(_this, 'isLocal')) === 'true') { + localStorage.setItem(getLocalStorageHash(_this, 'gui'), JSON.stringify(_this.getSaveObject())); + } + }; + this.saveToLocalStorageIfPossible = saveToLocalStorage; + function resetWidth() { + var root = _this.getRoot(); + root.width += 1; + Common.defer(function () { + root.width -= 1; + }); + } + if (!params.parent) { + resetWidth(); + } +}; +GUI.toggleHide = function () { + hide = !hide; + Common.each(hideableGuis, function (gui) { + gui.domElement.style.display = hide ? 'none' : ''; + }); +}; +GUI.CLASS_AUTO_PLACE = 'a'; +GUI.CLASS_AUTO_PLACE_CONTAINER = 'ac'; +GUI.CLASS_MAIN = 'main'; +GUI.CLASS_CONTROLLER_ROW = 'cr'; +GUI.CLASS_TOO_TALL = 'taller-than-window'; +GUI.CLASS_CLOSED = 'closed'; +GUI.CLASS_CLOSE_BUTTON = 'close-button'; +GUI.CLASS_CLOSE_TOP = 'close-top'; +GUI.CLASS_CLOSE_BOTTOM = 'close-bottom'; +GUI.CLASS_DRAG = 'drag'; +GUI.DEFAULT_WIDTH = 245; +GUI.TEXT_CLOSED = 'Close Controls'; +GUI.TEXT_OPEN = 'Open Controls'; +GUI._keydownHandler = function (e) { + if (document.activeElement.type !== 'text' && (e.which === HIDE_KEY_CODE || e.keyCode === HIDE_KEY_CODE)) { + GUI.toggleHide(); + } +}; +dom.bind(window, 'keydown', GUI._keydownHandler, false); +Common.extend(GUI.prototype, +{ + add: function add(object, property) { + return _add(this, object, property, { + factoryArgs: Array.prototype.slice.call(arguments, 2) + }); + }, + addColor: function addColor(object, property) { + return _add(this, object, property, { + color: true + }); + }, + remove: function remove(controller) { + this.__ul.removeChild(controller.__li); + this.__controllers.splice(this.__controllers.indexOf(controller), 1); + var _this = this; + Common.defer(function () { + _this.onResize(); + }); + }, + destroy: function destroy() { + if (this.parent) { + throw new Error('Only the root GUI should be removed with .destroy(). ' + 'For subfolders, use gui.removeFolder(folder) instead.'); + } + if (this.autoPlace) { + autoPlaceContainer.removeChild(this.domElement); + } + var _this = this; + Common.each(this.__folders, function (subfolder) { + _this.removeFolder(subfolder); + }); + dom.unbind(window, 'keydown', GUI._keydownHandler, false); + removeListeners(this); + }, + addFolder: function addFolder(name) { + if (this.__folders[name] !== undefined) { + throw new Error('You already have a folder in this GUI by the' + ' name "' + name + '"'); + } + var newGuiParams = { name: name, parent: this }; + newGuiParams.autoPlace = this.autoPlace; + if (this.load && + this.load.folders && + this.load.folders[name]) { + newGuiParams.closed = this.load.folders[name].closed; + newGuiParams.load = this.load.folders[name]; + } + var gui = new GUI(newGuiParams); + this.__folders[name] = gui; + var li = addRow(this, gui.domElement); + dom.addClass(li, 'folder'); + return gui; + }, + removeFolder: function removeFolder(folder) { + this.__ul.removeChild(folder.domElement.parentElement); + delete this.__folders[folder.name]; + if (this.load && + this.load.folders && + this.load.folders[folder.name]) { + delete this.load.folders[folder.name]; + } + removeListeners(folder); + var _this = this; + Common.each(folder.__folders, function (subfolder) { + folder.removeFolder(subfolder); + }); + Common.defer(function () { + _this.onResize(); + }); + }, + open: function open() { + this.closed = false; + }, + close: function close() { + this.closed = true; + }, + hide: function hide() { + this.domElement.style.display = 'none'; + }, + show: function show() { + this.domElement.style.display = ''; + }, + onResize: function onResize() { + var root = this.getRoot(); + if (root.scrollable) { + var top = dom.getOffset(root.__ul).top; + var h = 0; + Common.each(root.__ul.childNodes, function (node) { + if (!(root.autoPlace && node === root.__save_row)) { + h += dom.getHeight(node); + } + }); + if (window.innerHeight - top - CLOSE_BUTTON_HEIGHT < h) { + dom.addClass(root.domElement, GUI.CLASS_TOO_TALL); + root.__ul.style.height = window.innerHeight - top - CLOSE_BUTTON_HEIGHT + 'px'; + } else { + dom.removeClass(root.domElement, GUI.CLASS_TOO_TALL); + root.__ul.style.height = 'auto'; + } + } + if (root.__resize_handle) { + Common.defer(function () { + root.__resize_handle.style.height = root.__ul.offsetHeight + 'px'; + }); + } + if (root.__closeButton) { + root.__closeButton.style.width = root.width + 'px'; + } + }, + onResizeDebounced: Common.debounce(function () { + this.onResize(); + }, 50), + remember: function remember() { + if (Common.isUndefined(SAVE_DIALOGUE)) { + SAVE_DIALOGUE = new CenteredDiv(); + SAVE_DIALOGUE.domElement.innerHTML = saveDialogContents; + } + if (this.parent) { + throw new Error('You can only call remember on a top level GUI.'); + } + var _this = this; + Common.each(Array.prototype.slice.call(arguments), function (object) { + if (_this.__rememberedObjects.length === 0) { + addSaveMenu(_this); + } + if (_this.__rememberedObjects.indexOf(object) === -1) { + _this.__rememberedObjects.push(object); + } + }); + if (this.autoPlace) { + setWidth(this, this.width); + } + }, + getRoot: function getRoot() { + var gui = this; + while (gui.parent) { + gui = gui.parent; + } + return gui; + }, + getSaveObject: function getSaveObject() { + var toReturn = this.load; + toReturn.closed = this.closed; + if (this.__rememberedObjects.length > 0) { + toReturn.preset = this.preset; + if (!toReturn.remembered) { + toReturn.remembered = {}; + } + toReturn.remembered[this.preset] = getCurrentPreset(this); + } + toReturn.folders = {}; + Common.each(this.__folders, function (element, key) { + toReturn.folders[key] = element.getSaveObject(); + }); + return toReturn; + }, + save: function save() { + if (!this.load.remembered) { + this.load.remembered = {}; + } + this.load.remembered[this.preset] = getCurrentPreset(this); + markPresetModified(this, false); + this.saveToLocalStorageIfPossible(); + }, + saveAs: function saveAs(presetName) { + if (!this.load.remembered) { + this.load.remembered = {}; + this.load.remembered[DEFAULT_DEFAULT_PRESET_NAME] = getCurrentPreset(this, true); + } + this.load.remembered[presetName] = getCurrentPreset(this); + this.preset = presetName; + addPresetOption(this, presetName, true); + this.saveToLocalStorageIfPossible(); + }, + revert: function revert(gui) { + Common.each(this.__controllers, function (controller) { + if (!this.getRoot().load.remembered) { + controller.setValue(controller.initialValue); + } else { + recallSavedValue(gui || this.getRoot(), controller); + } + if (controller.__onFinishChange) { + controller.__onFinishChange.call(controller, controller.getValue()); + } + }, this); + Common.each(this.__folders, function (folder) { + folder.revert(folder); + }); + if (!gui) { + markPresetModified(this.getRoot(), false); + } + }, + listen: function listen(controller) { + var init = this.__listening.length === 0; + this.__listening.push(controller); + if (init) { + updateDisplays(this.__listening); + } + }, + updateDisplay: function updateDisplay() { + Common.each(this.__controllers, function (controller) { + controller.updateDisplay(); + }); + Common.each(this.__folders, function (folder) { + folder.updateDisplay(); + }); + } +}); +function addRow(gui, newDom, liBefore) { + var li = document.createElement('li'); + if (newDom) { + li.appendChild(newDom); + } + if (liBefore) { + gui.__ul.insertBefore(li, liBefore); + } else { + gui.__ul.appendChild(li); + } + gui.onResize(); + return li; +} +function removeListeners(gui) { + dom.unbind(window, 'resize', gui.__resizeHandler); + if (gui.saveToLocalStorageIfPossible) { + dom.unbind(window, 'unload', gui.saveToLocalStorageIfPossible); + } +} +function markPresetModified(gui, modified) { + var opt = gui.__preset_select[gui.__preset_select.selectedIndex]; + if (modified) { + opt.innerHTML = opt.value + '*'; + } else { + opt.innerHTML = opt.value; + } +} +function augmentController(gui, li, controller) { + controller.__li = li; + controller.__gui = gui; + Common.extend(controller, { + options: function options(_options) { + if (arguments.length > 1) { + var nextSibling = controller.__li.nextElementSibling; + controller.remove(); + return _add(gui, controller.object, controller.property, { + before: nextSibling, + factoryArgs: [Common.toArray(arguments)] + }); + } + if (Common.isArray(_options) || Common.isObject(_options)) { + var _nextSibling = controller.__li.nextElementSibling; + controller.remove(); + return _add(gui, controller.object, controller.property, { + before: _nextSibling, + factoryArgs: [_options] + }); + } + }, + name: function name(_name) { + controller.__li.firstElementChild.firstElementChild.innerHTML = _name; + return controller; + }, + listen: function listen() { + controller.__gui.listen(controller); + return controller; + }, + remove: function remove() { + controller.__gui.remove(controller); + return controller; + } + }); + if (controller instanceof NumberControllerSlider) { + var box = new NumberControllerBox(controller.object, controller.property, { min: controller.__min, max: controller.__max, step: controller.__step }); + Common.each(['updateDisplay', 'onChange', 'onFinishChange', 'step', 'min', 'max'], function (method) { + var pc = controller[method]; + var pb = box[method]; + controller[method] = box[method] = function () { + var args = Array.prototype.slice.call(arguments); + pb.apply(box, args); + return pc.apply(controller, args); + }; + }); + dom.addClass(li, 'has-slider'); + controller.domElement.insertBefore(box.domElement, controller.domElement.firstElementChild); + } else if (controller instanceof NumberControllerBox) { + var r = function r(returned) { + if (Common.isNumber(controller.__min) && Common.isNumber(controller.__max)) { + var oldName = controller.__li.firstElementChild.firstElementChild.innerHTML; + var wasListening = controller.__gui.__listening.indexOf(controller) > -1; + controller.remove(); + var newController = _add(gui, controller.object, controller.property, { + before: controller.__li.nextElementSibling, + factoryArgs: [controller.__min, controller.__max, controller.__step] + }); + newController.name(oldName); + if (wasListening) newController.listen(); + return newController; + } + return returned; + }; + controller.min = Common.compose(r, controller.min); + controller.max = Common.compose(r, controller.max); + } else if (controller instanceof BooleanController) { + dom.bind(li, 'click', function () { + dom.fakeEvent(controller.__checkbox, 'click'); + }); + dom.bind(controller.__checkbox, 'click', function (e) { + e.stopPropagation(); + }); + } else if (controller instanceof FunctionController) { + dom.bind(li, 'click', function () { + dom.fakeEvent(controller.__button, 'click'); + }); + dom.bind(li, 'mouseover', function () { + dom.addClass(controller.__button, 'hover'); + }); + dom.bind(li, 'mouseout', function () { + dom.removeClass(controller.__button, 'hover'); + }); + } else if (controller instanceof ColorController) { + dom.addClass(li, 'color'); + controller.updateDisplay = Common.compose(function (val) { + li.style.borderLeftColor = controller.__color.toString(); + return val; + }, controller.updateDisplay); + controller.updateDisplay(); + } + controller.setValue = Common.compose(function (val) { + if (gui.getRoot().__preset_select && controller.isModified()) { + markPresetModified(gui.getRoot(), true); + } + return val; + }, controller.setValue); +} +function recallSavedValue(gui, controller) { + var root = gui.getRoot(); + var matchedIndex = root.__rememberedObjects.indexOf(controller.object); + if (matchedIndex !== -1) { + var controllerMap = root.__rememberedObjectIndecesToControllers[matchedIndex]; + if (controllerMap === undefined) { + controllerMap = {}; + root.__rememberedObjectIndecesToControllers[matchedIndex] = controllerMap; + } + controllerMap[controller.property] = controller; + if (root.load && root.load.remembered) { + var presetMap = root.load.remembered; + var preset = void 0; + if (presetMap[gui.preset]) { + preset = presetMap[gui.preset]; + } else if (presetMap[DEFAULT_DEFAULT_PRESET_NAME]) { + preset = presetMap[DEFAULT_DEFAULT_PRESET_NAME]; + } else { + return; + } + if (preset[matchedIndex] && preset[matchedIndex][controller.property] !== undefined) { + var value = preset[matchedIndex][controller.property]; + controller.initialValue = value; + controller.setValue(value); + } + } + } +} +function _add(gui, object, property, params) { + if (object[property] === undefined) { + throw new Error('Object "' + object + '" has no property "' + property + '"'); + } + var controller = void 0; + if (params.color) { + controller = new ColorController(object, property); + } else { + var factoryArgs = [object, property].concat(params.factoryArgs); + controller = ControllerFactory.apply(gui, factoryArgs); + } + if (params.before instanceof Controller) { + params.before = params.before.__li; + } + recallSavedValue(gui, controller); + dom.addClass(controller.domElement, 'c'); + var name = document.createElement('span'); + dom.addClass(name, 'property-name'); + name.innerHTML = controller.property; + var container = document.createElement('div'); + container.appendChild(name); + container.appendChild(controller.domElement); + var li = addRow(gui, container, params.before); + dom.addClass(li, GUI.CLASS_CONTROLLER_ROW); + if (controller instanceof ColorController) { + dom.addClass(li, 'color'); + } else { + dom.addClass(li, _typeof(controller.getValue())); + } + augmentController(gui, li, controller); + gui.__controllers.push(controller); + return controller; +} +function getLocalStorageHash(gui, key) { + return document.location.href + '.' + key; +} +function addPresetOption(gui, name, setSelected) { + var opt = document.createElement('option'); + opt.innerHTML = name; + opt.value = name; + gui.__preset_select.appendChild(opt); + if (setSelected) { + gui.__preset_select.selectedIndex = gui.__preset_select.length - 1; + } +} +function showHideExplain(gui, explain) { + explain.style.display = gui.useLocalStorage ? 'block' : 'none'; +} +function addSaveMenu(gui) { + var div = gui.__save_row = document.createElement('li'); + dom.addClass(gui.domElement, 'has-save'); + gui.__ul.insertBefore(div, gui.__ul.firstChild); + dom.addClass(div, 'save-row'); + var gears = document.createElement('span'); + gears.innerHTML = ' '; + dom.addClass(gears, 'button gears'); + var button = document.createElement('span'); + button.innerHTML = 'Save'; + dom.addClass(button, 'button'); + dom.addClass(button, 'save'); + var button2 = document.createElement('span'); + button2.innerHTML = 'New'; + dom.addClass(button2, 'button'); + dom.addClass(button2, 'save-as'); + var button3 = document.createElement('span'); + button3.innerHTML = 'Revert'; + dom.addClass(button3, 'button'); + dom.addClass(button3, 'revert'); + var select = gui.__preset_select = document.createElement('select'); + if (gui.load && gui.load.remembered) { + Common.each(gui.load.remembered, function (value, key) { + addPresetOption(gui, key, key === gui.preset); + }); + } else { + addPresetOption(gui, DEFAULT_DEFAULT_PRESET_NAME, false); + } + dom.bind(select, 'change', function () { + for (var index = 0; index < gui.__preset_select.length; index++) { + gui.__preset_select[index].innerHTML = gui.__preset_select[index].value; + } + gui.preset = this.value; + }); + div.appendChild(select); + div.appendChild(gears); + div.appendChild(button); + div.appendChild(button2); + div.appendChild(button3); + if (SUPPORTS_LOCAL_STORAGE) { + var explain = document.getElementById('dg-local-explain'); + var localStorageCheckBox = document.getElementById('dg-local-storage'); + var saveLocally = document.getElementById('dg-save-locally'); + saveLocally.style.display = 'block'; + if (localStorage.getItem(getLocalStorageHash(gui, 'isLocal')) === 'true') { + localStorageCheckBox.setAttribute('checked', 'checked'); + } + showHideExplain(gui, explain); + dom.bind(localStorageCheckBox, 'change', function () { + gui.useLocalStorage = !gui.useLocalStorage; + showHideExplain(gui, explain); + }); + } + var newConstructorTextArea = document.getElementById('dg-new-constructor'); + dom.bind(newConstructorTextArea, 'keydown', function (e) { + if (e.metaKey && (e.which === 67 || e.keyCode === 67)) { + SAVE_DIALOGUE.hide(); + } + }); + dom.bind(gears, 'click', function () { + newConstructorTextArea.innerHTML = JSON.stringify(gui.getSaveObject(), undefined, 2); + SAVE_DIALOGUE.show(); + newConstructorTextArea.focus(); + newConstructorTextArea.select(); + }); + dom.bind(button, 'click', function () { + gui.save(); + }); + dom.bind(button2, 'click', function () { + var presetName = prompt('Enter a new preset name.'); + if (presetName) { + gui.saveAs(presetName); + } + }); + dom.bind(button3, 'click', function () { + gui.revert(); + }); +} +function addResizeHandle(gui) { + var pmouseX = void 0; + gui.__resize_handle = document.createElement('div'); + Common.extend(gui.__resize_handle.style, { + width: '6px', + marginLeft: '-3px', + height: '200px', + cursor: 'ew-resize', + position: 'absolute' + }); + function drag(e) { + e.preventDefault(); + gui.width += pmouseX - e.clientX; + gui.onResize(); + pmouseX = e.clientX; + return false; + } + function dragStop() { + dom.removeClass(gui.__closeButton, GUI.CLASS_DRAG); + dom.unbind(window, 'mousemove', drag); + dom.unbind(window, 'mouseup', dragStop); + } + function dragStart(e) { + e.preventDefault(); + pmouseX = e.clientX; + dom.addClass(gui.__closeButton, GUI.CLASS_DRAG); + dom.bind(window, 'mousemove', drag); + dom.bind(window, 'mouseup', dragStop); + return false; + } + dom.bind(gui.__resize_handle, 'mousedown', dragStart); + dom.bind(gui.__closeButton, 'mousedown', dragStart); + gui.domElement.insertBefore(gui.__resize_handle, gui.domElement.firstElementChild); +} +function setWidth(gui, w) { + gui.domElement.style.width = w + 'px'; + if (gui.__save_row && gui.autoPlace) { + gui.__save_row.style.width = w + 'px'; + } + if (gui.__closeButton) { + gui.__closeButton.style.width = w + 'px'; + } +} +function getCurrentPreset(gui, useInitialValues) { + var toReturn = {}; + Common.each(gui.__rememberedObjects, function (val, index) { + var savedValues = {}; + var controllerMap = gui.__rememberedObjectIndecesToControllers[index]; + Common.each(controllerMap, function (controller, property) { + savedValues[property] = useInitialValues ? controller.initialValue : controller.getValue(); + }); + toReturn[index] = savedValues; + }); + return toReturn; +} +function setPresetSelectIndex(gui) { + for (var index = 0; index < gui.__preset_select.length; index++) { + if (gui.__preset_select[index].value === gui.preset) { + gui.__preset_select.selectedIndex = index; + } + } +} +function updateDisplays(controllerArray) { + if (controllerArray.length !== 0) { + requestAnimationFrame$1.call(window, function () { + updateDisplays(controllerArray); + }); + } + Common.each(controllerArray, function (c) { + c.updateDisplay(); + }); +} + +var color = { + Color: Color, + math: ColorMath, + interpret: interpret +}; +var controllers = { + Controller: Controller, + BooleanController: BooleanController, + OptionController: OptionController, + StringController: StringController, + NumberController: NumberController, + NumberControllerBox: NumberControllerBox, + NumberControllerSlider: NumberControllerSlider, + FunctionController: FunctionController, + ColorController: ColorController +}; +var dom$1 = { dom: dom }; +var gui = { GUI: GUI }; +var GUI$1 = GUI; +var index = { + color: color, + controllers: controllers, + dom: dom$1, + gui: gui, + GUI: GUI$1 +}; + + +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (index); +//# sourceMappingURL=dat.gui.module.js.map + + +/***/ }), + +/***/ "../../node_modules/park-miller/index.js": +/*!***********************************************!*\ + !*** ../../node_modules/park-miller/index.js ***! + \***********************************************/ +/***/ ((module) => { + + +const MAX_INT32 = 2147483647; +const MINSTD = 16807; + +class ParkMiller { + constructor(seed) { + if (!Number.isInteger(seed)) { + throw new TypeError('Expected `seed` to be a `integer`'); + } + + this._seed = seed % MAX_INT32; + + if (this._seed <= 0) { + this._seed += (MAX_INT32 - 1); + } + } + + integer() { + this._seed *= MINSTD; + this._seed %= MAX_INT32; + return this._seed; + } + + integerInRange(min, max) { + return Math.round(this.floatInRange(min, max)); + } + + float() { + return (this.integer() - 1) / (MAX_INT32 - 1); + } + + floatInRange(min, max) { + return min + ((max - min) * this.float()); + } + + boolean() { + return this.integer() % 2 === 0; + } +} + +module.exports = ParkMiller; + + +/***/ }), + +/***/ "./canvas.ts": +/*!*******************!*\ + !*** ./canvas.ts ***! + \*******************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createCanvas: () => (/* binding */ createCanvas), +/* harmony export */ drawOptions: () => (/* binding */ drawOptions) +/* harmony export */ }); +/* harmony import */ var _snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/draw/drawWorld */ "../draw/drawWorld.ts"); + +const drawOptions = { + sizeDotBorderRadius: 2, + sizeCell: 16, + sizeDot: 12, + colorDotBorder: "#1b1f230a", + colorDots: { + 1: "#9be9a8", + 2: "#40c463", + 3: "#30a14e", + 4: "#216e39", + }, + colorEmpty: "#ebedf0", + colorSnake: "purple", + dark: { + colorEmpty: "#161b22", + colorDots: { 1: "#01311f", 2: "#034525", 3: "#0f6d31", 4: "#00c647" }, + }, +}; +const getPointedCell = (canvas) => ({ pageX, pageY }) => { + const { left, top } = canvas.getBoundingClientRect(); + const x = Math.floor((pageX - left) / drawOptions.sizeCell) - 1; + const y = Math.floor((pageY - top) / drawOptions.sizeCell) - 2; + return { x, y }; +}; +const createCanvas = ({ width, height, }) => { + const canvas = document.createElement("canvas"); + const upscale = 2; + const w = drawOptions.sizeCell * (width + 4); + const h = drawOptions.sizeCell * (height + 4) + 200; + canvas.width = w * upscale; + canvas.height = h * upscale; + canvas.style.width = w + "px"; + canvas.style.height = h + "px"; + canvas.style.display = "block"; + // canvas.style.pointerEvents = "none"; + const cellInfo = document.createElement("div"); + cellInfo.style.height = "20px"; + document.body.appendChild(cellInfo); + document.body.appendChild(canvas); + canvas.addEventListener("mousemove", (e) => { + const { x, y } = getPointedCell(canvas)(e); + cellInfo.innerText = [x, y] + .map((u) => u.toString().padStart(2, " ")) + .join(" / "); + }); + const ctx = canvas.getContext("2d"); + ctx.scale(upscale, upscale); + const draw = (grid, snake, stack) => { + ctx.clearRect(0, 0, 9999, 9999); + (0,_snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__.drawWorld)(ctx, grid, null, snake, stack, drawOptions); + }; + const drawLerp = (grid, snake0, snake1, stack, k) => { + ctx.clearRect(0, 0, 9999, 9999); + (0,_snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__.drawLerpWorld)(ctx, grid, null, snake0, snake1, stack, k, drawOptions); + }; + const highlightCell = (x, y, color = "orange") => { + ctx.fillStyle = color; + ctx.beginPath(); + ctx.fillRect((1 + x + 0.5) * 16 - 2, (2 + y + 0.5) * 16 - 2, 4, 4); + }; + return { + draw, + drawLerp, + highlightCell, + canvas, + getPointedCell: getPointedCell(canvas), + ctx, + }; +}; + + +/***/ }), + +/***/ "./menu.ts": +/*!*****************!*\ + !*** ./menu.ts ***! + \*****************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ gui: () => (/* binding */ gui) +/* harmony export */ }); +/* harmony import */ var dat_gui__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! dat.gui */ "../../node_modules/dat.gui/build/dat.gui.module.js"); +/* harmony import */ var _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/__fixtures__/grid */ "../types/__fixtures__/grid.ts"); +/* harmony import */ var _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/__fixtures__/snake */ "../types/__fixtures__/snake.ts"); +/* harmony import */ var _sample__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sample */ "./sample.ts"); + + + + +const demos = __webpack_require__(/*! ./demo.json */ "./demo.json"); +const gui = new dat_gui__WEBPACK_IMPORTED_MODULE_0__.GUI(); +const config = { + snake: Object.entries(_snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__).find(([_, s]) => s === _sample__WEBPACK_IMPORTED_MODULE_3__.snake)[0], + grid: Object.entries(_snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__).find(([_, s]) => s === _sample__WEBPACK_IMPORTED_MODULE_3__.grid)[0], + demo: demos[0], +}; +{ + const d = window.location.pathname.match(/(\w+)\.html/); + if (d && demos.includes(d[1])) + config.demo = d[1]; +} +const onChange = () => { + const search = new URLSearchParams({ + snake: config.snake, + grid: config.grid, + }).toString(); + const url = new URL(config.demo + ".html?" + search, window.location.href).toString(); + window.location.href = url; +}; +gui.add(config, "demo", demos).onChange(onChange); +gui.add(config, "grid", Object.keys(_snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__)).onChange(onChange); +gui.add(config, "snake", Object.keys(_snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__)).onChange(onChange); + + +/***/ }), + +/***/ "./sample.ts": +/*!*******************!*\ + !*** ./sample.ts ***! + \*******************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ grid: () => (/* binding */ grid), +/* harmony export */ snake: () => (/* binding */ snake) +/* harmony export */ }); +/* harmony import */ var _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/__fixtures__/grid */ "../types/__fixtures__/grid.ts"); +/* harmony import */ var _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/__fixtures__/snake */ "../types/__fixtures__/snake.ts"); + + +const sp = new URLSearchParams(window.location.search); +const gLabel = sp.get("grid") || "simple"; +const sLabel = sp.get("snake") || "snake3"; +//@ts-ignore +const grid = _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__[gLabel] || _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__.simple; +//@ts-ignore +const snake = _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__[sLabel] || _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__.snake3; + + +/***/ }), + +/***/ "../draw/drawGrid.ts": +/*!***************************!*\ + !*** ../draw/drawGrid.ts ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawGrid: () => (/* binding */ drawGrid) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _pathRoundedRect__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./pathRoundedRect */ "../draw/pathRoundedRect.ts"); + + +const drawGrid = (ctx, grid, cells, o) => { + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + if (!cells || cells.some((c) => c.x === x && c.y === y)) { + const c = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + // @ts-ignore + const color = !c ? o.colorEmpty : o.colorDots[c]; + ctx.save(); + ctx.translate(x * o.sizeCell + (o.sizeCell - o.sizeDot) / 2, y * o.sizeCell + (o.sizeCell - o.sizeDot) / 2); + ctx.fillStyle = color; + ctx.strokeStyle = o.colorDotBorder; + ctx.lineWidth = 1; + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_1__.pathRoundedRect)(ctx, o.sizeDot, o.sizeDot, o.sizeDotBorderRadius); + ctx.fill(); + ctx.stroke(); + ctx.closePath(); + ctx.restore(); + } + } +}; + + +/***/ }), + +/***/ "../draw/drawSnake.ts": +/*!****************************!*\ + !*** ../draw/drawSnake.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawSnake: () => (/* binding */ drawSnake), +/* harmony export */ drawSnakeLerp: () => (/* binding */ drawSnakeLerp) +/* harmony export */ }); +/* harmony import */ var _pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./pathRoundedRect */ "../draw/pathRoundedRect.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); + + +const drawSnake = (ctx, snake, o) => { + const cells = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.snakeToCells)(snake); + for (let i = 0; i < cells.length; i++) { + const u = (i + 1) * 0.6; + ctx.save(); + ctx.fillStyle = o.colorSnake; + ctx.translate(cells[i].x * o.sizeCell + u, cells[i].y * o.sizeCell + u); + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__.pathRoundedRect)(ctx, o.sizeCell - u * 2, o.sizeCell - u * 2, (o.sizeCell - u * 2) * 0.25); + ctx.fill(); + ctx.restore(); + } +}; +const lerp = (k, a, b) => (1 - k) * a + k * b; +const clamp = (x, a, b) => Math.max(a, Math.min(b, x)); +const drawSnakeLerp = (ctx, snake0, snake1, k, o) => { + const m = 0.8; + const n = snake0.length / 2; + for (let i = 0; i < n; i++) { + const u = (i + 1) * 0.6 * (o.sizeCell / 16); + const a = (1 - m) * (i / Math.max(n - 1, 1)); + const ki = clamp((k - a) / m, 0, 1); + const x = lerp(ki, snake0[i * 2 + 0], snake1[i * 2 + 0]) - 2; + const y = lerp(ki, snake0[i * 2 + 1], snake1[i * 2 + 1]) - 2; + ctx.save(); + ctx.fillStyle = o.colorSnake; + ctx.translate(x * o.sizeCell + u, y * o.sizeCell + u); + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__.pathRoundedRect)(ctx, o.sizeCell - u * 2, o.sizeCell - u * 2, (o.sizeCell - u * 2) * 0.25); + ctx.fill(); + ctx.restore(); + } +}; + + +/***/ }), + +/***/ "../draw/drawWorld.ts": +/*!****************************!*\ + !*** ../draw/drawWorld.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawLerpWorld: () => (/* binding */ drawLerpWorld), +/* harmony export */ drawStack: () => (/* binding */ drawStack), +/* harmony export */ drawWorld: () => (/* binding */ drawWorld), +/* harmony export */ getCanvasWorldSize: () => (/* binding */ getCanvasWorldSize) +/* harmony export */ }); +/* harmony import */ var _drawGrid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./drawGrid */ "../draw/drawGrid.ts"); +/* harmony import */ var _drawSnake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./drawSnake */ "../draw/drawSnake.ts"); + + +const drawStack = (ctx, stack, max, width, o) => { + ctx.save(); + const m = width / max; + for (let i = 0; i < stack.length; i++) { + // @ts-ignore + ctx.fillStyle = o.colorDots[stack[i]]; + ctx.fillRect(i * m, 0, m + width * 0.005, 10); + } + ctx.restore(); +}; +const drawWorld = (ctx, grid, cells, snake, stack, o) => { + ctx.save(); + ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); + (0,_drawGrid__WEBPACK_IMPORTED_MODULE_0__.drawGrid)(ctx, grid, cells, o); + (0,_drawSnake__WEBPACK_IMPORTED_MODULE_1__.drawSnake)(ctx, snake, o); + ctx.restore(); + ctx.save(); + ctx.translate(o.sizeCell, (grid.height + 4) * o.sizeCell); + const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length); + drawStack(ctx, stack, max, grid.width * o.sizeCell, o); + ctx.restore(); + // ctx.save(); + // ctx.translate(o.sizeCell + 100, (grid.height + 4) * o.sizeCell + 100); + // ctx.scale(0.6, 0.6); + // drawCircleStack(ctx, stack, o); + // ctx.restore(); +}; +const drawLerpWorld = (ctx, grid, cells, snake0, snake1, stack, k, o) => { + ctx.save(); + ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); + (0,_drawGrid__WEBPACK_IMPORTED_MODULE_0__.drawGrid)(ctx, grid, cells, o); + (0,_drawSnake__WEBPACK_IMPORTED_MODULE_1__.drawSnakeLerp)(ctx, snake0, snake1, k, o); + ctx.translate(0, (grid.height + 2) * o.sizeCell); + const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length); + drawStack(ctx, stack, max, grid.width * o.sizeCell, o); + ctx.restore(); +}; +const getCanvasWorldSize = (grid, o) => { + const width = o.sizeCell * (grid.width + 2); + const height = o.sizeCell * (grid.height + 4) + 30; + return { width, height }; +}; + + +/***/ }), + +/***/ "../draw/pathRoundedRect.ts": +/*!**********************************!*\ + !*** ../draw/pathRoundedRect.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ pathRoundedRect: () => (/* binding */ pathRoundedRect) +/* harmony export */ }); +const pathRoundedRect = (ctx, width, height, borderRadius) => { + ctx.moveTo(borderRadius, 0); + ctx.arcTo(width, 0, width, height, borderRadius); + ctx.arcTo(width, height, 0, height, borderRadius); + ctx.arcTo(0, height, 0, 0, borderRadius); + ctx.arcTo(0, 0, width, 0, borderRadius); +}; + + +/***/ }), + +/***/ "../solver/outside.ts": +/*!****************************!*\ + !*** ../solver/outside.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createOutside: () => (/* binding */ createOutside), +/* harmony export */ fillOutside: () => (/* binding */ fillOutside), +/* harmony export */ isOutside: () => (/* binding */ isOutside) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); + + +const createOutside = (grid, color = 0) => { + const outside = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.createEmptyGrid)(grid.width, grid.height); + for (let x = outside.width; x--;) + for (let y = outside.height; y--;) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(outside, x, y, 1); + fillOutside(outside, grid, color); + return outside; +}; +const fillOutside = (outside, grid, color = 0) => { + let changed = true; + while (changed) { + changed = false; + for (let x = outside.width; x--;) + for (let y = outside.height; y--;) + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) <= color && + !isOutside(outside, x, y) && + _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4.some((a) => isOutside(outside, x + a.x, y + a.y))) { + changed = true; + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(outside, x, y); + } + } + return outside; +}; +const isOutside = (outside, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(outside, x, y) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(outside, x, y)); + + +/***/ }), + +/***/ "../types/__fixtures__/createFromAscii.ts": +/*!************************************************!*\ + !*** ../types/__fixtures__/createFromAscii.ts ***! + \************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createFromAscii: () => (/* binding */ createFromAscii) +/* harmony export */ }); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../grid */ "../types/grid.ts"); + +const createFromAscii = (ascii) => { + const a = ascii.split("\n"); + if (a[0] === "") + a.shift(); + const height = a.length; + const width = Math.max(...a.map((r) => r.length)); + const grid = (0,_grid__WEBPACK_IMPORTED_MODULE_0__.createEmptyGrid)(width, height); + for (let x = width; x--;) + for (let y = height; y--;) { + const c = a[y][x]; + const color = (c === "#" && 3) || (c === "@" && 2) || (c === "." && 1) || +c; + if (c) + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(grid, x, y, color); + } + return grid; +}; + + +/***/ }), + +/***/ "../types/__fixtures__/grid.ts": +/*!*************************************!*\ + !*** ../types/__fixtures__/grid.ts ***! + \*************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ closedO: () => (/* binding */ closedO), +/* harmony export */ closedP: () => (/* binding */ closedP), +/* harmony export */ closedU: () => (/* binding */ closedU), +/* harmony export */ corner: () => (/* binding */ corner), +/* harmony export */ empty: () => (/* binding */ empty), +/* harmony export */ enclaveBorder: () => (/* binding */ enclaveBorder), +/* harmony export */ enclaveK: () => (/* binding */ enclaveK), +/* harmony export */ enclaveM: () => (/* binding */ enclaveM), +/* harmony export */ enclaveN: () => (/* binding */ enclaveN), +/* harmony export */ enclaveU: () => (/* binding */ enclaveU), +/* harmony export */ realistic: () => (/* binding */ realistic), +/* harmony export */ realisticFull: () => (/* binding */ realisticFull), +/* harmony export */ simple: () => (/* binding */ simple), +/* harmony export */ small: () => (/* binding */ small), +/* harmony export */ smallFull: () => (/* binding */ smallFull), +/* harmony export */ smallPacked: () => (/* binding */ smallPacked), +/* harmony export */ tunnels: () => (/* binding */ tunnels) +/* harmony export */ }); +/* harmony import */ var park_miller__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! park-miller */ "../../node_modules/park-miller/index.js"); +/* harmony import */ var park_miller__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(park_miller__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../grid */ "../types/grid.ts"); +/* harmony import */ var _randomlyFillGrid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../randomlyFillGrid */ "../types/randomlyFillGrid.ts"); +/* harmony import */ var _createFromAscii__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./createFromAscii */ "../types/__fixtures__/createFromAscii.ts"); + + + + +const colors = [1, 2, 3]; +// empty small grid +const empty = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +// empty small grid with a unique color at the middle +const simple = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(simple, 2, 2, 1); +// empty small grid with color at each corner +const corner = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 0, 4, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 4, 0, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 4, 4, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 0, 0, 1); +const enclaveN = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #.# + # + +`); +const enclaveBorder = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + #.# + # + +`); +const enclaveM = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### + # # + # . # + # # + # # +`); +const enclaveK = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + # .# + # # + # # + # # +`); +const enclaveU = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + #..# + #..# + #.# + # # . +`); +const closedP = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### + ##.# + ## # + ## +`); +const closedU = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + #..# + #..# + #.# + ### +`); +const closedO = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ####### + # # + # . # + # # + ####### +`); +const tunnels = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### ### ### + #.# #.# #.# + #.# ### # # +`); +const createRandom = (width, height, emptyP) => { + const grid = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(width, height); + const pm = new (park_miller__WEBPACK_IMPORTED_MODULE_0___default())(10); + const random = pm.integerInRange.bind(pm); + (0,_randomlyFillGrid__WEBPACK_IMPORTED_MODULE_2__.randomlyFillGrid)(grid, { colors, emptyP }, random); + return grid; +}; +// small realistic +const small = createRandom(10, 7, 3); +const smallPacked = createRandom(10, 7, 1); +const smallFull = createRandom(10, 7, 0); +// small realistic +const realistic = createRandom(52, 7, 3); +const realisticFull = createRandom(52, 7, 0); + + +/***/ }), + +/***/ "../types/__fixtures__/snake.ts": +/*!**************************************!*\ + !*** ../types/__fixtures__/snake.ts ***! + \**************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ snake1: () => (/* binding */ snake1), +/* harmony export */ snake3: () => (/* binding */ snake3), +/* harmony export */ snake4: () => (/* binding */ snake4), +/* harmony export */ snake5: () => (/* binding */ snake5), +/* harmony export */ snake9: () => (/* binding */ snake9) +/* harmony export */ }); +/* harmony import */ var _snake__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../snake */ "../types/snake.ts"); + +const create = (length) => (0,_snake__WEBPACK_IMPORTED_MODULE_0__.createSnakeFromCells)(Array.from({ length }, (_, i) => ({ x: i, y: -1 }))); +const snake1 = create(1); +const snake3 = create(3); +const snake4 = create(4); +const snake5 = create(5); +const snake9 = create(9); + + +/***/ }), + +/***/ "../types/grid.ts": +/*!************************!*\ + !*** ../types/grid.ts ***! + \************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copyGrid: () => (/* binding */ copyGrid), +/* harmony export */ createEmptyGrid: () => (/* binding */ createEmptyGrid), +/* harmony export */ getColor: () => (/* binding */ getColor), +/* harmony export */ gridEquals: () => (/* binding */ gridEquals), +/* harmony export */ isEmpty: () => (/* binding */ isEmpty), +/* harmony export */ isGridEmpty: () => (/* binding */ isGridEmpty), +/* harmony export */ isInside: () => (/* binding */ isInside), +/* harmony export */ isInsideLarge: () => (/* binding */ isInsideLarge), +/* harmony export */ setColor: () => (/* binding */ setColor), +/* harmony export */ setColorEmpty: () => (/* binding */ setColorEmpty) +/* harmony export */ }); +const isInside = (grid, x, y) => x >= 0 && y >= 0 && x < grid.width && y < grid.height; +const isInsideLarge = (grid, m, x, y) => x >= -m && y >= -m && x < grid.width + m && y < grid.height + m; +const copyGrid = ({ width, height, data }) => ({ + width, + height, + data: Uint8Array.from(data), +}); +const getIndex = (grid, x, y) => x * grid.height + y; +const getColor = (grid, x, y) => grid.data[getIndex(grid, x, y)]; +const isEmpty = (color) => color === 0; +const setColor = (grid, x, y, color) => { + grid.data[getIndex(grid, x, y)] = color || 0; +}; +const setColorEmpty = (grid, x, y) => { + setColor(grid, x, y, 0); +}; +/** + * return true if the grid is empty + */ +const isGridEmpty = (grid) => grid.data.every((x) => x === 0); +const gridEquals = (a, b) => a.data.every((_, i) => a.data[i] === b.data[i]); +const createEmptyGrid = (width, height) => ({ + width, + height, + data: new Uint8Array(width * height), +}); + + +/***/ }), + +/***/ "../types/point.ts": +/*!*************************!*\ + !*** ../types/point.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ around4: () => (/* binding */ around4), +/* harmony export */ pointEquals: () => (/* binding */ pointEquals) +/* harmony export */ }); +const around4 = [ + { x: 1, y: 0 }, + { x: 0, y: -1 }, + { x: -1, y: 0 }, + { x: 0, y: 1 }, +]; +const pointEquals = (a, b) => a.x === b.x && a.y === b.y; + + +/***/ }), + +/***/ "../types/randomlyFillGrid.ts": +/*!************************************!*\ + !*** ../types/randomlyFillGrid.ts ***! + \************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ randomlyFillGrid: () => (/* binding */ randomlyFillGrid) +/* harmony export */ }); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./grid */ "../types/grid.ts"); + +const defaultRand = (a, b) => Math.floor(Math.random() * (b - a + 1)) + a; +const randomlyFillGrid = (grid, { colors = [1, 2, 3], emptyP = 2, } = {}, rand = defaultRand) => { + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + const k = rand(-emptyP, colors.length - 1); + if (k >= 0) + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(grid, x, y, colors[k]); + else + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); + } +}; + + +/***/ }), + +/***/ "../types/snake.ts": +/*!*************************!*\ + !*** ../types/snake.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copySnake: () => (/* binding */ copySnake), +/* harmony export */ createSnakeFromCells: () => (/* binding */ createSnakeFromCells), +/* harmony export */ getHeadX: () => (/* binding */ getHeadX), +/* harmony export */ getHeadY: () => (/* binding */ getHeadY), +/* harmony export */ getSnakeLength: () => (/* binding */ getSnakeLength), +/* harmony export */ nextSnake: () => (/* binding */ nextSnake), +/* harmony export */ snakeEquals: () => (/* binding */ snakeEquals), +/* harmony export */ snakeToCells: () => (/* binding */ snakeToCells), +/* harmony export */ snakeWillSelfCollide: () => (/* binding */ snakeWillSelfCollide) +/* harmony export */ }); +const getHeadX = (snake) => snake[0] - 2; +const getHeadY = (snake) => snake[1] - 2; +const getSnakeLength = (snake) => snake.length / 2; +const copySnake = (snake) => snake.slice(); +const snakeEquals = (a, b) => { + for (let i = 0; i < a.length; i++) + if (a[i] !== b[i]) + return false; + return true; +}; +/** + * return a copy of the next snake, considering that dx, dy is the direction + */ +const nextSnake = (snake, dx, dy) => { + const copy = new Uint8Array(snake.length); + for (let i = 2; i < snake.length; i++) + copy[i] = snake[i - 2]; + copy[0] = snake[0] + dx; + copy[1] = snake[1] + dy; + return copy; +}; +/** + * return true if the next snake will collide with itself + */ +const snakeWillSelfCollide = (snake, dx, dy) => { + const nx = snake[0] + dx; + const ny = snake[1] + dy; + for (let i = 2; i < snake.length - 2; i += 2) + if (snake[i + 0] === nx && snake[i + 1] === ny) + return true; + return false; +}; +const snakeToCells = (snake) => Array.from({ length: snake.length / 2 }, (_, i) => ({ + x: snake[i * 2 + 0] - 2, + y: snake[i * 2 + 1] - 2, +})); +const createSnakeFromCells = (points) => { + const snake = new Uint8Array(points.length * 2); + for (let i = points.length; i--;) { + snake[i * 2 + 0] = points[i].x + 2; + snake[i * 2 + 1] = points[i].y + 2; + } + return snake; +}; + + +/***/ }), + +/***/ "./demo.json": +/*!*******************!*\ + !*** ./demo.json ***! + \*******************/ +/***/ ((module) => { + +module.exports = JSON.parse('["interactive","getBestRoute","getBestTunnel","outside","getPathToPose","getPathTo","svg"]'); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ (() => { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = (module) => { +/******/ var getter = module && module.__esModule ? +/******/ () => (module['default']) : +/******/ () => (module); +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +/*!*************************!*\ + !*** ./demo.outside.ts ***! + \*************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _menu__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./menu */ "./menu.ts"); +/* harmony import */ var _canvas__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./canvas */ "./canvas.ts"); +/* harmony import */ var _sample__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./sample */ "./sample.ts"); +/* harmony import */ var _snk_solver_outside__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @snk/solver/outside */ "../solver/outside.ts"); + + + + +const { canvas, ctx, draw, highlightCell } = (0,_canvas__WEBPACK_IMPORTED_MODULE_1__.createCanvas)(_sample__WEBPACK_IMPORTED_MODULE_2__.grid); +document.body.appendChild(canvas); +let k = 0; +const onChange = () => { + ctx.clearRect(0, 0, 9999, 9999); + draw(_sample__WEBPACK_IMPORTED_MODULE_2__.grid, [], []); + const outside = (0,_snk_solver_outside__WEBPACK_IMPORTED_MODULE_3__.createOutside)(_sample__WEBPACK_IMPORTED_MODULE_2__.grid, k); + for (let x = outside.width; x--;) + for (let y = outside.height; y--;) + if ((0,_snk_solver_outside__WEBPACK_IMPORTED_MODULE_3__.isOutside)(outside, x, y)) + highlightCell(x, y); +}; +onChange(); +const inputK = document.createElement("input"); +inputK.type = "range"; +inputK.value = 0; +inputK.step = 1; +inputK.min = 0; +inputK.max = 4; +inputK.style.width = "90%"; +inputK.style.padding = "20px 0"; +inputK.addEventListener("input", () => { + k = +inputK.value; + onChange(); +}); +document.body.append(inputK); +window.addEventListener("click", (e) => { + if (e.target === document.body || e.target === document.body.parentElement) + inputK.focus(); +}); + +})(); + +/******/ })() +; \ No newline at end of file diff --git a/cfdd0cc20caa206086b5.js b/cfdd0cc20caa206086b5.js new file mode 100644 index 000000000..75b4a3a85 --- /dev/null +++ b/cfdd0cc20caa206086b5.js @@ -0,0 +1,4014 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "../../node_modules/dat.gui/build/dat.gui.module.js": +/*!**********************************************************!*\ + !*** ../../node_modules/dat.gui/build/dat.gui.module.js ***! + \**********************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ GUI: () => (/* binding */ GUI$1), +/* harmony export */ color: () => (/* binding */ color), +/* harmony export */ controllers: () => (/* binding */ controllers), +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), +/* harmony export */ dom: () => (/* binding */ dom$1), +/* harmony export */ gui: () => (/* binding */ gui) +/* harmony export */ }); +/** + * dat-gui JavaScript Controller Library + * https://github.com/dataarts/dat.gui + * + * Copyright 2011 Data Arts Team, Google Creative Lab + * + * 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 + */ + +function ___$insertStyle(css) { + if (!css) { + return; + } + if (typeof window === 'undefined') { + return; + } + + var style = document.createElement('style'); + + style.setAttribute('type', 'text/css'); + style.innerHTML = css; + document.head.appendChild(style); + + return css; +} + +function colorToString (color, forceCSSHex) { + var colorFormat = color.__state.conversionName.toString(); + var r = Math.round(color.r); + var g = Math.round(color.g); + var b = Math.round(color.b); + var a = color.a; + var h = Math.round(color.h); + var s = color.s.toFixed(1); + var v = color.v.toFixed(1); + if (forceCSSHex || colorFormat === 'THREE_CHAR_HEX' || colorFormat === 'SIX_CHAR_HEX') { + var str = color.hex.toString(16); + while (str.length < 6) { + str = '0' + str; + } + return '#' + str; + } else if (colorFormat === 'CSS_RGB') { + return 'rgb(' + r + ',' + g + ',' + b + ')'; + } else if (colorFormat === 'CSS_RGBA') { + return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; + } else if (colorFormat === 'HEX') { + return '0x' + color.hex.toString(16); + } else if (colorFormat === 'RGB_ARRAY') { + return '[' + r + ',' + g + ',' + b + ']'; + } else if (colorFormat === 'RGBA_ARRAY') { + return '[' + r + ',' + g + ',' + b + ',' + a + ']'; + } else if (colorFormat === 'RGB_OBJ') { + return '{r:' + r + ',g:' + g + ',b:' + b + '}'; + } else if (colorFormat === 'RGBA_OBJ') { + return '{r:' + r + ',g:' + g + ',b:' + b + ',a:' + a + '}'; + } else if (colorFormat === 'HSV_OBJ') { + return '{h:' + h + ',s:' + s + ',v:' + v + '}'; + } else if (colorFormat === 'HSVA_OBJ') { + return '{h:' + h + ',s:' + s + ',v:' + v + ',a:' + a + '}'; + } + return 'unknown format'; +} + +var ARR_EACH = Array.prototype.forEach; +var ARR_SLICE = Array.prototype.slice; +var Common = { + BREAK: {}, + extend: function extend(target) { + this.each(ARR_SLICE.call(arguments, 1), function (obj) { + var keys = this.isObject(obj) ? Object.keys(obj) : []; + keys.forEach(function (key) { + if (!this.isUndefined(obj[key])) { + target[key] = obj[key]; + } + }.bind(this)); + }, this); + return target; + }, + defaults: function defaults(target) { + this.each(ARR_SLICE.call(arguments, 1), function (obj) { + var keys = this.isObject(obj) ? Object.keys(obj) : []; + keys.forEach(function (key) { + if (this.isUndefined(target[key])) { + target[key] = obj[key]; + } + }.bind(this)); + }, this); + return target; + }, + compose: function compose() { + var toCall = ARR_SLICE.call(arguments); + return function () { + var args = ARR_SLICE.call(arguments); + for (var i = toCall.length - 1; i >= 0; i--) { + args = [toCall[i].apply(this, args)]; + } + return args[0]; + }; + }, + each: function each(obj, itr, scope) { + if (!obj) { + return; + } + if (ARR_EACH && obj.forEach && obj.forEach === ARR_EACH) { + obj.forEach(itr, scope); + } else if (obj.length === obj.length + 0) { + var key = void 0; + var l = void 0; + for (key = 0, l = obj.length; key < l; key++) { + if (key in obj && itr.call(scope, obj[key], key) === this.BREAK) { + return; + } + } + } else { + for (var _key in obj) { + if (itr.call(scope, obj[_key], _key) === this.BREAK) { + return; + } + } + } + }, + defer: function defer(fnc) { + setTimeout(fnc, 0); + }, + debounce: function debounce(func, threshold, callImmediately) { + var timeout = void 0; + return function () { + var obj = this; + var args = arguments; + function delayed() { + timeout = null; + if (!callImmediately) func.apply(obj, args); + } + var callNow = callImmediately || !timeout; + clearTimeout(timeout); + timeout = setTimeout(delayed, threshold); + if (callNow) { + func.apply(obj, args); + } + }; + }, + toArray: function toArray(obj) { + if (obj.toArray) return obj.toArray(); + return ARR_SLICE.call(obj); + }, + isUndefined: function isUndefined(obj) { + return obj === undefined; + }, + isNull: function isNull(obj) { + return obj === null; + }, + isNaN: function (_isNaN) { + function isNaN(_x) { + return _isNaN.apply(this, arguments); + } + isNaN.toString = function () { + return _isNaN.toString(); + }; + return isNaN; + }(function (obj) { + return isNaN(obj); + }), + isArray: Array.isArray || function (obj) { + return obj.constructor === Array; + }, + isObject: function isObject(obj) { + return obj === Object(obj); + }, + isNumber: function isNumber(obj) { + return obj === obj + 0; + }, + isString: function isString(obj) { + return obj === obj + ''; + }, + isBoolean: function isBoolean(obj) { + return obj === false || obj === true; + }, + isFunction: function isFunction(obj) { + return obj instanceof Function; + } +}; + +var INTERPRETATIONS = [ +{ + litmus: Common.isString, + conversions: { + THREE_CHAR_HEX: { + read: function read(original) { + var test = original.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i); + if (test === null) { + return false; + } + return { + space: 'HEX', + hex: parseInt('0x' + test[1].toString() + test[1].toString() + test[2].toString() + test[2].toString() + test[3].toString() + test[3].toString(), 0) + }; + }, + write: colorToString + }, + SIX_CHAR_HEX: { + read: function read(original) { + var test = original.match(/^#([A-F0-9]{6})$/i); + if (test === null) { + return false; + } + return { + space: 'HEX', + hex: parseInt('0x' + test[1].toString(), 0) + }; + }, + write: colorToString + }, + CSS_RGB: { + read: function read(original) { + var test = original.match(/^rgb\(\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*\)/); + if (test === null) { + return false; + } + return { + space: 'RGB', + r: parseFloat(test[1]), + g: parseFloat(test[2]), + b: parseFloat(test[3]) + }; + }, + write: colorToString + }, + CSS_RGBA: { + read: function read(original) { + var test = original.match(/^rgba\(\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*\)/); + if (test === null) { + return false; + } + return { + space: 'RGB', + r: parseFloat(test[1]), + g: parseFloat(test[2]), + b: parseFloat(test[3]), + a: parseFloat(test[4]) + }; + }, + write: colorToString + } + } +}, +{ + litmus: Common.isNumber, + conversions: { + HEX: { + read: function read(original) { + return { + space: 'HEX', + hex: original, + conversionName: 'HEX' + }; + }, + write: function write(color) { + return color.hex; + } + } + } +}, +{ + litmus: Common.isArray, + conversions: { + RGB_ARRAY: { + read: function read(original) { + if (original.length !== 3) { + return false; + } + return { + space: 'RGB', + r: original[0], + g: original[1], + b: original[2] + }; + }, + write: function write(color) { + return [color.r, color.g, color.b]; + } + }, + RGBA_ARRAY: { + read: function read(original) { + if (original.length !== 4) return false; + return { + space: 'RGB', + r: original[0], + g: original[1], + b: original[2], + a: original[3] + }; + }, + write: function write(color) { + return [color.r, color.g, color.b, color.a]; + } + } + } +}, +{ + litmus: Common.isObject, + conversions: { + RGBA_OBJ: { + read: function read(original) { + if (Common.isNumber(original.r) && Common.isNumber(original.g) && Common.isNumber(original.b) && Common.isNumber(original.a)) { + return { + space: 'RGB', + r: original.r, + g: original.g, + b: original.b, + a: original.a + }; + } + return false; + }, + write: function write(color) { + return { + r: color.r, + g: color.g, + b: color.b, + a: color.a + }; + } + }, + RGB_OBJ: { + read: function read(original) { + if (Common.isNumber(original.r) && Common.isNumber(original.g) && Common.isNumber(original.b)) { + return { + space: 'RGB', + r: original.r, + g: original.g, + b: original.b + }; + } + return false; + }, + write: function write(color) { + return { + r: color.r, + g: color.g, + b: color.b + }; + } + }, + HSVA_OBJ: { + read: function read(original) { + if (Common.isNumber(original.h) && Common.isNumber(original.s) && Common.isNumber(original.v) && Common.isNumber(original.a)) { + return { + space: 'HSV', + h: original.h, + s: original.s, + v: original.v, + a: original.a + }; + } + return false; + }, + write: function write(color) { + return { + h: color.h, + s: color.s, + v: color.v, + a: color.a + }; + } + }, + HSV_OBJ: { + read: function read(original) { + if (Common.isNumber(original.h) && Common.isNumber(original.s) && Common.isNumber(original.v)) { + return { + space: 'HSV', + h: original.h, + s: original.s, + v: original.v + }; + } + return false; + }, + write: function write(color) { + return { + h: color.h, + s: color.s, + v: color.v + }; + } + } + } +}]; +var result = void 0; +var toReturn = void 0; +var interpret = function interpret() { + toReturn = false; + var original = arguments.length > 1 ? Common.toArray(arguments) : arguments[0]; + Common.each(INTERPRETATIONS, function (family) { + if (family.litmus(original)) { + Common.each(family.conversions, function (conversion, conversionName) { + result = conversion.read(original); + if (toReturn === false && result !== false) { + toReturn = result; + result.conversionName = conversionName; + result.conversion = conversion; + return Common.BREAK; + } + }); + return Common.BREAK; + } + }); + return toReturn; +}; + +var tmpComponent = void 0; +var ColorMath = { + hsv_to_rgb: function hsv_to_rgb(h, s, v) { + var hi = Math.floor(h / 60) % 6; + var f = h / 60 - Math.floor(h / 60); + var p = v * (1.0 - s); + var q = v * (1.0 - f * s); + var t = v * (1.0 - (1.0 - f) * s); + var c = [[v, t, p], [q, v, p], [p, v, t], [p, q, v], [t, p, v], [v, p, q]][hi]; + return { + r: c[0] * 255, + g: c[1] * 255, + b: c[2] * 255 + }; + }, + rgb_to_hsv: function rgb_to_hsv(r, g, b) { + var min = Math.min(r, g, b); + var max = Math.max(r, g, b); + var delta = max - min; + var h = void 0; + var s = void 0; + if (max !== 0) { + s = delta / max; + } else { + return { + h: NaN, + s: 0, + v: 0 + }; + } + if (r === max) { + h = (g - b) / delta; + } else if (g === max) { + h = 2 + (b - r) / delta; + } else { + h = 4 + (r - g) / delta; + } + h /= 6; + if (h < 0) { + h += 1; + } + return { + h: h * 360, + s: s, + v: max / 255 + }; + }, + rgb_to_hex: function rgb_to_hex(r, g, b) { + var hex = this.hex_with_component(0, 2, r); + hex = this.hex_with_component(hex, 1, g); + hex = this.hex_with_component(hex, 0, b); + return hex; + }, + component_from_hex: function component_from_hex(hex, componentIndex) { + return hex >> componentIndex * 8 & 0xFF; + }, + hex_with_component: function hex_with_component(hex, componentIndex, value) { + return value << (tmpComponent = componentIndex * 8) | hex & ~(0xFF << tmpComponent); + } +}; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; +} : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; +}; + + + + + + + + + + + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; + +var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; +}(); + + + + + + + +var get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); + + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + + if (getter === undefined) { + return undefined; + } + + return getter.call(receiver); + } +}; + +var inherits = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; +}; + + + + + + + + + + + +var possibleConstructorReturn = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && (typeof call === "object" || typeof call === "function") ? call : self; +}; + +var Color = function () { + function Color() { + classCallCheck(this, Color); + this.__state = interpret.apply(this, arguments); + if (this.__state === false) { + throw new Error('Failed to interpret color arguments'); + } + this.__state.a = this.__state.a || 1; + } + createClass(Color, [{ + key: 'toString', + value: function toString() { + return colorToString(this); + } + }, { + key: 'toHexString', + value: function toHexString() { + return colorToString(this, true); + } + }, { + key: 'toOriginal', + value: function toOriginal() { + return this.__state.conversion.write(this); + } + }]); + return Color; +}(); +function defineRGBComponent(target, component, componentHexIndex) { + Object.defineProperty(target, component, { + get: function get$$1() { + if (this.__state.space === 'RGB') { + return this.__state[component]; + } + Color.recalculateRGB(this, component, componentHexIndex); + return this.__state[component]; + }, + set: function set$$1(v) { + if (this.__state.space !== 'RGB') { + Color.recalculateRGB(this, component, componentHexIndex); + this.__state.space = 'RGB'; + } + this.__state[component] = v; + } + }); +} +function defineHSVComponent(target, component) { + Object.defineProperty(target, component, { + get: function get$$1() { + if (this.__state.space === 'HSV') { + return this.__state[component]; + } + Color.recalculateHSV(this); + return this.__state[component]; + }, + set: function set$$1(v) { + if (this.__state.space !== 'HSV') { + Color.recalculateHSV(this); + this.__state.space = 'HSV'; + } + this.__state[component] = v; + } + }); +} +Color.recalculateRGB = function (color, component, componentHexIndex) { + if (color.__state.space === 'HEX') { + color.__state[component] = ColorMath.component_from_hex(color.__state.hex, componentHexIndex); + } else if (color.__state.space === 'HSV') { + Common.extend(color.__state, ColorMath.hsv_to_rgb(color.__state.h, color.__state.s, color.__state.v)); + } else { + throw new Error('Corrupted color state'); + } +}; +Color.recalculateHSV = function (color) { + var result = ColorMath.rgb_to_hsv(color.r, color.g, color.b); + Common.extend(color.__state, { + s: result.s, + v: result.v + }); + if (!Common.isNaN(result.h)) { + color.__state.h = result.h; + } else if (Common.isUndefined(color.__state.h)) { + color.__state.h = 0; + } +}; +Color.COMPONENTS = ['r', 'g', 'b', 'h', 's', 'v', 'hex', 'a']; +defineRGBComponent(Color.prototype, 'r', 2); +defineRGBComponent(Color.prototype, 'g', 1); +defineRGBComponent(Color.prototype, 'b', 0); +defineHSVComponent(Color.prototype, 'h'); +defineHSVComponent(Color.prototype, 's'); +defineHSVComponent(Color.prototype, 'v'); +Object.defineProperty(Color.prototype, 'a', { + get: function get$$1() { + return this.__state.a; + }, + set: function set$$1(v) { + this.__state.a = v; + } +}); +Object.defineProperty(Color.prototype, 'hex', { + get: function get$$1() { + if (this.__state.space !== 'HEX') { + this.__state.hex = ColorMath.rgb_to_hex(this.r, this.g, this.b); + this.__state.space = 'HEX'; + } + return this.__state.hex; + }, + set: function set$$1(v) { + this.__state.space = 'HEX'; + this.__state.hex = v; + } +}); + +var Controller = function () { + function Controller(object, property) { + classCallCheck(this, Controller); + this.initialValue = object[property]; + this.domElement = document.createElement('div'); + this.object = object; + this.property = property; + this.__onChange = undefined; + this.__onFinishChange = undefined; + } + createClass(Controller, [{ + key: 'onChange', + value: function onChange(fnc) { + this.__onChange = fnc; + return this; + } + }, { + key: 'onFinishChange', + value: function onFinishChange(fnc) { + this.__onFinishChange = fnc; + return this; + } + }, { + key: 'setValue', + value: function setValue(newValue) { + this.object[this.property] = newValue; + if (this.__onChange) { + this.__onChange.call(this, newValue); + } + this.updateDisplay(); + return this; + } + }, { + key: 'getValue', + value: function getValue() { + return this.object[this.property]; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + return this; + } + }, { + key: 'isModified', + value: function isModified() { + return this.initialValue !== this.getValue(); + } + }]); + return Controller; +}(); + +var EVENT_MAP = { + HTMLEvents: ['change'], + MouseEvents: ['click', 'mousemove', 'mousedown', 'mouseup', 'mouseover'], + KeyboardEvents: ['keydown'] +}; +var EVENT_MAP_INV = {}; +Common.each(EVENT_MAP, function (v, k) { + Common.each(v, function (e) { + EVENT_MAP_INV[e] = k; + }); +}); +var CSS_VALUE_PIXELS = /(\d+(\.\d+)?)px/; +function cssValueToPixels(val) { + if (val === '0' || Common.isUndefined(val)) { + return 0; + } + var match = val.match(CSS_VALUE_PIXELS); + if (!Common.isNull(match)) { + return parseFloat(match[1]); + } + return 0; +} +var dom = { + makeSelectable: function makeSelectable(elem, selectable) { + if (elem === undefined || elem.style === undefined) return; + elem.onselectstart = selectable ? function () { + return false; + } : function () {}; + elem.style.MozUserSelect = selectable ? 'auto' : 'none'; + elem.style.KhtmlUserSelect = selectable ? 'auto' : 'none'; + elem.unselectable = selectable ? 'on' : 'off'; + }, + makeFullscreen: function makeFullscreen(elem, hor, vert) { + var vertical = vert; + var horizontal = hor; + if (Common.isUndefined(horizontal)) { + horizontal = true; + } + if (Common.isUndefined(vertical)) { + vertical = true; + } + elem.style.position = 'absolute'; + if (horizontal) { + elem.style.left = 0; + elem.style.right = 0; + } + if (vertical) { + elem.style.top = 0; + elem.style.bottom = 0; + } + }, + fakeEvent: function fakeEvent(elem, eventType, pars, aux) { + var params = pars || {}; + var className = EVENT_MAP_INV[eventType]; + if (!className) { + throw new Error('Event type ' + eventType + ' not supported.'); + } + var evt = document.createEvent(className); + switch (className) { + case 'MouseEvents': + { + var clientX = params.x || params.clientX || 0; + var clientY = params.y || params.clientY || 0; + evt.initMouseEvent(eventType, params.bubbles || false, params.cancelable || true, window, params.clickCount || 1, 0, + 0, + clientX, + clientY, + false, false, false, false, 0, null); + break; + } + case 'KeyboardEvents': + { + var init = evt.initKeyboardEvent || evt.initKeyEvent; + Common.defaults(params, { + cancelable: true, + ctrlKey: false, + altKey: false, + shiftKey: false, + metaKey: false, + keyCode: undefined, + charCode: undefined + }); + init(eventType, params.bubbles || false, params.cancelable, window, params.ctrlKey, params.altKey, params.shiftKey, params.metaKey, params.keyCode, params.charCode); + break; + } + default: + { + evt.initEvent(eventType, params.bubbles || false, params.cancelable || true); + break; + } + } + Common.defaults(evt, aux); + elem.dispatchEvent(evt); + }, + bind: function bind(elem, event, func, newBool) { + var bool = newBool || false; + if (elem.addEventListener) { + elem.addEventListener(event, func, bool); + } else if (elem.attachEvent) { + elem.attachEvent('on' + event, func); + } + return dom; + }, + unbind: function unbind(elem, event, func, newBool) { + var bool = newBool || false; + if (elem.removeEventListener) { + elem.removeEventListener(event, func, bool); + } else if (elem.detachEvent) { + elem.detachEvent('on' + event, func); + } + return dom; + }, + addClass: function addClass(elem, className) { + if (elem.className === undefined) { + elem.className = className; + } else if (elem.className !== className) { + var classes = elem.className.split(/ +/); + if (classes.indexOf(className) === -1) { + classes.push(className); + elem.className = classes.join(' ').replace(/^\s+/, '').replace(/\s+$/, ''); + } + } + return dom; + }, + removeClass: function removeClass(elem, className) { + if (className) { + if (elem.className === className) { + elem.removeAttribute('class'); + } else { + var classes = elem.className.split(/ +/); + var index = classes.indexOf(className); + if (index !== -1) { + classes.splice(index, 1); + elem.className = classes.join(' '); + } + } + } else { + elem.className = undefined; + } + return dom; + }, + hasClass: function hasClass(elem, className) { + return new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)').test(elem.className) || false; + }, + getWidth: function getWidth(elem) { + var style = getComputedStyle(elem); + return cssValueToPixels(style['border-left-width']) + cssValueToPixels(style['border-right-width']) + cssValueToPixels(style['padding-left']) + cssValueToPixels(style['padding-right']) + cssValueToPixels(style.width); + }, + getHeight: function getHeight(elem) { + var style = getComputedStyle(elem); + return cssValueToPixels(style['border-top-width']) + cssValueToPixels(style['border-bottom-width']) + cssValueToPixels(style['padding-top']) + cssValueToPixels(style['padding-bottom']) + cssValueToPixels(style.height); + }, + getOffset: function getOffset(el) { + var elem = el; + var offset = { left: 0, top: 0 }; + if (elem.offsetParent) { + do { + offset.left += elem.offsetLeft; + offset.top += elem.offsetTop; + elem = elem.offsetParent; + } while (elem); + } + return offset; + }, + isActive: function isActive(elem) { + return elem === document.activeElement && (elem.type || elem.href); + } +}; + +var BooleanController = function (_Controller) { + inherits(BooleanController, _Controller); + function BooleanController(object, property) { + classCallCheck(this, BooleanController); + var _this2 = possibleConstructorReturn(this, (BooleanController.__proto__ || Object.getPrototypeOf(BooleanController)).call(this, object, property)); + var _this = _this2; + _this2.__prev = _this2.getValue(); + _this2.__checkbox = document.createElement('input'); + _this2.__checkbox.setAttribute('type', 'checkbox'); + function onChange() { + _this.setValue(!_this.__prev); + } + dom.bind(_this2.__checkbox, 'change', onChange, false); + _this2.domElement.appendChild(_this2.__checkbox); + _this2.updateDisplay(); + return _this2; + } + createClass(BooleanController, [{ + key: 'setValue', + value: function setValue(v) { + var toReturn = get(BooleanController.prototype.__proto__ || Object.getPrototypeOf(BooleanController.prototype), 'setValue', this).call(this, v); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + this.__prev = this.getValue(); + return toReturn; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + if (this.getValue() === true) { + this.__checkbox.setAttribute('checked', 'checked'); + this.__checkbox.checked = true; + this.__prev = true; + } else { + this.__checkbox.checked = false; + this.__prev = false; + } + return get(BooleanController.prototype.__proto__ || Object.getPrototypeOf(BooleanController.prototype), 'updateDisplay', this).call(this); + } + }]); + return BooleanController; +}(Controller); + +var OptionController = function (_Controller) { + inherits(OptionController, _Controller); + function OptionController(object, property, opts) { + classCallCheck(this, OptionController); + var _this2 = possibleConstructorReturn(this, (OptionController.__proto__ || Object.getPrototypeOf(OptionController)).call(this, object, property)); + var options = opts; + var _this = _this2; + _this2.__select = document.createElement('select'); + if (Common.isArray(options)) { + var map = {}; + Common.each(options, function (element) { + map[element] = element; + }); + options = map; + } + Common.each(options, function (value, key) { + var opt = document.createElement('option'); + opt.innerHTML = key; + opt.setAttribute('value', value); + _this.__select.appendChild(opt); + }); + _this2.updateDisplay(); + dom.bind(_this2.__select, 'change', function () { + var desiredValue = this.options[this.selectedIndex].value; + _this.setValue(desiredValue); + }); + _this2.domElement.appendChild(_this2.__select); + return _this2; + } + createClass(OptionController, [{ + key: 'setValue', + value: function setValue(v) { + var toReturn = get(OptionController.prototype.__proto__ || Object.getPrototypeOf(OptionController.prototype), 'setValue', this).call(this, v); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + return toReturn; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + if (dom.isActive(this.__select)) return this; + this.__select.value = this.getValue(); + return get(OptionController.prototype.__proto__ || Object.getPrototypeOf(OptionController.prototype), 'updateDisplay', this).call(this); + } + }]); + return OptionController; +}(Controller); + +var StringController = function (_Controller) { + inherits(StringController, _Controller); + function StringController(object, property) { + classCallCheck(this, StringController); + var _this2 = possibleConstructorReturn(this, (StringController.__proto__ || Object.getPrototypeOf(StringController)).call(this, object, property)); + var _this = _this2; + function onChange() { + _this.setValue(_this.__input.value); + } + function onBlur() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + _this2.__input = document.createElement('input'); + _this2.__input.setAttribute('type', 'text'); + dom.bind(_this2.__input, 'keyup', onChange); + dom.bind(_this2.__input, 'change', onChange); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + this.blur(); + } + }); + _this2.updateDisplay(); + _this2.domElement.appendChild(_this2.__input); + return _this2; + } + createClass(StringController, [{ + key: 'updateDisplay', + value: function updateDisplay() { + if (!dom.isActive(this.__input)) { + this.__input.value = this.getValue(); + } + return get(StringController.prototype.__proto__ || Object.getPrototypeOf(StringController.prototype), 'updateDisplay', this).call(this); + } + }]); + return StringController; +}(Controller); + +function numDecimals(x) { + var _x = x.toString(); + if (_x.indexOf('.') > -1) { + return _x.length - _x.indexOf('.') - 1; + } + return 0; +} +var NumberController = function (_Controller) { + inherits(NumberController, _Controller); + function NumberController(object, property, params) { + classCallCheck(this, NumberController); + var _this = possibleConstructorReturn(this, (NumberController.__proto__ || Object.getPrototypeOf(NumberController)).call(this, object, property)); + var _params = params || {}; + _this.__min = _params.min; + _this.__max = _params.max; + _this.__step = _params.step; + if (Common.isUndefined(_this.__step)) { + if (_this.initialValue === 0) { + _this.__impliedStep = 1; + } else { + _this.__impliedStep = Math.pow(10, Math.floor(Math.log(Math.abs(_this.initialValue)) / Math.LN10)) / 10; + } + } else { + _this.__impliedStep = _this.__step; + } + _this.__precision = numDecimals(_this.__impliedStep); + return _this; + } + createClass(NumberController, [{ + key: 'setValue', + value: function setValue(v) { + var _v = v; + if (this.__min !== undefined && _v < this.__min) { + _v = this.__min; + } else if (this.__max !== undefined && _v > this.__max) { + _v = this.__max; + } + if (this.__step !== undefined && _v % this.__step !== 0) { + _v = Math.round(_v / this.__step) * this.__step; + } + return get(NumberController.prototype.__proto__ || Object.getPrototypeOf(NumberController.prototype), 'setValue', this).call(this, _v); + } + }, { + key: 'min', + value: function min(minValue) { + this.__min = minValue; + return this; + } + }, { + key: 'max', + value: function max(maxValue) { + this.__max = maxValue; + return this; + } + }, { + key: 'step', + value: function step(stepValue) { + this.__step = stepValue; + this.__impliedStep = stepValue; + this.__precision = numDecimals(stepValue); + return this; + } + }]); + return NumberController; +}(Controller); + +function roundToDecimal(value, decimals) { + var tenTo = Math.pow(10, decimals); + return Math.round(value * tenTo) / tenTo; +} +var NumberControllerBox = function (_NumberController) { + inherits(NumberControllerBox, _NumberController); + function NumberControllerBox(object, property, params) { + classCallCheck(this, NumberControllerBox); + var _this2 = possibleConstructorReturn(this, (NumberControllerBox.__proto__ || Object.getPrototypeOf(NumberControllerBox)).call(this, object, property, params)); + _this2.__truncationSuspended = false; + var _this = _this2; + var prevY = void 0; + function onChange() { + var attempted = parseFloat(_this.__input.value); + if (!Common.isNaN(attempted)) { + _this.setValue(attempted); + } + } + function onFinish() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + function onBlur() { + onFinish(); + } + function onMouseDrag(e) { + var diff = prevY - e.clientY; + _this.setValue(_this.getValue() + diff * _this.__impliedStep); + prevY = e.clientY; + } + function onMouseUp() { + dom.unbind(window, 'mousemove', onMouseDrag); + dom.unbind(window, 'mouseup', onMouseUp); + onFinish(); + } + function onMouseDown(e) { + dom.bind(window, 'mousemove', onMouseDrag); + dom.bind(window, 'mouseup', onMouseUp); + prevY = e.clientY; + } + _this2.__input = document.createElement('input'); + _this2.__input.setAttribute('type', 'text'); + dom.bind(_this2.__input, 'change', onChange); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__input, 'mousedown', onMouseDown); + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + _this.__truncationSuspended = true; + this.blur(); + _this.__truncationSuspended = false; + onFinish(); + } + }); + _this2.updateDisplay(); + _this2.domElement.appendChild(_this2.__input); + return _this2; + } + createClass(NumberControllerBox, [{ + key: 'updateDisplay', + value: function updateDisplay() { + this.__input.value = this.__truncationSuspended ? this.getValue() : roundToDecimal(this.getValue(), this.__precision); + return get(NumberControllerBox.prototype.__proto__ || Object.getPrototypeOf(NumberControllerBox.prototype), 'updateDisplay', this).call(this); + } + }]); + return NumberControllerBox; +}(NumberController); + +function map(v, i1, i2, o1, o2) { + return o1 + (o2 - o1) * ((v - i1) / (i2 - i1)); +} +var NumberControllerSlider = function (_NumberController) { + inherits(NumberControllerSlider, _NumberController); + function NumberControllerSlider(object, property, min, max, step) { + classCallCheck(this, NumberControllerSlider); + var _this2 = possibleConstructorReturn(this, (NumberControllerSlider.__proto__ || Object.getPrototypeOf(NumberControllerSlider)).call(this, object, property, { min: min, max: max, step: step })); + var _this = _this2; + _this2.__background = document.createElement('div'); + _this2.__foreground = document.createElement('div'); + dom.bind(_this2.__background, 'mousedown', onMouseDown); + dom.bind(_this2.__background, 'touchstart', onTouchStart); + dom.addClass(_this2.__background, 'slider'); + dom.addClass(_this2.__foreground, 'slider-fg'); + function onMouseDown(e) { + document.activeElement.blur(); + dom.bind(window, 'mousemove', onMouseDrag); + dom.bind(window, 'mouseup', onMouseUp); + onMouseDrag(e); + } + function onMouseDrag(e) { + e.preventDefault(); + var bgRect = _this.__background.getBoundingClientRect(); + _this.setValue(map(e.clientX, bgRect.left, bgRect.right, _this.__min, _this.__max)); + return false; + } + function onMouseUp() { + dom.unbind(window, 'mousemove', onMouseDrag); + dom.unbind(window, 'mouseup', onMouseUp); + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + function onTouchStart(e) { + if (e.touches.length !== 1) { + return; + } + dom.bind(window, 'touchmove', onTouchMove); + dom.bind(window, 'touchend', onTouchEnd); + onTouchMove(e); + } + function onTouchMove(e) { + var clientX = e.touches[0].clientX; + var bgRect = _this.__background.getBoundingClientRect(); + _this.setValue(map(clientX, bgRect.left, bgRect.right, _this.__min, _this.__max)); + } + function onTouchEnd() { + dom.unbind(window, 'touchmove', onTouchMove); + dom.unbind(window, 'touchend', onTouchEnd); + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + _this2.updateDisplay(); + _this2.__background.appendChild(_this2.__foreground); + _this2.domElement.appendChild(_this2.__background); + return _this2; + } + createClass(NumberControllerSlider, [{ + key: 'updateDisplay', + value: function updateDisplay() { + var pct = (this.getValue() - this.__min) / (this.__max - this.__min); + this.__foreground.style.width = pct * 100 + '%'; + return get(NumberControllerSlider.prototype.__proto__ || Object.getPrototypeOf(NumberControllerSlider.prototype), 'updateDisplay', this).call(this); + } + }]); + return NumberControllerSlider; +}(NumberController); + +var FunctionController = function (_Controller) { + inherits(FunctionController, _Controller); + function FunctionController(object, property, text) { + classCallCheck(this, FunctionController); + var _this2 = possibleConstructorReturn(this, (FunctionController.__proto__ || Object.getPrototypeOf(FunctionController)).call(this, object, property)); + var _this = _this2; + _this2.__button = document.createElement('div'); + _this2.__button.innerHTML = text === undefined ? 'Fire' : text; + dom.bind(_this2.__button, 'click', function (e) { + e.preventDefault(); + _this.fire(); + return false; + }); + dom.addClass(_this2.__button, 'button'); + _this2.domElement.appendChild(_this2.__button); + return _this2; + } + createClass(FunctionController, [{ + key: 'fire', + value: function fire() { + if (this.__onChange) { + this.__onChange.call(this); + } + this.getValue().call(this.object); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + } + }]); + return FunctionController; +}(Controller); + +var ColorController = function (_Controller) { + inherits(ColorController, _Controller); + function ColorController(object, property) { + classCallCheck(this, ColorController); + var _this2 = possibleConstructorReturn(this, (ColorController.__proto__ || Object.getPrototypeOf(ColorController)).call(this, object, property)); + _this2.__color = new Color(_this2.getValue()); + _this2.__temp = new Color(0); + var _this = _this2; + _this2.domElement = document.createElement('div'); + dom.makeSelectable(_this2.domElement, false); + _this2.__selector = document.createElement('div'); + _this2.__selector.className = 'selector'; + _this2.__saturation_field = document.createElement('div'); + _this2.__saturation_field.className = 'saturation-field'; + _this2.__field_knob = document.createElement('div'); + _this2.__field_knob.className = 'field-knob'; + _this2.__field_knob_border = '2px solid '; + _this2.__hue_knob = document.createElement('div'); + _this2.__hue_knob.className = 'hue-knob'; + _this2.__hue_field = document.createElement('div'); + _this2.__hue_field.className = 'hue-field'; + _this2.__input = document.createElement('input'); + _this2.__input.type = 'text'; + _this2.__input_textShadow = '0 1px 1px '; + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + onBlur.call(this); + } + }); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__selector, 'mousedown', function () { + dom.addClass(this, 'drag').bind(window, 'mouseup', function () { + dom.removeClass(_this.__selector, 'drag'); + }); + }); + dom.bind(_this2.__selector, 'touchstart', function () { + dom.addClass(this, 'drag').bind(window, 'touchend', function () { + dom.removeClass(_this.__selector, 'drag'); + }); + }); + var valueField = document.createElement('div'); + Common.extend(_this2.__selector.style, { + width: '122px', + height: '102px', + padding: '3px', + backgroundColor: '#222', + boxShadow: '0px 1px 3px rgba(0,0,0,0.3)' + }); + Common.extend(_this2.__field_knob.style, { + position: 'absolute', + width: '12px', + height: '12px', + border: _this2.__field_knob_border + (_this2.__color.v < 0.5 ? '#fff' : '#000'), + boxShadow: '0px 1px 3px rgba(0,0,0,0.5)', + borderRadius: '12px', + zIndex: 1 + }); + Common.extend(_this2.__hue_knob.style, { + position: 'absolute', + width: '15px', + height: '2px', + borderRight: '4px solid #fff', + zIndex: 1 + }); + Common.extend(_this2.__saturation_field.style, { + width: '100px', + height: '100px', + border: '1px solid #555', + marginRight: '3px', + display: 'inline-block', + cursor: 'pointer' + }); + Common.extend(valueField.style, { + width: '100%', + height: '100%', + background: 'none' + }); + linearGradient(valueField, 'top', 'rgba(0,0,0,0)', '#000'); + Common.extend(_this2.__hue_field.style, { + width: '15px', + height: '100px', + border: '1px solid #555', + cursor: 'ns-resize', + position: 'absolute', + top: '3px', + right: '3px' + }); + hueGradient(_this2.__hue_field); + Common.extend(_this2.__input.style, { + outline: 'none', + textAlign: 'center', + color: '#fff', + border: 0, + fontWeight: 'bold', + textShadow: _this2.__input_textShadow + 'rgba(0,0,0,0.7)' + }); + dom.bind(_this2.__saturation_field, 'mousedown', fieldDown); + dom.bind(_this2.__saturation_field, 'touchstart', fieldDown); + dom.bind(_this2.__field_knob, 'mousedown', fieldDown); + dom.bind(_this2.__field_knob, 'touchstart', fieldDown); + dom.bind(_this2.__hue_field, 'mousedown', fieldDownH); + dom.bind(_this2.__hue_field, 'touchstart', fieldDownH); + function fieldDown(e) { + setSV(e); + dom.bind(window, 'mousemove', setSV); + dom.bind(window, 'touchmove', setSV); + dom.bind(window, 'mouseup', fieldUpSV); + dom.bind(window, 'touchend', fieldUpSV); + } + function fieldDownH(e) { + setH(e); + dom.bind(window, 'mousemove', setH); + dom.bind(window, 'touchmove', setH); + dom.bind(window, 'mouseup', fieldUpH); + dom.bind(window, 'touchend', fieldUpH); + } + function fieldUpSV() { + dom.unbind(window, 'mousemove', setSV); + dom.unbind(window, 'touchmove', setSV); + dom.unbind(window, 'mouseup', fieldUpSV); + dom.unbind(window, 'touchend', fieldUpSV); + onFinish(); + } + function fieldUpH() { + dom.unbind(window, 'mousemove', setH); + dom.unbind(window, 'touchmove', setH); + dom.unbind(window, 'mouseup', fieldUpH); + dom.unbind(window, 'touchend', fieldUpH); + onFinish(); + } + function onBlur() { + var i = interpret(this.value); + if (i !== false) { + _this.__color.__state = i; + _this.setValue(_this.__color.toOriginal()); + } else { + this.value = _this.__color.toString(); + } + } + function onFinish() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.__color.toOriginal()); + } + } + _this2.__saturation_field.appendChild(valueField); + _this2.__selector.appendChild(_this2.__field_knob); + _this2.__selector.appendChild(_this2.__saturation_field); + _this2.__selector.appendChild(_this2.__hue_field); + _this2.__hue_field.appendChild(_this2.__hue_knob); + _this2.domElement.appendChild(_this2.__input); + _this2.domElement.appendChild(_this2.__selector); + _this2.updateDisplay(); + function setSV(e) { + if (e.type.indexOf('touch') === -1) { + e.preventDefault(); + } + var fieldRect = _this.__saturation_field.getBoundingClientRect(); + var _ref = e.touches && e.touches[0] || e, + clientX = _ref.clientX, + clientY = _ref.clientY; + var s = (clientX - fieldRect.left) / (fieldRect.right - fieldRect.left); + var v = 1 - (clientY - fieldRect.top) / (fieldRect.bottom - fieldRect.top); + if (v > 1) { + v = 1; + } else if (v < 0) { + v = 0; + } + if (s > 1) { + s = 1; + } else if (s < 0) { + s = 0; + } + _this.__color.v = v; + _this.__color.s = s; + _this.setValue(_this.__color.toOriginal()); + return false; + } + function setH(e) { + if (e.type.indexOf('touch') === -1) { + e.preventDefault(); + } + var fieldRect = _this.__hue_field.getBoundingClientRect(); + var _ref2 = e.touches && e.touches[0] || e, + clientY = _ref2.clientY; + var h = 1 - (clientY - fieldRect.top) / (fieldRect.bottom - fieldRect.top); + if (h > 1) { + h = 1; + } else if (h < 0) { + h = 0; + } + _this.__color.h = h * 360; + _this.setValue(_this.__color.toOriginal()); + return false; + } + return _this2; + } + createClass(ColorController, [{ + key: 'updateDisplay', + value: function updateDisplay() { + var i = interpret(this.getValue()); + if (i !== false) { + var mismatch = false; + Common.each(Color.COMPONENTS, function (component) { + if (!Common.isUndefined(i[component]) && !Common.isUndefined(this.__color.__state[component]) && i[component] !== this.__color.__state[component]) { + mismatch = true; + return {}; + } + }, this); + if (mismatch) { + Common.extend(this.__color.__state, i); + } + } + Common.extend(this.__temp.__state, this.__color.__state); + this.__temp.a = 1; + var flip = this.__color.v < 0.5 || this.__color.s > 0.5 ? 255 : 0; + var _flip = 255 - flip; + Common.extend(this.__field_knob.style, { + marginLeft: 100 * this.__color.s - 7 + 'px', + marginTop: 100 * (1 - this.__color.v) - 7 + 'px', + backgroundColor: this.__temp.toHexString(), + border: this.__field_knob_border + 'rgb(' + flip + ',' + flip + ',' + flip + ')' + }); + this.__hue_knob.style.marginTop = (1 - this.__color.h / 360) * 100 + 'px'; + this.__temp.s = 1; + this.__temp.v = 1; + linearGradient(this.__saturation_field, 'left', '#fff', this.__temp.toHexString()); + this.__input.value = this.__color.toString(); + Common.extend(this.__input.style, { + backgroundColor: this.__color.toHexString(), + color: 'rgb(' + flip + ',' + flip + ',' + flip + ')', + textShadow: this.__input_textShadow + 'rgba(' + _flip + ',' + _flip + ',' + _flip + ',.7)' + }); + } + }]); + return ColorController; +}(Controller); +var vendors = ['-moz-', '-o-', '-webkit-', '-ms-', '']; +function linearGradient(elem, x, a, b) { + elem.style.background = ''; + Common.each(vendors, function (vendor) { + elem.style.cssText += 'background: ' + vendor + 'linear-gradient(' + x + ', ' + a + ' 0%, ' + b + ' 100%); '; + }); +} +function hueGradient(elem) { + elem.style.background = ''; + elem.style.cssText += 'background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);'; + elem.style.cssText += 'background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; +} + +var css = { + load: function load(url, indoc) { + var doc = indoc || document; + var link = doc.createElement('link'); + link.type = 'text/css'; + link.rel = 'stylesheet'; + link.href = url; + doc.getElementsByTagName('head')[0].appendChild(link); + }, + inject: function inject(cssContent, indoc) { + var doc = indoc || document; + var injected = document.createElement('style'); + injected.type = 'text/css'; + injected.innerHTML = cssContent; + var head = doc.getElementsByTagName('head')[0]; + try { + head.appendChild(injected); + } catch (e) { + } + } +}; + +var saveDialogContents = "
\n\n Here's the new load parameter for your GUI's constructor:\n\n \n\n
\n\n Automatically save\n values to localStorage on exit.\n\n
The values saved to localStorage will\n override those passed to dat.GUI's constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n\n
\n\n
\n\n
"; + +var ControllerFactory = function ControllerFactory(object, property) { + var initialValue = object[property]; + if (Common.isArray(arguments[2]) || Common.isObject(arguments[2])) { + return new OptionController(object, property, arguments[2]); + } + if (Common.isNumber(initialValue)) { + if (Common.isNumber(arguments[2]) && Common.isNumber(arguments[3])) { + if (Common.isNumber(arguments[4])) { + return new NumberControllerSlider(object, property, arguments[2], arguments[3], arguments[4]); + } + return new NumberControllerSlider(object, property, arguments[2], arguments[3]); + } + if (Common.isNumber(arguments[4])) { + return new NumberControllerBox(object, property, { min: arguments[2], max: arguments[3], step: arguments[4] }); + } + return new NumberControllerBox(object, property, { min: arguments[2], max: arguments[3] }); + } + if (Common.isString(initialValue)) { + return new StringController(object, property); + } + if (Common.isFunction(initialValue)) { + return new FunctionController(object, property, ''); + } + if (Common.isBoolean(initialValue)) { + return new BooleanController(object, property); + } + return null; +}; + +function requestAnimationFrame(callback) { + setTimeout(callback, 1000 / 60); +} +var requestAnimationFrame$1 = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || requestAnimationFrame; + +var CenteredDiv = function () { + function CenteredDiv() { + classCallCheck(this, CenteredDiv); + this.backgroundElement = document.createElement('div'); + Common.extend(this.backgroundElement.style, { + backgroundColor: 'rgba(0,0,0,0.8)', + top: 0, + left: 0, + display: 'none', + zIndex: '1000', + opacity: 0, + WebkitTransition: 'opacity 0.2s linear', + transition: 'opacity 0.2s linear' + }); + dom.makeFullscreen(this.backgroundElement); + this.backgroundElement.style.position = 'fixed'; + this.domElement = document.createElement('div'); + Common.extend(this.domElement.style, { + position: 'fixed', + display: 'none', + zIndex: '1001', + opacity: 0, + WebkitTransition: '-webkit-transform 0.2s ease-out, opacity 0.2s linear', + transition: 'transform 0.2s ease-out, opacity 0.2s linear' + }); + document.body.appendChild(this.backgroundElement); + document.body.appendChild(this.domElement); + var _this = this; + dom.bind(this.backgroundElement, 'click', function () { + _this.hide(); + }); + } + createClass(CenteredDiv, [{ + key: 'show', + value: function show() { + var _this = this; + this.backgroundElement.style.display = 'block'; + this.domElement.style.display = 'block'; + this.domElement.style.opacity = 0; + this.domElement.style.webkitTransform = 'scale(1.1)'; + this.layout(); + Common.defer(function () { + _this.backgroundElement.style.opacity = 1; + _this.domElement.style.opacity = 1; + _this.domElement.style.webkitTransform = 'scale(1)'; + }); + } + }, { + key: 'hide', + value: function hide() { + var _this = this; + var hide = function hide() { + _this.domElement.style.display = 'none'; + _this.backgroundElement.style.display = 'none'; + dom.unbind(_this.domElement, 'webkitTransitionEnd', hide); + dom.unbind(_this.domElement, 'transitionend', hide); + dom.unbind(_this.domElement, 'oTransitionEnd', hide); + }; + dom.bind(this.domElement, 'webkitTransitionEnd', hide); + dom.bind(this.domElement, 'transitionend', hide); + dom.bind(this.domElement, 'oTransitionEnd', hide); + this.backgroundElement.style.opacity = 0; + this.domElement.style.opacity = 0; + this.domElement.style.webkitTransform = 'scale(1.1)'; + } + }, { + key: 'layout', + value: function layout() { + this.domElement.style.left = window.innerWidth / 2 - dom.getWidth(this.domElement) / 2 + 'px'; + this.domElement.style.top = window.innerHeight / 2 - dom.getHeight(this.domElement) / 2 + 'px'; + } + }]); + return CenteredDiv; +}(); + +var styleSheet = ___$insertStyle(".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity .1s linear;-o-transition:opacity .1s linear;-moz-transition:opacity .1s linear;transition:opacity .1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1 !important}.dg.main:hover .close-button,.dg.main .close-button.drag{opacity:1}.dg.main .close-button{-webkit-transition:opacity .1s linear;-o-transition:opacity .1s linear;-moz-transition:opacity .1s linear;transition:opacity .1s linear;border:0;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button.close-top{position:relative}.dg.main .close-button.close-bottom{position:absolute}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-y:visible}.dg.a.has-save>ul.close-top{margin-top:0}.dg.a.has-save>ul.close-bottom{margin-top:27px}.dg.a.has-save>ul.closed{margin-top:0}.dg.a .save-row{top:0;z-index:1002}.dg.a .save-row.close-top{position:relative}.dg.a .save-row.close-bottom{position:fixed}.dg li{-webkit-transition:height .1s ease-out;-o-transition:height .1s ease-out;-moz-transition:height .1s ease-out;transition:height .1s ease-out;-webkit-transition:overflow .1s linear;-o-transition:overflow .1s linear;-moz-transition:overflow .1s linear;transition:overflow .1s linear}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid rgba(0,0,0,0)}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li>*{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px;overflow:hidden}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .cr.function .property-name{width:100%}.dg .c{float:left;width:60%;position:relative}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:7px}.dg .c select{margin-top:5px}.dg .cr.function,.dg .cr.function .property-name,.dg .cr.function *,.dg .cr.boolean,.dg .cr.boolean *{cursor:pointer}.dg .cr.color{overflow:visible}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0px 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco, monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px 'Lucida Grande', sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px 4px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid rgba(255,255,255,0.2)}.dg .closed li.title{background-image:url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==)}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.color{border-left:3px solid}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2FA1D6}.dg .cr.number input[type=text]{color:#2FA1D6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.function:hover,.dg .cr.boolean:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2FA1D6;max-width:100%}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}\n"); + +css.inject(styleSheet); +var CSS_NAMESPACE = 'dg'; +var HIDE_KEY_CODE = 72; +var CLOSE_BUTTON_HEIGHT = 20; +var DEFAULT_DEFAULT_PRESET_NAME = 'Default'; +var SUPPORTS_LOCAL_STORAGE = function () { + try { + return !!window.localStorage; + } catch (e) { + return false; + } +}(); +var SAVE_DIALOGUE = void 0; +var autoPlaceVirgin = true; +var autoPlaceContainer = void 0; +var hide = false; +var hideableGuis = []; +var GUI = function GUI(pars) { + var _this = this; + var params = pars || {}; + this.domElement = document.createElement('div'); + this.__ul = document.createElement('ul'); + this.domElement.appendChild(this.__ul); + dom.addClass(this.domElement, CSS_NAMESPACE); + this.__folders = {}; + this.__controllers = []; + this.__rememberedObjects = []; + this.__rememberedObjectIndecesToControllers = []; + this.__listening = []; + params = Common.defaults(params, { + closeOnTop: false, + autoPlace: true, + width: GUI.DEFAULT_WIDTH + }); + params = Common.defaults(params, { + resizable: params.autoPlace, + hideable: params.autoPlace + }); + if (!Common.isUndefined(params.load)) { + if (params.preset) { + params.load.preset = params.preset; + } + } else { + params.load = { preset: DEFAULT_DEFAULT_PRESET_NAME }; + } + if (Common.isUndefined(params.parent) && params.hideable) { + hideableGuis.push(this); + } + params.resizable = Common.isUndefined(params.parent) && params.resizable; + if (params.autoPlace && Common.isUndefined(params.scrollable)) { + params.scrollable = true; + } + var useLocalStorage = SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(this, 'isLocal')) === 'true'; + var saveToLocalStorage = void 0; + var titleRow = void 0; + Object.defineProperties(this, + { + parent: { + get: function get$$1() { + return params.parent; + } + }, + scrollable: { + get: function get$$1() { + return params.scrollable; + } + }, + autoPlace: { + get: function get$$1() { + return params.autoPlace; + } + }, + closeOnTop: { + get: function get$$1() { + return params.closeOnTop; + } + }, + preset: { + get: function get$$1() { + if (_this.parent) { + return _this.getRoot().preset; + } + return params.load.preset; + }, + set: function set$$1(v) { + if (_this.parent) { + _this.getRoot().preset = v; + } else { + params.load.preset = v; + } + setPresetSelectIndex(this); + _this.revert(); + } + }, + width: { + get: function get$$1() { + return params.width; + }, + set: function set$$1(v) { + params.width = v; + setWidth(_this, v); + } + }, + name: { + get: function get$$1() { + return params.name; + }, + set: function set$$1(v) { + params.name = v; + if (titleRow) { + titleRow.innerHTML = params.name; + } + } + }, + closed: { + get: function get$$1() { + return params.closed; + }, + set: function set$$1(v) { + params.closed = v; + if (params.closed) { + dom.addClass(_this.__ul, GUI.CLASS_CLOSED); + } else { + dom.removeClass(_this.__ul, GUI.CLASS_CLOSED); + } + this.onResize(); + if (_this.__closeButton) { + _this.__closeButton.innerHTML = v ? GUI.TEXT_OPEN : GUI.TEXT_CLOSED; + } + } + }, + load: { + get: function get$$1() { + return params.load; + } + }, + useLocalStorage: { + get: function get$$1() { + return useLocalStorage; + }, + set: function set$$1(bool) { + if (SUPPORTS_LOCAL_STORAGE) { + useLocalStorage = bool; + if (bool) { + dom.bind(window, 'unload', saveToLocalStorage); + } else { + dom.unbind(window, 'unload', saveToLocalStorage); + } + localStorage.setItem(getLocalStorageHash(_this, 'isLocal'), bool); + } + } + } + }); + if (Common.isUndefined(params.parent)) { + this.closed = params.closed || false; + dom.addClass(this.domElement, GUI.CLASS_MAIN); + dom.makeSelectable(this.domElement, false); + if (SUPPORTS_LOCAL_STORAGE) { + if (useLocalStorage) { + _this.useLocalStorage = true; + var savedGui = localStorage.getItem(getLocalStorageHash(this, 'gui')); + if (savedGui) { + params.load = JSON.parse(savedGui); + } + } + } + this.__closeButton = document.createElement('div'); + this.__closeButton.innerHTML = GUI.TEXT_CLOSED; + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_BUTTON); + if (params.closeOnTop) { + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_TOP); + this.domElement.insertBefore(this.__closeButton, this.domElement.childNodes[0]); + } else { + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_BOTTOM); + this.domElement.appendChild(this.__closeButton); + } + dom.bind(this.__closeButton, 'click', function () { + _this.closed = !_this.closed; + }); + } else { + if (params.closed === undefined) { + params.closed = true; + } + var titleRowName = document.createTextNode(params.name); + dom.addClass(titleRowName, 'controller-name'); + titleRow = addRow(_this, titleRowName); + var onClickTitle = function onClickTitle(e) { + e.preventDefault(); + _this.closed = !_this.closed; + return false; + }; + dom.addClass(this.__ul, GUI.CLASS_CLOSED); + dom.addClass(titleRow, 'title'); + dom.bind(titleRow, 'click', onClickTitle); + if (!params.closed) { + this.closed = false; + } + } + if (params.autoPlace) { + if (Common.isUndefined(params.parent)) { + if (autoPlaceVirgin) { + autoPlaceContainer = document.createElement('div'); + dom.addClass(autoPlaceContainer, CSS_NAMESPACE); + dom.addClass(autoPlaceContainer, GUI.CLASS_AUTO_PLACE_CONTAINER); + document.body.appendChild(autoPlaceContainer); + autoPlaceVirgin = false; + } + autoPlaceContainer.appendChild(this.domElement); + dom.addClass(this.domElement, GUI.CLASS_AUTO_PLACE); + } + if (!this.parent) { + setWidth(_this, params.width); + } + } + this.__resizeHandler = function () { + _this.onResizeDebounced(); + }; + dom.bind(window, 'resize', this.__resizeHandler); + dom.bind(this.__ul, 'webkitTransitionEnd', this.__resizeHandler); + dom.bind(this.__ul, 'transitionend', this.__resizeHandler); + dom.bind(this.__ul, 'oTransitionEnd', this.__resizeHandler); + this.onResize(); + if (params.resizable) { + addResizeHandle(this); + } + saveToLocalStorage = function saveToLocalStorage() { + if (SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(_this, 'isLocal')) === 'true') { + localStorage.setItem(getLocalStorageHash(_this, 'gui'), JSON.stringify(_this.getSaveObject())); + } + }; + this.saveToLocalStorageIfPossible = saveToLocalStorage; + function resetWidth() { + var root = _this.getRoot(); + root.width += 1; + Common.defer(function () { + root.width -= 1; + }); + } + if (!params.parent) { + resetWidth(); + } +}; +GUI.toggleHide = function () { + hide = !hide; + Common.each(hideableGuis, function (gui) { + gui.domElement.style.display = hide ? 'none' : ''; + }); +}; +GUI.CLASS_AUTO_PLACE = 'a'; +GUI.CLASS_AUTO_PLACE_CONTAINER = 'ac'; +GUI.CLASS_MAIN = 'main'; +GUI.CLASS_CONTROLLER_ROW = 'cr'; +GUI.CLASS_TOO_TALL = 'taller-than-window'; +GUI.CLASS_CLOSED = 'closed'; +GUI.CLASS_CLOSE_BUTTON = 'close-button'; +GUI.CLASS_CLOSE_TOP = 'close-top'; +GUI.CLASS_CLOSE_BOTTOM = 'close-bottom'; +GUI.CLASS_DRAG = 'drag'; +GUI.DEFAULT_WIDTH = 245; +GUI.TEXT_CLOSED = 'Close Controls'; +GUI.TEXT_OPEN = 'Open Controls'; +GUI._keydownHandler = function (e) { + if (document.activeElement.type !== 'text' && (e.which === HIDE_KEY_CODE || e.keyCode === HIDE_KEY_CODE)) { + GUI.toggleHide(); + } +}; +dom.bind(window, 'keydown', GUI._keydownHandler, false); +Common.extend(GUI.prototype, +{ + add: function add(object, property) { + return _add(this, object, property, { + factoryArgs: Array.prototype.slice.call(arguments, 2) + }); + }, + addColor: function addColor(object, property) { + return _add(this, object, property, { + color: true + }); + }, + remove: function remove(controller) { + this.__ul.removeChild(controller.__li); + this.__controllers.splice(this.__controllers.indexOf(controller), 1); + var _this = this; + Common.defer(function () { + _this.onResize(); + }); + }, + destroy: function destroy() { + if (this.parent) { + throw new Error('Only the root GUI should be removed with .destroy(). ' + 'For subfolders, use gui.removeFolder(folder) instead.'); + } + if (this.autoPlace) { + autoPlaceContainer.removeChild(this.domElement); + } + var _this = this; + Common.each(this.__folders, function (subfolder) { + _this.removeFolder(subfolder); + }); + dom.unbind(window, 'keydown', GUI._keydownHandler, false); + removeListeners(this); + }, + addFolder: function addFolder(name) { + if (this.__folders[name] !== undefined) { + throw new Error('You already have a folder in this GUI by the' + ' name "' + name + '"'); + } + var newGuiParams = { name: name, parent: this }; + newGuiParams.autoPlace = this.autoPlace; + if (this.load && + this.load.folders && + this.load.folders[name]) { + newGuiParams.closed = this.load.folders[name].closed; + newGuiParams.load = this.load.folders[name]; + } + var gui = new GUI(newGuiParams); + this.__folders[name] = gui; + var li = addRow(this, gui.domElement); + dom.addClass(li, 'folder'); + return gui; + }, + removeFolder: function removeFolder(folder) { + this.__ul.removeChild(folder.domElement.parentElement); + delete this.__folders[folder.name]; + if (this.load && + this.load.folders && + this.load.folders[folder.name]) { + delete this.load.folders[folder.name]; + } + removeListeners(folder); + var _this = this; + Common.each(folder.__folders, function (subfolder) { + folder.removeFolder(subfolder); + }); + Common.defer(function () { + _this.onResize(); + }); + }, + open: function open() { + this.closed = false; + }, + close: function close() { + this.closed = true; + }, + hide: function hide() { + this.domElement.style.display = 'none'; + }, + show: function show() { + this.domElement.style.display = ''; + }, + onResize: function onResize() { + var root = this.getRoot(); + if (root.scrollable) { + var top = dom.getOffset(root.__ul).top; + var h = 0; + Common.each(root.__ul.childNodes, function (node) { + if (!(root.autoPlace && node === root.__save_row)) { + h += dom.getHeight(node); + } + }); + if (window.innerHeight - top - CLOSE_BUTTON_HEIGHT < h) { + dom.addClass(root.domElement, GUI.CLASS_TOO_TALL); + root.__ul.style.height = window.innerHeight - top - CLOSE_BUTTON_HEIGHT + 'px'; + } else { + dom.removeClass(root.domElement, GUI.CLASS_TOO_TALL); + root.__ul.style.height = 'auto'; + } + } + if (root.__resize_handle) { + Common.defer(function () { + root.__resize_handle.style.height = root.__ul.offsetHeight + 'px'; + }); + } + if (root.__closeButton) { + root.__closeButton.style.width = root.width + 'px'; + } + }, + onResizeDebounced: Common.debounce(function () { + this.onResize(); + }, 50), + remember: function remember() { + if (Common.isUndefined(SAVE_DIALOGUE)) { + SAVE_DIALOGUE = new CenteredDiv(); + SAVE_DIALOGUE.domElement.innerHTML = saveDialogContents; + } + if (this.parent) { + throw new Error('You can only call remember on a top level GUI.'); + } + var _this = this; + Common.each(Array.prototype.slice.call(arguments), function (object) { + if (_this.__rememberedObjects.length === 0) { + addSaveMenu(_this); + } + if (_this.__rememberedObjects.indexOf(object) === -1) { + _this.__rememberedObjects.push(object); + } + }); + if (this.autoPlace) { + setWidth(this, this.width); + } + }, + getRoot: function getRoot() { + var gui = this; + while (gui.parent) { + gui = gui.parent; + } + return gui; + }, + getSaveObject: function getSaveObject() { + var toReturn = this.load; + toReturn.closed = this.closed; + if (this.__rememberedObjects.length > 0) { + toReturn.preset = this.preset; + if (!toReturn.remembered) { + toReturn.remembered = {}; + } + toReturn.remembered[this.preset] = getCurrentPreset(this); + } + toReturn.folders = {}; + Common.each(this.__folders, function (element, key) { + toReturn.folders[key] = element.getSaveObject(); + }); + return toReturn; + }, + save: function save() { + if (!this.load.remembered) { + this.load.remembered = {}; + } + this.load.remembered[this.preset] = getCurrentPreset(this); + markPresetModified(this, false); + this.saveToLocalStorageIfPossible(); + }, + saveAs: function saveAs(presetName) { + if (!this.load.remembered) { + this.load.remembered = {}; + this.load.remembered[DEFAULT_DEFAULT_PRESET_NAME] = getCurrentPreset(this, true); + } + this.load.remembered[presetName] = getCurrentPreset(this); + this.preset = presetName; + addPresetOption(this, presetName, true); + this.saveToLocalStorageIfPossible(); + }, + revert: function revert(gui) { + Common.each(this.__controllers, function (controller) { + if (!this.getRoot().load.remembered) { + controller.setValue(controller.initialValue); + } else { + recallSavedValue(gui || this.getRoot(), controller); + } + if (controller.__onFinishChange) { + controller.__onFinishChange.call(controller, controller.getValue()); + } + }, this); + Common.each(this.__folders, function (folder) { + folder.revert(folder); + }); + if (!gui) { + markPresetModified(this.getRoot(), false); + } + }, + listen: function listen(controller) { + var init = this.__listening.length === 0; + this.__listening.push(controller); + if (init) { + updateDisplays(this.__listening); + } + }, + updateDisplay: function updateDisplay() { + Common.each(this.__controllers, function (controller) { + controller.updateDisplay(); + }); + Common.each(this.__folders, function (folder) { + folder.updateDisplay(); + }); + } +}); +function addRow(gui, newDom, liBefore) { + var li = document.createElement('li'); + if (newDom) { + li.appendChild(newDom); + } + if (liBefore) { + gui.__ul.insertBefore(li, liBefore); + } else { + gui.__ul.appendChild(li); + } + gui.onResize(); + return li; +} +function removeListeners(gui) { + dom.unbind(window, 'resize', gui.__resizeHandler); + if (gui.saveToLocalStorageIfPossible) { + dom.unbind(window, 'unload', gui.saveToLocalStorageIfPossible); + } +} +function markPresetModified(gui, modified) { + var opt = gui.__preset_select[gui.__preset_select.selectedIndex]; + if (modified) { + opt.innerHTML = opt.value + '*'; + } else { + opt.innerHTML = opt.value; + } +} +function augmentController(gui, li, controller) { + controller.__li = li; + controller.__gui = gui; + Common.extend(controller, { + options: function options(_options) { + if (arguments.length > 1) { + var nextSibling = controller.__li.nextElementSibling; + controller.remove(); + return _add(gui, controller.object, controller.property, { + before: nextSibling, + factoryArgs: [Common.toArray(arguments)] + }); + } + if (Common.isArray(_options) || Common.isObject(_options)) { + var _nextSibling = controller.__li.nextElementSibling; + controller.remove(); + return _add(gui, controller.object, controller.property, { + before: _nextSibling, + factoryArgs: [_options] + }); + } + }, + name: function name(_name) { + controller.__li.firstElementChild.firstElementChild.innerHTML = _name; + return controller; + }, + listen: function listen() { + controller.__gui.listen(controller); + return controller; + }, + remove: function remove() { + controller.__gui.remove(controller); + return controller; + } + }); + if (controller instanceof NumberControllerSlider) { + var box = new NumberControllerBox(controller.object, controller.property, { min: controller.__min, max: controller.__max, step: controller.__step }); + Common.each(['updateDisplay', 'onChange', 'onFinishChange', 'step', 'min', 'max'], function (method) { + var pc = controller[method]; + var pb = box[method]; + controller[method] = box[method] = function () { + var args = Array.prototype.slice.call(arguments); + pb.apply(box, args); + return pc.apply(controller, args); + }; + }); + dom.addClass(li, 'has-slider'); + controller.domElement.insertBefore(box.domElement, controller.domElement.firstElementChild); + } else if (controller instanceof NumberControllerBox) { + var r = function r(returned) { + if (Common.isNumber(controller.__min) && Common.isNumber(controller.__max)) { + var oldName = controller.__li.firstElementChild.firstElementChild.innerHTML; + var wasListening = controller.__gui.__listening.indexOf(controller) > -1; + controller.remove(); + var newController = _add(gui, controller.object, controller.property, { + before: controller.__li.nextElementSibling, + factoryArgs: [controller.__min, controller.__max, controller.__step] + }); + newController.name(oldName); + if (wasListening) newController.listen(); + return newController; + } + return returned; + }; + controller.min = Common.compose(r, controller.min); + controller.max = Common.compose(r, controller.max); + } else if (controller instanceof BooleanController) { + dom.bind(li, 'click', function () { + dom.fakeEvent(controller.__checkbox, 'click'); + }); + dom.bind(controller.__checkbox, 'click', function (e) { + e.stopPropagation(); + }); + } else if (controller instanceof FunctionController) { + dom.bind(li, 'click', function () { + dom.fakeEvent(controller.__button, 'click'); + }); + dom.bind(li, 'mouseover', function () { + dom.addClass(controller.__button, 'hover'); + }); + dom.bind(li, 'mouseout', function () { + dom.removeClass(controller.__button, 'hover'); + }); + } else if (controller instanceof ColorController) { + dom.addClass(li, 'color'); + controller.updateDisplay = Common.compose(function (val) { + li.style.borderLeftColor = controller.__color.toString(); + return val; + }, controller.updateDisplay); + controller.updateDisplay(); + } + controller.setValue = Common.compose(function (val) { + if (gui.getRoot().__preset_select && controller.isModified()) { + markPresetModified(gui.getRoot(), true); + } + return val; + }, controller.setValue); +} +function recallSavedValue(gui, controller) { + var root = gui.getRoot(); + var matchedIndex = root.__rememberedObjects.indexOf(controller.object); + if (matchedIndex !== -1) { + var controllerMap = root.__rememberedObjectIndecesToControllers[matchedIndex]; + if (controllerMap === undefined) { + controllerMap = {}; + root.__rememberedObjectIndecesToControllers[matchedIndex] = controllerMap; + } + controllerMap[controller.property] = controller; + if (root.load && root.load.remembered) { + var presetMap = root.load.remembered; + var preset = void 0; + if (presetMap[gui.preset]) { + preset = presetMap[gui.preset]; + } else if (presetMap[DEFAULT_DEFAULT_PRESET_NAME]) { + preset = presetMap[DEFAULT_DEFAULT_PRESET_NAME]; + } else { + return; + } + if (preset[matchedIndex] && preset[matchedIndex][controller.property] !== undefined) { + var value = preset[matchedIndex][controller.property]; + controller.initialValue = value; + controller.setValue(value); + } + } + } +} +function _add(gui, object, property, params) { + if (object[property] === undefined) { + throw new Error('Object "' + object + '" has no property "' + property + '"'); + } + var controller = void 0; + if (params.color) { + controller = new ColorController(object, property); + } else { + var factoryArgs = [object, property].concat(params.factoryArgs); + controller = ControllerFactory.apply(gui, factoryArgs); + } + if (params.before instanceof Controller) { + params.before = params.before.__li; + } + recallSavedValue(gui, controller); + dom.addClass(controller.domElement, 'c'); + var name = document.createElement('span'); + dom.addClass(name, 'property-name'); + name.innerHTML = controller.property; + var container = document.createElement('div'); + container.appendChild(name); + container.appendChild(controller.domElement); + var li = addRow(gui, container, params.before); + dom.addClass(li, GUI.CLASS_CONTROLLER_ROW); + if (controller instanceof ColorController) { + dom.addClass(li, 'color'); + } else { + dom.addClass(li, _typeof(controller.getValue())); + } + augmentController(gui, li, controller); + gui.__controllers.push(controller); + return controller; +} +function getLocalStorageHash(gui, key) { + return document.location.href + '.' + key; +} +function addPresetOption(gui, name, setSelected) { + var opt = document.createElement('option'); + opt.innerHTML = name; + opt.value = name; + gui.__preset_select.appendChild(opt); + if (setSelected) { + gui.__preset_select.selectedIndex = gui.__preset_select.length - 1; + } +} +function showHideExplain(gui, explain) { + explain.style.display = gui.useLocalStorage ? 'block' : 'none'; +} +function addSaveMenu(gui) { + var div = gui.__save_row = document.createElement('li'); + dom.addClass(gui.domElement, 'has-save'); + gui.__ul.insertBefore(div, gui.__ul.firstChild); + dom.addClass(div, 'save-row'); + var gears = document.createElement('span'); + gears.innerHTML = ' '; + dom.addClass(gears, 'button gears'); + var button = document.createElement('span'); + button.innerHTML = 'Save'; + dom.addClass(button, 'button'); + dom.addClass(button, 'save'); + var button2 = document.createElement('span'); + button2.innerHTML = 'New'; + dom.addClass(button2, 'button'); + dom.addClass(button2, 'save-as'); + var button3 = document.createElement('span'); + button3.innerHTML = 'Revert'; + dom.addClass(button3, 'button'); + dom.addClass(button3, 'revert'); + var select = gui.__preset_select = document.createElement('select'); + if (gui.load && gui.load.remembered) { + Common.each(gui.load.remembered, function (value, key) { + addPresetOption(gui, key, key === gui.preset); + }); + } else { + addPresetOption(gui, DEFAULT_DEFAULT_PRESET_NAME, false); + } + dom.bind(select, 'change', function () { + for (var index = 0; index < gui.__preset_select.length; index++) { + gui.__preset_select[index].innerHTML = gui.__preset_select[index].value; + } + gui.preset = this.value; + }); + div.appendChild(select); + div.appendChild(gears); + div.appendChild(button); + div.appendChild(button2); + div.appendChild(button3); + if (SUPPORTS_LOCAL_STORAGE) { + var explain = document.getElementById('dg-local-explain'); + var localStorageCheckBox = document.getElementById('dg-local-storage'); + var saveLocally = document.getElementById('dg-save-locally'); + saveLocally.style.display = 'block'; + if (localStorage.getItem(getLocalStorageHash(gui, 'isLocal')) === 'true') { + localStorageCheckBox.setAttribute('checked', 'checked'); + } + showHideExplain(gui, explain); + dom.bind(localStorageCheckBox, 'change', function () { + gui.useLocalStorage = !gui.useLocalStorage; + showHideExplain(gui, explain); + }); + } + var newConstructorTextArea = document.getElementById('dg-new-constructor'); + dom.bind(newConstructorTextArea, 'keydown', function (e) { + if (e.metaKey && (e.which === 67 || e.keyCode === 67)) { + SAVE_DIALOGUE.hide(); + } + }); + dom.bind(gears, 'click', function () { + newConstructorTextArea.innerHTML = JSON.stringify(gui.getSaveObject(), undefined, 2); + SAVE_DIALOGUE.show(); + newConstructorTextArea.focus(); + newConstructorTextArea.select(); + }); + dom.bind(button, 'click', function () { + gui.save(); + }); + dom.bind(button2, 'click', function () { + var presetName = prompt('Enter a new preset name.'); + if (presetName) { + gui.saveAs(presetName); + } + }); + dom.bind(button3, 'click', function () { + gui.revert(); + }); +} +function addResizeHandle(gui) { + var pmouseX = void 0; + gui.__resize_handle = document.createElement('div'); + Common.extend(gui.__resize_handle.style, { + width: '6px', + marginLeft: '-3px', + height: '200px', + cursor: 'ew-resize', + position: 'absolute' + }); + function drag(e) { + e.preventDefault(); + gui.width += pmouseX - e.clientX; + gui.onResize(); + pmouseX = e.clientX; + return false; + } + function dragStop() { + dom.removeClass(gui.__closeButton, GUI.CLASS_DRAG); + dom.unbind(window, 'mousemove', drag); + dom.unbind(window, 'mouseup', dragStop); + } + function dragStart(e) { + e.preventDefault(); + pmouseX = e.clientX; + dom.addClass(gui.__closeButton, GUI.CLASS_DRAG); + dom.bind(window, 'mousemove', drag); + dom.bind(window, 'mouseup', dragStop); + return false; + } + dom.bind(gui.__resize_handle, 'mousedown', dragStart); + dom.bind(gui.__closeButton, 'mousedown', dragStart); + gui.domElement.insertBefore(gui.__resize_handle, gui.domElement.firstElementChild); +} +function setWidth(gui, w) { + gui.domElement.style.width = w + 'px'; + if (gui.__save_row && gui.autoPlace) { + gui.__save_row.style.width = w + 'px'; + } + if (gui.__closeButton) { + gui.__closeButton.style.width = w + 'px'; + } +} +function getCurrentPreset(gui, useInitialValues) { + var toReturn = {}; + Common.each(gui.__rememberedObjects, function (val, index) { + var savedValues = {}; + var controllerMap = gui.__rememberedObjectIndecesToControllers[index]; + Common.each(controllerMap, function (controller, property) { + savedValues[property] = useInitialValues ? controller.initialValue : controller.getValue(); + }); + toReturn[index] = savedValues; + }); + return toReturn; +} +function setPresetSelectIndex(gui) { + for (var index = 0; index < gui.__preset_select.length; index++) { + if (gui.__preset_select[index].value === gui.preset) { + gui.__preset_select.selectedIndex = index; + } + } +} +function updateDisplays(controllerArray) { + if (controllerArray.length !== 0) { + requestAnimationFrame$1.call(window, function () { + updateDisplays(controllerArray); + }); + } + Common.each(controllerArray, function (c) { + c.updateDisplay(); + }); +} + +var color = { + Color: Color, + math: ColorMath, + interpret: interpret +}; +var controllers = { + Controller: Controller, + BooleanController: BooleanController, + OptionController: OptionController, + StringController: StringController, + NumberController: NumberController, + NumberControllerBox: NumberControllerBox, + NumberControllerSlider: NumberControllerSlider, + FunctionController: FunctionController, + ColorController: ColorController +}; +var dom$1 = { dom: dom }; +var gui = { GUI: GUI }; +var GUI$1 = GUI; +var index = { + color: color, + controllers: controllers, + dom: dom$1, + gui: gui, + GUI: GUI$1 +}; + + +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (index); +//# sourceMappingURL=dat.gui.module.js.map + + +/***/ }), + +/***/ "../../node_modules/park-miller/index.js": +/*!***********************************************!*\ + !*** ../../node_modules/park-miller/index.js ***! + \***********************************************/ +/***/ ((module) => { + + +const MAX_INT32 = 2147483647; +const MINSTD = 16807; + +class ParkMiller { + constructor(seed) { + if (!Number.isInteger(seed)) { + throw new TypeError('Expected `seed` to be a `integer`'); + } + + this._seed = seed % MAX_INT32; + + if (this._seed <= 0) { + this._seed += (MAX_INT32 - 1); + } + } + + integer() { + this._seed *= MINSTD; + this._seed %= MAX_INT32; + return this._seed; + } + + integerInRange(min, max) { + return Math.round(this.floatInRange(min, max)); + } + + float() { + return (this.integer() - 1) / (MAX_INT32 - 1); + } + + floatInRange(min, max) { + return min + ((max - min) * this.float()); + } + + boolean() { + return this.integer() % 2 === 0; + } +} + +module.exports = ParkMiller; + + +/***/ }), + +/***/ "./canvas.ts": +/*!*******************!*\ + !*** ./canvas.ts ***! + \*******************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createCanvas: () => (/* binding */ createCanvas), +/* harmony export */ drawOptions: () => (/* binding */ drawOptions) +/* harmony export */ }); +/* harmony import */ var _snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/draw/drawWorld */ "../draw/drawWorld.ts"); + +const drawOptions = { + sizeDotBorderRadius: 2, + sizeCell: 16, + sizeDot: 12, + colorDotBorder: "#1b1f230a", + colorDots: { + 1: "#9be9a8", + 2: "#40c463", + 3: "#30a14e", + 4: "#216e39", + }, + colorEmpty: "#ebedf0", + colorSnake: "purple", + dark: { + colorEmpty: "#161b22", + colorDots: { 1: "#01311f", 2: "#034525", 3: "#0f6d31", 4: "#00c647" }, + }, +}; +const getPointedCell = (canvas) => ({ pageX, pageY }) => { + const { left, top } = canvas.getBoundingClientRect(); + const x = Math.floor((pageX - left) / drawOptions.sizeCell) - 1; + const y = Math.floor((pageY - top) / drawOptions.sizeCell) - 2; + return { x, y }; +}; +const createCanvas = ({ width, height, }) => { + const canvas = document.createElement("canvas"); + const upscale = 2; + const w = drawOptions.sizeCell * (width + 4); + const h = drawOptions.sizeCell * (height + 4) + 200; + canvas.width = w * upscale; + canvas.height = h * upscale; + canvas.style.width = w + "px"; + canvas.style.height = h + "px"; + canvas.style.display = "block"; + // canvas.style.pointerEvents = "none"; + const cellInfo = document.createElement("div"); + cellInfo.style.height = "20px"; + document.body.appendChild(cellInfo); + document.body.appendChild(canvas); + canvas.addEventListener("mousemove", (e) => { + const { x, y } = getPointedCell(canvas)(e); + cellInfo.innerText = [x, y] + .map((u) => u.toString().padStart(2, " ")) + .join(" / "); + }); + const ctx = canvas.getContext("2d"); + ctx.scale(upscale, upscale); + const draw = (grid, snake, stack) => { + ctx.clearRect(0, 0, 9999, 9999); + (0,_snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__.drawWorld)(ctx, grid, null, snake, stack, drawOptions); + }; + const drawLerp = (grid, snake0, snake1, stack, k) => { + ctx.clearRect(0, 0, 9999, 9999); + (0,_snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__.drawLerpWorld)(ctx, grid, null, snake0, snake1, stack, k, drawOptions); + }; + const highlightCell = (x, y, color = "orange") => { + ctx.fillStyle = color; + ctx.beginPath(); + ctx.fillRect((1 + x + 0.5) * 16 - 2, (2 + y + 0.5) * 16 - 2, 4, 4); + }; + return { + draw, + drawLerp, + highlightCell, + canvas, + getPointedCell: getPointedCell(canvas), + ctx, + }; +}; + + +/***/ }), + +/***/ "./menu.ts": +/*!*****************!*\ + !*** ./menu.ts ***! + \*****************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ gui: () => (/* binding */ gui) +/* harmony export */ }); +/* harmony import */ var dat_gui__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! dat.gui */ "../../node_modules/dat.gui/build/dat.gui.module.js"); +/* harmony import */ var _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/__fixtures__/grid */ "../types/__fixtures__/grid.ts"); +/* harmony import */ var _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/__fixtures__/snake */ "../types/__fixtures__/snake.ts"); +/* harmony import */ var _sample__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sample */ "./sample.ts"); + + + + +const demos = __webpack_require__(/*! ./demo.json */ "./demo.json"); +const gui = new dat_gui__WEBPACK_IMPORTED_MODULE_0__.GUI(); +const config = { + snake: Object.entries(_snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__).find(([_, s]) => s === _sample__WEBPACK_IMPORTED_MODULE_3__.snake)[0], + grid: Object.entries(_snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__).find(([_, s]) => s === _sample__WEBPACK_IMPORTED_MODULE_3__.grid)[0], + demo: demos[0], +}; +{ + const d = window.location.pathname.match(/(\w+)\.html/); + if (d && demos.includes(d[1])) + config.demo = d[1]; +} +const onChange = () => { + const search = new URLSearchParams({ + snake: config.snake, + grid: config.grid, + }).toString(); + const url = new URL(config.demo + ".html?" + search, window.location.href).toString(); + window.location.href = url; +}; +gui.add(config, "demo", demos).onChange(onChange); +gui.add(config, "grid", Object.keys(_snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__)).onChange(onChange); +gui.add(config, "snake", Object.keys(_snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__)).onChange(onChange); + + +/***/ }), + +/***/ "./sample.ts": +/*!*******************!*\ + !*** ./sample.ts ***! + \*******************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ grid: () => (/* binding */ grid), +/* harmony export */ snake: () => (/* binding */ snake) +/* harmony export */ }); +/* harmony import */ var _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/__fixtures__/grid */ "../types/__fixtures__/grid.ts"); +/* harmony import */ var _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/__fixtures__/snake */ "../types/__fixtures__/snake.ts"); + + +const sp = new URLSearchParams(window.location.search); +const gLabel = sp.get("grid") || "simple"; +const sLabel = sp.get("snake") || "snake3"; +//@ts-ignore +const grid = _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__[gLabel] || _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__.simple; +//@ts-ignore +const snake = _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__[sLabel] || _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__.snake3; + + +/***/ }), + +/***/ "../draw/drawGrid.ts": +/*!***************************!*\ + !*** ../draw/drawGrid.ts ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawGrid: () => (/* binding */ drawGrid) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _pathRoundedRect__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./pathRoundedRect */ "../draw/pathRoundedRect.ts"); + + +const drawGrid = (ctx, grid, cells, o) => { + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + if (!cells || cells.some((c) => c.x === x && c.y === y)) { + const c = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + // @ts-ignore + const color = !c ? o.colorEmpty : o.colorDots[c]; + ctx.save(); + ctx.translate(x * o.sizeCell + (o.sizeCell - o.sizeDot) / 2, y * o.sizeCell + (o.sizeCell - o.sizeDot) / 2); + ctx.fillStyle = color; + ctx.strokeStyle = o.colorDotBorder; + ctx.lineWidth = 1; + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_1__.pathRoundedRect)(ctx, o.sizeDot, o.sizeDot, o.sizeDotBorderRadius); + ctx.fill(); + ctx.stroke(); + ctx.closePath(); + ctx.restore(); + } + } +}; + + +/***/ }), + +/***/ "../draw/drawSnake.ts": +/*!****************************!*\ + !*** ../draw/drawSnake.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawSnake: () => (/* binding */ drawSnake), +/* harmony export */ drawSnakeLerp: () => (/* binding */ drawSnakeLerp) +/* harmony export */ }); +/* harmony import */ var _pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./pathRoundedRect */ "../draw/pathRoundedRect.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); + + +const drawSnake = (ctx, snake, o) => { + const cells = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.snakeToCells)(snake); + for (let i = 0; i < cells.length; i++) { + const u = (i + 1) * 0.6; + ctx.save(); + ctx.fillStyle = o.colorSnake; + ctx.translate(cells[i].x * o.sizeCell + u, cells[i].y * o.sizeCell + u); + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__.pathRoundedRect)(ctx, o.sizeCell - u * 2, o.sizeCell - u * 2, (o.sizeCell - u * 2) * 0.25); + ctx.fill(); + ctx.restore(); + } +}; +const lerp = (k, a, b) => (1 - k) * a + k * b; +const clamp = (x, a, b) => Math.max(a, Math.min(b, x)); +const drawSnakeLerp = (ctx, snake0, snake1, k, o) => { + const m = 0.8; + const n = snake0.length / 2; + for (let i = 0; i < n; i++) { + const u = (i + 1) * 0.6 * (o.sizeCell / 16); + const a = (1 - m) * (i / Math.max(n - 1, 1)); + const ki = clamp((k - a) / m, 0, 1); + const x = lerp(ki, snake0[i * 2 + 0], snake1[i * 2 + 0]) - 2; + const y = lerp(ki, snake0[i * 2 + 1], snake1[i * 2 + 1]) - 2; + ctx.save(); + ctx.fillStyle = o.colorSnake; + ctx.translate(x * o.sizeCell + u, y * o.sizeCell + u); + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__.pathRoundedRect)(ctx, o.sizeCell - u * 2, o.sizeCell - u * 2, (o.sizeCell - u * 2) * 0.25); + ctx.fill(); + ctx.restore(); + } +}; + + +/***/ }), + +/***/ "../draw/drawWorld.ts": +/*!****************************!*\ + !*** ../draw/drawWorld.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawLerpWorld: () => (/* binding */ drawLerpWorld), +/* harmony export */ drawStack: () => (/* binding */ drawStack), +/* harmony export */ drawWorld: () => (/* binding */ drawWorld), +/* harmony export */ getCanvasWorldSize: () => (/* binding */ getCanvasWorldSize) +/* harmony export */ }); +/* harmony import */ var _drawGrid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./drawGrid */ "../draw/drawGrid.ts"); +/* harmony import */ var _drawSnake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./drawSnake */ "../draw/drawSnake.ts"); + + +const drawStack = (ctx, stack, max, width, o) => { + ctx.save(); + const m = width / max; + for (let i = 0; i < stack.length; i++) { + // @ts-ignore + ctx.fillStyle = o.colorDots[stack[i]]; + ctx.fillRect(i * m, 0, m + width * 0.005, 10); + } + ctx.restore(); +}; +const drawWorld = (ctx, grid, cells, snake, stack, o) => { + ctx.save(); + ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); + (0,_drawGrid__WEBPACK_IMPORTED_MODULE_0__.drawGrid)(ctx, grid, cells, o); + (0,_drawSnake__WEBPACK_IMPORTED_MODULE_1__.drawSnake)(ctx, snake, o); + ctx.restore(); + ctx.save(); + ctx.translate(o.sizeCell, (grid.height + 4) * o.sizeCell); + const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length); + drawStack(ctx, stack, max, grid.width * o.sizeCell, o); + ctx.restore(); + // ctx.save(); + // ctx.translate(o.sizeCell + 100, (grid.height + 4) * o.sizeCell + 100); + // ctx.scale(0.6, 0.6); + // drawCircleStack(ctx, stack, o); + // ctx.restore(); +}; +const drawLerpWorld = (ctx, grid, cells, snake0, snake1, stack, k, o) => { + ctx.save(); + ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); + (0,_drawGrid__WEBPACK_IMPORTED_MODULE_0__.drawGrid)(ctx, grid, cells, o); + (0,_drawSnake__WEBPACK_IMPORTED_MODULE_1__.drawSnakeLerp)(ctx, snake0, snake1, k, o); + ctx.translate(0, (grid.height + 2) * o.sizeCell); + const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length); + drawStack(ctx, stack, max, grid.width * o.sizeCell, o); + ctx.restore(); +}; +const getCanvasWorldSize = (grid, o) => { + const width = o.sizeCell * (grid.width + 2); + const height = o.sizeCell * (grid.height + 4) + 30; + return { width, height }; +}; + + +/***/ }), + +/***/ "../draw/pathRoundedRect.ts": +/*!**********************************!*\ + !*** ../draw/pathRoundedRect.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ pathRoundedRect: () => (/* binding */ pathRoundedRect) +/* harmony export */ }); +const pathRoundedRect = (ctx, width, height, borderRadius) => { + ctx.moveTo(borderRadius, 0); + ctx.arcTo(width, 0, width, height, borderRadius); + ctx.arcTo(width, height, 0, height, borderRadius); + ctx.arcTo(0, height, 0, 0, borderRadius); + ctx.arcTo(0, 0, width, 0, borderRadius); +}; + + +/***/ }), + +/***/ "../solver/clearCleanColoredLayer.ts": +/*!*******************************************!*\ + !*** ../solver/clearCleanColoredLayer.ts ***! + \*******************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ clearCleanColoredLayer: () => (/* binding */ clearCleanColoredLayer), +/* harmony export */ getTunnellablePoints: () => (/* binding */ getTunnellablePoints) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); +/* harmony import */ var _getBestTunnel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./getBestTunnel */ "../solver/getBestTunnel.ts"); +/* harmony import */ var _outside__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./outside */ "../solver/outside.ts"); + + + + + +const clearCleanColoredLayer = (grid, outside, snake0, color) => { + const snakeN = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getSnakeLength)(snake0); + const points = getTunnellablePoints(grid, outside, snakeN, color); + const chain = [snake0]; + while (points.length) { + const path = getPathToNextPoint(grid, chain[0], color, points); + path.pop(); + for (const snake of path) + setEmptySafe(grid, (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake)); + chain.unshift(...path); + } + (0,_outside__WEBPACK_IMPORTED_MODULE_4__.fillOutside)(outside, grid); + chain.pop(); + return chain; +}; +const unwrap = (m) => !m ? [] : [m.snake, ...unwrap(m.parent)]; +const getPathToNextPoint = (grid, snake0, color, points) => { + const closeList = []; + const openList = [{ snake: snake0 }]; + while (openList.length) { + const o = openList.shift(); + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(o.snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(o.snake); + const i = points.findIndex((p) => p.x === x && p.y === y); + if (i >= 0) { + points.splice(i, 1); + return unwrap(o); + } + for (const { x: dx, y: dy } of _snk_types_point__WEBPACK_IMPORTED_MODULE_2__.around4) { + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInsideLarge)(grid, 2, x + dx, y + dy) && + !(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.snakeWillSelfCollide)(o.snake, dx, dy) && + getColorSafe(grid, x + dx, y + dy) <= color) { + const snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.nextSnake)(o.snake, dx, dy); + if (!closeList.some((s0) => (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.snakeEquals)(s0, snake))) { + closeList.push(snake); + openList.push({ snake, parent: o }); + } + } + } + } +}; +/** + * get all cells that are tunnellable + */ +const getTunnellablePoints = (grid, outside, snakeN, color) => { + const points = []; + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + const c = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + if (!(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)(c) && + c <= color && + !points.some((p) => p.x === x && p.y === y)) { + const tunnel = (0,_getBestTunnel__WEBPACK_IMPORTED_MODULE_3__.getBestTunnel)(grid, outside, x, y, color, snakeN); + if (tunnel) + for (const p of tunnel) + if (!isEmptySafe(grid, p.x, p.y)) + points.push(p); + } + } + return points; +}; +const getColorSafe = (grid, x, y) => (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) ? (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) : 0; +const setEmptySafe = (grid, x, y) => { + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y)) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); +}; +const isEmptySafe = (grid, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) && (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y)); + + +/***/ }), + +/***/ "../solver/clearResidualColoredLayer.ts": +/*!**********************************************!*\ + !*** ../solver/clearResidualColoredLayer.ts ***! + \**********************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ clearResidualColoredLayer: () => (/* binding */ clearResidualColoredLayer), +/* harmony export */ getPriority: () => (/* binding */ getPriority), +/* harmony export */ getTunnellablePoints: () => (/* binding */ getTunnellablePoints) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _getBestTunnel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./getBestTunnel */ "../solver/getBestTunnel.ts"); +/* harmony import */ var _outside__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./outside */ "../solver/outside.ts"); +/* harmony import */ var _tunnel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./tunnel */ "../solver/tunnel.ts"); +/* harmony import */ var _getPathTo__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./getPathTo */ "../solver/getPathTo.ts"); + + + + + + +const clearResidualColoredLayer = (grid, outside, snake0, color) => { + const snakeN = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getSnakeLength)(snake0); + const tunnels = getTunnellablePoints(grid, outside, snakeN, color); + // sort + tunnels.sort((a, b) => b.priority - a.priority); + const chain = [snake0]; + while (tunnels.length) { + // get the best next tunnel + let t = getNextTunnel(tunnels, chain[0]); + // goes to the start of the tunnel + chain.unshift(...(0,_getPathTo__WEBPACK_IMPORTED_MODULE_5__.getPathTo)(grid, chain[0], t[0].x, t[0].y)); + // goes to the end of the tunnel + chain.unshift(...(0,_tunnel__WEBPACK_IMPORTED_MODULE_4__.getTunnelPath)(chain[0], t)); + // update grid + for (const { x, y } of t) + setEmptySafe(grid, x, y); + // update outside + (0,_outside__WEBPACK_IMPORTED_MODULE_3__.fillOutside)(outside, grid); + // update tunnels + for (let i = tunnels.length; i--;) + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, tunnels[i].x, tunnels[i].y))) + tunnels.splice(i, 1); + else { + const t = tunnels[i]; + const tunnel = (0,_getBestTunnel__WEBPACK_IMPORTED_MODULE_2__.getBestTunnel)(grid, outside, t.x, t.y, color, snakeN); + if (!tunnel) + tunnels.splice(i, 1); + else { + t.tunnel = tunnel; + t.priority = getPriority(grid, color, tunnel); + } + } + // re-sort + tunnels.sort((a, b) => b.priority - a.priority); + } + chain.pop(); + return chain; +}; +const getNextTunnel = (ts, snake) => { + let minDistance = Infinity; + let closestTunnel = null; + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake); + const priority = ts[0].priority; + for (let i = 0; ts[i] && ts[i].priority === priority; i++) { + const t = ts[i].tunnel; + const d = distanceSq(t[0].x, t[0].y, x, y); + if (d < minDistance) { + minDistance = d; + closestTunnel = t; + } + } + return closestTunnel; +}; +/** + * get all the tunnels for all the cells accessible + */ +const getTunnellablePoints = (grid, outside, snakeN, color) => { + const points = []; + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + const c = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + if (!(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)(c) && c < color) { + const tunnel = (0,_getBestTunnel__WEBPACK_IMPORTED_MODULE_2__.getBestTunnel)(grid, outside, x, y, color, snakeN); + if (tunnel) { + const priority = getPriority(grid, color, tunnel); + points.push({ x, y, priority, tunnel }); + } + } + } + return points; +}; +/** + * get the score of the tunnel + * prioritize tunnel with maximum color smaller than and with minimum + * with some tweaks + */ +const getPriority = (grid, color, tunnel) => { + let nColor = 0; + let nLess = 0; + for (let i = 0; i < tunnel.length; i++) { + const { x, y } = tunnel[i]; + const c = getColorSafe(grid, x, y); + if (!(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)(c) && i === tunnel.findIndex((p) => p.x === x && p.y === y)) { + if (c === color) + nColor += 1; + else + nLess += color - c; + } + } + if (nColor === 0) + return 99999; + return nLess / nColor; +}; +const distanceSq = (ax, ay, bx, by) => (ax - bx) ** 2 + (ay - by) ** 2; +const getColorSafe = (grid, x, y) => (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) ? (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) : 0; +const setEmptySafe = (grid, x, y) => { + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y)) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); +}; + + +/***/ }), + +/***/ "../solver/getBestRoute.ts": +/*!*********************************!*\ + !*** ../solver/getBestRoute.ts ***! + \*********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getBestRoute: () => (/* binding */ getBestRoute) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _outside__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./outside */ "../solver/outside.ts"); +/* harmony import */ var _clearResidualColoredLayer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./clearResidualColoredLayer */ "../solver/clearResidualColoredLayer.ts"); +/* harmony import */ var _clearCleanColoredLayer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./clearCleanColoredLayer */ "../solver/clearCleanColoredLayer.ts"); + + + + +const getBestRoute = (grid0, snake0) => { + const grid = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.copyGrid)(grid0); + const outside = (0,_outside__WEBPACK_IMPORTED_MODULE_1__.createOutside)(grid); + const chain = [snake0]; + for (const color of extractColors(grid)) { + if (color > 1) + chain.unshift(...(0,_clearResidualColoredLayer__WEBPACK_IMPORTED_MODULE_2__.clearResidualColoredLayer)(grid, outside, chain[0], color)); + chain.unshift(...(0,_clearCleanColoredLayer__WEBPACK_IMPORTED_MODULE_3__.clearCleanColoredLayer)(grid, outside, chain[0], color)); + } + return chain.reverse(); +}; +const extractColors = (grid) => { + // @ts-ignore + let maxColor = Math.max(...grid.data); + return Array.from({ length: maxColor }, (_, i) => (i + 1)); +}; + + +/***/ }), + +/***/ "../solver/getBestTunnel.ts": +/*!**********************************!*\ + !*** ../solver/getBestTunnel.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getBestTunnel: () => (/* binding */ getBestTunnel) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); +/* harmony import */ var _utils_sortPush__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils/sortPush */ "../solver/utils/sortPush.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _outside__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./outside */ "../solver/outside.ts"); +/* harmony import */ var _tunnel__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./tunnel */ "../solver/tunnel.ts"); + + + + + + +const getColorSafe = (grid, x, y) => (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) ? (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) : 0; +const setEmptySafe = (grid, x, y) => { + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y)) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); +}; +const unwrap = (m) => !m + ? [] + : [...unwrap(m.parent), { x: (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadX)(m.snake), y: (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadY)(m.snake) }]; +/** + * returns the path to reach the outside which contains the least color cell + */ +const getSnakeEscapePath = (grid, outside, snake0, color) => { + const openList = [{ snake: snake0, w: 0 }]; + const closeList = []; + while (openList[0]) { + const o = openList.shift(); + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadX)(o.snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadY)(o.snake); + if ((0,_outside__WEBPACK_IMPORTED_MODULE_4__.isOutside)(outside, x, y)) + return unwrap(o); + for (const a of _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4) { + const c = getColorSafe(grid, x + a.x, y + a.y); + if (c <= color && !(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.snakeWillSelfCollide)(o.snake, a.x, a.y)) { + const snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.nextSnake)(o.snake, a.x, a.y); + if (!closeList.some((s0) => (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.snakeEquals)(s0, snake))) { + const w = o.w + 1 + +(c === color) * 1000; + (0,_utils_sortPush__WEBPACK_IMPORTED_MODULE_2__.sortPush)(openList, { snake, w, parent: o }, (a, b) => a.w - b.w); + closeList.push(snake); + } + } + } + } + return null; +}; +/** + * compute the best tunnel to get to the cell and back to the outside ( best = less usage of ) + * + * notice that it's one of the best tunnels, more with the same score could exist + */ +const getBestTunnel = (grid, outside, x, y, color, snakeN) => { + const c = { x, y }; + const snake0 = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.createSnakeFromCells)(Array.from({ length: snakeN }, () => c)); + const one = getSnakeEscapePath(grid, outside, snake0, color); + if (!one) + return null; + // get the position of the snake if it was going to leave the x,y cell + const snakeICells = one.slice(0, snakeN); + while (snakeICells.length < snakeN) + snakeICells.push(snakeICells[snakeICells.length - 1]); + const snakeI = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.createSnakeFromCells)(snakeICells); + // remove from the grid the colors that one eat + const gridI = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.copyGrid)(grid); + for (const { x, y } of one) + setEmptySafe(gridI, x, y); + const two = getSnakeEscapePath(gridI, outside, snakeI, color); + if (!two) + return null; + one.shift(); + one.reverse(); + one.push(...two); + (0,_tunnel__WEBPACK_IMPORTED_MODULE_5__.trimTunnelStart)(grid, one); + (0,_tunnel__WEBPACK_IMPORTED_MODULE_5__.trimTunnelEnd)(grid, one); + return one; +}; + + +/***/ }), + +/***/ "../solver/getPathTo.ts": +/*!******************************!*\ + !*** ../solver/getPathTo.ts ***! + \******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getPathTo: () => (/* binding */ getPathTo) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _utils_sortPush__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./utils/sortPush */ "../solver/utils/sortPush.ts"); + + + + +/** + * starting from snake0, get to the cell x,y + * return the snake chain (reversed) + */ +const getPathTo = (grid, snake0, x, y) => { + const openList = [{ snake: snake0, w: 0 }]; + const closeList = []; + while (openList.length) { + const c = openList.shift(); + const cx = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.getHeadX)(c.snake); + const cy = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.getHeadY)(c.snake); + for (let i = 0; i < _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4.length; i++) { + const { x: dx, y: dy } = _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4[i]; + const nx = cx + dx; + const ny = cy + dy; + if (nx === x && ny === y) { + // unwrap + const path = [(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.nextSnake)(c.snake, dx, dy)]; + let e = c; + while (e.parent) { + path.push(e.snake); + e = e.parent; + } + return path; + } + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInsideLarge)(grid, 2, nx, ny) && + !(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.snakeWillSelfCollide)(c.snake, dx, dy) && + (!(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, nx, ny) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, nx, ny)))) { + const nsnake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.nextSnake)(c.snake, dx, dy); + if (!closeList.some((s) => (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.snakeEquals)(nsnake, s))) { + const w = c.w + 1; + const h = Math.abs(nx - x) + Math.abs(ny - y); + const f = w + h; + const o = { snake: nsnake, parent: c, w, h, f }; + (0,_utils_sortPush__WEBPACK_IMPORTED_MODULE_3__.sortPush)(openList, o, (a, b) => a.f - b.f); + closeList.push(nsnake); + } + } + } + } +}; + + +/***/ }), + +/***/ "../solver/outside.ts": +/*!****************************!*\ + !*** ../solver/outside.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createOutside: () => (/* binding */ createOutside), +/* harmony export */ fillOutside: () => (/* binding */ fillOutside), +/* harmony export */ isOutside: () => (/* binding */ isOutside) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); + + +const createOutside = (grid, color = 0) => { + const outside = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.createEmptyGrid)(grid.width, grid.height); + for (let x = outside.width; x--;) + for (let y = outside.height; y--;) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(outside, x, y, 1); + fillOutside(outside, grid, color); + return outside; +}; +const fillOutside = (outside, grid, color = 0) => { + let changed = true; + while (changed) { + changed = false; + for (let x = outside.width; x--;) + for (let y = outside.height; y--;) + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) <= color && + !isOutside(outside, x, y) && + _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4.some((a) => isOutside(outside, x + a.x, y + a.y))) { + changed = true; + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(outside, x, y); + } + } + return outside; +}; +const isOutside = (outside, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(outside, x, y) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(outside, x, y)); + + +/***/ }), + +/***/ "../solver/step.ts": +/*!*************************!*\ + !*** ../solver/step.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ step: () => (/* binding */ step) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); + + +const step = (grid, stack, snake) => { + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake); + const color = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) && !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)(color)) { + stack.push(color); + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); + } +}; + + +/***/ }), + +/***/ "../solver/tunnel.ts": +/*!***************************!*\ + !*** ../solver/tunnel.ts ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getTunnelPath: () => (/* binding */ getTunnelPath), +/* harmony export */ trimTunnelEnd: () => (/* binding */ trimTunnelEnd), +/* harmony export */ trimTunnelStart: () => (/* binding */ trimTunnelStart), +/* harmony export */ updateTunnel: () => (/* binding */ updateTunnel) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); + + +/** + * get the sequence of snake to cross the tunnel + */ +const getTunnelPath = (snake0, tunnel) => { + const chain = []; + let snake = snake0; + for (let i = 1; i < tunnel.length; i++) { + const dx = tunnel[i].x - (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake); + const dy = tunnel[i].y - (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake); + snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.nextSnake)(snake, dx, dy); + chain.unshift(snake); + } + return chain; +}; +/** + * assuming the grid change and the colors got deleted, update the tunnel + */ +const updateTunnel = (grid, tunnel, toDelete) => { + while (tunnel.length) { + const { x, y } = tunnel[0]; + if (isEmptySafe(grid, x, y) || + toDelete.some((p) => p.x === x && p.y === y)) { + tunnel.shift(); + } + else + break; + } + while (tunnel.length) { + const { x, y } = tunnel[tunnel.length - 1]; + if (isEmptySafe(grid, x, y) || + toDelete.some((p) => p.x === x && p.y === y)) { + tunnel.pop(); + } + else + break; + } +}; +const isEmptySafe = (grid, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y)); +/** + * remove empty cell from start + */ +const trimTunnelStart = (grid, tunnel) => { + while (tunnel.length) { + const { x, y } = tunnel[0]; + if (isEmptySafe(grid, x, y)) + tunnel.shift(); + else + break; + } +}; +/** + * remove empty cell from end + */ +const trimTunnelEnd = (grid, tunnel) => { + while (tunnel.length) { + const i = tunnel.length - 1; + const { x, y } = tunnel[i]; + if (isEmptySafe(grid, x, y) || + tunnel.findIndex((p) => p.x === x && p.y === y) < i) + tunnel.pop(); + else + break; + } +}; + + +/***/ }), + +/***/ "../solver/utils/sortPush.ts": +/*!***********************************!*\ + !*** ../solver/utils/sortPush.ts ***! + \***********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ sortPush: () => (/* binding */ sortPush) +/* harmony export */ }); +const sortPush = (arr, x, sortFn) => { + let a = 0; + let b = arr.length; + if (arr.length === 0 || sortFn(x, arr[a]) <= 0) { + arr.unshift(x); + return; + } + while (b - a > 1) { + const e = Math.ceil((a + b) / 2); + const s = sortFn(x, arr[e]); + if (s === 0) + a = b = e; + else if (s > 0) + a = e; + else + b = e; + } + const e = Math.ceil((a + b) / 2); + arr.splice(e, 0, x); +}; + + +/***/ }), + +/***/ "../types/__fixtures__/createFromAscii.ts": +/*!************************************************!*\ + !*** ../types/__fixtures__/createFromAscii.ts ***! + \************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createFromAscii: () => (/* binding */ createFromAscii) +/* harmony export */ }); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../grid */ "../types/grid.ts"); + +const createFromAscii = (ascii) => { + const a = ascii.split("\n"); + if (a[0] === "") + a.shift(); + const height = a.length; + const width = Math.max(...a.map((r) => r.length)); + const grid = (0,_grid__WEBPACK_IMPORTED_MODULE_0__.createEmptyGrid)(width, height); + for (let x = width; x--;) + for (let y = height; y--;) { + const c = a[y][x]; + const color = (c === "#" && 3) || (c === "@" && 2) || (c === "." && 1) || +c; + if (c) + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(grid, x, y, color); + } + return grid; +}; + + +/***/ }), + +/***/ "../types/__fixtures__/grid.ts": +/*!*************************************!*\ + !*** ../types/__fixtures__/grid.ts ***! + \*************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ closedO: () => (/* binding */ closedO), +/* harmony export */ closedP: () => (/* binding */ closedP), +/* harmony export */ closedU: () => (/* binding */ closedU), +/* harmony export */ corner: () => (/* binding */ corner), +/* harmony export */ empty: () => (/* binding */ empty), +/* harmony export */ enclaveBorder: () => (/* binding */ enclaveBorder), +/* harmony export */ enclaveK: () => (/* binding */ enclaveK), +/* harmony export */ enclaveM: () => (/* binding */ enclaveM), +/* harmony export */ enclaveN: () => (/* binding */ enclaveN), +/* harmony export */ enclaveU: () => (/* binding */ enclaveU), +/* harmony export */ realistic: () => (/* binding */ realistic), +/* harmony export */ realisticFull: () => (/* binding */ realisticFull), +/* harmony export */ simple: () => (/* binding */ simple), +/* harmony export */ small: () => (/* binding */ small), +/* harmony export */ smallFull: () => (/* binding */ smallFull), +/* harmony export */ smallPacked: () => (/* binding */ smallPacked), +/* harmony export */ tunnels: () => (/* binding */ tunnels) +/* harmony export */ }); +/* harmony import */ var park_miller__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! park-miller */ "../../node_modules/park-miller/index.js"); +/* harmony import */ var park_miller__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(park_miller__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../grid */ "../types/grid.ts"); +/* harmony import */ var _randomlyFillGrid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../randomlyFillGrid */ "../types/randomlyFillGrid.ts"); +/* harmony import */ var _createFromAscii__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./createFromAscii */ "../types/__fixtures__/createFromAscii.ts"); + + + + +const colors = [1, 2, 3]; +// empty small grid +const empty = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +// empty small grid with a unique color at the middle +const simple = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(simple, 2, 2, 1); +// empty small grid with color at each corner +const corner = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 0, 4, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 4, 0, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 4, 4, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 0, 0, 1); +const enclaveN = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #.# + # + +`); +const enclaveBorder = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + #.# + # + +`); +const enclaveM = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### + # # + # . # + # # + # # +`); +const enclaveK = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + # .# + # # + # # + # # +`); +const enclaveU = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + #..# + #..# + #.# + # # . +`); +const closedP = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### + ##.# + ## # + ## +`); +const closedU = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + #..# + #..# + #.# + ### +`); +const closedO = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ####### + # # + # . # + # # + ####### +`); +const tunnels = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### ### ### + #.# #.# #.# + #.# ### # # +`); +const createRandom = (width, height, emptyP) => { + const grid = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(width, height); + const pm = new (park_miller__WEBPACK_IMPORTED_MODULE_0___default())(10); + const random = pm.integerInRange.bind(pm); + (0,_randomlyFillGrid__WEBPACK_IMPORTED_MODULE_2__.randomlyFillGrid)(grid, { colors, emptyP }, random); + return grid; +}; +// small realistic +const small = createRandom(10, 7, 3); +const smallPacked = createRandom(10, 7, 1); +const smallFull = createRandom(10, 7, 0); +// small realistic +const realistic = createRandom(52, 7, 3); +const realisticFull = createRandom(52, 7, 0); + + +/***/ }), + +/***/ "../types/__fixtures__/snake.ts": +/*!**************************************!*\ + !*** ../types/__fixtures__/snake.ts ***! + \**************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ snake1: () => (/* binding */ snake1), +/* harmony export */ snake3: () => (/* binding */ snake3), +/* harmony export */ snake4: () => (/* binding */ snake4), +/* harmony export */ snake5: () => (/* binding */ snake5), +/* harmony export */ snake9: () => (/* binding */ snake9) +/* harmony export */ }); +/* harmony import */ var _snake__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../snake */ "../types/snake.ts"); + +const create = (length) => (0,_snake__WEBPACK_IMPORTED_MODULE_0__.createSnakeFromCells)(Array.from({ length }, (_, i) => ({ x: i, y: -1 }))); +const snake1 = create(1); +const snake3 = create(3); +const snake4 = create(4); +const snake5 = create(5); +const snake9 = create(9); + + +/***/ }), + +/***/ "../types/grid.ts": +/*!************************!*\ + !*** ../types/grid.ts ***! + \************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copyGrid: () => (/* binding */ copyGrid), +/* harmony export */ createEmptyGrid: () => (/* binding */ createEmptyGrid), +/* harmony export */ getColor: () => (/* binding */ getColor), +/* harmony export */ gridEquals: () => (/* binding */ gridEquals), +/* harmony export */ isEmpty: () => (/* binding */ isEmpty), +/* harmony export */ isGridEmpty: () => (/* binding */ isGridEmpty), +/* harmony export */ isInside: () => (/* binding */ isInside), +/* harmony export */ isInsideLarge: () => (/* binding */ isInsideLarge), +/* harmony export */ setColor: () => (/* binding */ setColor), +/* harmony export */ setColorEmpty: () => (/* binding */ setColorEmpty) +/* harmony export */ }); +const isInside = (grid, x, y) => x >= 0 && y >= 0 && x < grid.width && y < grid.height; +const isInsideLarge = (grid, m, x, y) => x >= -m && y >= -m && x < grid.width + m && y < grid.height + m; +const copyGrid = ({ width, height, data }) => ({ + width, + height, + data: Uint8Array.from(data), +}); +const getIndex = (grid, x, y) => x * grid.height + y; +const getColor = (grid, x, y) => grid.data[getIndex(grid, x, y)]; +const isEmpty = (color) => color === 0; +const setColor = (grid, x, y, color) => { + grid.data[getIndex(grid, x, y)] = color || 0; +}; +const setColorEmpty = (grid, x, y) => { + setColor(grid, x, y, 0); +}; +/** + * return true if the grid is empty + */ +const isGridEmpty = (grid) => grid.data.every((x) => x === 0); +const gridEquals = (a, b) => a.data.every((_, i) => a.data[i] === b.data[i]); +const createEmptyGrid = (width, height) => ({ + width, + height, + data: new Uint8Array(width * height), +}); + + +/***/ }), + +/***/ "../types/point.ts": +/*!*************************!*\ + !*** ../types/point.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ around4: () => (/* binding */ around4), +/* harmony export */ pointEquals: () => (/* binding */ pointEquals) +/* harmony export */ }); +const around4 = [ + { x: 1, y: 0 }, + { x: 0, y: -1 }, + { x: -1, y: 0 }, + { x: 0, y: 1 }, +]; +const pointEquals = (a, b) => a.x === b.x && a.y === b.y; + + +/***/ }), + +/***/ "../types/randomlyFillGrid.ts": +/*!************************************!*\ + !*** ../types/randomlyFillGrid.ts ***! + \************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ randomlyFillGrid: () => (/* binding */ randomlyFillGrid) +/* harmony export */ }); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./grid */ "../types/grid.ts"); + +const defaultRand = (a, b) => Math.floor(Math.random() * (b - a + 1)) + a; +const randomlyFillGrid = (grid, { colors = [1, 2, 3], emptyP = 2, } = {}, rand = defaultRand) => { + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + const k = rand(-emptyP, colors.length - 1); + if (k >= 0) + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(grid, x, y, colors[k]); + else + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); + } +}; + + +/***/ }), + +/***/ "../types/snake.ts": +/*!*************************!*\ + !*** ../types/snake.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copySnake: () => (/* binding */ copySnake), +/* harmony export */ createSnakeFromCells: () => (/* binding */ createSnakeFromCells), +/* harmony export */ getHeadX: () => (/* binding */ getHeadX), +/* harmony export */ getHeadY: () => (/* binding */ getHeadY), +/* harmony export */ getSnakeLength: () => (/* binding */ getSnakeLength), +/* harmony export */ nextSnake: () => (/* binding */ nextSnake), +/* harmony export */ snakeEquals: () => (/* binding */ snakeEquals), +/* harmony export */ snakeToCells: () => (/* binding */ snakeToCells), +/* harmony export */ snakeWillSelfCollide: () => (/* binding */ snakeWillSelfCollide) +/* harmony export */ }); +const getHeadX = (snake) => snake[0] - 2; +const getHeadY = (snake) => snake[1] - 2; +const getSnakeLength = (snake) => snake.length / 2; +const copySnake = (snake) => snake.slice(); +const snakeEquals = (a, b) => { + for (let i = 0; i < a.length; i++) + if (a[i] !== b[i]) + return false; + return true; +}; +/** + * return a copy of the next snake, considering that dx, dy is the direction + */ +const nextSnake = (snake, dx, dy) => { + const copy = new Uint8Array(snake.length); + for (let i = 2; i < snake.length; i++) + copy[i] = snake[i - 2]; + copy[0] = snake[0] + dx; + copy[1] = snake[1] + dy; + return copy; +}; +/** + * return true if the next snake will collide with itself + */ +const snakeWillSelfCollide = (snake, dx, dy) => { + const nx = snake[0] + dx; + const ny = snake[1] + dy; + for (let i = 2; i < snake.length - 2; i += 2) + if (snake[i + 0] === nx && snake[i + 1] === ny) + return true; + return false; +}; +const snakeToCells = (snake) => Array.from({ length: snake.length / 2 }, (_, i) => ({ + x: snake[i * 2 + 0] - 2, + y: snake[i * 2 + 1] - 2, +})); +const createSnakeFromCells = (points) => { + const snake = new Uint8Array(points.length * 2); + for (let i = points.length; i--;) { + snake[i * 2 + 0] = points[i].x + 2; + snake[i * 2 + 1] = points[i].y + 2; + } + return snake; +}; + + +/***/ }), + +/***/ "./demo.json": +/*!*******************!*\ + !*** ./demo.json ***! + \*******************/ +/***/ ((module) => { + +module.exports = JSON.parse('["interactive","getBestRoute","getBestTunnel","outside","getPathToPose","getPathTo","svg"]'); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ (() => { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = (module) => { +/******/ var getter = module && module.__esModule ? +/******/ () => (module['default']) : +/******/ () => (module); +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +/*!******************************!*\ + !*** ./demo.getBestRoute.ts ***! + \******************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _menu__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./menu */ "./menu.ts"); +/* harmony import */ var _canvas__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./canvas */ "./canvas.ts"); +/* harmony import */ var _snk_solver_getBestRoute__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/solver/getBestRoute */ "../solver/getBestRoute.ts"); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _sample__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./sample */ "./sample.ts"); +/* harmony import */ var _snk_solver_step__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @snk/solver/step */ "../solver/step.ts"); + + + + + + +const chain = (0,_snk_solver_getBestRoute__WEBPACK_IMPORTED_MODULE_2__.getBestRoute)(_sample__WEBPACK_IMPORTED_MODULE_4__.grid, _sample__WEBPACK_IMPORTED_MODULE_4__.snake); +// +// draw +let k = 0; +const { canvas, draw } = (0,_canvas__WEBPACK_IMPORTED_MODULE_1__.createCanvas)(_sample__WEBPACK_IMPORTED_MODULE_4__.grid); +document.body.appendChild(canvas); +const onChange = () => { + const gridN = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_3__.copyGrid)(_sample__WEBPACK_IMPORTED_MODULE_4__.grid); + const stack = []; + for (let i = 0; i <= k; i++) + (0,_snk_solver_step__WEBPACK_IMPORTED_MODULE_5__.step)(gridN, stack, chain[i]); + draw(gridN, chain[k], stack); +}; +onChange(); +const input = document.createElement("input"); +input.type = "range"; +input.value = 0; +input.step = 1; +input.min = 0; +input.max = chain.length - 1; +input.style.width = "90%"; +input.addEventListener("input", () => { + k = +input.value; + onChange(); +}); +document.body.append(input); +window.addEventListener("click", (e) => { + if (e.target === document.body || e.target === document.body.parentElement) + input.focus(); +}); + +})(); + +/******/ })() +; \ No newline at end of file diff --git a/d0e6b597987beddaf192.js b/d0e6b597987beddaf192.js new file mode 100644 index 000000000..fac4ecf06 --- /dev/null +++ b/d0e6b597987beddaf192.js @@ -0,0 +1,3519 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "../../node_modules/dat.gui/build/dat.gui.module.js": +/*!**********************************************************!*\ + !*** ../../node_modules/dat.gui/build/dat.gui.module.js ***! + \**********************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ GUI: () => (/* binding */ GUI$1), +/* harmony export */ color: () => (/* binding */ color), +/* harmony export */ controllers: () => (/* binding */ controllers), +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), +/* harmony export */ dom: () => (/* binding */ dom$1), +/* harmony export */ gui: () => (/* binding */ gui) +/* harmony export */ }); +/** + * dat-gui JavaScript Controller Library + * https://github.com/dataarts/dat.gui + * + * Copyright 2011 Data Arts Team, Google Creative Lab + * + * 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 + */ + +function ___$insertStyle(css) { + if (!css) { + return; + } + if (typeof window === 'undefined') { + return; + } + + var style = document.createElement('style'); + + style.setAttribute('type', 'text/css'); + style.innerHTML = css; + document.head.appendChild(style); + + return css; +} + +function colorToString (color, forceCSSHex) { + var colorFormat = color.__state.conversionName.toString(); + var r = Math.round(color.r); + var g = Math.round(color.g); + var b = Math.round(color.b); + var a = color.a; + var h = Math.round(color.h); + var s = color.s.toFixed(1); + var v = color.v.toFixed(1); + if (forceCSSHex || colorFormat === 'THREE_CHAR_HEX' || colorFormat === 'SIX_CHAR_HEX') { + var str = color.hex.toString(16); + while (str.length < 6) { + str = '0' + str; + } + return '#' + str; + } else if (colorFormat === 'CSS_RGB') { + return 'rgb(' + r + ',' + g + ',' + b + ')'; + } else if (colorFormat === 'CSS_RGBA') { + return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; + } else if (colorFormat === 'HEX') { + return '0x' + color.hex.toString(16); + } else if (colorFormat === 'RGB_ARRAY') { + return '[' + r + ',' + g + ',' + b + ']'; + } else if (colorFormat === 'RGBA_ARRAY') { + return '[' + r + ',' + g + ',' + b + ',' + a + ']'; + } else if (colorFormat === 'RGB_OBJ') { + return '{r:' + r + ',g:' + g + ',b:' + b + '}'; + } else if (colorFormat === 'RGBA_OBJ') { + return '{r:' + r + ',g:' + g + ',b:' + b + ',a:' + a + '}'; + } else if (colorFormat === 'HSV_OBJ') { + return '{h:' + h + ',s:' + s + ',v:' + v + '}'; + } else if (colorFormat === 'HSVA_OBJ') { + return '{h:' + h + ',s:' + s + ',v:' + v + ',a:' + a + '}'; + } + return 'unknown format'; +} + +var ARR_EACH = Array.prototype.forEach; +var ARR_SLICE = Array.prototype.slice; +var Common = { + BREAK: {}, + extend: function extend(target) { + this.each(ARR_SLICE.call(arguments, 1), function (obj) { + var keys = this.isObject(obj) ? Object.keys(obj) : []; + keys.forEach(function (key) { + if (!this.isUndefined(obj[key])) { + target[key] = obj[key]; + } + }.bind(this)); + }, this); + return target; + }, + defaults: function defaults(target) { + this.each(ARR_SLICE.call(arguments, 1), function (obj) { + var keys = this.isObject(obj) ? Object.keys(obj) : []; + keys.forEach(function (key) { + if (this.isUndefined(target[key])) { + target[key] = obj[key]; + } + }.bind(this)); + }, this); + return target; + }, + compose: function compose() { + var toCall = ARR_SLICE.call(arguments); + return function () { + var args = ARR_SLICE.call(arguments); + for (var i = toCall.length - 1; i >= 0; i--) { + args = [toCall[i].apply(this, args)]; + } + return args[0]; + }; + }, + each: function each(obj, itr, scope) { + if (!obj) { + return; + } + if (ARR_EACH && obj.forEach && obj.forEach === ARR_EACH) { + obj.forEach(itr, scope); + } else if (obj.length === obj.length + 0) { + var key = void 0; + var l = void 0; + for (key = 0, l = obj.length; key < l; key++) { + if (key in obj && itr.call(scope, obj[key], key) === this.BREAK) { + return; + } + } + } else { + for (var _key in obj) { + if (itr.call(scope, obj[_key], _key) === this.BREAK) { + return; + } + } + } + }, + defer: function defer(fnc) { + setTimeout(fnc, 0); + }, + debounce: function debounce(func, threshold, callImmediately) { + var timeout = void 0; + return function () { + var obj = this; + var args = arguments; + function delayed() { + timeout = null; + if (!callImmediately) func.apply(obj, args); + } + var callNow = callImmediately || !timeout; + clearTimeout(timeout); + timeout = setTimeout(delayed, threshold); + if (callNow) { + func.apply(obj, args); + } + }; + }, + toArray: function toArray(obj) { + if (obj.toArray) return obj.toArray(); + return ARR_SLICE.call(obj); + }, + isUndefined: function isUndefined(obj) { + return obj === undefined; + }, + isNull: function isNull(obj) { + return obj === null; + }, + isNaN: function (_isNaN) { + function isNaN(_x) { + return _isNaN.apply(this, arguments); + } + isNaN.toString = function () { + return _isNaN.toString(); + }; + return isNaN; + }(function (obj) { + return isNaN(obj); + }), + isArray: Array.isArray || function (obj) { + return obj.constructor === Array; + }, + isObject: function isObject(obj) { + return obj === Object(obj); + }, + isNumber: function isNumber(obj) { + return obj === obj + 0; + }, + isString: function isString(obj) { + return obj === obj + ''; + }, + isBoolean: function isBoolean(obj) { + return obj === false || obj === true; + }, + isFunction: function isFunction(obj) { + return obj instanceof Function; + } +}; + +var INTERPRETATIONS = [ +{ + litmus: Common.isString, + conversions: { + THREE_CHAR_HEX: { + read: function read(original) { + var test = original.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i); + if (test === null) { + return false; + } + return { + space: 'HEX', + hex: parseInt('0x' + test[1].toString() + test[1].toString() + test[2].toString() + test[2].toString() + test[3].toString() + test[3].toString(), 0) + }; + }, + write: colorToString + }, + SIX_CHAR_HEX: { + read: function read(original) { + var test = original.match(/^#([A-F0-9]{6})$/i); + if (test === null) { + return false; + } + return { + space: 'HEX', + hex: parseInt('0x' + test[1].toString(), 0) + }; + }, + write: colorToString + }, + CSS_RGB: { + read: function read(original) { + var test = original.match(/^rgb\(\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*\)/); + if (test === null) { + return false; + } + return { + space: 'RGB', + r: parseFloat(test[1]), + g: parseFloat(test[2]), + b: parseFloat(test[3]) + }; + }, + write: colorToString + }, + CSS_RGBA: { + read: function read(original) { + var test = original.match(/^rgba\(\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*,\s*(\S+)\s*\)/); + if (test === null) { + return false; + } + return { + space: 'RGB', + r: parseFloat(test[1]), + g: parseFloat(test[2]), + b: parseFloat(test[3]), + a: parseFloat(test[4]) + }; + }, + write: colorToString + } + } +}, +{ + litmus: Common.isNumber, + conversions: { + HEX: { + read: function read(original) { + return { + space: 'HEX', + hex: original, + conversionName: 'HEX' + }; + }, + write: function write(color) { + return color.hex; + } + } + } +}, +{ + litmus: Common.isArray, + conversions: { + RGB_ARRAY: { + read: function read(original) { + if (original.length !== 3) { + return false; + } + return { + space: 'RGB', + r: original[0], + g: original[1], + b: original[2] + }; + }, + write: function write(color) { + return [color.r, color.g, color.b]; + } + }, + RGBA_ARRAY: { + read: function read(original) { + if (original.length !== 4) return false; + return { + space: 'RGB', + r: original[0], + g: original[1], + b: original[2], + a: original[3] + }; + }, + write: function write(color) { + return [color.r, color.g, color.b, color.a]; + } + } + } +}, +{ + litmus: Common.isObject, + conversions: { + RGBA_OBJ: { + read: function read(original) { + if (Common.isNumber(original.r) && Common.isNumber(original.g) && Common.isNumber(original.b) && Common.isNumber(original.a)) { + return { + space: 'RGB', + r: original.r, + g: original.g, + b: original.b, + a: original.a + }; + } + return false; + }, + write: function write(color) { + return { + r: color.r, + g: color.g, + b: color.b, + a: color.a + }; + } + }, + RGB_OBJ: { + read: function read(original) { + if (Common.isNumber(original.r) && Common.isNumber(original.g) && Common.isNumber(original.b)) { + return { + space: 'RGB', + r: original.r, + g: original.g, + b: original.b + }; + } + return false; + }, + write: function write(color) { + return { + r: color.r, + g: color.g, + b: color.b + }; + } + }, + HSVA_OBJ: { + read: function read(original) { + if (Common.isNumber(original.h) && Common.isNumber(original.s) && Common.isNumber(original.v) && Common.isNumber(original.a)) { + return { + space: 'HSV', + h: original.h, + s: original.s, + v: original.v, + a: original.a + }; + } + return false; + }, + write: function write(color) { + return { + h: color.h, + s: color.s, + v: color.v, + a: color.a + }; + } + }, + HSV_OBJ: { + read: function read(original) { + if (Common.isNumber(original.h) && Common.isNumber(original.s) && Common.isNumber(original.v)) { + return { + space: 'HSV', + h: original.h, + s: original.s, + v: original.v + }; + } + return false; + }, + write: function write(color) { + return { + h: color.h, + s: color.s, + v: color.v + }; + } + } + } +}]; +var result = void 0; +var toReturn = void 0; +var interpret = function interpret() { + toReturn = false; + var original = arguments.length > 1 ? Common.toArray(arguments) : arguments[0]; + Common.each(INTERPRETATIONS, function (family) { + if (family.litmus(original)) { + Common.each(family.conversions, function (conversion, conversionName) { + result = conversion.read(original); + if (toReturn === false && result !== false) { + toReturn = result; + result.conversionName = conversionName; + result.conversion = conversion; + return Common.BREAK; + } + }); + return Common.BREAK; + } + }); + return toReturn; +}; + +var tmpComponent = void 0; +var ColorMath = { + hsv_to_rgb: function hsv_to_rgb(h, s, v) { + var hi = Math.floor(h / 60) % 6; + var f = h / 60 - Math.floor(h / 60); + var p = v * (1.0 - s); + var q = v * (1.0 - f * s); + var t = v * (1.0 - (1.0 - f) * s); + var c = [[v, t, p], [q, v, p], [p, v, t], [p, q, v], [t, p, v], [v, p, q]][hi]; + return { + r: c[0] * 255, + g: c[1] * 255, + b: c[2] * 255 + }; + }, + rgb_to_hsv: function rgb_to_hsv(r, g, b) { + var min = Math.min(r, g, b); + var max = Math.max(r, g, b); + var delta = max - min; + var h = void 0; + var s = void 0; + if (max !== 0) { + s = delta / max; + } else { + return { + h: NaN, + s: 0, + v: 0 + }; + } + if (r === max) { + h = (g - b) / delta; + } else if (g === max) { + h = 2 + (b - r) / delta; + } else { + h = 4 + (r - g) / delta; + } + h /= 6; + if (h < 0) { + h += 1; + } + return { + h: h * 360, + s: s, + v: max / 255 + }; + }, + rgb_to_hex: function rgb_to_hex(r, g, b) { + var hex = this.hex_with_component(0, 2, r); + hex = this.hex_with_component(hex, 1, g); + hex = this.hex_with_component(hex, 0, b); + return hex; + }, + component_from_hex: function component_from_hex(hex, componentIndex) { + return hex >> componentIndex * 8 & 0xFF; + }, + hex_with_component: function hex_with_component(hex, componentIndex, value) { + return value << (tmpComponent = componentIndex * 8) | hex & ~(0xFF << tmpComponent); + } +}; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; +} : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; +}; + + + + + + + + + + + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; + +var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; +}(); + + + + + + + +var get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); + + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + + if (getter === undefined) { + return undefined; + } + + return getter.call(receiver); + } +}; + +var inherits = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; +}; + + + + + + + + + + + +var possibleConstructorReturn = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && (typeof call === "object" || typeof call === "function") ? call : self; +}; + +var Color = function () { + function Color() { + classCallCheck(this, Color); + this.__state = interpret.apply(this, arguments); + if (this.__state === false) { + throw new Error('Failed to interpret color arguments'); + } + this.__state.a = this.__state.a || 1; + } + createClass(Color, [{ + key: 'toString', + value: function toString() { + return colorToString(this); + } + }, { + key: 'toHexString', + value: function toHexString() { + return colorToString(this, true); + } + }, { + key: 'toOriginal', + value: function toOriginal() { + return this.__state.conversion.write(this); + } + }]); + return Color; +}(); +function defineRGBComponent(target, component, componentHexIndex) { + Object.defineProperty(target, component, { + get: function get$$1() { + if (this.__state.space === 'RGB') { + return this.__state[component]; + } + Color.recalculateRGB(this, component, componentHexIndex); + return this.__state[component]; + }, + set: function set$$1(v) { + if (this.__state.space !== 'RGB') { + Color.recalculateRGB(this, component, componentHexIndex); + this.__state.space = 'RGB'; + } + this.__state[component] = v; + } + }); +} +function defineHSVComponent(target, component) { + Object.defineProperty(target, component, { + get: function get$$1() { + if (this.__state.space === 'HSV') { + return this.__state[component]; + } + Color.recalculateHSV(this); + return this.__state[component]; + }, + set: function set$$1(v) { + if (this.__state.space !== 'HSV') { + Color.recalculateHSV(this); + this.__state.space = 'HSV'; + } + this.__state[component] = v; + } + }); +} +Color.recalculateRGB = function (color, component, componentHexIndex) { + if (color.__state.space === 'HEX') { + color.__state[component] = ColorMath.component_from_hex(color.__state.hex, componentHexIndex); + } else if (color.__state.space === 'HSV') { + Common.extend(color.__state, ColorMath.hsv_to_rgb(color.__state.h, color.__state.s, color.__state.v)); + } else { + throw new Error('Corrupted color state'); + } +}; +Color.recalculateHSV = function (color) { + var result = ColorMath.rgb_to_hsv(color.r, color.g, color.b); + Common.extend(color.__state, { + s: result.s, + v: result.v + }); + if (!Common.isNaN(result.h)) { + color.__state.h = result.h; + } else if (Common.isUndefined(color.__state.h)) { + color.__state.h = 0; + } +}; +Color.COMPONENTS = ['r', 'g', 'b', 'h', 's', 'v', 'hex', 'a']; +defineRGBComponent(Color.prototype, 'r', 2); +defineRGBComponent(Color.prototype, 'g', 1); +defineRGBComponent(Color.prototype, 'b', 0); +defineHSVComponent(Color.prototype, 'h'); +defineHSVComponent(Color.prototype, 's'); +defineHSVComponent(Color.prototype, 'v'); +Object.defineProperty(Color.prototype, 'a', { + get: function get$$1() { + return this.__state.a; + }, + set: function set$$1(v) { + this.__state.a = v; + } +}); +Object.defineProperty(Color.prototype, 'hex', { + get: function get$$1() { + if (this.__state.space !== 'HEX') { + this.__state.hex = ColorMath.rgb_to_hex(this.r, this.g, this.b); + this.__state.space = 'HEX'; + } + return this.__state.hex; + }, + set: function set$$1(v) { + this.__state.space = 'HEX'; + this.__state.hex = v; + } +}); + +var Controller = function () { + function Controller(object, property) { + classCallCheck(this, Controller); + this.initialValue = object[property]; + this.domElement = document.createElement('div'); + this.object = object; + this.property = property; + this.__onChange = undefined; + this.__onFinishChange = undefined; + } + createClass(Controller, [{ + key: 'onChange', + value: function onChange(fnc) { + this.__onChange = fnc; + return this; + } + }, { + key: 'onFinishChange', + value: function onFinishChange(fnc) { + this.__onFinishChange = fnc; + return this; + } + }, { + key: 'setValue', + value: function setValue(newValue) { + this.object[this.property] = newValue; + if (this.__onChange) { + this.__onChange.call(this, newValue); + } + this.updateDisplay(); + return this; + } + }, { + key: 'getValue', + value: function getValue() { + return this.object[this.property]; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + return this; + } + }, { + key: 'isModified', + value: function isModified() { + return this.initialValue !== this.getValue(); + } + }]); + return Controller; +}(); + +var EVENT_MAP = { + HTMLEvents: ['change'], + MouseEvents: ['click', 'mousemove', 'mousedown', 'mouseup', 'mouseover'], + KeyboardEvents: ['keydown'] +}; +var EVENT_MAP_INV = {}; +Common.each(EVENT_MAP, function (v, k) { + Common.each(v, function (e) { + EVENT_MAP_INV[e] = k; + }); +}); +var CSS_VALUE_PIXELS = /(\d+(\.\d+)?)px/; +function cssValueToPixels(val) { + if (val === '0' || Common.isUndefined(val)) { + return 0; + } + var match = val.match(CSS_VALUE_PIXELS); + if (!Common.isNull(match)) { + return parseFloat(match[1]); + } + return 0; +} +var dom = { + makeSelectable: function makeSelectable(elem, selectable) { + if (elem === undefined || elem.style === undefined) return; + elem.onselectstart = selectable ? function () { + return false; + } : function () {}; + elem.style.MozUserSelect = selectable ? 'auto' : 'none'; + elem.style.KhtmlUserSelect = selectable ? 'auto' : 'none'; + elem.unselectable = selectable ? 'on' : 'off'; + }, + makeFullscreen: function makeFullscreen(elem, hor, vert) { + var vertical = vert; + var horizontal = hor; + if (Common.isUndefined(horizontal)) { + horizontal = true; + } + if (Common.isUndefined(vertical)) { + vertical = true; + } + elem.style.position = 'absolute'; + if (horizontal) { + elem.style.left = 0; + elem.style.right = 0; + } + if (vertical) { + elem.style.top = 0; + elem.style.bottom = 0; + } + }, + fakeEvent: function fakeEvent(elem, eventType, pars, aux) { + var params = pars || {}; + var className = EVENT_MAP_INV[eventType]; + if (!className) { + throw new Error('Event type ' + eventType + ' not supported.'); + } + var evt = document.createEvent(className); + switch (className) { + case 'MouseEvents': + { + var clientX = params.x || params.clientX || 0; + var clientY = params.y || params.clientY || 0; + evt.initMouseEvent(eventType, params.bubbles || false, params.cancelable || true, window, params.clickCount || 1, 0, + 0, + clientX, + clientY, + false, false, false, false, 0, null); + break; + } + case 'KeyboardEvents': + { + var init = evt.initKeyboardEvent || evt.initKeyEvent; + Common.defaults(params, { + cancelable: true, + ctrlKey: false, + altKey: false, + shiftKey: false, + metaKey: false, + keyCode: undefined, + charCode: undefined + }); + init(eventType, params.bubbles || false, params.cancelable, window, params.ctrlKey, params.altKey, params.shiftKey, params.metaKey, params.keyCode, params.charCode); + break; + } + default: + { + evt.initEvent(eventType, params.bubbles || false, params.cancelable || true); + break; + } + } + Common.defaults(evt, aux); + elem.dispatchEvent(evt); + }, + bind: function bind(elem, event, func, newBool) { + var bool = newBool || false; + if (elem.addEventListener) { + elem.addEventListener(event, func, bool); + } else if (elem.attachEvent) { + elem.attachEvent('on' + event, func); + } + return dom; + }, + unbind: function unbind(elem, event, func, newBool) { + var bool = newBool || false; + if (elem.removeEventListener) { + elem.removeEventListener(event, func, bool); + } else if (elem.detachEvent) { + elem.detachEvent('on' + event, func); + } + return dom; + }, + addClass: function addClass(elem, className) { + if (elem.className === undefined) { + elem.className = className; + } else if (elem.className !== className) { + var classes = elem.className.split(/ +/); + if (classes.indexOf(className) === -1) { + classes.push(className); + elem.className = classes.join(' ').replace(/^\s+/, '').replace(/\s+$/, ''); + } + } + return dom; + }, + removeClass: function removeClass(elem, className) { + if (className) { + if (elem.className === className) { + elem.removeAttribute('class'); + } else { + var classes = elem.className.split(/ +/); + var index = classes.indexOf(className); + if (index !== -1) { + classes.splice(index, 1); + elem.className = classes.join(' '); + } + } + } else { + elem.className = undefined; + } + return dom; + }, + hasClass: function hasClass(elem, className) { + return new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)').test(elem.className) || false; + }, + getWidth: function getWidth(elem) { + var style = getComputedStyle(elem); + return cssValueToPixels(style['border-left-width']) + cssValueToPixels(style['border-right-width']) + cssValueToPixels(style['padding-left']) + cssValueToPixels(style['padding-right']) + cssValueToPixels(style.width); + }, + getHeight: function getHeight(elem) { + var style = getComputedStyle(elem); + return cssValueToPixels(style['border-top-width']) + cssValueToPixels(style['border-bottom-width']) + cssValueToPixels(style['padding-top']) + cssValueToPixels(style['padding-bottom']) + cssValueToPixels(style.height); + }, + getOffset: function getOffset(el) { + var elem = el; + var offset = { left: 0, top: 0 }; + if (elem.offsetParent) { + do { + offset.left += elem.offsetLeft; + offset.top += elem.offsetTop; + elem = elem.offsetParent; + } while (elem); + } + return offset; + }, + isActive: function isActive(elem) { + return elem === document.activeElement && (elem.type || elem.href); + } +}; + +var BooleanController = function (_Controller) { + inherits(BooleanController, _Controller); + function BooleanController(object, property) { + classCallCheck(this, BooleanController); + var _this2 = possibleConstructorReturn(this, (BooleanController.__proto__ || Object.getPrototypeOf(BooleanController)).call(this, object, property)); + var _this = _this2; + _this2.__prev = _this2.getValue(); + _this2.__checkbox = document.createElement('input'); + _this2.__checkbox.setAttribute('type', 'checkbox'); + function onChange() { + _this.setValue(!_this.__prev); + } + dom.bind(_this2.__checkbox, 'change', onChange, false); + _this2.domElement.appendChild(_this2.__checkbox); + _this2.updateDisplay(); + return _this2; + } + createClass(BooleanController, [{ + key: 'setValue', + value: function setValue(v) { + var toReturn = get(BooleanController.prototype.__proto__ || Object.getPrototypeOf(BooleanController.prototype), 'setValue', this).call(this, v); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + this.__prev = this.getValue(); + return toReturn; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + if (this.getValue() === true) { + this.__checkbox.setAttribute('checked', 'checked'); + this.__checkbox.checked = true; + this.__prev = true; + } else { + this.__checkbox.checked = false; + this.__prev = false; + } + return get(BooleanController.prototype.__proto__ || Object.getPrototypeOf(BooleanController.prototype), 'updateDisplay', this).call(this); + } + }]); + return BooleanController; +}(Controller); + +var OptionController = function (_Controller) { + inherits(OptionController, _Controller); + function OptionController(object, property, opts) { + classCallCheck(this, OptionController); + var _this2 = possibleConstructorReturn(this, (OptionController.__proto__ || Object.getPrototypeOf(OptionController)).call(this, object, property)); + var options = opts; + var _this = _this2; + _this2.__select = document.createElement('select'); + if (Common.isArray(options)) { + var map = {}; + Common.each(options, function (element) { + map[element] = element; + }); + options = map; + } + Common.each(options, function (value, key) { + var opt = document.createElement('option'); + opt.innerHTML = key; + opt.setAttribute('value', value); + _this.__select.appendChild(opt); + }); + _this2.updateDisplay(); + dom.bind(_this2.__select, 'change', function () { + var desiredValue = this.options[this.selectedIndex].value; + _this.setValue(desiredValue); + }); + _this2.domElement.appendChild(_this2.__select); + return _this2; + } + createClass(OptionController, [{ + key: 'setValue', + value: function setValue(v) { + var toReturn = get(OptionController.prototype.__proto__ || Object.getPrototypeOf(OptionController.prototype), 'setValue', this).call(this, v); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + return toReturn; + } + }, { + key: 'updateDisplay', + value: function updateDisplay() { + if (dom.isActive(this.__select)) return this; + this.__select.value = this.getValue(); + return get(OptionController.prototype.__proto__ || Object.getPrototypeOf(OptionController.prototype), 'updateDisplay', this).call(this); + } + }]); + return OptionController; +}(Controller); + +var StringController = function (_Controller) { + inherits(StringController, _Controller); + function StringController(object, property) { + classCallCheck(this, StringController); + var _this2 = possibleConstructorReturn(this, (StringController.__proto__ || Object.getPrototypeOf(StringController)).call(this, object, property)); + var _this = _this2; + function onChange() { + _this.setValue(_this.__input.value); + } + function onBlur() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + _this2.__input = document.createElement('input'); + _this2.__input.setAttribute('type', 'text'); + dom.bind(_this2.__input, 'keyup', onChange); + dom.bind(_this2.__input, 'change', onChange); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + this.blur(); + } + }); + _this2.updateDisplay(); + _this2.domElement.appendChild(_this2.__input); + return _this2; + } + createClass(StringController, [{ + key: 'updateDisplay', + value: function updateDisplay() { + if (!dom.isActive(this.__input)) { + this.__input.value = this.getValue(); + } + return get(StringController.prototype.__proto__ || Object.getPrototypeOf(StringController.prototype), 'updateDisplay', this).call(this); + } + }]); + return StringController; +}(Controller); + +function numDecimals(x) { + var _x = x.toString(); + if (_x.indexOf('.') > -1) { + return _x.length - _x.indexOf('.') - 1; + } + return 0; +} +var NumberController = function (_Controller) { + inherits(NumberController, _Controller); + function NumberController(object, property, params) { + classCallCheck(this, NumberController); + var _this = possibleConstructorReturn(this, (NumberController.__proto__ || Object.getPrototypeOf(NumberController)).call(this, object, property)); + var _params = params || {}; + _this.__min = _params.min; + _this.__max = _params.max; + _this.__step = _params.step; + if (Common.isUndefined(_this.__step)) { + if (_this.initialValue === 0) { + _this.__impliedStep = 1; + } else { + _this.__impliedStep = Math.pow(10, Math.floor(Math.log(Math.abs(_this.initialValue)) / Math.LN10)) / 10; + } + } else { + _this.__impliedStep = _this.__step; + } + _this.__precision = numDecimals(_this.__impliedStep); + return _this; + } + createClass(NumberController, [{ + key: 'setValue', + value: function setValue(v) { + var _v = v; + if (this.__min !== undefined && _v < this.__min) { + _v = this.__min; + } else if (this.__max !== undefined && _v > this.__max) { + _v = this.__max; + } + if (this.__step !== undefined && _v % this.__step !== 0) { + _v = Math.round(_v / this.__step) * this.__step; + } + return get(NumberController.prototype.__proto__ || Object.getPrototypeOf(NumberController.prototype), 'setValue', this).call(this, _v); + } + }, { + key: 'min', + value: function min(minValue) { + this.__min = minValue; + return this; + } + }, { + key: 'max', + value: function max(maxValue) { + this.__max = maxValue; + return this; + } + }, { + key: 'step', + value: function step(stepValue) { + this.__step = stepValue; + this.__impliedStep = stepValue; + this.__precision = numDecimals(stepValue); + return this; + } + }]); + return NumberController; +}(Controller); + +function roundToDecimal(value, decimals) { + var tenTo = Math.pow(10, decimals); + return Math.round(value * tenTo) / tenTo; +} +var NumberControllerBox = function (_NumberController) { + inherits(NumberControllerBox, _NumberController); + function NumberControllerBox(object, property, params) { + classCallCheck(this, NumberControllerBox); + var _this2 = possibleConstructorReturn(this, (NumberControllerBox.__proto__ || Object.getPrototypeOf(NumberControllerBox)).call(this, object, property, params)); + _this2.__truncationSuspended = false; + var _this = _this2; + var prevY = void 0; + function onChange() { + var attempted = parseFloat(_this.__input.value); + if (!Common.isNaN(attempted)) { + _this.setValue(attempted); + } + } + function onFinish() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + function onBlur() { + onFinish(); + } + function onMouseDrag(e) { + var diff = prevY - e.clientY; + _this.setValue(_this.getValue() + diff * _this.__impliedStep); + prevY = e.clientY; + } + function onMouseUp() { + dom.unbind(window, 'mousemove', onMouseDrag); + dom.unbind(window, 'mouseup', onMouseUp); + onFinish(); + } + function onMouseDown(e) { + dom.bind(window, 'mousemove', onMouseDrag); + dom.bind(window, 'mouseup', onMouseUp); + prevY = e.clientY; + } + _this2.__input = document.createElement('input'); + _this2.__input.setAttribute('type', 'text'); + dom.bind(_this2.__input, 'change', onChange); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__input, 'mousedown', onMouseDown); + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + _this.__truncationSuspended = true; + this.blur(); + _this.__truncationSuspended = false; + onFinish(); + } + }); + _this2.updateDisplay(); + _this2.domElement.appendChild(_this2.__input); + return _this2; + } + createClass(NumberControllerBox, [{ + key: 'updateDisplay', + value: function updateDisplay() { + this.__input.value = this.__truncationSuspended ? this.getValue() : roundToDecimal(this.getValue(), this.__precision); + return get(NumberControllerBox.prototype.__proto__ || Object.getPrototypeOf(NumberControllerBox.prototype), 'updateDisplay', this).call(this); + } + }]); + return NumberControllerBox; +}(NumberController); + +function map(v, i1, i2, o1, o2) { + return o1 + (o2 - o1) * ((v - i1) / (i2 - i1)); +} +var NumberControllerSlider = function (_NumberController) { + inherits(NumberControllerSlider, _NumberController); + function NumberControllerSlider(object, property, min, max, step) { + classCallCheck(this, NumberControllerSlider); + var _this2 = possibleConstructorReturn(this, (NumberControllerSlider.__proto__ || Object.getPrototypeOf(NumberControllerSlider)).call(this, object, property, { min: min, max: max, step: step })); + var _this = _this2; + _this2.__background = document.createElement('div'); + _this2.__foreground = document.createElement('div'); + dom.bind(_this2.__background, 'mousedown', onMouseDown); + dom.bind(_this2.__background, 'touchstart', onTouchStart); + dom.addClass(_this2.__background, 'slider'); + dom.addClass(_this2.__foreground, 'slider-fg'); + function onMouseDown(e) { + document.activeElement.blur(); + dom.bind(window, 'mousemove', onMouseDrag); + dom.bind(window, 'mouseup', onMouseUp); + onMouseDrag(e); + } + function onMouseDrag(e) { + e.preventDefault(); + var bgRect = _this.__background.getBoundingClientRect(); + _this.setValue(map(e.clientX, bgRect.left, bgRect.right, _this.__min, _this.__max)); + return false; + } + function onMouseUp() { + dom.unbind(window, 'mousemove', onMouseDrag); + dom.unbind(window, 'mouseup', onMouseUp); + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + function onTouchStart(e) { + if (e.touches.length !== 1) { + return; + } + dom.bind(window, 'touchmove', onTouchMove); + dom.bind(window, 'touchend', onTouchEnd); + onTouchMove(e); + } + function onTouchMove(e) { + var clientX = e.touches[0].clientX; + var bgRect = _this.__background.getBoundingClientRect(); + _this.setValue(map(clientX, bgRect.left, bgRect.right, _this.__min, _this.__max)); + } + function onTouchEnd() { + dom.unbind(window, 'touchmove', onTouchMove); + dom.unbind(window, 'touchend', onTouchEnd); + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.getValue()); + } + } + _this2.updateDisplay(); + _this2.__background.appendChild(_this2.__foreground); + _this2.domElement.appendChild(_this2.__background); + return _this2; + } + createClass(NumberControllerSlider, [{ + key: 'updateDisplay', + value: function updateDisplay() { + var pct = (this.getValue() - this.__min) / (this.__max - this.__min); + this.__foreground.style.width = pct * 100 + '%'; + return get(NumberControllerSlider.prototype.__proto__ || Object.getPrototypeOf(NumberControllerSlider.prototype), 'updateDisplay', this).call(this); + } + }]); + return NumberControllerSlider; +}(NumberController); + +var FunctionController = function (_Controller) { + inherits(FunctionController, _Controller); + function FunctionController(object, property, text) { + classCallCheck(this, FunctionController); + var _this2 = possibleConstructorReturn(this, (FunctionController.__proto__ || Object.getPrototypeOf(FunctionController)).call(this, object, property)); + var _this = _this2; + _this2.__button = document.createElement('div'); + _this2.__button.innerHTML = text === undefined ? 'Fire' : text; + dom.bind(_this2.__button, 'click', function (e) { + e.preventDefault(); + _this.fire(); + return false; + }); + dom.addClass(_this2.__button, 'button'); + _this2.domElement.appendChild(_this2.__button); + return _this2; + } + createClass(FunctionController, [{ + key: 'fire', + value: function fire() { + if (this.__onChange) { + this.__onChange.call(this); + } + this.getValue().call(this.object); + if (this.__onFinishChange) { + this.__onFinishChange.call(this, this.getValue()); + } + } + }]); + return FunctionController; +}(Controller); + +var ColorController = function (_Controller) { + inherits(ColorController, _Controller); + function ColorController(object, property) { + classCallCheck(this, ColorController); + var _this2 = possibleConstructorReturn(this, (ColorController.__proto__ || Object.getPrototypeOf(ColorController)).call(this, object, property)); + _this2.__color = new Color(_this2.getValue()); + _this2.__temp = new Color(0); + var _this = _this2; + _this2.domElement = document.createElement('div'); + dom.makeSelectable(_this2.domElement, false); + _this2.__selector = document.createElement('div'); + _this2.__selector.className = 'selector'; + _this2.__saturation_field = document.createElement('div'); + _this2.__saturation_field.className = 'saturation-field'; + _this2.__field_knob = document.createElement('div'); + _this2.__field_knob.className = 'field-knob'; + _this2.__field_knob_border = '2px solid '; + _this2.__hue_knob = document.createElement('div'); + _this2.__hue_knob.className = 'hue-knob'; + _this2.__hue_field = document.createElement('div'); + _this2.__hue_field.className = 'hue-field'; + _this2.__input = document.createElement('input'); + _this2.__input.type = 'text'; + _this2.__input_textShadow = '0 1px 1px '; + dom.bind(_this2.__input, 'keydown', function (e) { + if (e.keyCode === 13) { + onBlur.call(this); + } + }); + dom.bind(_this2.__input, 'blur', onBlur); + dom.bind(_this2.__selector, 'mousedown', function () { + dom.addClass(this, 'drag').bind(window, 'mouseup', function () { + dom.removeClass(_this.__selector, 'drag'); + }); + }); + dom.bind(_this2.__selector, 'touchstart', function () { + dom.addClass(this, 'drag').bind(window, 'touchend', function () { + dom.removeClass(_this.__selector, 'drag'); + }); + }); + var valueField = document.createElement('div'); + Common.extend(_this2.__selector.style, { + width: '122px', + height: '102px', + padding: '3px', + backgroundColor: '#222', + boxShadow: '0px 1px 3px rgba(0,0,0,0.3)' + }); + Common.extend(_this2.__field_knob.style, { + position: 'absolute', + width: '12px', + height: '12px', + border: _this2.__field_knob_border + (_this2.__color.v < 0.5 ? '#fff' : '#000'), + boxShadow: '0px 1px 3px rgba(0,0,0,0.5)', + borderRadius: '12px', + zIndex: 1 + }); + Common.extend(_this2.__hue_knob.style, { + position: 'absolute', + width: '15px', + height: '2px', + borderRight: '4px solid #fff', + zIndex: 1 + }); + Common.extend(_this2.__saturation_field.style, { + width: '100px', + height: '100px', + border: '1px solid #555', + marginRight: '3px', + display: 'inline-block', + cursor: 'pointer' + }); + Common.extend(valueField.style, { + width: '100%', + height: '100%', + background: 'none' + }); + linearGradient(valueField, 'top', 'rgba(0,0,0,0)', '#000'); + Common.extend(_this2.__hue_field.style, { + width: '15px', + height: '100px', + border: '1px solid #555', + cursor: 'ns-resize', + position: 'absolute', + top: '3px', + right: '3px' + }); + hueGradient(_this2.__hue_field); + Common.extend(_this2.__input.style, { + outline: 'none', + textAlign: 'center', + color: '#fff', + border: 0, + fontWeight: 'bold', + textShadow: _this2.__input_textShadow + 'rgba(0,0,0,0.7)' + }); + dom.bind(_this2.__saturation_field, 'mousedown', fieldDown); + dom.bind(_this2.__saturation_field, 'touchstart', fieldDown); + dom.bind(_this2.__field_knob, 'mousedown', fieldDown); + dom.bind(_this2.__field_knob, 'touchstart', fieldDown); + dom.bind(_this2.__hue_field, 'mousedown', fieldDownH); + dom.bind(_this2.__hue_field, 'touchstart', fieldDownH); + function fieldDown(e) { + setSV(e); + dom.bind(window, 'mousemove', setSV); + dom.bind(window, 'touchmove', setSV); + dom.bind(window, 'mouseup', fieldUpSV); + dom.bind(window, 'touchend', fieldUpSV); + } + function fieldDownH(e) { + setH(e); + dom.bind(window, 'mousemove', setH); + dom.bind(window, 'touchmove', setH); + dom.bind(window, 'mouseup', fieldUpH); + dom.bind(window, 'touchend', fieldUpH); + } + function fieldUpSV() { + dom.unbind(window, 'mousemove', setSV); + dom.unbind(window, 'touchmove', setSV); + dom.unbind(window, 'mouseup', fieldUpSV); + dom.unbind(window, 'touchend', fieldUpSV); + onFinish(); + } + function fieldUpH() { + dom.unbind(window, 'mousemove', setH); + dom.unbind(window, 'touchmove', setH); + dom.unbind(window, 'mouseup', fieldUpH); + dom.unbind(window, 'touchend', fieldUpH); + onFinish(); + } + function onBlur() { + var i = interpret(this.value); + if (i !== false) { + _this.__color.__state = i; + _this.setValue(_this.__color.toOriginal()); + } else { + this.value = _this.__color.toString(); + } + } + function onFinish() { + if (_this.__onFinishChange) { + _this.__onFinishChange.call(_this, _this.__color.toOriginal()); + } + } + _this2.__saturation_field.appendChild(valueField); + _this2.__selector.appendChild(_this2.__field_knob); + _this2.__selector.appendChild(_this2.__saturation_field); + _this2.__selector.appendChild(_this2.__hue_field); + _this2.__hue_field.appendChild(_this2.__hue_knob); + _this2.domElement.appendChild(_this2.__input); + _this2.domElement.appendChild(_this2.__selector); + _this2.updateDisplay(); + function setSV(e) { + if (e.type.indexOf('touch') === -1) { + e.preventDefault(); + } + var fieldRect = _this.__saturation_field.getBoundingClientRect(); + var _ref = e.touches && e.touches[0] || e, + clientX = _ref.clientX, + clientY = _ref.clientY; + var s = (clientX - fieldRect.left) / (fieldRect.right - fieldRect.left); + var v = 1 - (clientY - fieldRect.top) / (fieldRect.bottom - fieldRect.top); + if (v > 1) { + v = 1; + } else if (v < 0) { + v = 0; + } + if (s > 1) { + s = 1; + } else if (s < 0) { + s = 0; + } + _this.__color.v = v; + _this.__color.s = s; + _this.setValue(_this.__color.toOriginal()); + return false; + } + function setH(e) { + if (e.type.indexOf('touch') === -1) { + e.preventDefault(); + } + var fieldRect = _this.__hue_field.getBoundingClientRect(); + var _ref2 = e.touches && e.touches[0] || e, + clientY = _ref2.clientY; + var h = 1 - (clientY - fieldRect.top) / (fieldRect.bottom - fieldRect.top); + if (h > 1) { + h = 1; + } else if (h < 0) { + h = 0; + } + _this.__color.h = h * 360; + _this.setValue(_this.__color.toOriginal()); + return false; + } + return _this2; + } + createClass(ColorController, [{ + key: 'updateDisplay', + value: function updateDisplay() { + var i = interpret(this.getValue()); + if (i !== false) { + var mismatch = false; + Common.each(Color.COMPONENTS, function (component) { + if (!Common.isUndefined(i[component]) && !Common.isUndefined(this.__color.__state[component]) && i[component] !== this.__color.__state[component]) { + mismatch = true; + return {}; + } + }, this); + if (mismatch) { + Common.extend(this.__color.__state, i); + } + } + Common.extend(this.__temp.__state, this.__color.__state); + this.__temp.a = 1; + var flip = this.__color.v < 0.5 || this.__color.s > 0.5 ? 255 : 0; + var _flip = 255 - flip; + Common.extend(this.__field_knob.style, { + marginLeft: 100 * this.__color.s - 7 + 'px', + marginTop: 100 * (1 - this.__color.v) - 7 + 'px', + backgroundColor: this.__temp.toHexString(), + border: this.__field_knob_border + 'rgb(' + flip + ',' + flip + ',' + flip + ')' + }); + this.__hue_knob.style.marginTop = (1 - this.__color.h / 360) * 100 + 'px'; + this.__temp.s = 1; + this.__temp.v = 1; + linearGradient(this.__saturation_field, 'left', '#fff', this.__temp.toHexString()); + this.__input.value = this.__color.toString(); + Common.extend(this.__input.style, { + backgroundColor: this.__color.toHexString(), + color: 'rgb(' + flip + ',' + flip + ',' + flip + ')', + textShadow: this.__input_textShadow + 'rgba(' + _flip + ',' + _flip + ',' + _flip + ',.7)' + }); + } + }]); + return ColorController; +}(Controller); +var vendors = ['-moz-', '-o-', '-webkit-', '-ms-', '']; +function linearGradient(elem, x, a, b) { + elem.style.background = ''; + Common.each(vendors, function (vendor) { + elem.style.cssText += 'background: ' + vendor + 'linear-gradient(' + x + ', ' + a + ' 0%, ' + b + ' 100%); '; + }); +} +function hueGradient(elem) { + elem.style.background = ''; + elem.style.cssText += 'background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);'; + elem.style.cssText += 'background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; + elem.style.cssText += 'background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);'; +} + +var css = { + load: function load(url, indoc) { + var doc = indoc || document; + var link = doc.createElement('link'); + link.type = 'text/css'; + link.rel = 'stylesheet'; + link.href = url; + doc.getElementsByTagName('head')[0].appendChild(link); + }, + inject: function inject(cssContent, indoc) { + var doc = indoc || document; + var injected = document.createElement('style'); + injected.type = 'text/css'; + injected.innerHTML = cssContent; + var head = doc.getElementsByTagName('head')[0]; + try { + head.appendChild(injected); + } catch (e) { + } + } +}; + +var saveDialogContents = "
\n\n Here's the new load parameter for your GUI's constructor:\n\n \n\n
\n\n Automatically save\n values to localStorage on exit.\n\n
The values saved to localStorage will\n override those passed to dat.GUI's constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n\n
\n\n
\n\n
"; + +var ControllerFactory = function ControllerFactory(object, property) { + var initialValue = object[property]; + if (Common.isArray(arguments[2]) || Common.isObject(arguments[2])) { + return new OptionController(object, property, arguments[2]); + } + if (Common.isNumber(initialValue)) { + if (Common.isNumber(arguments[2]) && Common.isNumber(arguments[3])) { + if (Common.isNumber(arguments[4])) { + return new NumberControllerSlider(object, property, arguments[2], arguments[3], arguments[4]); + } + return new NumberControllerSlider(object, property, arguments[2], arguments[3]); + } + if (Common.isNumber(arguments[4])) { + return new NumberControllerBox(object, property, { min: arguments[2], max: arguments[3], step: arguments[4] }); + } + return new NumberControllerBox(object, property, { min: arguments[2], max: arguments[3] }); + } + if (Common.isString(initialValue)) { + return new StringController(object, property); + } + if (Common.isFunction(initialValue)) { + return new FunctionController(object, property, ''); + } + if (Common.isBoolean(initialValue)) { + return new BooleanController(object, property); + } + return null; +}; + +function requestAnimationFrame(callback) { + setTimeout(callback, 1000 / 60); +} +var requestAnimationFrame$1 = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || requestAnimationFrame; + +var CenteredDiv = function () { + function CenteredDiv() { + classCallCheck(this, CenteredDiv); + this.backgroundElement = document.createElement('div'); + Common.extend(this.backgroundElement.style, { + backgroundColor: 'rgba(0,0,0,0.8)', + top: 0, + left: 0, + display: 'none', + zIndex: '1000', + opacity: 0, + WebkitTransition: 'opacity 0.2s linear', + transition: 'opacity 0.2s linear' + }); + dom.makeFullscreen(this.backgroundElement); + this.backgroundElement.style.position = 'fixed'; + this.domElement = document.createElement('div'); + Common.extend(this.domElement.style, { + position: 'fixed', + display: 'none', + zIndex: '1001', + opacity: 0, + WebkitTransition: '-webkit-transform 0.2s ease-out, opacity 0.2s linear', + transition: 'transform 0.2s ease-out, opacity 0.2s linear' + }); + document.body.appendChild(this.backgroundElement); + document.body.appendChild(this.domElement); + var _this = this; + dom.bind(this.backgroundElement, 'click', function () { + _this.hide(); + }); + } + createClass(CenteredDiv, [{ + key: 'show', + value: function show() { + var _this = this; + this.backgroundElement.style.display = 'block'; + this.domElement.style.display = 'block'; + this.domElement.style.opacity = 0; + this.domElement.style.webkitTransform = 'scale(1.1)'; + this.layout(); + Common.defer(function () { + _this.backgroundElement.style.opacity = 1; + _this.domElement.style.opacity = 1; + _this.domElement.style.webkitTransform = 'scale(1)'; + }); + } + }, { + key: 'hide', + value: function hide() { + var _this = this; + var hide = function hide() { + _this.domElement.style.display = 'none'; + _this.backgroundElement.style.display = 'none'; + dom.unbind(_this.domElement, 'webkitTransitionEnd', hide); + dom.unbind(_this.domElement, 'transitionend', hide); + dom.unbind(_this.domElement, 'oTransitionEnd', hide); + }; + dom.bind(this.domElement, 'webkitTransitionEnd', hide); + dom.bind(this.domElement, 'transitionend', hide); + dom.bind(this.domElement, 'oTransitionEnd', hide); + this.backgroundElement.style.opacity = 0; + this.domElement.style.opacity = 0; + this.domElement.style.webkitTransform = 'scale(1.1)'; + } + }, { + key: 'layout', + value: function layout() { + this.domElement.style.left = window.innerWidth / 2 - dom.getWidth(this.domElement) / 2 + 'px'; + this.domElement.style.top = window.innerHeight / 2 - dom.getHeight(this.domElement) / 2 + 'px'; + } + }]); + return CenteredDiv; +}(); + +var styleSheet = ___$insertStyle(".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity .1s linear;-o-transition:opacity .1s linear;-moz-transition:opacity .1s linear;transition:opacity .1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1 !important}.dg.main:hover .close-button,.dg.main .close-button.drag{opacity:1}.dg.main .close-button{-webkit-transition:opacity .1s linear;-o-transition:opacity .1s linear;-moz-transition:opacity .1s linear;transition:opacity .1s linear;border:0;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button.close-top{position:relative}.dg.main .close-button.close-bottom{position:absolute}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-y:visible}.dg.a.has-save>ul.close-top{margin-top:0}.dg.a.has-save>ul.close-bottom{margin-top:27px}.dg.a.has-save>ul.closed{margin-top:0}.dg.a .save-row{top:0;z-index:1002}.dg.a .save-row.close-top{position:relative}.dg.a .save-row.close-bottom{position:fixed}.dg li{-webkit-transition:height .1s ease-out;-o-transition:height .1s ease-out;-moz-transition:height .1s ease-out;transition:height .1s ease-out;-webkit-transition:overflow .1s linear;-o-transition:overflow .1s linear;-moz-transition:overflow .1s linear;transition:overflow .1s linear}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid rgba(0,0,0,0)}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li>*{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px;overflow:hidden}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .cr.function .property-name{width:100%}.dg .c{float:left;width:60%;position:relative}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:7px}.dg .c select{margin-top:5px}.dg .cr.function,.dg .cr.function .property-name,.dg .cr.function *,.dg .cr.boolean,.dg .cr.boolean *{cursor:pointer}.dg .cr.color{overflow:visible}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0px 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco, monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px 'Lucida Grande', sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px 4px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid rgba(255,255,255,0.2)}.dg .closed li.title{background-image:url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==)}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.color{border-left:3px solid}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2FA1D6}.dg .cr.number input[type=text]{color:#2FA1D6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.function:hover,.dg .cr.boolean:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2FA1D6;max-width:100%}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}\n"); + +css.inject(styleSheet); +var CSS_NAMESPACE = 'dg'; +var HIDE_KEY_CODE = 72; +var CLOSE_BUTTON_HEIGHT = 20; +var DEFAULT_DEFAULT_PRESET_NAME = 'Default'; +var SUPPORTS_LOCAL_STORAGE = function () { + try { + return !!window.localStorage; + } catch (e) { + return false; + } +}(); +var SAVE_DIALOGUE = void 0; +var autoPlaceVirgin = true; +var autoPlaceContainer = void 0; +var hide = false; +var hideableGuis = []; +var GUI = function GUI(pars) { + var _this = this; + var params = pars || {}; + this.domElement = document.createElement('div'); + this.__ul = document.createElement('ul'); + this.domElement.appendChild(this.__ul); + dom.addClass(this.domElement, CSS_NAMESPACE); + this.__folders = {}; + this.__controllers = []; + this.__rememberedObjects = []; + this.__rememberedObjectIndecesToControllers = []; + this.__listening = []; + params = Common.defaults(params, { + closeOnTop: false, + autoPlace: true, + width: GUI.DEFAULT_WIDTH + }); + params = Common.defaults(params, { + resizable: params.autoPlace, + hideable: params.autoPlace + }); + if (!Common.isUndefined(params.load)) { + if (params.preset) { + params.load.preset = params.preset; + } + } else { + params.load = { preset: DEFAULT_DEFAULT_PRESET_NAME }; + } + if (Common.isUndefined(params.parent) && params.hideable) { + hideableGuis.push(this); + } + params.resizable = Common.isUndefined(params.parent) && params.resizable; + if (params.autoPlace && Common.isUndefined(params.scrollable)) { + params.scrollable = true; + } + var useLocalStorage = SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(this, 'isLocal')) === 'true'; + var saveToLocalStorage = void 0; + var titleRow = void 0; + Object.defineProperties(this, + { + parent: { + get: function get$$1() { + return params.parent; + } + }, + scrollable: { + get: function get$$1() { + return params.scrollable; + } + }, + autoPlace: { + get: function get$$1() { + return params.autoPlace; + } + }, + closeOnTop: { + get: function get$$1() { + return params.closeOnTop; + } + }, + preset: { + get: function get$$1() { + if (_this.parent) { + return _this.getRoot().preset; + } + return params.load.preset; + }, + set: function set$$1(v) { + if (_this.parent) { + _this.getRoot().preset = v; + } else { + params.load.preset = v; + } + setPresetSelectIndex(this); + _this.revert(); + } + }, + width: { + get: function get$$1() { + return params.width; + }, + set: function set$$1(v) { + params.width = v; + setWidth(_this, v); + } + }, + name: { + get: function get$$1() { + return params.name; + }, + set: function set$$1(v) { + params.name = v; + if (titleRow) { + titleRow.innerHTML = params.name; + } + } + }, + closed: { + get: function get$$1() { + return params.closed; + }, + set: function set$$1(v) { + params.closed = v; + if (params.closed) { + dom.addClass(_this.__ul, GUI.CLASS_CLOSED); + } else { + dom.removeClass(_this.__ul, GUI.CLASS_CLOSED); + } + this.onResize(); + if (_this.__closeButton) { + _this.__closeButton.innerHTML = v ? GUI.TEXT_OPEN : GUI.TEXT_CLOSED; + } + } + }, + load: { + get: function get$$1() { + return params.load; + } + }, + useLocalStorage: { + get: function get$$1() { + return useLocalStorage; + }, + set: function set$$1(bool) { + if (SUPPORTS_LOCAL_STORAGE) { + useLocalStorage = bool; + if (bool) { + dom.bind(window, 'unload', saveToLocalStorage); + } else { + dom.unbind(window, 'unload', saveToLocalStorage); + } + localStorage.setItem(getLocalStorageHash(_this, 'isLocal'), bool); + } + } + } + }); + if (Common.isUndefined(params.parent)) { + this.closed = params.closed || false; + dom.addClass(this.domElement, GUI.CLASS_MAIN); + dom.makeSelectable(this.domElement, false); + if (SUPPORTS_LOCAL_STORAGE) { + if (useLocalStorage) { + _this.useLocalStorage = true; + var savedGui = localStorage.getItem(getLocalStorageHash(this, 'gui')); + if (savedGui) { + params.load = JSON.parse(savedGui); + } + } + } + this.__closeButton = document.createElement('div'); + this.__closeButton.innerHTML = GUI.TEXT_CLOSED; + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_BUTTON); + if (params.closeOnTop) { + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_TOP); + this.domElement.insertBefore(this.__closeButton, this.domElement.childNodes[0]); + } else { + dom.addClass(this.__closeButton, GUI.CLASS_CLOSE_BOTTOM); + this.domElement.appendChild(this.__closeButton); + } + dom.bind(this.__closeButton, 'click', function () { + _this.closed = !_this.closed; + }); + } else { + if (params.closed === undefined) { + params.closed = true; + } + var titleRowName = document.createTextNode(params.name); + dom.addClass(titleRowName, 'controller-name'); + titleRow = addRow(_this, titleRowName); + var onClickTitle = function onClickTitle(e) { + e.preventDefault(); + _this.closed = !_this.closed; + return false; + }; + dom.addClass(this.__ul, GUI.CLASS_CLOSED); + dom.addClass(titleRow, 'title'); + dom.bind(titleRow, 'click', onClickTitle); + if (!params.closed) { + this.closed = false; + } + } + if (params.autoPlace) { + if (Common.isUndefined(params.parent)) { + if (autoPlaceVirgin) { + autoPlaceContainer = document.createElement('div'); + dom.addClass(autoPlaceContainer, CSS_NAMESPACE); + dom.addClass(autoPlaceContainer, GUI.CLASS_AUTO_PLACE_CONTAINER); + document.body.appendChild(autoPlaceContainer); + autoPlaceVirgin = false; + } + autoPlaceContainer.appendChild(this.domElement); + dom.addClass(this.domElement, GUI.CLASS_AUTO_PLACE); + } + if (!this.parent) { + setWidth(_this, params.width); + } + } + this.__resizeHandler = function () { + _this.onResizeDebounced(); + }; + dom.bind(window, 'resize', this.__resizeHandler); + dom.bind(this.__ul, 'webkitTransitionEnd', this.__resizeHandler); + dom.bind(this.__ul, 'transitionend', this.__resizeHandler); + dom.bind(this.__ul, 'oTransitionEnd', this.__resizeHandler); + this.onResize(); + if (params.resizable) { + addResizeHandle(this); + } + saveToLocalStorage = function saveToLocalStorage() { + if (SUPPORTS_LOCAL_STORAGE && localStorage.getItem(getLocalStorageHash(_this, 'isLocal')) === 'true') { + localStorage.setItem(getLocalStorageHash(_this, 'gui'), JSON.stringify(_this.getSaveObject())); + } + }; + this.saveToLocalStorageIfPossible = saveToLocalStorage; + function resetWidth() { + var root = _this.getRoot(); + root.width += 1; + Common.defer(function () { + root.width -= 1; + }); + } + if (!params.parent) { + resetWidth(); + } +}; +GUI.toggleHide = function () { + hide = !hide; + Common.each(hideableGuis, function (gui) { + gui.domElement.style.display = hide ? 'none' : ''; + }); +}; +GUI.CLASS_AUTO_PLACE = 'a'; +GUI.CLASS_AUTO_PLACE_CONTAINER = 'ac'; +GUI.CLASS_MAIN = 'main'; +GUI.CLASS_CONTROLLER_ROW = 'cr'; +GUI.CLASS_TOO_TALL = 'taller-than-window'; +GUI.CLASS_CLOSED = 'closed'; +GUI.CLASS_CLOSE_BUTTON = 'close-button'; +GUI.CLASS_CLOSE_TOP = 'close-top'; +GUI.CLASS_CLOSE_BOTTOM = 'close-bottom'; +GUI.CLASS_DRAG = 'drag'; +GUI.DEFAULT_WIDTH = 245; +GUI.TEXT_CLOSED = 'Close Controls'; +GUI.TEXT_OPEN = 'Open Controls'; +GUI._keydownHandler = function (e) { + if (document.activeElement.type !== 'text' && (e.which === HIDE_KEY_CODE || e.keyCode === HIDE_KEY_CODE)) { + GUI.toggleHide(); + } +}; +dom.bind(window, 'keydown', GUI._keydownHandler, false); +Common.extend(GUI.prototype, +{ + add: function add(object, property) { + return _add(this, object, property, { + factoryArgs: Array.prototype.slice.call(arguments, 2) + }); + }, + addColor: function addColor(object, property) { + return _add(this, object, property, { + color: true + }); + }, + remove: function remove(controller) { + this.__ul.removeChild(controller.__li); + this.__controllers.splice(this.__controllers.indexOf(controller), 1); + var _this = this; + Common.defer(function () { + _this.onResize(); + }); + }, + destroy: function destroy() { + if (this.parent) { + throw new Error('Only the root GUI should be removed with .destroy(). ' + 'For subfolders, use gui.removeFolder(folder) instead.'); + } + if (this.autoPlace) { + autoPlaceContainer.removeChild(this.domElement); + } + var _this = this; + Common.each(this.__folders, function (subfolder) { + _this.removeFolder(subfolder); + }); + dom.unbind(window, 'keydown', GUI._keydownHandler, false); + removeListeners(this); + }, + addFolder: function addFolder(name) { + if (this.__folders[name] !== undefined) { + throw new Error('You already have a folder in this GUI by the' + ' name "' + name + '"'); + } + var newGuiParams = { name: name, parent: this }; + newGuiParams.autoPlace = this.autoPlace; + if (this.load && + this.load.folders && + this.load.folders[name]) { + newGuiParams.closed = this.load.folders[name].closed; + newGuiParams.load = this.load.folders[name]; + } + var gui = new GUI(newGuiParams); + this.__folders[name] = gui; + var li = addRow(this, gui.domElement); + dom.addClass(li, 'folder'); + return gui; + }, + removeFolder: function removeFolder(folder) { + this.__ul.removeChild(folder.domElement.parentElement); + delete this.__folders[folder.name]; + if (this.load && + this.load.folders && + this.load.folders[folder.name]) { + delete this.load.folders[folder.name]; + } + removeListeners(folder); + var _this = this; + Common.each(folder.__folders, function (subfolder) { + folder.removeFolder(subfolder); + }); + Common.defer(function () { + _this.onResize(); + }); + }, + open: function open() { + this.closed = false; + }, + close: function close() { + this.closed = true; + }, + hide: function hide() { + this.domElement.style.display = 'none'; + }, + show: function show() { + this.domElement.style.display = ''; + }, + onResize: function onResize() { + var root = this.getRoot(); + if (root.scrollable) { + var top = dom.getOffset(root.__ul).top; + var h = 0; + Common.each(root.__ul.childNodes, function (node) { + if (!(root.autoPlace && node === root.__save_row)) { + h += dom.getHeight(node); + } + }); + if (window.innerHeight - top - CLOSE_BUTTON_HEIGHT < h) { + dom.addClass(root.domElement, GUI.CLASS_TOO_TALL); + root.__ul.style.height = window.innerHeight - top - CLOSE_BUTTON_HEIGHT + 'px'; + } else { + dom.removeClass(root.domElement, GUI.CLASS_TOO_TALL); + root.__ul.style.height = 'auto'; + } + } + if (root.__resize_handle) { + Common.defer(function () { + root.__resize_handle.style.height = root.__ul.offsetHeight + 'px'; + }); + } + if (root.__closeButton) { + root.__closeButton.style.width = root.width + 'px'; + } + }, + onResizeDebounced: Common.debounce(function () { + this.onResize(); + }, 50), + remember: function remember() { + if (Common.isUndefined(SAVE_DIALOGUE)) { + SAVE_DIALOGUE = new CenteredDiv(); + SAVE_DIALOGUE.domElement.innerHTML = saveDialogContents; + } + if (this.parent) { + throw new Error('You can only call remember on a top level GUI.'); + } + var _this = this; + Common.each(Array.prototype.slice.call(arguments), function (object) { + if (_this.__rememberedObjects.length === 0) { + addSaveMenu(_this); + } + if (_this.__rememberedObjects.indexOf(object) === -1) { + _this.__rememberedObjects.push(object); + } + }); + if (this.autoPlace) { + setWidth(this, this.width); + } + }, + getRoot: function getRoot() { + var gui = this; + while (gui.parent) { + gui = gui.parent; + } + return gui; + }, + getSaveObject: function getSaveObject() { + var toReturn = this.load; + toReturn.closed = this.closed; + if (this.__rememberedObjects.length > 0) { + toReturn.preset = this.preset; + if (!toReturn.remembered) { + toReturn.remembered = {}; + } + toReturn.remembered[this.preset] = getCurrentPreset(this); + } + toReturn.folders = {}; + Common.each(this.__folders, function (element, key) { + toReturn.folders[key] = element.getSaveObject(); + }); + return toReturn; + }, + save: function save() { + if (!this.load.remembered) { + this.load.remembered = {}; + } + this.load.remembered[this.preset] = getCurrentPreset(this); + markPresetModified(this, false); + this.saveToLocalStorageIfPossible(); + }, + saveAs: function saveAs(presetName) { + if (!this.load.remembered) { + this.load.remembered = {}; + this.load.remembered[DEFAULT_DEFAULT_PRESET_NAME] = getCurrentPreset(this, true); + } + this.load.remembered[presetName] = getCurrentPreset(this); + this.preset = presetName; + addPresetOption(this, presetName, true); + this.saveToLocalStorageIfPossible(); + }, + revert: function revert(gui) { + Common.each(this.__controllers, function (controller) { + if (!this.getRoot().load.remembered) { + controller.setValue(controller.initialValue); + } else { + recallSavedValue(gui || this.getRoot(), controller); + } + if (controller.__onFinishChange) { + controller.__onFinishChange.call(controller, controller.getValue()); + } + }, this); + Common.each(this.__folders, function (folder) { + folder.revert(folder); + }); + if (!gui) { + markPresetModified(this.getRoot(), false); + } + }, + listen: function listen(controller) { + var init = this.__listening.length === 0; + this.__listening.push(controller); + if (init) { + updateDisplays(this.__listening); + } + }, + updateDisplay: function updateDisplay() { + Common.each(this.__controllers, function (controller) { + controller.updateDisplay(); + }); + Common.each(this.__folders, function (folder) { + folder.updateDisplay(); + }); + } +}); +function addRow(gui, newDom, liBefore) { + var li = document.createElement('li'); + if (newDom) { + li.appendChild(newDom); + } + if (liBefore) { + gui.__ul.insertBefore(li, liBefore); + } else { + gui.__ul.appendChild(li); + } + gui.onResize(); + return li; +} +function removeListeners(gui) { + dom.unbind(window, 'resize', gui.__resizeHandler); + if (gui.saveToLocalStorageIfPossible) { + dom.unbind(window, 'unload', gui.saveToLocalStorageIfPossible); + } +} +function markPresetModified(gui, modified) { + var opt = gui.__preset_select[gui.__preset_select.selectedIndex]; + if (modified) { + opt.innerHTML = opt.value + '*'; + } else { + opt.innerHTML = opt.value; + } +} +function augmentController(gui, li, controller) { + controller.__li = li; + controller.__gui = gui; + Common.extend(controller, { + options: function options(_options) { + if (arguments.length > 1) { + var nextSibling = controller.__li.nextElementSibling; + controller.remove(); + return _add(gui, controller.object, controller.property, { + before: nextSibling, + factoryArgs: [Common.toArray(arguments)] + }); + } + if (Common.isArray(_options) || Common.isObject(_options)) { + var _nextSibling = controller.__li.nextElementSibling; + controller.remove(); + return _add(gui, controller.object, controller.property, { + before: _nextSibling, + factoryArgs: [_options] + }); + } + }, + name: function name(_name) { + controller.__li.firstElementChild.firstElementChild.innerHTML = _name; + return controller; + }, + listen: function listen() { + controller.__gui.listen(controller); + return controller; + }, + remove: function remove() { + controller.__gui.remove(controller); + return controller; + } + }); + if (controller instanceof NumberControllerSlider) { + var box = new NumberControllerBox(controller.object, controller.property, { min: controller.__min, max: controller.__max, step: controller.__step }); + Common.each(['updateDisplay', 'onChange', 'onFinishChange', 'step', 'min', 'max'], function (method) { + var pc = controller[method]; + var pb = box[method]; + controller[method] = box[method] = function () { + var args = Array.prototype.slice.call(arguments); + pb.apply(box, args); + return pc.apply(controller, args); + }; + }); + dom.addClass(li, 'has-slider'); + controller.domElement.insertBefore(box.domElement, controller.domElement.firstElementChild); + } else if (controller instanceof NumberControllerBox) { + var r = function r(returned) { + if (Common.isNumber(controller.__min) && Common.isNumber(controller.__max)) { + var oldName = controller.__li.firstElementChild.firstElementChild.innerHTML; + var wasListening = controller.__gui.__listening.indexOf(controller) > -1; + controller.remove(); + var newController = _add(gui, controller.object, controller.property, { + before: controller.__li.nextElementSibling, + factoryArgs: [controller.__min, controller.__max, controller.__step] + }); + newController.name(oldName); + if (wasListening) newController.listen(); + return newController; + } + return returned; + }; + controller.min = Common.compose(r, controller.min); + controller.max = Common.compose(r, controller.max); + } else if (controller instanceof BooleanController) { + dom.bind(li, 'click', function () { + dom.fakeEvent(controller.__checkbox, 'click'); + }); + dom.bind(controller.__checkbox, 'click', function (e) { + e.stopPropagation(); + }); + } else if (controller instanceof FunctionController) { + dom.bind(li, 'click', function () { + dom.fakeEvent(controller.__button, 'click'); + }); + dom.bind(li, 'mouseover', function () { + dom.addClass(controller.__button, 'hover'); + }); + dom.bind(li, 'mouseout', function () { + dom.removeClass(controller.__button, 'hover'); + }); + } else if (controller instanceof ColorController) { + dom.addClass(li, 'color'); + controller.updateDisplay = Common.compose(function (val) { + li.style.borderLeftColor = controller.__color.toString(); + return val; + }, controller.updateDisplay); + controller.updateDisplay(); + } + controller.setValue = Common.compose(function (val) { + if (gui.getRoot().__preset_select && controller.isModified()) { + markPresetModified(gui.getRoot(), true); + } + return val; + }, controller.setValue); +} +function recallSavedValue(gui, controller) { + var root = gui.getRoot(); + var matchedIndex = root.__rememberedObjects.indexOf(controller.object); + if (matchedIndex !== -1) { + var controllerMap = root.__rememberedObjectIndecesToControllers[matchedIndex]; + if (controllerMap === undefined) { + controllerMap = {}; + root.__rememberedObjectIndecesToControllers[matchedIndex] = controllerMap; + } + controllerMap[controller.property] = controller; + if (root.load && root.load.remembered) { + var presetMap = root.load.remembered; + var preset = void 0; + if (presetMap[gui.preset]) { + preset = presetMap[gui.preset]; + } else if (presetMap[DEFAULT_DEFAULT_PRESET_NAME]) { + preset = presetMap[DEFAULT_DEFAULT_PRESET_NAME]; + } else { + return; + } + if (preset[matchedIndex] && preset[matchedIndex][controller.property] !== undefined) { + var value = preset[matchedIndex][controller.property]; + controller.initialValue = value; + controller.setValue(value); + } + } + } +} +function _add(gui, object, property, params) { + if (object[property] === undefined) { + throw new Error('Object "' + object + '" has no property "' + property + '"'); + } + var controller = void 0; + if (params.color) { + controller = new ColorController(object, property); + } else { + var factoryArgs = [object, property].concat(params.factoryArgs); + controller = ControllerFactory.apply(gui, factoryArgs); + } + if (params.before instanceof Controller) { + params.before = params.before.__li; + } + recallSavedValue(gui, controller); + dom.addClass(controller.domElement, 'c'); + var name = document.createElement('span'); + dom.addClass(name, 'property-name'); + name.innerHTML = controller.property; + var container = document.createElement('div'); + container.appendChild(name); + container.appendChild(controller.domElement); + var li = addRow(gui, container, params.before); + dom.addClass(li, GUI.CLASS_CONTROLLER_ROW); + if (controller instanceof ColorController) { + dom.addClass(li, 'color'); + } else { + dom.addClass(li, _typeof(controller.getValue())); + } + augmentController(gui, li, controller); + gui.__controllers.push(controller); + return controller; +} +function getLocalStorageHash(gui, key) { + return document.location.href + '.' + key; +} +function addPresetOption(gui, name, setSelected) { + var opt = document.createElement('option'); + opt.innerHTML = name; + opt.value = name; + gui.__preset_select.appendChild(opt); + if (setSelected) { + gui.__preset_select.selectedIndex = gui.__preset_select.length - 1; + } +} +function showHideExplain(gui, explain) { + explain.style.display = gui.useLocalStorage ? 'block' : 'none'; +} +function addSaveMenu(gui) { + var div = gui.__save_row = document.createElement('li'); + dom.addClass(gui.domElement, 'has-save'); + gui.__ul.insertBefore(div, gui.__ul.firstChild); + dom.addClass(div, 'save-row'); + var gears = document.createElement('span'); + gears.innerHTML = ' '; + dom.addClass(gears, 'button gears'); + var button = document.createElement('span'); + button.innerHTML = 'Save'; + dom.addClass(button, 'button'); + dom.addClass(button, 'save'); + var button2 = document.createElement('span'); + button2.innerHTML = 'New'; + dom.addClass(button2, 'button'); + dom.addClass(button2, 'save-as'); + var button3 = document.createElement('span'); + button3.innerHTML = 'Revert'; + dom.addClass(button3, 'button'); + dom.addClass(button3, 'revert'); + var select = gui.__preset_select = document.createElement('select'); + if (gui.load && gui.load.remembered) { + Common.each(gui.load.remembered, function (value, key) { + addPresetOption(gui, key, key === gui.preset); + }); + } else { + addPresetOption(gui, DEFAULT_DEFAULT_PRESET_NAME, false); + } + dom.bind(select, 'change', function () { + for (var index = 0; index < gui.__preset_select.length; index++) { + gui.__preset_select[index].innerHTML = gui.__preset_select[index].value; + } + gui.preset = this.value; + }); + div.appendChild(select); + div.appendChild(gears); + div.appendChild(button); + div.appendChild(button2); + div.appendChild(button3); + if (SUPPORTS_LOCAL_STORAGE) { + var explain = document.getElementById('dg-local-explain'); + var localStorageCheckBox = document.getElementById('dg-local-storage'); + var saveLocally = document.getElementById('dg-save-locally'); + saveLocally.style.display = 'block'; + if (localStorage.getItem(getLocalStorageHash(gui, 'isLocal')) === 'true') { + localStorageCheckBox.setAttribute('checked', 'checked'); + } + showHideExplain(gui, explain); + dom.bind(localStorageCheckBox, 'change', function () { + gui.useLocalStorage = !gui.useLocalStorage; + showHideExplain(gui, explain); + }); + } + var newConstructorTextArea = document.getElementById('dg-new-constructor'); + dom.bind(newConstructorTextArea, 'keydown', function (e) { + if (e.metaKey && (e.which === 67 || e.keyCode === 67)) { + SAVE_DIALOGUE.hide(); + } + }); + dom.bind(gears, 'click', function () { + newConstructorTextArea.innerHTML = JSON.stringify(gui.getSaveObject(), undefined, 2); + SAVE_DIALOGUE.show(); + newConstructorTextArea.focus(); + newConstructorTextArea.select(); + }); + dom.bind(button, 'click', function () { + gui.save(); + }); + dom.bind(button2, 'click', function () { + var presetName = prompt('Enter a new preset name.'); + if (presetName) { + gui.saveAs(presetName); + } + }); + dom.bind(button3, 'click', function () { + gui.revert(); + }); +} +function addResizeHandle(gui) { + var pmouseX = void 0; + gui.__resize_handle = document.createElement('div'); + Common.extend(gui.__resize_handle.style, { + width: '6px', + marginLeft: '-3px', + height: '200px', + cursor: 'ew-resize', + position: 'absolute' + }); + function drag(e) { + e.preventDefault(); + gui.width += pmouseX - e.clientX; + gui.onResize(); + pmouseX = e.clientX; + return false; + } + function dragStop() { + dom.removeClass(gui.__closeButton, GUI.CLASS_DRAG); + dom.unbind(window, 'mousemove', drag); + dom.unbind(window, 'mouseup', dragStop); + } + function dragStart(e) { + e.preventDefault(); + pmouseX = e.clientX; + dom.addClass(gui.__closeButton, GUI.CLASS_DRAG); + dom.bind(window, 'mousemove', drag); + dom.bind(window, 'mouseup', dragStop); + return false; + } + dom.bind(gui.__resize_handle, 'mousedown', dragStart); + dom.bind(gui.__closeButton, 'mousedown', dragStart); + gui.domElement.insertBefore(gui.__resize_handle, gui.domElement.firstElementChild); +} +function setWidth(gui, w) { + gui.domElement.style.width = w + 'px'; + if (gui.__save_row && gui.autoPlace) { + gui.__save_row.style.width = w + 'px'; + } + if (gui.__closeButton) { + gui.__closeButton.style.width = w + 'px'; + } +} +function getCurrentPreset(gui, useInitialValues) { + var toReturn = {}; + Common.each(gui.__rememberedObjects, function (val, index) { + var savedValues = {}; + var controllerMap = gui.__rememberedObjectIndecesToControllers[index]; + Common.each(controllerMap, function (controller, property) { + savedValues[property] = useInitialValues ? controller.initialValue : controller.getValue(); + }); + toReturn[index] = savedValues; + }); + return toReturn; +} +function setPresetSelectIndex(gui) { + for (var index = 0; index < gui.__preset_select.length; index++) { + if (gui.__preset_select[index].value === gui.preset) { + gui.__preset_select.selectedIndex = index; + } + } +} +function updateDisplays(controllerArray) { + if (controllerArray.length !== 0) { + requestAnimationFrame$1.call(window, function () { + updateDisplays(controllerArray); + }); + } + Common.each(controllerArray, function (c) { + c.updateDisplay(); + }); +} + +var color = { + Color: Color, + math: ColorMath, + interpret: interpret +}; +var controllers = { + Controller: Controller, + BooleanController: BooleanController, + OptionController: OptionController, + StringController: StringController, + NumberController: NumberController, + NumberControllerBox: NumberControllerBox, + NumberControllerSlider: NumberControllerSlider, + FunctionController: FunctionController, + ColorController: ColorController +}; +var dom$1 = { dom: dom }; +var gui = { GUI: GUI }; +var GUI$1 = GUI; +var index = { + color: color, + controllers: controllers, + dom: dom$1, + gui: gui, + GUI: GUI$1 +}; + + +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (index); +//# sourceMappingURL=dat.gui.module.js.map + + +/***/ }), + +/***/ "../../node_modules/park-miller/index.js": +/*!***********************************************!*\ + !*** ../../node_modules/park-miller/index.js ***! + \***********************************************/ +/***/ ((module) => { + + +const MAX_INT32 = 2147483647; +const MINSTD = 16807; + +class ParkMiller { + constructor(seed) { + if (!Number.isInteger(seed)) { + throw new TypeError('Expected `seed` to be a `integer`'); + } + + this._seed = seed % MAX_INT32; + + if (this._seed <= 0) { + this._seed += (MAX_INT32 - 1); + } + } + + integer() { + this._seed *= MINSTD; + this._seed %= MAX_INT32; + return this._seed; + } + + integerInRange(min, max) { + return Math.round(this.floatInRange(min, max)); + } + + float() { + return (this.integer() - 1) / (MAX_INT32 - 1); + } + + floatInRange(min, max) { + return min + ((max - min) * this.float()); + } + + boolean() { + return this.integer() % 2 === 0; + } +} + +module.exports = ParkMiller; + + +/***/ }), + +/***/ "./canvas.ts": +/*!*******************!*\ + !*** ./canvas.ts ***! + \*******************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createCanvas: () => (/* binding */ createCanvas), +/* harmony export */ drawOptions: () => (/* binding */ drawOptions) +/* harmony export */ }); +/* harmony import */ var _snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/draw/drawWorld */ "../draw/drawWorld.ts"); + +const drawOptions = { + sizeDotBorderRadius: 2, + sizeCell: 16, + sizeDot: 12, + colorDotBorder: "#1b1f230a", + colorDots: { + 1: "#9be9a8", + 2: "#40c463", + 3: "#30a14e", + 4: "#216e39", + }, + colorEmpty: "#ebedf0", + colorSnake: "purple", + dark: { + colorEmpty: "#161b22", + colorDots: { 1: "#01311f", 2: "#034525", 3: "#0f6d31", 4: "#00c647" }, + }, +}; +const getPointedCell = (canvas) => ({ pageX, pageY }) => { + const { left, top } = canvas.getBoundingClientRect(); + const x = Math.floor((pageX - left) / drawOptions.sizeCell) - 1; + const y = Math.floor((pageY - top) / drawOptions.sizeCell) - 2; + return { x, y }; +}; +const createCanvas = ({ width, height, }) => { + const canvas = document.createElement("canvas"); + const upscale = 2; + const w = drawOptions.sizeCell * (width + 4); + const h = drawOptions.sizeCell * (height + 4) + 200; + canvas.width = w * upscale; + canvas.height = h * upscale; + canvas.style.width = w + "px"; + canvas.style.height = h + "px"; + canvas.style.display = "block"; + // canvas.style.pointerEvents = "none"; + const cellInfo = document.createElement("div"); + cellInfo.style.height = "20px"; + document.body.appendChild(cellInfo); + document.body.appendChild(canvas); + canvas.addEventListener("mousemove", (e) => { + const { x, y } = getPointedCell(canvas)(e); + cellInfo.innerText = [x, y] + .map((u) => u.toString().padStart(2, " ")) + .join(" / "); + }); + const ctx = canvas.getContext("2d"); + ctx.scale(upscale, upscale); + const draw = (grid, snake, stack) => { + ctx.clearRect(0, 0, 9999, 9999); + (0,_snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__.drawWorld)(ctx, grid, null, snake, stack, drawOptions); + }; + const drawLerp = (grid, snake0, snake1, stack, k) => { + ctx.clearRect(0, 0, 9999, 9999); + (0,_snk_draw_drawWorld__WEBPACK_IMPORTED_MODULE_0__.drawLerpWorld)(ctx, grid, null, snake0, snake1, stack, k, drawOptions); + }; + const highlightCell = (x, y, color = "orange") => { + ctx.fillStyle = color; + ctx.beginPath(); + ctx.fillRect((1 + x + 0.5) * 16 - 2, (2 + y + 0.5) * 16 - 2, 4, 4); + }; + return { + draw, + drawLerp, + highlightCell, + canvas, + getPointedCell: getPointedCell(canvas), + ctx, + }; +}; + + +/***/ }), + +/***/ "./menu.ts": +/*!*****************!*\ + !*** ./menu.ts ***! + \*****************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ gui: () => (/* binding */ gui) +/* harmony export */ }); +/* harmony import */ var dat_gui__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! dat.gui */ "../../node_modules/dat.gui/build/dat.gui.module.js"); +/* harmony import */ var _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/__fixtures__/grid */ "../types/__fixtures__/grid.ts"); +/* harmony import */ var _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/__fixtures__/snake */ "../types/__fixtures__/snake.ts"); +/* harmony import */ var _sample__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sample */ "./sample.ts"); + + + + +const demos = __webpack_require__(/*! ./demo.json */ "./demo.json"); +const gui = new dat_gui__WEBPACK_IMPORTED_MODULE_0__.GUI(); +const config = { + snake: Object.entries(_snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__).find(([_, s]) => s === _sample__WEBPACK_IMPORTED_MODULE_3__.snake)[0], + grid: Object.entries(_snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__).find(([_, s]) => s === _sample__WEBPACK_IMPORTED_MODULE_3__.grid)[0], + demo: demos[0], +}; +{ + const d = window.location.pathname.match(/(\w+)\.html/); + if (d && demos.includes(d[1])) + config.demo = d[1]; +} +const onChange = () => { + const search = new URLSearchParams({ + snake: config.snake, + grid: config.grid, + }).toString(); + const url = new URL(config.demo + ".html?" + search, window.location.href).toString(); + window.location.href = url; +}; +gui.add(config, "demo", demos).onChange(onChange); +gui.add(config, "grid", Object.keys(_snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_1__)).onChange(onChange); +gui.add(config, "snake", Object.keys(_snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__)).onChange(onChange); + + +/***/ }), + +/***/ "./sample.ts": +/*!*******************!*\ + !*** ./sample.ts ***! + \*******************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ grid: () => (/* binding */ grid), +/* harmony export */ snake: () => (/* binding */ snake) +/* harmony export */ }); +/* harmony import */ var _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/__fixtures__/grid */ "../types/__fixtures__/grid.ts"); +/* harmony import */ var _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/__fixtures__/snake */ "../types/__fixtures__/snake.ts"); + + +const sp = new URLSearchParams(window.location.search); +const gLabel = sp.get("grid") || "simple"; +const sLabel = sp.get("snake") || "snake3"; +//@ts-ignore +const grid = _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__[gLabel] || _snk_types_fixtures_grid__WEBPACK_IMPORTED_MODULE_0__.simple; +//@ts-ignore +const snake = _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__[sLabel] || _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_1__.snake3; + + +/***/ }), + +/***/ "../draw/drawGrid.ts": +/*!***************************!*\ + !*** ../draw/drawGrid.ts ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawGrid: () => (/* binding */ drawGrid) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _pathRoundedRect__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./pathRoundedRect */ "../draw/pathRoundedRect.ts"); + + +const drawGrid = (ctx, grid, cells, o) => { + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + if (!cells || cells.some((c) => c.x === x && c.y === y)) { + const c = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + // @ts-ignore + const color = !c ? o.colorEmpty : o.colorDots[c]; + ctx.save(); + ctx.translate(x * o.sizeCell + (o.sizeCell - o.sizeDot) / 2, y * o.sizeCell + (o.sizeCell - o.sizeDot) / 2); + ctx.fillStyle = color; + ctx.strokeStyle = o.colorDotBorder; + ctx.lineWidth = 1; + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_1__.pathRoundedRect)(ctx, o.sizeDot, o.sizeDot, o.sizeDotBorderRadius); + ctx.fill(); + ctx.stroke(); + ctx.closePath(); + ctx.restore(); + } + } +}; + + +/***/ }), + +/***/ "../draw/drawSnake.ts": +/*!****************************!*\ + !*** ../draw/drawSnake.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawSnake: () => (/* binding */ drawSnake), +/* harmony export */ drawSnakeLerp: () => (/* binding */ drawSnakeLerp) +/* harmony export */ }); +/* harmony import */ var _pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./pathRoundedRect */ "../draw/pathRoundedRect.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); + + +const drawSnake = (ctx, snake, o) => { + const cells = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.snakeToCells)(snake); + for (let i = 0; i < cells.length; i++) { + const u = (i + 1) * 0.6; + ctx.save(); + ctx.fillStyle = o.colorSnake; + ctx.translate(cells[i].x * o.sizeCell + u, cells[i].y * o.sizeCell + u); + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__.pathRoundedRect)(ctx, o.sizeCell - u * 2, o.sizeCell - u * 2, (o.sizeCell - u * 2) * 0.25); + ctx.fill(); + ctx.restore(); + } +}; +const lerp = (k, a, b) => (1 - k) * a + k * b; +const clamp = (x, a, b) => Math.max(a, Math.min(b, x)); +const drawSnakeLerp = (ctx, snake0, snake1, k, o) => { + const m = 0.8; + const n = snake0.length / 2; + for (let i = 0; i < n; i++) { + const u = (i + 1) * 0.6 * (o.sizeCell / 16); + const a = (1 - m) * (i / Math.max(n - 1, 1)); + const ki = clamp((k - a) / m, 0, 1); + const x = lerp(ki, snake0[i * 2 + 0], snake1[i * 2 + 0]) - 2; + const y = lerp(ki, snake0[i * 2 + 1], snake1[i * 2 + 1]) - 2; + ctx.save(); + ctx.fillStyle = o.colorSnake; + ctx.translate(x * o.sizeCell + u, y * o.sizeCell + u); + ctx.beginPath(); + (0,_pathRoundedRect__WEBPACK_IMPORTED_MODULE_0__.pathRoundedRect)(ctx, o.sizeCell - u * 2, o.sizeCell - u * 2, (o.sizeCell - u * 2) * 0.25); + ctx.fill(); + ctx.restore(); + } +}; + + +/***/ }), + +/***/ "../draw/drawWorld.ts": +/*!****************************!*\ + !*** ../draw/drawWorld.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ drawLerpWorld: () => (/* binding */ drawLerpWorld), +/* harmony export */ drawStack: () => (/* binding */ drawStack), +/* harmony export */ drawWorld: () => (/* binding */ drawWorld), +/* harmony export */ getCanvasWorldSize: () => (/* binding */ getCanvasWorldSize) +/* harmony export */ }); +/* harmony import */ var _drawGrid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./drawGrid */ "../draw/drawGrid.ts"); +/* harmony import */ var _drawSnake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./drawSnake */ "../draw/drawSnake.ts"); + + +const drawStack = (ctx, stack, max, width, o) => { + ctx.save(); + const m = width / max; + for (let i = 0; i < stack.length; i++) { + // @ts-ignore + ctx.fillStyle = o.colorDots[stack[i]]; + ctx.fillRect(i * m, 0, m + width * 0.005, 10); + } + ctx.restore(); +}; +const drawWorld = (ctx, grid, cells, snake, stack, o) => { + ctx.save(); + ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); + (0,_drawGrid__WEBPACK_IMPORTED_MODULE_0__.drawGrid)(ctx, grid, cells, o); + (0,_drawSnake__WEBPACK_IMPORTED_MODULE_1__.drawSnake)(ctx, snake, o); + ctx.restore(); + ctx.save(); + ctx.translate(o.sizeCell, (grid.height + 4) * o.sizeCell); + const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length); + drawStack(ctx, stack, max, grid.width * o.sizeCell, o); + ctx.restore(); + // ctx.save(); + // ctx.translate(o.sizeCell + 100, (grid.height + 4) * o.sizeCell + 100); + // ctx.scale(0.6, 0.6); + // drawCircleStack(ctx, stack, o); + // ctx.restore(); +}; +const drawLerpWorld = (ctx, grid, cells, snake0, snake1, stack, k, o) => { + ctx.save(); + ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); + (0,_drawGrid__WEBPACK_IMPORTED_MODULE_0__.drawGrid)(ctx, grid, cells, o); + (0,_drawSnake__WEBPACK_IMPORTED_MODULE_1__.drawSnakeLerp)(ctx, snake0, snake1, k, o); + ctx.translate(0, (grid.height + 2) * o.sizeCell); + const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length); + drawStack(ctx, stack, max, grid.width * o.sizeCell, o); + ctx.restore(); +}; +const getCanvasWorldSize = (grid, o) => { + const width = o.sizeCell * (grid.width + 2); + const height = o.sizeCell * (grid.height + 4) + 30; + return { width, height }; +}; + + +/***/ }), + +/***/ "../draw/pathRoundedRect.ts": +/*!**********************************!*\ + !*** ../draw/pathRoundedRect.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ pathRoundedRect: () => (/* binding */ pathRoundedRect) +/* harmony export */ }); +const pathRoundedRect = (ctx, width, height, borderRadius) => { + ctx.moveTo(borderRadius, 0); + ctx.arcTo(width, 0, width, height, borderRadius); + ctx.arcTo(width, height, 0, height, borderRadius); + ctx.arcTo(0, height, 0, 0, borderRadius); + ctx.arcTo(0, 0, width, 0, borderRadius); +}; + + +/***/ }), + +/***/ "../solver/getPathTo.ts": +/*!******************************!*\ + !*** ../solver/getPathTo.ts ***! + \******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getPathTo: () => (/* binding */ getPathTo) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _utils_sortPush__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./utils/sortPush */ "../solver/utils/sortPush.ts"); + + + + +/** + * starting from snake0, get to the cell x,y + * return the snake chain (reversed) + */ +const getPathTo = (grid, snake0, x, y) => { + const openList = [{ snake: snake0, w: 0 }]; + const closeList = []; + while (openList.length) { + const c = openList.shift(); + const cx = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.getHeadX)(c.snake); + const cy = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.getHeadY)(c.snake); + for (let i = 0; i < _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4.length; i++) { + const { x: dx, y: dy } = _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4[i]; + const nx = cx + dx; + const ny = cy + dy; + if (nx === x && ny === y) { + // unwrap + const path = [(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.nextSnake)(c.snake, dx, dy)]; + let e = c; + while (e.parent) { + path.push(e.snake); + e = e.parent; + } + return path; + } + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInsideLarge)(grid, 2, nx, ny) && + !(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.snakeWillSelfCollide)(c.snake, dx, dy) && + (!(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, nx, ny) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, nx, ny)))) { + const nsnake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.nextSnake)(c.snake, dx, dy); + if (!closeList.some((s) => (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.snakeEquals)(nsnake, s))) { + const w = c.w + 1; + const h = Math.abs(nx - x) + Math.abs(ny - y); + const f = w + h; + const o = { snake: nsnake, parent: c, w, h, f }; + (0,_utils_sortPush__WEBPACK_IMPORTED_MODULE_3__.sortPush)(openList, o, (a, b) => a.f - b.f); + closeList.push(nsnake); + } + } + } + } +}; + + +/***/ }), + +/***/ "../solver/utils/sortPush.ts": +/*!***********************************!*\ + !*** ../solver/utils/sortPush.ts ***! + \***********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ sortPush: () => (/* binding */ sortPush) +/* harmony export */ }); +const sortPush = (arr, x, sortFn) => { + let a = 0; + let b = arr.length; + if (arr.length === 0 || sortFn(x, arr[a]) <= 0) { + arr.unshift(x); + return; + } + while (b - a > 1) { + const e = Math.ceil((a + b) / 2); + const s = sortFn(x, arr[e]); + if (s === 0) + a = b = e; + else if (s > 0) + a = e; + else + b = e; + } + const e = Math.ceil((a + b) / 2); + arr.splice(e, 0, x); +}; + + +/***/ }), + +/***/ "../types/__fixtures__/createFromAscii.ts": +/*!************************************************!*\ + !*** ../types/__fixtures__/createFromAscii.ts ***! + \************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createFromAscii: () => (/* binding */ createFromAscii) +/* harmony export */ }); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../grid */ "../types/grid.ts"); + +const createFromAscii = (ascii) => { + const a = ascii.split("\n"); + if (a[0] === "") + a.shift(); + const height = a.length; + const width = Math.max(...a.map((r) => r.length)); + const grid = (0,_grid__WEBPACK_IMPORTED_MODULE_0__.createEmptyGrid)(width, height); + for (let x = width; x--;) + for (let y = height; y--;) { + const c = a[y][x]; + const color = (c === "#" && 3) || (c === "@" && 2) || (c === "." && 1) || +c; + if (c) + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(grid, x, y, color); + } + return grid; +}; + + +/***/ }), + +/***/ "../types/__fixtures__/grid.ts": +/*!*************************************!*\ + !*** ../types/__fixtures__/grid.ts ***! + \*************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ closedO: () => (/* binding */ closedO), +/* harmony export */ closedP: () => (/* binding */ closedP), +/* harmony export */ closedU: () => (/* binding */ closedU), +/* harmony export */ corner: () => (/* binding */ corner), +/* harmony export */ empty: () => (/* binding */ empty), +/* harmony export */ enclaveBorder: () => (/* binding */ enclaveBorder), +/* harmony export */ enclaveK: () => (/* binding */ enclaveK), +/* harmony export */ enclaveM: () => (/* binding */ enclaveM), +/* harmony export */ enclaveN: () => (/* binding */ enclaveN), +/* harmony export */ enclaveU: () => (/* binding */ enclaveU), +/* harmony export */ realistic: () => (/* binding */ realistic), +/* harmony export */ realisticFull: () => (/* binding */ realisticFull), +/* harmony export */ simple: () => (/* binding */ simple), +/* harmony export */ small: () => (/* binding */ small), +/* harmony export */ smallFull: () => (/* binding */ smallFull), +/* harmony export */ smallPacked: () => (/* binding */ smallPacked), +/* harmony export */ tunnels: () => (/* binding */ tunnels) +/* harmony export */ }); +/* harmony import */ var park_miller__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! park-miller */ "../../node_modules/park-miller/index.js"); +/* harmony import */ var park_miller__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(park_miller__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../grid */ "../types/grid.ts"); +/* harmony import */ var _randomlyFillGrid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../randomlyFillGrid */ "../types/randomlyFillGrid.ts"); +/* harmony import */ var _createFromAscii__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./createFromAscii */ "../types/__fixtures__/createFromAscii.ts"); + + + + +const colors = [1, 2, 3]; +// empty small grid +const empty = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +// empty small grid with a unique color at the middle +const simple = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(simple, 2, 2, 1); +// empty small grid with color at each corner +const corner = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(5, 5); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 0, 4, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 4, 0, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 4, 4, 1); +(0,_grid__WEBPACK_IMPORTED_MODULE_1__.setColor)(corner, 0, 0, 1); +const enclaveN = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #.# + # + +`); +const enclaveBorder = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + #.# + # + +`); +const enclaveM = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### + # # + # . # + # # + # # +`); +const enclaveK = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + # .# + # # + # # + # # +`); +const enclaveU = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + #..# + #..# + #.# + # # . +`); +const closedP = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### + ##.# + ## # + ## +`); +const closedU = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + #### + #..# + #..# + #.# + ### +`); +const closedO = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ####### + # # + # . # + # # + ####### +`); +const tunnels = (0,_createFromAscii__WEBPACK_IMPORTED_MODULE_3__.createFromAscii)(` + + ### ### ### + #.# #.# #.# + #.# ### # # +`); +const createRandom = (width, height, emptyP) => { + const grid = (0,_grid__WEBPACK_IMPORTED_MODULE_1__.createEmptyGrid)(width, height); + const pm = new (park_miller__WEBPACK_IMPORTED_MODULE_0___default())(10); + const random = pm.integerInRange.bind(pm); + (0,_randomlyFillGrid__WEBPACK_IMPORTED_MODULE_2__.randomlyFillGrid)(grid, { colors, emptyP }, random); + return grid; +}; +// small realistic +const small = createRandom(10, 7, 3); +const smallPacked = createRandom(10, 7, 1); +const smallFull = createRandom(10, 7, 0); +// small realistic +const realistic = createRandom(52, 7, 3); +const realisticFull = createRandom(52, 7, 0); + + +/***/ }), + +/***/ "../types/__fixtures__/snake.ts": +/*!**************************************!*\ + !*** ../types/__fixtures__/snake.ts ***! + \**************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ snake1: () => (/* binding */ snake1), +/* harmony export */ snake3: () => (/* binding */ snake3), +/* harmony export */ snake4: () => (/* binding */ snake4), +/* harmony export */ snake5: () => (/* binding */ snake5), +/* harmony export */ snake9: () => (/* binding */ snake9) +/* harmony export */ }); +/* harmony import */ var _snake__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../snake */ "../types/snake.ts"); + +const create = (length) => (0,_snake__WEBPACK_IMPORTED_MODULE_0__.createSnakeFromCells)(Array.from({ length }, (_, i) => ({ x: i, y: -1 }))); +const snake1 = create(1); +const snake3 = create(3); +const snake4 = create(4); +const snake5 = create(5); +const snake9 = create(9); + + +/***/ }), + +/***/ "../types/grid.ts": +/*!************************!*\ + !*** ../types/grid.ts ***! + \************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copyGrid: () => (/* binding */ copyGrid), +/* harmony export */ createEmptyGrid: () => (/* binding */ createEmptyGrid), +/* harmony export */ getColor: () => (/* binding */ getColor), +/* harmony export */ gridEquals: () => (/* binding */ gridEquals), +/* harmony export */ isEmpty: () => (/* binding */ isEmpty), +/* harmony export */ isGridEmpty: () => (/* binding */ isGridEmpty), +/* harmony export */ isInside: () => (/* binding */ isInside), +/* harmony export */ isInsideLarge: () => (/* binding */ isInsideLarge), +/* harmony export */ setColor: () => (/* binding */ setColor), +/* harmony export */ setColorEmpty: () => (/* binding */ setColorEmpty) +/* harmony export */ }); +const isInside = (grid, x, y) => x >= 0 && y >= 0 && x < grid.width && y < grid.height; +const isInsideLarge = (grid, m, x, y) => x >= -m && y >= -m && x < grid.width + m && y < grid.height + m; +const copyGrid = ({ width, height, data }) => ({ + width, + height, + data: Uint8Array.from(data), +}); +const getIndex = (grid, x, y) => x * grid.height + y; +const getColor = (grid, x, y) => grid.data[getIndex(grid, x, y)]; +const isEmpty = (color) => color === 0; +const setColor = (grid, x, y, color) => { + grid.data[getIndex(grid, x, y)] = color || 0; +}; +const setColorEmpty = (grid, x, y) => { + setColor(grid, x, y, 0); +}; +/** + * return true if the grid is empty + */ +const isGridEmpty = (grid) => grid.data.every((x) => x === 0); +const gridEquals = (a, b) => a.data.every((_, i) => a.data[i] === b.data[i]); +const createEmptyGrid = (width, height) => ({ + width, + height, + data: new Uint8Array(width * height), +}); + + +/***/ }), + +/***/ "../types/point.ts": +/*!*************************!*\ + !*** ../types/point.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ around4: () => (/* binding */ around4), +/* harmony export */ pointEquals: () => (/* binding */ pointEquals) +/* harmony export */ }); +const around4 = [ + { x: 1, y: 0 }, + { x: 0, y: -1 }, + { x: -1, y: 0 }, + { x: 0, y: 1 }, +]; +const pointEquals = (a, b) => a.x === b.x && a.y === b.y; + + +/***/ }), + +/***/ "../types/randomlyFillGrid.ts": +/*!************************************!*\ + !*** ../types/randomlyFillGrid.ts ***! + \************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ randomlyFillGrid: () => (/* binding */ randomlyFillGrid) +/* harmony export */ }); +/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./grid */ "../types/grid.ts"); + +const defaultRand = (a, b) => Math.floor(Math.random() * (b - a + 1)) + a; +const randomlyFillGrid = (grid, { colors = [1, 2, 3], emptyP = 2, } = {}, rand = defaultRand) => { + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + const k = rand(-emptyP, colors.length - 1); + if (k >= 0) + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(grid, x, y, colors[k]); + else + (0,_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); + } +}; + + +/***/ }), + +/***/ "../types/snake.ts": +/*!*************************!*\ + !*** ../types/snake.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copySnake: () => (/* binding */ copySnake), +/* harmony export */ createSnakeFromCells: () => (/* binding */ createSnakeFromCells), +/* harmony export */ getHeadX: () => (/* binding */ getHeadX), +/* harmony export */ getHeadY: () => (/* binding */ getHeadY), +/* harmony export */ getSnakeLength: () => (/* binding */ getSnakeLength), +/* harmony export */ nextSnake: () => (/* binding */ nextSnake), +/* harmony export */ snakeEquals: () => (/* binding */ snakeEquals), +/* harmony export */ snakeToCells: () => (/* binding */ snakeToCells), +/* harmony export */ snakeWillSelfCollide: () => (/* binding */ snakeWillSelfCollide) +/* harmony export */ }); +const getHeadX = (snake) => snake[0] - 2; +const getHeadY = (snake) => snake[1] - 2; +const getSnakeLength = (snake) => snake.length / 2; +const copySnake = (snake) => snake.slice(); +const snakeEquals = (a, b) => { + for (let i = 0; i < a.length; i++) + if (a[i] !== b[i]) + return false; + return true; +}; +/** + * return a copy of the next snake, considering that dx, dy is the direction + */ +const nextSnake = (snake, dx, dy) => { + const copy = new Uint8Array(snake.length); + for (let i = 2; i < snake.length; i++) + copy[i] = snake[i - 2]; + copy[0] = snake[0] + dx; + copy[1] = snake[1] + dy; + return copy; +}; +/** + * return true if the next snake will collide with itself + */ +const snakeWillSelfCollide = (snake, dx, dy) => { + const nx = snake[0] + dx; + const ny = snake[1] + dy; + for (let i = 2; i < snake.length - 2; i += 2) + if (snake[i + 0] === nx && snake[i + 1] === ny) + return true; + return false; +}; +const snakeToCells = (snake) => Array.from({ length: snake.length / 2 }, (_, i) => ({ + x: snake[i * 2 + 0] - 2, + y: snake[i * 2 + 1] - 2, +})); +const createSnakeFromCells = (points) => { + const snake = new Uint8Array(points.length * 2); + for (let i = points.length; i--;) { + snake[i * 2 + 0] = points[i].x + 2; + snake[i * 2 + 1] = points[i].y + 2; + } + return snake; +}; + + +/***/ }), + +/***/ "./demo.json": +/*!*******************!*\ + !*** ./demo.json ***! + \*******************/ +/***/ ((module) => { + +module.exports = JSON.parse('["interactive","getBestRoute","getBestTunnel","outside","getPathToPose","getPathTo","svg"]'); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ (() => { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = (module) => { +/******/ var getter = module && module.__esModule ? +/******/ () => (module['default']) : +/******/ () => (module); +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +/*!***************************!*\ + !*** ./demo.getPathTo.ts ***! + \***************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _menu__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./menu */ "./menu.ts"); +/* harmony import */ var _canvas__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./canvas */ "./canvas.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _sample__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sample */ "./sample.ts"); +/* harmony import */ var _snk_solver_getPathTo__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @snk/solver/getPathTo */ "../solver/getPathTo.ts"); + + + + + +const { canvas, ctx, draw, getPointedCell, highlightCell } = (0,_canvas__WEBPACK_IMPORTED_MODULE_1__.createCanvas)(_sample__WEBPACK_IMPORTED_MODULE_3__.grid); +canvas.style.pointerEvents = "auto"; +let snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.copySnake)(_sample__WEBPACK_IMPORTED_MODULE_3__.snake); +let chain = [snake]; +canvas.addEventListener("mousemove", (e) => { + const { x, y } = getPointedCell(e); + chain = [...((0,_snk_solver_getPathTo__WEBPACK_IMPORTED_MODULE_4__.getPathTo)(_sample__WEBPACK_IMPORTED_MODULE_3__.grid, snake, x, y) || []), snake].reverse(); + inputI.max = chain.length - 1; + i = inputI.value = chain.length - 1; + onChange(); +}); +canvas.addEventListener("click", () => { + snake = chain.slice(-1)[0]; + chain = [snake]; + inputI.max = chain.length - 1; + i = inputI.value = chain.length - 1; + onChange(); +}); +let i = 0; +const onChange = () => { + ctx.clearRect(0, 0, 9999, 9999); + draw(_sample__WEBPACK_IMPORTED_MODULE_3__.grid, chain[i], []); + chain + .map(_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.snakeToCells) + .flat() + .forEach(({ x, y }) => highlightCell(x, y)); +}; +onChange(); +const inputI = document.createElement("input"); +inputI.type = "range"; +inputI.value = 0; +inputI.max = chain ? chain.length - 1 : 0; +inputI.step = 1; +inputI.min = 0; +inputI.style.width = "90%"; +inputI.style.padding = "20px 0"; +inputI.addEventListener("input", () => { + i = +inputI.value; + onChange(); +}); +document.body.append(inputI); + +})(); + +/******/ })() +; \ No newline at end of file diff --git a/d290bb7f144da7140603.js b/d290bb7f144da7140603.js new file mode 100644 index 000000000..ba42f23e7 --- /dev/null +++ b/d290bb7f144da7140603.js @@ -0,0 +1,968 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "./worker-utils.ts": +/*!*************************!*\ + !*** ./worker-utils.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createRpcClient: () => (/* binding */ createRpcClient), +/* harmony export */ createRpcServer: () => (/* binding */ createRpcServer) +/* harmony export */ }); +const symbol = "worker-rpc__"; +const createRpcServer = (api) => self.addEventListener("message", async (event) => { + var _a; + if (((_a = event.data) === null || _a === void 0 ? void 0 : _a.symbol) === symbol) { + try { + const res = await api[event.data.methodName](...event.data.args); + self.postMessage({ symbol, key: event.data.key, res }); + } + catch (error) { + postMessage({ symbol, key: event.data.key, error: error.message }); + } + } +}); +const createRpcClient = (worker) => { + const originalTerminate = worker.terminate; + worker.terminate = () => { + worker.dispatchEvent(new Event("terminate")); + originalTerminate.call(worker); + }; + return new Proxy({}, { + get: (_, methodName) => (...args) => new Promise((resolve, reject) => { + const key = Math.random().toString(); + const onTerminate = () => { + worker.removeEventListener("terminate", onTerminate); + worker.removeEventListener("message", onMessageHandler); + reject(new Error("worker terminated")); + }; + const onMessageHandler = (event) => { + var _a; + if (((_a = event.data) === null || _a === void 0 ? void 0 : _a.symbol) === symbol && event.data.key === key) { + if (event.data.error) + reject(event.data.error); + else if (event.data.res) + resolve(event.data.res); + worker.removeEventListener("terminate", onTerminate); + worker.removeEventListener("message", onMessageHandler); + } + }; + worker.addEventListener("message", onMessageHandler); + worker.addEventListener("terminate", onTerminate); + worker.postMessage({ symbol, key, methodName, args }); + }), + }); +}; + + +/***/ }), + +/***/ "../solver/clearCleanColoredLayer.ts": +/*!*******************************************!*\ + !*** ../solver/clearCleanColoredLayer.ts ***! + \*******************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ clearCleanColoredLayer: () => (/* binding */ clearCleanColoredLayer), +/* harmony export */ getTunnellablePoints: () => (/* binding */ getTunnellablePoints) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); +/* harmony import */ var _getBestTunnel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./getBestTunnel */ "../solver/getBestTunnel.ts"); +/* harmony import */ var _outside__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./outside */ "../solver/outside.ts"); + + + + + +const clearCleanColoredLayer = (grid, outside, snake0, color) => { + const snakeN = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getSnakeLength)(snake0); + const points = getTunnellablePoints(grid, outside, snakeN, color); + const chain = [snake0]; + while (points.length) { + const path = getPathToNextPoint(grid, chain[0], color, points); + path.pop(); + for (const snake of path) + setEmptySafe(grid, (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake)); + chain.unshift(...path); + } + (0,_outside__WEBPACK_IMPORTED_MODULE_4__.fillOutside)(outside, grid); + chain.pop(); + return chain; +}; +const unwrap = (m) => !m ? [] : [m.snake, ...unwrap(m.parent)]; +const getPathToNextPoint = (grid, snake0, color, points) => { + const closeList = []; + const openList = [{ snake: snake0 }]; + while (openList.length) { + const o = openList.shift(); + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(o.snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(o.snake); + const i = points.findIndex((p) => p.x === x && p.y === y); + if (i >= 0) { + points.splice(i, 1); + return unwrap(o); + } + for (const { x: dx, y: dy } of _snk_types_point__WEBPACK_IMPORTED_MODULE_2__.around4) { + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInsideLarge)(grid, 2, x + dx, y + dy) && + !(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.snakeWillSelfCollide)(o.snake, dx, dy) && + getColorSafe(grid, x + dx, y + dy) <= color) { + const snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.nextSnake)(o.snake, dx, dy); + if (!closeList.some((s0) => (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.snakeEquals)(s0, snake))) { + closeList.push(snake); + openList.push({ snake, parent: o }); + } + } + } + } +}; +/** + * get all cells that are tunnellable + */ +const getTunnellablePoints = (grid, outside, snakeN, color) => { + const points = []; + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + const c = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + if (!(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)(c) && + c <= color && + !points.some((p) => p.x === x && p.y === y)) { + const tunnel = (0,_getBestTunnel__WEBPACK_IMPORTED_MODULE_3__.getBestTunnel)(grid, outside, x, y, color, snakeN); + if (tunnel) + for (const p of tunnel) + if (!isEmptySafe(grid, p.x, p.y)) + points.push(p); + } + } + return points; +}; +const getColorSafe = (grid, x, y) => (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) ? (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) : 0; +const setEmptySafe = (grid, x, y) => { + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y)) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); +}; +const isEmptySafe = (grid, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) && (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y)); + + +/***/ }), + +/***/ "../solver/clearResidualColoredLayer.ts": +/*!**********************************************!*\ + !*** ../solver/clearResidualColoredLayer.ts ***! + \**********************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ clearResidualColoredLayer: () => (/* binding */ clearResidualColoredLayer), +/* harmony export */ getPriority: () => (/* binding */ getPriority), +/* harmony export */ getTunnellablePoints: () => (/* binding */ getTunnellablePoints) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _getBestTunnel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./getBestTunnel */ "../solver/getBestTunnel.ts"); +/* harmony import */ var _outside__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./outside */ "../solver/outside.ts"); +/* harmony import */ var _tunnel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./tunnel */ "../solver/tunnel.ts"); +/* harmony import */ var _getPathTo__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./getPathTo */ "../solver/getPathTo.ts"); + + + + + + +const clearResidualColoredLayer = (grid, outside, snake0, color) => { + const snakeN = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getSnakeLength)(snake0); + const tunnels = getTunnellablePoints(grid, outside, snakeN, color); + // sort + tunnels.sort((a, b) => b.priority - a.priority); + const chain = [snake0]; + while (tunnels.length) { + // get the best next tunnel + let t = getNextTunnel(tunnels, chain[0]); + // goes to the start of the tunnel + chain.unshift(...(0,_getPathTo__WEBPACK_IMPORTED_MODULE_5__.getPathTo)(grid, chain[0], t[0].x, t[0].y)); + // goes to the end of the tunnel + chain.unshift(...(0,_tunnel__WEBPACK_IMPORTED_MODULE_4__.getTunnelPath)(chain[0], t)); + // update grid + for (const { x, y } of t) + setEmptySafe(grid, x, y); + // update outside + (0,_outside__WEBPACK_IMPORTED_MODULE_3__.fillOutside)(outside, grid); + // update tunnels + for (let i = tunnels.length; i--;) + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, tunnels[i].x, tunnels[i].y))) + tunnels.splice(i, 1); + else { + const t = tunnels[i]; + const tunnel = (0,_getBestTunnel__WEBPACK_IMPORTED_MODULE_2__.getBestTunnel)(grid, outside, t.x, t.y, color, snakeN); + if (!tunnel) + tunnels.splice(i, 1); + else { + t.tunnel = tunnel; + t.priority = getPriority(grid, color, tunnel); + } + } + // re-sort + tunnels.sort((a, b) => b.priority - a.priority); + } + chain.pop(); + return chain; +}; +const getNextTunnel = (ts, snake) => { + let minDistance = Infinity; + let closestTunnel = null; + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake); + const priority = ts[0].priority; + for (let i = 0; ts[i] && ts[i].priority === priority; i++) { + const t = ts[i].tunnel; + const d = distanceSq(t[0].x, t[0].y, x, y); + if (d < minDistance) { + minDistance = d; + closestTunnel = t; + } + } + return closestTunnel; +}; +/** + * get all the tunnels for all the cells accessible + */ +const getTunnellablePoints = (grid, outside, snakeN, color) => { + const points = []; + for (let x = grid.width; x--;) + for (let y = grid.height; y--;) { + const c = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y); + if (!(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)(c) && c < color) { + const tunnel = (0,_getBestTunnel__WEBPACK_IMPORTED_MODULE_2__.getBestTunnel)(grid, outside, x, y, color, snakeN); + if (tunnel) { + const priority = getPriority(grid, color, tunnel); + points.push({ x, y, priority, tunnel }); + } + } + } + return points; +}; +/** + * get the score of the tunnel + * prioritize tunnel with maximum color smaller than and with minimum + * with some tweaks + */ +const getPriority = (grid, color, tunnel) => { + let nColor = 0; + let nLess = 0; + for (let i = 0; i < tunnel.length; i++) { + const { x, y } = tunnel[i]; + const c = getColorSafe(grid, x, y); + if (!(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)(c) && i === tunnel.findIndex((p) => p.x === x && p.y === y)) { + if (c === color) + nColor += 1; + else + nLess += color - c; + } + } + if (nColor === 0) + return 99999; + return nLess / nColor; +}; +const distanceSq = (ax, ay, bx, by) => (ax - bx) ** 2 + (ay - by) ** 2; +const getColorSafe = (grid, x, y) => (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) ? (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) : 0; +const setEmptySafe = (grid, x, y) => { + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y)) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); +}; + + +/***/ }), + +/***/ "../solver/getBestRoute.ts": +/*!*********************************!*\ + !*** ../solver/getBestRoute.ts ***! + \*********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getBestRoute: () => (/* binding */ getBestRoute) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _outside__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./outside */ "../solver/outside.ts"); +/* harmony import */ var _clearResidualColoredLayer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./clearResidualColoredLayer */ "../solver/clearResidualColoredLayer.ts"); +/* harmony import */ var _clearCleanColoredLayer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./clearCleanColoredLayer */ "../solver/clearCleanColoredLayer.ts"); + + + + +const getBestRoute = (grid0, snake0) => { + const grid = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.copyGrid)(grid0); + const outside = (0,_outside__WEBPACK_IMPORTED_MODULE_1__.createOutside)(grid); + const chain = [snake0]; + for (const color of extractColors(grid)) { + if (color > 1) + chain.unshift(...(0,_clearResidualColoredLayer__WEBPACK_IMPORTED_MODULE_2__.clearResidualColoredLayer)(grid, outside, chain[0], color)); + chain.unshift(...(0,_clearCleanColoredLayer__WEBPACK_IMPORTED_MODULE_3__.clearCleanColoredLayer)(grid, outside, chain[0], color)); + } + return chain.reverse(); +}; +const extractColors = (grid) => { + // @ts-ignore + let maxColor = Math.max(...grid.data); + return Array.from({ length: maxColor }, (_, i) => (i + 1)); +}; + + +/***/ }), + +/***/ "../solver/getBestTunnel.ts": +/*!**********************************!*\ + !*** ../solver/getBestTunnel.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getBestTunnel: () => (/* binding */ getBestTunnel) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); +/* harmony import */ var _utils_sortPush__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils/sortPush */ "../solver/utils/sortPush.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _outside__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./outside */ "../solver/outside.ts"); +/* harmony import */ var _tunnel__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./tunnel */ "../solver/tunnel.ts"); + + + + + + +const getColorSafe = (grid, x, y) => (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) ? (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) : 0; +const setEmptySafe = (grid, x, y) => { + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y)) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(grid, x, y); +}; +const unwrap = (m) => !m + ? [] + : [...unwrap(m.parent), { x: (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadX)(m.snake), y: (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadY)(m.snake) }]; +/** + * returns the path to reach the outside which contains the least color cell + */ +const getSnakeEscapePath = (grid, outside, snake0, color) => { + const openList = [{ snake: snake0, w: 0 }]; + const closeList = []; + while (openList[0]) { + const o = openList.shift(); + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadX)(o.snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.getHeadY)(o.snake); + if ((0,_outside__WEBPACK_IMPORTED_MODULE_4__.isOutside)(outside, x, y)) + return unwrap(o); + for (const a of _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4) { + const c = getColorSafe(grid, x + a.x, y + a.y); + if (c <= color && !(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.snakeWillSelfCollide)(o.snake, a.x, a.y)) { + const snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.nextSnake)(o.snake, a.x, a.y); + if (!closeList.some((s0) => (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.snakeEquals)(s0, snake))) { + const w = o.w + 1 + +(c === color) * 1000; + (0,_utils_sortPush__WEBPACK_IMPORTED_MODULE_2__.sortPush)(openList, { snake, w, parent: o }, (a, b) => a.w - b.w); + closeList.push(snake); + } + } + } + } + return null; +}; +/** + * compute the best tunnel to get to the cell and back to the outside ( best = less usage of ) + * + * notice that it's one of the best tunnels, more with the same score could exist + */ +const getBestTunnel = (grid, outside, x, y, color, snakeN) => { + const c = { x, y }; + const snake0 = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.createSnakeFromCells)(Array.from({ length: snakeN }, () => c)); + const one = getSnakeEscapePath(grid, outside, snake0, color); + if (!one) + return null; + // get the position of the snake if it was going to leave the x,y cell + const snakeICells = one.slice(0, snakeN); + while (snakeICells.length < snakeN) + snakeICells.push(snakeICells[snakeICells.length - 1]); + const snakeI = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_3__.createSnakeFromCells)(snakeICells); + // remove from the grid the colors that one eat + const gridI = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.copyGrid)(grid); + for (const { x, y } of one) + setEmptySafe(gridI, x, y); + const two = getSnakeEscapePath(gridI, outside, snakeI, color); + if (!two) + return null; + one.shift(); + one.reverse(); + one.push(...two); + (0,_tunnel__WEBPACK_IMPORTED_MODULE_5__.trimTunnelStart)(grid, one); + (0,_tunnel__WEBPACK_IMPORTED_MODULE_5__.trimTunnelEnd)(grid, one); + return one; +}; + + +/***/ }), + +/***/ "../solver/getPathTo.ts": +/*!******************************!*\ + !*** ../solver/getPathTo.ts ***! + \******************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getPathTo: () => (/* binding */ getPathTo) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _utils_sortPush__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./utils/sortPush */ "../solver/utils/sortPush.ts"); + + + + +/** + * starting from snake0, get to the cell x,y + * return the snake chain (reversed) + */ +const getPathTo = (grid, snake0, x, y) => { + const openList = [{ snake: snake0, w: 0 }]; + const closeList = []; + while (openList.length) { + const c = openList.shift(); + const cx = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.getHeadX)(c.snake); + const cy = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.getHeadY)(c.snake); + for (let i = 0; i < _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4.length; i++) { + const { x: dx, y: dy } = _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4[i]; + const nx = cx + dx; + const ny = cy + dy; + if (nx === x && ny === y) { + // unwrap + const path = [(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.nextSnake)(c.snake, dx, dy)]; + let e = c; + while (e.parent) { + path.push(e.snake); + e = e.parent; + } + return path; + } + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInsideLarge)(grid, 2, nx, ny) && + !(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.snakeWillSelfCollide)(c.snake, dx, dy) && + (!(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, nx, ny) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, nx, ny)))) { + const nsnake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.nextSnake)(c.snake, dx, dy); + if (!closeList.some((s) => (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_2__.snakeEquals)(nsnake, s))) { + const w = c.w + 1; + const h = Math.abs(nx - x) + Math.abs(ny - y); + const f = w + h; + const o = { snake: nsnake, parent: c, w, h, f }; + (0,_utils_sortPush__WEBPACK_IMPORTED_MODULE_3__.sortPush)(openList, o, (a, b) => a.f - b.f); + closeList.push(nsnake); + } + } + } + } +}; + + +/***/ }), + +/***/ "../solver/getPathToPose.ts": +/*!**********************************!*\ + !*** ../solver/getPathToPose.ts ***! + \**********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getPathToPose: () => (/* binding */ getPathToPose) +/* harmony export */ }); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _tunnel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./tunnel */ "../solver/tunnel.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); +/* harmony import */ var _utils_sortPush__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./utils/sortPush */ "../solver/utils/sortPush.ts"); + + + + + +const isEmptySafe = (grid, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_1__.isInside)(grid, x, y) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_1__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_1__.getColor)(grid, x, y)); +const getPathToPose = (snake0, target, grid) => { + if ((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.snakeEquals)(snake0, target)) + return []; + const targetCells = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.snakeToCells)(target).reverse(); + const snakeN = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getSnakeLength)(snake0); + const box = { + min: { + x: Math.min((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(snake0), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(target)) - snakeN - 1, + y: Math.min((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(snake0), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(target)) - snakeN - 1, + }, + max: { + x: Math.max((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(snake0), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(target)) + snakeN + 1, + y: Math.max((0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(snake0), (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(target)) + snakeN + 1, + }, + }; + const [t0, ...forbidden] = targetCells; + forbidden.slice(0, 3); + const openList = [{ snake: snake0, w: 0 }]; + const closeList = []; + while (openList.length) { + const o = openList.shift(); + const x = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadX)(o.snake); + const y = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.getHeadY)(o.snake); + if (x === t0.x && y === t0.y) { + const path = []; + let e = o; + while (e) { + path.push(e.snake); + e = e.parent; + } + path.unshift(...(0,_tunnel__WEBPACK_IMPORTED_MODULE_2__.getTunnelPath)(path[0], targetCells)); + path.pop(); + path.reverse(); + return path; + } + for (let i = 0; i < _snk_types_point__WEBPACK_IMPORTED_MODULE_3__.around4.length; i++) { + const { x: dx, y: dy } = _snk_types_point__WEBPACK_IMPORTED_MODULE_3__.around4[i]; + const nx = x + dx; + const ny = y + dy; + if (!(0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.snakeWillSelfCollide)(o.snake, dx, dy) && + (!grid || isEmptySafe(grid, nx, ny)) && + (grid + ? (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_1__.isInsideLarge)(grid, 2, nx, ny) + : box.min.x <= nx && + nx <= box.max.x && + box.min.y <= ny && + ny <= box.max.y) && + !forbidden.some((p) => p.x === nx && p.y === ny)) { + const snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.nextSnake)(o.snake, dx, dy); + if (!closeList.some((s) => (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_0__.snakeEquals)(snake, s))) { + const w = o.w + 1; + const h = Math.abs(nx - x) + Math.abs(ny - y); + const f = w + h; + (0,_utils_sortPush__WEBPACK_IMPORTED_MODULE_4__.sortPush)(openList, { f, w, snake, parent: o }, (a, b) => a.f - b.f); + closeList.push(snake); + } + } + } + } +}; + + +/***/ }), + +/***/ "../solver/outside.ts": +/*!****************************!*\ + !*** ../solver/outside.ts ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createOutside: () => (/* binding */ createOutside), +/* harmony export */ fillOutside: () => (/* binding */ fillOutside), +/* harmony export */ isOutside: () => (/* binding */ isOutside) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_point__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/point */ "../types/point.ts"); + + +const createOutside = (grid, color = 0) => { + const outside = (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.createEmptyGrid)(grid.width, grid.height); + for (let x = outside.width; x--;) + for (let y = outside.height; y--;) + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColor)(outside, x, y, 1); + fillOutside(outside, grid, color); + return outside; +}; +const fillOutside = (outside, grid, color = 0) => { + let changed = true; + while (changed) { + changed = false; + for (let x = outside.width; x--;) + for (let y = outside.height; y--;) + if ((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y) <= color && + !isOutside(outside, x, y) && + _snk_types_point__WEBPACK_IMPORTED_MODULE_1__.around4.some((a) => isOutside(outside, x + a.x, y + a.y))) { + changed = true; + (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.setColorEmpty)(outside, x, y); + } + } + return outside; +}; +const isOutside = (outside, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(outside, x, y) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(outside, x, y)); + + +/***/ }), + +/***/ "../solver/tunnel.ts": +/*!***************************!*\ + !*** ../solver/tunnel.ts ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getTunnelPath: () => (/* binding */ getTunnelPath), +/* harmony export */ trimTunnelEnd: () => (/* binding */ trimTunnelEnd), +/* harmony export */ trimTunnelStart: () => (/* binding */ trimTunnelStart), +/* harmony export */ updateTunnel: () => (/* binding */ updateTunnel) +/* harmony export */ }); +/* harmony import */ var _snk_types_grid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/types/grid */ "../types/grid.ts"); +/* harmony import */ var _snk_types_snake__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/types/snake */ "../types/snake.ts"); + + +/** + * get the sequence of snake to cross the tunnel + */ +const getTunnelPath = (snake0, tunnel) => { + const chain = []; + let snake = snake0; + for (let i = 1; i < tunnel.length; i++) { + const dx = tunnel[i].x - (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadX)(snake); + const dy = tunnel[i].y - (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.getHeadY)(snake); + snake = (0,_snk_types_snake__WEBPACK_IMPORTED_MODULE_1__.nextSnake)(snake, dx, dy); + chain.unshift(snake); + } + return chain; +}; +/** + * assuming the grid change and the colors got deleted, update the tunnel + */ +const updateTunnel = (grid, tunnel, toDelete) => { + while (tunnel.length) { + const { x, y } = tunnel[0]; + if (isEmptySafe(grid, x, y) || + toDelete.some((p) => p.x === x && p.y === y)) { + tunnel.shift(); + } + else + break; + } + while (tunnel.length) { + const { x, y } = tunnel[tunnel.length - 1]; + if (isEmptySafe(grid, x, y) || + toDelete.some((p) => p.x === x && p.y === y)) { + tunnel.pop(); + } + else + break; + } +}; +const isEmptySafe = (grid, x, y) => !(0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isInside)(grid, x, y) || (0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.isEmpty)((0,_snk_types_grid__WEBPACK_IMPORTED_MODULE_0__.getColor)(grid, x, y)); +/** + * remove empty cell from start + */ +const trimTunnelStart = (grid, tunnel) => { + while (tunnel.length) { + const { x, y } = tunnel[0]; + if (isEmptySafe(grid, x, y)) + tunnel.shift(); + else + break; + } +}; +/** + * remove empty cell from end + */ +const trimTunnelEnd = (grid, tunnel) => { + while (tunnel.length) { + const i = tunnel.length - 1; + const { x, y } = tunnel[i]; + if (isEmptySafe(grid, x, y) || + tunnel.findIndex((p) => p.x === x && p.y === y) < i) + tunnel.pop(); + else + break; + } +}; + + +/***/ }), + +/***/ "../solver/utils/sortPush.ts": +/*!***********************************!*\ + !*** ../solver/utils/sortPush.ts ***! + \***********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ sortPush: () => (/* binding */ sortPush) +/* harmony export */ }); +const sortPush = (arr, x, sortFn) => { + let a = 0; + let b = arr.length; + if (arr.length === 0 || sortFn(x, arr[a]) <= 0) { + arr.unshift(x); + return; + } + while (b - a > 1) { + const e = Math.ceil((a + b) / 2); + const s = sortFn(x, arr[e]); + if (s === 0) + a = b = e; + else if (s > 0) + a = e; + else + b = e; + } + const e = Math.ceil((a + b) / 2); + arr.splice(e, 0, x); +}; + + +/***/ }), + +/***/ "../types/__fixtures__/snake.ts": +/*!**************************************!*\ + !*** ../types/__fixtures__/snake.ts ***! + \**************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ snake1: () => (/* binding */ snake1), +/* harmony export */ snake3: () => (/* binding */ snake3), +/* harmony export */ snake4: () => (/* binding */ snake4), +/* harmony export */ snake5: () => (/* binding */ snake5), +/* harmony export */ snake9: () => (/* binding */ snake9) +/* harmony export */ }); +/* harmony import */ var _snake__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../snake */ "../types/snake.ts"); + +const create = (length) => (0,_snake__WEBPACK_IMPORTED_MODULE_0__.createSnakeFromCells)(Array.from({ length }, (_, i) => ({ x: i, y: -1 }))); +const snake1 = create(1); +const snake3 = create(3); +const snake4 = create(4); +const snake5 = create(5); +const snake9 = create(9); + + +/***/ }), + +/***/ "../types/grid.ts": +/*!************************!*\ + !*** ../types/grid.ts ***! + \************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copyGrid: () => (/* binding */ copyGrid), +/* harmony export */ createEmptyGrid: () => (/* binding */ createEmptyGrid), +/* harmony export */ getColor: () => (/* binding */ getColor), +/* harmony export */ gridEquals: () => (/* binding */ gridEquals), +/* harmony export */ isEmpty: () => (/* binding */ isEmpty), +/* harmony export */ isGridEmpty: () => (/* binding */ isGridEmpty), +/* harmony export */ isInside: () => (/* binding */ isInside), +/* harmony export */ isInsideLarge: () => (/* binding */ isInsideLarge), +/* harmony export */ setColor: () => (/* binding */ setColor), +/* harmony export */ setColorEmpty: () => (/* binding */ setColorEmpty) +/* harmony export */ }); +const isInside = (grid, x, y) => x >= 0 && y >= 0 && x < grid.width && y < grid.height; +const isInsideLarge = (grid, m, x, y) => x >= -m && y >= -m && x < grid.width + m && y < grid.height + m; +const copyGrid = ({ width, height, data }) => ({ + width, + height, + data: Uint8Array.from(data), +}); +const getIndex = (grid, x, y) => x * grid.height + y; +const getColor = (grid, x, y) => grid.data[getIndex(grid, x, y)]; +const isEmpty = (color) => color === 0; +const setColor = (grid, x, y, color) => { + grid.data[getIndex(grid, x, y)] = color || 0; +}; +const setColorEmpty = (grid, x, y) => { + setColor(grid, x, y, 0); +}; +/** + * return true if the grid is empty + */ +const isGridEmpty = (grid) => grid.data.every((x) => x === 0); +const gridEquals = (a, b) => a.data.every((_, i) => a.data[i] === b.data[i]); +const createEmptyGrid = (width, height) => ({ + width, + height, + data: new Uint8Array(width * height), +}); + + +/***/ }), + +/***/ "../types/point.ts": +/*!*************************!*\ + !*** ../types/point.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ around4: () => (/* binding */ around4), +/* harmony export */ pointEquals: () => (/* binding */ pointEquals) +/* harmony export */ }); +const around4 = [ + { x: 1, y: 0 }, + { x: 0, y: -1 }, + { x: -1, y: 0 }, + { x: 0, y: 1 }, +]; +const pointEquals = (a, b) => a.x === b.x && a.y === b.y; + + +/***/ }), + +/***/ "../types/snake.ts": +/*!*************************!*\ + !*** ../types/snake.ts ***! + \*************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ copySnake: () => (/* binding */ copySnake), +/* harmony export */ createSnakeFromCells: () => (/* binding */ createSnakeFromCells), +/* harmony export */ getHeadX: () => (/* binding */ getHeadX), +/* harmony export */ getHeadY: () => (/* binding */ getHeadY), +/* harmony export */ getSnakeLength: () => (/* binding */ getSnakeLength), +/* harmony export */ nextSnake: () => (/* binding */ nextSnake), +/* harmony export */ snakeEquals: () => (/* binding */ snakeEquals), +/* harmony export */ snakeToCells: () => (/* binding */ snakeToCells), +/* harmony export */ snakeWillSelfCollide: () => (/* binding */ snakeWillSelfCollide) +/* harmony export */ }); +const getHeadX = (snake) => snake[0] - 2; +const getHeadY = (snake) => snake[1] - 2; +const getSnakeLength = (snake) => snake.length / 2; +const copySnake = (snake) => snake.slice(); +const snakeEquals = (a, b) => { + for (let i = 0; i < a.length; i++) + if (a[i] !== b[i]) + return false; + return true; +}; +/** + * return a copy of the next snake, considering that dx, dy is the direction + */ +const nextSnake = (snake, dx, dy) => { + const copy = new Uint8Array(snake.length); + for (let i = 2; i < snake.length; i++) + copy[i] = snake[i - 2]; + copy[0] = snake[0] + dx; + copy[1] = snake[1] + dy; + return copy; +}; +/** + * return true if the next snake will collide with itself + */ +const snakeWillSelfCollide = (snake, dx, dy) => { + const nx = snake[0] + dx; + const ny = snake[1] + dy; + for (let i = 2; i < snake.length - 2; i += 2) + if (snake[i + 0] === nx && snake[i + 1] === ny) + return true; + return false; +}; +const snakeToCells = (snake) => Array.from({ length: snake.length / 2 }, (_, i) => ({ + x: snake[i * 2 + 0] - 2, + y: snake[i * 2 + 1] - 2, +})); +const createSnakeFromCells = (points) => { + const snake = new Uint8Array(points.length * 2); + for (let i = points.length; i--;) { + snake[i * 2 + 0] = points[i].x + 2; + snake[i * 2 + 1] = points[i].y + 2; + } + return snake; +}; + + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +/*!************************************!*\ + !*** ./demo.interactive.worker.ts ***! + \************************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _snk_solver_getBestRoute__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @snk/solver/getBestRoute */ "../solver/getBestRoute.ts"); +/* harmony import */ var _snk_solver_getPathToPose__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @snk/solver/getPathToPose */ "../solver/getPathToPose.ts"); +/* harmony import */ var _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @snk/types/__fixtures__/snake */ "../types/__fixtures__/snake.ts"); +/* harmony import */ var _worker_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./worker-utils */ "./worker-utils.ts"); + + + + +const getChain = (grid) => { + const chain = (0,_snk_solver_getBestRoute__WEBPACK_IMPORTED_MODULE_0__.getBestRoute)(grid, _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__.snake4); + chain.push(...(0,_snk_solver_getPathToPose__WEBPACK_IMPORTED_MODULE_1__.getPathToPose)(chain.slice(-1)[0], _snk_types_fixtures_snake__WEBPACK_IMPORTED_MODULE_2__.snake4)); + return chain; +}; +const api = { getChain }; +(0,_worker_utils__WEBPACK_IMPORTED_MODULE_3__.createRpcServer)(api); + +})(); + +/******/ })() +; \ No newline at end of file diff --git a/getBestRoute.html b/getBestRoute.html new file mode 100644 index 000000000..85aed7c58 --- /dev/null +++ b/getBestRoute.html @@ -0,0 +1,9 @@ + + + + + snk - getBestRoute + + + + \ No newline at end of file diff --git a/getBestTunnel.html b/getBestTunnel.html new file mode 100644 index 000000000..d9e9d189a --- /dev/null +++ b/getBestTunnel.html @@ -0,0 +1,9 @@ + + + + + snk - getBestTunnel + + + + \ No newline at end of file diff --git a/getPathTo.html b/getPathTo.html new file mode 100644 index 000000000..2d5dcf861 --- /dev/null +++ b/getPathTo.html @@ -0,0 +1,9 @@ + + + + + snk - getPathTo + + + + \ No newline at end of file diff --git a/getPathToPose.html b/getPathToPose.html new file mode 100644 index 000000000..d8c4078c6 --- /dev/null +++ b/getPathToPose.html @@ -0,0 +1,9 @@ + + + + + snk - getPathToPose + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 000000000..986d85015 --- /dev/null +++ b/index.html @@ -0,0 +1,9 @@ + + + + + snk - interactive + + + + \ No newline at end of file diff --git a/interactive.html b/interactive.html new file mode 100644 index 000000000..986d85015 --- /dev/null +++ b/interactive.html @@ -0,0 +1,9 @@ + + + + + snk - interactive + + + + \ No newline at end of file diff --git a/outside.html b/outside.html new file mode 100644 index 000000000..f509ae39e --- /dev/null +++ b/outside.html @@ -0,0 +1,9 @@ + + + + + snk - outside + + + + \ No newline at end of file diff --git a/svg.html b/svg.html new file mode 100644 index 000000000..14e4f6ef2 --- /dev/null +++ b/svg.html @@ -0,0 +1,9 @@ + + + + + snk - svg + + + + \ No newline at end of file