diff --git a/global/globalScript.js b/global/globalScript.js
index bca46cd..880a3e1 100644
--- a/global/globalScript.js
+++ b/global/globalScript.js
@@ -5,7 +5,8 @@ const PAGES = {
TOYS: 2,
LICENSE: 3,
LOADING: 4,
- LIBS: 5
+ LIBS: 5,
+ CRAFTING: 6
}
const CONSOLE_COLORS = {
red: "color: #FF0000;",
@@ -189,6 +190,7 @@ document.addEventListener("DOMContentLoaded", async function () {
case (PAGES.LICENSE): loadingScreenStars(); await loadingScreenLicense(); break
case (PAGES.TOYS): loadingScreenStars(); break
case (PAGES.LIBS): loadingScreenStars(); break
+ case (PAGES.CRAFTING): loadingScreenCrafting(); break
}
if (navBarPresent) {
diff --git a/global/globalStyle.css b/global/globalStyle.css
index 4df0fe6..3a974fd 100644
--- a/global/globalStyle.css
+++ b/global/globalStyle.css
@@ -64,6 +64,9 @@ canvas {
margin: calc(3px * var(--pxDensity)) calc(3px * var(--pxDensity)) 0% 0%;
width: round(auto, var(--pxDensity));
/*height: calc(6px * var(--pxDensity));*/
+ border: none;
+ color: #ffffff;
+ font-size: inherit;
}
.switch {
position: relative;
@@ -109,4 +112,41 @@ canvas {
aspect-ratio: 1 / 1;
image-rendering: pixelated;
transform: translate(-50%, -50%);
+}
+button {
+ display: inline-block;
+ background-color: var(--navBarBtn_Inner);
+ box-shadow: calc(1px * var(--pxDensity)) 0px var(--navBarBtn_Border),
+ calc(-1px * var(--pxDensity)) 0px var(--navBarBtn_Border),
+ 0px calc(1px * var(--pxDensity)) var(--navBarBtn_Border),
+ 0px calc(-1px * var(--pxDensity)) var(--navBarBtn_Border);
+
+ padding: calc(1px * var(--pxDensity));
+ margin: calc(3px * var(--pxDensity)) calc(3px * var(--pxDensity)) 0% 0%;
+ width: round(auto, var(--pxDensity));
+ /*height: calc(6px * var(--pxDensity));*/
+ border: none;
+ color: #ffffff;
+ font-size: inherit;
+}
+button:hover {
+ filter: brightness(1.35) drop-shadow(0px calc(1px * var(--pxDensity)) rgba(0, 0, 0, 0.5));
+ cursor: pointer;
+}
+button:active {
+ filter: brightness(0.75);
+ transform: translateY(calc(1px * var(--pxDensity)));
+}
+button:disabled, button[disabled] {
+ filter: brightness(0.75) drop-shadow(0px calc(1px * var(--pxDensity)) rgba(0, 0, 0, 0.5));
+ cursor: not-allowed;
+}
+button:disabled:hover, button[disabled]:hover {
+ filter: brightness(0.75) drop-shadow(0px calc(1px * var(--pxDensity)) rgba(0, 0, 0, 0.5));
+ cursor: not-allowed;
+}
+button:disabled:active, button[disabled]:active {
+ filter: brightness(0.75) drop-shadow(0px calc(1px * var(--pxDensity)) rgba(0, 0, 0, 0.5));
+ cursor: not-allowed;
+ transform: none;
}
\ No newline at end of file
diff --git a/global/navBar.css b/global/navBar.css
index 66482ed..ebb9378 100644
--- a/global/navBar.css
+++ b/global/navBar.css
@@ -20,27 +20,9 @@ li {
padding: 0%;
border: none;
filter: drop-shadow(0px calc(1px * var(--pxDensity)) rgba(0, 0, 0, 0.5));
-}
-button:hover {
- filter: brightness(1.35) drop-shadow(0px calc(1px * var(--pxDensity)) rgba(0, 0, 0, 0.5));
- cursor: pointer;
-}
-button:active {
- filter: brightness(0.75);
- transform: translateY(calc(1px * var(--pxDensity)));
-}
-.button:disabled, button[disabled] {
- filter: brightness(0.75) drop-shadow(0px calc(1px * var(--pxDensity)) rgba(0, 0, 0, 0.5));
- cursor: not-allowed;
-}
-.button:disabled:hover, button[disabled]:hover {
- filter: brightness(0.75) drop-shadow(0px calc(1px * var(--pxDensity)) rgba(0, 0, 0, 0.5));
- cursor: not-allowed;
-}
-.button:disabled:active, button[disabled]:active {
- filter: brightness(0.75) drop-shadow(0px calc(1px * var(--pxDensity)) rgba(0, 0, 0, 0.5));
- cursor: not-allowed;
- transform: none;
+ margin: 0%;
+ box-shadow: none;
+ width: auto;
}
.navBtnImg {
width: calc(12px * var(--pxDensity));
diff --git a/index.html b/index.html
index 8c67e49..d9ae5fb 100644
--- a/index.html
+++ b/index.html
@@ -35,7 +35,7 @@

-
+
@@ -48,7 +48,7 @@
-
+
diff --git a/toys/crafting/index.html b/toys/crafting/index.html
new file mode 100644
index 0000000..81b0cc9
--- /dev/null
+++ b/toys/crafting/index.html
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Byte Dice - Crafting
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/toys/crafting/script.js b/toys/crafting/script.js
new file mode 100644
index 0000000..bc4db57
--- /dev/null
+++ b/toys/crafting/script.js
@@ -0,0 +1,81 @@
+CURRENT_PAGE = PAGES.CRAFTING
+
+let tomlInputContainer = document.getElementById("tomlInputContainer")
+let collapseButton = document.getElementById("collapseButton")
+let treeStatic = document.getElementById("treeStaticContainer")
+let treeScale = document.getElementById("treeScaleContainer")
+
+
+let mouseX = 0
+let mouseY = 0
+let dragX = 0
+let dragY = 0
+let dragOffsetX = 0
+let dragOffsetY = 0
+let isDragging = false
+let scale = 1
+
+
+let isCollapsed = false
+
+
+document.addEventListener("mousemove", function(event) {
+ mouseX = event.clientX;
+ mouseY = event.clientY;
+})
+
+
+function collapseInput() {
+ const COLLAPSE = "collapse 0.5s cubic-bezier(0, 0, 0, 1.46) forwards"
+ tomlInputContainer.style.animation = COLLAPSE
+ isCollapsed = true
+ collapseButton.textContent = ">"
+}
+
+
+function unCollapseInput() {
+ const UN_COLLAPSE = "un-collapse 0.5s cubic-bezier(0, 0, 0, 1.46) forwards"
+ tomlInputContainer.style.animation = UN_COLLAPSE
+ isCollapsed = false
+ collapseButton.textContent = "<"
+}
+
+
+collapseButton.onclick = function() {
+ if (!isCollapsed) { collapseInput(); }
+ else { unCollapseInput(); }
+}
+
+
+function loadingScreenCrafting() {
+ unCollapseInput();
+}
+
+
+function drag_trees(mouse_offset) {
+ dragX = (mouseX - dragOffsetX) / scale
+ dragY = (mouseY - dragOffsetY) / scale
+
+ trees.style.transform = `translate(${dragX}px, ${dragY}px)`
+}
+function on_start_drag() {
+ dragOffsetX = mouseX - dragX * scale
+ dragOffsetY = mouseY - dragY * scale
+ isDragging = true
+}
+function dragLoop() {
+ if (isDragging) { drag_trees() }
+
+ requestAnimationFrame(dragLoop)
+}
+
+
+treeStatic.onmousedown = on_start_drag
+document.addEventListener("mouseup", function() { isDragging = false })
+treeStatic.addEventListener("wheel", function(event) {
+ scale += (-event.deltaY / 500)
+ scale = Math.max(0.2, scale)
+ treeScale.style.transform = `scale(${scale})`
+})
+
+document.addEventListener("DOMContentLoaded", dragLoop)
\ No newline at end of file
diff --git a/toys/crafting/style.css b/toys/crafting/style.css
new file mode 100644
index 0000000..7973e44
--- /dev/null
+++ b/toys/crafting/style.css
@@ -0,0 +1,84 @@
+.tomlInputContainer textarea {
+ font-family: "Roboto", sans-serif;
+ background-color: var(--navBarBtn_Inner);
+ box-shadow: calc(1px * var(--pxDensity)) 0px var(--navBarBtn_Border),
+ calc(-1px * var(--pxDensity)) 0px var(--navBarBtn_Border),
+ 0px calc(1px * var(--pxDensity)) var(--navBarBtn_Border),
+ 0px calc(-1px * var(--pxDensity)) var(--navBarBtn_Border);
+
+ padding: calc(1px * var(--pxDensity));
+ border: none;
+ font-size: min(5vmin, 1.2vmax, 0.9rem);
+ margin: calc(3px * var(--pxDensity)) 0% 0% 0%;
+ box-sizing: border-box;
+ width: calc(60px * var(--pxDensity));
+ /*height: calc(100px * var(--pxDensity));*/
+ height: 65vh;
+ color: inherit;
+ display: inline-block;
+ text-align: left;
+ resize: none
+}
+.tomlInputContainer textarea:hover {
+ filter: brightness(1.35);
+ cursor: pointer;
+}
+
+
+.tomlInputContainer label {
+ background-color: var(--navBarBtn_Inner);
+ box-shadow: calc(1px * var(--pxDensity)) 0px var(--navBarBtn_Border),
+ calc(-1px * var(--pxDensity)) 0px var(--navBarBtn_Border),
+ 0px calc(1px * var(--pxDensity)) var(--navBarBtn_Border),
+ 0px calc(-1px * var(--pxDensity)) var(--navBarBtn_Border);
+
+ padding: calc(1px * var(--pxDensity));
+ box-sizing: border-box;
+ width: round(auto, var(--pxDensity));
+ height: calc(6px * var(--pxDensity));
+ font-weight: 800;
+ text-align: center;
+}
+
+
+.tomlInputGrid {
+ display: grid;
+}
+
+
+.tomlInputContainer {
+ position: relative;
+ display: inline-flex;
+ margin: 0% auto 0% auto;
+ width: max-content;
+ max-height: 70vh;
+ padding: calc(2px * var(--pxDensity));
+ max-width: min(600px, 100vw, 100vw);
+ font-size: min(1.5rem, calc(4px * var(--pxDensity)));
+ box-sizing: border-box;
+}
+
+
+#generateButton {
+ width: 100%;
+ height: calc(6px * var(--pxDensity));
+}
+
+
+#collapseButton {
+ margin: 0% calc(3px * var(--pxDensity));
+ height: calc(6px * var(--pxDensity));
+ width: calc(6px * var(--pxDensity));
+ aspect-ratio: 1 / 1;
+}
+
+
+@keyframes collapse {
+ 0% { transform: translateX(0%); }
+ 100% { transform: translateX(calc(-63px * var(--pxDensity))); }
+}
+
+@keyframes un-collapse {
+ 0% { transform: translateX(calc(-63px * var(--pxDensity))); }
+ 100% { transform: translateX(0%); }
+}
\ No newline at end of file
diff --git a/toys/crafting/tree.css b/toys/crafting/tree.css
new file mode 100644
index 0000000..cfb4e64
--- /dev/null
+++ b/toys/crafting/tree.css
@@ -0,0 +1,85 @@
+#trees {
+ position: absolute;
+ left: 0%;
+ top: 0%;
+ width: max-content;
+ height: max-content;
+ padding: calc(16px * var(--pxDensity)) calc(2px * var(--pxDensity));
+ overflow: visible;
+ display: flex;
+ flex-direction: column;
+ gap: calc(5px * var(--pxDensity));
+ user-select: none;
+}
+
+.tree {
+ display: inline-flex;
+ justify-content: center;
+ width: min-content;
+ height: min-content;
+ padding: calc(3px * var(--pxDensity));
+ background-color: rgba(0.1, 0.1, 0.1, 0.1);
+ user-select: none;
+}
+.item {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ overflow: visible;
+ margin-bottom: calc(3px * var(--pxDensity));
+ user-select: none;
+}
+.siblings {
+ display: flex;
+ justify-content: center;
+ gap: calc(3px * var(--pxDensity));
+ align-items: flex-end;
+ background-color: rgba(0.1, 0.1, 0.1, 0.1);
+ padding: calc(2px * var(--pxDensity));
+ margin-bottom: calc(3px * var(--pxDensity));
+ user-select: none;
+}
+
+.item p { /* from .encased */
+ display: inline-block;
+ background-color: var(--navBarBtn_Inner);
+ box-shadow: calc(1px * var(--pxDensity)) 0px var(--navBarBtn_Border),
+ calc(-1px * var(--pxDensity)) 0px var(--navBarBtn_Border),
+ 0px calc(1px * var(--pxDensity)) var(--navBarBtn_Border),
+ 0px calc(-1px * var(--pxDensity)) var(--navBarBtn_Border);
+
+ padding: calc(1px * var(--pxDensity));
+ width: round(auto, var(--pxDensity));
+ height: calc(3px * var(--pxDensity));
+ border: none;
+ color: #ffffff;
+ font-size: min(5vmin, 1.2vmax, 0.9rem);
+ min-width: calc(12px * var(--pxDensity));
+ text-align: center;
+ margin: 0;
+ user-select: none;
+}
+.item .blue {
+ background-color: var(--navBar_Inner);
+ box-shadow: calc(1px * var(--pxDensity)) 0px var(--navBar_Border),
+ calc(-1px * var(--pxDensity)) 0px var(--navBar_Border),
+ 0px calc(1px * var(--pxDensity)) var(--navBar_Border),
+ 0px calc(-1px * var(--pxDensity)) var(--navBar_Border);
+}
+
+
+#treeStaticContainer {
+ position: fixed;
+ top: 0%;
+ left: 0%;
+ width: 100vw;
+ height: 100vh;
+ display: inline-block;
+ cursor: grab;
+}
+
+#treeScaleContainer {
+ width: 100vw;
+ height: 100vh;
+}
\ No newline at end of file
diff --git a/toys/crafting/tree_generator.js b/toys/crafting/tree_generator.js
new file mode 100644
index 0000000..b8fc2e0
--- /dev/null
+++ b/toys/crafting/tree_generator.js
@@ -0,0 +1,120 @@
+import { parse } from "https://esm.sh/smol-toml"
+
+let tomlInput = document.getElementById("tomlInput")
+let genButton = document.getElementById("generateButton")
+let trees = document.getElementById("trees")
+
+let recipes = {}
+let startItems = []
+let products = []
+
+
+genButton.onclick = getDataFromInput
+
+
+function getDataFromInput() {
+ let input = tomlInput.value
+ try {
+ let json = parse(input)
+
+ startItems = json.io.inputs
+ products = json.io.products
+ recipes = json.recipes
+ } catch (e) { alert(e) }
+
+ clearTrees()
+
+ for (let product of products) {
+ console.log("generating: \"" + product + "\"")
+ genTreeForProduct(product)
+ }
+}
+
+
+function genTreeForProduct(product) {
+ let treeData = RecursivelyGetRecipes(product)
+
+ let treeNode = document.createElement("div")
+ treeNode.className = "tree"
+
+ makeTreeHTML(treeData, treeNode, true)
+
+ trees.appendChild(treeNode)
+}
+
+
+function RecursivelyGetRecipes(product) {
+ let recipe = recipes[product]
+
+ if (recipe == undefined) {
+ alert("ERROR: Recipe not found for \"" + product + "\"")
+ return [product]
+ }
+
+ let children = []
+
+ for (let item of recipe) {
+ if (startItems.includes(item)) { children.push(item) }
+ else { children.push(...RecursivelyGetRecipes(item)) }
+ }
+
+ return [product, children]
+}
+
+
+function prettyTreeString(tree, indent=0) {
+ let string = ""
+
+ for (let item of tree) {
+ if (typeof item == "string")
+ { string += "| ".repeat(indent) + item + "\n" }
+ else { string += prettyTreeString(item, indent + 1) }
+ }
+
+ return string
+}
+
+
+function clearTrees() {
+ let children = trees.children
+ for (let c of children) { c.remove() }
+}
+
+
+function makeTreeHTML(tree, parentNode, blue = false) {
+ let previouslyAdded = undefined
+
+ let stringCount = tree.filter((x) => typeof(x) == "string").length
+ let arrCount = tree.length - stringCount
+
+ // add .siblings container if theres more than 1 .item
+ if (stringCount > 1) {
+ let s = document.createElement("div")
+ s.className = "siblings"
+ parentNode.prepend(s)
+ parentNode = s
+ }
+ if (arrCount == 0) { blue = true }
+
+ for (let i = 0; i < tree.length; i++) {
+ if (typeof(tree[i]) == "string") {
+ if (tree.length - 1 == i || tree[i + 1] == "string") { blue = true }
+ let n = makeItemNode(tree[i], blue)
+ parentNode.prepend(n)
+ previouslyAdded = n
+ }
+ else { makeTreeHTML(tree[i], previouslyAdded, false) }
+ }
+}
+
+
+function makeItemNode(name, blue = false) {
+ let node = document.createElement("div")
+ node.className = "item"
+ let p = document.createElement("p")
+ if (blue) { p.className = "blue" }
+ p.textContent = name
+ node.appendChild(p)
+
+ return node
+}
\ No newline at end of file
diff --git a/toys/index.html b/toys/index.html
index 910c24f..45966f0 100644
--- a/toys/index.html
+++ b/toys/index.html
@@ -50,6 +50,15 @@
+
+
+
diff --git a/toys/style.css b/toys/style.css
index c0e322e..46a26f6 100644
--- a/toys/style.css
+++ b/toys/style.css
@@ -36,7 +36,7 @@ h1 {
margin: 0%;
}
button:hover {
- filter: brightness(1.15) drop-shadow(0px calc(1px * var(--pxDensity)) rgba(0, 0, 0, 0.5));
+ filter: brightness(1.15) drop-shadow(0px calc(2px * var(--pxDensity)) rgba(0, 0, 0, 0.5));
cursor: pointer;
}
button:active {
@@ -44,7 +44,7 @@ button:active {
transform: translateY(calc(1px * var(--pxDensity)));
}
.toyUl {
- padding: calc(3px * var(--pxDensity));
+ padding: 0% calc(3px * var(--pxDensity));
display: inline-flex;
width: fit-content;
justify-content: center;