From 2ab9ce7d27929403e583c52a54b51765b756bd0b Mon Sep 17 00:00:00 2001 From: Fen Dweller Date: Thu, 2 Sep 2021 17:00:55 -0400 Subject: [PATCH] Add rotation Entities can now be rotated. This does not affect their height. For now, they can only be rotated by 45 degrees at a time. I will work out something nicer later on. --- macrovision.css | 9 +++- macrovision.html | 7 +++ macrovision.js | 122 ++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 119 insertions(+), 19 deletions(-) diff --git a/macrovision.css b/macrovision.css index 4bfcf835..c9b9867f 100644 --- a/macrovision.css +++ b/macrovision.css @@ -48,7 +48,8 @@ body.smoothing .entity-box { -moz-user-drag: none; -o-user-drag: none; --offset: -100%; - transform: translate(-50%, var(--offset)); + --rotation: 30deg; + transform: translate(-50%, var(--offset)) rotate(var(--rotation)); filter: brightness(var(--brightness)); } @@ -411,7 +412,11 @@ select { body #test-canvas { position: fixed; - top: 500vh; + top: 100px; + left: 400px; + z-index: 99999999; + pointer-events: none; + display: none; } .switch { diff --git a/macrovision.html b/macrovision.html index c2d00c52..aed82471 100644 --- a/macrovision.html +++ b/macrovision.html @@ -143,6 +143,13 @@
+
+ Rotation +
+
+ + +
Brightness
diff --git a/macrovision.js b/macrovision.js index 1bb69032..c47c1f41 100644 --- a/macrovision.js +++ b/macrovision.js @@ -1092,6 +1092,7 @@ function makeEntity(info, views, sizes) { name: info.name, identifier: info.name, scale: 1, + rotation: 0, info: JSON.parse(JSON.stringify(info)), views: JSON.parse(JSON.stringify(views), math.reviver), sizes: sizes === undefined ? [] : JSON.parse(JSON.stringify(sizes), math.reviver), @@ -1681,10 +1682,17 @@ function clearViewOptions() { const testCanvas = document.createElement("canvas"); testCanvas.id = "test-canvas"; +function rotate(point, angle) { + return [ + point[0] * Math.cos(angle) - point[1] * Math.sin(angle), + point[0] * Math.sin(angle) + point[1] * Math.cos(angle) + ]; +} + const testCtx = testCanvas.getContext("2d"); function testClick(event) { - // oh my god I can't believe I'm doing this + testCtx.save(); const target = event.target; if (rulerMode) { @@ -1709,19 +1717,59 @@ function testClick(event) { h /= ratioH; } + // todo remove some of this unused stuff + const ratio = ratioW * ratioH; + console.log("SDFSDFSD") + console.log(ratio); + const entity = entities[target.parentElement.dataset.key]; + + const angle = entity.rotation; var x = event.clientX - target.getBoundingClientRect().x, y = event.clientY - target.getBoundingClientRect().y, alpha; - testCtx.canvas.width = w; - testCtx.canvas.height = h; - - // Draw image to canvas - // and read Alpha channel value - testCtx.drawImage(target, 0, 0, w, h); - alpha = testCtx.getImageData(Math.floor(x / ratio), Math.floor(y / ratio), 1, 1).data[3]; // [0]R [1]G [2]B [3]A - // If pixel is transparent, + + [xTarget,yTarget] = [x,y]; + console.log(xTarget); + + [actualW, actualH] = [target.getBoundingClientRect().width, target.getBoundingClientRect().height]; + xTarget -= actualW/2; + xTarget /= ratio; + xTarget += actualW/2; + yTarget -= actualH/2; + yTarget /= ratio; + yTarget += actualH/2; + + + + testCtx.canvas.width = actualW; + testCtx.canvas.height = actualH; + + testCtx.save(); + + // dear future me: Sorry :( + + testCtx.resetTransform(); + + + testCtx.translate(actualW/2, actualH/2); + testCtx.rotate(angle); + testCtx.translate(-actualW/2, -actualH/2); + testCtx.drawImage(target, (actualW/2 - w/2), (actualH/2 - h/2), w, h); + testCtx.fillStyle = "red"; + testCtx.fillRect(actualW/2,actualH/2,10,10); + + testCtx.restore(); + + testCtx.fillStyle = "red"; + alpha = testCtx.getImageData(xTarget, yTarget, 1, 1).data[3]; + testCtx.fillRect(xTarget, yTarget, 3, 3); + // console.log(testCtx.canvas.width, testCtx.canvas.height); + console.log(actualW, actualH); + // console.log(xTarget, yTarget); + + // If the pixel is transparent, // retrieve the element underneath and trigger its click event if (alpha === 0) { const oldDisplay = target.style.display; @@ -1735,6 +1783,7 @@ function testClick(event) { } else { clickDown(target.parentElement, event.clientX, event.clientY); } + testCtx.restore(); } function arrangeEntities(order) { @@ -1984,6 +2033,8 @@ function displayEntity(entity, view, x, y, selectEntity = false, refresh = false img.style.setProperty("--offset", ((-1) * 100) + "%") } + img.style.setProperty("--rotation", (entity.rotation * 180 / Math.PI) + "deg") + box.dataset.x = x; box.dataset.y = y; @@ -2359,7 +2410,7 @@ const settingsData = { "high", "medium", "low", - "bottom" + "bottom", ], get value() { return config.groundPos; @@ -2942,12 +2993,28 @@ document.addEventListener("DOMContentLoaded", () => { document.querySelector("#options-brightness-down").addEventListener("click", e => { if (selected) { - entities[selected.dataset.key].brightness = Math.max(entities[selected.dataset.key].brightness -1, 0); + entities[selected.dataset.key].brightness -= 1; } document.querySelector("#options-brightness-display").innerText = entities[selected.dataset.key].brightness; updateSizes(); }); + document.querySelector("#options-rotate-left").addEventListener("click", e => { + if (selected) { + entities[selected.dataset.key].rotation -= Math.PI/4; + } + selected.querySelector("img").style.setProperty("--rotation", (entities[selected.dataset.key].rotation * 180 / Math.PI) + "deg") + updateSizes(); + }); + + document.querySelector("#options-rotate-right").addEventListener("click", e => { + if (selected) { + entities[selected.dataset.key].rotation += Math.PI/4; + } + selected.querySelector("img").style.setProperty("--rotation", (entities[selected.dataset.key].rotation * 180 / Math.PI) + "deg") + updateSizes(); + }); + document.querySelector("#options-flip").addEventListener("click", e => { if (selected) { selected.querySelector(".entity-image").classList.toggle("flipped"); @@ -4380,6 +4447,7 @@ function exportScene() { name: entity.identifier, customName: entity.name, scale: entity.scale, + rotation: entity.rotation, view: entity.view, x: element.dataset.x, y: element.dataset.y, @@ -4502,6 +4570,17 @@ const migrationDefs = [ data.entities.forEach(entity => { entity.customName = entity.name }); + }, + /* + Migration: 3 -> $ + + Rotation is now stored + */ + + data => { + data.entities.forEach(entity => { + entity.rotation = 0 + }); } ] @@ -4527,6 +4606,7 @@ function importScene(data) { const entity = findEntity(entityInfo.name).constructor(); entity.name = entityInfo.customName; entity.scale = entityInfo.scale; + entity.rotation = entityInfo.rotation; entity.priority = entityInfo.priority; entity.brightness = entityInfo.brightness; displayEntity(entity, entityInfo.view, entityInfo.x, entityInfo.y); @@ -4567,17 +4647,25 @@ function renderToCanvas() { let offset = img.style.getPropertyValue("--offset"); offset = parseFloat(offset.substring(0, offset.length-1)) - x = coords.x - img.getBoundingClientRect().width/2; - y = coords.y - img.getBoundingClientRect().height * (-offset/100); - let xSize = img.getBoundingClientRect().width; - let ySize = img.getBoundingClientRect().height; + let xSize = img.width; + let ySize = img.height; + x = coords.x + y = coords.y + ySize/2 + ySize * offset / 100; const oldFilter = ctx.filter const brightness = getComputedStyle(element).getPropertyValue("--brightness") ctx.filter = `brightness(${brightness})`; - - ctx.drawImage(img, x, y, xSize, ySize); + + ctx.save(); + ctx.resetTransform(); + ctx.translate(x, y); + console.log(entity.rotation) + ctx.rotate(entity.rotation); + ctx.drawImage(img, -xSize/2, -ySize/2, xSize, ySize); + console.log(x,y) + ctx.restore(); ctx.drawImage(document.querySelector("#rulers"), 0, 0); + ctx.translate(-xSize/2, -ySize/2); ctx.filter = oldFilter });