prosperon/scripts/mum.js

360 lines
8.8 KiB
JavaScript
Raw Normal View History

2024-07-09 01:03:39 -05:00
globalThis.mum = {};
2024-07-10 09:39:28 -05:00
var panel;
2024-07-09 13:48:15 -05:00
var selected = undefined;
mum.inputs = {};
2024-09-26 11:36:09 -05:00
mum.inputs.lm = function () {
2024-07-09 13:48:15 -05:00
if (!selected) return;
2024-07-11 14:25:45 -05:00
if (!selected.action) return;
2024-07-09 13:48:15 -05:00
selected.action();
2024-09-26 11:36:09 -05:00
};
2024-07-09 13:48:15 -05:00
2024-07-09 01:03:39 -05:00
mum.base = {
2024-09-26 11:36:09 -05:00
offset: [0, 0], // Move x,y to the right and down before drawing
padding: [0, 0], // Pad inwards after drawing, to prepare for the next element
2024-07-09 01:03:39 -05:00
font: "fonts/c64.ttf",
selectable: false,
selected: false,
font_size: 16,
scale: 1,
angle: 0,
2024-09-26 11:36:09 -05:00
anchor: [0, 1], // where to draw the item from, relative to the cursor. [0,1] is from the top left corner. [1,0] is from the bottom right
2024-07-09 01:03:39 -05:00
background_image: null,
2024-08-24 08:04:41 -05:00
slice: null, // pass to slice an image as a 9 slice. see render.slice9 for its format
2024-07-11 16:37:24 -05:00
hover: {
color: Color.red,
},
2024-07-09 01:03:39 -05:00
text_shadow: {
2024-09-26 11:36:09 -05:00
pos: [0, 0],
2024-07-09 01:03:39 -05:00
color: Color.white,
},
2024-07-15 15:54:18 -05:00
border: 0, // Draw a border around the element. For text, an outline.
overflow: "wrap", // how to deal with overflow from parent element
wrap: -1,
2024-09-26 11:36:09 -05:00
text_align: "left" /* left, center, right */,
2024-07-15 15:54:18 -05:00
shader: null, // Use this shader, instead of the engine provided one
2024-07-09 01:03:39 -05:00
color: Color.white,
2024-09-26 11:36:09 -05:00
opacity: 1,
width: 0,
height: 0,
2024-07-09 01:03:39 -05:00
max_width: Infinity,
max_height: Infinity,
image_repeat: false,
2024-09-26 11:36:09 -05:00
image_repeat_offset: [0, 0],
debug: false /* set to true to draw debug boxes */,
2024-07-09 01:03:39 -05:00
hide: false,
2024-10-05 08:43:51 -05:00
child_gap: 0,
child_layout: 'top2bottom', /* top2bottom, left2right */
2024-07-09 13:48:15 -05:00
tooltip: null,
2024-10-05 08:43:51 -05:00
children: [],
2024-09-26 11:36:09 -05:00
};
2024-07-09 01:03:39 -05:00
2024-07-16 15:37:07 -05:00
// data is passed into each function, and various stats are generated
// drawpos: the point to start the drawing from
// wh: an array of [width,height]
// bound: a boundingbox around the drawn UI element
// extent: a boundingbox around the total extents of the element (ie before padding)
2024-09-26 11:36:09 -05:00
function show_debug() {
return prosperon.debug && mum.debug;
}
2024-07-11 16:37:24 -05:00
2024-10-04 12:47:50 -05:00
var context = mum.base;
var context_stack = [];
var cursor = [0,0];
2024-10-05 08:43:51 -05:00
function computeContainerSize(context)
{
var sizing = context.sizing.value;
var content_dim = [0,0];
var max_child_dim = [0,0];
if (context.layout === 'left2right') {
for (var child of context.children) {
content_dim.x += child.size.x + context.child_gap;
if (child.size.y > max_child_dim.y)
max_child_dim.y = child.size.y;
}
content_dim.width -= context.child_gap; // remove extra gap after last child
content_dim.y = max_child_dim.y;
} else {
for (var child of context.children) {
content_dim.y += child.size.y + context.child_gap;
if (child.size.x > max_child_dim.x)
max_child_dim.x = child.size.x;
}
content_dim.y -= child_gap;
content_dim.x = max_child_dim.x;
}
content_dim = content_dim.add(context.padding.scale(2));
var container_size = [0,0];
if (context.sizing.x.type === 'fit')
container_size.x = content_dim.x;
else if (container.sizing.x.type === 'grow') {
}
}
2024-10-13 19:44:28 -05:00
2024-10-04 12:47:50 -05:00
mum.container = function(data, cb) {
context_stack.push(context);
data.__proto__ = mum.base;
2024-10-05 08:43:51 -05:00
data.children = [];
2024-10-04 12:47:50 -05:00
var container_context = {
pos:cursor.slice(),
size:[0,0],
children:[]
};
context = data;
cb();
computeContainerSize(context);
}
2024-07-10 09:39:28 -05:00
mum.debug = false;
2024-09-26 11:36:09 -05:00
var post = function () {};
2024-07-09 01:03:39 -05:00
var posts = [];
2024-07-16 15:37:07 -05:00
mum.style = mum.base;
2024-07-09 01:03:39 -05:00
2024-09-26 11:36:09 -05:00
var cursor = [0, 0];
2024-07-09 01:03:39 -05:00
2024-09-26 11:36:09 -05:00
var pre = function (data) {
2024-07-10 09:39:28 -05:00
if (data.hide) return true;
2024-07-16 15:37:07 -05:00
data.__proto__ = mum.style;
2024-09-26 11:36:09 -05:00
2024-07-16 15:37:07 -05:00
if (data.pos) cursor = data.pos.slice();
data.drawpos = cursor.slice().add(data.offset);
2024-08-05 15:26:18 -05:00
if (data.opacity && data.opacity !== 1) {
2024-07-16 15:37:07 -05:00
data.color = data.color.slice();
data.color[3] = data.opacity;
}
2024-09-26 11:36:09 -05:00
data.wh = [data.width, data.height];
};
2024-07-09 01:03:39 -05:00
2024-09-26 11:36:09 -05:00
var anchor_calc = function (data) {
var aa = [0, 1].sub(data.anchor);
data.drawpos = data.drawpos.add([data.width, data.height]).scale(aa);
};
2024-07-09 13:48:15 -05:00
2024-09-26 11:36:09 -05:00
var end = function (data) {
2024-07-16 15:37:07 -05:00
cursor = cursor.add(data.padding);
post(data);
2024-09-26 11:36:09 -05:00
};
2024-07-15 15:54:18 -05:00
2024-09-26 11:36:09 -05:00
mum.list = function (fn, data = {}) {
2024-07-09 01:03:39 -05:00
if (pre(data)) return;
2024-09-26 11:36:09 -05:00
var aa = [0, 1].sub(data.anchor);
cursor = cursor.add([data.width, data.height].scale(aa)).add(data.offset).add(data.padding);
2024-07-14 16:09:50 -05:00
2024-07-09 01:03:39 -05:00
posts.push(post);
2024-07-16 15:37:07 -05:00
post = mum.list.post.bind(data);
2024-09-26 11:36:09 -05:00
2024-07-14 16:09:50 -05:00
if (show_debug())
render.boundingbox({
2024-09-26 11:36:09 -05:00
t: cursor.y,
b: cursor.y - data.height,
l: cursor.x,
r: cursor.x + data.width,
2024-07-14 16:09:50 -05:00
});
2024-09-26 11:36:09 -05:00
//if (data.background_image) mum.image(null, Object.create(data))
2024-07-16 15:37:07 -05:00
if (data.background_image) {
var imgpos = data.pos.slice();
2024-09-26 11:36:09 -05:00
imgpos.y -= data.height / 2;
imgpos.x -= data.width / 2;
var imgscale = [data.width, data.height];
if (data.slice) render.slice9(game.texture(data.background_image), imgpos, data.slice, imgscale);
else render.image(game.texture(data.background_image), imgpos, [data.width, data.height]);
2024-07-14 16:09:50 -05:00
}
2024-09-26 11:36:09 -05:00
2024-07-09 01:03:39 -05:00
fn();
2024-09-26 11:36:09 -05:00
2024-07-16 15:37:07 -05:00
data.bb.l -= data.padding.x;
data.bb.r += data.padding.x;
data.bb.t += data.padding.y;
data.bb.b -= data.padding.y;
2024-07-10 09:39:28 -05:00
2024-09-26 11:36:09 -05:00
if (show_debug()) render.boundingbox(data.bb);
2024-07-10 09:39:28 -05:00
2024-07-09 01:03:39 -05:00
post = posts.pop();
2024-07-16 15:37:07 -05:00
end(data);
2024-09-26 11:36:09 -05:00
};
2024-07-09 01:03:39 -05:00
2024-09-26 11:36:09 -05:00
mum.list.post = function (e) {
cursor.y -= e.bb.t - e.bb.b;
2024-07-10 09:39:28 -05:00
cursor.y -= e.padding.y;
2024-09-26 11:36:09 -05:00
if (this.bb) this.bb = bbox.expand(this.bb, e.bb);
else this.bb = e.bb;
};
mum.label = function (str, data = {}) {
2024-07-10 09:39:28 -05:00
if (pre(data)) return;
2024-07-16 15:37:07 -05:00
render.set_font(data.font, data.font_size);
2024-09-26 11:36:09 -05:00
2024-07-16 15:37:07 -05:00
data.bb = render.text_bb(str, data.scale, -1, cursor);
data.wh = bbox.towh(data.bb);
2024-09-26 11:36:09 -05:00
var aa = [0, 1].sub(data.anchor);
data.drawpos.y -= data.bb.t - cursor.y;
2024-07-16 15:37:07 -05:00
data.drawpos = data.drawpos.add(data.wh.scale(aa)).add(data.offset);
2024-07-14 16:09:50 -05:00
2024-07-16 15:37:07 -05:00
data.bb = render.text_bb(str, data.scale, data.wrap, data.drawpos);
2024-07-10 09:39:28 -05:00
2024-07-16 15:37:07 -05:00
if (data.action && bbox.pointin(data.bb, input.mouse.screenpos())) {
if (data.hover) {
data.hover.__proto__ = data;
data = data.hover;
selected = data;
2024-07-10 09:39:28 -05:00
}
}
2024-07-16 15:37:07 -05:00
data.bb = render.text(str, data.drawpos, data.scale, data.color, data.wrap);
2024-09-26 11:36:09 -05:00
if (show_debug()) render.boundingbox(data.bb);
2024-07-16 15:37:07 -05:00
end(data);
2024-09-26 11:36:09 -05:00
};
2024-07-10 09:39:28 -05:00
2024-09-26 11:36:09 -05:00
mum.image = function (path, data = {}) {
2024-07-09 01:03:39 -05:00
if (pre(data)) return;
2024-07-16 15:37:07 -05:00
path ??= data.background_image;
2024-10-05 08:43:51 -05:00
var image = game.texture(path);
var tex = image.texture;
2024-07-15 15:54:18 -05:00
2024-07-16 20:34:09 -05:00
if (!data.height)
2024-09-26 11:36:09 -05:00
if (data.width) data.height = tex.height * (data.width / tex.width);
else data.height = tex.height;
2024-07-15 15:54:18 -05:00
2024-07-16 20:34:09 -05:00
if (!data.width)
2024-09-26 11:36:09 -05:00
if (data.height) data.width = tex.width * (data.height / tex.height);
else data.height = tex.height;
2024-07-16 20:34:09 -05:00
if (!data.width) data.width = tex.width;
if (!data.height) data.height = tex.height;
2024-09-26 11:36:09 -05:00
var aa = [0, 1].sub(data.anchor);
data.drawpos = data.drawpos.add(aa.scale([data.width, data.height]));
if (data.slice) render.slice9(tex, data.drawpos, data.slice, [data.width, data.height]);
2024-10-05 08:43:51 -05:00
else data.bb = render.image(image, data.drawpos, [data.width, data.height]);
2024-09-26 11:36:09 -05:00
2024-07-16 15:37:07 -05:00
end(data);
2024-09-26 11:36:09 -05:00
};
2024-07-16 15:37:07 -05:00
2024-10-05 08:43:51 -05:00
mum.rectangle = function (data = {}, cb) {
2024-07-16 15:37:07 -05:00
if (pre(data)) return;
2024-09-26 11:36:09 -05:00
var aa = [0, 0].sub(data.anchor);
data.drawpos = data.drawpos.add(aa.scale([data.width, data.height]));
render.rectangle(data.drawpos, data.drawpos.add([data.width, data.height]), data.color);
2024-07-16 15:37:07 -05:00
end(data);
2024-09-26 11:36:09 -05:00
};
2024-07-09 01:03:39 -05:00
2024-07-09 13:48:15 -05:00
var btnbb;
2024-09-26 11:36:09 -05:00
var btnpost = function () {
2024-07-16 15:37:07 -05:00
btnbb = data.bb;
2024-09-26 11:36:09 -05:00
};
2024-07-09 13:48:15 -05:00
2024-09-26 11:36:09 -05:00
mum.button = function (str, data = { padding: [4, 4], color: Color.black }) {
2024-07-09 01:03:39 -05:00
if (pre(data)) return;
2024-07-09 13:48:15 -05:00
posts.push(post);
post = btnpost;
2024-09-26 11:36:09 -05:00
if (typeof str === "string") render.text(str, cursor.add(data.padding), data.scale, data.color);
else str();
2024-07-09 13:48:15 -05:00
2024-07-11 16:37:24 -05:00
if (data.action && data.hover && bbox.pointin(btnbb, input.mouse.screenpos())) {
2024-07-09 13:48:15 -05:00
data.hover.__proto__ = data;
2024-07-16 15:37:07 -05:00
data = data.hover;
2024-07-09 13:48:15 -05:00
}
2024-09-26 11:36:09 -05:00
render.rectangle([btnbb.l - data.padding.x, btnbb.b - data.padding.y], [btnbb.r + data.padding.y, btnbb.t + data.padding.y], data.color);
2024-07-16 15:37:07 -05:00
data.bb = btnbb;
2024-07-09 13:48:15 -05:00
post = posts.pop();
2024-07-16 15:37:07 -05:00
end(data);
2024-09-26 11:36:09 -05:00
};
2024-07-09 13:48:15 -05:00
2024-10-13 19:44:28 -05:00
mum.window = function (pos = [0,0], size = game.size.slice(), config = {}, fn) {
if (pre(config)) return;
2024-07-09 13:48:15 -05:00
2024-07-16 15:37:07 -05:00
render.rectangle(cursor, cursor.add(data.size), data.color);
2024-10-13 19:44:28 -05:00
config.pos = pos;
config.pos = config.add(config.padding);
2024-07-09 13:48:15 -05:00
fn();
2024-07-16 15:37:07 -05:00
end(data);
2024-09-26 11:36:09 -05:00
};
2024-07-14 16:09:50 -05:00
2024-10-13 19:44:28 -05:00
mum.hstack = function(data = {}, fn)
{
}
2024-09-26 11:36:09 -05:00
mum.ex_hud = function () {
mum.label("TOP LEFT", { pos: [0, game.size.y], anchor: [0, 1] });
mum.label("BOTTOM LEFT", { pos: [0, 0], anchor: [0, 0] });
mum.label("TOP RIGHT", { pos: game.size, anchor: [1, 1] });
mum.label("BOTTOM RIGHT", { pos: [game.size.x, 0], anchor: [1, 0] });
};
2024-07-23 17:21:27 -05:00
mum.drawinput = undefined;
var ptext = "";
var panpan = {
draw() {
2024-09-26 11:36:09 -05:00
mum.rectangle({
pos: [0, 0],
anchor: [0, 0],
height: 20,
width: window.size.x,
padding: [10, 16],
color: Color.black,
});
2024-07-23 17:21:27 -05:00
mum.label("input level: ");
2024-09-26 11:36:09 -05:00
mum.label(ptext, { offset: [50, 0], color: Color.red });
2024-07-23 17:21:27 -05:00
},
inputs: {
block: true,
char(c) {
2024-09-26 11:36:09 -05:00
ptext += c;
2024-07-23 17:21:27 -05:00
},
enter() {
delete mum.drawinput;
player[0].uncontrol(panpan);
},
escape() {
delete mum.drawinput;
player[0].uncontrol(panpan);
},
backspace() {
2024-09-26 11:36:09 -05:00
ptext = ptext.slice(0, ptext.length - 1);
},
2024-07-23 17:21:27 -05:00
},
2024-09-26 11:36:09 -05:00
};
2024-07-23 17:21:27 -05:00
mum.textinput = function (fn, str = "") {
mum.drawinput = panpan.draw;
ptext = str;
player[0].control(panpan);
2024-09-26 11:36:09 -05:00
panpan.inputs.enter = function () {
2024-07-23 17:21:27 -05:00
fn(ptext);
delete mum.drawinput;
player[0].uncontrol(panpan);
2024-09-26 11:36:09 -05:00
};
};