sandboxels/mods/moreViews.js

503 lines
25 KiB
JavaScript
Raw Normal View History

if (!enabledMods.includes("mods/betterSettings.js")) { enabledMods.unshift("mods/betterSettings.js"); localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); alert("'betterSettings.js' is a dependency for 'moreViews.js' and has been added. Please reload for it to take effect.") }
else {
const views = [
// default sandboxels
"Default View",
"",
"Thermal View",
"Basic View",
"Smooth View",
// custom
"3D View",
"Inverted",
"Darker",
"Brighter",
"Gray scale",
"Sepia",
"Hue rotation 180°",
"Saturated",
"Time",
"Anaglyph",
"VHS (VCR)",
"Outline",
"Upside down",
"Vignette"
];
setView = (n) => {
if (n <= views.length - 1 && n > 1) {
view = n;
} else {
view = null;
}
setSetting('view', parseInt(view));
document.querySelector('span[setting="view"]').children[0].value = view ?? 0;
}
for (const i in views) {
2024-03-18 17:27:02 -04:00
if (i < 4) continue;
const option = document.createElement("option");
option.setAttribute("value", i);
option.innerText = views[i];
document.querySelector('.setting-span[setting="view"]').querySelector("select").appendChild(option);
viewKey[i] = views[i];
}
const vcrFont = new FontFace("VCR", "url(mods/VCR_OSD_MONO.ttf)");
vcrFont.load().then(font => {
console.log(font);
document.fonts.add(font);
})
function blending(color, color2, t = 0.5) {
const [r, g, b] = parseColor(color).replace("#", "").match(/../g).map(a => parseInt(a, 16));
const [r2, g2, b2] = parseColor(color2).replace("#", "").match(/../g).map(a => parseInt(a, 16));
if ([r, g, b].includes(undefined) || [r, g, b, t].includes(NaN)) console.log([r, g, b, t], parseColor(color), color);
return `#${[
(1 - t) * r + t * r2,
(1 - t) * g + t * g2,
(1 - t) * b + t * b2
].map(a => Math.floor(a).toString(16).padStart(2, "0")).join("")}`;
}
const cache = new Map();
function mixColors(color, color2) {
if (cache.has(`${color}_${color2}`) || cache.has(`${color2}_${color}`)) return cache.get(`${color}_${color2}`) ?? cache.get(`${color2}_${color}`);
const [r, g, b] = parseColor(color).replace("#", "").match(/../g).map(a => parseInt(a, 16));
const [r2, g2, b2] = parseColor(color2).replace("#", "").match(/../g).map(a => parseInt(a, 16));
const res = [
Math.max(r, r2),
Math.max(g, g2),
Math.max(b, b2)
];
cache.set(`${color}_${color2}`, `#${res.map(a => (Math.floor(a) % 256).toString(16).padStart(2, "0")).join("")}`);
return `#${res.map(a => (Math.floor(a) % 256).toString(16).padStart(2, "0")).join("")}`;
}
const parseColor = (colorString) => {
if (colorString instanceof Array) return parseColor(colorString[0]);
if (typeof colorString != "string") return "#ffffff";
if (colorString.startsWith("rgb(")) {
const color = colorString.replace("rgb(", "").replace(")", "");
return `#${color.split(",").map(a => parseInt(a).toString(16).length == 1 ? `0${parseInt(a).toString(16)}` : parseInt(a).toString(16)).join("")}`;
} else if (colorString.startsWith("rgba(")) {
const color = colorString.replace("rgba(", "").replace(")", "");
return `#${color.split(",").filter((_, i) => i <= 2).map(a => parseInt(a).toString(16).length == 1 ? `0${parseInt(a).toString(16)}` : parseInt(a).toString(16)).join("")}`;
} else {
if (colorString.startsWith("#")) {
const color = colorString.slice(1);
if (color.length == 3) return `#${color.split(a => a.repeat(2)).join()}`;
else if (color.length >= 6) return `#${color.slice(0, 6)}`;
else return `#${color}`;
}
}
}
const rgbToHsl = (r, g, b) => {
const r1 = r / 255;
const g1 = g / 255;
const b1 = b / 255;
const cmax = Math.max(r1, g1, b1);
const cmin = Math.min(r1, g1, b1);
const delta = cmax - cmin;
const l = (cmax + cmin) / 2;
const s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
let h = 0;
if (delta != 0) {
switch (cmax) {
case r1:
h = 60 * (((g1 - b1) / delta) % 6);
break;
case g1:
h = 60 * ((b1 - r1) / delta + 2);
break;
default:
h = 60 * ((r1 - g1) / delta + 4);
}
}
return {h, s, l};
}
const thetaSetting = new Setting("3D View Angle (0-90)", "theta", settingType.NUMBER, false, parseFloat((Math.atan(2) * 180 / Math.PI).toPrecision(3)));
const tab = new SettingsTab("moreViews.js");
tab.registerSetting(thetaSetting);
let maxDistance = -1;
const colorCache = new Map();
function getModeColor(color, distance = 0) {
if (!colorCache.has(view)) colorCache.set(view, new Map());
if (view == 18) {
if (colorCache.get(view).has(color) && colorCache.get(view).get(color).has(distance)) return colorCache.get(view).get(color).get(distance);
} else if (colorCache.get(view).has(color)) return colorCache.get(view).get(color);
switch (view) {
case 6: {
const newColor = "#" + (parseInt(`0x1${parseColor(color).slice(1)}`) ^ 0xffffff).toString(16).slice(1);
colorCache.get(view).set(color, newColor);
return newColor;
}
case 7: {
const newColor = blending(pixel.color, "#000000");
colorCache.get(view).set(color, newColor);
return newColor;
}
case 8: {
const newColor = blending(pixel.color, "#ffffff");
colorCache.get(view).set(color, newColor);
return newColor;
}
case 9: {
const [r, g, b] = parseColor(color).slice(1).match(/.{1,2}/g).map(a => parseInt(a, 16)).slice(0, 3);
const {h, l} = rgbToHsl(r, g, b);
const newColor = `hsl(${Math.round(h)}, 0%, ${Math.round(l * 100)}%)`;
colorCache.get(view).set(color, newColor);
return newColor;
}
case 10: {
const [r, g, b] = parseColor(color).replace("#", "").match(/../g).map(a => parseInt(a, 16));
const [r2, g2, b2] = [
Math.min(255, (r * 0.393) + (g * 0.769) + (b * 0.189)),
Math.min(255, (r * 0.349) + (g * 0.686) + (b * 0.168)),
Math.min(255, (r * 0.272) + (g * 0.534) + (b * 0.131))
];
const newColor = `#${Math.floor(r2).toString(16).padStart(2, "0")}${Math.floor(g2).toString(16).padStart(2, "0")}${Math.floor(b2).toString(16).padStart(2, "0")}`;
colorCache.get(view).set(color, newColor);
return newColor;
}
case 11: {
const [r, g, b] = parseColor(color).slice(1).match(/.{1,2}/g).map(a => parseInt(a, 16)).slice(0, 3);
const {h, s, l} = rgbToHsl(r, g, b);
const newColor = `hsl(${(Math.round(h) + 180 % 360)}, ${Math.round(s * 100)}%, ${Math.round(l * 100)}%)`;
colorCache.get(view).set(color, newColor);
return newColor;
}
case 12: {
const [r, g, b] = parseColor(color).slice(1).match(/.{1,2}/g).map(a => parseInt(a, 16)).slice(0, 3);
const {h, s, l} = rgbToHsl(r, g, b);
const newColor = `hsl(${Math.round(h)}, ${Math.round(s * 100) * 4}%, ${Math.round(l * 100)}%)`;
colorCache.get(view).set(color, newColor);
return newColor;
}
case 15: {
const [r, g, b] = parseColor(color).replace("#", "").match(/../g);
const [r2, g2, b2] = [parseInt(r, 16) * 0.75, parseInt(g, 16) * 0.75, parseInt(b, 16) * 0.75];
const newColor = `rgb(${r2}, ${g2}, ${b2})`;
colorCache.get(view).set(color, newColor);
return newColor;
}
case 18: {
const newColor = blending(pixel.color, "#000000", (1 / maxDistance) * distance);
colorCache.get(view).has(color)
? colorCache.get(view).get(color).set(distance, newColor)
: colorCache.get(view).set(color, new Map([[distance, newColor]]));
return newColor;
}
}
return color;
}
settingsManager.registerTab(tab);
runAfterLoadList.push(() => drawPixels = (function() {
const oldDrawPixels = drawPixels;
return function(forceTick = false) {
2024-03-12 18:37:53 -04:00
if (view >= 4) {
if (maxDistance == -1) maxDistance = Math.sqrt((width / 2) ** 2 + (height / 2) ** 2) * 2;
const canvas = document.getElementById("game");
const ctx = canvas.getContext("2d");
var newCurrentPixels = currentPixels.slice();
var pixelsFirst = [];
var pixelsLast = [];
if (!paused || forceTick) {
shuffleArray(newCurrentPixels);
}
for (var i = 0; i < newCurrentPixels.length; i++) {
pixel = newCurrentPixels[i];
if (pixel.del) {continue}
if (!paused || forceTick) {
if (elements[pixel.element].tick) {
elements[pixel.element].tick(pixel);
}
if (pixel.del) {continue}
if (elements[pixel.element].behavior) {
pixelTick(pixel);
}
};
if (pixel.con) { pixel = pixel.con }
if (elements[pixel.element].isGas || elements[pixel.element].glow) {
pixelsLast.push(pixel);
}
else {
pixelsFirst.push(pixel);
}
}
if (hiding) {
if (ctx.globalAlpha < 1) {
ctx.globalAlpha = 1;
}
if (elements[currentElement].maxSize < mouseSize) {
var mouseOffset = Math.trunc(elements[currentElement].maxSize/2);
}
else {
var mouseOffset = Math.trunc(mouseSize/2);
}
var topLeft = [mousePos.x-mouseOffset,mousePos.y-mouseOffset];
var bottomRight = [mousePos.x+mouseOffset,mousePos.y+mouseOffset];
ctx.strokeStyle = "white";
ctx.strokeRect(topLeft[0]*pixelSize,topLeft[1]*pixelSize,(bottomRight[0]-topLeft[0]+1)*pixelSize,(bottomRight[1]-topLeft[1]+1)*pixelSize);
if (settings.precision) {
ctx.fillStyle = "rgba(255,255,255,0.5)";
ctx.fillRect(mousePos.x*pixelSize,mousePos.y*pixelSize,pixelSize,pixelSize);
}
if ((!paused) || forceTick) {pixelTicks++};
return;
}
if (!settings["bg"]) {ctx.clearRect(0, 0, canvas.width, canvas.height)}
else {
ctx.fillStyle = settings["bg"];
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
var pixelDrawList = pixelsFirst.concat(pixelsLast);
for (var i = 0; i < pixelDrawList.length; i++) {
pixel = pixelDrawList[i];
if (pixelMap[pixel.x][pixel.y] == undefined) {continue}
if (pixel.con) { pixel = pixel.con };
ctx.fillStyle = getModeColor(pixel.color, view == 18 ? Math.sqrt((width / 2 - pixel.x) ** 2 + (height / 2 - pixel.y) ** 2) : 0);
2024-03-12 18:37:53 -04:00
if (view == 4) {
let colorList = [];
for (var j = 0; j < biCoords.length; j++) {
const x = pixel.x + biCoords[j][0];
const y = pixel.y + biCoords[j][1];
if (isEmpty(x,y,true) || elements[pixelMap[x][y].element].state !== elements[pixel.element].state) {continue}
const color = pixelMap[x][y].color;
const [r, g, b] = color.replace(/[rgb()]/g, "").split(",").map(a => parseInt(a.trim()));
const [r1, g1, b1] = pixel.color.replace(/[rgb()]/g, "").split(",").map(a => parseInt(a.trim()));
if (Math.abs(r - r1) + Math.abs(g - g1) + Math.abs(b - b1) > 75 && pixelMap[x][y].element != pixel.element) continue;
if (color.indexOf("rgb") !== -1) {
colorList.push(color.match(/\d+/g));
}
}
if (colorList.length === 0) {
ctx.fillStyle = pixel.color;
}
else {
ctx.fillStyle = averageRGB(colorList);
}
ctx.fillRect(pixel.x * pixelSize, pixel.y * pixelSize, pixelSize, pixelSize);
}
// 3D VIEW
2024-03-12 18:37:53 -04:00
else if (view == 5) {
const neighborRight = !outOfBounds(pixel.x + 1, pixel.y) && !!pixelMap[pixel.x + 1][pixel.y];
const neighborUp = !outOfBounds(pixel.x, pixel.y - 1) && !!pixelMap[pixel.x][pixel.y - 1];
const neighborUpRight = !outOfBounds(pixel.x + 1, pixel.y - 1) && !!pixelMap[pixel.x + 1][pixel.y - 1];
let size = 0;
let currentY = pixel.y;
while (!outOfBounds(pixel.x, currentY) && pixelMap[pixel.x][currentY] && pixelMap[pixel.x][currentY].element == pixel.element) {
currentY++;
size++;
}
ctx.globalAlpha = 1;
ctx.fillStyle = pixel.color;
ctx.fillRect(pixel.x * pixelSize, pixel.y * pixelSize, pixelSize, pixelSize);
const px = pixel.x * pixelSize;
const py = pixel.y * pixelSize;
const theta = Math.max(Math.min(thetaSetting.get(), 90), 0) * Math.PI / 180;
const a = Math.cos(theta);
const b = Math.sin(theta);
const w = pixelSize;
const px2 = px + a * w;
const py2 = py - b * w;
const parts = [[[px, py], [[px2, py2], [px + w, py2], [px + w, py]], !neighborUp], [[px + w, py + w], [[px2 + w, py2 + w], [px2 + w, py], [px + w, py]], !neighborRight], [[px + w, py], [[px + w, py2], [px2 + w, py2], [px + w, py]], !neighborUp && !neighborUpRight], [[px + w, py], [[px2 + w, py2], [px2 + w, py], [px + w, py]], !neighborRight && !neighborUpRight]]
for (const part of parts.filter(p => p[2])) {
ctx.fillStyle = blending(pixel.color, "#000000");
ctx.beginPath();
ctx.moveTo(...part[0]);
for (const v of part[1]) {
ctx.lineTo(...v);
}
ctx.closePath();
ctx.fill();
}
} else if (view == 13) {
const hue = 225 - (Math.log(pixel.start) / Math.log(pixelTicks)) * 225;
ctx.globalAlpha = 1;
ctx.fillStyle = `hsl(${Math.min(Math.round(hue), 250)}, 100%, 50%)`;
ctx.fillRect(pixel.x * pixelSize, pixel.y * pixelSize, pixelSize, pixelSize);
} else if (view == 14) {
ctx.globalAlpha = 1;
ctx.fillStyle = pixel.color;
ctx.fillRect(pixel.x * pixelSize, pixel.y * pixelSize, pixelSize, pixelSize);
if (outOfBounds(pixel.x - 1, pixel.y) || !pixelMap[pixel.x - 1][pixel.y]) {
ctx.fillStyle = "#ff0000";
ctx.globalAlpha = 0.5;
ctx.fillRect(pixel.x * pixelSize - 0.5 * pixelSize, pixel.y * pixelSize, pixelSize, pixelSize);
}
if (outOfBounds(pixel.x + 1, pixel.y) || !pixelMap[pixel.x + 1][pixel.y]) {
ctx.fillStyle = "#00ffff";
ctx.globalAlpha = 0.5;
ctx.fillRect(pixel.x * pixelSize + 0.5 * pixelSize, pixel.y * pixelSize, pixelSize, pixelSize);
}
} else if (view == 15) {
const [r, g, b] = parseColor(pixel.color).replace("#", "").match(/../g);
const [r2, g2, b2] = [parseInt(r, 16) * 0.75, parseInt(g, 16) * 0.75, parseInt(b, 16) * 0.75]
// scrolling effect
const offset = (pixelTicks + 6) % height >= pixel.y && (pixelTicks - 3) % height <= pixel.y
|| (pixelTicks + 66) % height >= pixel.y && (pixelTicks - 57) % height <= pixel.y;
if (!pixelMap[pixel.x - 1] || !pixelMap[pixel.x - 1][pixel.y]) {
ctx.globalAlpha = 0.5;
ctx.fillStyle = `#${r.padStart(2, "0")}0000`;
ctx.fillRect(pixel.x * pixelSize - 0.75 * pixelSize - (offset ? 0.5 * pixelSize : 0) , pixel.y * pixelSize, pixelSize, pixelSize);
}
if (!pixelMap[pixel.x + 1] || !pixelMap[pixel.x + 1][pixel.y]) {
ctx.globalAlpha = 0.5;
ctx.fillStyle = `#0000${b.padStart(2, "0")}`;
ctx.fillRect(pixel.x * pixelSize + 0.75 * pixelSize - (offset ? 0.5 * pixelSize : 0), pixel.y * pixelSize, pixelSize, pixelSize);
}
ctx.globalAlpha = 1;
ctx.fillStyle = `rgb(${r2}, ${g2}, ${b2})`
ctx.fillRect(pixel.x * pixelSize - (offset ? 0.5 * pixelSize : 0), pixel.y * pixelSize, pixelSize, pixelSize);
ctx.globalAlpha = 1;
// i fucking hate it but at least it works
// and i dont feel like finding something that is fast and pretty
} else if (view == 16) {
ctx.globalAlpha = 1;
ctx.strokeStyle = pixel.color;
ctx.lineWidth = 2;
const cond1 = outOfBounds(pixel.x - 1, pixel.y)
|| !pixelMap[pixel.x - 1][pixel.y]
|| pixelMap[pixel.x - 1][pixel.y].element != pixel.element;
const cond2 = outOfBounds(pixel.x + 1, pixel.y)
|| !pixelMap[pixel.x + 1][pixel.y]
|| pixelMap[pixel.x + 1][pixel.y].element != pixel.element;
const cond3 = outOfBounds(pixel.x, pixel.y - 1)
|| !pixelMap[pixel.x][pixel.y - 1]
|| pixelMap[pixel.x][pixel.y - 1].element != pixel.element;
const cond4 = outOfBounds(pixel.x, pixel.y + 1)
|| !pixelMap[pixel.x][pixel.y + 1]
|| pixelMap[pixel.x][pixel.y + 1].element != pixel.element;
const cond5 = outOfBounds(pixel.x - 1, pixel.y - 1)
|| !pixelMap[pixel.x - 1][pixel.y - 1]
|| pixelMap[pixel.x - 1][pixel.y - 1].element != pixel.element;
const cond6 = outOfBounds(pixel.x + 1, pixel.y - 1)
|| !pixelMap[pixel.x + 1][pixel.y - 1]
|| pixelMap[pixel.x + 1][pixel.y - 1].element != pixel.element;
const cond7 = outOfBounds(pixel.x - 1, pixel.y + 1)
|| !pixelMap[pixel.x - 1][pixel.y + 1]
|| pixelMap[pixel.x - 1][pixel.y + 1].element != pixel.element;
const cond8 = outOfBounds(pixel.x + 1, pixel.y + 1)
|| !pixelMap[pixel.x + 1][pixel.y + 1]
|| pixelMap[pixel.x + 1][pixel.y + 1].element != pixel.element;
if (cond1) {
ctx.beginPath();
ctx.moveTo(pixel.x * pixelSize + ctx.lineWidth / 2, pixel.y * pixelSize);
ctx.lineTo(pixel.x * pixelSize + ctx.lineWidth / 2, (pixel.y + 1) * pixelSize);
ctx.stroke();
}
if (cond2) {
ctx.beginPath();
ctx.moveTo((pixel.x + 1) * pixelSize - ctx.lineWidth / 2, pixel.y * pixelSize);
ctx.lineTo((pixel.x + 1) * pixelSize - ctx.lineWidth / 2, (pixel.y + 1) * pixelSize);
ctx.stroke();
}
if (cond3) {
ctx.beginPath();
ctx.moveTo(pixel.x * pixelSize, pixel.y * pixelSize + ctx.lineWidth / 2);
ctx.lineTo((pixel.x + 1) * pixelSize, pixel.y * pixelSize + ctx.lineWidth / 2);
ctx.stroke();
}
if (cond4) {
ctx.beginPath();
ctx.moveTo(pixel.x * pixelSize, (pixel.y + 1) * pixelSize - ctx.lineWidth / 2);
ctx.lineTo((pixel.x + 1) * pixelSize, (pixel.y + 1) * pixelSize - ctx.lineWidth / 2);
ctx.stroke();
}
if (!cond2 && !cond4 && cond8) ctx.fillRect((pixel.x + 1) * pixelSize - ctx.lineWidth, (pixel.y + 1) * pixelSize - ctx.lineWidth, ctx.lineWidth, ctx.lineWidth);
if (!cond2 && !cond3 && cond6) ctx.fillRect((pixel.x + 1) * pixelSize - ctx.lineWidth, pixel.y * pixelSize, ctx.lineWidth, ctx.lineWidth);
if (!cond1 && !cond3 && cond5) ctx.fillRect(pixel.x * pixelSize, pixel.y * pixelSize, ctx.lineWidth, ctx.lineWidth);
if (!cond1 && !cond4 && cond7) ctx.fillRect(pixel.x * pixelSize, (pixel.y + 1) * pixelSize - ctx.lineWidth, ctx.lineWidth, ctx.lineWidth);
} else if (view == 17) {
ctx.fillRect(pixel.x * pixelSize, (height - pixel.y) * pixelSize, pixelSize, pixelSize);
} else {
ctx.fillRect(pixel.x*pixelSize, pixel.y*pixelSize, pixelSize, pixelSize);
}
if (pixel.charge && view !== 2) { // Yellow glow on charge
if (!elements[pixel.element].colorOn) {
ctx.fillStyle = "rgba(255,255,0,0.5)";
ctx.fillRect(pixel.x*pixelSize, pixel.y*pixelSize, pixelSize, pixelSize);
}
}
}
if (view == 15) {
// TRACK READ NOISE
for (let n = 0; n < 3; n++) {
const number = Math.floor(Math.random() * height);
ctx.globalAlpha = Math.random();
ctx.fillStyle = "#fff";
ctx.fillRect(0, (number + 0.5) * pixelSize, width * pixelSize, 0.2);
ctx.globalAlpha = 1;
}
const {font, textAlign} = ctx;
ctx.font = "30px VCR";
ctx.textAlign = "start";
ctx.fillText(paused ? "PAUSE" : "PLAY", (0.025 * width) * pixelSize, (0.025 * width) * pixelSize + 15);
if (paused) {
ctx.fillRect((0.05 * width) * pixelSize + ctx.measureText("PAUSE").width, (0.025 * width) * pixelSize - 7.5, 5, 22.5);
ctx.fillRect((0.05 * width) * pixelSize + ctx.measureText("PAUSE").width + 8, (0.025 * width) * pixelSize - 7.5, 5, 22.5);
} else {
ctx.fillStyle = "#fff";
ctx.beginPath();
ctx.moveTo((0.05 * width) * pixelSize + ctx.measureText("PLAY").width, (0.025 * width) * pixelSize - 7.5);
ctx.lineTo((0.05 * width) * pixelSize + ctx.measureText("PLAY").width, (0.025 * width) * pixelSize + 15);
ctx.lineTo((0.05 * width) * pixelSize + ctx.measureText("PLAY").width + 17.5, (0.025 * width) * pixelSize + 3.75);
ctx.lineTo((0.05 * width) * pixelSize + ctx.measureText("PLAY").width, (0.025 * width) * pixelSize - 7.5);
ctx.fill();
}
const base = Math.floor(pixelTicks / tps);
const seconds = base % 60 + "";
const minutes = Math.floor(base / 60) % 60 + "";
const hours = Math.floor(base / 60 / 60) + "";
ctx.textAlign = "end";
ctx.fillText(`${hours.padStart(2, "0")}:${minutes.padStart(2, "0")}:${seconds.padStart(2, "0")}`, (0.975 * width) * pixelSize, (0.025 * width) * pixelSize + 15);
ctx.font = font;
ctx.textAlign = textAlign;
}
if (ctx.globalAlpha < 1) {
ctx.globalAlpha = 1;
}
if (elements[currentElement].maxSize < mouseSize) {
var mouseOffset = Math.trunc(elements[currentElement].maxSize/2);
}
else {
var mouseOffset = Math.trunc(mouseSize/2);
}
var topLeft = [mousePos.x-mouseOffset,mousePos.y-mouseOffset];
var bottomRight = [mousePos.x+mouseOffset,mousePos.y+mouseOffset];
// Draw a square around the mouse
ctx.strokeStyle = "white";
ctx.strokeRect(topLeft[0]*pixelSize,topLeft[1]*pixelSize,(bottomRight[0]-topLeft[0]+1)*pixelSize,(bottomRight[1]-topLeft[1]+1)*pixelSize);
// draw one transparent pixel in the center
if (settings.precision) {
ctx.fillStyle = "rgba(255,255,255,0.5)";
ctx.fillRect(mousePos.x*pixelSize,mousePos.y*pixelSize,pixelSize,pixelSize);
}
if ((!paused) || forceTick) {pixelTicks++};
} else oldDrawPixels.apply(this, arguments);
}
}()));
}