-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit e73a5f0
Showing
8 changed files
with
10,537 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
Large diffs are not rendered by default.
Oops, something went wrong.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// This is the "root" _module_ which is loaded by bootstrap_nonmod.js and imports all others. | ||
|
||
import init, { start_game } from './all_is_cubes_wasm.js'; | ||
|
||
|
||
document.getElementById('loading-log').innerText = 'Loading code...'; | ||
|
||
// init() is a function generated by wasm-pack (wasm-bindgen?) which loads the actual wasm | ||
init().then(() => start_game()).catch(error => { | ||
// TODO: This no longer does very much useful since start_game() is async and the panic | ||
// doesn't turn into a promise failure. | ||
|
||
document.getElementById('loading-log').innerText += | ||
'\nError during initial loading! Check console for details.'; | ||
|
||
if (String(error) !== 'RuntimeError: unreachable') { | ||
// Only log errors that aren't Rust's panics because those are logged separately. | ||
console.error(error); | ||
} | ||
}); |
98 changes: 98 additions & 0 deletions
98
client/snippets/all-is-cubes-wasm-ed7534c6cefcab5e/src/js/gui.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// HTML GUI code, including management of the WebGL canvas outside of | ||
// actually drawing. | ||
// | ||
// This is in JS because writing DOM-based GUI code from Rust raises all sorts | ||
// lifetime and reference management issues. | ||
// The Rust bindings for this file may be found in src/js_bindings.js. | ||
|
||
// Construct all GUI helper objects that refer to elements defined in the HTML | ||
// rather than created dynamically. | ||
export function makeAllStaticGuiHelpers(window, document) { | ||
const result = { | ||
canvasHelper: new CanvasHelper(document.getElementById('view-canvas')), | ||
}; | ||
|
||
// Set up initial focus | ||
result.canvasHelper.canvas.focus(); | ||
|
||
return result; | ||
} | ||
|
||
// Manages a <canvas> element; particularly, resizing it to have 1:1 pixel resolution. | ||
export class CanvasHelper { | ||
// TODO: unit test this class ... where? | ||
|
||
constructor(canvas) { | ||
if (!canvas) throw new Error('canvas missing'); | ||
|
||
this.canvas = canvas; | ||
|
||
const canvasComputedStyle = window.getComputedStyle(canvas, null); | ||
let layoutPixelWidth; | ||
let layoutPixelHeight; | ||
|
||
const updateViewport = () => { | ||
// allow canvas to flex-shrink, then get actual size | ||
canvas.width = 1; | ||
canvas.height = 1; | ||
layoutPixelWidth = parseInt(canvasComputedStyle.width, 10); | ||
layoutPixelHeight = parseInt(canvasComputedStyle.height, 10); | ||
|
||
canvas.width = layoutPixelWidth * window.devicePixelRatio; | ||
canvas.height = layoutPixelHeight * window.devicePixelRatio; | ||
|
||
this.viewportPx = Object.freeze([layoutPixelWidth, layoutPixelHeight]); | ||
this.viewportDev = Object.freeze([canvas.width, canvas.height]); | ||
}; | ||
this.updateViewport = updateViewport; // allow explicit calls | ||
|
||
updateViewport(); | ||
|
||
const resizeObserver = new ResizeObserver(_entries => { | ||
updateViewport(); | ||
// TODO once we have the _option_ of not rendering if nothing changed, | ||
// we'll need to tell the renderer to render because the aspect ratio changed. | ||
}); | ||
resizeObserver.observe(canvas); | ||
} | ||
|
||
// property .canvas | ||
|
||
// property .viewportPx | ||
|
||
// Attempt to enter or leave fullscreen mode. | ||
// | ||
// TODO: This and its companion isFullscreen() make document.body fullscreen, but for | ||
// more flexibility we should have an explicit canvas-and-everything container element. | ||
setFullscreen(shouldBeFullscreen) { | ||
const document = this.canvas.ownerDocument; | ||
|
||
if (shouldBeFullscreen) { | ||
if (document.body.requestFullscreen) { | ||
document.body.requestFullscreen(); | ||
} else if (document.body.webkitRequestFullscreen) { | ||
// Safari still does not have unprefixed fullscreen API as of version 16.1 | ||
document.body.webkitRequestFullscreen(); | ||
} else { | ||
// TODO: instead we should have noticed this from the start and not enabled | ||
// fullscreen control | ||
alert("Full screen not supported, apparently."); | ||
} | ||
} else { | ||
if (document.exitFullscreen) { | ||
document.exitFullscreen(); | ||
} else if (document.webkitExitFullscreen) { | ||
document.webkitExitFullscreen(); | ||
} | ||
} | ||
} | ||
|
||
isFullscreen() { | ||
const document = this.canvas.ownerDocument; | ||
|
||
// Note: this test must be consistent with what we _make_ fullscreen. | ||
console.log("fse", document.webkitFullscreenElement); | ||
return document.fullscreenElement === document.body | ||
|| document.webkitFullscreenElement === document.body; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<!doctype html> | ||
<html id="app-root" class="state-script-not-loaded"><head> | ||
<title>All is Cubes</title> | ||
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> | ||
<meta name="viewport" content="width=device-width"> | ||
<link rel="stylesheet" href="style.css" type="text/css"> | ||
<script defer type="module" src="client/bootstrap.js"></script> | ||
</head><body> | ||
|
||
<div class="overlay-bounds"> | ||
<canvas id="view-canvas" tabindex="0" class="viewport" width="640" height="480"> | ||
<!-- Only visible to browsers which do not recognize <canvas> --> | ||
<div class="error-notice"> | ||
<p>Sorry, but the web browser you are using does not appear to support WebGL.</p> | ||
</div> | ||
</canvas> | ||
<div id="license-overlay"><a href="third-party-licenses.html">Open source licenses</a></div> | ||
<div id="scene-info-overlay" class="overlay"> | ||
<progress id="loading-progress-bar" value="0.0" min="0.0" max="1.0"></progress> | ||
<pre id="loading-log">JavaScript not loaded...</pre> | ||
<pre id="scene-info-text"></pre> | ||
</div> | ||
</div> | ||
|
||
</body></html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
html, body { | ||
background: gray; /* ordinarily invisible, but makes initial loading better */ | ||
} | ||
|
||
.overlay-bounds { | ||
position: relative; /* define a new positioning root */ | ||
overflow: hidden; | ||
} | ||
|
||
.overlay { | ||
position: absolute; | ||
font-weight: bold; | ||
color: white; | ||
text-shadow: 0 0 .1em #000, 0 0 .1em #000; | ||
margin: 0 0; | ||
display: table; | ||
pointer-events: none; | ||
user-select: none; /* prevents selection-like clicking *through* the overlay from applying */ | ||
} | ||
.overlay p, .overlay pre { | ||
margin: 0; | ||
} | ||
.overlay .object-chip { | ||
pointer-events: auto; | ||
} | ||
|
||
#scene-info-overlay { | ||
position: absolute; | ||
left: 1px; | ||
top: 1px; | ||
} | ||
|
||
/* --- main UI layout --- */ | ||
|
||
/* ensure that our content fills the window and has no layout-quirk scrollbars */ | ||
html, body { | ||
margin: 0; | ||
border: 0; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
|
||
body { | ||
overflow: hidden; /* suppress extra margin in moz flexbox */ | ||
display: flex; | ||
flex-direction: row; | ||
} | ||
|
||
.overlay-bounds { | ||
display: flex; | ||
flex: 1 1; | ||
height: 100%; | ||
} | ||
.viewport { | ||
flex: 1 1; | ||
display: block; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
|
||
#loading-progress-bar { | ||
box-sizing: content-box; | ||
/* TODO: this is width of the text box container, right now */ | ||
width: 100%; | ||
} | ||
.state-fully-loaded #loading-progress-bar { | ||
display: none; | ||
} | ||
|
||
/* --- block menu --- */ | ||
|
||
#menu-container { /* exists to support centering */ | ||
position: absolute; | ||
pointer-events: none; | ||
left: 0; | ||
bottom: 0; | ||
display: table; | ||
width: 100%; | ||
} | ||
#menu { | ||
pointer-events: auto; | ||
margin: 2px auto; | ||
background: #333; | ||
background: rgba(0, 0, 0, 0.5); | ||
color: white; | ||
border-radius: 5px; | ||
display: table; | ||
text-align: center; | ||
font-family: monospace; | ||
} | ||
.menu-item { | ||
display: inline-block; | ||
position: relative; | ||
margin: 1px 1px; | ||
} | ||
.menu-item td { | ||
margin: 0; | ||
padding: 0; | ||
} | ||
.menu-item canvas { | ||
vertical-align: middle; /* remove baseline gap */ | ||
} | ||
.menu-shortcut-key { | ||
position: absolute; | ||
bottom: -1px; | ||
left: 1px; | ||
} | ||
#menu .selected-tool { | ||
border-radius: 5px; | ||
margin: -1px -1px; /* outlines don't have radius */ | ||
border: 2px solid white; | ||
background: gray; | ||
} | ||
|
||
.ui-mode-hidden #menu { visibility: hidden; } | ||
.ui-mode-hidden #quick-bar .menu-item { visibility: visible; } | ||
.ui-mode-hidden #quick-bar { opacity: 0.75; } | ||
|
||
/* --- --- */ | ||
|
||
#error-notices { | ||
position: absolute; | ||
top: 5em; | ||
right: 50%; | ||
margin-right: -17em; | ||
|
||
z-index: 1; | ||
} | ||
.error-notice { | ||
border-radius: 2em; | ||
text-align: center; | ||
max-width: 30em; | ||
padding: 1em 2em; | ||
border: .2em solid red; | ||
|
||
background: white; | ||
color: black; | ||
font: message-box; | ||
} | ||
|
||
#license-overlay { | ||
position: absolute; | ||
bottom: 6px; | ||
right: 6px; | ||
text-align: right; | ||
} | ||
#license-overlay * { | ||
/* override link color for contrast */ | ||
color: white; | ||
text-shadow: 0 0 .1em #000; | ||
background: none; | ||
} |
Oops, something went wrong.