add thumbnail making
This commit is contained in:
parent
1b5bd399cd
commit
2fe4e825aa
2
Makefile
2
Makefile
|
@ -267,7 +267,7 @@ crossmac: Prosperon.icns
|
||||||
cp Prosperon.icns Prosperon.app/Contents/Resources
|
cp Prosperon.icns Prosperon.app/Contents/Resources
|
||||||
|
|
||||||
crosswin:
|
crosswin:
|
||||||
make CROSS=x86_64-w64-mingw32ucrt- OS=Windows_NT CC=gcc
|
make CROSS=x86_64-w64-mingw32- OS=Windows_NT CC=gcc
|
||||||
|
|
||||||
crossweb:
|
crossweb:
|
||||||
make CC=emcc OS=wasm
|
make CC=emcc OS=wasm
|
||||||
|
|
|
@ -61,6 +61,7 @@ var sprite = {
|
||||||
this._p = p;
|
this._p = p;
|
||||||
this.del_anim?.();
|
this.del_anim?.();
|
||||||
this.texture = game.texture(p);
|
this.texture = game.texture(p);
|
||||||
|
say(p);
|
||||||
this.diffuse = this.texture;
|
this.diffuse = this.texture;
|
||||||
this.rect = [0,0,1,1];
|
this.rect = [0,0,1,1];
|
||||||
|
|
||||||
|
|
|
@ -1,107 +1,97 @@
|
||||||
"use math";
|
"use math";
|
||||||
|
|
||||||
Object.defineProperty(String.prototype, 'tolast', {
|
Object.defineProperty(String.prototype, "tolast", {
|
||||||
value: function(val) {
|
value: function (val) {
|
||||||
var idx = this.lastIndexOf(val);
|
var idx = this.lastIndexOf(val);
|
||||||
if (idx === -1) return this.slice();
|
if (idx === -1) return this.slice();
|
||||||
return this.slice(0,idx);
|
return this.slice(0, idx);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.defineProperty(String.prototype, 'dir', {
|
Object.defineProperty(String.prototype, "dir", {
|
||||||
value: function() {
|
value: function () {
|
||||||
if (!this.includes('/')) return "";
|
if (!this.includes("/")) return "";
|
||||||
return this.tolast('/');
|
return this.tolast("/");
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.defineProperty(String.prototype, 'folder', {
|
Object.defineProperty(String.prototype, "folder", {
|
||||||
value: function() {
|
value: function () {
|
||||||
var dir = this.dir();
|
var dir = this.dir();
|
||||||
if (!dir) return "";
|
if (!dir) return "";
|
||||||
else return dir + "/";
|
else return dir + "/";
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
globalThis.Resources = {};
|
globalThis.Resources = {};
|
||||||
|
|
||||||
Resources.replpath = function(str, path)
|
Resources.replpath = function (str, path) {
|
||||||
{
|
|
||||||
if (!str) return str;
|
if (!str) return str;
|
||||||
if (str[0] === "/")
|
if (str[0] === "/") return str.rm(0);
|
||||||
return str.rm(0);
|
|
||||||
|
|
||||||
if (str[0] === "@")
|
if (str[0] === "@") return os.prefpath() + "/" + str.rm(0);
|
||||||
return os.prefpath() + "/" + str.rm(0);
|
|
||||||
|
|
||||||
if (!path) return str;
|
if (!path) return str;
|
||||||
|
|
||||||
var stem = path.dir();
|
var stem = path.dir();
|
||||||
while (stem) {
|
while (stem) {
|
||||||
var tr = stem + "/" +str;
|
var tr = stem + "/" + str;
|
||||||
if (io.exists(tr)) return tr;
|
if (io.exists(tr)) return tr;
|
||||||
stem = stem.updir();
|
stem = stem.updir();
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
};
|
||||||
|
|
||||||
Resources.replstrs = function(path)
|
Resources.replstrs = function (path) {
|
||||||
{
|
|
||||||
if (!path) return;
|
if (!path) return;
|
||||||
var script = io.slurp(path);
|
var script = io.slurp(path);
|
||||||
var regexp = /"[^"\s]*?\.[^"\s]+?"/g;
|
var regexp = /"[^"\s]*?\.[^"\s]+?"/g;
|
||||||
var stem = path.dir();
|
var stem = path.dir();
|
||||||
|
|
||||||
script = script.replace(regexp,function(str) {
|
script = script.replace(regexp, function (str) {
|
||||||
var newstr = Resources.replpath(str.trimchr('"'), path);
|
var newstr = Resources.replpath(str.trimchr('"'), path);
|
||||||
return `"${newstr}"`;
|
return `"${newstr}"`;
|
||||||
});
|
});
|
||||||
|
|
||||||
return script;
|
return script;
|
||||||
}
|
};
|
||||||
|
|
||||||
globalThis.json = {};
|
globalThis.json = {};
|
||||||
json.encode = function(value, replacer, space = 1)
|
json.encode = function (value, replacer, space = 1) {
|
||||||
{
|
|
||||||
return JSON.stringify(value, replacer, space);
|
return JSON.stringify(value, replacer, space);
|
||||||
}
|
};
|
||||||
|
|
||||||
json.decode = function(text, reviver)
|
json.decode = function (text, reviver) {
|
||||||
{
|
|
||||||
if (!text) return undefined;
|
if (!text) return undefined;
|
||||||
return JSON.parse(text,reviver);
|
return JSON.parse(text, reviver);
|
||||||
}
|
};
|
||||||
|
|
||||||
json.readout = function(obj)
|
json.readout = function (obj) {
|
||||||
{
|
|
||||||
var j = {};
|
var j = {};
|
||||||
for (var k in obj)
|
for (var k in obj)
|
||||||
if (typeof obj[k] === 'function')
|
if (typeof obj[k] === "function") j[k] = "function " + obj[k].toString();
|
||||||
j[k] = 'function ' + obj[k].toString();
|
else j[k] = obj[k];
|
||||||
else
|
|
||||||
j[k] = obj[k];
|
|
||||||
|
|
||||||
return json.encode(j);
|
return json.encode(j);
|
||||||
}
|
};
|
||||||
|
|
||||||
json.doc = {
|
json.doc = {
|
||||||
doc: "json implementation.",
|
doc: "json implementation.",
|
||||||
encode: "Encode a value to json.",
|
encode: "Encode a value to json.",
|
||||||
decode: "Decode a json string to a value.",
|
decode: "Decode a json string to a value.",
|
||||||
readout: "Encode an object fully, including function definitions."
|
readout: "Encode an object fully, including function definitions.",
|
||||||
};
|
};
|
||||||
|
|
||||||
Resources.scripts = ["jsoc", "jsc", "jso", "js"];
|
Resources.scripts = ["jsoc", "jsc", "jso", "js"];
|
||||||
Resources.images = ["png", "gif", "jpg", "jpeg"];
|
Resources.images = ["png", "gif", "jpg", "jpeg"];
|
||||||
Resources.sounds = ["wav", 'flac', 'mp3', "qoa"];
|
Resources.sounds = ["wav", "flac", "mp3", "qoa"];
|
||||||
Resources.is_image = function(path) {
|
Resources.is_image = function (path) {
|
||||||
var ext = path.ext();
|
var ext = path.ext();
|
||||||
return Resources.images.any(x => x === ext);
|
return Resources.images.any((x) => x === ext);
|
||||||
}
|
};
|
||||||
|
|
||||||
function find_ext(file, ext)
|
function find_ext(file, ext) {
|
||||||
{
|
|
||||||
if (io.exists(file)) return file;
|
if (io.exists(file)) return file;
|
||||||
for (var e of ext) {
|
for (var e of ext) {
|
||||||
var nf = `${file}.${e}`;
|
var nf = `${file}.${e}`;
|
||||||
|
@ -110,45 +100,48 @@ function find_ext(file, ext)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Resources.find_image = function(file) { return find_ext(file,Resources.images); }
|
Resources.find_image = function (file) {
|
||||||
Resources.find_sound = function(file) { return find_ext(file,Resources.sounds); }
|
return find_ext(file, Resources.images);
|
||||||
Resources.find_script = function(file) { return find_ext(file,Resources.scripts); }
|
};
|
||||||
|
Resources.find_sound = function (file) {
|
||||||
|
return find_ext(file, Resources.sounds);
|
||||||
|
};
|
||||||
|
Resources.find_script = function (file) {
|
||||||
|
return find_ext(file, Resources.scripts);
|
||||||
|
};
|
||||||
|
|
||||||
profile.best_t = function(t) {
|
profile.best_t = function (t) {
|
||||||
var qq = 'ns';
|
var qq = "ns";
|
||||||
if (t > 1000) {
|
if (t > 1000) {
|
||||||
t /= 1000;
|
t /= 1000;
|
||||||
qq = 'us';
|
qq = "us";
|
||||||
if (t > 1000) {
|
if (t > 1000) {
|
||||||
t /= 1000;
|
t /= 1000;
|
||||||
qq = 'ms';
|
qq = "ms";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return `${t.toPrecision(4)} ${qq}`;
|
return `${t.toPrecision(4)} ${qq}`;
|
||||||
}
|
};
|
||||||
|
|
||||||
profile.report = function(start, msg = "[undefined report]")
|
profile.report = function (start, msg = "[undefined report]") {
|
||||||
{
|
console.info(`${msg} in ${profile.best_t(profile.now() - start)}`);
|
||||||
console.info(`${msg} in ${profile.best_t(profile.now()-start)}`);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
profile.addreport = function(cache, line, start)
|
profile.addreport = function (cache, line, start) {
|
||||||
{
|
|
||||||
cache[line] ??= [];
|
cache[line] ??= [];
|
||||||
cache[line].push(profile.now()-start);
|
cache[line].push(profile.now() - start);
|
||||||
}
|
};
|
||||||
|
|
||||||
profile.printreport = function(cache, name)
|
profile.printreport = function (cache, name) {
|
||||||
{
|
|
||||||
var report = name + "\n";
|
var report = name + "\n";
|
||||||
for (var i in cache)
|
for (var i in cache)
|
||||||
report += `${i} ${profile.best_t(cache[i].reduce((a,b) => a+b)/cache[i].length)}\n`;
|
report += `${i} ${profile.best_t(cache[i].reduce((a, b) => a + b) / cache[i].length)}\n`;
|
||||||
|
|
||||||
return report;
|
return report;
|
||||||
}
|
};
|
||||||
|
|
||||||
console.transcript = "";
|
console.transcript = "";
|
||||||
console.say = function(msg) {
|
console.say = function (msg) {
|
||||||
msg += "\n";
|
msg += "\n";
|
||||||
console.print(msg);
|
console.print(msg);
|
||||||
console.transcript += msg;
|
console.transcript += msg;
|
||||||
|
@ -157,16 +150,14 @@ console.log = console.say;
|
||||||
globalThis.say = console.say;
|
globalThis.say = console.say;
|
||||||
globalThis.print = console.print;
|
globalThis.print = console.print;
|
||||||
|
|
||||||
console.pprint = function(msg,lvl = 0) {
|
console.pprint = function (msg, lvl = 0) {
|
||||||
|
if (typeof msg === "object") msg = JSON.stringify(msg, null, 2);
|
||||||
if (typeof msg === 'object')
|
|
||||||
msg = JSON.stringify(msg, null, 2);
|
|
||||||
|
|
||||||
var file = "nofile";
|
var file = "nofile";
|
||||||
var line = 0;
|
var line = 0;
|
||||||
console.rec(0,msg,file,line);
|
console.rec(0, msg, file, line);
|
||||||
|
|
||||||
var caller = (new Error()).stack.split('\n')[2];
|
var caller = new Error().stack.split("\n")[2];
|
||||||
if (caller) {
|
if (caller) {
|
||||||
var md = caller.match(/\((.*)\:/);
|
var md = caller.match(/\((.*)\:/);
|
||||||
var m = md ? md[1] : "SCRIPT";
|
var m = md ? md[1] : "SCRIPT";
|
||||||
|
@ -179,19 +170,33 @@ console.pprint = function(msg,lvl = 0) {
|
||||||
console.rec(lvl, msg, file, line);
|
console.rec(lvl, msg, file, line);
|
||||||
};
|
};
|
||||||
|
|
||||||
console.spam = function(msg) { console.pprint (msg,0); };
|
console.spam = function (msg) {
|
||||||
console.debug = function(msg) { console.pprint(msg,1); };
|
console.pprint(msg, 0);
|
||||||
console.info = function(msg) { console.pprint(msg, 2); };
|
};
|
||||||
console.warn = function(msg) { console.pprint(msg, 3); };
|
console.debug = function (msg) {
|
||||||
console.error = function(msg) { console.pprint(msg + "\n" + console.stackstr(2), 4);};
|
console.pprint(msg, 1);
|
||||||
console.panic = function(msg) { console.pprint(msg + "\n" + console.stackstr(2), 5); };
|
};
|
||||||
console.stackstr = function(skip=0) {
|
console.info = function (msg) {
|
||||||
|
console.pprint(msg, 2);
|
||||||
|
};
|
||||||
|
console.warn = function (msg) {
|
||||||
|
console.pprint(msg, 3);
|
||||||
|
};
|
||||||
|
console.error = function (msg) {
|
||||||
|
console.pprint(msg + "\n" + console.stackstr(2), 4);
|
||||||
|
};
|
||||||
|
console.panic = function (msg) {
|
||||||
|
console.pprint(msg + "\n" + console.stackstr(2), 5);
|
||||||
|
};
|
||||||
|
console.stackstr = function (skip = 0) {
|
||||||
var err = new Error();
|
var err = new Error();
|
||||||
var stack = err.stack.split('\n');
|
var stack = err.stack.split("\n");
|
||||||
return stack.slice(skip,stack.length).join('\n');
|
return stack.slice(skip, stack.length).join("\n");
|
||||||
};
|
};
|
||||||
|
|
||||||
console.stack = function(skip = 0) { console.log(console.stackstr(skip+1)); };
|
console.stack = function (skip = 0) {
|
||||||
|
console.log(console.stackstr(skip + 1));
|
||||||
|
};
|
||||||
|
|
||||||
console.stdout_lvl = 1;
|
console.stdout_lvl = 1;
|
||||||
console.trace = console.stack;
|
console.trace = console.stack;
|
||||||
|
@ -206,15 +211,14 @@ console.doc = {
|
||||||
say: "Write raw text to console, plus a newline.",
|
say: "Write raw text to console, plus a newline.",
|
||||||
stack: "Output a stacktrace to console.",
|
stack: "Output a stacktrace to console.",
|
||||||
console: "Output directly to in game console.",
|
console: "Output directly to in game console.",
|
||||||
clear: "Clear console."
|
clear: "Clear console.",
|
||||||
};
|
};
|
||||||
|
|
||||||
globalThis.global = globalThis;
|
globalThis.global = globalThis;
|
||||||
|
|
||||||
var profcache = {};
|
var profcache = {};
|
||||||
|
|
||||||
function use(file, env = {}, script)
|
function use(file, env = {}, script) {
|
||||||
{
|
|
||||||
file = Resources.find_script(file);
|
file = Resources.find_script(file);
|
||||||
var st = profile.now();
|
var st = profile.now();
|
||||||
|
|
||||||
|
@ -227,7 +231,7 @@ function use(file, env = {}, script)
|
||||||
}
|
}
|
||||||
script ??= Resources.replstrs(file);
|
script ??= Resources.replstrs(file);
|
||||||
script = `(function() { var self = this; ${script}; })`;
|
script = `(function() { var self = this; ${script}; })`;
|
||||||
var fn = os.eval(file,script);
|
var fn = os.eval(file, script);
|
||||||
use.cache[file] = fn;
|
use.cache[file] = fn;
|
||||||
var ret = fn.call(env);
|
var ret = fn.call(env);
|
||||||
profile.addreport(profcache, file, st);
|
profile.addreport(profcache, file, st);
|
||||||
|
@ -236,35 +240,34 @@ function use(file, env = {}, script)
|
||||||
|
|
||||||
use.cache = {};
|
use.cache = {};
|
||||||
|
|
||||||
global.check_registers = function(obj)
|
global.check_registers = function (obj) {
|
||||||
{
|
if (typeof obj.update === "function")
|
||||||
if (typeof obj.update === 'function')
|
obj.timers.push(Register.update.register(obj.update.bind(obj)));
|
||||||
obj.timers.push(Register.update.register(obj.update.bind(obj)));
|
|
||||||
|
|
||||||
if (typeof obj.physupdate === 'function')
|
if (typeof obj.physupdate === "function")
|
||||||
obj.timers.push(Register.physupdate.register(obj.physupdate.bind(obj)));
|
obj.timers.push(Register.physupdate.register(obj.physupdate.bind(obj)));
|
||||||
|
|
||||||
if (typeof obj.draw === 'function')
|
if (typeof obj.draw === "function")
|
||||||
obj.timers.push(Register.draw.register(obj.draw.bind(obj), obj));
|
obj.timers.push(Register.draw.register(obj.draw.bind(obj), obj));
|
||||||
|
|
||||||
if (typeof obj.debug === 'function')
|
if (typeof obj.debug === "function")
|
||||||
obj.timers.push(Register.debug.register(obj.debug.bind(obj)));
|
obj.timers.push(Register.debug.register(obj.debug.bind(obj)));
|
||||||
|
|
||||||
if (typeof obj.gui === 'function')
|
if (typeof obj.gui === "function")
|
||||||
obj.timers.push(Register.gui.register(obj.gui.bind(obj)));
|
obj.timers.push(Register.gui.register(obj.gui.bind(obj)));
|
||||||
|
|
||||||
if (typeof obj.screengui === 'function')
|
if (typeof obj.screengui === "function")
|
||||||
obj.timers.push(Register.screengui.register(obj.screengui.bind(obj)));
|
obj.timers.push(Register.screengui.register(obj.screengui.bind(obj)));
|
||||||
|
|
||||||
for (var k in obj) {
|
for (var k in obj) {
|
||||||
if (!k.startswith("on_")) continue;
|
if (!k.startswith("on_")) continue;
|
||||||
var signal = k.fromfirst("on_");
|
var signal = k.fromfirst("on_");
|
||||||
Event.observe(signal, obj, obj[k]);
|
Event.observe(signal, obj, obj[k]);
|
||||||
};
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Object.assign(global, use("scripts/base"));
|
Object.assign(global, use("scripts/base"));
|
||||||
global.obscure('global');
|
global.obscure("global");
|
||||||
global.mixin("scripts/render");
|
global.mixin("scripts/render");
|
||||||
global.mixin("scripts/debug");
|
global.mixin("scripts/debug");
|
||||||
|
|
||||||
|
@ -272,63 +275,71 @@ var frame_t = profile.secs(profile.now());
|
||||||
|
|
||||||
var sim = {};
|
var sim = {};
|
||||||
sim.mode = "play";
|
sim.mode = "play";
|
||||||
sim.play = function() { this.mode = "play"; os.reindex_static(); };
|
sim.play = function () {
|
||||||
sim.playing = function() { return this.mode === 'play'; };
|
this.mode = "play";
|
||||||
sim.pause = function() { this.mode = "pause"; };
|
os.reindex_static();
|
||||||
sim.paused = function() { return this.mode === 'pause'; };
|
};
|
||||||
sim.step = function() { this.mode = 'step'; };
|
sim.playing = function () {
|
||||||
sim.stepping = function() { return this.mode === 'step'; }
|
return this.mode === "play";
|
||||||
|
};
|
||||||
|
sim.pause = function () {
|
||||||
|
this.mode = "pause";
|
||||||
|
};
|
||||||
|
sim.paused = function () {
|
||||||
|
return this.mode === "pause";
|
||||||
|
};
|
||||||
|
sim.step = function () {
|
||||||
|
this.mode = "step";
|
||||||
|
};
|
||||||
|
sim.stepping = function () {
|
||||||
|
return this.mode === "step";
|
||||||
|
};
|
||||||
|
|
||||||
var physlag = 0;
|
var physlag = 0;
|
||||||
|
|
||||||
var gggstart = game.engine_start;
|
var gggstart = game.engine_start;
|
||||||
game.engine_start = function(s) {
|
game.engine_start = function (s) {
|
||||||
game.startengine = 1;
|
game.startengine = 1;
|
||||||
gggstart(function() {
|
gggstart(
|
||||||
global.mixin("scripts/sound.js");
|
function () {
|
||||||
world_start();
|
global.mixin("scripts/sound.js");
|
||||||
window.set_icon(os.make_texture("icons/moon.gif"))
|
world_start();
|
||||||
Object.readonly(window.__proto__, 'vsync');
|
window.set_icon(os.make_texture("icons/moon.gif"));
|
||||||
Object.readonly(window.__proto__, 'enable_dragndrop');
|
Object.readonly(window.__proto__, "vsync");
|
||||||
Object.readonly(window.__proto__, 'enable_clipboard');
|
Object.readonly(window.__proto__, "enable_dragndrop");
|
||||||
Object.readonly(window.__proto__, 'high_dpi');
|
Object.readonly(window.__proto__, "enable_clipboard");
|
||||||
Object.readonly(window.__proto__, 'sample_count');
|
Object.readonly(window.__proto__, "high_dpi");
|
||||||
s();
|
Object.readonly(window.__proto__, "sample_count");
|
||||||
|
s();
|
||||||
|
|
||||||
shape.quad = {
|
shape.quad = {
|
||||||
pos:os.make_buffer([
|
pos: os.make_buffer([0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0], 0),
|
||||||
0,0,0,
|
verts: 4,
|
||||||
1,0,0,
|
uv: os.make_buffer([0, 1, 1, 1, 0, 0, 1, 0], 2),
|
||||||
0,1,0,
|
index: os.make_buffer([0, 1, 2, 2, 1, 3], 1),
|
||||||
1,1,0
|
count: 6,
|
||||||
],0),
|
};
|
||||||
verts: 4,
|
|
||||||
uv: os.make_buffer([0,1,1,1,0,0,1,0],2),
|
|
||||||
index: os.make_buffer([0,1,2,2,1,3], 1),
|
|
||||||
count: 6
|
|
||||||
};
|
|
||||||
|
|
||||||
shape.triangle = {
|
shape.triangle = {
|
||||||
pos: os.make_buffer([
|
pos: os.make_buffer([0, 0, 0, 0.5, 1, 0, 1, 0, 0], 0),
|
||||||
0,0,0,
|
uv: os.make_buffer([0, 0, 0.5, 1, 1, 0], 2),
|
||||||
0.5,1,0,
|
verts: 3,
|
||||||
1,0,0]
|
count: 3,
|
||||||
,0),
|
index: os.make_buffer([0, 2, 1], 1),
|
||||||
uv: os.make_buffer([0,0,0.5,1,1,0],2),
|
};
|
||||||
verts: 3,
|
|
||||||
count: 3,
|
|
||||||
index: os.make_buffer([0,2,1],1),
|
|
||||||
};
|
|
||||||
|
|
||||||
render.init();
|
render.init();
|
||||||
}, process, window.size.x, window.size.y);
|
},
|
||||||
}
|
process,
|
||||||
|
window.size.x,
|
||||||
|
window.size.y,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
game.startengine = 0;
|
game.startengine = 0;
|
||||||
var frames = [];
|
var frames = [];
|
||||||
|
|
||||||
function process()
|
function process() {
|
||||||
{
|
|
||||||
var startframe = profile.now();
|
var startframe = profile.now();
|
||||||
var dt = profile.secs(profile.now()) - frame_t;
|
var dt = profile.secs(profile.now()) - frame_t;
|
||||||
frame_t = profile.secs(profile.now());
|
frame_t = profile.secs(profile.now());
|
||||||
|
@ -337,17 +348,16 @@ function process()
|
||||||
input.procdown();
|
input.procdown();
|
||||||
|
|
||||||
if (sim.mode === "play" || sim.mode === "step") {
|
if (sim.mode === "play" || sim.mode === "step") {
|
||||||
prosperon.update(dt*game.timescale);
|
prosperon.update(dt * game.timescale);
|
||||||
if (sim.mode === "step")
|
if (sim.mode === "step") sim.pause();
|
||||||
sim.pause();
|
|
||||||
|
|
||||||
physlag += dt;
|
physlag += dt;
|
||||||
|
|
||||||
while (physlag > physics.delta) {
|
while (physlag > physics.delta) {
|
||||||
physlag -= physics.delta;
|
physlag -= physics.delta;
|
||||||
var st = profile.now();
|
var st = profile.now();
|
||||||
prosperon.phys2d_step(physics.delta*game.timescale);
|
prosperon.phys2d_step(physics.delta * game.timescale);
|
||||||
prosperon.physupdate(physics.delta*game.timescale);
|
prosperon.physupdate(physics.delta * game.timescale);
|
||||||
profile.addreport(profcache, "physics step", st);
|
profile.addreport(profcache, "physics step", st);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -359,58 +369,52 @@ function process()
|
||||||
prosperon.screengui();
|
prosperon.screengui();
|
||||||
prosperon.hookend?.();
|
prosperon.hookend?.();
|
||||||
profile.addreport(profcache, "render frame", st);
|
profile.addreport(profcache, "render frame", st);
|
||||||
frames.push(profile.secs(profile.now()-startframe));
|
frames.push(profile.secs(profile.now() - startframe));
|
||||||
if (frames.length > 20) frames.shift();
|
if (frames.length > 20) frames.shift();
|
||||||
}
|
}
|
||||||
|
|
||||||
globalThis.fps = function()
|
globalThis.fps = function () {
|
||||||
{
|
|
||||||
var sum = 0;
|
var sum = 0;
|
||||||
for (var i = 0; i < frames.length; i++)
|
for (var i = 0; i < frames.length; i++) sum += frames[i];
|
||||||
sum += frames[i];
|
return frames.length / sum;
|
||||||
return frames.length/sum;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
game.timescale = 1;
|
game.timescale = 1;
|
||||||
|
|
||||||
var eachobj = function(obj,fn)
|
var eachobj = function (obj, fn) {
|
||||||
{
|
|
||||||
var val = fn(obj);
|
var val = fn(obj);
|
||||||
if (val) return val;
|
if (val) return val;
|
||||||
for (var o in obj.objects) {
|
for (var o in obj.objects) {
|
||||||
if (obj.objects[o] === obj)
|
if (obj.objects[o] === obj)
|
||||||
console.error(`Object ${obj.toString()} is referenced by itself.`);
|
console.error(`Object ${obj.toString()} is referenced by itself.`);
|
||||||
val = eachobj(obj.objects[o],fn);
|
val = eachobj(obj.objects[o], fn);
|
||||||
if (val) return val;
|
if (val) return val;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
game.all_objects = function(fn, startobj = world) { return eachobj(startobj,fn); };
|
game.all_objects = function (fn, startobj = world) {
|
||||||
game.find_object = function(fn, startobj = world) {
|
return eachobj(startobj, fn);
|
||||||
|
};
|
||||||
}
|
game.find_object = function (fn, startobj = world) {};
|
||||||
|
|
||||||
game.tags = {};
|
game.tags = {};
|
||||||
game.tag_add = function(tag, obj) {
|
game.tag_add = function (tag, obj) {
|
||||||
game.tags[tag] ??= {};
|
game.tags[tag] ??= {};
|
||||||
game.tags[tag][obj.guid] = obj;
|
game.tags[tag][obj.guid] = obj;
|
||||||
}
|
};
|
||||||
|
|
||||||
game.tag_rm = function(tag, obj) {
|
game.tag_rm = function (tag, obj) {
|
||||||
delete game.tags[tag][obj.guid];
|
delete game.tags[tag][obj.guid];
|
||||||
}
|
};
|
||||||
|
|
||||||
game.tag_clear_guid = function(guid)
|
game.tag_clear_guid = function (guid) {
|
||||||
{
|
for (var tag in game.tags) delete game.tags[tag][guid];
|
||||||
for (var tag in game.tags)
|
};
|
||||||
delete game.tags[tag][guid];
|
|
||||||
}
|
|
||||||
|
|
||||||
game.objects_with_tag = function(tag)
|
game.objects_with_tag = function (tag) {
|
||||||
{
|
|
||||||
if (!game.tags[tag]) return [];
|
if (!game.tags[tag]) return [];
|
||||||
return Object.values(game.tags[tag]);
|
return Object.values(game.tags[tag]);
|
||||||
}
|
};
|
||||||
|
|
||||||
game.doc = {};
|
game.doc = {};
|
||||||
game.doc.object = "Returns the entity belonging to a given id.";
|
game.doc.object = "Returns the entity belonging to a given id.";
|
||||||
|
@ -418,89 +422,85 @@ game.doc.pause = "Pause game simulation.";
|
||||||
game.doc.play = "Resume or start game simulation.";
|
game.doc.play = "Resume or start game simulation.";
|
||||||
game.doc.camera = "Current camera.";
|
game.doc.camera = "Current camera.";
|
||||||
|
|
||||||
game.texture = function(path)
|
game.texture = function (path) {
|
||||||
{
|
|
||||||
if (game.texture.cache[path]) return game.texture.cache[path];
|
if (game.texture.cache[path]) return game.texture.cache[path];
|
||||||
|
|
||||||
if (!io.exists(path)) {
|
if (!io.exists(path)) {
|
||||||
console.warn(`Missing texture: ${path}`);
|
console.warn(`Missing texture: ${path}`);
|
||||||
game.texture.cache[path] = game.texture("icons/no_tex.gif");
|
game.texture.cache[path] = game.texture("icons/no_tex.gif");
|
||||||
} else
|
} else game.texture.cache[path] ??= os.make_texture(path);
|
||||||
game.texture.cache[path] ??= os.make_texture(path);
|
|
||||||
|
|
||||||
return game.texture.cache[path];
|
return game.texture.cache[path];
|
||||||
}
|
};
|
||||||
game.texture.cache = {};
|
game.texture.cache = {};
|
||||||
|
|
||||||
prosperon.semver = {};
|
prosperon.semver = {};
|
||||||
prosperon.semver.valid = function(v, range)
|
prosperon.semver.valid = function (v, range) {
|
||||||
{
|
v = v.split(".");
|
||||||
v = v.split('.');
|
range = range.split(".");
|
||||||
range = range.split('.');
|
|
||||||
if (v.length !== 3) return undefined;
|
if (v.length !== 3) return undefined;
|
||||||
if (range.length !== 3) return undefined;
|
if (range.length !== 3) return undefined;
|
||||||
|
|
||||||
if (range[0][0] === '^') {
|
if (range[0][0] === "^") {
|
||||||
range[0] = range[0].slice(1);
|
range[0] = range[0].slice(1);
|
||||||
if (parseInt(v[0]) >= parseInt(range[0])) return true;
|
if (parseInt(v[0]) >= parseInt(range[0])) return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (range[0] === '~') {
|
if (range[0] === "~") {
|
||||||
range[0] = range[0].slice(1);
|
range[0] = range[0].slice(1);
|
||||||
for (var i = 0; i < 2; i++)
|
for (var i = 0; i < 2; i++)
|
||||||
if (parseInt(v[i]) < parseInt(range[i])) return false;
|
if (parseInt(v[i]) < parseInt(range[i])) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return prosperon.semver.cmp(v.join('.'), range.join('.')) === 0;
|
return prosperon.semver.cmp(v.join("."), range.join(".")) === 0;
|
||||||
}
|
};
|
||||||
|
|
||||||
prosperon.semver.cmp = function(v1, v2)
|
prosperon.semver.cmp = function (v1, v2) {
|
||||||
{
|
var ver1 = v1.split(".");
|
||||||
var ver1 = v1.split('.');
|
var ver2 = v2.split(".");
|
||||||
var ver2 = v2.split('.');
|
|
||||||
|
|
||||||
for (var i = 0; i < 3; i++) {
|
for (var i = 0; i < 3; i++) {
|
||||||
var n1 = parseInt(ver1[i]);
|
var n1 = parseInt(ver1[i]);
|
||||||
var n2 = parseInt(ver2[i]);
|
var n2 = parseInt(ver2[i]);
|
||||||
if (n1 > n2)
|
if (n1 > n2) return 1;
|
||||||
return 1;
|
else if (n1 < n2) return -1;
|
||||||
else if (n1 < n2)
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
};
|
||||||
|
|
||||||
prosperon.semver.doc = "Functions for semantic versioning numbers. Semantic versioning is given as a triple digit number, as MAJOR.MINOR.PATCH.";
|
prosperon.semver.doc =
|
||||||
prosperon.semver.cmp.doc = "Compare two semantic version numbers, given like X.X.X.";
|
"Functions for semantic versioning numbers. Semantic versioning is given as a triple digit number, as MAJOR.MINOR.PATCH.";
|
||||||
|
prosperon.semver.cmp.doc =
|
||||||
|
"Compare two semantic version numbers, given like X.X.X.";
|
||||||
prosperon.semver.valid.doc = `Test if semantic version v is valid, given a range.
|
prosperon.semver.valid.doc = `Test if semantic version v is valid, given a range.
|
||||||
Range is given by a semantic versioning number, prefixed with nothing, a ~, or a ^.
|
Range is given by a semantic versioning number, prefixed with nothing, a ~, or a ^.
|
||||||
~ means that MAJOR and MINOR must match exactly, but any PATCH greater or equal is valid.
|
~ means that MAJOR and MINOR must match exactly, but any PATCH greater or equal is valid.
|
||||||
^ means that MAJOR must match exactly, but any MINOR and PATCH greater or equal is valid.`;
|
^ means that MAJOR must match exactly, but any MINOR and PATCH greater or equal is valid.`;
|
||||||
|
|
||||||
prosperon.iconified = function(icon) {};
|
prosperon.iconified = function (icon) {};
|
||||||
prosperon.focus = function(focus) {};
|
prosperon.focus = function (focus) {};
|
||||||
prosperon.resize = function(dimensions) {
|
prosperon.resize = function (dimensions) {
|
||||||
window.size.x = dimensions.x;
|
window.size.x = dimensions.x;
|
||||||
window.size.y = dimensions.y;
|
window.size.y = dimensions.y;
|
||||||
};
|
};
|
||||||
prosperon.suspended = function(sus) {};
|
prosperon.suspended = function (sus) {};
|
||||||
prosperon.mouseenter = function(){};
|
prosperon.mouseenter = function () {};
|
||||||
prosperon.mouseleave = function(){};
|
prosperon.mouseleave = function () {};
|
||||||
prosperon.touchpress = function(touches){};
|
prosperon.touchpress = function (touches) {};
|
||||||
prosperon.touchrelease = function(touches){};
|
prosperon.touchrelease = function (touches) {};
|
||||||
prosperon.touchmove = function(touches){};
|
prosperon.touchmove = function (touches) {};
|
||||||
prosperon.clipboardpaste = function(str){};
|
prosperon.clipboardpaste = function (str) {};
|
||||||
prosperon.quit = function(){
|
prosperon.quit = function () {
|
||||||
say(profile.printreport(profcache, "USE REPORT"));
|
say(profile.printreport(profcache, "USE REPORT"));
|
||||||
say(profile.printreport(entityreport, "ENTITY REPORT"));
|
say(profile.printreport(entityreport, "ENTITY REPORT"));
|
||||||
|
|
||||||
console.info("QUITTING");
|
console.info("QUITTING");
|
||||||
for (var i in debug.log.time)
|
for (var i in debug.log.time)
|
||||||
say(debug.log.time[i].map(x=>profile.ms(x)));
|
say(debug.log.time[i].map((x) => profile.ms(x)));
|
||||||
};
|
};
|
||||||
|
|
||||||
global.mixin("scripts/input");
|
global.mixin("scripts/input");
|
||||||
|
@ -551,18 +551,21 @@ var Register = {
|
||||||
var n = {};
|
var n = {};
|
||||||
var fns = [];
|
var fns = [];
|
||||||
|
|
||||||
n.register = function(fn, obj) {
|
n.register = function (fn, obj) {
|
||||||
if (typeof fn !== 'function') return;
|
if (typeof fn !== "function") return;
|
||||||
if (typeof obj === 'object')
|
if (typeof obj === "object") fn = fn.bind(obj);
|
||||||
fn = fn.bind(obj);
|
|
||||||
fns.push(fn);
|
fns.push(fn);
|
||||||
return function() {
|
return function () {
|
||||||
fns.remove(fn);
|
fns.remove(fn);
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
prosperon[name] = function(...args) { fns.forEach(x => x(...args)); }
|
prosperon[name] = function (...args) {
|
||||||
|
fns.forEach((x) => x(...args));
|
||||||
|
};
|
||||||
prosperon[name].fns = fns;
|
prosperon[name].fns = fns;
|
||||||
n.clear = function() { fns = []; }
|
n.clear = function () {
|
||||||
|
fns = [];
|
||||||
|
};
|
||||||
|
|
||||||
Register[name] = n;
|
Register[name] = n;
|
||||||
Register.registries.push(n);
|
Register.registries.push(n);
|
||||||
|
@ -588,16 +591,16 @@ var Event = {
|
||||||
},
|
},
|
||||||
|
|
||||||
unobserve(name, obj) {
|
unobserve(name, obj) {
|
||||||
this.events[name] = this.events[name].filter(x => x[0] !== obj);
|
this.events[name] = this.events[name].filter((x) => x[0] !== obj);
|
||||||
},
|
},
|
||||||
|
|
||||||
rm_obj(obj) {
|
rm_obj(obj) {
|
||||||
Object.keys(this.events).forEach(name => Event.unobserve(name,obj));
|
Object.keys(this.events).forEach((name) => Event.unobserve(name, obj));
|
||||||
},
|
},
|
||||||
|
|
||||||
notify(name, ...args) {
|
notify(name, ...args) {
|
||||||
if (!this.events[name]) return;
|
if (!this.events[name]) return;
|
||||||
this.events[name].forEach(function(x) {
|
this.events[name].forEach(function (x) {
|
||||||
x[1].call(x[0], ...args);
|
x[1].call(x[0], ...args);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -623,9 +626,11 @@ global.mixin("scripts/spline");
|
||||||
global.mixin("scripts/components");
|
global.mixin("scripts/components");
|
||||||
|
|
||||||
window.doc = {};
|
window.doc = {};
|
||||||
window.doc.dimensions = "Window width and height packaged in an array [width,height]";
|
window.doc.dimensions =
|
||||||
|
"Window width and height packaged in an array [width,height]";
|
||||||
window.doc.title = "Name in the title bar of the window.";
|
window.doc.title = "Name in the title bar of the window.";
|
||||||
window.doc.boundingbox = "Boundingbox of the window, with top and right being its height and width.";
|
window.doc.boundingbox =
|
||||||
|
"Boundingbox of the window, with top and right being its height and width.";
|
||||||
|
|
||||||
global.mixin("scripts/actor");
|
global.mixin("scripts/actor");
|
||||||
global.mixin("scripts/entity");
|
global.mixin("scripts/entity");
|
||||||
|
@ -634,9 +639,13 @@ function world_start() {
|
||||||
globalThis.world = Object.create(entity);
|
globalThis.world = Object.create(entity);
|
||||||
world.transform = os.make_transform();
|
world.transform = os.make_transform();
|
||||||
world.objects = {};
|
world.objects = {};
|
||||||
world.toString = function() { return "world"; };
|
world.toString = function () {
|
||||||
|
return "world";
|
||||||
|
};
|
||||||
world.ur = "world";
|
world.ur = "world";
|
||||||
world.kill = function() { this.clear(); };
|
world.kill = function () {
|
||||||
|
this.clear();
|
||||||
|
};
|
||||||
world.phys = 2;
|
world.phys = 2;
|
||||||
world.zoom = 1;
|
world.zoom = 1;
|
||||||
world._ed = { selectable: false };
|
world._ed = { selectable: false };
|
||||||
|
@ -651,9 +660,9 @@ global.mixin("scripts/widget");
|
||||||
globalThis.mum = app.spawn("scripts/mum");
|
globalThis.mum = app.spawn("scripts/mum");
|
||||||
|
|
||||||
window.title = `Prosperon v${prosperon.version}`;
|
window.title = `Prosperon v${prosperon.version}`;
|
||||||
window.size = [500,500];
|
window.size = [500, 500];
|
||||||
window.boundingbox = function() {
|
window.boundingbox = function () {
|
||||||
var pos = game.camera.pos;
|
var pos = game.camera.pos;
|
||||||
var wh = window.rendersize.scale(game.camera.zoom);
|
var wh = window.rendersize.scale(game.camera.zoom);
|
||||||
return bbox.fromcwh(pos,wh);
|
return bbox.fromcwh(pos, wh);
|
||||||
}
|
};
|
||||||
|
|
|
@ -105,7 +105,7 @@ var entity = {
|
||||||
set scale(x) { this.transform.scale = x; },
|
set scale(x) { this.transform.scale = x; },
|
||||||
|
|
||||||
move(vec) { this.pos = this.pos.add(vec); },
|
move(vec) { this.pos = this.pos.add(vec); },
|
||||||
rotate(x) { this.angle += x; },
|
rotate(x) { this.transform.rotate(x, [0,0,-1]); },
|
||||||
grow(vec) {
|
grow(vec) {
|
||||||
if (typeof vec === 'number') vec = [vec,vec];
|
if (typeof vec === 'number') vec = [vec,vec];
|
||||||
this.scale = this.scale.map((x,i) => x*vec[i]);
|
this.scale = this.scale.map((x,i) => x*vec[i]);
|
||||||
|
|
|
@ -1909,6 +1909,21 @@ HMM_Quat HMM_M4ToQ_LH(HMM_Mat4 M) {
|
||||||
return Q;
|
return Q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float HMM_Q_Roll(HMM_Quat q)
|
||||||
|
{
|
||||||
|
return atan2(2.0*(q.x*q.y + q.w*q.z), q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
float HMM_Q_Pitch(HMM_Quat q)
|
||||||
|
{
|
||||||
|
return asin(-2.0*(q.x*q.z - q.w*q.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
float HMM_Q_Yaw(HMM_Quat q)
|
||||||
|
{
|
||||||
|
return atan2(2.0*(q.y*q.z + q.w*q.x), q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z);
|
||||||
|
}
|
||||||
|
|
||||||
HMM_Quat HMM_QFromAxisAngle_RH(HMM_Vec3 Axis, float AngleOfRotation) {
|
HMM_Quat HMM_QFromAxisAngle_RH(HMM_Vec3 Axis, float AngleOfRotation) {
|
||||||
|
|
||||||
HMM_Quat Result;
|
HMM_Quat Result;
|
||||||
|
|
|
@ -658,4 +658,8 @@ HMM_Quat HMM_M4ToQ_LH(HMM_Mat4 M);
|
||||||
HMM_Quat HMM_QFromAxisAngle_RH(HMM_Vec3 Axis, float AngleOfRotation);
|
HMM_Quat HMM_QFromAxisAngle_RH(HMM_Vec3 Axis, float AngleOfRotation);
|
||||||
HMM_Quat HMM_QFromAxisAngle_LH(HMM_Vec3 Axis, float AngleOfRotation);
|
HMM_Quat HMM_QFromAxisAngle_LH(HMM_Vec3 Axis, float AngleOfRotation);
|
||||||
|
|
||||||
|
float HMM_Q_Roll(HMM_Quat q);
|
||||||
|
float HMM_Q_Yaw(HMM_Quat q);
|
||||||
|
float HMM_Q_Pitch(HMM_Quat q);
|
||||||
|
|
||||||
#endif /* HANDMADE_MATH_H */
|
#endif /* HANDMADE_MATH_H */
|
||||||
|
|
|
@ -1474,6 +1474,7 @@ JSC_GETSET(transform, pos, vec3)
|
||||||
JSC_GETSET(transform, scale, vec3)
|
JSC_GETSET(transform, scale, vec3)
|
||||||
JSC_GETSET(transform, rotation, quat)
|
JSC_GETSET(transform, rotation, quat)
|
||||||
JSC_CCALL(transform_move, transform_move(js2transform(self), js2vec3(argv[0])); )
|
JSC_CCALL(transform_move, transform_move(js2transform(self), js2vec3(argv[0])); )
|
||||||
|
|
||||||
JSC_CCALL(transform_lookat,
|
JSC_CCALL(transform_lookat,
|
||||||
HMM_Vec3 point = js2vec3(argv[0]);
|
HMM_Vec3 point = js2vec3(argv[0]);
|
||||||
transform *go = js2transform(self);
|
transform *go = js2transform(self);
|
||||||
|
@ -1488,6 +1489,15 @@ JSC_CCALL(transform_rotate,
|
||||||
t->rotation = HMM_MulQ(t->rotation,rot);
|
t->rotation = HMM_MulQ(t->rotation,rot);
|
||||||
)
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(transform_angle,
|
||||||
|
HMM_Vec3 axis = js2vec3(argv[0]);
|
||||||
|
transform *t = js2transform(self);
|
||||||
|
if (axis.x) return angle2js(HMM_Q_Roll(t->rotation));
|
||||||
|
if (axis.y) return angle2js(HMM_Q_Pitch(t->rotation));
|
||||||
|
if (axis.z) return angle2js(HMM_Q_Yaw(t->rotation));
|
||||||
|
return angle2js(0);
|
||||||
|
)
|
||||||
|
|
||||||
JSC_CCALL(transform_direction,
|
JSC_CCALL(transform_direction,
|
||||||
transform *t = js2transform(self);
|
transform *t = js2transform(self);
|
||||||
return vec32js(HMM_QVRot(js2vec3(argv[0]), t->rotation));
|
return vec32js(HMM_QVRot(js2vec3(argv[0]), t->rotation));
|
||||||
|
@ -1499,6 +1509,7 @@ static const JSCFunctionListEntry js_transform_funcs[] = {
|
||||||
CGETSET_ADD(transform, rotation),
|
CGETSET_ADD(transform, rotation),
|
||||||
MIST_FUNC_DEF(transform, move, 1),
|
MIST_FUNC_DEF(transform, move, 1),
|
||||||
MIST_FUNC_DEF(transform, rotate, 2),
|
MIST_FUNC_DEF(transform, rotate, 2),
|
||||||
|
MIST_FUNC_DEF(transform, angle, 1),
|
||||||
MIST_FUNC_DEF(transform, lookat, 1),
|
MIST_FUNC_DEF(transform, lookat, 1),
|
||||||
MIST_FUNC_DEF(transform, direction, 1),
|
MIST_FUNC_DEF(transform, direction, 1),
|
||||||
};
|
};
|
||||||
|
@ -1988,11 +1999,18 @@ JSC_GET(texture, height, number)
|
||||||
JSC_GET(texture, frames, number)
|
JSC_GET(texture, frames, number)
|
||||||
JSC_GET(texture, delays, ints)
|
JSC_GET(texture, delays, ints)
|
||||||
|
|
||||||
|
JSC_SCALL(texture_save, texture_save(js2texture(self), str));
|
||||||
|
|
||||||
|
JSC_CCALL(texture_blit,
|
||||||
|
texture_blit(js2texture(self), js2texture(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), js2number(argv[4])))
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_texture_funcs[] = {
|
static const JSCFunctionListEntry js_texture_funcs[] = {
|
||||||
MIST_GET(texture, width),
|
MIST_GET(texture, width),
|
||||||
MIST_GET(texture, height),
|
MIST_GET(texture, height),
|
||||||
MIST_GET(texture, frames),
|
MIST_GET(texture, frames),
|
||||||
MIST_GET(texture, delays),
|
MIST_GET(texture, delays),
|
||||||
|
MIST_FUNC_DEF(texture, save, 2),
|
||||||
|
MIST_FUNC_DEF(texture, blit, 3)
|
||||||
};
|
};
|
||||||
|
|
||||||
JSC_GETSET(font, linegap, number)
|
JSC_GETSET(font, linegap, number)
|
||||||
|
@ -2289,6 +2307,8 @@ JSC_SCALL(os_make_texture,
|
||||||
JS_SetPropertyStr(js, ret, "path", JS_DupValue(js,argv[0]));
|
JS_SetPropertyStr(js, ret, "path", JS_DupValue(js,argv[0]));
|
||||||
)
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_make_tex_data, ret = texture2js(texture_empty(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]))))
|
||||||
|
|
||||||
JSC_CCALL(os_make_font,
|
JSC_CCALL(os_make_font,
|
||||||
font *f = MakeFont(js2str(argv[0]), js2number(argv[1]));
|
font *f = MakeFont(js2str(argv[0]), js2number(argv[1]));
|
||||||
ret = font2js(f);
|
ret = font2js(f);
|
||||||
|
@ -2517,6 +2537,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||||
MIST_FUNC_DEF(os, make_poly2d, 2),
|
MIST_FUNC_DEF(os, make_poly2d, 2),
|
||||||
MIST_FUNC_DEF(os, make_seg2d, 1),
|
MIST_FUNC_DEF(os, make_seg2d, 1),
|
||||||
MIST_FUNC_DEF(os, make_texture, 1),
|
MIST_FUNC_DEF(os, make_texture, 1),
|
||||||
|
MIST_FUNC_DEF(os, make_tex_data, 3),
|
||||||
MIST_FUNC_DEF(os, make_font, 2),
|
MIST_FUNC_DEF(os, make_font, 2),
|
||||||
MIST_FUNC_DEF(os, make_model, 1),
|
MIST_FUNC_DEF(os, make_model, 1),
|
||||||
MIST_FUNC_DEF(os, make_transform, 0),
|
MIST_FUNC_DEF(os, make_transform, 0),
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "sokol/sokol_gfx.h"
|
#include "sokol/sokol_gfx.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stb_image.h>
|
#include <stb_image.h>
|
||||||
|
#include <stb_image_write.h>
|
||||||
|
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
|
|
||||||
|
@ -173,6 +174,26 @@ void texture_free(texture *tex)
|
||||||
free(tex);
|
free(tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct texture *texture_empty(int w, int h, int n)
|
||||||
|
{
|
||||||
|
texture *tex = calloc(1,sizeof(*tex));
|
||||||
|
tex->data = calloc(w*h*n, sizeof(unsigned char));
|
||||||
|
tex->width = w;
|
||||||
|
tex->height = h;
|
||||||
|
sg_image_data sgdata;
|
||||||
|
sgdata.subimage[0][0] = (sg_range){.ptr = tex->data, .size = w*h*4};
|
||||||
|
tex->id = sg_make_image(&(sg_image_desc){
|
||||||
|
.type = SG_IMAGETYPE_2D,
|
||||||
|
.width = tex->width,
|
||||||
|
.height = tex->height,
|
||||||
|
.usage = SG_USAGE_IMMUTABLE,
|
||||||
|
.num_mipmaps = 1,
|
||||||
|
.data = sgdata,
|
||||||
|
});
|
||||||
|
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
struct texture *texture_fromdata(void *raw, long size)
|
struct texture *texture_fromdata(void *raw, long size)
|
||||||
{
|
{
|
||||||
struct texture *tex = calloc(1, sizeof(*tex));
|
struct texture *tex = calloc(1, sizeof(*tex));
|
||||||
|
@ -260,6 +281,64 @@ double grad (int hash, double x, double y, double z)
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void texture_save(texture *tex, const char *file)
|
||||||
|
{
|
||||||
|
char *ext = strrchr(file, '.');
|
||||||
|
printf("SAVING TO %s with ext %s\n", file, ext);
|
||||||
|
if (!strcmp(ext, ".png"))
|
||||||
|
stbi_write_png(file, tex->width, tex->height, 4, tex->data, 4*tex->width);
|
||||||
|
else if (!strcmp(ext, ".bmp"))
|
||||||
|
stbi_write_bmp(file, tex->width, tex->height, 4, tex->data);
|
||||||
|
else if (!strcmp(ext, ".tga"))
|
||||||
|
stbi_write_tga(file, tex->width, tex->height, 4, tex->data);
|
||||||
|
else if (!strcmp(ext, ".jpg") || !strcmp(ext, ".jpeg"))
|
||||||
|
stbi_write_jpg(file, tex->width, tex->height, 4, tex->data, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void blit_image(uint8_t* src, uint8_t* dest, int src_width, int src_height, int dest_width, int dest_height, int sx, int sy, int sw, int sh) {
|
||||||
|
int src_stride = src_width * 4;
|
||||||
|
int dest_stride = dest_width * 4;
|
||||||
|
|
||||||
|
for (int y = 0; y < sw; y++) {
|
||||||
|
for (int x = 0; x < sh; x++) {
|
||||||
|
int src_index = (y * src_stride) + (x * 4);
|
||||||
|
int dest_index = ((y + sy) * dest_stride) + ((x + sx) * 4);
|
||||||
|
|
||||||
|
// Calculate the alpha value for the source pixel
|
||||||
|
uint8_t src_alpha = src[src_index + 3];
|
||||||
|
|
||||||
|
// Calculate the alpha value for the destination pixel
|
||||||
|
uint8_t dest_alpha = dest[dest_index + 3];
|
||||||
|
|
||||||
|
// Calculate the resulting alpha value
|
||||||
|
uint8_t result_alpha = src_alpha + (255 - src_alpha) * dest_alpha / 255;
|
||||||
|
|
||||||
|
// Calculate the resulting RGB values
|
||||||
|
uint8_t result_red = (src[src_index + 0] * src_alpha + dest[dest_index + 0] * (255 - src_alpha) * dest_alpha / 255) / result_alpha;
|
||||||
|
uint8_t result_green = (src[src_index + 1] * src_alpha + dest[dest_index + 1] * (255 - src_alpha) * dest_alpha / 255) / result_alpha;
|
||||||
|
uint8_t result_blue = (src[src_index + 2] * src_alpha + dest[dest_index + 2] * (255 - src_alpha) * dest_alpha / 255) / result_alpha;
|
||||||
|
|
||||||
|
// Set the resulting pixel values
|
||||||
|
dest[dest_index + 0] = result_red;
|
||||||
|
dest[dest_index + 1] = result_green;
|
||||||
|
dest[dest_index + 2] = result_blue;
|
||||||
|
dest[dest_index + 3] = result_alpha;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Function to draw source image pixels on top of a destination image
|
||||||
|
void texture_blit(texture *dest, texture *src, int x, int y, int w, int h) {
|
||||||
|
blit_image(src->data, dest->data, src->width, src->height, dest->height, dest->width, x, y, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void texture_flip(texture *tex, int y)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static int p[512] = {151,160,137,91,90,15,
|
static int p[512] = {151,160,137,91,90,15,
|
||||||
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
||||||
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
||||||
|
|
|
@ -40,8 +40,11 @@ typedef struct img_sampler{
|
||||||
|
|
||||||
texture *texture_from_file(const char *path);
|
texture *texture_from_file(const char *path);
|
||||||
void texture_free(texture *tex);
|
void texture_free(texture *tex);
|
||||||
|
|
||||||
struct texture *texture_fromdata(void *raw, long size);
|
struct texture *texture_fromdata(void *raw, long size);
|
||||||
|
texture *texture_empty(int width, int height, int n);
|
||||||
|
void texture_blit(texture *dest, texture *src, int x, int y, int w, int h);
|
||||||
|
void texture_flip(texture *tex, int y);
|
||||||
|
void texture_save(texture *tex, const char *file);
|
||||||
|
|
||||||
double perlin(double x, double y, double z);
|
double perlin(double x, double y, double z);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue