function createPanelCursor(divElement) { "use strict"; var cursor = createCanvas(0, 0); cursor.classList.add("cursor"); divElement.appendChild(cursor); function show() { cursor.style.display = "block"; } function hide() { cursor.style.display = "none"; } function resize(width, height) { cursor.style.width = width + "px"; cursor.style.height = height + "px"; } function setPos(x, y) { cursor.style.left = x - 1 + "px"; cursor.style.top = y - 1 + "px"; } return { "show": show, "hide": hide, "resize": resize, "setPos": setPos }; } function createFloatingPanelPalette(width, height) { "use strict"; var canvasContainer = document.createElement("DIV"); var cursor = createPanelCursor(canvasContainer); var canvas = createCanvas(width, height); canvasContainer.appendChild(canvas); var ctx = canvas.getContext("2d"); var imageData = new Array(16); function generateSwatch(colour) { imageData[colour] = ctx.createImageData(width / 8, height / 2); var rgba = palette.getRGBAColour(colour); for (var y = 0, i = 0; y < imageData[colour].height; y++) { for (var x = 0; x < imageData[colour].width; x++, i += 4) { imageData[colour].data.set(rgba, i); } } } function generateSwatches() { for (var colour = 0; colour < 16; colour++) { generateSwatch(colour); } } function redrawSwatch(colour) { ctx.putImageData(imageData[colour], (colour % 8) * (width / 8), (colour > 7) ? 0 : (height / 2)); } function redrawSwatches() { for (var colour = 0; colour < 16; colour++) { redrawSwatch(colour); } } function mouseDown(evt) { var rect = canvas.getBoundingClientRect(); var mouseX = evt.clientX - rect.left; var mouseY = evt.clientY - rect.top; var colour = Math.floor(mouseX / (width / 8)) + ((mouseY < (height / 2)) ? 8 : 0); if (evt.ctrlKey === false && evt.which != 3) { palette.setForegroundColour(colour); } else { palette.setBackgroundColour(colour); } } function updateColour(colour) { generateSwatch(colour); redrawSwatch(colour); } function updatePalette() { for (var colour = 0; colour < 16; colour++) { updateColour(colour); } } function getElement() { return canvasContainer; } function updateCursor(colour) { cursor.resize(width / 8, height / 2); cursor.setPos((colour % 8) * (width / 8), (colour > 7) ? 0 : (height / 2)); } function onForegroundChange(evt) { updateCursor(evt.detail); } function resize(newWidth, newHeight) { width = newWidth; height = newHeight; canvas.width = width; canvas.height = height; generateSwatches(); redrawSwatches(); updateCursor(palette.getForegroundColour()); } generateSwatches(); redrawSwatches(); updateCursor(palette.getForegroundColour()); canvas.addEventListener("mousedown", mouseDown); canvas.addEventListener("contextmenu", (evt) => { evt.preventDefault(); }); document.addEventListener("onForegroundChange", onForegroundChange); return { "updateColour": updateColour, "updatePalette": updatePalette, "getElement": getElement, "showCursor": cursor.show, "hideCursor": cursor.hide, "resize": resize }; } function createFloatingPanel(x, y) { "use strict"; var panel = document.createElement("DIV"); panel.classList.add("floating-panel"); $("body-container").appendChild(panel); var enabled = false; var prev; function setPos(newX, newY) { panel.style.left = newX + "px"; x = newX; panel.style.top = newY + "px"; y = newY; } function mousedown(evt) { prev = [evt.clientX, evt.clientY]; } function touchMove(evt) { if (evt.which === 1 && prev !== undefined) { evt.preventDefault(); evt.stopPropagation(); var rect = panel.getBoundingClientRect(); setPos(rect.left + (evt.touches[0].pageX - prev[0]), rect.top + (evt.touches[0].pageY - prev[1])); prev = [evt.touches[0].pageX, evt.touches[0].pageY]; } } function mouseMove(evt) { if (evt.which === 1 && prev !== undefined) { evt.preventDefault(); evt.stopPropagation(); var rect = panel.getBoundingClientRect(); setPos(rect.left + (evt.clientX - prev[0]), rect.top + (evt.clientY - prev[1])); prev = [evt.clientX, evt.clientY]; } } function mouseUp() { prev = undefined; } function enable() { panel.classList.add("enabled"); enabled = true; document.addEventListener("touchmove", touchMove); document.addEventListener("mousemove", mouseMove); document.addEventListener("mouseup", mouseUp); } function disable() { panel.classList.remove("enabled"); enabled = false; document.removeEventListener("touchmove", touchMove); document.removeEventListener("mousemove", mouseMove); document.removeEventListener("mouseup", mouseUp); } function append(element) { panel.appendChild(element); } setPos(x, y); panel.addEventListener("mousedown", mousedown); return { "setPos": setPos, "enable": enable, "disable": disable, "append": append }; } function createFreehandController(panel) { "use strict"; var prev = {}; var drawMode; function line(x0, y0, x1, y1, callback) { var dx = Math.abs(x1 - x0); var sx = (x0 < x1) ? 1 : -1; var dy = Math.abs(y1 - y0); var sy = (y0 < y1) ? 1 : -1; var err = ((dx > dy) ? dx : -dy) / 2; var e2; while (true) { callback(x0, y0); if (x0 === x1 && y0 === y1) { break; } e2 = err; if (e2 > -dx) { err -= dy; x0 += sx; } if (e2 < dy) { err += dx; y0 += sy; } } } function draw(coords) { if (prev.x !== coords.x || prev.y !== coords.y || prev.halfBlockY !== coords.halfBlockY) { if (drawMode.halfBlockMode === true) { var colour = (coords.leftMouseButton === true) ? palette.getForegroundColour() : palette.getBackgroundColour(); if (Math.abs(prev.x - coords.x) > 1 || Math.abs(prev.halfBlockY - coords.halfBlockY) > 1) { textArtCanvas.drawHalfBlock((callback) => { line(prev.x, prev.halfBlockY, coords.x, coords.halfBlockY, (x, y) => { callback(colour, x, y); }); }); } else { textArtCanvas.drawHalfBlock((callback) => { callback(colour, coords.x, coords.halfBlockY); }); } } else { if (Math.abs(prev.x - coords.x) > 1 || Math.abs(prev.y - coords.y) > 1) { textArtCanvas.draw((callback) => { line(prev.x, prev.y, coords.x, coords.y, (x, y) => { callback(drawMode.charCode, drawMode.foreground, drawMode.background, x, y); }); }, false); } else { textArtCanvas.draw((callback) => { callback(drawMode.charCode, drawMode.foreground, drawMode.background, coords.x, coords.y); }, false); } } positionInfo.update(coords.x, coords.y); prev = coords; } } function canvasUp() { prev = {}; } function canvasDown(evt) { drawMode = panel.getMode(); textArtCanvas.startUndo(); draw(evt.detail); } function canvasDrag(evt) { draw(evt.detail); } function enable() { document.addEventListener("onTextCanvasDown", canvasDown); document.addEventListener("onTextCanvasUp", canvasUp); document.addEventListener("onTextCanvasDrag", canvasDrag); panel.enable(); } function disable() { document.removeEventListener("onTextCanvasDown", canvasDown); document.removeEventListener("onTextCanvasUp", canvasUp); document.removeEventListener("onTextCanvasDrag", canvasDrag); panel.disable(); } return { "enable": enable, "disable": disable, "select": panel.select, "ignore": panel.ignore, "unignore": panel.unignore }; } function createShadingPanel() { "use strict"; var panelWidth = font.getWidth() * 20; var panel = createFloatingPanel(50, 30); var palettePanel = createFloatingPanelPalette(panelWidth, 40); var canvasContainer = document.createElement("div"); var cursor = createPanelCursor(canvasContainer); var canvases = new Array(16); var halfBlockMode = true; var x = 0; var y = 0; var ignored = false; function updateCursor() { var width = canvases[0].width / 5; var height = canvases[0].height / 15; cursor.resize(width, height); cursor.setPos(x * width, y * height); } function mouseDownGenerator(colour) { return function (evt) { var rect = canvases[colour].getBoundingClientRect(); var mouseX = evt.clientX - rect.left; var mouseY = evt.clientY - rect.top; halfBlockMode = false; x = Math.floor(mouseX / (canvases[colour].width / 5)); y = Math.floor(mouseY / (canvases[colour].height / 15)); palettePanel.hideCursor(); updateCursor(); cursor.show(); }; } function generateCanvases() { var fontHeight = font.getHeight(); for (var foreground = 0; foreground < 16; foreground++) { var canvas = createCanvas(panelWidth, fontHeight * 15); var ctx = canvas.getContext("2d"); var y = 0; for (var background = 0; background < 8; background++) { if (foreground !== background) { for (var i = 0; i < 4; i++) { font.draw(219, foreground, background, ctx, i, y); } for (var i = 4; i < 8; i++) { font.draw(178, foreground, background, ctx, i, y); } for (var i = 8; i < 12; i++) { font.draw(177, foreground, background, ctx, i, y); } for (var i = 12; i < 16; i++) { font.draw(176, foreground, background, ctx, i, y); } for (var i = 16; i < 20; i++) { font.draw(0, foreground, background, ctx, i, y); } y += 1; } } for (var background = 8; background < 16; background++) { if (foreground !== background) { for (var i = 0; i < 4; i++) { font.draw(219, foreground, background, ctx, i, y); } for (var i = 4; i < 8; i++) { font.draw(178, foreground, background, ctx, i, y); } for (var i = 8; i < 12; i++) { font.draw(177, foreground, background, ctx, i, y); } for (var i = 12; i < 16; i++) { font.draw(176, foreground, background, ctx, i, y); } for (var i = 16; i < 20; i++) { font.draw(0, foreground, background, ctx, i, y); } y += 1; } } canvas.addEventListener("mousedown", mouseDownGenerator(foreground)); canvases[foreground] = canvas; } } function keyDown(evt) { if (ignored === false) { var keyCode = (evt.keyCode || evt.which); if (halfBlockMode === false) { switch(keyCode) { case 37: evt.preventDefault(); x = Math.max(x - 1, 0); updateCursor(); break; case 38: evt.preventDefault(); y = Math.max(y - 1, 0); updateCursor(); break; case 39: evt.preventDefault(); x = Math.min(x + 1, 4); updateCursor(); break; case 40: evt.preventDefault(); y = Math.min(y + 1, 14); updateCursor(); break; default: break; } } else if (keyCode >= 37 && keyCode <= 40) { evt.preventDefault(); halfBlockMode = false; palettePanel.hideCursor(); cursor.show(); } } } function enable() { document.addEventListener("keydown", keyDown); panel.enable(); } function disable() { document.removeEventListener("keydown", keyDown); panel.disable(); } function ignore() { ignored = true; } function unignore() { ignored = false; } function getMode() { var charCode = 0; switch(x) { case 0: charCode = 219; break; case 1: charCode = 178; break; case 2: charCode = 177; break; case 3: charCode = 176; break; case 4: charCode = 0; break; default: break; } var foreground = palette.getForegroundColour(); var background = y; if (y >= foreground) { background += 1; } return { "halfBlockMode": halfBlockMode, "foreground": foreground, "background": background, "charCode": charCode }; } function foregroundChange(evt) { canvasContainer.removeChild(canvasContainer.firstChild); canvasContainer.insertBefore(canvases[evt.detail], canvasContainer.firstChild); palettePanel.showCursor(); cursor.hide(); halfBlockMode = true; } function fontChange() { panelWidth = font.getWidth() * 20; palettePanel.resize(panelWidth, 40); generateCanvases(); updateCursor(); canvasContainer.removeChild(canvasContainer.firstChild); canvasContainer.insertBefore(canvases[palette.getForegroundColour()], canvasContainer.firstChild); } function select(charCode) { halfBlockMode = false; x = 3 - (charCode - 176); y = palette.getBackgroundColour(); if (y > palette.getForegroundColour()) { y -= 1; } palettePanel.hideCursor(); updateCursor(); cursor.show(); } document.addEventListener("onForegroundChange", foregroundChange); document.addEventListener("onLetterSpacingChange", fontChange); document.addEventListener("onFontChange", fontChange); palettePanel.showCursor(); panel.append(palettePanel.getElement()); generateCanvases(); updateCursor(); canvasContainer.insertBefore(canvases[palette.getForegroundColour()], canvasContainer.firstChild); panel.append(canvasContainer); cursor.hide(); return { "enable": enable, "disable": disable, "getMode": getMode, "select": select, "ignore": ignore, "unignore": unignore }; } function createCharacterBrushPanel() { "use strict"; var panelWidth = font.getWidth() * 16; var panel = createFloatingPanel(50, 30); var palettePanel = createFloatingPanelPalette(panelWidth, 40); var canvasContainer = document.createElement("div"); var cursor = createPanelCursor(canvasContainer); var canvas = createCanvas(panelWidth, font.getHeight() * 16); var ctx = canvas.getContext("2d"); var x = 0; var y = 0; var ignored = false; function updateCursor() { var width = canvas.width / 16; var height = canvas.height / 16; cursor.resize(width, height); cursor.setPos(x * width, y * height); } function redrawCanvas() { var foreground = palette.getForegroundColour(); var background = palette.getBackgroundColour(); for (var y = 0, charCode = 0; y < 16; y++) { for (var x = 0; x < 16; x++, charCode++) { font.draw(charCode, foreground, background, ctx, x, y); } } } function keyDown(evt) { if (ignored === false) { var keyCode = (evt.keyCode || evt.which); switch(keyCode) { case 37: evt.preventDefault(); x = Math.max(x - 1, 0); updateCursor(); break; case 38: evt.preventDefault(); y = Math.max(y - 1, 0); updateCursor(); break; case 39: evt.preventDefault(); x = Math.min(x + 1, 15); updateCursor(); break; case 40: evt.preventDefault(); y = Math.min(y + 1, 15); updateCursor(); break; default: break; } } } function enable() { document.addEventListener("keydown", keyDown); panel.enable(); } function disable() { document.removeEventListener("keydown", keyDown); panel.disable(); } function getMode() { var charCode = y * 16 + x; return { "halfBlockMode": false, "foreground": palette.getForegroundColour(), "background": palette.getBackgroundColour(), "charCode": charCode }; } function resizeCanvas() { panelWidth = font.getWidth() * 16; palettePanel.resize(panelWidth, 40); canvas.width = panelWidth; canvas.height = font.getHeight() * 16; redrawCanvas(); updateCursor(); } function mouseDown(evt) { var rect = canvas.getBoundingClientRect(); var mouseX = evt.clientX - rect.left; var mouseY = evt.clientY - rect.top; x = Math.floor(mouseX / (canvas.width / 16)); y = Math.floor(mouseY / (canvas.height / 16)); updateCursor(); } function select(charCode) { x = charCode % 16; y = Math.floor(charCode / 16); updateCursor(); } function ignore() { ignored = true; } function unignore() { ignored = false; } document.addEventListener("onForegroundChange", redrawCanvas); document.addEventListener("onBackgroundChange", redrawCanvas); document.addEventListener("onLetterSpacingChange", resizeCanvas); document.addEventListener("onFontChange", resizeCanvas); canvas.addEventListener("mousedown", mouseDown); panel.append(palettePanel.getElement()); updateCursor(); cursor.show(); canvasContainer.appendChild(canvas); panel.append(canvasContainer); redrawCanvas(); return { "enable": enable, "disable": disable, "getMode": getMode, "select": select, "ignore": ignore, "unignore": unignore }; } function createFillController() { "use strict"; function fillPoint(evt) { var block = textArtCanvas.getHalfBlock(evt.detail.x, evt.detail.halfBlockY); if (block.isBlocky) { var targetColour = (block.halfBlockY === 0) ? block.upperBlockColour : block.lowerBlockColour; var fillColour = palette.getForegroundColour(); if (targetColour !== fillColour) { var columns = textArtCanvas.getColumns(); var rows = textArtCanvas.getRows(); var coord = [evt.detail.x, evt.detail.halfBlockY]; var queue = [coord]; textArtCanvas.startUndo(); textArtCanvas.drawHalfBlock((callback) => { while (queue.length !== 0) { coord = queue.pop(); block = textArtCanvas.getHalfBlock(coord[0], coord[1]); if (block.isBlocky && (((block.halfBlockY === 0) && (block.upperBlockColour === targetColour)) || ((block.halfBlockY === 1) && (block.lowerBlockColour === targetColour)))) { callback(fillColour, coord[0], coord[1]); if (coord[0] > 0) { queue.push([coord[0] - 1, coord[1], 0]); } if (coord[0] < columns - 1) { queue.push([coord[0] + 1, coord[1], 1]); } if (coord[1] > 0) { queue.push([coord[0], coord[1] - 1, 2]); } if (coord[1] < rows * 2 - 1) { queue.push([coord[0], coord[1] + 1, 3]); } } else if (block.isVerticalBlocky) { if (coord[2] !== 0 && block.leftBlockColour === targetColour) { textArtCanvas.draw(function (callback) { callback(221, fillColour, block.rightBlockColour, coord[0], block.textY); }, true); if (coord[0] > 0) { queue.push([coord[0] - 1, coord[1], 0]); } if (coord[1] > 2) { if (block.halfBlockY === 1) { queue.push([coord[0], coord[1] - 2, 2]); } else { queue.push([coord[0], coord[1] - 1, 2]); } } if (coord[1] < rows * 2 - 2) { if (block.halfBlockY === 1) { queue.push([coord[0], coord[1] + 1, 3]); } else { queue.push([coord[0], coord[1] + 2, 3]); } } } if (coord[2] !== 1 && block.rightBlockColour === targetColour) { textArtCanvas.draw(function (callback) { callback(222, fillColour, block.leftBlockColour, coord[0], block.textY); }, true); if (coord[0] > 0) { queue.push([coord[0] - 1, coord[1], 0]); } if (coord[1] > 2) { if (block.halfBlockY === 1) { queue.push([coord[0], coord[1] - 2, 2]); } else { queue.push([coord[0], coord[1] - 1, 2]); } } if (coord[1] < rows * 2 - 2) { if (block.halfBlockY === 1) { queue.push([coord[0], coord[1] + 1, 3]); } else { queue.push([coord[0], coord[1] + 2, 3]); } } } } } }); } } } function enable() { document.addEventListener("onTextCanvasDown", fillPoint); } function disable() { document.removeEventListener("onTextCanvasDown", fillPoint); } return { "enable": enable, "disable": disable }; } function createLineController() { "use strict"; var startXY; var endXY; function canvasDown(evt) { startXY = evt.detail; } function line(x0, y0, x1, y1, callback) { var dx = Math.abs(x1 - x0); var sx = (x0 < x1) ? 1 : -1; var dy = Math.abs(y1 - y0); var sy = (y0 < y1) ? 1 : -1; var err = ((dx > dy) ? dx : -dy) / 2; var e2; while (true) { callback(x0, y0); if (x0 === x1 && y0 === y1) { break; } e2 = err; if (e2 > -dx) { err -= dy; x0 += sx; } if (e2 < dy) { err += dx; y0 += sy; } } } function canvasUp() { toolPreview.clear(); var foreground = palette.getForegroundColour(); textArtCanvas.startUndo(); textArtCanvas.drawHalfBlock((draw) => { line(startXY.x, startXY.halfBlockY, endXY.x, endXY.halfBlockY, function (lineX, lineY) { draw(foreground, lineX, lineY); }); }); startXY = undefined; endXY = undefined; } function canvasDrag(evt) { if (startXY !== undefined) { if (endXY === undefined || (evt.detail.x !== endXY.x || evt.detail.y !== endXY.y || evt.detail.halfBlockY !== endXY.halfBlockY)) { if (endXY !== undefined) { toolPreview.clear(); } endXY = evt.detail; var foreground = palette.getForegroundColour(); line(startXY.x, startXY.halfBlockY, endXY.x, endXY.halfBlockY, function (lineX, lineY) { toolPreview.drawHalfBlock(foreground, lineX, lineY); }); } } } function enable() { document.addEventListener("onTextCanvasDown", canvasDown); document.addEventListener("onTextCanvasUp", canvasUp); document.addEventListener("onTextCanvasDrag", canvasDrag); } function disable() { document.removeEventListener("onTextCanvasDown", canvasDown); document.removeEventListener("onTextCanvasUp", canvasUp); document.removeEventListener("onTextCanvasDrag", canvasDrag); } return { "enable": enable, "disable": disable }; } function createSquareController() { "use strict"; var panel = createFloatingPanel(50, 30); var palettePanel = createFloatingPanelPalette(160, 40); var startXY; var endXY; var outlineMode = true; var outlineToggle = createToggleButton("Outline", "Filled", () => { outlineMode = true; }, () => { outlineMode = false; }); function canvasDown(evt) { startXY = evt.detail; } function processCoords() { var x0, y0, x1, y1; if (startXY.x < endXY.x) { x0 = startXY.x; x1 = endXY.x; } else { x0 = endXY.x; x1 = startXY.x; } if (startXY.halfBlockY < endXY.halfBlockY) { y0 = startXY.halfBlockY; y1 = endXY.halfBlockY; } else { y0 = endXY.halfBlockY; y1 = startXY.halfBlockY; } return {"x0": x0, "y0": y0, "x1": x1, "y1": y1}; } function canvasUp() { toolPreview.clear(); var coords = processCoords(); var foreground = palette.getForegroundColour(); textArtCanvas.startUndo(); textArtCanvas.drawHalfBlock((draw) => { if (outlineMode === true) { for (var px = coords.x0; px <= coords.x1; px++) { draw(foreground, px, coords.y0); draw(foreground, px, coords.y1); } for (var py = coords.y0 + 1; py < coords.y1; py++) { draw(foreground, coords.x0, py); draw(foreground, coords.x1, py); } } else { for (var py = coords.y0; py <= coords.y1; py++) { for (var px = coords.x0; px <= coords.x1; px++) { draw(foreground, px, py); } } } }); startXY = undefined; endXY = undefined; } function canvasDrag(evt) { if (startXY !== undefined) { if (evt.detail.x !== startXY.x || evt.detail.y !== startXY.y || evt.detail.halfBlockY !== startXY.halfBlockY) { if (endXY !== undefined) { toolPreview.clear(); } endXY = evt.detail; var coords = processCoords(); var foreground = palette.getForegroundColour(); if (outlineMode === true) { for (var px = coords.x0; px <= coords.x1; px++) { toolPreview.drawHalfBlock(foreground, px, coords.y0); toolPreview.drawHalfBlock(foreground, px, coords.y1); } for (var py = coords.y0 + 1; py < coords.y1; py++) { toolPreview.drawHalfBlock(foreground, coords.x0, py); toolPreview.drawHalfBlock(foreground, coords.x1, py); } } else { for (var py = coords.y0; py <= coords.y1; py++) { for (var px = coords.x0; px <= coords.x1; px++) { toolPreview.drawHalfBlock(foreground, px, py); } } } } } } function enable() { panel.enable(); document.addEventListener("onTextCanvasDown", canvasDown); document.addEventListener("onTextCanvasUp", canvasUp); document.addEventListener("onTextCanvasDrag", canvasDrag); } function disable() { panel.disable(); document.removeEventListener("onTextCanvasDown", canvasDown); document.removeEventListener("onTextCanvasUp", canvasUp); document.removeEventListener("onTextCanvasDrag", canvasDrag); } panel.append(palettePanel.getElement()); palettePanel.showCursor(); panel.append(outlineToggle.getElement()); if (outlineMode === true) { outlineToggle.setStateOne(); } else { outlineToggle.setStateTwo(); } return { "enable": enable, "disable": disable }; } function createCircleController() { "use strict"; var panel = createFloatingPanel(50, 30); var palettePanel = createFloatingPanelPalette(160, 40); var startXY; var endXY; var outlineMode = true; var outlineToggle = createToggleButton("Outline", "Filled", () => { outlineMode = true; }, () => { outlineMode = false; }); function canvasDown(evt) { startXY = evt.detail; } function processCoords() { var sx, sy, width, height; sx = startXY.x; sy = startXY.halfBlockY; width = Math.abs(endXY.x - startXY.x); height = Math.abs(endXY.halfBlockY - startXY.halfBlockY); return { "sx": sx, "sy": sy, "width": width, "height": height }; } function ellipseOutline(sx, sy, width, height, callback) { var a2 = width * width; var b2 = height * height; var fa2 = 4 * a2; var fb2 = 4 * b2; for (var px = 0, py = height, sigma = 2 * b2 + a2 * (1 - 2 * height); b2 * px <= a2 * py; px += 1) { callback(sx + px, sy + py); callback(sx - px, sy + py); callback(sx + px, sy - py); callback(sx - px, sy - py); if (sigma >= 0) { sigma += fa2 * (1 - py); py -= 1; } sigma += b2 * ((4 * px) + 6); } for (var px = width, py = 0, sigma = 2 * a2 + b2 * (1 - 2 * width); a2 * py <= b2 * px; py += 1) { callback(sx + px, sy + py); callback(sx - px, sy + py); callback(sx + px, sy - py); callback(sx - px, sy - py); if (sigma >= 0) { sigma += fb2 * (1 - px); px -= 1; } sigma += a2 * ((4 * py) + 6); } } function ellipseFilled(sx, sy, width, height, callback) { var a2 = width * width; var b2 = height * height; var fa2 = 4 * a2; var fb2 = 4 * b2; for (var px = 0, py = height, sigma = 2 * b2 + a2 * (1 - 2 * height); b2 * px <= a2 * py; px += 1) { var amount = px * 2; var start = sx - px; var y0 = sy + py; var y1 = sy - py; for (var i = 0; i < amount; i++) { callback(start + i, y0); callback(start + i, y1); } if (sigma >= 0) { sigma += fa2 * (1 - py); py -= 1; } sigma += b2 * ((4 * px) + 6); } for (var px = width, py = 0, sigma = 2 * a2 + b2 * (1 - 2 * width); a2 * py <= b2 * px; py += 1) { var amount = px * 2; var start = sx - px; var y0 = sy + py; var y1 = sy - py; for (var i = 0; i < amount; i++) { callback(start + i, y0); callback(start + i, y1); } if (sigma >= 0) { sigma += fb2 * (1 - px); px -= 1; } sigma += a2 * ((4 * py) + 6); } } function canvasUp() { toolPreview.clear(); var coords = processCoords(); var foreground = palette.getForegroundColour(); textArtCanvas.startUndo(); var columns = textArtCanvas.getColumns(); var rows = textArtCanvas.getRows(); var doubleRows = rows * 2; textArtCanvas.drawHalfBlock((draw) => { if (outlineMode === true) { ellipseOutline(coords.sx, coords.sy, coords.width, coords.height, (px, py) => { if (px >= 0 && px < columns && py >= 0 && py < doubleRows) { draw(foreground, px, py); } }); } else { ellipseFilled(coords.sx, coords.sy, coords.width, coords.height, (px, py) => { if (px >= 0 && px < columns && py >= 0 && py < doubleRows) { draw(foreground, px, py); } }); } }); startXY = undefined; endXY = undefined; } function canvasDrag(evt) { if (startXY !== undefined) { if (evt.detail.x !== startXY.x || evt.detail.y !== startXY.y || evt.detail.halfBlockY !== startXY.halfBlockY) { if (endXY !== undefined) { toolPreview.clear(); } endXY = evt.detail; var coords = processCoords(); var foreground = palette.getForegroundColour(); var columns = textArtCanvas.getColumns(); var rows = textArtCanvas.getRows(); var doubleRows = rows * 2; if (outlineMode === true) { ellipseOutline(coords.sx, coords.sy, coords.width, coords.height, (px, py) => { if (px >= 0 && px < columns && py >= 0 && py < doubleRows) { toolPreview.drawHalfBlock(foreground, px, py); } }); } else { ellipseFilled(coords.sx, coords.sy, coords.width, coords.height, (px, py) => { if (px >= 0 && px < columns && py >= 0 && py < doubleRows) { toolPreview.drawHalfBlock(foreground, px, py); } }); } } } } function enable() { panel.enable(); document.addEventListener("onTextCanvasDown", canvasDown); document.addEventListener("onTextCanvasUp", canvasUp); document.addEventListener("onTextCanvasDrag", canvasDrag); } function disable() { panel.disable(); document.removeEventListener("onTextCanvasDown", canvasDown); document.removeEventListener("onTextCanvasUp", canvasUp); document.removeEventListener("onTextCanvasDrag", canvasDrag); } panel.append(palettePanel.getElement()); palettePanel.showCursor(); panel.append(outlineToggle.getElement()); if (outlineMode === true) { outlineToggle.setStateOne(); } else { outlineToggle.setStateTwo(); } return { "enable": enable, "disable": disable }; } function createSampleTool(divElement, freestyle, divFreestyle, characterBrush, divCharacterBrush) { "use strict"; function sample(x, halfBlockY) { var block = textArtCanvas.getHalfBlock(x, halfBlockY); if (block.isBlocky) { if (block.halfBlockY === 0) { palette.setForegroundColour(block.upperBlockColour); } else { palette.setForegroundColour(block.lowerBlockColour); } } else { block = textArtCanvas.getBlock(block.x, Math.floor(block.y / 2)); palette.setForegroundColour(block.foregroundColour); palette.setBackgroundColour(block.backgroundColour); if (block.charCode >= 176 && block.charCode <= 178) { freestyle.select(block.charCode); divFreestyle.click(); } else { characterBrush.select(block.charCode); divCharacterBrush.click(); } } } function canvasDown(evt) { sample(evt.detail.x, evt.detail.halfBlockY); } function enable() { document.addEventListener("onTextCanvasDown", canvasDown); } function disable() { document.removeEventListener("onTextCanvasDown", canvasDown); } return { "enable": enable, "disable": disable, "sample": sample }; } function createSelectionTool(divElement) { "use strict"; function canvasDown(evt) { selectionCursor.setStart(evt.detail.x, evt.detail.y); selectionCursor.setEnd(evt.detail.x, evt.detail.y); } function canvasDrag(evt) { selectionCursor.setEnd(evt.detail.x, evt.detail.y); } function enable() { document.addEventListener("onTextCanvasDown", canvasDown); document.addEventListener("onTextCanvasDrag", canvasDrag); } function disable() { selectionCursor.hide(); document.removeEventListener("onTextCanvasDown", canvasDown); document.removeEventListener("onTextCanvasDrag", canvasDrag); pasteTool.disable(); } return { "enable": enable, "disable": disable }; }