Browse Source

Platform: overhaul builtin style+markup for Emscripten apps.

What's new:

 * The style is consistent with the dark m.css theme that's used on the
   website and so provides a bit better "brand identity".
 * The canvas is responsive, looking properly on mobile and scaling down
   with aspect ratio preservation if the screen is too narrow.
 * It's now possible to override canvas size and aspect ratio or make it
   "fullscreen", i.e. occupying the whole browser window.
 * If the app crashes, a helpful message is printed instead of
   everything just being stuck.
pull/272/head
Vladimír Vondruš 8 years ago
parent
commit
b2cb689cdc
  1. 11
      doc/changelog.dox
  2. 213
      doc/platforms-html5.dox
  3. 28
      src/Magnum/Audio/al-info.html
  4. 40
      src/Magnum/Platform/EmscriptenApplication.js
  5. 19
      src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp
  6. 34
      src/Magnum/Platform/Test/Sdl2ApplicationTest.html
  7. 25
      src/Magnum/Platform/Test/WindowlessEglApplicationTest.html
  8. 186
      src/Magnum/Platform/WebApplication.css
  9. 40
      src/Magnum/Platform/WindowlessEmscriptenApplication.js
  10. 27
      src/Magnum/Platform/gl-info.html

11
doc/changelog.dox

@ -178,6 +178,17 @@ See also:
- @ref Platform::Sdl2Application::viewportEvent() "Platform::*Application::viewportEvent()"
now gets all information needed for DPI-aware rendering instead of just
a framebuffer size --- now also window size and the DPI scaling value
- Overhauled the builtin @ref platforms-html5 "Emscripten" HTML markup and
styling for HTML5/WebGL apps:
- the builtin style now matches the dark theme of the Magnum website
- canvas is responsively sized and preserves aspect ratio when scaled
down
- when the app aborts, a helpful message is printed instead of everything
getting stuck
- it's possible to override the default canvas size and aspect ratio,
see @ref platforms-html5-layout
- documentation explaining quirks of event handling, see
@ref platforms-html5-events
- @ref Platform::GlfwApplication now behaves the same as
@ref Platform::Sdl2Application when creating an OpenGL context: first it
attempts to create a forward-compatible core OpenGL 3.2+ context and if

213
doc/platforms-html5.dox

