diff --git a/static/admin.js b/static/admin.js index b507c5d..2dd4bf2 100644 --- a/static/admin.js +++ b/static/admin.js @@ -7,6 +7,15 @@ const createTokenForm = document.getElementById("createTokenForm"); const tokenWrapper = document.getElementById("adminWrapper_tokens"); const newTableName = document.getElementById("newTableName"); const newTablePass = document.getElementById("newTablePass"); +const tokenSpriteDropdown = document.getElementById("token_combobox"); +const tokenName = document.getElementById("token_name"); +const tokenWidth = document.getElementById("token_width"); +const tokenHeight = document.getElementById("token_height"); +const tokenCX = document.getElementById("token_cx"); +const tokenCY = document.getElementById("token_cy"); +const previewZone = document.getElementById("tokenPreview_zone"); +const tokenAspect = document.getElementById("tokenKeepAspect"); +const aspectLockLabel = document.getElementById("aspectLockLabel"); async function getTable(name, pass) { try { @@ -50,7 +59,7 @@ async function getTable(name, pass) { } adminZone.innerHTML = infoHtml; - let tokenListHTML = "
"; + let tokenListHTML = "
"; if (tokenImgs.ok) { tokenListHTML += ""; const tokens = await tokenImgs.json(); @@ -60,15 +69,19 @@ async function getTable(name, pass) { tokenListHTML += `
  • ${parts[parts.length - 1]} view
  • \n` } tokenListHTML += ""; + fillSpriteDropdown(tokens); } else { tokenListHTML += "" } spriteZone.innerHTML = tokenListHTML; + + tokenWrapper.style.display = "inline"; // also, we have to fill and toggle the tokens window + } else { console.log(res.status); } @@ -77,6 +90,144 @@ async function getTable(name, pass) { } } +function fillSpriteDropdown(tokens) { + let options = ""; + for (const t of tokens) { + const parts = t.split("/"); + const o = `\n`; + options += o; + } + tokenSpriteDropdown.innerHTML = options; +} + +function previewSprite(source) { + if (source) { + switch (source.id) { + case "token_combobox": + reinitializeSpritePreview(); + break; + case "token_cx": + case "token_cy": + drawTokenOrigin(); + break; + default: + scaleSpritePreview(source); + console.log("default case"); + } + } +} + +function toggleAspectLock() { + if (tokenKeepAspect.checked) { + aspectLockLabel.innerHTML = "🔒" + } else { + aspectLockLabel.innerHTML = "🔓" + } +} + +function scaleSpritePreview(source) { + if (mapImg && mapImg._image) { + console.log(mapImg); + const scaleFactor = mapImg._image.clientWidth / mapImg._image.naturalWidth; + const keepAspect = tokenAspect.checked; + const img = previewZone.children[0]; + if (img) { + if (!keepAspect || !source) { + img.width = Number(tokenWidth.value) * scaleFactor; + img.height = Number(tokenHeight.value) * scaleFactor; + } else { + + const currentAspect = img.width/img.height; + switch (source.id) { + case "token_width": + img.width = Number(tokenWidth.value) * scaleFactor; + img.height = (img.clientWidth / img.naturalWidth) * img.naturalHeight; + tokenHeight.value = Number(tokenWidth.value)/currentAspect; + break; + case "token_height": + img.height = Number(tokenHeight.value) * scaleFactor; + img.width = (img.clientHeight / img.naturalHeight) * img.naturalWidth; + tokenWidth.value = currentAspect * Number(tokenHeight.value); + break; + } + } + tokenCX.value = Number(tokenWidth.value)/2; + tokenCY.value = Number(tokenHeight.value)/2; + drawTokenOrigin(); + } + } +} + +function drawTokenOrigin() { + const img = previewZone.children[0]; + const x = Number(tokenWidth.value) / Number(tokenCX.value); + const y = Number(tokenHeight.value) / Number(tokenCY.value); + const origin = {x: img.width/x, y: img.height/y}; + const originImg = document.createElement("img"); + originImg.src="/table/origin.png"; + originImg.style.position = "absolute"; + originImg.style.left = (origin.x - 2) + "px"; + originImg.style.top = (origin.y - 2) + "px"; + if (previewZone.children.length > 1) { + previewZone.replaceChild(originImg, previewZone.children[1]); + } else { + previewZone.appendChild(originImg); + } + + +} + +function reinitializeSpritePreview() { + const img = document.createElement("img"); + img.src = tokenSpriteDropdown[tokenSpriteDropdown.selectedIndex].value; + const tokenNameParts = tokenSpriteDropdown[tokenSpriteDropdown.selectedIndex].text.split("."); + tokenNameParts.pop(); + tokenName.value = tokenNameParts.join("."); + img.onload = () => { + const w = img.naturalWidth; + const h = img.naturalHeight; + + tokenWidth.value = w; + tokenHeight.value = h; + scaleSpritePreview(); + } + if (previewZone.children.length) { + previewZone.replaceChild(img, previewZone.children[0]); + } else { + previewZone.appendChild(img); + } +} + +function createToken() { + const w = Number(tokenWidth.value); + const h = Number(tokenHeight.value); + const oX = Number(tokenCX.value); + const oY = Number(tokenCY.value); + const img = tokenSpriteDropdown[tokenSpriteDropdown.selectedIndex].value; + const name = tokenName.value; + + console.log("creating token"); + if (!isNaN(w) && !isNaN(h) && !isNaN(oX) && !isNaN(oY) && img && name) { + console.log("all green"); + const self = { + sz: [w, h], + m: L.marker(getCascadingPos(), { + icon: L.icon({ + iconUrl: img, + iconSize: [w,h], + }), + title: name, + draggable: true, + autoPan: true + }), + }; + tokens.push(self); + self.m.addTo(map); + resizeMarkers(); + + } +} + function publishAuxMsg() { const txtArea = document.getElementById("auxMsgZone"); if (txtArea != null) { @@ -223,8 +374,8 @@ async function doLogin() { if (adminUsrInput && adminPassInput) { adminToken = await getAdminToken(adminUsrInput.value, adminPassInput.value); if (adminToken) { - adminWrapper.style.display="inline"; getTables(); + adminWrapper.style.display="inline"; adminZone.style.display = "block"; } else { setErr("Incorrect credentials"); diff --git a/static/index.html b/static/index.html index 1f3f8c0..567c151 100644 --- a/static/index.html +++ b/static/index.html @@ -89,14 +89,15 @@
    tokens
    -
    -
    -
    -
    -
    -
    +
    +
    + +
    +
    +
    +
    - +
    diff --git a/static/map.js b/static/map.js index 29d5f51..1436fb5 100644 --- a/static/map.js +++ b/static/map.js @@ -1,18 +1,19 @@ let map = null; let mapImg = null; let tokens = []; +const worldBounds = [[180, -180],[-180, 180]]; function initializeMap(mapImgUrl) { if (!map) { map = L.map('map', { minZoom: 0, maxZoom: 4, crs: L.CRS.Simple }); - map.on("zoomend", resizeMarkers); + map.on("zoomend", ()=>{resizeMarkers();scaleSpritePreview();}); } if (mapImg) { mapImg.removeFrom(map); } - mapImg = L.imageOverlay(mapImgUrl, [[-180, 180],[180, -180]]); + mapImg = L.imageOverlay(mapImgUrl, worldBounds); mapImg.addTo(map); - map.setMaxBounds([[-180,180],[180,-180]]); + map.setMaxBounds(worldBounds); map.setView([0,0], 2); while (tokens.some(t=>t)) { tokens[0].m.removeFrom(map); @@ -30,6 +31,14 @@ function resizeMarkers() { }); } +function getCascadingPos() { + const topLeft = worldBounds[0]; + const n = tokens.length; + topLeft[1] += (n+1)*5; + topLeft[0] -= (n+1)*5; + return topLeft; +} + function addToken(token) { const self = { sz: token.sz, m: L.marker(token.pos, { icon: L.icon({ diff --git a/static/origin.png b/static/origin.png new file mode 100644 index 0000000..052ae58 Binary files /dev/null and b/static/origin.png differ diff --git a/static/socket.js b/static/socket.js index 5bf54bd..4e34ab7 100644 --- a/static/socket.js +++ b/static/socket.js @@ -19,6 +19,7 @@ function fmtLeading(n) { } function formatDice(r) { + console.log(r); const date = new Date(r.timestamp) const p = document.createElement("p"); const month = date.getMonth() + 1; @@ -51,7 +52,6 @@ function logDice(dice, many) { function setAuxMsg(msg) { const auxDiv = document.getElementById("aux"); if (auxDiv) { - console.log("eeee"); auxDiv.innerText = msg; } } @@ -111,7 +111,6 @@ function dial() { }); conn.addEventListener("open", e => { // TODO: add message to let user know they are at the table - console.info("socket connected"); tabletop = document.getElementById("tabletop"); if (tabletop) { tabletop.style.display = "block"; @@ -132,6 +131,9 @@ function dial() { table = data; makeUpToDate(table); } else { + if (data.diceRoll) { + data.diceRoll.roll = Uint8Array.from(atob(data.diceRoll.roll), c => c.charCodeAt(0)); + } makeUpToDate(data); } diff --git a/static/style.css b/static/style.css index 53ac96c..02ee9be 100644 --- a/static/style.css +++ b/static/style.css @@ -169,4 +169,12 @@ nav { .leaflet-container { background: transparent; +} + +#tokenKeepAspect { + display: none; +} + +#tokenPreview_zone { + position: relative; } \ No newline at end of file diff --git a/static/util.js b/static/util.js index 46f020f..3448c98 100644 --- a/static/util.js +++ b/static/util.js @@ -30,7 +30,6 @@ function loadName() { if (username) { const cookies = document.cookie.split(";") cookies.forEach(c=>{ - console.log(c); if (c.trim().startsWith("username=")) { username.value = c.trim().split("=")[1]; }