client/src/ui.js

98 lines
2.2 KiB
JavaScript

function UI(buttons, screen) {
return {
animation: animation,
cinematic: cinematic,
frame: frame,
menu: menu,
text: text
};
function animation(frames) {
var frameCounter = 0;
var scheduled;
var step = function() {
if(frameCounter < frames.length) {
scheduled = null;
frames[frameCounter].action();
if(frames[frameCounter].delay != undefined) {
scheduled = setTimeout(step, frames[frameCounter].delay);
}
frameCounter++
}
};
return {
run: step,
pause: function() { if(scheduled != undefined) { clearTimeout(scheduled); } }
};
}
function cinematic(frames, controls) {
var remote = animation(frames);
var mapping = {};
for(var key in controls) {
mapping[key] = function() {
buttons.pop();
remote.pause();
controls[key]();
};
}
return function(f) {
buttons.push(mapping);
remote.run();
f();
};
}
function frame(id) {
screen.clear();
screen.frame(id);
}
function menu(config) {
var cursor = 0;
var m = screen.menu(config.entries);
var sync = function() { screen.select(cursor); };
var mapping = {
'Up': function() { cursor = Math.max(0, cursor - 1); sync(); },
'Down': function() { cursor = Math.min(config.entries.length - 1, cursor + 1); sync(); },
'A': function() { config.entries[cursor].action(); }
};
if(config.cancel != undefined) {
mapping['B'] = function() { buttons.pop(); screen.clear(m); config.cancel(); }
}
buttons.push(mapping);
}
function textScreen(message) {
var characters = message.split('');
var frames = [];
var ready = false;
var append = function(c) { return function() { screen.appendText(c); }; };
for(var i = 0; i < characters.length; i++) {
frames.push({action: append(characters[i]), delay: 50});
}
frames.push({action: function() { ready = true; screen.markAsRead(); }, delay: null});
var remote = animation(frames);
return function(f) {
buttons.push({
'A': function() {
if(ready) {
f();
} else {
remote.pause();
screen.text(message);
ready = true;
}
}
});
screen.text('');
remote.run();
};
}
function text(message) {
return textScreen(message);
}
}