22 Commits

Author SHA1 Message Date
24ce6260d5 js: Pay attention to the device pixel ratio
The CSS "px" unit isn't always a device pixel.  On devices with
high-DPI displays, there can often be multiple device pixels to a CSS
px, while in particularly low-resolution displays (like feature
phones), the user might zoom out to get several CSS px to a device
pixel.  And even on desktop browsers, text zooming controls can change
the ratio.

To make Puzzles' rendering look good on an arbitrary device pixel
ratio, we really want the pixels of the canvas to be device pixels,
not CSS px, so that the canvas doesn't have to be scaled by the
browser for display.  To correct this, we now control the CSS size of
the puzzle canvas, via its containing <div>, to be the canvas size
divided by the device pixel ratio.

There is a significant gap, which is that this doesn't yet track
changes to the device pixel ratio.  This is slightly complicated, so
I'll put it off to the next commit.
2022-10-22 13:55:55 +01:00
0197ca4359 js: Percent-encode game IDs in URLs and decode them again on input
This is necessary to allow all random seeds to round-trip properly.
It's probably not currently necessary for descriptive game IDs, but it
won't hurt.

I've deliberately gone for encoding only those characters that are not
valid in fragment identifiers to minimise the ugliness of the generated
URLs.  For slightly interesting historical reasons, '#' is not valid in
a fragment identifier, so all random seed links end up a little bit
ugly.
2022-10-21 10:28:01 +01:00
5c180cfa6f js: When making a hidden element visible, just remove "display: none"
This removes any assumption in the JavaScript code about precisely what
"display" setting the element should have.

This means that now the only places where the JavaScript manipulates
elements' styles are to set the width of the puzzle container and to
mark and unmark elements with "display: none".  These both seem like
reasonable kinds of semantic markup that just happen to be expressed as
styles.
2022-10-17 23:17:59 +01:00
3c3d8aff22 js: Remove unnecessary setting of status bar size
An element with display: block will naturally adjust to fit the width of
its container, so if that's what you want there's no need to set its
width explicitly.
2022-10-17 23:16:35 +01:00
c90d64f243 js: Move most style settings from JavaScript to CSS
Some elements (generally those created by JavaScript) had their style
parameters set directly by JavaScript.  Putting styles in CSS generally
makes them easier to understand (and fiddle with), so I've done that.
The only styles left in JavaScript are those that are calculated by
JavaScript (like the status-bar size) and the random-seed permalink
visibility because I wasn't quite sure how to handle it.
2022-10-17 22:04:16 +01:00
f6434e8496 Update web puzzles to current WASM-based Emscripten.
I presume this will improve performance. Also, if I've understood
correctly, WASM-based compiled web code is capable of automatically
growing its memory, which the previous asm.js build of the puzzles
could not do, and occasionally caused people to complain that if they
tried to play a _really big_ game in their browser, the JS would
eventually freeze because the emulated memory ran out.

I've been putting off doing this for ages because my previous
Emscripten build setup was so finicky that I didn't like to meddle
with it. But now that the new cmake system in this source tree makes
things generally easier, and particularly since I've just found out
that the up-to-date Emscripten is available as a Docker image (namely
"emscripten/emsdk"), this seemed like a good moment to give it a try.

The source and build changes required for this update weren't too
onerous. I was half expecting a huge API upheaval, and indeed there
was _some_ change, but very little:

 - in the JS initPuzzle function, move the call to Module.callMain()
   into Module.onRuntimeInitialized instead of doing it at the top
   level, because New Emscripten's .js output likes to load the
   accompanying .wasm file asynchronously, so you can't call the WASM
   main() until it actually exists.

 - in the JS-side library code, replace all uses of Emscripten's
   Pointer_stringify() function with the new name UTF8ToString(). (The
   new version also has an ASCIIToString(), so I guess the reason for
   the name change is that now you get to choose which character set
   you meant. I need to use UTF-8, so that the × and ÷ signs in Keen
   will work.)

 - set EXTRA_EXPORTED_RUNTIME_METHODS=[cwrap,callMain] on the emcc
   link command line, otherwise they aren't available for my JS setup
   code to call.

 - (removed -s ASM_JS=1 from the link options, though I'm not actually
   sure it made any difference one way or the other in the new WASM
   world)

 - be prepared for a set of .wasm files to show up as build products
   alongside the .js ones.

 - stop building with -DCMAKE_BUILD_TYPE=Release! I'm not sure why
   that was needed, but if I leave that flag on my cmake command line,
   the output .js file fails to embed my emccpre.js, so the initial
   call to initPuzzle() fails from the HTML wrapper page, meaning
   nothing at all happens.
2021-04-03 09:22:49 +01:00
b31ea22167 Factor some HTML dialog functions out of emcclib.
I'm about to want to call these from Javascript as well as from
Emscripten-compiled C, so I need versions of them that aren't wrapped
up in the Emscripten library object and also don't expect half their
parameters to be Emscripten-verse char pointers requiring calls to
Pointer_stringify.

The easiest way to achieve all of that is to turn the Emscripten-
ready versions of those functions in emcclib.js into tiny wrappers
around the JS versions, which do the pointer stringification and a
couple of other details like directing callbacks to the right C
functions.
2017-09-05 20:55:11 +01:00
5e53ec5e36 Organise the JS menus/buttons bar more like a menu.
I'm about to introduce a few more options, and the button bar is
already a bit wide, so I think I should shrink it horizontally before
putting more stuff on it. So I've organised the options into something
more like the Game and Type submenus that the desktop versions use.

However, I haven't gone quite all the way, on the basis that the web
versions will be at least slightly playable on devices without much
keyboard, which makes it worth keeping the in-play actions (Undo,
Redo, and to a lesser extent Restart and Solve) accessible as
top-level buttons in a single click each.

As part of this change, I've also separated the menu bar into a
drop-down menus section and a top-level buttons section with a gap
between them, and put a signalling "..." on the end of the titles in
the former section.

This change also removes the class="left" on the game-type menu and
its submenus, which were previously there to deal with that menu being
all the way over on the far right of the menu bar. But the CSS for
those classes is still there in jspage.pl, and should still work if I
need it again in future.
2017-09-05 20:54:19 +01:00
a7dc17c425 Rework the preset menu system to permit submenus.
To do this, I've completely replaced the API between mid-end and front
end, so any downstream front end maintainers will have to do some
rewriting of their own (sorry). I've done the necessary work in all
five of the front ends I keep in-tree here - Windows, GTK, OS X,
Javascript/Emscripten, and Java/NestedVM - and I've done it in various
different styles (as each front end found most convenient), so that
should provide a variety of sample code to show downstreams how, if
they should need it.

I've left in the old puzzle back-end API function to return a flat
list of presets, so for the moment, all the puzzle backends are
unchanged apart from an extra null pointer appearing in their
top-level game structure. In a future commit I'll actually use the new
feature in a puzzle; perhaps in the further future it might make sense
to migrate all the puzzles to the new API and stop providing back ends
with two alternative ways of doing things, but this seemed like enough
upheaval for one day.
2017-04-26 21:51:23 +01:00
bc2c1f69fd Javascript puzzles: switch to a CSS-based drop-down system.
The previous control buttons and dropdowns based on form elements were
always a bit ugly: partly in a purely visual sense, and partly because
of the nasty bodge I had to do with splitting the usual 'Custom' game
type menu item into two (to get round the fact that if an element of a
<select> is already selected, browsers won't send an event when it's
re-selected). Also, I'm about to want to introduce hierarchical
submenus in the Type menu, and <select> doesn't support that at all.

So here's a replacement system which does everything by CSS
properties, including the popping-up of menus when the mouse moves
over their parent menu item. (Thanks to the Internet in general for
showing me how that trick is done.)
2017-04-26 21:48:11 +01:00
ff8a9fbc54 Fix vertically misaligned text in Javascript puzzles.
When I constructed my test canvas to measure the vertical extent of a
text string for ALIGN_VCENTRE, I forgot to ensure that the 'width'
variable was an integer, as a result of which the loop over canvas
pixels kept trying to use fractional array indices and returning
undefined :-)

[originally from svn r10196]
2014-06-21 17:40:29 +00:00
c0fff857fd Add a draggable resize handle to the JS puzzles.
Rather than design an ersatz 'window frame' surrounding the puzzle
canvas, I've simply overlaid the resize handle on the corner of the
puzzle itself (canvas or status bar, depending on whether the latter
exists), trusting that all games in my collection provide a reasonable
border within their drawing area. (OS X already does this with its
resize handle, so it's not as if there's no precedent.)

Unlike the desktop versions, I control the resize behaviour completely
in this environment, so I can constrain the canvas to only ever be
sensible sizes with no dead space round the edges (and, in particular,
preserve the aspect ratio).

