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];
}