@ -90,7 +90,7 @@ cd build-emscripten-wasm/src
node my-application.js
@endcode
@section platforms-html5-apps Building and deploying graphics apps
@section platforms-html5-apps Building and deploying graphical apps
In case you don't have an OpenGL ES build set up yet, you need to copy
`FindOpenGLES2.cmake` (or `FindOpenGLES3.cmake`) from the
@ -117,36 +117,43 @@ install prefix.
@code{.html-jinja}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Magnum Emscripten Application</title>
<link rel="stylesheet" href="WebApplication.css" />
</head>
<body>
<h1>Magnum Emscripten Application</h1>
<div id="listener">
<head>
<meta charset="UTF-8" />
<title>Magnum Emscripten Application</title>
<link rel="stylesheet" href="WebApplication.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<h1>Magnum Emscripten Application</h1>
<div id="container">
<div id="sizer"><div id="expander"><div id="listener">
<canvas id="module"></canvas>
<div id="status">Initialization...</div>
<div id="statusDescription"></div>
<div id="status-description"></div>
<script src="EmscriptenApplication.js"></script>
<script async="async" src="{{ application }}.js"></script>
</div>
</body>
</div></div></div>
</div>
</body>
</html>
@endcode
Replace @cb{.jinja} {{ application }} @ce with the name of your application
executable. You can modify all the files to your liking, but the HTML file must
contain at least the @cb{.html} <canvas> @ce enclosed in listener
@cb{.html} <div> @ce. The JavaScript file contains event listeners which print
loading status on the page. The status displayed in the remaining two
@cb{.html} <div> @ce s, if they are available. The CSS file contains
a rudimentary style.
In order to deploy the app, you need to install the JS driver code, the
WebAssembly binary (or the asm.js memory image, in case you are compiling
with the classic asm.js toolchain), the HTML markup and the JS/CSS modules to a
common location. The following CMake snippet handles all of that:
For basic usage you don't need to modify the CSS and JS files at all and
everything can be set up directly from the HTML markup. Replace
@cb{.jinja} {{ application }} @ce with the name of your application executable
and adapt page title and heading as desired. You can modify all files to your
liking, but the HTML file must contain at least
@cb{.html} <canvas id="module"> @ce enclosed in
@cb{.html} <div id="listener"> @ce. The JavaScript file contains event
listeners that print loading status on the page. The status is displayed in the
remaining two @cb{.html} <div> @ce s, if they are available. The CSS file
contains a basic style, see @ref platforms-html5-layout "below" for available
options to tweak the default look.
In order to deploy the app, you need to put the JS driver code, the WebAssembly
binary (or the asm.js memory image, in case you are compiling with the classic
asm.js toolchain), the HTML markup and the JS/CSS files to a common location.
The following CMake snippet handles all of that:
@code{.cmake}
if(CORRADE_TARGET_EMSCRIPTEN)
@ -194,9 +201,9 @@ class. See its documentation for more information
about general usage. You can also use the Emscripten APIs directly or any other
way.
@note The @ref Platform::WindowlessEglApplication also contains a fully
configured bootstrap project that's ready to build and deploy. Check its
documentation for details.
@note @ref Platform::WindowlessEglApplication also contains a fully configured
bootstrap project that's ready to build and deploy. Check its documentation
for details.
Similarly to graphics apps, you need to provide a HTML markup for your
application. Template one is below, its main difference from the one above is
@ -209,22 +216,25 @@ install prefix.
@code{.html-jinja}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Magnum Windowless Emscripten Application</title>
<link rel="stylesheet" href="WebApplication.css" />
</head>
<body>
<h1>Magnum Windowless Emscripten Application</h1>
<div id="listener">
<head>
<meta charset="UTF-8" />
<title>Magnum Windowless Emscripten Application</title>
<link rel="stylesheet" href="WebApplication.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<h1>Magnum Windowless Emscripten Application</h1>
<div id="container">
<div id="sizer"><div id="expander"><div id="listener">
<canvas id="module" class="hidden"></canvas>
<pre id="log"></pre>
<div id="status">Initialization...</div>
<div id="statusDescription"></div>
<div id="status-description"></div>
<script src="WindowlessEmscriptenApplication.js"></script>
<script async="async" src="{{ application }}.js"></script>
</div>
</body>
</div></div></div>
</div>
</body>
</html>
@endcode
@ -234,9 +244,11 @@ contain at least the @cb{.html} <canvas> @ce enclosed in listener @cb{.html} <di
and the @cb{.html} <pre id="log"> @ce for displaying the output. The JavaScript
file contains event listeners which print loading status on the page. The
status displayed in the remaining two @cb{.html} <div> @ce s, if they are
available. The CSS file contains a rudimentary style.
available. The CSS file is shared with graphical apps, again see
@ref platforms-html5-layout "below" for available options to tweak the default
look.
Deployment is similar to @ref platforms-html5-apps "graphics apps", only
Deployment is similar to @ref platforms-html5-apps "graphical apps", only
referencing a different JS file:
@code{.cmake}
@ -254,12 +266,125 @@ if(CORRADE_TARGET_EMSCRIPTEN)
endif()
@endcode
@section platforms-html5-layout Modifying page style, canvas size and aspect ratio
The `WebApplication.css` file contains a basic style and the additional
@cb{.css} .container @ce, @cb{.css} .sizer @ce and @cb{.css} .expander @ce
@cb{.html} <div> @ce s take care of aligning the canvas to the center and
making it responsively scale on narrow screens, preserving aspect ratio. For
proper responsiveness on all platforms it's important to include the
@cb{.html} <meta name="viewport"> @ce tag in the HTML markup as well.
By default the canvas is @cpp 640px @ce wide with a 4:3 aspect ratio, you can
modify this by placing one of the @cb{.css} .aspect-* @ce CSS classes on the
@cb{.html} <div id="container"> @ce:
Aspect ratio | CSS class (landscape/portrait)
--------------- | ------------------------------
1:1 | @cb{.css} .aspect-1-1 @ce <b></b>
4:3 (1.33:1) | @cb{.css} .aspect-4-3 @ce (default) / @cb{.css} .aspect-3-4 @ce
3:2 (1.5:1) | @cb{.css} .aspect-3-2 @ce / @cb{.css} .aspect-2-3 @ce
16:9 (1.78:1) | @cb{.css} .aspect-16-9 @ce / @cb{.css} .aspect-9-16 @ce
2:1 | @cb{.css} .aspect-2-1 @ce / @cb{.css} .aspect-1-2 @ce
For example, for a 640x360 canvas (16:9 aspect ratio), you would use
@cb{.html} <div id="container" class="aspect-16-9"> @ce. Besides the predefined
classes above, it's also possible to specify your own aspect ratio using a
@cb{.css} padding-bottom @ce style with a percentage equal to inverse of
the ratio for @cb{.css} div#expander @ce --- for example, a 2.35:1 ratio would
be @cb{.html} <div id="expander" style="padding-bottom: 42.553%"> @ce.
Size of the canvas can be also overriden by specifying one of the
@cb{.css} .width-* @ce CSS classes on the @cb{.html} <div id="container"> @ce:
Width | CSS class
--------------- | ---------
240px | @cb{.css} .width-240 @ce <b></b>
320px | @cb{.css} .width-320 @ce <b></b>
360px | @cb{.css} .width-360 @ce <b></b>
480px | @cb{.css} .width-480 @ce <b></b>
600px | @cb{.css} .width-600 @ce <b></b>
640px | @cb{.css} .width-640 @ce (default)
800px | @cb{.css} .width-800 @ce <b></b>
For example, for a 480x640 canvas (3:4, portrait) you would use
@cb{.html} <div id="container" class="width-480 aspect-3-4"> @ce. Besides the
predefined classes above, it's also possible to specify your own by adding a
@cb{.css} width @ce style to the @cb{.css} div#sizer @ce --- for example, a
1024x768 canvas would be @cb{.html} <div id="sizer" style="width: 1024px"> @ce.
Again note that if the canvas is larger than window width, it gets
automatically scaled down, preserving its aspect ratio.
It's also possible to stretch the canvas to occupy the full page using the
@cb{.css} .fullsize @ce CSS class set to @cb{.css} div#container @ce. In this
case it's advised to remove all other elements (such as the @cb{.html} <h1> @ce
element) from the page to avoid them affecting the canvas. Combining
@cb{.css} .fullsize @ce with the other @cb{.css} .aspect-* @ce or
@cb{.css} .width-* @ce classes is not supported.
@section platforms-html5-events Controlling event behavior
@subsection platforms-html5-events-keyboard Keyboard events
By default, the graphical Emscripten application grabs all keyboard input
anywhere on the page (so e.g. @m_class{m-label m-default} **F5** or opening
browser console via a keyboard shortcut doesn't work). If you don't want it to
grab keyboard input at all, set @cb{.js} Module.doNotCaptureKeyboard @ce to
@cb{.js} true @ce, either by modifying the `EmscriptenApplication.js` file or
directly in the HTML source:
@code{.html}
<script>
// after EmscriptenApplication.js has been loaded
Module.doNotCaptureKeyboard = true;
</script>
@endcode
The above is implicitly set for windowless apps, because these don't have any
event loop.
Another solution is to specify the element on which it should capture keybard
using @cb{.js} Module.keyboardListeningElement @ce --- it requires the actual
element instance (*not* just its ID). The element then needs to be activated
(for example with a mouse click) in order to start receiving input. The
@cb{.html} <canvas> @ce element is a bit special in this regard --- in order to
make it receive keyboard input, you have to add a `tabindex` attribute to it
like this:
@code{.html}
<canvas id="module" tabindex="0"></canvas>
@endcode
After that, the canvas can be focused with a @m_class{m-label m-default} **Tab**
key. But because Emscripten eats all mouse input, the `mousedown` event won't
be propagated to focus the canvas unlesss you do that manually:
@code{.js}
Module.keyboardListeningElement = Module.canvas;
Module.canvas.addEventListener('mousedown', function(event) {
event.target.focus();
});
@endcode
@subsection platforms-html5-events-contextmenu Context menu
By default, the canvas opens a browser-specific popup menu on right click. That
allows the user to for example save a screenshot of the canvas, but if you are
handling right click directly in your app, you may want to disable the default
behavior:
@code{.js}
Module.canvas.addEventListener('contextmenu', function(event) {
event.preventDefault();
}, true);
@endcode
@section platforms-html5-environment Terminal output, environment and command-line arguments
When running console apps using Node.js, command-line arguments and terminal
output work like usual.
For graphics apps in the browser, `EmscriptenApplication.js` redirects all
For graphical apps in the browser, `EmscriptenApplication.js` redirects all
output (thus also @ref Corrade::Utility::Debug "Debug",
@ref Corrade::Utility::Warning "Warning" and @ref Corrade::Utility::Error "Error")
to JavaScript console. For windowless apps, `WindowlessEmscriptenApplication.js`
@ -380,14 +505,14 @@ following scenarios are possible:
- By default, the size of Emscripten heap is restricted to 16 MB. That might
not be enough if you have large compiled-in resources or allocate large
amount of memory. This can be solved either with:
amount of memory. This can be solved with either of these:
- Adding `-s TOTAL_MEMORY=&lt;bytes&gt;` to compiler/linker flags, where
&lt;bytes&gt; is the new heap size
- Adding `-s ALLOW_MEMORY_GROWTH=1` to compiler/linker flags. This is
useful in case you don't know how much memory you need in advance and
[might disable some optimizations](https://kripken.github.io/emscripten-site/docs/optimizing/Optimizing-Code.html#memory-growth).
- Setting `Module { TOTAL_MEMORY: &lt;bytes&gt;; }` in the JavaScript
driver file
- Setting @cb{.js} Module { TOTAL_MEMORY: <bytes>; } @ce in the
JavaScript driver file
- Sometimes Chromium-based browsers refuse to create WebGL context on a
particular page, while on other sites it works and the same page works in
other browsers such as Firefox. This can be caused by Chromium running for

28
src/Magnum/Audio/al-info.html

@ -1,18 +1,22 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Magnum AL Info</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="WebApplication.css" />
</head>
<body>
<h1>Magnum AL Info</h1>
<div id="listener">
<html>
<head>
<meta charset="UTF-8" />
<title>Magnum AL Info</title>
<link rel="stylesheet" href="WebApplication.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<h1>Magnum AL Info</h1>
<div id="container">
<div id="sizer"><div id="expander"><div id="listener">
<canvas id="module" class="hidden"></canvas>
<pre id="log"></pre>
<div id="status">Initialization...</div>
<div id="statusDescription"></div>
<div id="status-description"></div>
<script src="WindowlessEmscriptenApplication.js"></script>
<script async="async" src="magnum-al-info.js"></script>
</div>
</body>
</div></div></div>
</div>
</body>
</html>

40
src/Magnum/Platform/EmscriptenApplication.js

@ -1,3 +1,28 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
var Module = {
preRun: [],
postRun: [],
@ -12,6 +37,13 @@ var Module = {
console.log(Array.prototype.slice.call(arguments).join(' '));
},
onAbort: function() {
Module.canvas.style.opacity = 0.333;
Module.canvas.style.zIndex = -1;
Module.setStatus("Oops :(");
Module.setStatusDescription("The app crashed. Refresh the page or check the browser console for details.");
},
canvas: document.getElementById('module'),
setStatus: function(message) {
@ -20,7 +52,7 @@ var Module = {
},
setStatusDescription: function(message) {
var statusDescription = document.getElementById('statusDescription');
var statusDescription = document.getElementById('status-description');
if(statusDescription) statusDescription.innerHTML = message;
},
@ -31,7 +63,7 @@ var Module = {
if(left) {
Module.setStatus('Downloading...');
Module.setStatusDescription((this.totalDependencies - left) + '/' + this.totalDependencies);
Module.setStatusDescription((this.totalDependencies - left) + ' / ' + this.totalDependencies);
} else {
Module.setStatus('Download complete');
Module.setStatusDescription('');
@ -54,7 +86,3 @@ for(var i = 0; i != args.length; ++i) {
}
Module.setStatus('Downloading...');
Module.canvas.addEventListener('contextmenu', function(event) {
event.preventDefault();
}, true);

19
src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp

@ -28,8 +28,25 @@
namespace Magnum { namespace Platform { namespace Test {
struct Sdl2ApplicationTest: Platform::Application {
explicit Sdl2ApplicationTest(const Arguments& arguments): Platform::Application{arguments} {}
/* For testing resize events */
explicit Sdl2ApplicationTest(const Arguments& arguments): Platform::Application{arguments, Configuration{}.setWindowFlags(Configuration::WindowFlag::Resizable)} {}
void drawEvent() override {}
/* For testing HiDPI resize events */
void viewportEvent(ViewportEvent& event) override {
Debug{} << "viewport event" << event.windowSize() << event.framebufferSize() << event.dpiScaling();
}
/* For testing event coordinates */
void mousePressEvent(MouseEvent& event) override {
Debug{} << event.position();
}
/* For testing keyboard capture */
void keyPressEvent(KeyEvent& event) override {
Debug{} << event.keyName();
}
};
}}}

34
src/Magnum/Platform/Test/Sdl2ApplicationTest.html

@ -1,18 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Magnum Sdl2Application Test</title>
<link rel="stylesheet" href="WebApplication.css" />
</head>
<body>
<h1>Magnum Sdl2Application Test</h1>
<div id="listener">
<canvas id="module"></canvas>
<head>
<meta charset="UTF-8" />
<title>Magnum Sdl2Application Test</title>
<link rel="stylesheet" href="WebApplication.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<h1>Magnum Sdl2Application Test</h1>
<div id="container">
<div id="sizer"><div id="expander"><div id="listener">
<canvas id="module" tabindex="0"></canvas>
<div id="status">Initialization...</div>
<div id="statusDescription"></div>
<div id="status-description"></div>
<script src="EmscriptenApplication.js"></script>
<script async="async" src="PlatformSdl2ApplicationTest.js"></script>
</div>
</body>
<script>
/* To test keyboard capture directly on the canvas */
Module.keyboardListeningElement = document.getElementById('module');
Module.canvas.addEventListener('mousedown', function(event) {
event.target.focus();
});
</script>
</div></div></div>
</div>
</body>
</html>

25
src/Magnum/Platform/Test/WindowlessEglApplicationTest.html

@ -1,19 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Magnum WindowlessEglApplication Test</title>
<link rel="stylesheet" href="WebApplication.css" />
</head>
<body>
<h1>Magnum WindowlessEglApplication Test</h1>
<div id="listener">
<head>
<meta charset="UTF-8" />
<title>Magnum WindowlessEglApplication Test</title>
<link rel="stylesheet" href="WebApplication.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<h1>Magnum WindowlessEglApplication Test</h1>
<div id="container" class="">
<div id="sizer"><div id="expander"><div id="listener">
<canvas id="module" class="hidden"></canvas>
<pre id="log"></pre>
<div id="status">Initialization...</div>
<div id="statusDescription"></div>
<div id="status-description"></div>
<script src="WindowlessEmscriptenApplication.js"></script>
<script async="async" src="PlatformWindowlessEglApplicationTest.js"></script>
</div>
</body>
</div></div></div>
</div>
</body>
</html>

186
src/Magnum/Platform/WebApplication.css

@ -1,65 +1,155 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/* Colors kept in sync with m.css dark theme, http://mcss.mosra.cz */
*, ::before, ::after { box-sizing: border-box; }
body {
margin: 0px;
padding: 0px;
font-family: sans-serif;
background-color: #111111;
color: #aaaaaa;
margin: 1rem;
padding: 0;
font-family: sans-serif;
font-size: 16px;
background-color: #2f363f; /*var(--background-color)*/
color: #dcdcdc; /*var(--color)*/
}
h1 {
text-align: center;
font-size: 20px;
text-align: center;
font-size: 1.75rem;
font-weight: 600;
}
/* #container makes the canvas occupy the whole page width
#sizer centers it
#expander does aspect ratio preservation
#listener snaps to #expander edges
#listener::before does the border, which finally goes below the canvas */
#container {
margin: 1rem -1rem 1rem -1rem;
}
#sizer {
margin-left: auto;
margin-right: auto;
max-width: 100%;
width: 640px;
}
#expander {
position: relative;
}
#listener {
border-style: solid;
border-color: #333333;
border-width: 1px;
padding: 1px;
width: 640px;
height: 480px;
margin-left: auto;
margin-right: auto;
margin-top: 20px;
margin-bottom: 20px;
position: relative;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
#listener::before {
position: absolute;
content: ' ';
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: -1;
border-style: solid;
border-width: 0.125rem;
border-radius: 0.2rem; /*var(--border-radius)*/
border-color: #405363; /*var(--line-color)*/
}
#module {
width: 640px;
height: 480px;
z-index: 10;
/* Canvas size and aspect ratio knobs */
#container.fullsize {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 0;
}
#container.fullsize #sizer, #container.fullsize #expander {
width: 100%; height: 100%;
}
#status {
position: absolute;
width: 640px;
text-align: center;
top: 200px;
font-size: 30px;
font-weight: bold;
z-index: 9;
#container.width-240 #sizer { width: 240px; }
#container.width-320 #sizer { width: 320px; }
#container.width-360 #sizer { width: 360px; }
#container.width-480 #sizer { width: 480px; }
#container.width-600 #sizer { width: 600px; }
#container.width-640 #sizer, #container #sizer {
width: 640px; /* default */
}
#container.width-800 #sizer { width: 800px; }
#statusDescription {
position: absolute;
width: 640px;
text-align: center;
top: 250px;
font-size: 15px;
z-index: 9;
#container.aspect-1-1 #expander { padding-bottom: 100%; }
#container.aspect-4-3 #expander, #container:not(.fullsize) #expander {
padding-bottom: 75%; /* default */
}
#container.aspect-3-4 #expander { padding-bottom: 133.3333%; }
#container.aspect-3-2 #expander { padding-bottom: 66.6667%; }
#container.aspect-2-3 #expander { padding-bottom: 150%; }
#container.aspect-16-9 #expander { padding-bottom: 56.25% }
#container.aspect-9-16 #expander { padding-bottom: 177.7778% }
#container.aspect-2-1 #expander { padding-bottom: 50%; }
#container.aspect-1-2 #expander { padding-bottom: 200%; }
#module, pre#log {
max-width: 100%;
width: 100%;
height: 100%;
z-index: 10;
border-radius: 0.2rem; /*var(--border-radius)*/
}
#module {
margin-bottom: -0.25rem; /* otherwise there's scrollbar w/ fullsize (why?) */
}
#status, #status-description {
position: absolute;
text-align: center;
width: 100%;
z-index: 9;
}
#status {
top: 10%;
font-size: 1.5rem;
font-weight: 600;
}
#status-description {
top: 22.5%;
padding-left: 2rem;
padding-right: 2rem;
}
#module.hidden {
display: none;
display: none;
}
#log {
width: 640px;
height: 480px;
overflow-y: scroll;
overflow-x: hidden;
white-space: pre-wrap;
z-index: 10;
margin: 0;
pre#log {
padding: 0.5rem 1rem;
overflow-x: auto;
margin-top: 0; /* stupid defaults */
color: #e6e6e6; /*var(--code-color)*/
background-color: #282e36; /*var(--code-background-color)*/
font-size: 0.8rem; /* so 80 columns fits into 640 pixels */
}
/* kate: indent-width 2; */