Right-clicking the resize handle will restore the puzzle's default
tile size. I had intended to implement a maximise-to-browser-window
button too, but was annoyingly foiled by scrollbars - if you maximise
to the current window width, and as a result the text below the puzzle
scrolls off the bottom, then a vertical scrollbar appears and eats
into the width you just maximised to. Gah.

[originally from svn r9822]
2013-04-07 10:24:37 +00:00
36f35f5db8 Regretfully remove my trickery with a hidden <option> element inside
the game-type <select>, since IE turns out to ignore display:none on
options. Oh well.

Instead I now do a more transparent thing: when custom game params are
in use, there's a "Custom" option selected in the dropdown, and a
separate 'Re-customise' option which brings the config box back up.
When an ordinary preset is selected, the Custom option is missing, and
there's just a 'Customise'.

In the process I've tinkered a bit to arrange that the custom 'preset'
is always represented by a negative number rather than one past the
last real preset; that seems more consistent overall.

[originally from svn r9811]
2013-04-05 15:49:29 +00:00
5dc559c8be Assorted HTML/CSS fiddlings to make things work better in IE. I've
added a trivial doctype (IE complained without it), but that caused a
gap to appear between the puzzle and the status bar, so I tinkered a
bit more and ended up removing the <table> completely (no great loss)
as well as adding display:block to the canvas and explicitly setting
the width of not only the status bar div but also its parent div.
Meanwhile, I'm putting the "px" on the end of a lot of properties I
set from JS, because IE complains about that too if I don't.

[originally from svn r9809]
2013-04-05 15:49:25 +00:00
841c9318f3 Remove trailing commas at the ends of initialiser lists. IE 8 and 9
didn't like them, which doesn't matter as such since they won't run
these JS puzzles anyway (no TypedArray support) but it hints that
other JS implementations might be picky about this too.

[originally from svn r9804]
2013-04-05 15:49:19 +00:00
3bc0e5cc24 Clarify header comments in the Emscripten frontend's source files to
mention that the HTML pages generated by html/jspage.pl are also an
integral part of this front end. (The NestedVM frontend is more
self-contained, needing only an appropriate <applet> tag, but this one
expects quite a few components to exist on the page and have the right
ids.)

[originally from svn r9803]
2013-04-05 15:49:18 +00:00
742cf3a443 A UI suggestion from Ben: label the Custom element in the dropdown
with a trailing "..." to hint that it opens a further dialog box.
However, the _invisible_ Custom option is merely indicating what you
_do_ have selected, so we leave that one as it is. (So now they're no
longer exact twins of each other, of course.)

[originally from svn r9796]
2013-03-31 18:36:03 +00:00
75137adf8c Oops. I consistently misspelled my desired lineCap and lineJoin values
as "1" rather than "round". Must have had my Postscript brain in,
and/or been confused by lineWidth = "1" just beforehand. This fixes a
display glitch in Towers, where there's a tiny spike at the top left
corner of each tower due to a very sharp mitred line join.

[originally from svn r9791]
2013-03-31 09:58:48 +00:00
2d2afe9ad4 Fix a crash when changing presets in Inertia. Turns out that my
Javascript-side blitter creation function had forgotten to return the
new blitter's id, so the C code was still trying to use blitter #0
after it had been thrown away and replaced.

[originally from svn r9790]
2013-03-31 09:58:47 +00:00
9826ecd5c3 Apply a bodge to arrange that if the user selects Custom from the game
type dropdown, we still get an 'onchange' event if they select it a
second time. Normally this wouldn't happen, because onchange means
what it says and we only get it if a _different_ element is selected.

My solution is to create two list items called Custom, set one of them
as display:none to stop it showing up when the list is dropped down,
and to select it after the configuration box closes.

[originally from svn r9788]
2013-03-31 09:58:46 +00:00
3e39f6b80b Stop using the dangerously unescaped 'innerHTML' for <option>
contents; use document.createTextNode like I do everywhere else.

[originally from svn r9787]
2013-03-31 09:58:45 +00:00
49fba922ea New front end! To complement the webification of my puzzles via Java
applets, here's an alternative webification in Javascript, using
Emscripten in asm.js mode (so that as browsers incorporate asm.js
optimisation, the game generation should run really fast).

[originally from svn r9781]
2013-03-30 20:16:21 +00:00