40
src/Magnum/Platform/WindowlessEmscriptenApplication.js

@ -1,9 +1,36 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
var Module = {
preRun: [],
postRun: [],
arguments: [],
doNotCaptureKeyboard: true,
printErr: function(message) {
var log = document.getElementById('log');
log.innerHTML += Array.prototype.slice.call(arguments).join(' ') + '\n';
@ -14,6 +41,8 @@ var Module = {
log.innerHTML += Array.prototype.slice.call(arguments).join(' ') + '\n';
},
/* onAbort not handled here, as the output is printed directly on the page */
canvas: document.getElementById('module'),
setStatus: function(message) {
@ -22,7 +51,7 @@ var Module = {
},
setStatusDescription: function(message) {
var statusDescription = document.getElementById('statusDescription');
var statusDescription = document.getElementById('status-description');
if(statusDescription) statusDescription.innerHTML = message;
},
@ -33,9 +62,9 @@ var Module = {
if(left) {
Module.setStatus('Downloading...');
Module.setStatusDescription((this.totalDependencies - left) + '/' + this.totalDependencies);
Module.setStatusDescription((this.totalDependencies - left) + ' / ' + this.totalDependencies);
} else {
Module.setStatus('');
Module.setStatus('Download complete');
Module.setStatusDescription('');
document.getElementById('log').style.display = 'block';
}
@ -57,9 +86,4 @@ for(var i = 0; i != args.length; ++i) {
}
Module.setStatus('Downloading...');
document.getElementById('log').style.display = 'none';
if(Module.canvas) Module.canvas.addEventListener('contextmenu', function(event) {
event.preventDefault();
}, true);

27
src/Magnum/Platform/gl-info.html

@ -1,19 +1,22 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Magnum GL Info</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="WebApplication.css" />
</head>
<body>
<h1>Magnum GL Info</h1>
<div id="listener">
<html>
<head>
<meta charset="UTF-8" />
<title>Magnum GL Info</title>
<link rel="stylesheet" href="WebApplication.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<h1>Magnum GL Info</h1>
<div id="container">
<div id="sizer"><div id="expander"><div id="listener">
<canvas id="module" class="hidden"></canvas>
<pre id="log"></pre>
<div id="status">Initialization...</div>
<div id="statusDescription"></div>
<div id="status-description"></div>
<script src="WindowlessEmscriptenApplication.js"></script>
<script async="async" src="magnum-gl-info.js"></script>
</div>
</body>
</div></div></div>
</div>
</body>
</html>

Loading…
Cancel
Save