Compare commits
20 commits
845ee6ade3
...
33d4ebf14a
Author | SHA1 | Date | |
---|---|---|---|
John Alanbrook | 33d4ebf14a | ||
John Alanbrook | 570c12e3db | ||
John Alanbrook | 05bc965d10 | ||
John Alanbrook | 1142bfb896 | ||
John Alanbrook | 6047452b62 | ||
John Alanbrook | 0a7f5a5cdd | ||
John Alanbrook | 55ae7e2171 | ||
John Alanbrook | cb6f64925e | ||
John Alanbrook | 90940b42f5 | ||
John Alanbrook | ef802bb6f2 | ||
John Alanbrook | 08725d474d | ||
John Alanbrook | f905dbc571 | ||
John Alanbrook | 531cc1b43e | ||
John Alanbrook | 9d51858266 | ||
John Alanbrook | d4b057dc6f | ||
John Alanbrook | ff71ee9db6 | ||
John Alanbrook | 2eb75491ea | ||
John Alanbrook | cf6feffda2 | ||
John Alanbrook | 066b213fbe | ||
John Alanbrook | 63239fa51a |
169
docs/api/mum.md
169
docs/api/mum.md
|
@ -1,9 +1,172 @@
|
||||||
# mum
|
# Mum
|
||||||
#### screengui()
|
#### padding
|
||||||
|
**array**
|
||||||
|
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
|
||||||
|
#### offset
|
||||||
|
**array**
|
||||||
|
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
|
||||||
|
#### font
|
||||||
|
**string**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### prompt(msg = "prompt", value = "", list = [], cb = function()
|
#### selectable
|
||||||
|
**boolean**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### selected
|
||||||
|
**boolean**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### font_size
|
||||||
|
**number**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### text_align
|
||||||
|
**string**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### scale
|
||||||
|
**number**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### angle
|
||||||
|
**number**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### anchor
|
||||||
|
**array**
|
||||||
|
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
|
||||||
|
#### hovered
|
||||||
|
**object**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### text_shadow
|
||||||
|
**object**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### text_outline
|
||||||
|
**number**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### color
|
||||||
|
**array**
|
||||||
|
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
|
||||||
|
#### margin
|
||||||
|
**array**
|
||||||
|
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
|
||||||
|
#### width
|
||||||
|
**number**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### height
|
||||||
|
**number**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### max_width
|
||||||
|
**number**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### max_height
|
||||||
|
**number**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### image_repeat
|
||||||
|
**boolean**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### image_repeat_offset
|
||||||
|
**array**
|
||||||
|
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
|
||||||
|
#### debug
|
||||||
|
**boolean**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### make(def)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### prestart()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### start()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### extend(def)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### text(def)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### button(def)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### window(def)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### image(def)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### column(def)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### debug_colors
|
||||||
|
**object**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1 +1,15 @@
|
||||||
scripts/debug.js:205: [2024-07-03 12:13:12] [22;33mwarn[0m, script: Cannot print the API of something that isn't an object.
|
# Tween
|
||||||
|
#### default
|
||||||
|
**object**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### start(obj, target, tvals, options)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### make(obj, target, tvals, options)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
9
docs/engine_tour/profiling.md
Normal file
9
docs/engine_tour/profiling.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Profiling
|
||||||
|
|
||||||
|
There are a handful of profiling methods available to you.
|
||||||
|
|
||||||
|
## Frame by frame profile
|
||||||
|
|
||||||
|
## Cpu instrumentation
|
||||||
|
|
||||||
|
## Game stats
|
|
@ -12,11 +12,18 @@ actor.spawn = function(script, config, callback){
|
||||||
padawan.timers = [];
|
padawan.timers = [];
|
||||||
padawan.master = this;
|
padawan.master = this;
|
||||||
Object.hide(padawan, "master", "timers", "padawans");
|
Object.hide(padawan, "master", "timers", "padawans");
|
||||||
|
padawan.toString = function() { return script; }
|
||||||
check_registers(padawan);
|
check_registers(padawan);
|
||||||
this.padawans.push(padawan);
|
this.padawans.push(padawan);
|
||||||
return padawan;
|
return padawan;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
actor.tween = function(from,to,time,fn) {
|
||||||
|
var stop = tween(from,to,time,fn);
|
||||||
|
this.timers.push(stop);
|
||||||
|
return stop;
|
||||||
|
}
|
||||||
|
|
||||||
actor.spawn.doc = `Create a new actor, using this actor as the master, initializing it with 'script' and with data (as a JSON or Nota file) from 'config'.`;
|
actor.spawn.doc = `Create a new actor, using this actor as the master, initializing it with 'script' and with data (as a JSON or Nota file) from 'config'.`;
|
||||||
|
|
||||||
actor.rm_pawn = function(pawn)
|
actor.rm_pawn = function(pawn)
|
||||||
|
@ -36,26 +43,11 @@ actor.kill = function(){
|
||||||
this.__dead__ = true;
|
this.__dead__ = true;
|
||||||
if (typeof this.die === 'function') this.die();
|
if (typeof this.die === 'function') this.die();
|
||||||
if (typeof this.stop === 'function') this.stop();
|
if (typeof this.stop === 'function') this.stop();
|
||||||
|
if (typeof this.garbage === 'function') this.garbage();
|
||||||
};
|
};
|
||||||
|
|
||||||
actor.kill.doc = `Remove this actor and all its padawans from existence.`;
|
actor.kill.doc = `Remove this actor and all its padawans from existence.`;
|
||||||
|
|
||||||
actor.interval = function(fn, seconds) {
|
|
||||||
var cur;
|
|
||||||
var stop = function() {
|
|
||||||
cur();
|
|
||||||
}
|
|
||||||
|
|
||||||
var f = function() {
|
|
||||||
fn.call(this);
|
|
||||||
cur = this.delay(f,seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
cur = this.delay(f,seconds);
|
|
||||||
|
|
||||||
return stop;
|
|
||||||
}
|
|
||||||
|
|
||||||
actor.delay = function(fn, seconds) {
|
actor.delay = function(fn, seconds) {
|
||||||
var timers = this.timers;
|
var timers = this.timers;
|
||||||
var stop = function() {
|
var stop = function() {
|
||||||
|
@ -64,7 +56,8 @@ actor.delay = function(fn, seconds) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function execute() {
|
function execute() {
|
||||||
fn();
|
if (fn) fn();
|
||||||
|
if (stop.then) stop.then();
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,9 +66,10 @@ actor.delay = function(fn, seconds) {
|
||||||
stop.pct = function() { return 1-(stop.remain / stop.seconds); };
|
stop.pct = function() { return 1-(stop.remain / stop.seconds); };
|
||||||
|
|
||||||
function update(dt) {
|
function update(dt) {
|
||||||
|
profile.frame("timer");
|
||||||
stop.remain -= dt;
|
stop.remain -= dt;
|
||||||
if (stop.remain <= 0)
|
if (stop.remain <= 0) execute();
|
||||||
execute();
|
profile.endframe();
|
||||||
}
|
}
|
||||||
|
|
||||||
var rm = Register.appupdate.register(update);
|
var rm = Register.appupdate.register(update);
|
||||||
|
|
205
scripts/base.js
205
scripts/base.js
|
@ -409,7 +409,7 @@ Object.dainty_assign = function(target, source)
|
||||||
|
|
||||||
Object.isObject = function(o)
|
Object.isObject = function(o)
|
||||||
{
|
{
|
||||||
return (typeof o === 'object' && !Array.isArray(o));
|
return (o instanceof Object && !(o instanceof Array));
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setter_assign = function(target, source)
|
Object.setter_assign = function(target, source)
|
||||||
|
@ -512,7 +512,7 @@ Object.copy = function(proto, ...objs)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OBJECT DEFININTioNS */
|
/* OBJECT DEFININTIONS */
|
||||||
Object.defHidden = function(obj, prop)
|
Object.defHidden = function(obj, prop)
|
||||||
{
|
{
|
||||||
Object.defineProperty(obj, prop, {enumerable:false, writable:true});
|
Object.defineProperty(obj, prop, {enumerable:false, writable:true});
|
||||||
|
@ -657,19 +657,6 @@ Object.defineProperty(Object.prototype, 'push', {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.defineProperty(Object.prototype, 'findIndex', {
|
|
||||||
value: function(x) {
|
|
||||||
var i = 0;
|
|
||||||
for (var key in this) {
|
|
||||||
if (this[key] === x) return i;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/* STRING DEFS */
|
/* STRING DEFS */
|
||||||
|
|
||||||
Object.defineProperty(String.prototype, 'next', {
|
Object.defineProperty(String.prototype, 'next', {
|
||||||
|
@ -763,12 +750,6 @@ Object.defineProperty(String.prototype, 'up_path', {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.defineProperty(String.prototype, 'resolve', {
|
|
||||||
value: function(path) {
|
|
||||||
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(String.prototype, 'fromlast', {
|
Object.defineProperty(String.prototype, 'fromlast', {
|
||||||
value: function(val) {
|
value: function(val) {
|
||||||
var idx = this.lastIndexOf(val);
|
var idx = this.lastIndexOf(val);
|
||||||
|
@ -824,10 +805,6 @@ Object.defineProperty(String.prototype, 'sub', {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.defineProperty(String.prototype, 'rm', {
|
|
||||||
value: function(index, endidx = index+1) { return this.slice(0,index) + this.slice(endidx); }
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(String.prototype, 'updir', {
|
Object.defineProperty(String.prototype, 'updir', {
|
||||||
value: function() {
|
value: function() {
|
||||||
if (this.lastIndexOf('/') === this.length-1)
|
if (this.lastIndexOf('/') === this.length-1)
|
||||||
|
@ -840,42 +817,7 @@ Object.defineProperty(String.prototype, 'updir', {
|
||||||
|
|
||||||
Object.defineProperty(String.prototype, 'trimchr', {
|
Object.defineProperty(String.prototype, 'trimchr', {
|
||||||
value: function(chars) {
|
value: function(chars) {
|
||||||
var start = this.length;
|
return vector.trimchr(this, chars);
|
||||||
var end = 0;
|
|
||||||
for (var i = 0; i < this.length; i++) {
|
|
||||||
if (!chars.includes(this[i])) {
|
|
||||||
start = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = this.length-1; i >= 0; i--) {
|
|
||||||
if (!chars.includes(this[i])) {
|
|
||||||
end = i+1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.substring(start,end);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(String.prototype, 'startswith', {
|
|
||||||
value: function(val) {
|
|
||||||
if (!val) return false;
|
|
||||||
return this.startsWith(val);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(String.prototype, 'endswith', {
|
|
||||||
value: function(val) {
|
|
||||||
if (!val) return false;
|
|
||||||
return this.endsWith(val);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(String.prototype, 'pct', {
|
|
||||||
value: function(val) {
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -883,11 +825,6 @@ Object.defineProperty(String.prototype, 'uc', { value: function() { return this.
|
||||||
Object.defineProperty(String.prototype, 'lc', {value:function() { return this.toLowerCase(); }});
|
Object.defineProperty(String.prototype, 'lc', {value:function() { return this.toLowerCase(); }});
|
||||||
|
|
||||||
/* ARRAY DEFS */
|
/* ARRAY DEFS */
|
||||||
Object.defineProperty(Array.prototype, 'aspect', {
|
|
||||||
value: function() {
|
|
||||||
return this.x/this.y;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(Array.prototype, 'copy', {
|
Object.defineProperty(Array.prototype, 'copy', {
|
||||||
value: function() {
|
value: function() {
|
||||||
var c = [];
|
var c = [];
|
||||||
|
@ -900,6 +837,18 @@ Object.defineProperty(Array.prototype, 'copy', {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(Array.prototype, 'forFrom', {
|
||||||
|
value: function(n, fn) {
|
||||||
|
for (var i = n; i < this.length; i++) fn(this[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(Array.prototype, 'forTo', {
|
||||||
|
value: function(n, fn) {
|
||||||
|
for (var i = 0; i < n; i++) fn(this[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Object.defineProperty(Array.prototype, 'dofilter', {
|
Object.defineProperty(Array.prototype, 'dofilter', {
|
||||||
value: function(fn) {
|
value: function(fn) {
|
||||||
for (let i = 0; i < this.length; i++) {
|
for (let i = 0; i < this.length; i++) {
|
||||||
|
@ -1026,13 +975,6 @@ swizz.forEach(function(x) {
|
||||||
};
|
};
|
||||||
make_swizz();
|
make_swizz();
|
||||||
|
|
||||||
Object.defineProperty(Array.prototype, 'add', {
|
|
||||||
value: function(b) {
|
|
||||||
var c = [];
|
|
||||||
for (var i = 0; i < this.length; i++) { c[i] = this[i] + b[i]; }
|
|
||||||
return c;
|
|
||||||
}});
|
|
||||||
|
|
||||||
Object.defineProperty(Array.prototype, 'normalized', {
|
Object.defineProperty(Array.prototype, 'normalized', {
|
||||||
value: function() {
|
value: function() {
|
||||||
var c = this.slice();
|
var c = this.slice();
|
||||||
|
@ -1067,13 +1009,6 @@ Object.defineProperty(Array.prototype, 'doubleup', {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.defineProperty(Array.prototype, 'sub', {
|
|
||||||
value: function(b) {
|
|
||||||
var c = [];
|
|
||||||
for (var i = 0; i < this.length; i++) { c[i] = this[i] - b[i]; }
|
|
||||||
return c;
|
|
||||||
}});
|
|
||||||
|
|
||||||
Object.defineProperty(Array.prototype, 'mult', {
|
Object.defineProperty(Array.prototype, 'mult', {
|
||||||
value: function(arr) {
|
value: function(arr) {
|
||||||
var c = [];
|
var c = [];
|
||||||
|
@ -1087,16 +1022,6 @@ Object.defineProperty(Array.prototype, 'apply', {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.defineProperty(Array.prototype, 'scale', {
|
|
||||||
value: function(s) {
|
|
||||||
if (Array.isArray(s)) {
|
|
||||||
var c = this.slice();
|
|
||||||
c.forEach(function(x,i) { c[i] = x * s[i]; });
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
return this.map(function(x) { return x*s; });
|
|
||||||
}});
|
|
||||||
|
|
||||||
Object.defineProperty(Array.prototype, 'sorted', {
|
Object.defineProperty(Array.prototype, 'sorted', {
|
||||||
value: function() {
|
value: function() {
|
||||||
return this.toSorted();
|
return this.toSorted();
|
||||||
|
@ -1131,7 +1056,6 @@ Object.defineProperty(Array.prototype, 'mapvec', {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
Object.defineProperty(Array.prototype, 'remove', {
|
Object.defineProperty(Array.prototype, 'remove', {
|
||||||
value: function(b) {
|
value: function(b) {
|
||||||
var idx = this.indexOf(b);
|
var idx = this.indexOf(b);
|
||||||
|
@ -1268,19 +1192,23 @@ Object.defineProperty(Array.prototype, 'mirrored', {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.defineProperty(Array.prototype, 'lerp', {
|
Math.lerp = vector.lerp;
|
||||||
value: function(to, t) {
|
Math.gcd = vector.gcd;
|
||||||
var c = [];
|
Math.lcm = vector.lcm;
|
||||||
this.forEach(function(x,i) {
|
Math.sum = vector.sum;
|
||||||
c[i] = (to[i] - x) * t + x;
|
Math.mean = vector.mean;
|
||||||
});
|
Math.sigma = vector.sigma;
|
||||||
return c;
|
Math.median = vector.median;
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Math.lerp = function(s,f,t) { return (f-s)*t + s; };
|
Math.variance = function(series) {
|
||||||
Math.gcd = function(a,b) { return b === 0 ? a : gcd(b,a%b); }
|
var mean = Math.mean(series);
|
||||||
Math.lcm = function(a,b) { return (a*b)/gcd(a,b); }
|
var vnce = 0;
|
||||||
|
for (var i = 0; i < series.length; i++)
|
||||||
|
vnce += Math.pow(series[i]-mean, 2);
|
||||||
|
return vnce/(series.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Math.ci = function(series) { return 3*Math.sigma(series)/Math.sqrt(series.length); }
|
||||||
|
|
||||||
Math.grab_from_points = function(pos, points, slop) {
|
Math.grab_from_points = function(pos, points, slop) {
|
||||||
var shortest = slop;
|
var shortest = slop;
|
||||||
|
@ -1324,22 +1252,18 @@ Object.defineProperty(Object.prototype, 'lerp',{
|
||||||
return obj;
|
return obj;
|
||||||
}});
|
}});
|
||||||
|
|
||||||
/* MATH EXTENSioNS */
|
/* MATH EXTENSIONS */
|
||||||
Object.defineProperty(Number.prototype, 'lerp', {
|
Object.defineProperty(Number.prototype, 'lerp', {
|
||||||
value: function(to, t) {
|
value: function(to, t) { return Math.lerp(this, to, t); }
|
||||||
var s = this;
|
|
||||||
return (to - this) * t + this;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.defineProperty(Number.prototype, 'clamp', {
|
Object.defineProperty(Number.prototype, 'clamp', {
|
||||||
value: function(from,to) {
|
value: function(from,to) { return Math.clamp(this,from,to); }
|
||||||
return Math.clamp(this,from,to);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Math.clamp = function (x, l, h) { return x > h ? h : x < l ? l : x; }
|
Math.clamp = vector.clamp;
|
||||||
|
|
||||||
Math.random_range = function(min,max) { return Math.random() * (max-min) + min; };
|
Math.random_range = vector.random_range;
|
||||||
Math.rand_int = function(max) { return Math.floor(Math.random()*max); };
|
Math.rand_int = function(max) { return Math.floor(Math.random()*max); };
|
||||||
|
|
||||||
Math.snap = function(val, grid) {
|
Math.snap = function(val, grid) {
|
||||||
|
@ -1351,32 +1275,17 @@ Math.snap = function(val, grid) {
|
||||||
return d+i;
|
return d+i;
|
||||||
}
|
}
|
||||||
|
|
||||||
Math.angledist = function (a1, a2) {
|
Math.angledist = vector.angledist;
|
||||||
a1 = a1%1;
|
|
||||||
a2 = a2%1;
|
|
||||||
var dist = a2 - a1;
|
|
||||||
if (dist == 0) return dist;
|
|
||||||
|
|
||||||
if (dist > 0) {
|
|
||||||
if (dist > 0.5) return dist-1;
|
|
||||||
return dist;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dist < -0.5) return dist+1;
|
|
||||||
|
|
||||||
return dist;
|
|
||||||
};
|
|
||||||
Math.angledist.doc = "Find the shortest angle between two angles.";
|
Math.angledist.doc = "Find the shortest angle between two angles.";
|
||||||
Math.TAU = Math.PI*2;
|
Math.TAU = Math.PI*2;
|
||||||
Math.deg2rad = function(deg) { return deg * 0.0174533; };
|
Math.deg2rad = function(deg) { return deg * 0.0174533; };
|
||||||
Math.rad2deg = function(rad) { return rad / 0.0174533; };
|
Math.rad2deg = function(rad) { return rad / 0.0174533; };
|
||||||
Math.deg2rad = function(x) { return x; };
|
|
||||||
Math.rad2deg = function(x) { return x; };
|
|
||||||
Math.turn2rad = function(x) { return x*Math.TAU; };
|
Math.turn2rad = function(x) { return x*Math.TAU; };
|
||||||
Math.rad2turn = function(x) { return x/Math.TAU; };
|
Math.rad2turn = function(x) { return x/Math.TAU; };
|
||||||
Math.turn2deg = function(x) { return x*360; };
|
Math.turn2deg = function(x) { return x*360; };
|
||||||
Math.deg2turn = function(x) { return x/360; };
|
Math.deg2turn = function(x) { return x/360; };
|
||||||
Math.randomint = function(max) { return Math.clamp(Math.floor(Math.random() * max), 0, max-1); };
|
Math.randomint = function(max) { return Math.clamp(Math.floor(Math.random() * max), 0, max-1); };
|
||||||
|
Math.variate = vector.variate;
|
||||||
|
|
||||||
/* BOUNDINGBOXES */
|
/* BOUNDINGBOXES */
|
||||||
var bbox = {};
|
var bbox = {};
|
||||||
|
@ -1509,39 +1418,18 @@ bbox.fromobjs = function(objs)
|
||||||
|
|
||||||
/* VECTORS */
|
/* VECTORS */
|
||||||
var Vector = {};
|
var Vector = {};
|
||||||
Vector.length = function(v) {
|
Vector.length = function(v) { return Math.hypot(...v); }
|
||||||
var sum = v.reduce(function(acc, val) { return acc + val**2; }, 0);
|
|
||||||
return Math.sqrt(sum);
|
Vector.norm = vector.norm;
|
||||||
}
|
Vector.project = vector.project;
|
||||||
Vector.norm = function(v) {
|
Vector.dot = vector.dot;
|
||||||
var len = Vector.length(v);
|
|
||||||
if (!len) return [0,0];
|
|
||||||
return [v.x/len, v.y/len];
|
|
||||||
}
|
|
||||||
Vector.project = function(a, b) { return vector.project(a,b); }
|
|
||||||
Vector.dot = function(a, b) { return vector.dot(a,b); },
|
|
||||||
Vector.random = function() {
|
Vector.random = function() {
|
||||||
var vec = [Math.random()-0.5, Math.random()-0.5];
|
var vec = [Math.random()-0.5, Math.random()-0.5];
|
||||||
return Vector.norm(vec);
|
return Vector.norm(vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector.angle_between = function(a,b)
|
Vector.angle_between = vector.angle_between;
|
||||||
{
|
Vector.rotate = vector.rotate;
|
||||||
var dot = Vector.dot(a,b);
|
|
||||||
var am = Vector.length(a);
|
|
||||||
var bm = Vector.length(b);
|
|
||||||
var cos_a = dot / (am*bm);
|
|
||||||
var angle = Math.acos(cos_a);
|
|
||||||
return Math.rad2turn(angle);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector.angle = function(v) { return Math.rad2turn(Math.atan2(v.y, v.x)); }
|
|
||||||
Vector.rotate = function(v,angle) {
|
|
||||||
var r = Vector.length(v);
|
|
||||||
angle += Vector.angle(v);
|
|
||||||
angle = Math.turn2rad(angle);
|
|
||||||
return [r*Math.cos(angle), r*Math.sin(angle)];
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector.equal = function(v1, v2, tol) {
|
Vector.equal = function(v1, v2, tol) {
|
||||||
if (!tol)
|
if (!tol)
|
||||||
|
@ -1652,7 +1540,6 @@ Math.sign = function(n) { return n >= 0 ? 1 : -1; }
|
||||||
return {
|
return {
|
||||||
convert,
|
convert,
|
||||||
time,
|
time,
|
||||||
json,
|
|
||||||
Vector,
|
Vector,
|
||||||
bbox,
|
bbox,
|
||||||
yaml
|
yaml
|
||||||
|
|
|
@ -15,6 +15,21 @@ var make_point_obj = function(o, p)
|
||||||
|
|
||||||
var fullrect = [0,0,1,1];
|
var fullrect = [0,0,1,1];
|
||||||
|
|
||||||
|
var sprite_addbucket = function(sprite)
|
||||||
|
{
|
||||||
|
var layer = sprite.gameobject.drawlayer;
|
||||||
|
sprite_buckets[layer] ??= {};
|
||||||
|
sprite_buckets[layer][sprite.path] ??= {};
|
||||||
|
sprite_buckets[layer][sprite.path][sprite.guid] = sprite;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sprite_rmbucket = function(sprite)
|
||||||
|
{
|
||||||
|
for (var layer of Object.values(sprite_buckets))
|
||||||
|
for (var path of Object.values(layer))
|
||||||
|
delete path[sprite.guid];
|
||||||
|
}
|
||||||
|
|
||||||
var sprite = {
|
var sprite = {
|
||||||
loop: true,
|
loop: true,
|
||||||
rect: fullrect,
|
rect: fullrect,
|
||||||
|
@ -41,6 +56,7 @@ var sprite = {
|
||||||
//self.path = playing.path;
|
//self.path = playing.path;
|
||||||
self.frame = playing.frames[f].rect;
|
self.frame = playing.frames[f].rect;
|
||||||
self.rect = [self.frame.x, self.frame.y, self.frame.w, self.frame.h];
|
self.rect = [self.frame.x, self.frame.y, self.frame.w, self.frame.h];
|
||||||
|
self.update_dimensions();
|
||||||
f = (f+1)%playing.frames.length;
|
f = (f+1)%playing.frames.length;
|
||||||
if (f === 0) {
|
if (f === 0) {
|
||||||
self.anim_done?.();
|
self.anim_done?.();
|
||||||
|
@ -62,6 +78,7 @@ var sprite = {
|
||||||
}
|
}
|
||||||
if (p === this.path) return;
|
if (p === this.path) return;
|
||||||
this._p = p;
|
this._p = p;
|
||||||
|
|
||||||
this.del_anim?.();
|
this.del_anim?.();
|
||||||
this.texture = game.texture(p);
|
this.texture = game.texture(p);
|
||||||
|
|
||||||
|
@ -69,17 +86,20 @@ var sprite = {
|
||||||
this.rect = fullrect;
|
this.rect = fullrect;
|
||||||
|
|
||||||
var anim = SpriteAnim.make(p);
|
var anim = SpriteAnim.make(p);
|
||||||
|
this.update_dimensions();
|
||||||
|
this.sync();
|
||||||
|
|
||||||
if (!anim) return;
|
if (!anim) return;
|
||||||
this.anim = anim;
|
this.anim = anim;
|
||||||
this.play();
|
this.play();
|
||||||
|
|
||||||
this.pos = this.dimensions().scale(this.anchor);
|
this.pos = this.dimensions().scale(this.anchor);
|
||||||
|
|
||||||
},
|
},
|
||||||
get path() {
|
get path() {
|
||||||
return this._p;
|
return this._p;
|
||||||
},
|
},
|
||||||
kill() {
|
kill() {
|
||||||
|
sprite_rmbucket(this);
|
||||||
this.del_anim?.();
|
this.del_anim?.();
|
||||||
this.anim = undefined;
|
this.anim = undefined;
|
||||||
this.gameobject = undefined;
|
this.gameobject = undefined;
|
||||||
|
@ -92,7 +112,10 @@ var sprite = {
|
||||||
this.pos = this.pos.scale(x);
|
this.pos = this.pos.scale(x);
|
||||||
},
|
},
|
||||||
anchor:[0,0],
|
anchor:[0,0],
|
||||||
sync() { },
|
sync() {
|
||||||
|
sprite_rmbucket(this);
|
||||||
|
sprite_addbucket(this);
|
||||||
|
},
|
||||||
pick() { return this; },
|
pick() { return this; },
|
||||||
boundingbox() {
|
boundingbox() {
|
||||||
var dim = this.dimensions();
|
var dim = this.dimensions();
|
||||||
|
@ -101,16 +124,21 @@ var sprite = {
|
||||||
return bbox.fromcwh(realpos,dim);
|
return bbox.fromcwh(realpos,dim);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
update_dimensions() {
|
||||||
|
this._dimensions = [this.texture.width*this.rect[2], this.texture.height*this.rect[3]];
|
||||||
|
component.sprite_dim_hook?.(this);
|
||||||
|
},
|
||||||
|
|
||||||
dimensions() {
|
dimensions() {
|
||||||
var dim = [this.texture.width, this.texture.height];
|
return this._dimensions;
|
||||||
dim.x *= this.frame.w;
|
|
||||||
dim.y *= this.frame.h;
|
|
||||||
return dim;
|
|
||||||
},
|
},
|
||||||
width() { return this.dimensions().x; },
|
width() { return this.dimensions().x; },
|
||||||
height() { return this.dimensions().y; },
|
height() { return this.dimensions().y; },
|
||||||
};
|
};
|
||||||
globalThis.allsprites = {};
|
globalThis.allsprites = {};
|
||||||
|
var sprite_buckets = {};
|
||||||
|
|
||||||
|
component.sprite_buckets = function() { return sprite_buckets; }
|
||||||
|
|
||||||
sprite.doc = {
|
sprite.doc = {
|
||||||
path: "Path to the texture.",
|
path: "Path to the texture.",
|
||||||
|
@ -149,10 +177,14 @@ sprite.inputs.kp1 = function() { this.setanchor("ul"); }
|
||||||
component.sprite = function(obj) {
|
component.sprite = function(obj) {
|
||||||
var sp = Object.create(sprite);
|
var sp = Object.create(sprite);
|
||||||
sp.gameobject = obj;
|
sp.gameobject = obj;
|
||||||
|
sp.transform = obj.transform;
|
||||||
sp.guid = prosperon.guid();
|
sp.guid = prosperon.guid();
|
||||||
allsprites[sp.guid] = sp;
|
allsprites[sp.guid] = sp;
|
||||||
|
if (component.sprite.make_hook) component.sprite.make_hook(sp);
|
||||||
|
sprite_addbucket(sp);
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprite.shade = [1,1,1,1];
|
sprite.shade = [1,1,1,1];
|
||||||
|
|
||||||
Object.mixin(os.make_seg2d(), {
|
Object.mixin(os.make_seg2d(), {
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
var debug = {};
|
|
||||||
|
|
||||||
debug.build = function(fn) { fn(); }
|
debug.build = function(fn) { fn(); }
|
||||||
|
|
||||||
debug.fn_break = function(fn,obj = globalThis) {
|
debug.fn_break = function(fn,obj = globalThis) {
|
||||||
|
@ -50,7 +48,7 @@ debug.draw = function() {
|
||||||
"EDIT", [0, 0], 1);
|
"EDIT", [0, 0], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function assert(op, str = `assertion failed [value '${op}']`)
|
var assert = function(op, str = `assertion failed [value '${op}']`)
|
||||||
{
|
{
|
||||||
if (!op)
|
if (!op)
|
||||||
console.panic(str);
|
console.panic(str);
|
||||||
|
@ -64,21 +62,6 @@ var Gizmos = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
profile.cpu = function(fn, times = 1, q = "unnamed") {
|
|
||||||
var start = profile.now();
|
|
||||||
for (var i = 0; i < times; i++)
|
|
||||||
fn();
|
|
||||||
|
|
||||||
var elapsed = profile.now() - start;
|
|
||||||
var avgt = profile.best_t(elapsed/times);
|
|
||||||
var totalt = profile.best_t(elapsed);
|
|
||||||
|
|
||||||
say(`profile [${q}]: ${profile.best_t(avgt)} average [${profile.best_t(totalt)} for ${times} loops]`);
|
|
||||||
}
|
|
||||||
|
|
||||||
profile.ms = function(t) { return t/1000000; }
|
|
||||||
profile.secs = function(t) { return t/1000000000; }
|
|
||||||
|
|
||||||
/* These controls are available during editing, and during play of debug builds */
|
/* These controls are available during editing, and during play of debug builds */
|
||||||
debug.inputs = {};
|
debug.inputs = {};
|
||||||
debug.inputs.f1 = function () { debug.draw_phys = !debug.draw_phys; };
|
debug.inputs.f1 = function () { debug.draw_phys = !debug.draw_phys; };
|
||||||
|
@ -226,23 +209,6 @@ debug.api.print_doc = function(name)
|
||||||
return mdoc;
|
return mdoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.log = {};
|
|
||||||
|
|
||||||
debug.log.time = function(fn, name, avg=0)
|
|
||||||
{
|
|
||||||
debug.log.time[name] ??= [];
|
|
||||||
var start = profile.now();
|
|
||||||
fn();
|
|
||||||
debug.log.time[name].push(profile.now()-start);
|
|
||||||
}
|
|
||||||
|
|
||||||
debug.kill = function()
|
|
||||||
{
|
|
||||||
assert = function() {};
|
|
||||||
debug.build = function() {};
|
|
||||||
debug.fn_break = function() {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
debug,
|
debug,
|
||||||
Gizmos,
|
Gizmos,
|
||||||
|
|
|
@ -569,7 +569,7 @@ var editor = {
|
||||||
obj.ur = sub;
|
obj.ur = sub;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if (!sub.startswith(obj.ur)) {
|
} else if (!sub.startsWith(obj.ur)) {
|
||||||
console.warn(`Cannot make an ur of type ${sub} from an object with the ur ${obj.ur}`);
|
console.warn(`Cannot make an ur of type ${sub} from an object with the ur ${obj.ur}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1433,7 +1433,7 @@ replpanel.inputs.tab = function() {
|
||||||
var stub = this.value.fromlast('.');
|
var stub = this.value.fromlast('.');
|
||||||
var replobj = (editor.selectlist.length === 1) ? "editor.selectlist[0]" : "editor.edit_level";
|
var replobj = (editor.selectlist.length === 1) ? "editor.selectlist[0]" : "editor.edit_level";
|
||||||
|
|
||||||
if (this.value.startswith("this."))
|
if (this.value.startsWith("this."))
|
||||||
keyobj = keyobj.replace("this", replobj);
|
keyobj = keyobj.replace("this", replobj);
|
||||||
|
|
||||||
if (!this.value.includes('.')) keys.push("this");
|
if (!this.value.includes('.')) keys.push("this");
|
||||||
|
@ -1461,7 +1461,7 @@ replpanel.inputs.tab = function() {
|
||||||
|
|
||||||
if (stub)
|
if (stub)
|
||||||
this.value = o + '.' + comp;
|
this.value = o + '.' + comp;
|
||||||
else if (this.value.endswith('.'))
|
else if (this.value.endsWith('.'))
|
||||||
this.value = o + '.' + comp;
|
this.value = o + '.' + comp;
|
||||||
else
|
else
|
||||||
this.value = comp;
|
this.value = comp;
|
||||||
|
@ -1677,7 +1677,7 @@ var openlevelpanel = Object.copy(inputpanel, {
|
||||||
|
|
||||||
keycb() {
|
keycb() {
|
||||||
if(this.value)
|
if(this.value)
|
||||||
this.assets = this.allassets.filter(x => x.startswith(this.value));
|
this.assets = this.allassets.filter(x => x.startsWith(this.value));
|
||||||
else
|
else
|
||||||
this.assets = this.allassets.slice();
|
this.assets = this.allassets.slice();
|
||||||
for (var m in this.mumlist)
|
for (var m in this.mumlist)
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
"use math";
|
"use math";
|
||||||
|
|
||||||
|
Object.defineProperty(String.prototype, 'rm', {
|
||||||
|
value: function(index, endidx = index+1) { return this.slice(0,index) + this.slice(endidx); }
|
||||||
|
});
|
||||||
|
|
||||||
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);
|
||||||
|
@ -25,7 +29,26 @@ Object.defineProperty(String.prototype, "folder", {
|
||||||
|
|
||||||
globalThis.Resources = {};
|
globalThis.Resources = {};
|
||||||
|
|
||||||
Resources.replpath = function (str, path) {
|
Resources.rm_fn = function rm_fn(fn, text)
|
||||||
|
{
|
||||||
|
var reg = new RegExp(fn.source + "\\s*\\(");
|
||||||
|
var match;
|
||||||
|
while (match = text.match(reg)) {
|
||||||
|
var last = match.index+match[0].length;
|
||||||
|
var par = 1;
|
||||||
|
while (par !== 0) {
|
||||||
|
if (text[last] === '(') par++;
|
||||||
|
if (text[last] === ')') par--;
|
||||||
|
last++;
|
||||||
|
}
|
||||||
|
text = text.rm(match.index, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
Resources.rm_fn.doc = "Remove calls to a given function from a given text script.";
|
||||||
|
|
||||||
|
Resources.replpath = function replpath(str, path) {
|
||||||
if (!str) return str;
|
if (!str) return str;
|
||||||
if (str[0] === "/") return str.rm(0);
|
if (str[0] === "/") return str.rm(0);
|
||||||
|
|
||||||
|
@ -43,12 +66,24 @@ Resources.replpath = function (str, path) {
|
||||||
return str;
|
return str;
|
||||||
};
|
};
|
||||||
|
|
||||||
Resources.replstrs = function (path) {
|
Resources.replstrs = function replstrs(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();
|
||||||
|
|
||||||
|
// remove console statements
|
||||||
|
if (!console.enabled)
|
||||||
|
script = Resources.rm_fn(/console\.(spam|info|warn|error)/, script);
|
||||||
|
|
||||||
|
if (!profile.enabled)
|
||||||
|
script = Resources.rm_fn(/profile\.(cache|frame|endcache|endframe)/, script);
|
||||||
|
|
||||||
|
if (!debug.enabled) {
|
||||||
|
script = Resources.rm_fn(/assert/, script);
|
||||||
|
script = Resources.rm_fn(/debug\.(build|fn_break)/, script);
|
||||||
|
}
|
||||||
|
|
||||||
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}"`;
|
||||||
|
@ -110,38 +145,6 @@ Resources.find_script = function (file) {
|
||||||
return find_ext(file, Resources.scripts);
|
return find_ext(file, Resources.scripts);
|
||||||
};
|
};
|
||||||
|
|
||||||
profile.best_t = function (t) {
|
|
||||||
var qq = "ns";
|
|
||||||
if (t > 1000) {
|
|
||||||
t /= 1000;
|
|
||||||
qq = "us";
|
|
||||||
if (t > 1000) {
|
|
||||||
t /= 1000;
|
|
||||||
qq = "ms";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return `${t.toPrecision(4)} ${qq}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
profile.report = function (start, msg = "[undefined report]") {
|
|
||||||
console.info(`${msg} in ${profile.best_t(profile.now() - start)}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
profile.addreport = function (cache, line, start) {
|
|
||||||
cache ??= profcache;
|
|
||||||
cache[line] ??= [];
|
|
||||||
cache[line].push(profile.now() - start);
|
|
||||||
return profile.now();
|
|
||||||
};
|
|
||||||
|
|
||||||
profile.printreport = function (cache, name) {
|
|
||||||
var report = name + "\n";
|
|
||||||
for (var i in cache)
|
|
||||||
report += `${i} ${profile.best_t(cache[i].reduce((a, b) => a + b) / cache[i].length)}\n`;
|
|
||||||
|
|
||||||
return report;
|
|
||||||
};
|
|
||||||
|
|
||||||
console.transcript = "";
|
console.transcript = "";
|
||||||
console.say = function (msg) {
|
console.say = function (msg) {
|
||||||
msg += "\n";
|
msg += "\n";
|
||||||
|
@ -218,425 +221,71 @@ console.doc = {
|
||||||
|
|
||||||
globalThis.global = globalThis;
|
globalThis.global = globalThis;
|
||||||
|
|
||||||
var profcache = {};
|
var use_cache = {};
|
||||||
|
|
||||||
function use(file, env = {}, script) {
|
globalThis.use = function use(file, env = {}, script) {
|
||||||
file = Resources.find_script(file);
|
file = Resources.find_script(file);
|
||||||
var st = profile.now();
|
profile.cache("USE", file);
|
||||||
|
|
||||||
profcache[file] ??= [];
|
if (use_cache[file]) {
|
||||||
|
var ret = use_cache[file].call(env);
|
||||||
if (use.cache[file]) {
|
|
||||||
var ret = use.cache[file].call(env);
|
|
||||||
profile.addreport(profcache, file, st);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
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.endcache();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
use.cache = {};
|
function stripped_use (file, env = {}, script) {
|
||||||
|
file = Resources.find_script(file);
|
||||||
|
|
||||||
global.check_registers = function (obj) {
|
if (use_cache[file]) {
|
||||||
for (var reg in Register.registries)
|
var ret = use_cache[file].call(env);
|
||||||
if (typeof obj[reg] === 'function')
|
return;
|
||||||
obj.timers.push(Register.registries[reg].register(obj[reg].bind(obj)));
|
|
||||||
for (var k in obj) {
|
|
||||||
if (!k.startswith("on_")) continue;
|
|
||||||
var signal = k.fromfirst("on_");
|
|
||||||
Event.observe(signal, obj, obj[k]);
|
|
||||||
}
|
}
|
||||||
};
|
script ??= Resources.replstrs(file);
|
||||||
|
|
||||||
Object.assign(global, use("scripts/base"));
|
script = `(function() { var self = this; ${script}; })`;
|
||||||
global.obscure("global");
|
var fn = os.eval(file, script);
|
||||||
global.mixin("scripts/render");
|
var ret = fn.call(env);
|
||||||
global.mixin("scripts/debug");
|
profile.endcache();
|
||||||
|
|
||||||
var frame_t = profile.secs(profile.now());
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
var sim = {};
|
function bare_use(file)
|
||||||
sim.mode = "play";
|
|
||||||
sim.play = function () {
|
|
||||||
this.mode = "play";
|
|
||||||
os.reindex_static();
|
|
||||||
};
|
|
||||||
sim.playing = function () {
|
|
||||||
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 gggstart = game.engine_start;
|
|
||||||
game.engine_start = function (s) {
|
|
||||||
game.startengine = 1;
|
|
||||||
gggstart(
|
|
||||||
function () {
|
|
||||||
global.mixin("scripts/sound.js");
|
|
||||||
world_start();
|
|
||||||
window.set_icon(os.make_texture("icons/moon.gif"));
|
|
||||||
Object.readonly(window.__proto__, "vsync");
|
|
||||||
Object.readonly(window.__proto__, "enable_dragndrop");
|
|
||||||
Object.readonly(window.__proto__, "enable_clipboard");
|
|
||||||
Object.readonly(window.__proto__, "high_dpi");
|
|
||||||
Object.readonly(window.__proto__, "sample_count");
|
|
||||||
s();
|
|
||||||
|
|
||||||
shape.quad = {
|
|
||||||
pos: os.make_buffer([0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0], 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 = {
|
|
||||||
pos: os.make_buffer([0, 0, 0, 0.5, 1, 0, 1, 0, 0], 0),
|
|
||||||
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();
|
|
||||||
},
|
|
||||||
process,
|
|
||||||
window.size.x,
|
|
||||||
window.size.y,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
game.startengine = 0;
|
|
||||||
var frames = [];
|
|
||||||
|
|
||||||
prosperon.release_mode = function()
|
|
||||||
{
|
{
|
||||||
prosperon.debug = false;
|
var script = io.slurp(file);
|
||||||
mum.debug = false;
|
if (!script) return;
|
||||||
debug.kill();
|
script = `(function() { var self = this; ${script}; })`;
|
||||||
}
|
Object.assign(globalThis, os.eval(file, script).call(globalThis));
|
||||||
prosperon.debug = true;
|
|
||||||
|
|
||||||
function process() {
|
|
||||||
var startframe = profile.now();
|
|
||||||
var dt = profile.secs(profile.now()) - frame_t;
|
|
||||||
frame_t = profile.secs(profile.now());
|
|
||||||
|
|
||||||
prosperon.appupdate(dt);
|
|
||||||
input.procdown();
|
|
||||||
|
|
||||||
if (sim.mode === "play" || sim.mode === "step") {
|
|
||||||
prosperon.update(dt * game.timescale);
|
|
||||||
if (sim.mode === "step") sim.pause();
|
|
||||||
|
|
||||||
physlag += dt;
|
|
||||||
|
|
||||||
while (physlag > physics.delta) {
|
|
||||||
physlag -= physics.delta;
|
|
||||||
var st = profile.now();
|
|
||||||
prosperon.phys2d_step(physics.delta * game.timescale);
|
|
||||||
prosperon.physupdate(physics.delta * game.timescale);
|
|
||||||
profile.addreport(profcache, "physics step", st);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var st = profile.now();
|
|
||||||
prosperon.window_render(window.size);
|
|
||||||
prosperon.render();
|
|
||||||
profile.addreport(profcache, "render frame", st);
|
|
||||||
frames.push(profile.secs(profile.now() - startframe));
|
|
||||||
if (frames.length > 20) frames.shift();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
globalThis.fps = function () {
|
globalThis.debug = {};
|
||||||
var sum = 0;
|
|
||||||
for (var i = 0; i < frames.length; i++) sum += frames[i];
|
|
||||||
return frames.length / sum;
|
|
||||||
};
|
|
||||||
|
|
||||||
game.timescale = 1;
|
profile.enabled = true;
|
||||||
|
console.enabled = true;
|
||||||
|
debug.enabled = true;
|
||||||
|
|
||||||
var eachobj = function (obj, fn) {
|
bare_use("scripts/base.js");
|
||||||
var val = fn(obj);
|
bare_use("scripts/profile.js");
|
||||||
if (val) return val;
|
|
||||||
for (var o in obj.objects) {
|
|
||||||
if (obj.objects[o] === obj)
|
|
||||||
console.error(`Object ${obj.toString()} is referenced by itself.`);
|
|
||||||
val = eachobj(obj.objects[o], fn);
|
|
||||||
if (val) return val;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
game.all_objects = function (fn, startobj = world) {
|
prosperon.release = function()
|
||||||
return eachobj(startobj, fn);
|
{
|
||||||
};
|
profile.enabled = false;
|
||||||
game.find_object = function (fn, startobj = world) {};
|
console.enabled = false;
|
||||||
|
debug.enabled = false;
|
||||||
game.tags = {};
|
|
||||||
game.tag_add = function (tag, obj) {
|
|
||||||
game.tags[tag] ??= {};
|
|
||||||
game.tags[tag][obj.guid] = obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
game.tag_rm = function (tag, obj) {
|
|
||||||
delete game.tags[tag][obj.guid];
|
|
||||||
};
|
|
||||||
|
|
||||||
game.tag_clear_guid = function (guid) {
|
|
||||||
for (var tag in game.tags) delete game.tags[tag][guid];
|
|
||||||
};
|
|
||||||
|
|
||||||
game.objects_with_tag = function (tag) {
|
|
||||||
if (!game.tags[tag]) return [];
|
|
||||||
return Object.values(game.tags[tag]);
|
|
||||||
};
|
|
||||||
|
|
||||||
game.doc = {};
|
|
||||||
game.doc.object = "Returns the entity belonging to a given id.";
|
|
||||||
game.doc.pause = "Pause game simulation.";
|
|
||||||
game.doc.play = "Resume or start game simulation.";
|
|
||||||
game.doc.camera = "Current camera.";
|
|
||||||
|
|
||||||
game.texture = function (path, force = false) {
|
|
||||||
if (force && game.texture.cache[path]) return game.texture.cache[path];
|
|
||||||
|
|
||||||
if (!io.exists(path)) {
|
|
||||||
console.warn(`Missing texture: ${path}`);
|
|
||||||
game.texture.cache[path] = game.texture("icons/no_tex.gif");
|
|
||||||
} else game.texture.cache[path] ??= os.make_texture(path);
|
|
||||||
|
|
||||||
return game.texture.cache[path];
|
|
||||||
};
|
|
||||||
game.texture.cache = {};
|
|
||||||
|
|
||||||
prosperon.semver = {};
|
|
||||||
prosperon.semver.valid = function (v, range) {
|
|
||||||
v = v.split(".");
|
|
||||||
range = range.split(".");
|
|
||||||
if (v.length !== 3) return undefined;
|
|
||||||
if (range.length !== 3) return undefined;
|
|
||||||
|
|
||||||
if (range[0][0] === "^") {
|
|
||||||
range[0] = range[0].slice(1);
|
|
||||||
if (parseInt(v[0]) >= parseInt(range[0])) return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (range[0] === "~") {
|
bare_use("preconfig.js");
|
||||||
range[0] = range[0].slice(1);
|
|
||||||
for (var i = 0; i < 2; i++)
|
|
||||||
if (parseInt(v[i]) < parseInt(range[i])) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return prosperon.semver.cmp(v.join("."), range.join(".")) === 0;
|
if (!profile.enabled)
|
||||||
};
|
use = stripped_use;
|
||||||
|
|
||||||
prosperon.semver.cmp = function (v1, v2) {
|
Object.assign(globalThis, use("scripts/prosperon.js"));
|
||||||
var ver1 = v1.split(".");
|
|
||||||
var ver2 = v2.split(".");
|
|
||||||
|
|
||||||
for (var i = 0; i < 3; i++) {
|
|
||||||
var n1 = parseInt(ver1[i]);
|
|
||||||
var n2 = parseInt(ver2[i]);
|
|
||||||
if (n1 > n2) return 1;
|
|
||||||
else if (n1 < n2) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.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.
|
|
||||||
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 must match exactly, but any MINOR and PATCH greater or equal is valid.`;
|
|
||||||
|
|
||||||
prosperon.iconified = function (icon) {};
|
|
||||||
prosperon.focus = function (focus) {};
|
|
||||||
prosperon.resize = function (dimensions) {
|
|
||||||
window.size.x = dimensions.x;
|
|
||||||
window.size.y = dimensions.y;
|
|
||||||
};
|
|
||||||
prosperon.suspended = function (sus) {};
|
|
||||||
prosperon.mouseenter = function () {};
|
|
||||||
prosperon.mouseleave = function () {};
|
|
||||||
prosperon.touchpress = function (touches) {};
|
|
||||||
prosperon.touchrelease = function (touches) {};
|
|
||||||
prosperon.touchmove = function (touches) {};
|
|
||||||
prosperon.clipboardpaste = function (str) {};
|
|
||||||
prosperon.quit = function () {
|
|
||||||
say(profile.printreport(profcache, "USE REPORT"));
|
|
||||||
say(profile.printreport(entityreport, "ENTITY REPORT"));
|
|
||||||
|
|
||||||
console.info("QUITTING");
|
|
||||||
for (var i in debug.log.time)
|
|
||||||
say(debug.log.time[i].map((x) => profile.ms(x)));
|
|
||||||
};
|
|
||||||
|
|
||||||
window.size = [640, 480];
|
|
||||||
window.mode = "keep";
|
|
||||||
window.toggle_fullscreen = function() { window.fullscreen = !window.fullscreen; }
|
|
||||||
|
|
||||||
window.set_icon.doc = "Set the icon of the window using the PNG image at path.";
|
|
||||||
|
|
||||||
window.doc = {};
|
|
||||||
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.boundingbox = "Boundingbox of the window, with top and right being its height and width.";
|
|
||||||
|
|
||||||
global.mixin("scripts/input");
|
|
||||||
global.mixin("scripts/std");
|
|
||||||
global.mixin("scripts/diff");
|
|
||||||
global.mixin("scripts/color");
|
|
||||||
global.mixin("scripts/gui");
|
|
||||||
global.mixin("scripts/tween");
|
|
||||||
global.mixin("scripts/ai");
|
|
||||||
|
|
||||||
var timer = {
|
|
||||||
update(dt) {
|
|
||||||
this.remain -= dt;
|
|
||||||
if (this.remain <= 0) {
|
|
||||||
this.fn();
|
|
||||||
this.kill();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
kill() {
|
|
||||||
this.end();
|
|
||||||
delete this.fn;
|
|
||||||
},
|
|
||||||
|
|
||||||
delay(fn, secs) {
|
|
||||||
var t = Object.create(this);
|
|
||||||
t.time = secs;
|
|
||||||
t.remain = secs;
|
|
||||||
t.fn = fn;
|
|
||||||
t.end = Register.update.register(timer.update.bind(t));
|
|
||||||
var returnfn = timer.kill.bind(t);
|
|
||||||
returnfn.remain = secs;
|
|
||||||
return returnfn;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
global.mixin("scripts/physics");
|
|
||||||
global.mixin("scripts/geometry");
|
|
||||||
|
|
||||||
/*
|
|
||||||
Factory for creating registries. Register one with 'X.register',
|
|
||||||
which returns a function that, when invoked, cancels the registry.
|
|
||||||
*/
|
|
||||||
var Register = {
|
|
||||||
registries: [],
|
|
||||||
|
|
||||||
add_cb(name, e_event = false) {
|
|
||||||
var n = {};
|
|
||||||
var fns = [];
|
|
||||||
|
|
||||||
n.register = function (fn, obj) {
|
|
||||||
if (typeof fn !== "function") return;
|
|
||||||
if (typeof obj === "object") fn = fn.bind(obj);
|
|
||||||
fns.push(fn);
|
|
||||||
return function () {
|
|
||||||
fns.remove(fn);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
prosperon[name] = function (...args) {
|
|
||||||
fns.forEach((x) => x(...args));
|
|
||||||
};
|
|
||||||
prosperon[name].fns = fns;
|
|
||||||
n.clear = function () {
|
|
||||||
fns = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
Register[name] = n;
|
|
||||||
Register.registries[name] = n;
|
|
||||||
|
|
||||||
return n;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Register.add_cb("appupdate", true);
|
|
||||||
Register.add_cb("update", true).doc = "Called once per frame.";
|
|
||||||
Register.add_cb("physupdate", true);
|
|
||||||
Register.add_cb("gui", true);
|
|
||||||
Register.add_cb("hud", true);
|
|
||||||
Register.add_cb("draw_dbg", true);
|
|
||||||
Register.add_cb("gui_dbg", true);
|
|
||||||
Register.add_cb("hud_dbg", true);
|
|
||||||
Register.add_cb("draw", true);
|
|
||||||
|
|
||||||
var Event = {
|
|
||||||
events: {},
|
|
||||||
|
|
||||||
observe(name, obj, fn) {
|
|
||||||
this.events[name] ??= [];
|
|
||||||
this.events[name].push([obj, fn]);
|
|
||||||
},
|
|
||||||
|
|
||||||
unobserve(name, obj) {
|
|
||||||
this.events[name] = this.events[name].filter((x) => x[0] !== obj);
|
|
||||||
},
|
|
||||||
|
|
||||||
rm_obj(obj) {
|
|
||||||
Object.keys(this.events).forEach((name) => Event.unobserve(name, obj));
|
|
||||||
},
|
|
||||||
|
|
||||||
notify(name, ...args) {
|
|
||||||
if (!this.events[name]) return;
|
|
||||||
this.events[name].forEach(function (x) {
|
|
||||||
x[1].call(x[0], ...args);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
global.mixin("scripts/spline");
|
|
||||||
global.mixin("scripts/components");
|
|
||||||
global.mixin("scripts/actor");
|
|
||||||
global.mixin("scripts/entity");
|
|
||||||
|
|
||||||
function world_start() {
|
|
||||||
globalThis.world = Object.create(entity);
|
|
||||||
world.transform = os.make_transform();
|
|
||||||
world.objects = {};
|
|
||||||
world.toString = function () {
|
|
||||||
return "world";
|
|
||||||
};
|
|
||||||
world.ur = "world";
|
|
||||||
world.kill = function () {
|
|
||||||
this.clear();
|
|
||||||
};
|
|
||||||
world.phys = 2;
|
|
||||||
world.zoom = 1;
|
|
||||||
world._ed = { selectable: false };
|
|
||||||
world.ur = {};
|
|
||||||
world.ur.fresh = {};
|
|
||||||
game.cam = world;
|
|
||||||
}
|
|
||||||
|
|
||||||
global.mixin("scripts/physics");
|
|
||||||
global.mixin("scripts/widget");
|
|
||||||
global.mixin("scripts/mum");
|
|
||||||
|
|
||||||
window.title = `Prosperon v${prosperon.version}`;
|
|
||||||
window.size = [500, 500];
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
globalThis.entityreport = {};
|
globalThis.entityreport = {};
|
||||||
|
|
||||||
|
var timer_update = function(dt)
|
||||||
|
{
|
||||||
|
this.fn();
|
||||||
|
}
|
||||||
|
|
||||||
function obj_unique_name(name, obj) {
|
function obj_unique_name(name, obj) {
|
||||||
name = name.replaceAll('.', '_');
|
name = name.replaceAll('.', '_');
|
||||||
if (!(name in obj)) return name;
|
if (!(name in obj)) return name;
|
||||||
|
@ -24,6 +29,7 @@ function unique_name(list, name = "new_object") {
|
||||||
};
|
};
|
||||||
|
|
||||||
var entity = {
|
var entity = {
|
||||||
|
drawlayer: -1,
|
||||||
get_comp_by_name(name) {
|
get_comp_by_name(name) {
|
||||||
var comps = [];
|
var comps = [];
|
||||||
for (var c of Object.values(this.components))
|
for (var c of Object.values(this.components))
|
||||||
|
@ -37,7 +43,6 @@ var entity = {
|
||||||
this.body = os.make_body(this.transform);
|
this.body = os.make_body(this.transform);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
path_from(o) {
|
path_from(o) {
|
||||||
var p = this.toString();
|
var p = this.toString();
|
||||||
var c = this.master;
|
var c = this.master;
|
||||||
|
@ -61,14 +66,14 @@ var entity = {
|
||||||
},
|
},
|
||||||
|
|
||||||
sync() {
|
sync() {
|
||||||
this.components.forEach(function(x) { x.sync?.(); });
|
for (var c of Object.values(this.components)) c.sync?.();
|
||||||
this.objects.forEach(function(x) { x.sync(); });
|
for (var o of Object.values(this.objects)) o.sync();
|
||||||
},
|
},
|
||||||
|
|
||||||
delay(fn, seconds) {
|
delay(fn, seconds) {
|
||||||
var timers = this.timers;
|
var timers = this.timers;
|
||||||
var stop = function() {
|
var stop = function() {
|
||||||
timers.remove(stop);
|
delete timers[guid];
|
||||||
execute = undefined;
|
execute = undefined;
|
||||||
stop = undefined;
|
stop = undefined;
|
||||||
rm?.();
|
rm?.();
|
||||||
|
@ -86,12 +91,15 @@ var entity = {
|
||||||
stop.pct = function() { return 1 - (stop.remain/stop.seconds); };
|
stop.pct = function() { return 1 - (stop.remain/stop.seconds); };
|
||||||
|
|
||||||
function update(dt) {
|
function update(dt) {
|
||||||
|
profile.frame("timer");
|
||||||
stop.remain -= dt;
|
stop.remain -= dt;
|
||||||
if (stop.remain <= 0) execute();
|
if (stop.remain <= 0) execute();
|
||||||
|
profile.endframe();
|
||||||
}
|
}
|
||||||
|
|
||||||
var rm = Register.update.register(update);
|
var rm = Register.update.register(update);
|
||||||
timers.push(stop);
|
var guid = prosperon.guid();
|
||||||
|
timers[guid] = (stop);
|
||||||
return stop;
|
return stop;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -138,7 +146,7 @@ var entity = {
|
||||||
},
|
},
|
||||||
|
|
||||||
spawn(text, config, callback) {
|
spawn(text, config, callback) {
|
||||||
var st = profile.now();
|
|
||||||
var ent = Object.create(entity);
|
var ent = Object.create(entity);
|
||||||
ent.transform = os.make_transform();
|
ent.transform = os.make_transform();
|
||||||
|
|
||||||
|
@ -146,11 +154,11 @@ var entity = {
|
||||||
|
|
||||||
ent.components = {};
|
ent.components = {};
|
||||||
ent.objects = {};
|
ent.objects = {};
|
||||||
ent.timers = [];
|
ent.timers = {};
|
||||||
|
|
||||||
if (!text)
|
if (!text)
|
||||||
ent.ur = emptyur;
|
ent.ur = emptyur;
|
||||||
else if (typeof text === 'object' && text) {// assume it's an ur
|
else if (text instanceof Object) {// assume it's an ur
|
||||||
ent.ur = text;
|
ent.ur = text;
|
||||||
text = ent.ur.text;
|
text = ent.ur.text;
|
||||||
config = [ent.ur.data, config].filter(x => x).flat();
|
config = [ent.ur.data, config].filter(x => x).flat();
|
||||||
|
@ -164,19 +172,20 @@ var entity = {
|
||||||
if (typeof text === 'string')
|
if (typeof text === 'string')
|
||||||
use(text, ent);
|
use(text, ent);
|
||||||
else if (Array.isArray(text))
|
else if (Array.isArray(text))
|
||||||
text.forEach(path => use(path,ent));
|
for (var path of text) use(path,ent);
|
||||||
|
profile.cache("ENTITY TIME", ent.ur.name);
|
||||||
|
var st = profile.now();
|
||||||
if (typeof config === 'string')
|
if (typeof config === 'string')
|
||||||
Object.merge(ent, json.decode(Resources.replstrs(config)));
|
Object.merge(ent, json.decode(Resources.replstrs(config)));
|
||||||
else if (Array.isArray(config))
|
else if (Array.isArray(config))
|
||||||
config.forEach(function(path) {
|
for (var path of config) {
|
||||||
if (typeof path === 'string') {
|
if (typeof path === 'string') {
|
||||||
console.info(`ingesting ${path} ...`);
|
console.info(`ingesting ${path} ...`);
|
||||||
Object.merge(ent, json.decode(Resources.replstrs(path)));
|
Object.merge(ent, json.decode(Resources.replstrs(path)));
|
||||||
}
|
}
|
||||||
else if (typeof path === 'object')
|
else if (path instanceof Object)
|
||||||
Object.merge(ent,path);
|
Object.merge(ent,path);
|
||||||
});
|
};
|
||||||
|
|
||||||
ent.reparent(this);
|
ent.reparent(this);
|
||||||
|
|
||||||
|
@ -191,9 +200,9 @@ var entity = {
|
||||||
|
|
||||||
check_registers(ent);
|
check_registers(ent);
|
||||||
|
|
||||||
if (typeof ent.load === 'function') ent.load();
|
if (ent.load instanceof Function) ent.load();
|
||||||
if (sim.playing())
|
if (sim.playing())
|
||||||
if (typeof ent.start === 'function') ent.start();
|
if (ent.start instanceof Function) ent.start();
|
||||||
|
|
||||||
Object.hide(ent, 'ur', 'components', 'objects', 'timers', 'guid', 'master');
|
Object.hide(ent, 'ur', 'components', 'objects', 'timers', 'guid', 'master');
|
||||||
|
|
||||||
|
@ -230,13 +239,13 @@ var entity = {
|
||||||
for (var i in ent.objects)
|
for (var i in ent.objects)
|
||||||
ent.ur.fresh.objects[i] = ent.objects[i].instance_obj();
|
ent.ur.fresh.objects[i] = ent.objects[i].instance_obj();
|
||||||
|
|
||||||
profile.addreport(entityreport, ent.ur.name, st);
|
profile.endcache();
|
||||||
|
|
||||||
return ent;
|
return ent;
|
||||||
},
|
},
|
||||||
|
|
||||||
disable() { this.components.forEach(function(x) { x.disable(); }); },
|
disable() { for (var x of this.components) x.disable(); },
|
||||||
enable() { this.components.forEach(function(x) { x.enable(); }); },
|
enable() { for (var x of this.components) x.enable(); },
|
||||||
|
|
||||||
this2screen(pos) { return game.camera.world2view(this.this2world(pos)); },
|
this2screen(pos) { return game.camera.world2view(this.this2world(pos)); },
|
||||||
screen2this(pos) { return this.world2this(game.camera.view2world(pos)); },
|
screen2this(pos) { return this.world2this(game.camera.view2world(pos)); },
|
||||||
|
@ -280,7 +289,7 @@ var entity = {
|
||||||
|
|
||||||
var bb = boxes.shift();
|
var bb = boxes.shift();
|
||||||
|
|
||||||
boxes.forEach(function(x) { bb = bbox.expand(bb, x); });
|
for (var x of boxes) bb = bbox.expand(bb, x);
|
||||||
|
|
||||||
bb = bbox.move(bb, this.pos);
|
bb = bbox.move(bb, this.pos);
|
||||||
|
|
||||||
|
@ -338,8 +347,8 @@ dup(diff) {
|
||||||
this.__kill = true;
|
this.__kill = true;
|
||||||
console.spam(`Killing entity of type ${this.ur}`);
|
console.spam(`Killing entity of type ${this.ur}`);
|
||||||
|
|
||||||
this.timers.forEach(t => t());
|
this.timers.forEach(x => x());
|
||||||
this.timers = [];
|
delete this.timers;
|
||||||
Event.rm_obj(this);
|
Event.rm_obj(this);
|
||||||
input.do_uncontrol(this);
|
input.do_uncontrol(this);
|
||||||
|
|
||||||
|
@ -354,20 +363,19 @@ dup(diff) {
|
||||||
this.components[key].enabled = false;
|
this.components[key].enabled = false;
|
||||||
delete this.components[key];
|
delete this.components[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
delete this.components;
|
delete this.components;
|
||||||
|
|
||||||
this.clear();
|
this.clear();
|
||||||
if (typeof this.stop === 'function') this.stop();
|
if (this.stop instanceof Function) this.stop();
|
||||||
|
|
||||||
game.tag_clear_guid(this.guid);
|
game.tag_clear_guid(this.guid);
|
||||||
|
|
||||||
for (var i in this) {
|
for (var i in this) {
|
||||||
if (typeof this[i] === 'object') delete this[i];
|
if (this[i] instanceof Object || this[i] instanceof Function) delete this[i];
|
||||||
if (typeof this[i] === 'function') delete this[i];
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
make_objs(objs) {
|
make_objs(objs) {
|
||||||
for (var prop in objs) {
|
for (var prop in objs) {
|
||||||
say(`spawning ${json.encode(objs[prop])}`);
|
say(`spawning ${json.encode(objs[prop])}`);
|
||||||
|
@ -482,17 +490,17 @@ var gameobject = {
|
||||||
var newpos = relative.this2world(x);
|
var newpos = relative.this2world(x);
|
||||||
var move = newpos.sub(this.pos);
|
var move = newpos.sub(this.pos);
|
||||||
this.rpos = newpos;
|
this.rpos = newpos;
|
||||||
this.objects.forEach(x => x.move(move));
|
for (var o of this.objects) o.move(move);
|
||||||
},
|
},
|
||||||
|
|
||||||
set_angle(x, relative = world) {
|
set_angle(x, relative = world) {
|
||||||
var newangle = relative.angle + x;
|
var newangle = relative.angle + x;
|
||||||
var diff = newangle - this.angle;
|
var diff = newangle - this.angle;
|
||||||
this.rangle = newangle;
|
this.rangle = newangle;
|
||||||
this.objects.forEach(obj => {
|
for (var obj of this.objects) {
|
||||||
obj.rotate(diff);
|
obj.rotate(diff);
|
||||||
obj.set_pos(Vector.rotate(obj.get_pos(obj.master), diff), obj.master);
|
obj.set_pos(Vector.rotate(obj.get_pos(obj.master), diff), obj.master);
|
||||||
});
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
set_scale(x, relative = world) {
|
set_scale(x, relative = world) {
|
||||||
|
@ -500,10 +508,10 @@ var gameobject = {
|
||||||
var newscale = relative.scale.map((s,i) => x[i]*s);
|
var newscale = relative.scale.map((s,i) => x[i]*s);
|
||||||
var pct = this.scale.map((s,i) => newscale[i]/s);
|
var pct = this.scale.map((s,i) => newscale[i]/s);
|
||||||
this.rscale = newscale;
|
this.rscale = newscale;
|
||||||
this.objects.forEach(obj => {
|
for (var obj of this.objects) {
|
||||||
obj.grow(pct);
|
obj.grow(pct);
|
||||||
obj.set_pos(obj.get_pos(obj.master).map((x,i) => x*pct[i]), obj.master);
|
obj.set_pos(obj.get_pos(obj.master).map((x,i) => x*pct[i]), obj.master);
|
||||||
});
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
get_pos(relative = world) {
|
get_pos(relative = world) {
|
||||||
|
@ -650,17 +658,17 @@ function apply_ur(u, ent) {
|
||||||
if (typeof text === 'string')
|
if (typeof text === 'string')
|
||||||
use(text, ent);
|
use(text, ent);
|
||||||
else if (Array.isArray(text))
|
else if (Array.isArray(text))
|
||||||
text.forEach(path => use(path,ent));
|
for (var path of text) use(path,ent);
|
||||||
|
|
||||||
if (typeof data === 'string')
|
if (typeof data === 'string')
|
||||||
Object.merge(ent, json.decode(Resources.replstrs(data)));
|
Object.merge(ent, json.decode(Resources.replstrs(data)));
|
||||||
else if (Array.isArray(data)) {
|
else if (Array.isArray(data)) {
|
||||||
data.forEach(function(path) {
|
for (var path of data) {
|
||||||
if (typeof path === 'string')
|
if (typeof path === 'string')
|
||||||
Object.merge(ent, json.decode(Resources.replstrs(data)));
|
Object.merge(ent, json.decode(Resources.replstrs(data)));
|
||||||
else if (typeof path === 'object')
|
else if (path instanceof Object)
|
||||||
Object.merge(ent,path);
|
Object.merge(ent,path);
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -677,7 +685,10 @@ var getur = function(text, data)
|
||||||
name: "empty"
|
name: "empty"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
var urstr = text + "+" + data;
|
var urstr = text;
|
||||||
|
if (data)
|
||||||
|
urstr += "+" + data;
|
||||||
|
|
||||||
if (!ur[urstr]) {
|
if (!ur[urstr]) {
|
||||||
ur[urstr] = {
|
ur[urstr] = {
|
||||||
name: urstr,
|
name: urstr,
|
||||||
|
@ -726,16 +737,6 @@ game.loadurs = function() {
|
||||||
newur.data = data;
|
newur.data = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
for (var file of io.glob("**.json").filter(f => !ur[f.name()])) {
|
|
||||||
if (file[0] === '.' || file[0] === '_') continue;
|
|
||||||
var newur = ur_from_file(file);
|
|
||||||
if (!newur) continue;
|
|
||||||
Object.assign(newur, {
|
|
||||||
data: file
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
game.ur = {};
|
game.ur = {};
|
||||||
|
|
|
@ -190,18 +190,28 @@ mum.image = function(path, data = {})
|
||||||
if (typeof path === 'string')
|
if (typeof path === 'string')
|
||||||
tex = game.texture(path);
|
tex = game.texture(path);
|
||||||
|
|
||||||
data.width ??= tex.width;
|
if (!data.height)
|
||||||
data.height ??= tex.height;
|
if (data.width)
|
||||||
|
data.height = tex.height * (data.width/tex.width);
|
||||||
|
else
|
||||||
|
data.height = tex.height;
|
||||||
|
|
||||||
var aa = [0,0].sub(data.anchor);
|
if (!data.width)
|
||||||
|
if (data.height)
|
||||||
|
data.width = tex.width * (data.height/tex.height);
|
||||||
|
else
|
||||||
|
data.height = tex.height;
|
||||||
|
|
||||||
|
if (!data.width) data.width = tex.width;
|
||||||
|
if (!data.height) data.height = tex.height;
|
||||||
|
|
||||||
|
var aa = [0,1].sub(data.anchor);
|
||||||
data.drawpos = data.drawpos.add(aa.scale([data.width,data.height]));
|
data.drawpos = data.drawpos.add(aa.scale([data.width,data.height]));
|
||||||
|
|
||||||
if (data.slice)
|
if (data.slice)
|
||||||
render.slice9(tex, data.drawpos, data.slice, [data.width,data.height]);
|
render.slice9(tex, data.drawpos, data.slice, [data.width,data.height]);
|
||||||
else {
|
else
|
||||||
cursor.y -= tex.height*data.scale;
|
data.bb = render.image(tex, data.drawpos, [data.width, data.height]);
|
||||||
data.bb = render.image(tex, data.drawpos, [data.scale*tex.width, data.scale*tex.height]);
|
|
||||||
}
|
|
||||||
|
|
||||||
end(data);
|
end(data);
|
||||||
}
|
}
|
||||||
|
@ -262,3 +272,41 @@ mum.ex_hud = function()
|
||||||
mum.label("TOP RIGHT", {pos:game.size, anchor:[1,1]});
|
mum.label("TOP RIGHT", {pos:game.size, anchor:[1,1]});
|
||||||
mum.label("BOTTOM RIGHT", {pos:[game.size.x, 0], anchor:[1,0]});
|
mum.label("BOTTOM RIGHT", {pos:[game.size.x, 0], anchor:[1,0]});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mum.drawinput = undefined;
|
||||||
|
var ptext = "";
|
||||||
|
var panpan = {
|
||||||
|
draw() {
|
||||||
|
mum.rectangle({pos:[0,0], anchor:[0,0], height:20, width: window.size.x, padding:[10,16], color:Color.black});
|
||||||
|
mum.label("input level: ");
|
||||||
|
mum.label(ptext, {offset:[50,0], color:Color.red});
|
||||||
|
},
|
||||||
|
inputs: {
|
||||||
|
block: true,
|
||||||
|
char(c) {
|
||||||
|
ptext += c
|
||||||
|
},
|
||||||
|
enter() {
|
||||||
|
delete mum.drawinput;
|
||||||
|
player[0].uncontrol(panpan);
|
||||||
|
},
|
||||||
|
escape() {
|
||||||
|
delete mum.drawinput;
|
||||||
|
player[0].uncontrol(panpan);
|
||||||
|
},
|
||||||
|
backspace() {
|
||||||
|
ptext = ptext.slice(0,ptext.length-1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
mum.textinput = function (fn, str = "") {
|
||||||
|
mum.drawinput = panpan.draw;
|
||||||
|
ptext = str;
|
||||||
|
player[0].control(panpan);
|
||||||
|
panpan.inputs.enter = function() {
|
||||||
|
fn(ptext);
|
||||||
|
delete mum.drawinput;
|
||||||
|
player[0].uncontrol(panpan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
116
scripts/particle.js
Normal file
116
scripts/particle.js
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
var emitter = {};
|
||||||
|
emitter.particles = {};
|
||||||
|
emitter.life = 10;
|
||||||
|
emitter.scale = 1;
|
||||||
|
emitter.grow_for = 0;
|
||||||
|
emitter.spawn_timer = 0;
|
||||||
|
emitter.pps = 0;
|
||||||
|
emitter.color = Color.white;
|
||||||
|
|
||||||
|
emitter.draw = function()
|
||||||
|
{
|
||||||
|
var amt = Object.values(this.particles).length;
|
||||||
|
if (amt === 0) return;
|
||||||
|
render.use_shader(this.shader);
|
||||||
|
render.use_mat(this);
|
||||||
|
render.make_particle_ssbo(Object.values(this.particles), this.ssbo);
|
||||||
|
render.draw(this.shape, this.ssbo, amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
var std_spawn = function(par)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var std_step = function(p)
|
||||||
|
{
|
||||||
|
if (p.time < this.grow_for) {
|
||||||
|
var s = Math.lerp(0, this.scale, p.time/this.grow_for);
|
||||||
|
p.transform.scale = [s,s,s];
|
||||||
|
}
|
||||||
|
else if (p.time > (p.life - this.shrink_for)) {
|
||||||
|
var s = Math.lerp(0,this.scale,(p.life-p.time)/this.shrink_for);
|
||||||
|
p.transform.scale=[s,s,s];
|
||||||
|
} else
|
||||||
|
p.transform.scale = [this.scale,this.scale,this.scale];
|
||||||
|
}
|
||||||
|
|
||||||
|
var std_die = function(par)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
emitter.spawn_hook = std_spawn;
|
||||||
|
emitter.step_hook = std_step;
|
||||||
|
emitter.die_hook = std_die;
|
||||||
|
|
||||||
|
emitter.spawn = function(t)
|
||||||
|
{
|
||||||
|
t ??= this.transform;
|
||||||
|
|
||||||
|
var par = this.dead.shift();
|
||||||
|
if (par) {
|
||||||
|
par.body.pos = t.pos;
|
||||||
|
par.transform.scale = [this.scale,this.scale,this.scale];
|
||||||
|
this.particles[par.id] = par;
|
||||||
|
par.time = 0;
|
||||||
|
this.spawn_hook(par);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
par = {
|
||||||
|
transform: os.make_transform(),
|
||||||
|
life: this.life,
|
||||||
|
time: 0,
|
||||||
|
color: this.color
|
||||||
|
};
|
||||||
|
|
||||||
|
par.body = os.make_body(par.transform);
|
||||||
|
|
||||||
|
par.body.pos = t.pos;
|
||||||
|
par.transform.scale = [this.scale,this.scale,this.scale];
|
||||||
|
par.id = prosperon.guid();
|
||||||
|
this.particles[par.id] = par;
|
||||||
|
|
||||||
|
this.spawn_hook(par);
|
||||||
|
}
|
||||||
|
|
||||||
|
emitter.step = function(dt)
|
||||||
|
{
|
||||||
|
// update spawning particles
|
||||||
|
if (this.on && this.pps > 0) {
|
||||||
|
this.spawn_timer += dt;
|
||||||
|
var pp = 1/this.pps;
|
||||||
|
while (this.spawn_timer > pp) {
|
||||||
|
this.spawn_timer -= pp;
|
||||||
|
this.spawn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update all particles
|
||||||
|
for (var p of Object.values(this.particles)) {
|
||||||
|
p.time += dt;
|
||||||
|
this.step_hook?.(p);
|
||||||
|
|
||||||
|
if (p.time >= p.life) {
|
||||||
|
this.die_hook(p);
|
||||||
|
this.dead.push(this.particles[p.id]);
|
||||||
|
delete this.particles[p.id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emitter.burst = function(count, t) {
|
||||||
|
for (var i = 0; i < count; i++) this.spawn(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
var make_emitter = function()
|
||||||
|
{
|
||||||
|
var e = Object.create(emitter);
|
||||||
|
e.ssbo = render.make_textssbo();
|
||||||
|
e.shape = shape.centered_quad;
|
||||||
|
e.shader = "shaders/baseparticle.cg";
|
||||||
|
e.dead = [];
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {make_emitter};
|
279
scripts/profile.js
Normal file
279
scripts/profile.js
Normal file
|
@ -0,0 +1,279 @@
|
||||||
|
var t_units = ["ns", "us", "ms", "s", "ks", "Ms"];
|
||||||
|
|
||||||
|
function calc_cpu(fn, times, diff=0)
|
||||||
|
{
|
||||||
|
var series = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < times; i++) {
|
||||||
|
var st = profile.now();
|
||||||
|
fn(i);
|
||||||
|
series.push(profile.now()-st-diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
return series;
|
||||||
|
}
|
||||||
|
|
||||||
|
function empty_fn() {}
|
||||||
|
|
||||||
|
profile.cpu = function profile_cpu(fn, times = 1, q = "unnamed") {
|
||||||
|
profile.gather_stop();
|
||||||
|
var empty = calc_cpu(empty_fn, 100000);
|
||||||
|
var mean = Math.mean(empty);
|
||||||
|
var series = calc_cpu(fn,times, mean);
|
||||||
|
|
||||||
|
var elapsed = Math.sum(series);
|
||||||
|
var avgt = profile.best_t(elapsed/series.length);
|
||||||
|
var totalt = profile.best_t(elapsed);
|
||||||
|
|
||||||
|
say(`profile [${q}]: ${avgt} ± ${profile.best_t(Math.ci(series))} [${totalt} for ${times} loops]`);
|
||||||
|
start_prof_gather();
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.ms = function(t) { return t/1000000; }
|
||||||
|
profile.secs = function(t) { return t/1000000000; }
|
||||||
|
|
||||||
|
var callgraph = {};
|
||||||
|
var st = profile.now();
|
||||||
|
|
||||||
|
function add_callgraph(fn, line, time) {
|
||||||
|
var cc = callgraph[line];
|
||||||
|
if (!cc) {
|
||||||
|
var cc = {};
|
||||||
|
callgraph[line] = cc;
|
||||||
|
cc.time = 0;
|
||||||
|
cc.hits = 0;
|
||||||
|
cc.fn = fn;
|
||||||
|
cc.line = line;
|
||||||
|
}
|
||||||
|
cc.time += time;
|
||||||
|
cc.hits++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hittar = 500;
|
||||||
|
var hitpct = 0.2;
|
||||||
|
var start_gather = profile.now();
|
||||||
|
|
||||||
|
var gathering_cpu = false;
|
||||||
|
|
||||||
|
profile.start_cpu_gather = function()
|
||||||
|
{
|
||||||
|
if (gathering_cpu) return;
|
||||||
|
gathering_cpu = true;
|
||||||
|
profile.gather(hittar, function() {
|
||||||
|
var time = profile.now()-st;
|
||||||
|
|
||||||
|
var err = new Error();
|
||||||
|
var stack = err.stack.split("\n");
|
||||||
|
|
||||||
|
stack = stack.slice(1);
|
||||||
|
stack = stack.map(x => x.slice(7).split(' '));
|
||||||
|
|
||||||
|
var fns = stack.map(x => x[0]).filter(x=>x);
|
||||||
|
var lines = stack.map(x => x[1]).filter(x => x);
|
||||||
|
lines = lines.map(x => x.slice(1,x.length-1));
|
||||||
|
|
||||||
|
for (var i = 0; i < fns.length; i++)
|
||||||
|
add_callgraph(fns[i], lines[i], time);
|
||||||
|
|
||||||
|
st = profile.now();
|
||||||
|
|
||||||
|
profile.gather_rate(Math.variate(hittar,hitpct));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.cpu_frame = function()
|
||||||
|
{
|
||||||
|
if (gathering_cpu) return;
|
||||||
|
|
||||||
|
profile.gather(Math.random_range(300,600), function() {
|
||||||
|
console.stack(2);
|
||||||
|
profile.gather_stop();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var filecache = {};
|
||||||
|
function get_line(file, line) {
|
||||||
|
var text = filecache[file];
|
||||||
|
if (!text) {
|
||||||
|
var f = io.slurp(file);
|
||||||
|
if (!f) {
|
||||||
|
filecache[file] = "undefined";
|
||||||
|
return filecache[file];
|
||||||
|
}
|
||||||
|
filecache[file] = io.slurp(file).split('\n');
|
||||||
|
text = filecache[file];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof text === 'string') return text;
|
||||||
|
text = text[Number(line)-1];
|
||||||
|
if (!text) return "NULL";
|
||||||
|
return text.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.stop_cpu_instr = function()
|
||||||
|
{
|
||||||
|
if (!gathering_cpu) return;
|
||||||
|
|
||||||
|
say("===CPU INSTRUMENTATION===\n");
|
||||||
|
var gather_time = profile.now()-start_gather;
|
||||||
|
var e = Object.values(callgraph);
|
||||||
|
e = e.sort((a,b) => {
|
||||||
|
if (a.time > b.time) return -1;
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
e.forEach(x => {
|
||||||
|
var ffs = x.line.split(':');
|
||||||
|
var time = profile.best_t(x.time);
|
||||||
|
var pct = x.time/gather_time*100;
|
||||||
|
say(`${x.line}::${x.fn}:: ${time} (${pct.toPrecision(3)}%) (${x.hits} hits) --> ${get_line(ffs[0], ffs[1])}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.best_t = function (t) {
|
||||||
|
var qq = 0;
|
||||||
|
|
||||||
|
while (t > 1000 && qq < t_units.length-1) {
|
||||||
|
t /= 1000;
|
||||||
|
qq++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${t.toPrecision(4)} ${t_units[qq]}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
profile.report = function (start, msg = "[undefined report]") { console.info(`${msg} in ${profile.best_t(profile.now() - start)}`); };
|
||||||
|
|
||||||
|
var frame_avg = false;
|
||||||
|
|
||||||
|
profile.start_frame_avg = function()
|
||||||
|
{
|
||||||
|
if (frame_avg) return;
|
||||||
|
say("===STARTING FRAME AVERAGE MEASUREMENTS===");
|
||||||
|
profile_frames = {};
|
||||||
|
profile_frame_ts = [];
|
||||||
|
profile_cframe = profile_frames;
|
||||||
|
pframe = 0;
|
||||||
|
frame_avg = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.stop_frame_avg = function()
|
||||||
|
{
|
||||||
|
if (!frame_avg) return;
|
||||||
|
|
||||||
|
frame_avg = false;
|
||||||
|
profile.print_frame_avg();
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.toggle_frame_avg = function()
|
||||||
|
{
|
||||||
|
if (frame_avg) profile.stop_frame_avg();
|
||||||
|
else profile.start_frame_avg();
|
||||||
|
}
|
||||||
|
|
||||||
|
var profile_frames = {};
|
||||||
|
var profile_frame_ts = [];
|
||||||
|
var profile_cframe = profile_frames;
|
||||||
|
var pframe = 0;
|
||||||
|
|
||||||
|
profile.frame = function profile_frame(title)
|
||||||
|
{
|
||||||
|
if (!frame_avg) return;
|
||||||
|
|
||||||
|
profile_frame_ts.push(profile_cframe);
|
||||||
|
profile_cframe[title] ??= {};
|
||||||
|
profile_cframe = profile_cframe[title];
|
||||||
|
profile_cframe._times ??= [];
|
||||||
|
profile_cframe._times[pframe] ??= 0;
|
||||||
|
profile_cframe._times[pframe] = profile.now() - profile_cframe._times[pframe];
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.endframe = function profile_endframe()
|
||||||
|
{
|
||||||
|
if (!frame_avg) return;
|
||||||
|
|
||||||
|
if (profile_cframe === profile_frames) return;
|
||||||
|
profile_cframe._times[pframe] = profile.now() - profile_cframe._times[pframe];
|
||||||
|
profile_cframe = profile_frame_ts.pop();
|
||||||
|
if (profile_cframe === profile_frames) pframe++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var print_frame = function(frame, indent, title)
|
||||||
|
{
|
||||||
|
say(indent + `${title} ::::: ${profile.best_t(Math.mean(frame._times))} ± ${profile.best_t(Math.ci(frame._times))} (${frame._times.length} hits)`);
|
||||||
|
|
||||||
|
for (var i in frame) {
|
||||||
|
if (i === '_times') continue;
|
||||||
|
print_frame(frame[i], indent + " ", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.print_frame_avg = function()
|
||||||
|
{
|
||||||
|
say("===FRAME AVERAGES===\n");
|
||||||
|
|
||||||
|
var indent = "";
|
||||||
|
for (var i in profile_frames)
|
||||||
|
print_frame(profile_frames[i], "", 'frame');
|
||||||
|
|
||||||
|
say("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
var report_cache = {};
|
||||||
|
|
||||||
|
var cachest = 0;
|
||||||
|
var cachegroup;
|
||||||
|
var cachetitle;
|
||||||
|
profile.cache = function profile_cache(group, title)
|
||||||
|
{
|
||||||
|
cachest = profile.now();
|
||||||
|
cachegroup = group;
|
||||||
|
cachetitle = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.endcache = function profile_endcache(tag = "")
|
||||||
|
{
|
||||||
|
addreport(cachegroup, cachetitle + tag, cachest);
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.print_cache_report = function()
|
||||||
|
{
|
||||||
|
var str = "===START CACHE REPORTS===\n";
|
||||||
|
for (var i in report_cache)
|
||||||
|
str += printreport(report_cache[i], i) + "\n";
|
||||||
|
|
||||||
|
say(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addreport(group, line, start) {
|
||||||
|
if (typeof group !== 'string') group = 'UNGROUPED';
|
||||||
|
report_cache[group] ??= {};
|
||||||
|
var cache = report_cache[group];
|
||||||
|
cache[line] ??= [];
|
||||||
|
var t = profile.now();
|
||||||
|
cache[line].push(t - start);
|
||||||
|
return t;
|
||||||
|
};
|
||||||
|
|
||||||
|
function printreport(cache, name) {
|
||||||
|
var report = `==${name}==` + "\n";
|
||||||
|
|
||||||
|
var reports = [];
|
||||||
|
for (var i in cache) {
|
||||||
|
var time = cache[i].reduce((a,b)=>a+b);
|
||||||
|
reports.push({
|
||||||
|
time:time,
|
||||||
|
name:i,
|
||||||
|
hits:cache[i].length,
|
||||||
|
avg:time/cache[i].length
|
||||||
|
});
|
||||||
|
}
|
||||||
|
reports = reports.sort((a,b) => {
|
||||||
|
if (a.avg<b.avg) return 1;
|
||||||
|
return -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var rep of reports)
|
||||||
|
report += `${rep.name} ${profile.best_t(rep.avg)} (${rep.hits} hits) (total ${profile.best_t(rep.time)})\n`;
|
||||||
|
|
||||||
|
return report;
|
||||||
|
};
|
396
scripts/prosperon.js
Normal file
396
scripts/prosperon.js
Normal file
|
@ -0,0 +1,396 @@
|
||||||
|
globalThis.gamestate = {};
|
||||||
|
|
||||||
|
global.check_registers = function (obj) {
|
||||||
|
for (var reg in Register.registries) {
|
||||||
|
if (typeof obj[reg] === 'function') {
|
||||||
|
var fn = obj[reg].bind(obj);
|
||||||
|
var name = obj.ur ? obj.ur.name : obj.toString();
|
||||||
|
obj.timers.push(Register.registries[reg].register(fn, name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var k in obj) {
|
||||||
|
if (!k.startsWith("on_")) continue;
|
||||||
|
var signal = k.fromfirst("on_");
|
||||||
|
Event.observe(signal, obj, obj[k]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
global.obscure("global");
|
||||||
|
global.mixin("scripts/render");
|
||||||
|
global.mixin("scripts/debug");
|
||||||
|
|
||||||
|
var frame_t = profile.secs(profile.now());
|
||||||
|
|
||||||
|
var sim = {};
|
||||||
|
sim.mode = "play";
|
||||||
|
sim.play = function () {
|
||||||
|
this.mode = "play";
|
||||||
|
os.reindex_static();
|
||||||
|
};
|
||||||
|
sim.playing = function () {
|
||||||
|
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 gggstart = game.engine_start;
|
||||||
|
game.engine_start = function (s) {
|
||||||
|
game.startengine = 1;
|
||||||
|
gggstart(
|
||||||
|
function () {
|
||||||
|
global.mixin("scripts/sound.js");
|
||||||
|
world_start();
|
||||||
|
window.set_icon(os.make_texture("icons/moon.gif"));
|
||||||
|
Object.readonly(window.__proto__, "vsync");
|
||||||
|
Object.readonly(window.__proto__, "enable_dragndrop");
|
||||||
|
Object.readonly(window.__proto__, "enable_clipboard");
|
||||||
|
Object.readonly(window.__proto__, "high_dpi");
|
||||||
|
Object.readonly(window.__proto__, "sample_count");
|
||||||
|
s();
|
||||||
|
|
||||||
|
shape.quad = {
|
||||||
|
pos: os.make_buffer([0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0], 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 = {
|
||||||
|
pos: os.make_buffer([0, 0, 0, 0.5, 1, 0, 1, 0, 0], 0),
|
||||||
|
uv: os.make_buffer([0, 0, 0.5, 1, 1, 0], 2),
|
||||||
|
verts: 3,
|
||||||
|
count: 3,
|
||||||
|
index: os.make_buffer([0, 2, 1], 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
shape.centered_quad = {
|
||||||
|
pos: os.make_buffer([-0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5], 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
|
||||||
|
};
|
||||||
|
|
||||||
|
render.init();
|
||||||
|
|
||||||
|
prosperon.camera = prosperon.make_camera();
|
||||||
|
var camera = prosperon.camera;
|
||||||
|
camera.transform.pos = [0,0,-100];
|
||||||
|
camera.mode = "keep";
|
||||||
|
camera.break = "fit";
|
||||||
|
camera.size = game.size;
|
||||||
|
gamestate.camera = camera;
|
||||||
|
|
||||||
|
prosperon.hudcam = prosperon.make_camera();
|
||||||
|
var hudcam = prosperon.hudcam;
|
||||||
|
hudcam.near = 0;
|
||||||
|
hudcam.size = camera.size;
|
||||||
|
hudcam.mode = "keep";
|
||||||
|
hudcam.break = "fit";
|
||||||
|
|
||||||
|
prosperon.appcam = prosperon.make_camera();
|
||||||
|
var appcam = prosperon.appcam;
|
||||||
|
appcam.near = 0;
|
||||||
|
appcam.size = window.size;
|
||||||
|
appcam.transform.pos = [window.size.x,window.size.y,-100];
|
||||||
|
prosperon.screencolor = render.screencolor();
|
||||||
|
},
|
||||||
|
prosperon.process,
|
||||||
|
window.size.x,
|
||||||
|
window.size.y,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
game.startengine = 0;
|
||||||
|
var frames = [];
|
||||||
|
|
||||||
|
prosperon.release_mode = function()
|
||||||
|
{
|
||||||
|
prosperon.debug = false;
|
||||||
|
mum.debug = false;
|
||||||
|
debug.kill();
|
||||||
|
}
|
||||||
|
prosperon.debug = true;
|
||||||
|
|
||||||
|
globalThis.fps = function () {
|
||||||
|
return 0;
|
||||||
|
// var sum = 0;
|
||||||
|
// for (var i = 0; i < frames.length; i++) sum += frames[i];
|
||||||
|
// return frames.length / sum;
|
||||||
|
};
|
||||||
|
|
||||||
|
game.timescale = 1;
|
||||||
|
|
||||||
|
var eachobj = function (obj, fn) {
|
||||||
|
var val = fn(obj);
|
||||||
|
if (val) return val;
|
||||||
|
for (var o in obj.objects) {
|
||||||
|
if (obj.objects[o] === obj)
|
||||||
|
console.error(`Object ${obj.toString()} is referenced by itself.`);
|
||||||
|
val = eachobj(obj.objects[o], fn);
|
||||||
|
if (val) return val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
game.all_objects = function (fn, startobj = world) {
|
||||||
|
return eachobj(startobj, fn);
|
||||||
|
};
|
||||||
|
game.find_object = function (fn, startobj = world) {};
|
||||||
|
|
||||||
|
game.tags = {};
|
||||||
|
game.tag_add = function (tag, obj) {
|
||||||
|
game.tags[tag] ??= {};
|
||||||
|
game.tags[tag][obj.guid] = obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
game.tag_rm = function (tag, obj) {
|
||||||
|
delete game.tags[tag][obj.guid];
|
||||||
|
};
|
||||||
|
|
||||||
|
game.tag_clear_guid = function (guid) {
|
||||||
|
for (var tag in game.tags) delete game.tags[tag][guid];
|
||||||
|
};
|
||||||
|
|
||||||
|
game.objects_with_tag = function (tag) {
|
||||||
|
if (!game.tags[tag]) return [];
|
||||||
|
return Object.values(game.tags[tag]);
|
||||||
|
};
|
||||||
|
|
||||||
|
game.doc = {};
|
||||||
|
game.doc.object = "Returns the entity belonging to a given id.";
|
||||||
|
game.doc.pause = "Pause game simulation.";
|
||||||
|
game.doc.play = "Resume or start game simulation.";
|
||||||
|
game.doc.camera = "Current camera.";
|
||||||
|
|
||||||
|
game.texture = function (path, force = false) {
|
||||||
|
if (force && game.texture.cache[path]) return game.texture.cache[path];
|
||||||
|
|
||||||
|
if (!io.exists(path)) {
|
||||||
|
console.warn(`Missing texture: ${path}`);
|
||||||
|
game.texture.cache[path] = game.texture("icons/no_tex.gif");
|
||||||
|
} else game.texture.cache[path] ??= os.make_texture(path);
|
||||||
|
|
||||||
|
return game.texture.cache[path];
|
||||||
|
};
|
||||||
|
game.texture.cache = {};
|
||||||
|
|
||||||
|
prosperon.semver = {};
|
||||||
|
prosperon.semver.valid = function (v, range) {
|
||||||
|
v = v.split(".");
|
||||||
|
range = range.split(".");
|
||||||
|
if (v.length !== 3) return undefined;
|
||||||
|
if (range.length !== 3) return undefined;
|
||||||
|
|
||||||
|
if (range[0][0] === "^") {
|
||||||
|
range[0] = range[0].slice(1);
|
||||||
|
if (parseInt(v[0]) >= parseInt(range[0])) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (range[0] === "~") {
|
||||||
|
range[0] = range[0].slice(1);
|
||||||
|
for (var i = 0; i < 2; i++)
|
||||||
|
if (parseInt(v[i]) < parseInt(range[i])) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prosperon.semver.cmp(v.join("."), range.join(".")) === 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
prosperon.semver.cmp = function (v1, v2) {
|
||||||
|
var ver1 = v1.split(".");
|
||||||
|
var ver2 = v2.split(".");
|
||||||
|
|
||||||
|
for (var i = 0; i < 3; i++) {
|
||||||
|
var n1 = parseInt(ver1[i]);
|
||||||
|
var n2 = parseInt(ver2[i]);
|
||||||
|
if (n1 > n2) return 1;
|
||||||
|
else if (n1 < n2) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.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.
|
||||||
|
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 must match exactly, but any MINOR and PATCH greater or equal is valid.`;
|
||||||
|
|
||||||
|
prosperon.iconified = function (icon) {};
|
||||||
|
prosperon.focus = function (focus) {};
|
||||||
|
prosperon.resize = function (dimensions) {
|
||||||
|
window.size.x = dimensions.x;
|
||||||
|
window.size.y = dimensions.y;
|
||||||
|
};
|
||||||
|
prosperon.suspended = function (sus) {};
|
||||||
|
prosperon.mouseenter = function () {};
|
||||||
|
prosperon.mouseleave = function () {};
|
||||||
|
prosperon.touchpress = function (touches) {};
|
||||||
|
prosperon.touchrelease = function (touches) {};
|
||||||
|
prosperon.touchmove = function (touches) {};
|
||||||
|
prosperon.clipboardpaste = function (str) {};
|
||||||
|
prosperon.quit = function () {
|
||||||
|
profile.print_cache_report();
|
||||||
|
profile.stop_frame_avg()
|
||||||
|
profile.stop_cpu_instr();
|
||||||
|
};
|
||||||
|
|
||||||
|
window.size = [640, 480];
|
||||||
|
window.mode = "keep";
|
||||||
|
window.toggle_fullscreen = function() { window.fullscreen = !window.fullscreen; }
|
||||||
|
|
||||||
|
window.set_icon.doc = "Set the icon of the window using the PNG image at path.";
|
||||||
|
|
||||||
|
window.doc = {};
|
||||||
|
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.boundingbox = "Boundingbox of the window, with top and right being its height and width.";
|
||||||
|
|
||||||
|
global.mixin("scripts/input");
|
||||||
|
global.mixin("scripts/std");
|
||||||
|
global.mixin("scripts/diff");
|
||||||
|
global.mixin("scripts/color");
|
||||||
|
global.mixin("scripts/gui");
|
||||||
|
global.mixin("scripts/tween");
|
||||||
|
global.mixin("scripts/ai");
|
||||||
|
global.mixin("scripts/particle");
|
||||||
|
global.mixin("scripts/physics");
|
||||||
|
global.mixin("scripts/geometry");
|
||||||
|
|
||||||
|
/*
|
||||||
|
Factory for creating registries. Register one with 'X.register',
|
||||||
|
which returns a function that, when invoked, cancels the registry.
|
||||||
|
*/
|
||||||
|
var Register = {
|
||||||
|
registries: [],
|
||||||
|
|
||||||
|
add_cb(name, e_event = false) {
|
||||||
|
var n = {};
|
||||||
|
var fns = {};
|
||||||
|
|
||||||
|
n.register = function (fn, oname) {
|
||||||
|
if (!(fn instanceof Function)) return;
|
||||||
|
|
||||||
|
var guid = prosperon.guid();
|
||||||
|
|
||||||
|
var dofn = function(...args) {
|
||||||
|
profile.cache(name,oname);
|
||||||
|
var st = profile.now();
|
||||||
|
fn(...args);
|
||||||
|
profile.endcache();
|
||||||
|
}
|
||||||
|
|
||||||
|
fns[guid] = dofn;
|
||||||
|
return function () {
|
||||||
|
delete fns[guid];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
prosperon[name] = function (...args) {
|
||||||
|
fns.forEach(x => x(...args));
|
||||||
|
};
|
||||||
|
|
||||||
|
prosperon[name].fns = fns;
|
||||||
|
n.clear = function () {
|
||||||
|
fns = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
Register[name] = n;
|
||||||
|
Register.registries[name] = n;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Register.add_cb("appupdate", true);
|
||||||
|
Register.add_cb("update", true).doc = "Called once per frame.";
|
||||||
|
Register.add_cb("physupdate", true);
|
||||||
|
Register.add_cb("gui", true);
|
||||||
|
Register.add_cb("hud", true);
|
||||||
|
Register.add_cb("draw_dbg", true);
|
||||||
|
Register.add_cb("gui_dbg", true);
|
||||||
|
Register.add_cb("hud_dbg", true);
|
||||||
|
Register.add_cb("draw", true);
|
||||||
|
Register.add_cb("imgui", true);
|
||||||
|
|
||||||
|
var Event = {
|
||||||
|
events: {},
|
||||||
|
|
||||||
|
observe(name, obj, fn) {
|
||||||
|
this.events[name] ??= [];
|
||||||
|
this.events[name].push([obj, fn]);
|
||||||
|
},
|
||||||
|
|
||||||
|
unobserve(name, obj) {
|
||||||
|
this.events[name] = this.events[name].filter((x) => x[0] !== obj);
|
||||||
|
},
|
||||||
|
|
||||||
|
rm_obj(obj) {
|
||||||
|
Object.keys(this.events).forEach((name) => Event.unobserve(name, obj));
|
||||||
|
},
|
||||||
|
|
||||||
|
notify(name, ...args) {
|
||||||
|
if (!this.events[name]) return;
|
||||||
|
this.events[name].forEach(function (x) {
|
||||||
|
x[1].call(x[0], ...args);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
global.mixin("scripts/spline");
|
||||||
|
global.mixin("scripts/components");
|
||||||
|
global.mixin("scripts/actor");
|
||||||
|
global.mixin("scripts/entity");
|
||||||
|
|
||||||
|
function world_start() {
|
||||||
|
globalThis.world = Object.create(entity);
|
||||||
|
world.transform = os.make_transform();
|
||||||
|
world.objects = {};
|
||||||
|
world.toString = function () {
|
||||||
|
return "world";
|
||||||
|
};
|
||||||
|
world.ur = "world";
|
||||||
|
world.kill = function () {
|
||||||
|
this.clear();
|
||||||
|
};
|
||||||
|
world.phys = 2;
|
||||||
|
world.zoom = 1;
|
||||||
|
world._ed = { selectable: false };
|
||||||
|
world.ur = {};
|
||||||
|
world.ur.fresh = {};
|
||||||
|
game.cam = world;
|
||||||
|
}
|
||||||
|
|
||||||
|
global.mixin("scripts/physics");
|
||||||
|
global.mixin("scripts/widget");
|
||||||
|
global.mixin("scripts/mum");
|
||||||
|
|
||||||
|
window.title = `Prosperon v${prosperon.version}`;
|
||||||
|
window.size = [500, 500];
|
||||||
|
|
||||||
|
return {
|
||||||
|
Register,
|
||||||
|
sim,
|
||||||
|
frame_t,
|
||||||
|
physlag,
|
||||||
|
Event
|
||||||
|
}
|
|
@ -6,22 +6,24 @@ render.doc = {
|
||||||
|
|
||||||
var cur = {};
|
var cur = {};
|
||||||
|
|
||||||
render.use_shader = function(shader)
|
render.use_shader = function use_shader(shader)
|
||||||
{
|
{
|
||||||
|
if (typeof shader === 'string')
|
||||||
|
shader = make_shader(shader);
|
||||||
if (cur.shader === shader) return;
|
if (cur.shader === shader) return;
|
||||||
cur.shader = shader;
|
cur.shader = shader;
|
||||||
cur.globals = {};
|
|
||||||
cur.bind = undefined;
|
cur.bind = undefined;
|
||||||
cur.mesh = undefined;
|
cur.mesh = undefined;
|
||||||
render.setpipeline(shader.pipe);
|
render.setpipeline(shader.pipe);
|
||||||
|
shader_globals(cur.shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
render.use_mat = function(mat)
|
render.use_mat = function use_mat(mat)
|
||||||
{
|
{
|
||||||
if (!cur.shader) return;
|
if (!cur.shader) return;
|
||||||
if (cur.mat === mat) return;
|
if (cur.mat === mat) return;
|
||||||
|
|
||||||
render.shader_apply_material(cur.shader, mat, cur.mat);
|
shader_apply_material(cur.shader, mat, cur.mat);
|
||||||
|
|
||||||
cur.mat = mat;
|
cur.mat = mat;
|
||||||
|
|
||||||
|
@ -36,7 +38,7 @@ render.use_mat = function(mat)
|
||||||
|
|
||||||
var models_array = [];
|
var models_array = [];
|
||||||
|
|
||||||
render.set_model = function(t)
|
function set_model(t)
|
||||||
{
|
{
|
||||||
if (cur.shader.vs.unimap.model)
|
if (cur.shader.vs.unimap.model)
|
||||||
render.setunim4(0, cur.shader.vs.unimap.model.slot, t);
|
render.setunim4(0, cur.shader.vs.unimap.model.slot, t);
|
||||||
|
@ -94,7 +96,7 @@ var face_map = {
|
||||||
ccw: 1
|
ccw: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
render.poly_prim = function(verts)
|
render.poly_prim = function poly_prim(verts)
|
||||||
{
|
{
|
||||||
var index = [];
|
var index = [];
|
||||||
if (verts.length < 1) return undefined;
|
if (verts.length < 1) return undefined;
|
||||||
|
@ -129,42 +131,40 @@ function shader_directive(shader, name, map)
|
||||||
return ff;
|
return ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
function global_uni(uni, stage)
|
var uni_globals = {
|
||||||
{
|
time(stage, slot) { render.setuniv(stage, slot, profile.secs(profile.now())); },
|
||||||
cur.globals[stage] ??= {};
|
projection(stage,slot) { render.setuniproj(stage, slot); },
|
||||||
if (cur.globals[stage][uni.name]) return true;
|
view(stage,slot) { render.setuniview(stage, slot); },
|
||||||
switch(uni.name) {
|
vp(stage,slot) { render.setunivp(stage,slot); },
|
||||||
case "time":
|
|
||||||
cur.globals[stage][uni.name]
|
|
||||||
render.setuniv(stage, uni.slot, profile.secs(profile.now()));
|
|
||||||
cur.globals[stage][uni.name] = true;
|
|
||||||
return true;
|
|
||||||
case "projection":
|
|
||||||
render.setuniproj(stage, uni.slot);
|
|
||||||
cur.globals[stage][uni.name] = true;
|
|
||||||
return true;
|
|
||||||
case "view":
|
|
||||||
render.setuniview(stage, uni.slot);
|
|
||||||
cur.globals[stage][uni.name] = true;
|
|
||||||
return true;
|
|
||||||
case "vp":
|
|
||||||
render.setunivp(stage, uni.slot);
|
|
||||||
cur.globals[stage][uni.name] = true;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
function set_global_uni(uni, stage) {
|
||||||
|
uni_globals[uni.name]?.(stage, uni.slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
var setcam = render.set_camera;
|
var setcam = render.set_camera;
|
||||||
render.set_camera = function(cam)
|
render.set_camera = function(cam)
|
||||||
{
|
{
|
||||||
|
if (nextflush) {
|
||||||
|
nextflush();
|
||||||
|
nextflush = undefined;
|
||||||
|
}
|
||||||
delete cur.shader;
|
delete cur.shader;
|
||||||
setcam(cam);
|
setcam(cam);
|
||||||
}
|
}
|
||||||
|
|
||||||
render.make_shader = function(shader)
|
var shader_cache = {};
|
||||||
|
|
||||||
|
function strip_shader_inputs(shader)
|
||||||
{
|
{
|
||||||
|
for (var a of shader.vs.inputs)
|
||||||
|
a.name = a.name.slice(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_shader(shader)
|
||||||
|
{
|
||||||
|
if (shader_cache[shader]) return shader_cache[shader];
|
||||||
|
|
||||||
var file = shader;
|
var file = shader;
|
||||||
shader = io.slurp(shader);
|
shader = io.slurp(shader);
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
|
@ -172,20 +172,25 @@ render.make_shader = function(shader)
|
||||||
shader = io.slurp(`shaders/${file}`);
|
shader = io.slurp(`shaders/${file}`);
|
||||||
}
|
}
|
||||||
var writejson = `.prosperon/${file.name()}.shader.json`;
|
var writejson = `.prosperon/${file.name()}.shader.json`;
|
||||||
var st = profile.now();
|
|
||||||
|
profile.cache("shader", file);
|
||||||
|
|
||||||
breakme: if (io.exists(writejson)) {
|
breakme: if (io.exists(writejson)) {
|
||||||
var data = json.decode(io.slurp(writejson));
|
var data = json.decode(io.slurp(writejson));
|
||||||
var filemod = io.mod(writejson);
|
var filemod = io.mod(writejson);
|
||||||
if (!data.files) break breakme;
|
if (!data.files) break breakme;
|
||||||
for (var i of data.files)
|
for (var i of data.files) {
|
||||||
if (io.mod(i) > filemod)
|
if (io.mod(i) > filemod) {
|
||||||
break breakme;
|
break breakme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
profile.report(st, `CACHE make shader from ${file}`);
|
profile.endcache(" [cached]");
|
||||||
var shaderobj = json.decode(io.slurp(writejson));
|
var shaderobj = json.decode(io.slurp(writejson));
|
||||||
var obj = shaderobj[os.sys()];
|
var obj = shaderobj[os.sys()];
|
||||||
|
strip_shader_inputs(obj);
|
||||||
obj.pipe = render.pipeline(obj);
|
obj.pipe = render.pipeline(obj);
|
||||||
|
shader_cache[shader] = obj;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,11 +302,13 @@ render.make_shader = function(shader)
|
||||||
compiled.files = files;
|
compiled.files = files;
|
||||||
|
|
||||||
io.slurpwrite(writejson, json.encode(compiled));
|
io.slurpwrite(writejson, json.encode(compiled));
|
||||||
profile.report(st, `make shader from ${file}`);
|
profile.endcache();
|
||||||
|
|
||||||
var obj = compiled[os.sys()];
|
var obj = compiled[os.sys()];
|
||||||
|
strip_shader_inputs(obj);
|
||||||
obj.pipe = render.pipeline(obj);
|
obj.pipe = render.pipeline(obj);
|
||||||
|
|
||||||
|
shader_cache[shader] = obj;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,10 +319,19 @@ var shader_unisize = {
|
||||||
16: render.setuniv4
|
16: render.setuniv4
|
||||||
};
|
};
|
||||||
|
|
||||||
render.shader_apply_material = function(shader, material = {}, old = {})
|
function shader_globals(shader)
|
||||||
|
{
|
||||||
|
for (var p in shader.vs.unimap)
|
||||||
|
set_global_uni(shader.vs.unimap[p], 0);
|
||||||
|
|
||||||
|
for (var p in shader.fs.unimap)
|
||||||
|
set_global_uni(shader.fs.unimap[p], 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shader_apply_material(shader, material = {}, old = {})
|
||||||
{
|
{
|
||||||
for (var p in shader.vs.unimap) {
|
for (var p in shader.vs.unimap) {
|
||||||
if (global_uni(shader.vs.unimap[p], 0)) continue;
|
if (!(p in material)) continue;
|
||||||
if (material[p] === old[p]) continue;
|
if (material[p] === old[p]) continue;
|
||||||
assert(p in material, `shader ${shader.name} has no uniform for ${p}`);
|
assert(p in material, `shader ${shader.name} has no uniform for ${p}`);
|
||||||
var s = shader.vs.unimap[p];
|
var s = shader.vs.unimap[p];
|
||||||
|
@ -323,7 +339,7 @@ render.shader_apply_material = function(shader, material = {}, old = {})
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var p in shader.fs.unimap) {
|
for (var p in shader.fs.unimap) {
|
||||||
if (global_uni(shader.fs.unimap[p], 1)) continue;
|
if (!(p in material)) continue;
|
||||||
if (material[p] === old[p]) continue;
|
if (material[p] === old[p]) continue;
|
||||||
assert(p in material, `shader ${shader.name} has no uniform for ${p}`);
|
assert(p in material, `shader ${shader.name} has no uniform for ${p}`);
|
||||||
var s = shader.fs.unimap[p];
|
var s = shader.fs.unimap[p];
|
||||||
|
@ -340,7 +356,7 @@ render.shader_apply_material = function(shader, material = {}, old = {})
|
||||||
render.setuniv2(0, shader.vs.unimap.diffuse_size.slot, [material.diffuse.width, material.diffuse.height]);
|
render.setuniv2(0, shader.vs.unimap.diffuse_size.slot, [material.diffuse.width, material.diffuse.height]);
|
||||||
}
|
}
|
||||||
|
|
||||||
render.sg_bind = function(mesh, ssbo)
|
function sg_bind(mesh, ssbo)
|
||||||
{
|
{
|
||||||
if (cur.mesh === mesh && cur.bind) {
|
if (cur.mesh === mesh && cur.bind) {
|
||||||
cur.bind.inst = 1;
|
cur.bind.inst = 1;
|
||||||
|
@ -356,12 +372,9 @@ render.sg_bind = function(mesh, ssbo)
|
||||||
if (cur.shader.vs.inputs)
|
if (cur.shader.vs.inputs)
|
||||||
for (var a of cur.shader.vs.inputs) {
|
for (var a of cur.shader.vs.inputs) {
|
||||||
if (!(a.name in mesh)) {
|
if (!(a.name in mesh)) {
|
||||||
if (!(a.name.slice(2) in mesh)) {
|
|
||||||
console.error(`cannot draw shader ${cur.shader.name}; there is no attrib ${a.name} in the given mesh.`);
|
console.error(`cannot draw shader ${cur.shader.name}; there is no attrib ${a.name} in the given mesh.`);
|
||||||
return undefined;
|
return undefined;
|
||||||
} else
|
} else
|
||||||
bind.attrib.push(mesh[a.name.slice(2)]);
|
|
||||||
} else
|
|
||||||
bind.attrib.push(mesh[a.name]);
|
bind.attrib.push(mesh[a.name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,14 +439,27 @@ var textshader;
|
||||||
var circleshader;
|
var circleshader;
|
||||||
var polyshader;
|
var polyshader;
|
||||||
var slice9shader;
|
var slice9shader;
|
||||||
|
var parshader;
|
||||||
|
var spritessboshader;
|
||||||
|
var polyssboshader;
|
||||||
|
|
||||||
|
var sprite_ssbo;
|
||||||
|
|
||||||
render.init = function() {
|
render.init = function() {
|
||||||
textshader = render.make_shader("shaders/text_base.cg");
|
textshader = make_shader("shaders/text_base.cg");
|
||||||
render.spriteshader = render.make_shader("shaders/sprite.cg");
|
render.spriteshader = make_shader("shaders/sprite.cg");
|
||||||
render.postshader = render.make_shader("shaders/simplepost.cg");
|
spritessboshader = make_shader("shaders/sprite_ssbo.cg");
|
||||||
slice9shader = render.make_shader("shaders/9slice.cg");
|
render.postshader = make_shader("shaders/simplepost.cg");
|
||||||
circleshader = render.make_shader("shaders/circle.cg");
|
slice9shader = make_shader("shaders/9slice.cg");
|
||||||
polyshader = render.make_shader("shaders/poly.cg");
|
circleshader = make_shader("shaders/circle.cg");
|
||||||
|
polyshader = make_shader("shaders/poly.cg");
|
||||||
|
parshader = make_shader("shaders/baseparticle.cg");
|
||||||
|
polyssboshader = make_shader("shaders/poly_ssbo.cg");
|
||||||
|
textssbo = render.make_textssbo();
|
||||||
|
poly_ssbo = render.make_textssbo();
|
||||||
|
sprite_ssbo = render.make_textssbo();
|
||||||
|
|
||||||
|
globalThis.imgui = render.imgui_init();
|
||||||
|
|
||||||
render.textshader = textshader;
|
render.textshader = textshader;
|
||||||
|
|
||||||
|
@ -467,7 +493,55 @@ render.init = function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render.circle = function(pos, radius, color) {
|
render.sprites = function render_sprites(gridsize = 1)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
profile.frame("bucketing");
|
||||||
|
var sps = Object.values(allsprites);
|
||||||
|
|
||||||
|
var buckets = [];
|
||||||
|
for (var i = 0; i <= 20; i++)
|
||||||
|
buckets[i] = {};
|
||||||
|
|
||||||
|
for (var sprite of sps) {
|
||||||
|
var layer = sprite.gameobject.drawlayer+10;
|
||||||
|
if (buckets[layer][sprite.path])
|
||||||
|
buckets[layer][sprite.path].push(sprite);
|
||||||
|
else
|
||||||
|
buckets[layer][sprite.path] = [sprite];
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.endframe();
|
||||||
|
*/
|
||||||
|
|
||||||
|
profile.frame("sorting");
|
||||||
|
var sprite_buckets = component.sprite_buckets();
|
||||||
|
|
||||||
|
var buckets = Object.entries(sprite_buckets).sort((a,b) => {
|
||||||
|
var na = Number(a[0]);
|
||||||
|
var nb = Number(b[0]);
|
||||||
|
if (na < nb) return -1;
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
profile.endframe();
|
||||||
|
|
||||||
|
profile.frame("drawing");
|
||||||
|
render.use_shader(spritessboshader);
|
||||||
|
for (var layer of buckets) {
|
||||||
|
for (var img of Object.values(layer[1])) {
|
||||||
|
var sparray = Object.values(img);
|
||||||
|
if (sparray.length === 0) continue;
|
||||||
|
var ss = sparray[0];
|
||||||
|
render.use_mat(ss);
|
||||||
|
render.make_sprite_ssbo(sparray, sprite_ssbo);
|
||||||
|
render.draw(shape.quad, sprite_ssbo, sparray.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
profile.endframe();
|
||||||
|
}
|
||||||
|
|
||||||
|
render.circle = function render_circle(pos, radius, color) {
|
||||||
|
flush();
|
||||||
var mat = {
|
var mat = {
|
||||||
radius: radius,
|
radius: radius,
|
||||||
coord: pos,
|
coord: pos,
|
||||||
|
@ -478,24 +552,71 @@ render.circle = function(pos, radius, color) {
|
||||||
render.draw(shape.quad);
|
render.draw(shape.quad);
|
||||||
}
|
}
|
||||||
|
|
||||||
render.poly = function(points, color, transform) {
|
render.poly = function render_poly(points, color, transform) {
|
||||||
var buffer = render.poly_prim(points);
|
var buffer = render.poly_prim(points);
|
||||||
var mat = { shade: color};
|
var mat = { shade: color};
|
||||||
render.use_shader(polyshader);
|
render.use_shader(polyshader);
|
||||||
render.set_model(transform);
|
set_model(transform);
|
||||||
render.use_mat(mat);
|
render.use_mat(mat);
|
||||||
render.draw(buffer);
|
render.draw(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
render.line = function(points, color = Color.white, thickness = 1, transform) {
|
var nextflush = undefined;
|
||||||
var buffer = os.make_line_prim(points, thickness, 0, false);
|
function flush()
|
||||||
render.use_shader(polyshader);
|
{
|
||||||
var mat = {
|
nextflush?.();
|
||||||
shade: color
|
nextflush = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_flush(flush_fn)
|
||||||
|
{
|
||||||
|
if (!nextflush)
|
||||||
|
nextflush = flush_fn;
|
||||||
|
else if (nextflush !== flush_fn) {
|
||||||
|
nextflush();
|
||||||
|
nextflush = flush_fn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var poly_cache = [];
|
||||||
|
var poly_idx = 0;
|
||||||
|
var poly_ssbo;
|
||||||
|
|
||||||
|
function poly_e()
|
||||||
|
{
|
||||||
|
var e;
|
||||||
|
poly_idx++;
|
||||||
|
if (poly_idx > poly_cache.length) {
|
||||||
|
e = {
|
||||||
|
transform:os.make_transform(),
|
||||||
|
color: Color.white
|
||||||
};
|
};
|
||||||
render.use_mat(mat);
|
poly_cache.push(e);
|
||||||
render.set_model(transform);
|
return e;
|
||||||
render.draw(buffer);
|
}
|
||||||
|
var e = poly_cache[poly_idx-1];
|
||||||
|
e.transform.unit();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
function flush_poly()
|
||||||
|
{
|
||||||
|
if (poly_idx === 0) return;
|
||||||
|
render.use_shader(polyssboshader);
|
||||||
|
render.use_mat({});
|
||||||
|
render.make_particle_ssbo(poly_cache.slice(0,poly_idx), poly_ssbo);
|
||||||
|
render.draw(shape.centered_quad, poly_ssbo, poly_cache.length);
|
||||||
|
poly_idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
render.line = function render_line(points, color = Color.white, thickness = 1) {
|
||||||
|
var poly = poly_e();
|
||||||
|
var dist = vector.distance(points[0],points[1]);
|
||||||
|
poly.transform.move(vector.midpoint(points[0],points[1]));
|
||||||
|
poly.transform.rotate([0,0,-1], vector.angle([points[1].x-points[0].x, points[1].y-points[0].y]));
|
||||||
|
poly.transform.scale = [dist, thickness, 1];
|
||||||
|
poly.color = color;
|
||||||
|
check_flush(flush_poly);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All draw in screen space */
|
/* All draw in screen space */
|
||||||
|
@ -503,7 +624,7 @@ render.point = function(pos,size,color = Color.blue) {
|
||||||
render.circle(pos,size,size,color);
|
render.circle(pos,size,size,color);
|
||||||
};
|
};
|
||||||
|
|
||||||
render.cross = function(pos, size, color = Color.red, thickness = 1) {
|
render.cross = function render_cross(pos, size, color = Color.red, thickness = 1) {
|
||||||
var a = [
|
var a = [
|
||||||
pos.add([0,size]),
|
pos.add([0,size]),
|
||||||
pos.add([0,-size])
|
pos.add([0,-size])
|
||||||
|
@ -516,7 +637,7 @@ render.cross = function(pos, size, color = Color.red, thickness = 1) {
|
||||||
render.line(b,color,thickness);
|
render.line(b,color,thickness);
|
||||||
};
|
};
|
||||||
|
|
||||||
render.arrow = function(start, end, color = Color.red, wingspan = 4, wingangle = 10) {
|
render.arrow = function render_arrow(start, end, color = Color.red, wingspan = 4, wingangle = 10) {
|
||||||
var dir = end.sub(start).normalized();
|
var dir = end.sub(start).normalized();
|
||||||
var wing1 = [
|
var wing1 = [
|
||||||
Vector.rotate(dir, wingangle).scale(wingspan).add(end),
|
Vector.rotate(dir, wingangle).scale(wingspan).add(end),
|
||||||
|
@ -531,31 +652,34 @@ render.arrow = function(start, end, color = Color.red, wingspan = 4, wingangle =
|
||||||
render.line(wing2,color);
|
render.line(wing2,color);
|
||||||
};
|
};
|
||||||
|
|
||||||
render.coordinate = function(pos, size, color) {
|
render.coordinate = function render_coordinate(pos, size, color) {
|
||||||
render.text(JSON.stringify(pos.map(p=>Math.round(p))), pos, size, color);
|
render.text(JSON.stringify(pos.map(p=>Math.round(p))), pos, size, color);
|
||||||
render.point(pos, 2, color);
|
render.point(pos, 2, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
render.boundingbox = function(bb, color = Color.white) {
|
render.boundingbox = function render_boundingbox(bb, color = Color.white) {
|
||||||
render.line(bbox.topoints(bb).wrapped(1), color);
|
render.line(bbox.topoints(bb).wrapped(1), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
render.rectangle = function(lowerleft, upperright, color) {
|
render.rectangle = function render_rectangle(lowerleft, upperright, color) {
|
||||||
var points = [lowerleft, lowerleft.add([upperright.x-lowerleft.x,0]), upperright, lowerleft.add([0,upperright.y-lowerleft.y])];
|
var transform = os.make_transform();
|
||||||
render.poly(points, color);
|
var wh = [upperright.x-lowerleft.x, upperright.y-lowerleft.y];
|
||||||
|
var poly = poly_e();
|
||||||
|
poly.transform.move(vector.midpoint(lowerleft,upperright));
|
||||||
|
poly.transform.scale = [wh.x,wh.y,1];
|
||||||
|
poly.color = color;
|
||||||
|
check_flush(flush_poly);
|
||||||
};
|
};
|
||||||
|
|
||||||
render.box = function(pos, wh, color = Color.white) {
|
render.box = function render_box(pos, wh, color = Color.white) {
|
||||||
var lower = pos.sub(wh.scale(0.5));
|
var poly = poly_e();
|
||||||
var upper = pos.add(wh.scale(0.5));
|
poly.transform.move(pos);
|
||||||
render.rectangle(lower,upper,color);
|
poly.transform.scale = [wh.x,wh.y,1];
|
||||||
|
poly.color = color;
|
||||||
|
check_flush(flush_poly);
|
||||||
};
|
};
|
||||||
|
|
||||||
render.window = function(pos, wh, color) {
|
render.window = function render_window(pos, wh, color) { render.box(pos.add(wh.scale(0.5)),wh,color); };
|
||||||
var p = pos.slice();
|
|
||||||
p = p.add(wh.scale(0.5));
|
|
||||||
render.box(p,wh,color);
|
|
||||||
};
|
|
||||||
|
|
||||||
render.text_bb = function(str, size = 1, wrap = -1, pos = [0,0])
|
render.text_bb = function(str, size = 1, wrap = -1, pos = [0,0])
|
||||||
{
|
{
|
||||||
|
@ -573,6 +697,7 @@ render.text_bb = function(str, size = 1, wrap = -1, pos = [0,0])
|
||||||
render.text = function(str, pos, size = 1, color = Color.white, wrap = -1, anchor = [0,1], cursor = -1) {
|
render.text = function(str, pos, size = 1, color = Color.white, wrap = -1, anchor = [0,1], cursor = -1) {
|
||||||
var bb = render.text_bb(str, size, wrap, pos);
|
var bb = render.text_bb(str, size, wrap, pos);
|
||||||
gui.text(str, pos, size, color, wrap, cursor);
|
gui.text(str, pos, size, color, wrap, cursor);
|
||||||
|
check_flush(render.flush_text);
|
||||||
return bb;
|
return bb;
|
||||||
|
|
||||||
p.x -= w * anchor.x;
|
p.x -= w * anchor.x;
|
||||||
|
@ -586,11 +711,12 @@ render.text = function(str, pos, size = 1, color = Color.white, wrap = -1, ancho
|
||||||
};
|
};
|
||||||
|
|
||||||
render.image = function(tex, pos, scale = [tex.width, tex.height], rotation = 0, color = Color.white) {
|
render.image = function(tex, pos, scale = [tex.width, tex.height], rotation = 0, color = Color.white) {
|
||||||
|
flush();
|
||||||
var t = os.make_transform();
|
var t = os.make_transform();
|
||||||
t.pos = pos;
|
t.pos = pos;
|
||||||
t.scale = [scale.x/tex.width,scale.y/tex.height,1];
|
t.scale = [scale.x/tex.width,scale.y/tex.height,1];
|
||||||
render.use_shader(render.spriteshader);
|
render.use_shader(render.spriteshader);
|
||||||
render.set_model(t);
|
set_model(t);
|
||||||
render.use_mat({
|
render.use_mat({
|
||||||
shade: color,
|
shade: color,
|
||||||
diffuse: tex,
|
diffuse: tex,
|
||||||
|
@ -621,7 +747,7 @@ render.slice9 = function(tex, pos, bb, scale = [tex.width,tex.height], color = C
|
||||||
border = [bb.l/tex.width, bb.b/tex.height, bb.r/tex.width, bb.t/tex.height];
|
border = [bb.l/tex.width, bb.b/tex.height, bb.r/tex.width, bb.t/tex.height];
|
||||||
|
|
||||||
render.use_shader(slice9shader);
|
render.use_shader(slice9shader);
|
||||||
render.set_model(t);
|
set_model(t);
|
||||||
render.use_mat({
|
render.use_mat({
|
||||||
shade: color,
|
shade: color,
|
||||||
diffuse:tex,
|
diffuse:tex,
|
||||||
|
@ -633,27 +759,43 @@ render.slice9 = function(tex, pos, bb, scale = [tex.width,tex.height], color = C
|
||||||
render.draw(shape.quad);
|
render.draw(shape.quad);
|
||||||
}
|
}
|
||||||
|
|
||||||
var textssbo = render.text_ssbo();
|
render.emitter = function(emit)
|
||||||
|
{
|
||||||
|
var amt = Object.values(emit.particles).length;
|
||||||
|
if (amt === 0) return;
|
||||||
|
render.use_shader(parshader);
|
||||||
|
render.use_mat(emit);
|
||||||
|
var ts = [];
|
||||||
|
for (var p of Object.values(emit.particles)) ts.push([p.transform,p.color]);
|
||||||
|
render.make_particle_ssbo(ts, emit.ssbo);
|
||||||
|
render.draw(shape.quad, emit.ssbo, amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
var textssbo;
|
||||||
|
|
||||||
render.flush_text = function()
|
render.flush_text = function()
|
||||||
{
|
{
|
||||||
if (!render.textshader) return;
|
if (!render.textshader) return;
|
||||||
|
var amt = render.flushtext(textssbo);
|
||||||
|
|
||||||
render.use_shader(render.textshader);
|
render.use_shader(render.textshader);
|
||||||
render.use_mat({text:render.font.texture});
|
render.use_mat({text:render.font.texture});
|
||||||
|
|
||||||
render.draw(shape.quad, textssbo, render.flushtext());
|
if (amt === 0) return;
|
||||||
|
|
||||||
|
render.draw(shape.quad, textssbo, amt);
|
||||||
}
|
}
|
||||||
|
|
||||||
render.fontcache = {};
|
var fontcache = {};
|
||||||
render.set_font = function(path, size) {
|
render.set_font = function(path, size) {
|
||||||
var fontstr = `${path}-${size}`;
|
var fontstr = `${path}-${size}`;
|
||||||
if (render.font && render.fontcache[fontstr] === render.font) return;
|
if (render.font && fontcache[fontstr] === render.font) return;
|
||||||
if (!render.fontcache[fontstr]) render.fontcache[fontstr] = os.make_font(path, size);
|
if (!fontcache[fontstr]) fontcache[fontstr] = os.make_font(path, size);
|
||||||
|
|
||||||
render.flush_text();
|
render.flush_text();
|
||||||
|
|
||||||
gui.font_set(render.fontcache[fontstr]);
|
gui.font_set(fontcache[fontstr]);
|
||||||
render.font = render.fontcache[fontstr];
|
render.font = fontcache[fontstr];
|
||||||
}
|
}
|
||||||
|
|
||||||
render.doc = "Draw shapes in screen space.";
|
render.doc = "Draw shapes in screen space.";
|
||||||
|
@ -662,10 +804,204 @@ render.cross.doc = "Draw a cross centered at pos, with arm length size.";
|
||||||
render.arrow.doc = "Draw an arrow from start to end, with wings of length wingspan at angle wingangle.";
|
render.arrow.doc = "Draw an arrow from start to end, with wings of length wingspan at angle wingangle.";
|
||||||
render.rectangle.doc = "Draw a rectangle, with its corners at lowerleft and upperright.";
|
render.rectangle.doc = "Draw a rectangle, with its corners at lowerleft and upperright.";
|
||||||
|
|
||||||
render.draw = function(mesh, ssbo, inst = 1)
|
render.draw = function render_draw(mesh, ssbo, inst = 1)
|
||||||
{
|
{
|
||||||
render.sg_bind(mesh, ssbo);
|
sg_bind(mesh, ssbo);
|
||||||
|
profile.frame("gpu");
|
||||||
render.spdraw(cur.bind.count, inst);
|
render.spdraw(cur.bind.count, inst);
|
||||||
|
profile.endframe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns an array in the form of [left, bottom, right, top] in pixels of the camera to render to
|
||||||
|
// Camera viewport is [left,bottom,right,top] in relative values
|
||||||
|
function camviewport()
|
||||||
|
{
|
||||||
|
var aspect = (this.viewport[2]-this.viewport[0])/(this.viewport[3]-this.viewport[1])*window.size.x/window.size.y;
|
||||||
|
var raspect = this.size.x/this.size.y;
|
||||||
|
|
||||||
|
var left = this.viewport[0]*window.size.x;
|
||||||
|
var bottom = this.viewport[1]*window.size.y;
|
||||||
|
|
||||||
|
var usemode = this.mode;
|
||||||
|
|
||||||
|
if (this.break && this.size.x > window.size.x && this.size.y > window.size.y)
|
||||||
|
usemode = this.break;
|
||||||
|
|
||||||
|
if (usemode === "fit")
|
||||||
|
if (raspect < aspect) usemode = "height";
|
||||||
|
else usemode = "width";
|
||||||
|
|
||||||
|
switch(usemode) {
|
||||||
|
case "stretch":
|
||||||
|
case "expand":
|
||||||
|
return [0, 0, window.size.x, window.size.y];
|
||||||
|
case "keep":
|
||||||
|
return [left, bottom, left+this.size.x, bottom+this.size.y];
|
||||||
|
case "height":
|
||||||
|
var ret = [left, 0, this.size.x*(window.size.y/this.size.y), window.size.y];
|
||||||
|
ret[0] = (window.size.x-(ret[2]-ret[0]))/2;
|
||||||
|
return ret;
|
||||||
|
case "width":
|
||||||
|
var ret = [0, bottom, window.size.x, this.size.y*(window.size.x/this.size.x)];
|
||||||
|
ret[1] = (window.size.y-(ret[3]-ret[1]))/2;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [0, 0, window.size.x, window.size.y];
|
||||||
|
}
|
||||||
|
|
||||||
|
// pos is pixels on the screen, lower left[0,0]
|
||||||
|
function camscreen2world(pos)
|
||||||
|
{
|
||||||
|
var view = this.screen2cam(pos);
|
||||||
|
view.x *= this.size.x;
|
||||||
|
view.y *= this.size.y;
|
||||||
|
view = view.sub([this.size.x/2, this.size.y/2]);
|
||||||
|
view = view.add(this.pos.xy);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
camscreen2world.doc = "Convert a view position for a camera to world."
|
||||||
|
|
||||||
|
function screen2cam(pos)
|
||||||
|
{
|
||||||
|
var viewport = this.view();
|
||||||
|
var width = viewport[2]-viewport[0];
|
||||||
|
var height = viewport[3]-viewport[1];
|
||||||
|
var left = pos.x-viewport[0];
|
||||||
|
var bottom = pos.y-viewport[1];
|
||||||
|
var p = [left/width, bottom/height];
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
screen2cam.doc = "Convert a screen space position in pixels to a normalized viewport position in a camera."
|
||||||
|
|
||||||
|
prosperon.make_camera = function()
|
||||||
|
{
|
||||||
|
var cam = world.spawn();
|
||||||
|
cam.near = 0.1;
|
||||||
|
cam.far = 1000;
|
||||||
|
cam.ortho = true;
|
||||||
|
cam.viewport = [0,0,1,1];
|
||||||
|
cam.size = window.size.slice(); // The render size of this camera in pixels
|
||||||
|
// In ortho mode, this determines how many pixels it will see
|
||||||
|
cam.mode = "stretch";
|
||||||
|
cam.screen2world = camscreen2world;
|
||||||
|
cam.screen2cam = screen2cam;
|
||||||
|
|
||||||
|
cam.mousepos = function() { return this.screen2world(input.mouse.screenpos()); }
|
||||||
|
cam.view = camviewport;
|
||||||
|
cam.offscreen = false;
|
||||||
|
return cam;
|
||||||
|
}
|
||||||
|
|
||||||
|
var screencolor;
|
||||||
|
|
||||||
|
prosperon.render = function()
|
||||||
|
{
|
||||||
|
profile.frame("world");
|
||||||
|
render.set_camera(prosperon.camera);
|
||||||
|
profile.frame("sprites");
|
||||||
|
render.sprites();
|
||||||
|
profile.endframe();
|
||||||
|
profile.frame("draws");
|
||||||
|
prosperon.draw();
|
||||||
|
profile.endframe();
|
||||||
|
prosperon.hudcam.size = prosperon.camera.size;
|
||||||
|
prosperon.hudcam.transform.pos = [prosperon.hudcam.size.x/2, prosperon.hudcam.size.y/2, -100];
|
||||||
|
render.set_camera(prosperon.hudcam);
|
||||||
|
|
||||||
|
profile.endframe();
|
||||||
|
profile.frame("hud");
|
||||||
|
|
||||||
|
prosperon.hud();
|
||||||
|
render.flush_text();
|
||||||
|
|
||||||
|
render.end_pass();
|
||||||
|
|
||||||
|
profile.endframe();
|
||||||
|
|
||||||
|
profile.frame("post process");
|
||||||
|
/* draw the image of the game world first */
|
||||||
|
render.glue_pass();
|
||||||
|
render.viewport(...prosperon.camera.view());
|
||||||
|
render.use_shader(render.postshader);
|
||||||
|
render.use_mat({diffuse:prosperon.screencolor});
|
||||||
|
render.draw(shape.quad);
|
||||||
|
|
||||||
|
profile.endframe();
|
||||||
|
|
||||||
|
profile.frame("app");
|
||||||
|
|
||||||
|
// Flush & render
|
||||||
|
prosperon.appcam.transform.pos = [window.size.x/2, window.size.y/2, -100];
|
||||||
|
prosperon.appcam.size = window.size.slice();
|
||||||
|
if (os.sys() !== 'macos')
|
||||||
|
prosperon.appcam.size.y *= -1;
|
||||||
|
|
||||||
|
render.set_camera(prosperon.appcam);
|
||||||
|
render.viewport(...prosperon.appcam.view());
|
||||||
|
|
||||||
|
// Call gui functions
|
||||||
|
mum.style = mum.dbg_style;
|
||||||
|
prosperon.gui();
|
||||||
|
if (mum.drawinput) mum.drawinput();
|
||||||
|
prosperon.gui_dbg();
|
||||||
|
render.flush_text();
|
||||||
|
mum.style = mum.base;
|
||||||
|
|
||||||
|
profile.endframe();
|
||||||
|
|
||||||
|
profile.frame("imgui");
|
||||||
|
|
||||||
|
render.imgui_new(window.size.x, window.size.y, 0.01);
|
||||||
|
prosperon.imgui();
|
||||||
|
render.imgui_end();
|
||||||
|
|
||||||
|
profile.endframe();
|
||||||
|
|
||||||
|
render.end_pass();
|
||||||
|
render.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
prosperon.process = function process() {
|
||||||
|
profile.frame("frame");
|
||||||
|
var dt = profile.secs(profile.now()) - frame_t;
|
||||||
|
frame_t = profile.secs(profile.now());
|
||||||
|
|
||||||
|
profile.frame("app update");
|
||||||
|
prosperon.appupdate(dt);
|
||||||
|
profile.endframe();
|
||||||
|
|
||||||
|
profile.frame("input");
|
||||||
|
input.procdown();
|
||||||
|
profile.endframe();
|
||||||
|
|
||||||
|
if (sim.mode === "play" || sim.mode === "step") {
|
||||||
|
profile.frame("update");
|
||||||
|
prosperon.update(dt * game.timescale);
|
||||||
|
profile.endframe();
|
||||||
|
if (sim.mode === "step") sim.pause();
|
||||||
|
|
||||||
|
profile.frame("physics");
|
||||||
|
physlag += dt;
|
||||||
|
|
||||||
|
while (physlag > physics.delta) {
|
||||||
|
physlag -= physics.delta;
|
||||||
|
prosperon.phys2d_step(physics.delta * game.timescale);
|
||||||
|
prosperon.physupdate(physics.delta * game.timescale);
|
||||||
|
}
|
||||||
|
profile.endframe();
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.frame("render");
|
||||||
|
prosperon.window_render(window.size);
|
||||||
|
prosperon.render();
|
||||||
|
profile.endframe();
|
||||||
|
|
||||||
|
profile.endframe();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {render};
|
return {render};
|
||||||
|
|
|
@ -14,8 +14,10 @@ if (os.sys() === 'macos') {
|
||||||
appy.inputs['S-g'] = os.gc;
|
appy.inputs['S-g'] = os.gc;
|
||||||
}
|
}
|
||||||
|
|
||||||
appy.inputs.f12 = function() { mum.debug = !mum.debug; }
|
//appy.inputs.f12 = function() { mum.debug = !mum.debug; }
|
||||||
|
appy.inputs.f12 = function() { profile.cpu_frame(); }
|
||||||
appy.inputs.f11 = window.toggle_fullscreen;
|
appy.inputs.f11 = window.toggle_fullscreen;
|
||||||
|
appy.inputs.f10 = function() { profile.toggle_frame_avg(); }
|
||||||
appy.inputs['M-f4'] = prosperon.quit;
|
appy.inputs['M-f4'] = prosperon.quit;
|
||||||
|
|
||||||
player[0].control(appy);
|
player[0].control(appy);
|
||||||
|
|
|
@ -103,19 +103,22 @@ Ease.elastic = {
|
||||||
Ease.elastic.c4 = 2*Math.PI/3;
|
Ease.elastic.c4 = 2*Math.PI/3;
|
||||||
Ease.elastic.c5 = 2*Math.PI / 4.5;
|
Ease.elastic.c5 = 2*Math.PI / 4.5;
|
||||||
|
|
||||||
var tween = function(obj, val, to, time)
|
var tween = function(from, to, time, fn)
|
||||||
{
|
{
|
||||||
var start = profile.secs(profile.now());
|
var start = profile.secs(profile.now());
|
||||||
var startval = obj[val];
|
|
||||||
var update = function(dt) {
|
var update = function(dt) {
|
||||||
|
profile.frame("tween");
|
||||||
var elapsed = profile.secs(profile.now()) - start;
|
var elapsed = profile.secs(profile.now()) - start;
|
||||||
obj[val] = startval.lerp(to, elapsed/time);
|
fn(from.lerp(to,elapsed/time));
|
||||||
if (elapsed >= time) {
|
if (elapsed >= time) {
|
||||||
obj[val] = to;
|
fn(to);
|
||||||
|
if (stop.then) stop.then();
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
profile.endframe();
|
||||||
};
|
};
|
||||||
var stop = Register.update.register(update);
|
var stop = Register.update.register(update);
|
||||||
|
return stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
var Tween = {
|
var Tween = {
|
||||||
|
|
|
@ -171,7 +171,7 @@ var listpanel = Object.copy(inputpanel, {
|
||||||
|
|
||||||
keycb() {
|
keycb() {
|
||||||
if(this.value)
|
if(this.value)
|
||||||
this.assets = this.allassets.filter(x => x.startswith(this.value));
|
this.assets = this.allassets.filter(x => x.startsWith(this.value));
|
||||||
else
|
else
|
||||||
this.assets = this.allassets.slice();
|
this.assets = this.allassets.slice();
|
||||||
for (var m in this.mumlist)
|
for (var m in this.mumlist)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#blend mix
|
#blend mix
|
||||||
|
#depth off
|
||||||
#primitive triangle
|
#primitive triangle
|
||||||
#cull none
|
#cull none
|
||||||
#depth off
|
|
||||||
|
|
||||||
@vs vs
|
@vs vs
|
||||||
in vec3 a_pos;
|
in vec3 a_pos;
|
||||||
|
|
49
shaders/baseparticle.cg
Normal file
49
shaders/baseparticle.cg
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#depth off
|
||||||
|
#blend mix
|
||||||
|
|
||||||
|
@vs vs
|
||||||
|
in vec2 a_pos;
|
||||||
|
in vec2 a_uv;
|
||||||
|
|
||||||
|
uniform vec2 diffuse_size;
|
||||||
|
|
||||||
|
struct particle {
|
||||||
|
mat4 model;
|
||||||
|
vec4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
readonly buffer ssbo {
|
||||||
|
particle par[];
|
||||||
|
};
|
||||||
|
|
||||||
|
out vec2 uv;
|
||||||
|
out vec4 color0;
|
||||||
|
|
||||||
|
uniform mat4 vp;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
particle p = par[gl_InstanceIndex];
|
||||||
|
gl_Position = vp * p.model * vec4(a_pos, 0.0, 1.0);
|
||||||
|
uv = a_uv;
|
||||||
|
color0 = p.color;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@fs fs
|
||||||
|
in vec2 uv;
|
||||||
|
|
||||||
|
in vec4 color0;
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
texture2D diffuse;
|
||||||
|
sampler smp;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
color = texture(sampler2D(diffuse,smp),uv);
|
||||||
|
color *= color0;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@program text vs fs
|
|
@ -1,5 +1,5 @@
|
||||||
#blend mix
|
|
||||||
#depth off
|
#depth off
|
||||||
|
#blend mix
|
||||||
#primitive triangle
|
#primitive triangle
|
||||||
#cull none
|
#cull none
|
||||||
|
|
||||||
|
|
37
shaders/poly_ssbo.cg
Normal file
37
shaders/poly_ssbo.cg
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#depth off
|
||||||
|
#blend mix
|
||||||
|
#primitive triangle
|
||||||
|
#cull none
|
||||||
|
|
||||||
|
@vs vs
|
||||||
|
in vec3 a_pos;
|
||||||
|
uniform mat4 vp;
|
||||||
|
out vec4 shade;
|
||||||
|
|
||||||
|
struct poly {
|
||||||
|
mat4 model;
|
||||||
|
vec4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
readonly buffer ssbo {
|
||||||
|
poly polys[];
|
||||||
|
};
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
poly p = polys[gl_InstanceIndex];
|
||||||
|
gl_Position = vp * p.model * vec4(a_pos, 1);
|
||||||
|
shade = p.color;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@fs fs
|
||||||
|
|
||||||
|
in vec4 shade;
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
color = shade;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@program sprite vs fs
|
|
@ -13,7 +13,6 @@ uniform vec4 shade;
|
||||||
void frag()
|
void frag()
|
||||||
{
|
{
|
||||||
color = texture(sampler2D(diffuse,smp), uv);
|
color = texture(sampler2D(diffuse,smp), uv);
|
||||||
if (color.a < 0.1) discard;
|
|
||||||
color *= shade;
|
color *= shade;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
60
shaders/sprite_ssbo.cg
Normal file
60
shaders/sprite_ssbo.cg
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#blend mix
|
||||||
|
#depth off
|
||||||
|
#primitive triangle
|
||||||
|
#cull none
|
||||||
|
|
||||||
|
@vs vs
|
||||||
|
in vec3 a_pos;
|
||||||
|
in vec2 a_uv;
|
||||||
|
out vec2 uv;
|
||||||
|
|
||||||
|
vec3 pos;
|
||||||
|
|
||||||
|
struct sprite {
|
||||||
|
mat4 model;
|
||||||
|
vec4 rect;
|
||||||
|
};
|
||||||
|
|
||||||
|
readonly buffer ssbo {
|
||||||
|
sprite sprites[];
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform mat4 projection;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 vp;
|
||||||
|
uniform vec2 diffuse_size;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
sprite s = sprites[gl_InstanceIndex];
|
||||||
|
pos = a_pos;
|
||||||
|
uv = a_uv;
|
||||||
|
pos *= vec3(diffuse_size * s.rect.zw,1);
|
||||||
|
uv = (uv*s.rect.zw)+s.rect.xy;
|
||||||
|
gl_Position = vp * s.model * vec4(pos, 1.0);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@fs fs
|
||||||
|
|
||||||
|
in vec2 uv;
|
||||||
|
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
texture2D diffuse;
|
||||||
|
sampler smp;
|
||||||
|
|
||||||
|
uniform vec4 shade;
|
||||||
|
void frag()
|
||||||
|
{
|
||||||
|
color = texture(sampler2D(diffuse,smp), uv);
|
||||||
|
color *= shade;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
frag();
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@program sprite vs fs
|
|
@ -3,6 +3,7 @@
|
||||||
const HMM_Vec2 v2zero = {0,0};
|
const HMM_Vec2 v2zero = {0,0};
|
||||||
const HMM_Vec2 v2one = {1,1};
|
const HMM_Vec2 v2one = {1,1};
|
||||||
const HMM_Vec3 v3zero = {0,0,0};
|
const HMM_Vec3 v3zero = {0,0,0};
|
||||||
|
const HMM_Vec3 v3one = {1,1,1};
|
||||||
const HMM_Vec4 v4zero = {0,0,0,0};
|
const HMM_Vec4 v4zero = {0,0,0,0};
|
||||||
|
|
||||||
const HMM_Vec3 vX = {1.0,0.0,0.0};
|
const HMM_Vec3 vX = {1.0,0.0,0.0};
|
||||||
|
@ -17,7 +18,7 @@ const HMM_Vec3 vLEFT = {-1,0,0};
|
||||||
const HMM_Vec3 vRIGHT = {1,0,0};
|
const HMM_Vec3 vRIGHT = {1,0,0};
|
||||||
|
|
||||||
const HMM_Mat4 MAT1 = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
|
const HMM_Mat4 MAT1 = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
|
||||||
const HMM_Quat QUAT1 = {1,0,0,0};
|
const HMM_Quat QUAT1 = {0,0,0,1};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Angle unit conversion functions
|
* Angle unit conversion functions
|
||||||
|
@ -267,11 +268,6 @@ HMM_Vec4 HMM_SubV4(HMM_Vec4 Left, HMM_Vec4 Right) {
|
||||||
return HMM_V2(v.X*s, v.Y*s);
|
return HMM_V2(v.X*s, v.Y*s);
|
||||||
}
|
}
|
||||||
|
|
||||||
HMM_Vec3 HMM_ScaleV3(HMM_Vec3 v, double s)
|
|
||||||
{
|
|
||||||
return HMM_V3(v.x*s,v.y*s,v.z*s);
|
|
||||||
}
|
|
||||||
|
|
||||||
HMM_Vec2 HMM_MulV2(HMM_Vec2 Left, HMM_Vec2 Right) {
|
HMM_Vec2 HMM_MulV2(HMM_Vec2 Left, HMM_Vec2 Right) {
|
||||||
|
|
||||||
HMM_Vec2 Result;
|
HMM_Vec2 Result;
|
||||||
|
@ -529,7 +525,6 @@ float HMM_AngleV4(HMM_Vec4 a, HMM_Vec4 b)
|
||||||
}
|
}
|
||||||
|
|
||||||
HMM_Vec2 HMM_NormV2(HMM_Vec2 A) {
|
HMM_Vec2 HMM_NormV2(HMM_Vec2 A) {
|
||||||
// HMM_MulV2F(A, 1.0/HMM_LenV2(A)+FLOAT_MIN);
|
|
||||||
return HMM_MulV2F(A, HMM_InvSqrtF(HMM_DotV2(A, A)));
|
return HMM_MulV2F(A, HMM_InvSqrtF(HMM_DotV2(A, A)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1769,11 +1764,6 @@ HMM_Mat4 HMM_QToM4(HMM_Quat Left) {
|
||||||
|
|
||||||
HMM_Mat4 HMM_M4TRS(HMM_Vec3 t, HMM_Quat q, HMM_Vec3 s)
|
HMM_Mat4 HMM_M4TRS(HMM_Vec3 t, HMM_Quat q, HMM_Vec3 s)
|
||||||
{
|
{
|
||||||
HMM_Mat4 T = HMM_Translate(t);
|
|
||||||
HMM_Mat4 R = HMM_QToM4(q);
|
|
||||||
HMM_Mat4 S = HMM_Scale(s);
|
|
||||||
return HMM_MulM4(T, HMM_MulM4(R, S));
|
|
||||||
//return HMM_MulM4(T,S);
|
|
||||||
HMM_Mat4 l;
|
HMM_Mat4 l;
|
||||||
float *lm = (float*)&l;
|
float *lm = (float*)&l;
|
||||||
|
|
||||||
|
|
|
@ -416,6 +416,7 @@ typedef union HMM_Mat4 {
|
||||||
extern const HMM_Vec2 v2zero;
|
extern const HMM_Vec2 v2zero;
|
||||||
extern const HMM_Vec2 v2one;
|
extern const HMM_Vec2 v2one;
|
||||||
extern const HMM_Vec3 v3zero;
|
extern const HMM_Vec3 v3zero;
|
||||||
|
extern const HMM_Vec3 v3one;
|
||||||
extern const HMM_Vec4 v4zero;
|
extern const HMM_Vec4 v4zero;
|
||||||
|
|
||||||
typedef signed int HMM_Bool;
|
typedef signed int HMM_Bool;
|
||||||
|
@ -477,7 +478,6 @@ HMM_Vec4 HMM_AddV4(HMM_Vec4 Left, HMM_Vec4 Right);
|
||||||
HMM_Vec2 HMM_SubV2(HMM_Vec2 Left, HMM_Vec2 Right);
|
HMM_Vec2 HMM_SubV2(HMM_Vec2 Left, HMM_Vec2 Right);
|
||||||
HMM_Vec3 HMM_SubV3(HMM_Vec3 Left, HMM_Vec3 Right);
|
HMM_Vec3 HMM_SubV3(HMM_Vec3 Left, HMM_Vec3 Right);
|
||||||
HMM_Vec4 HMM_SubV4(HMM_Vec4 Left, HMM_Vec4 Right);
|
HMM_Vec4 HMM_SubV4(HMM_Vec4 Left, HMM_Vec4 Right);
|
||||||
HMM_Vec3 HMM_ScaleV3(HMM_Vec3 v, double s);
|
|
||||||
HMM_Vec2 HMM_MulV2(HMM_Vec2 Left, HMM_Vec2 Right);
|
HMM_Vec2 HMM_MulV2(HMM_Vec2 Left, HMM_Vec2 Right);
|
||||||
HMM_Vec2 HMM_MulV2F(HMM_Vec2 Left, float Right);
|
HMM_Vec2 HMM_MulV2F(HMM_Vec2 Left, float Right);
|
||||||
HMM_Vec3 HMM_MulV3(HMM_Vec3 Left, HMM_Vec3 Right);
|
HMM_Vec3 HMM_MulV3(HMM_Vec3 Left, HMM_Vec3 Right);
|
||||||
|
|
|
@ -20,8 +20,6 @@
|
||||||
|
|
||||||
struct sFont *use_font;
|
struct sFont *use_font;
|
||||||
|
|
||||||
sg_buffer text_ssbo;
|
|
||||||
|
|
||||||
struct text_vert {
|
struct text_vert {
|
||||||
HMM_Vec2 pos;
|
HMM_Vec2 pos;
|
||||||
HMM_Vec2 wh;
|
HMM_Vec2 wh;
|
||||||
|
@ -32,15 +30,6 @@ struct text_vert {
|
||||||
|
|
||||||
static struct text_vert *text_buffer;
|
static struct text_vert *text_buffer;
|
||||||
|
|
||||||
void font_init() {
|
|
||||||
text_ssbo = sg_make_buffer(&(sg_buffer_desc){
|
|
||||||
.size = sizeof(struct text_vert),
|
|
||||||
.type = SG_BUFFERTYPE_STORAGEBUFFER,
|
|
||||||
.usage = SG_USAGE_STREAM,
|
|
||||||
.label = "text buffer"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void font_free(font *f)
|
void font_free(font *f)
|
||||||
{
|
{
|
||||||
sg_destroy_image(f->texID);
|
sg_destroy_image(f->texID);
|
||||||
|
@ -115,7 +104,6 @@ struct sFont *MakeFont(const char *fontfile, int height) {
|
||||||
newfont->descent = descent*emscale;
|
newfont->descent = descent*emscale;
|
||||||
newfont->linegap = linegap*emscale;
|
newfont->linegap = linegap*emscale;
|
||||||
newfont->linegap = ((newfont->ascent - newfont->descent) - newfont->linegap);
|
newfont->linegap = ((newfont->ascent - newfont->descent) - newfont->linegap);
|
||||||
printf("newfont : %g, %g, %g\n", newfont->ascent, newfont->descent, newfont->linegap);
|
|
||||||
|
|
||||||
newfont->texture = malloc(sizeof(texture));
|
newfont->texture = malloc(sizeof(texture));
|
||||||
newfont->texture->id = sg_make_image(&(sg_image_desc){
|
newfont->texture->id = sg_make_image(&(sg_image_desc){
|
||||||
|
@ -177,15 +165,15 @@ void draw_char_box(struct Character c, HMM_Vec2 cursor, float scale, struct rgba
|
||||||
b.y = cursor.Y + wh.y/2;
|
b.y = cursor.Y + wh.y/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int text_flush() {
|
int text_flush(sg_buffer *buf) {
|
||||||
if (arrlen(text_buffer) == 0) return 0;
|
if (arrlen(text_buffer) == 0) return 0;
|
||||||
|
|
||||||
sg_range verts;
|
sg_range verts;
|
||||||
verts.ptr = text_buffer;
|
verts.ptr = text_buffer;
|
||||||
verts.size = sizeof(struct text_vert) * arrlen(text_buffer);
|
verts.size = sizeof(struct text_vert) * arrlen(text_buffer);
|
||||||
if (sg_query_buffer_will_overflow(text_ssbo, verts.size)) {
|
if (sg_query_buffer_will_overflow(*buf, verts.size)) {
|
||||||
sg_destroy_buffer(text_ssbo);
|
sg_destroy_buffer(*buf);
|
||||||
text_ssbo = sg_make_buffer(&(sg_buffer_desc){
|
*buf = sg_make_buffer(&(sg_buffer_desc){
|
||||||
.size = verts.size,
|
.size = verts.size,
|
||||||
.type = SG_BUFFERTYPE_STORAGEBUFFER,
|
.type = SG_BUFFERTYPE_STORAGEBUFFER,
|
||||||
.usage = SG_USAGE_STREAM,
|
.usage = SG_USAGE_STREAM,
|
||||||
|
@ -193,7 +181,7 @@ int text_flush() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sg_append_buffer(text_ssbo, &verts);
|
sg_append_buffer(*buf, &verts);
|
||||||
int n = arrlen(text_buffer);
|
int n = arrlen(text_buffer);
|
||||||
arrsetlen(text_buffer, 0);
|
arrsetlen(text_buffer, 0);
|
||||||
return n;
|
return n;
|
||||||
|
|
|
@ -34,7 +34,6 @@ typedef struct sFont font;
|
||||||
|
|
||||||
void font_free(font *f);
|
void font_free(font *f);
|
||||||
|
|
||||||
void font_init();
|
|
||||||
struct sFont *MakeFont(const char *fontfile, int height);
|
struct sFont *MakeFont(const char *fontfile, int height);
|
||||||
void font_set(font *f);
|
void font_set(font *f);
|
||||||
void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgba color);
|
void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgba color);
|
||||||
|
@ -42,6 +41,6 @@ void text_settype(struct sFont *font);
|
||||||
struct boundingbox text_bb(const char *text, float scale, float lw, float tracking);
|
struct boundingbox text_bb(const char *text, float scale, float lw, float tracking);
|
||||||
int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, float lw, int caret, float tracking);
|
int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, float lw, int caret, float tracking);
|
||||||
|
|
||||||
int text_flush();
|
int text_flush(sg_buffer *buf);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "sokol/sokol_app.h"
|
#include "sokol/sokol_app.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
#include "implot.h"
|
||||||
#define SOKOL_IMPL
|
#define SOKOL_IMPL
|
||||||
#include "sokol/util/sokol_imgui.h"
|
#include "sokol/util/sokol_imgui.h"
|
||||||
#include "sokol/util/sokol_gfx_imgui.h"
|
#include "sokol/util/sokol_gfx_imgui.h"
|
||||||
|
@ -37,6 +38,22 @@ JSC_CCALL(imgui_menuitem,
|
||||||
free(hotkey);
|
free(hotkey);
|
||||||
)
|
)
|
||||||
|
|
||||||
|
JSC_SCALL(imgui_startplot,
|
||||||
|
ImPlot::SetNextAxisToFit(ImAxis_X1);
|
||||||
|
ImPlot::SetNextAxisToFit(ImAxis_Y1);
|
||||||
|
ImPlot::BeginPlot(str);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(imgui_endplot, ImPlot::EndPlot() )
|
||||||
|
|
||||||
|
JSC_SCALL(imgui_lineplot,
|
||||||
|
double data[js_arrlen(argv[1])];
|
||||||
|
for (int i = 0; i < js_arrlen(argv[1]); i++)
|
||||||
|
data[i] = js2number(js_getpropidx(argv[1], i));
|
||||||
|
|
||||||
|
ImPlot::PlotLine(str, data, js_arrlen(argv[1]));
|
||||||
|
)
|
||||||
|
|
||||||
JSC_CCALL(imgui_beginmenubar, ImGui::BeginMenuBar())
|
JSC_CCALL(imgui_beginmenubar, ImGui::BeginMenuBar())
|
||||||
JSC_CCALL(imgui_endmenubar, ImGui::EndMenuBar())
|
JSC_CCALL(imgui_endmenubar, ImGui::EndMenuBar())
|
||||||
|
|
||||||
|
@ -55,6 +72,9 @@ static const JSCFunctionListEntry js_imgui_funcs[] = {
|
||||||
MIST_FUNC_DEF(imgui, beginmenubar, 0),
|
MIST_FUNC_DEF(imgui, beginmenubar, 0),
|
||||||
MIST_FUNC_DEF(imgui, endmenubar, 0),
|
MIST_FUNC_DEF(imgui, endmenubar, 0),
|
||||||
MIST_FUNC_DEF(imgui, textinput, 2),
|
MIST_FUNC_DEF(imgui, textinput, 2),
|
||||||
|
MIST_FUNC_DEF(imgui, startplot,1),
|
||||||
|
MIST_FUNC_DEF(imgui,endplot,0),
|
||||||
|
MIST_FUNC_DEF(imgui,lineplot,2)
|
||||||
};
|
};
|
||||||
|
|
||||||
static int started = 0;
|
static int started = 0;
|
||||||
|
@ -67,6 +87,8 @@ JSValue gui_init(JSContext *js)
|
||||||
sgimgui_desc_t desc = {0};
|
sgimgui_desc_t desc = {0};
|
||||||
sgimgui_init(&sgimgui, &desc);
|
sgimgui_init(&sgimgui, &desc);
|
||||||
|
|
||||||
|
ImPlot::CreateContext();
|
||||||
|
|
||||||
JSValue imgui = JS_NewObject(js);
|
JSValue imgui = JS_NewObject(js);
|
||||||
JS_SetPropertyFunctionList(js, imgui, js_imgui_funcs, countof(js_imgui_funcs));
|
JS_SetPropertyFunctionList(js, imgui, js_imgui_funcs, countof(js_imgui_funcs));
|
||||||
started = 1;
|
started = 1;
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "spline.h"
|
#include "spline.h"
|
||||||
#include "yugine.h"
|
#include "yugine.h"
|
||||||
#include "particle.h"
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
#include <sokol/sokol_time.h>
|
#include <sokol/sokol_time.h>
|
||||||
|
@ -35,6 +34,7 @@
|
||||||
#include "sokol_glue.h"
|
#include "sokol_glue.h"
|
||||||
#include <chipmunk/chipmunk_unsafe.h>
|
#include <chipmunk/chipmunk_unsafe.h>
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
#if (defined(_WIN32) || defined(__WIN32__))
|
#if (defined(_WIN32) || defined(__WIN32__))
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
|
@ -96,7 +96,6 @@ void cpConstraint_free(cpConstraint *c)
|
||||||
void jsfreestr(const char *s) { JS_FreeCString(js, s); }
|
void jsfreestr(const char *s) { JS_FreeCString(js, s); }
|
||||||
QJSCLASS(gameobject)
|
QJSCLASS(gameobject)
|
||||||
QJSCLASS(transform)
|
QJSCLASS(transform)
|
||||||
QJSCLASS(emitter)
|
|
||||||
QJSCLASS(dsp_node)
|
QJSCLASS(dsp_node)
|
||||||
QJSCLASS(texture)
|
QJSCLASS(texture)
|
||||||
QJSCLASS(font)
|
QJSCLASS(font)
|
||||||
|
@ -107,6 +106,7 @@ QJSCLASS(sg_buffer)
|
||||||
QJSCLASS(datastream)
|
QJSCLASS(datastream)
|
||||||
QJSCLASS(cpShape)
|
QJSCLASS(cpShape)
|
||||||
QJSCLASS(cpConstraint)
|
QJSCLASS(cpConstraint)
|
||||||
|
QJSCLASS(timer)
|
||||||
|
|
||||||
static JSValue js_circle2d;
|
static JSValue js_circle2d;
|
||||||
static JSValue js_poly2d;
|
static JSValue js_poly2d;
|
||||||
|
@ -661,32 +661,20 @@ sg_bindings js2bind(JSValue v)
|
||||||
return bind;
|
return bind;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSC_GETSET(emitter, life, number)
|
JSC_CCALL(render_flushtext,
|
||||||
JSC_GETSET(emitter, life_var, number)
|
sg_buffer *buf = js2sg_buffer(argv[0]);
|
||||||
JSC_GETSET(emitter, speed, number)
|
int amt = text_flush(buf);
|
||||||
JSC_GETSET(emitter, variation, number)
|
return number2js(amt);
|
||||||
JSC_GETSET(emitter, divergence, number)
|
|
||||||
JSC_GETSET(emitter, scale, number)
|
|
||||||
JSC_GETSET(emitter, scale_var, number)
|
|
||||||
JSC_GETSET(emitter, grow_for, number)
|
|
||||||
JSC_GETSET(emitter, shrink_for, number)
|
|
||||||
JSC_GETSET(emitter, max, number)
|
|
||||||
JSC_GETSET(emitter, explosiveness, number)
|
|
||||||
JSC_GETSET(emitter, bounce, number)
|
|
||||||
JSC_GETSET(emitter, collision_mask, bitmask)
|
|
||||||
JSC_GETSET(emitter, die_after_collision, boolean)
|
|
||||||
JSC_GETSET(emitter, persist, number)
|
|
||||||
JSC_GETSET(emitter, persist_var, number)
|
|
||||||
JSC_GETSET(emitter, warp_mask, bitmask)
|
|
||||||
JSC_CCALL(emitter_emit, emitter_emit(js2emitter(self), js2number(argv[0]), js2transform(argv[1])))
|
|
||||||
JSC_CCALL(emitter_step, emitter_step(js2emitter(self), js2number(argv[0]), js2transform(argv[1])))
|
|
||||||
JSC_CCALL(emitter_draw,
|
|
||||||
emitter_draw(js2emitter(self));
|
|
||||||
return number2js(arrlen(js2emitter(self)->verts));
|
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(render_flushtext,
|
JSC_CCALL(render_make_textssbo,
|
||||||
return number2js(text_flush());
|
sg_buffer *b = malloc(sizeof(*b));
|
||||||
|
*b = sg_make_buffer(&(sg_buffer_desc){
|
||||||
|
.type = SG_BUFFERTYPE_STORAGEBUFFER,
|
||||||
|
.size = 4,
|
||||||
|
.usage = SG_USAGE_STREAM
|
||||||
|
});
|
||||||
|
return sg_buffer2js(b);
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(render_glue_pass,
|
JSC_CCALL(render_glue_pass,
|
||||||
|
@ -934,15 +922,15 @@ JSC_CCALL(render_setunim4,
|
||||||
JSValue arr = argv[2];
|
JSValue arr = argv[2];
|
||||||
int n = js_arrlen(arr);
|
int n = js_arrlen(arr);
|
||||||
if (n == 1)
|
if (n == 1)
|
||||||
m = transform2mat(*js2transform(js_getpropidx(arr,0)));
|
m = transform2mat(js2transform(js_getpropidx(arr,0)));
|
||||||
else {
|
else {
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
HMM_Mat4 p = transform2mat(*js2transform(js_getpropidx(arr, i)));
|
HMM_Mat4 p = transform2mat(js2transform(js_getpropidx(arr, i)));
|
||||||
m = HMM_MulM4(p,m);
|
m = HMM_MulM4(p,m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!JS_IsUndefined(argv[2]))
|
} else if (!JS_IsUndefined(argv[2]))
|
||||||
m = transform2mat(*js2transform(argv[2]));
|
m = transform2mat(js2transform(argv[2]));
|
||||||
|
|
||||||
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(m.e));
|
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(m.e));
|
||||||
);
|
);
|
||||||
|
@ -952,24 +940,101 @@ JSC_CCALL(render_setbind,
|
||||||
sg_apply_bindings(&bind);
|
sg_apply_bindings(&bind);
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(render_make_t_ssbo,
|
typedef struct particle_ss {
|
||||||
JSValue array = argv[0];
|
HMM_Mat4 model;
|
||||||
HMM_Mat4 ms[js_arrlen(array)];
|
HMM_Vec4 color;
|
||||||
for (int i = 0; i < js_arrlen(array); i++)
|
} particle_ss;
|
||||||
ms[i] = transform2mat(*js2transform(js_getpropidx(array, i)));
|
|
||||||
|
|
||||||
sg_buffer *rr = malloc(sizeof(sg_buffer));
|
JSC_CCALL(render_make_particle_ssbo,
|
||||||
*rr = sg_make_buffer(&(sg_buffer_desc){
|
JSValue array = argv[0];
|
||||||
.data = {
|
size_t size = js_arrlen(array)*(sizeof(particle_ss));
|
||||||
.ptr = ms,
|
sg_buffer *b = js2sg_buffer(argv[1]);
|
||||||
.size = sizeof(HMM_Mat4)*js_arrlen(array),
|
if (!b) return JS_UNDEFINED;
|
||||||
},
|
|
||||||
|
particle_ss ms[js_arrlen(array)];
|
||||||
|
|
||||||
|
if (sg_query_buffer_will_overflow(*b, size)) {
|
||||||
|
sg_destroy_buffer(*b);
|
||||||
|
*b = sg_make_buffer(&(sg_buffer_desc){
|
||||||
.type = SG_BUFFERTYPE_STORAGEBUFFER,
|
.type = SG_BUFFERTYPE_STORAGEBUFFER,
|
||||||
.usage = SG_USAGE_IMMUTABLE,
|
.size = size,
|
||||||
|
.usage = SG_USAGE_STREAM,
|
||||||
.label = "transform buffer"
|
.label = "transform buffer"
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return sg_buffer2js(rr);
|
for (int i = 0; i < js_arrlen(array); i++) {
|
||||||
|
JSValue sub = js_getpropidx(array,i);
|
||||||
|
ms[i].model = transform2mat(js2transform(js_getpropstr(sub, "transform")));
|
||||||
|
ms[i].color = js2vec4(js_getpropstr(sub,"color"));
|
||||||
|
}
|
||||||
|
|
||||||
|
sg_append_buffer(*b, (&(sg_range){
|
||||||
|
.ptr = ms,
|
||||||
|
.size = size
|
||||||
|
}));
|
||||||
|
)
|
||||||
|
|
||||||
|
typedef struct sprite_ss {
|
||||||
|
HMM_Mat4 model;
|
||||||
|
HMM_Vec4 rect;
|
||||||
|
} sprite_ss;
|
||||||
|
|
||||||
|
JSC_CCALL(render_make_sprite_ssbo,
|
||||||
|
JSValue array = argv[0];
|
||||||
|
size_t size = js_arrlen(array)*(sizeof(sprite_ss));
|
||||||
|
sg_buffer *b = js2sg_buffer(argv[1]);
|
||||||
|
if (!b) return JS_UNDEFINED;
|
||||||
|
|
||||||
|
sprite_ss ms[js_arrlen(array)];
|
||||||
|
|
||||||
|
if (sg_query_buffer_will_overflow(*b, size)) {
|
||||||
|
sg_destroy_buffer(*b);
|
||||||
|
*b = sg_make_buffer(&(sg_buffer_desc){
|
||||||
|
.type = SG_BUFFERTYPE_STORAGEBUFFER,
|
||||||
|
.size = size,
|
||||||
|
.usage = SG_USAGE_STREAM,
|
||||||
|
.label = "transform buffer"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < js_arrlen(array); i++) {
|
||||||
|
JSValue sub = js_getpropidx(array,i);
|
||||||
|
ms[i].model = transform2mat(js2transform(js_getpropstr(sub, "transform")));
|
||||||
|
ms[i].rect = js2vec4(js_getpropstr(sub,"rect"));
|
||||||
|
}
|
||||||
|
|
||||||
|
sg_append_buffer(*b, (&(sg_range){
|
||||||
|
.ptr = ms,
|
||||||
|
.size = size
|
||||||
|
}));
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(render_make_t_ssbo,
|
||||||
|
JSValue array = argv[0];
|
||||||
|
size_t size = js_arrlen(array)*sizeof(HMM_Mat4);
|
||||||
|
sg_buffer *b = js2sg_buffer(argv[1]);
|
||||||
|
if (!b) return JS_UNDEFINED;
|
||||||
|
|
||||||
|
HMM_Mat4 ms[js_arrlen(array)];
|
||||||
|
|
||||||
|
if (sg_query_buffer_will_overflow(*b, size)) {
|
||||||
|
sg_destroy_buffer(*b);
|
||||||
|
*b = sg_make_buffer(&(sg_buffer_desc){
|
||||||
|
.type = SG_BUFFERTYPE_STORAGEBUFFER,
|
||||||
|
.size = size,
|
||||||
|
.usage = SG_USAGE_STREAM,
|
||||||
|
.label = "transform buffer"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < js_arrlen(array); i++)
|
||||||
|
ms[i] = transform2mat(js2transform(js_getpropidx(array, i)));
|
||||||
|
|
||||||
|
sg_append_buffer(*b, (&(sg_range){
|
||||||
|
.ptr = ms,
|
||||||
|
.size = size
|
||||||
|
}));
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(render_spdraw,
|
JSC_CCALL(render_spdraw,
|
||||||
|
@ -982,7 +1047,6 @@ JSC_CCALL(render_setpipeline,
|
||||||
sg_apply_pipeline(p);
|
sg_apply_pipeline(p);
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(render_text_ssbo, return sg_buffer2js(&text_ssbo))
|
|
||||||
JSC_CCALL(render_screencolor,
|
JSC_CCALL(render_screencolor,
|
||||||
texture *t = calloc(sizeof(*t), 1);
|
texture *t = calloc(sizeof(*t), 1);
|
||||||
t->id = screencolor;
|
t->id = screencolor;
|
||||||
|
@ -996,14 +1060,14 @@ JSC_CCALL(render_imgui_end, gui_endframe())
|
||||||
JSC_CCALL(render_imgui_init, return gui_init(js))
|
JSC_CCALL(render_imgui_init, return gui_init(js))
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_render_funcs[] = {
|
static const JSCFunctionListEntry js_render_funcs[] = {
|
||||||
MIST_FUNC_DEF(render, flushtext, 0),
|
MIST_FUNC_DEF(render, flushtext, 1),
|
||||||
MIST_FUNC_DEF(render, camera_screen2world, 2),
|
MIST_FUNC_DEF(render, camera_screen2world, 2),
|
||||||
|
MIST_FUNC_DEF(render, make_textssbo, 0),
|
||||||
MIST_FUNC_DEF(render, viewport, 4),
|
MIST_FUNC_DEF(render, viewport, 4),
|
||||||
MIST_FUNC_DEF(render, end_pass, 0),
|
MIST_FUNC_DEF(render, end_pass, 0),
|
||||||
MIST_FUNC_DEF(render, commit, 0),
|
MIST_FUNC_DEF(render, commit, 0),
|
||||||
MIST_FUNC_DEF(render, glue_pass, 0),
|
MIST_FUNC_DEF(render, glue_pass, 0),
|
||||||
MIST_FUNC_DEF(render, text_size, 3),
|
MIST_FUNC_DEF(render, text_size, 3),
|
||||||
MIST_FUNC_DEF(render, text_ssbo, 0),
|
|
||||||
MIST_FUNC_DEF(render, set_camera, 1),
|
MIST_FUNC_DEF(render, set_camera, 1),
|
||||||
MIST_FUNC_DEF(render, pipeline, 1),
|
MIST_FUNC_DEF(render, pipeline, 1),
|
||||||
MIST_FUNC_DEF(render, setuniv3, 2),
|
MIST_FUNC_DEF(render, setuniv3, 2),
|
||||||
|
@ -1022,7 +1086,9 @@ static const JSCFunctionListEntry js_render_funcs[] = {
|
||||||
MIST_FUNC_DEF(render, gfx_gui, 0),
|
MIST_FUNC_DEF(render, gfx_gui, 0),
|
||||||
MIST_FUNC_DEF(render, imgui_end, 0),
|
MIST_FUNC_DEF(render, imgui_end, 0),
|
||||||
MIST_FUNC_DEF(render, imgui_init, 0),
|
MIST_FUNC_DEF(render, imgui_init, 0),
|
||||||
MIST_FUNC_DEF(render, make_t_ssbo, 1)
|
MIST_FUNC_DEF(render, make_t_ssbo, 2),
|
||||||
|
MIST_FUNC_DEF(render, make_particle_ssbo, 2),
|
||||||
|
MIST_FUNC_DEF(render, make_sprite_ssbo, 2)
|
||||||
};
|
};
|
||||||
|
|
||||||
JSC_CCALL(gui_scissor, sg_apply_scissor_rect(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0))
|
JSC_CCALL(gui_scissor, sg_apply_scissor_rect(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0))
|
||||||
|
@ -1078,6 +1144,25 @@ JSValue js_vector_dot(JSContext *js, JSValue self, int argc, JSValue *argv) { re
|
||||||
|
|
||||||
JSC_CCALL(vector_project, return vec22js(HMM_ProjV2(js2vec2(argv[0]), js2vec2(argv[1]))))
|
JSC_CCALL(vector_project, return vec22js(HMM_ProjV2(js2vec2(argv[0]), js2vec2(argv[1]))))
|
||||||
|
|
||||||
|
JSC_CCALL(vector_midpoint,
|
||||||
|
HMM_Vec2 a = js2vec2(argv[0]);
|
||||||
|
HMM_Vec2 b = js2vec2(argv[1]);
|
||||||
|
// HMM_Vec2 c = HMM_AddV2(a,b);
|
||||||
|
// c = HMM_DivV2F(c, 2);
|
||||||
|
return vec22js((HMM_Vec2){(a.x+b.x)/2, (a.y+b.y)/2});
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(vector_distance,
|
||||||
|
HMM_Vec2 a = js2vec2(argv[0]);
|
||||||
|
HMM_Vec2 b = js2vec2(argv[1]);
|
||||||
|
return number2js(HMM_DistV2(a,b));
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(vector_angle,
|
||||||
|
HMM_Vec2 a = js2vec2(argv[0]);
|
||||||
|
return angle2js(atan2(a.y,a.x));
|
||||||
|
)
|
||||||
|
|
||||||
/* Given a series of points p, computes a new series with them expanded on either side by d */
|
/* Given a series of points p, computes a new series with them expanded on either side by d */
|
||||||
HMM_Vec2 *inflatepoints(HMM_Vec2 *p, float d, int n)
|
HMM_Vec2 *inflatepoints(HMM_Vec2 *p, float d, int n)
|
||||||
{
|
{
|
||||||
|
@ -1130,10 +1215,261 @@ JSC_CCALL(vector_inflate,
|
||||||
arrfree(p);
|
arrfree(p);
|
||||||
)
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(vector_rotate,
|
||||||
|
HMM_Vec2 vec = js2vec2(argv[0]);
|
||||||
|
float r = HMM_LenV2(vec);
|
||||||
|
double angle = js2angle(argv[1]);
|
||||||
|
angle += atan2(vec.y,vec.x);
|
||||||
|
vec.x = r*cos(angle);
|
||||||
|
vec.y = r*sin(angle);
|
||||||
|
return vec22js(vec);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(vector_add,
|
||||||
|
HMM_Vec4 a = js2vec4(argv[0]);
|
||||||
|
HMM_Vec4 b = js2vec4(argv[1]);
|
||||||
|
HMM_Vec4 c = HMM_AddV4(a,b);
|
||||||
|
return vec42js(c);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(vector_norm,
|
||||||
|
int len = js_arrlen(argv[0]);
|
||||||
|
|
||||||
|
switch(len) {
|
||||||
|
case 2: return vec22js(HMM_NormV2(js2vec2(argv[0])));
|
||||||
|
case 3: return vec32js(HMM_NormV3(js2vec3(argv[0])));
|
||||||
|
case 4: return vec42js(HMM_NormV4(js2vec4(argv[0])));
|
||||||
|
}
|
||||||
|
return argv[0];
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(vector_angle_between,
|
||||||
|
int len = js_arrlen(argv[0]);
|
||||||
|
switch(len) {
|
||||||
|
case 2: return angle2js(HMM_AngleV2(js2vec2(argv[0]), js2vec2(argv[1])));
|
||||||
|
case 3: return angle2js(HMM_AngleV3(js2vec3(argv[0]), js2vec3(argv[1])));
|
||||||
|
case 4: return angle2js(HMM_AngleV4(js2vec4(argv[0]), js2vec4(argv[1])));
|
||||||
|
}
|
||||||
|
return angle2js(0);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(vector_lerp,
|
||||||
|
double s = js2number(argv[0]);
|
||||||
|
double f = js2number(argv[1]);
|
||||||
|
double t = js2number(argv[2]);
|
||||||
|
|
||||||
|
return number2js((f-s)*t+s);
|
||||||
|
)
|
||||||
|
|
||||||
|
int gcd(int a, int b) {
|
||||||
|
if (b == 0)
|
||||||
|
return a;
|
||||||
|
return gcd(b, a % b);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSC_CCALL(vector_gcd,
|
||||||
|
return number2js(gcd(js2number(argv[0]), js2number(argv[1])));
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(vector_lcm,
|
||||||
|
double a = js2number(argv[0]);
|
||||||
|
double b = js2number(argv[1]);
|
||||||
|
return number2js((a*b)/gcd(a,b));
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(vector_clamp,
|
||||||
|
double x = js2number(argv[0]);
|
||||||
|
double l = js2number(argv[1]);
|
||||||
|
double h = js2number(argv[2]);
|
||||||
|
return number2js(x > h ? h : x < l ? l : x);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_SSCALL(vector_trimchr,
|
||||||
|
int len = js2number(js_getpropstr(argv[0], "length"));
|
||||||
|
char *start = str;
|
||||||
|
|
||||||
|
while (*start == *str2)
|
||||||
|
start++;
|
||||||
|
|
||||||
|
char *end = str + len-1;
|
||||||
|
while(*end == *str2)
|
||||||
|
end--;
|
||||||
|
|
||||||
|
ret = JS_NewStringLen(js, start, end-start+1);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(vector_angledist,
|
||||||
|
double a1 = js2number(argv[0]);
|
||||||
|
double a2 = js2number(argv[1]);
|
||||||
|
a1 = fmod(a1,1);
|
||||||
|
a2 = fmod(a2,1);
|
||||||
|
double dist = a2-a1;
|
||||||
|
if (dist == 0) return number2js(dist);
|
||||||
|
if (dist > 0) {
|
||||||
|
if (dist > 0.5) return number2js(dist-1);
|
||||||
|
return number2js(dist);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dist < -0.5) return number2js(dist+1);
|
||||||
|
|
||||||
|
return number2js(dist);
|
||||||
|
)
|
||||||
|
|
||||||
|
double r2()
|
||||||
|
{
|
||||||
|
return (double)rand() / (double)RAND_MAX ;
|
||||||
|
}
|
||||||
|
|
||||||
|
double rand_range(double min, double max) {
|
||||||
|
return r2() * (max-min) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSC_CCALL(vector_variate,
|
||||||
|
double n = js2number(argv[0]);
|
||||||
|
double pct = js2number(argv[1]);
|
||||||
|
|
||||||
|
return number2js(n + (rand_range(-pct,pct)*n));
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(vector_random_range, return number2js(rand_range(js2number(argv[0]), js2number(argv[1]))))
|
||||||
|
|
||||||
|
JSC_CCALL(vector_mean,
|
||||||
|
double len = js_arrlen(argv[0]);
|
||||||
|
double sum;
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
sum += js2number(js_getpropidx(argv[0], i));
|
||||||
|
|
||||||
|
return number2js(sum/len);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(vector_sum,
|
||||||
|
double sum;
|
||||||
|
int len = js_arrlen(argv[0]);
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
sum += js2number(js_getpropidx(argv[0], i));
|
||||||
|
|
||||||
|
return number2js(sum);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(vector_sigma,
|
||||||
|
int len = js_arrlen(argv[0]);
|
||||||
|
double sum;
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
sum += js2number(js_getpropidx(argv[0], i));
|
||||||
|
|
||||||
|
double mean = sum/(double)len;
|
||||||
|
|
||||||
|
double sq_diff = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
double x = js2number(js_getpropidx(argv[0],i));
|
||||||
|
sq_diff += pow(x-mean, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
double variance = sq_diff/((double)len);
|
||||||
|
|
||||||
|
return number2js(sqrt(variance));
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(vector_median,
|
||||||
|
int len = js_arrlen(argv[0]);
|
||||||
|
double arr[len];
|
||||||
|
double temp;
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
arr[i] = js2number(js_getpropidx(argv[0], i));
|
||||||
|
|
||||||
|
for (int i = 0; i < len-1; i++) {
|
||||||
|
for (int j = i+1; j < len; j++) {
|
||||||
|
if (arr[i] > arr[j]) {
|
||||||
|
temp = arr[i];
|
||||||
|
arr[i] = arr[j];
|
||||||
|
arr[j] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len % 2 == 0) return number2js((arr[len/2-1] + arr[len/2])/2.0);
|
||||||
|
return number2js(arr[len/2]);
|
||||||
|
)
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_vector_funcs[] = {
|
static const JSCFunctionListEntry js_vector_funcs[] = {
|
||||||
MIST_FUNC_DEF(vector, dot,2),
|
MIST_FUNC_DEF(vector, dot,2),
|
||||||
MIST_FUNC_DEF(vector, project,2),
|
MIST_FUNC_DEF(vector, project,2),
|
||||||
MIST_FUNC_DEF(vector, inflate, 2)
|
MIST_FUNC_DEF(vector, inflate, 2),
|
||||||
|
MIST_FUNC_DEF(vector, rotate, 2),
|
||||||
|
MIST_FUNC_DEF(vector, add, 2),
|
||||||
|
MIST_FUNC_DEF(vector, midpoint, 2),
|
||||||
|
MIST_FUNC_DEF(vector, distance, 2),
|
||||||
|
MIST_FUNC_DEF(vector, angle, 1),
|
||||||
|
MIST_FUNC_DEF(vector, norm, 1),
|
||||||
|
MIST_FUNC_DEF(vector, angle_between, 2),
|
||||||
|
MIST_FUNC_DEF(vector, lerp, 3),
|
||||||
|
MIST_FUNC_DEF(vector, gcd, 2),
|
||||||
|
MIST_FUNC_DEF(vector, lcm, 2),
|
||||||
|
MIST_FUNC_DEF(vector, clamp, 3),
|
||||||
|
MIST_FUNC_DEF(vector, trimchr, 2),
|
||||||
|
MIST_FUNC_DEF(vector, angledist, 2),
|
||||||
|
MIST_FUNC_DEF(vector, variate, 2),
|
||||||
|
MIST_FUNC_DEF(vector, random_range, 2),
|
||||||
|
MIST_FUNC_DEF(vector, mean, 1),
|
||||||
|
MIST_FUNC_DEF(vector, sum, 1),
|
||||||
|
MIST_FUNC_DEF(vector, sigma, 1),
|
||||||
|
MIST_FUNC_DEF(vector, median, 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
#define JS_HMM_FN(OP, HMM, SIGN) \
|
||||||
|
JSC_CCALL(array_##OP, \
|
||||||
|
int len = js_arrlen(self); \
|
||||||
|
if (!JS_IsArray(js, argv[0])) { \
|
||||||
|
double n = js2number(argv[0]); \
|
||||||
|
JSValue arr = JS_NewArray(js); \
|
||||||
|
for (int i = 0; i < len; i++) \
|
||||||
|
js_setprop_num(arr, i, number2js(js2number(js_getpropidx(self,i)) SIGN n)); \
|
||||||
|
return arr; \
|
||||||
|
} \
|
||||||
|
switch(len) { \
|
||||||
|
case 2: \
|
||||||
|
return vec22js(HMM_##HMM##V2(js2vec2(self), js2vec2(argv[0]))); \
|
||||||
|
case 3: \
|
||||||
|
return vec32js(HMM_##HMM##V3(js2vec3(self), js2vec3(argv[0]))); \
|
||||||
|
case 4: \
|
||||||
|
return vec42js(HMM_##HMM##V4(js2vec4(self), js2vec4(argv[0]))); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
JSValue arr = JS_NewArray(js); \
|
||||||
|
for (int i = 0; i < len; i++) { \
|
||||||
|
double a = js2number(js_getpropidx(self,i)); \
|
||||||
|
double b = js2number(js_getpropidx(argv[0],i)); \
|
||||||
|
js_setprop_num(arr, i, number2js(a SIGN b)); \
|
||||||
|
} \
|
||||||
|
return arr; \
|
||||||
|
) \
|
||||||
|
|
||||||
|
JS_HMM_FN(add, Add, +)
|
||||||
|
JS_HMM_FN(sub, Sub, -)
|
||||||
|
JS_HMM_FN(div, Div, /)
|
||||||
|
JS_HMM_FN(scale, Mul, *)
|
||||||
|
|
||||||
|
JSC_CCALL(array_lerp,
|
||||||
|
int len = js_arrlen(self);
|
||||||
|
JSValue arr = JS_NewArray(js);
|
||||||
|
double t = js2number(argv[1]);
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
double from = js2number(js_getpropidx(self, i));
|
||||||
|
double to = js2number(js_getpropidx(argv[0], i));
|
||||||
|
js_setprop_num(arr, i, number2js((to - from) * t + from));
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
)
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_array_funcs[] = {
|
||||||
|
MIST_FUNC_DEF(array, add, 1),
|
||||||
|
MIST_FUNC_DEF(array, sub, 1),
|
||||||
|
MIST_FUNC_DEF(array, div,1),
|
||||||
|
MIST_FUNC_DEF(array, scale, 1),
|
||||||
|
MIST_FUNC_DEF(array, lerp, 2)
|
||||||
};
|
};
|
||||||
|
|
||||||
JSC_CCALL(game_engine_start, engine_start(argv[0],argv[1], js2number(argv[2]), js2number(argv[3])))
|
JSC_CCALL(game_engine_start, engine_start(argv[0],argv[1], js2number(argv[2]), js2number(argv[3])))
|
||||||
|
@ -1159,13 +1495,18 @@ static const JSCFunctionListEntry js_input_funcs[] = {
|
||||||
JSC_CCALL(prosperon_phys2d_step, phys2d_update(js2number(argv[0])))
|
JSC_CCALL(prosperon_phys2d_step, phys2d_update(js2number(argv[0])))
|
||||||
JSC_CCALL(prosperon_window_render, openglRender(js2vec2(argv[0])))
|
JSC_CCALL(prosperon_window_render, openglRender(js2vec2(argv[0])))
|
||||||
JSC_CCALL(prosperon_guid,
|
JSC_CCALL(prosperon_guid,
|
||||||
uint8_t bytes[16];
|
int bits = 32;
|
||||||
for (int i = 0; i < 16; i++) bytes[i] = rand()%256;
|
char guid[33];
|
||||||
char uuid[37];
|
for (int i = 0; i < 4; i++) {
|
||||||
snprintf(uuid, 37, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
int r = rand();
|
||||||
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
|
for (int j = 0; j < 8; j++) {
|
||||||
bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]);
|
guid[i*8+j] = "0123456789abcdef"[r%16];
|
||||||
return str2js(uuid);
|
r /= 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
guid[32] = 0;
|
||||||
|
return str2js(guid);
|
||||||
)
|
)
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_prosperon_funcs[] = {
|
static const JSCFunctionListEntry js_prosperon_funcs[] = {
|
||||||
|
@ -1235,8 +1576,32 @@ static const JSCFunctionListEntry js_audio_funcs[] = {
|
||||||
|
|
||||||
JSC_CCALL(profile_now, return number2js(stm_now()))
|
JSC_CCALL(profile_now, return number2js(stm_now()))
|
||||||
|
|
||||||
|
static JSValue instr_v = JS_UNDEFINED;
|
||||||
|
int iiihandle(JSRuntime *rt, void *data)
|
||||||
|
{
|
||||||
|
script_call_sym(instr_v, 0, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSC_CCALL(profile_gather,
|
||||||
|
int count = js2number(argv[0]);
|
||||||
|
instr_v = JS_DupValue(js, argv[1]);
|
||||||
|
JS_SetInterruptHandler(rt, iiihandle, NULL);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(profile_gather_rate,
|
||||||
|
JS_SetInterruptRate(js2number(argv[0]));
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(profile_gather_stop,
|
||||||
|
JS_SetInterruptHandler(rt,NULL,NULL);
|
||||||
|
)
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_profile_funcs[] = {
|
static const JSCFunctionListEntry js_profile_funcs[] = {
|
||||||
MIST_FUNC_DEF(profile,now,0),
|
MIST_FUNC_DEF(profile,now,0),
|
||||||
|
MIST_FUNC_DEF(profile,gather,2),
|
||||||
|
MIST_FUNC_DEF(profile,gather_rate,1),
|
||||||
|
MIST_FUNC_DEF(profile,gather_stop,0),
|
||||||
};
|
};
|
||||||
|
|
||||||
JSC_SCALL(io_exists, ret = boolean2js(fexists(str)))
|
JSC_SCALL(io_exists, ret = boolean2js(fexists(str)))
|
||||||
|
@ -1469,29 +1834,6 @@ static const JSCFunctionListEntry js_physics_funcs[] = {
|
||||||
CGETSET_ADD(physics, collision_persistence),
|
CGETSET_ADD(physics, collision_persistence),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_emitter_funcs[] = {
|
|
||||||
CGETSET_ADD(emitter, life),
|
|
||||||
CGETSET_ADD(emitter, life_var),
|
|
||||||
CGETSET_ADD(emitter, speed),
|
|
||||||
CGETSET_ADD(emitter, variation),
|
|
||||||
CGETSET_ADD(emitter, divergence),
|
|
||||||
CGETSET_ADD(emitter, scale),
|
|
||||||
CGETSET_ADD(emitter, scale_var),
|
|
||||||
CGETSET_ADD(emitter, grow_for),
|
|
||||||
CGETSET_ADD(emitter, shrink_for),
|
|
||||||
CGETSET_ADD(emitter, max),
|
|
||||||
CGETSET_ADD(emitter, explosiveness),
|
|
||||||
CGETSET_ADD(emitter, bounce),
|
|
||||||
CGETSET_ADD(emitter, collision_mask),
|
|
||||||
CGETSET_ADD(emitter, die_after_collision),
|
|
||||||
CGETSET_ADD(emitter, persist),
|
|
||||||
CGETSET_ADD(emitter, persist_var),
|
|
||||||
CGETSET_ADD(emitter, warp_mask),
|
|
||||||
MIST_FUNC_DEF(emitter, emit, 1),
|
|
||||||
MIST_FUNC_DEF(emitter, step, 1),
|
|
||||||
MIST_FUNC_DEF(emitter, draw, 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
JSC_GETSET(transform, pos, vec3)
|
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)
|
||||||
|
@ -1502,6 +1844,7 @@ JSC_CCALL(transform_lookat,
|
||||||
transform *go = js2transform(self);
|
transform *go = js2transform(self);
|
||||||
HMM_Mat4 m = HMM_LookAt_LH(go->pos, point, vUP);
|
HMM_Mat4 m = HMM_LookAt_LH(go->pos, point, vUP);
|
||||||
go->rotation = HMM_M4ToQ_LH(m);
|
go->rotation = HMM_M4ToQ_LH(m);
|
||||||
|
go->dirty = true;
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(transform_rotate,
|
JSC_CCALL(transform_rotate,
|
||||||
|
@ -1509,6 +1852,7 @@ JSC_CCALL(transform_rotate,
|
||||||
transform *t = js2transform(self);
|
transform *t = js2transform(self);
|
||||||
HMM_Quat rot = HMM_QFromAxisAngle_LH(axis, js2angle(argv[1]));
|
HMM_Quat rot = HMM_QFromAxisAngle_LH(axis, js2angle(argv[1]));
|
||||||
t->rotation = HMM_MulQ(t->rotation,rot);
|
t->rotation = HMM_MulQ(t->rotation,rot);
|
||||||
|
t->dirty = true;
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(transform_angle,
|
JSC_CCALL(transform_angle,
|
||||||
|
@ -1525,15 +1869,34 @@ JSC_CCALL(transform_direction,
|
||||||
return vec32js(HMM_QVRot(js2vec3(argv[0]), t->rotation));
|
return vec32js(HMM_QVRot(js2vec3(argv[0]), t->rotation));
|
||||||
)
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(transform_phys2d,
|
||||||
|
transform *t = js2transform(self);
|
||||||
|
HMM_Vec2 v = js2vec2(argv[0]);
|
||||||
|
float av = js2number(argv[1]);
|
||||||
|
float dt = js2number(argv[2]);
|
||||||
|
transform_move(t, (HMM_Vec3){v.x*dt,v.y*dt,0});
|
||||||
|
HMM_Quat rot = HMM_QFromAxisAngle_LH((HMM_Vec3){0,0,1}, av*dt);
|
||||||
|
t->rotation = HMM_MulQ(t->rotation, rot);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(transform_unit,
|
||||||
|
transform *t = js2transform(self);
|
||||||
|
t->pos = v3zero;
|
||||||
|
t->rotation = QUAT1;
|
||||||
|
t->scale = v3one;
|
||||||
|
)
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_transform_funcs[] = {
|
static const JSCFunctionListEntry js_transform_funcs[] = {
|
||||||
CGETSET_ADD(transform, pos),
|
CGETSET_ADD(transform, pos),
|
||||||
CGETSET_ADD(transform, scale),
|
CGETSET_ADD(transform, scale),
|
||||||
CGETSET_ADD(transform, rotation),
|
CGETSET_ADD(transform, rotation),
|
||||||
|
MIST_FUNC_DEF(transform, phys2d, 3),
|
||||||
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, 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),
|
||||||
|
MIST_FUNC_DEF(transform, unit, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
JSC_GETSET(dsp_node, pass, boolean)
|
JSC_GETSET(dsp_node, pass, boolean)
|
||||||
|
@ -2036,6 +2399,9 @@ static const JSCFunctionListEntry js_texture_funcs[] = {
|
||||||
MIST_FUNC_DEF(texture, blit, 5)
|
MIST_FUNC_DEF(texture, blit, 5)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_timer_funcs[] = {
|
||||||
|
};
|
||||||
|
|
||||||
JSC_GETSET(font, linegap, number)
|
JSC_GETSET(font, linegap, number)
|
||||||
JSC_GET(font, height, number)
|
JSC_GET(font, height, number)
|
||||||
|
|
||||||
|
@ -2380,11 +2746,6 @@ JSC_SCALL(os_make_model,
|
||||||
js_setpropstr(v, "material", material2js(me->primitives[0].mat));
|
js_setpropstr(v, "material", material2js(me->primitives[0].mat));
|
||||||
return v;
|
return v;
|
||||||
)
|
)
|
||||||
JSC_CCALL(os_make_emitter,
|
|
||||||
emitter *e = make_emitter();
|
|
||||||
ret = emitter2js(e);
|
|
||||||
js_setpropstr(ret, "buffer", sg_buffer2js(&e->buffer));
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_make_buffer,
|
JSC_CCALL(os_make_buffer,
|
||||||
int type = js2number(argv[1]);
|
int type = js2number(argv[1]);
|
||||||
|
@ -2565,7 +2926,6 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||||
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),
|
||||||
MIST_FUNC_DEF(os, make_emitter, 0),
|
|
||||||
MIST_FUNC_DEF(os, make_buffer, 1),
|
MIST_FUNC_DEF(os, make_buffer, 1),
|
||||||
MIST_FUNC_DEF(os, make_line_prim, 4),
|
MIST_FUNC_DEF(os, make_line_prim, 4),
|
||||||
MIST_FUNC_DEF(os, make_cylinder, 2),
|
MIST_FUNC_DEF(os, make_cylinder, 2),
|
||||||
|
@ -2598,7 +2958,6 @@ void ffi_load() {
|
||||||
QJSCLASSPREP_FUNCS(gameobject);
|
QJSCLASSPREP_FUNCS(gameobject);
|
||||||
QJSCLASSPREP_FUNCS(transform);
|
QJSCLASSPREP_FUNCS(transform);
|
||||||
QJSCLASSPREP_FUNCS(dsp_node);
|
QJSCLASSPREP_FUNCS(dsp_node);
|
||||||
QJSCLASSPREP_FUNCS(emitter);
|
|
||||||
QJSCLASSPREP_FUNCS(warp_gravity);
|
QJSCLASSPREP_FUNCS(warp_gravity);
|
||||||
QJSCLASSPREP_FUNCS(warp_damp);
|
QJSCLASSPREP_FUNCS(warp_damp);
|
||||||
QJSCLASSPREP_FUNCS(texture);
|
QJSCLASSPREP_FUNCS(texture);
|
||||||
|
@ -2607,6 +2966,7 @@ void ffi_load() {
|
||||||
QJSCLASSPREP_FUNCS(window);
|
QJSCLASSPREP_FUNCS(window);
|
||||||
QJSCLASSPREP_FUNCS(datastream);
|
QJSCLASSPREP_FUNCS(datastream);
|
||||||
QJSCLASSPREP_FUNCS(cpShape);
|
QJSCLASSPREP_FUNCS(cpShape);
|
||||||
|
QJSCLASSPREP_FUNCS(timer);
|
||||||
|
|
||||||
QJSGLOBALCLASS(nota);
|
QJSGLOBALCLASS(nota);
|
||||||
QJSGLOBALCLASS(input);
|
QJSGLOBALCLASS(input);
|
||||||
|
@ -2659,6 +3019,10 @@ void ffi_load() {
|
||||||
JSSTATIC(damped_spring, cpConstraint_proto)
|
JSSTATIC(damped_spring, cpConstraint_proto)
|
||||||
JSSTATIC(groove, cpConstraint_proto)
|
JSSTATIC(groove, cpConstraint_proto)
|
||||||
|
|
||||||
|
JSValue array_proto = js_getpropstr(globalThis, "Array");
|
||||||
|
array_proto = js_getpropstr(array_proto, "prototype");
|
||||||
|
JS_SetPropertyFunctionList(js, array_proto, js_array_funcs, 4);
|
||||||
|
|
||||||
JS_FreeValue(js,globalThis);
|
JS_FreeValue(js,globalThis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,7 @@ static JSClassDef js_##TYPE##_class = {\
|
||||||
.finalizer = js_##TYPE##_finalizer,\
|
.finalizer = js_##TYPE##_finalizer,\
|
||||||
};\
|
};\
|
||||||
TYPE *js2##TYPE (JSValue val) { \
|
TYPE *js2##TYPE (JSValue val) { \
|
||||||
|
if (JS_IsUndefined(val)) return NULL; \
|
||||||
assert(JS_GetClassID(val) == js_##TYPE##_id); \
|
assert(JS_GetClassID(val) == js_##TYPE##_id); \
|
||||||
return JS_GetOpaque(val,js_##TYPE##_id); \
|
return JS_GetOpaque(val,js_##TYPE##_id); \
|
||||||
}\
|
}\
|
||||||
|
|
|
@ -508,7 +508,7 @@ sg_bindings primitive_bind(primitive *p)
|
||||||
|
|
||||||
void model_draw_go(model *model, transform *go)
|
void model_draw_go(model *model, transform *go)
|
||||||
{
|
{
|
||||||
HMM_Mat4 gom = transform2mat(*go);
|
HMM_Mat4 gom = transform2mat(go);
|
||||||
|
|
||||||
animation_run(&model->anim, apptime());
|
animation_run(&model->anim, apptime());
|
||||||
|
|
||||||
|
|
|
@ -1,124 +0,0 @@
|
||||||
#include "particle.h"
|
|
||||||
#include "stb_ds.h"
|
|
||||||
#include "render.h"
|
|
||||||
#include "2dphysics.h"
|
|
||||||
#include "math.h"
|
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
emitter *make_emitter() {
|
|
||||||
emitter *e = calloc(sizeof(*e),1);
|
|
||||||
|
|
||||||
e->max = 20;
|
|
||||||
arrsetcap(e->particles, 10);
|
|
||||||
for (int i = 0; i < arrlen(e->particles); i++)
|
|
||||||
e->particles[i].life = 0;
|
|
||||||
|
|
||||||
e->life = 10;
|
|
||||||
e->tte = lerp(e->explosiveness, e->life/e->max, 0);
|
|
||||||
e->scale = 1;
|
|
||||||
e->speed = 20;
|
|
||||||
e->buffer = sg_make_buffer(&(sg_buffer_desc){
|
|
||||||
.size = sizeof(struct par_vert),
|
|
||||||
.type = SG_BUFFERTYPE_STORAGEBUFFER,
|
|
||||||
.usage = SG_USAGE_STREAM
|
|
||||||
});
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void emitter_free(emitter *e)
|
|
||||||
{
|
|
||||||
arrfree(e->particles);
|
|
||||||
arrfree(e->verts);
|
|
||||||
free(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Variate a value around variance. Variance between 0 and 1. */
|
|
||||||
|
|
||||||
float variate(float val, float variance)
|
|
||||||
{
|
|
||||||
return val + val*(frand(variance)-(variance/2));
|
|
||||||
}
|
|
||||||
|
|
||||||
int emitter_spawn(emitter *e, transform *t)
|
|
||||||
{
|
|
||||||
if (arrlen(e->particles) == e->max) return 0;
|
|
||||||
particle p = {0};
|
|
||||||
p.life = e->life;
|
|
||||||
p.pos = (HMM_Vec4){t->pos.x,t->pos.y,t->pos.z,0};
|
|
||||||
HMM_Vec3 up = transform_direction(t, vFWD);
|
|
||||||
float newan = (frand(e->divergence)-(e->divergence/2))*HMM_TurnToRad;
|
|
||||||
HMM_Vec2 v2n = HMM_V2Rotate((HMM_Vec2){0,1}, newan);
|
|
||||||
HMM_Vec3 norm = (HMM_Vec3){v2n.x, v2n.y,0};
|
|
||||||
p.v = HMM_MulV4F((HMM_Vec4){norm.x,norm.y,norm.z,0}, variate(e->speed, e->variation));
|
|
||||||
p.angle = 0.25;
|
|
||||||
p.scale = variate(e->scale*t->scale.x, e->scale_var);
|
|
||||||
arrput(e->particles,p);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void emitter_emit(emitter *e, int count, transform *t)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
emitter_spawn(e, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void emitter_draw(emitter *e)
|
|
||||||
{
|
|
||||||
if (arrlen(e->particles) == 0) return;
|
|
||||||
arrsetlen(e->verts, arrlen(e->particles));
|
|
||||||
for (int i = 0; i < arrlen(e->particles); i++) {
|
|
||||||
if (e->particles[i].time >= e->particles[i].life) continue;
|
|
||||||
particle *p = e->particles+i;
|
|
||||||
e->verts[i].pos = p->pos.xy;
|
|
||||||
e->verts[i].angle = p->angle;
|
|
||||||
e->verts[i].scale = p->scale;
|
|
||||||
/* if (p->time < e->grow_for)
|
|
||||||
e->verts[i].scale = lerp(p->time/e->grow_for, 0, p->scale);
|
|
||||||
else if (p->time > (p->life - e->shrink_for))
|
|
||||||
e->verts[i].scale = lerp((p->time-(p->life-e->shrink_for))/e->shrink_for, p->scale, 0);*/
|
|
||||||
e->verts[i].color = p->color;
|
|
||||||
}
|
|
||||||
|
|
||||||
sg_range verts;
|
|
||||||
verts.ptr = e->verts;
|
|
||||||
verts.size = sizeof(*e->verts)*arrlen(e->verts);
|
|
||||||
if (sg_query_buffer_will_overflow(e->buffer, verts.size)) {
|
|
||||||
sg_destroy_buffer(e->buffer);
|
|
||||||
e->buffer = sg_make_buffer(&(sg_buffer_desc){
|
|
||||||
.size = verts.size,
|
|
||||||
.type = SG_BUFFERTYPE_STORAGEBUFFER,
|
|
||||||
.usage = SG_USAGE_STREAM
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
sg_append_buffer(e->buffer, &verts);
|
|
||||||
}
|
|
||||||
|
|
||||||
void emitter_step(emitter *e, double dt, transform *t) {
|
|
||||||
HMM_Vec4 g_accel = HMM_MulV4F((HMM_Vec4){cpSpaceGetGravity(space).x, cpSpaceGetGravity(space).y, 0, 0}, dt);
|
|
||||||
|
|
||||||
for (int i = 0; i < arrlen(e->particles); i++) {
|
|
||||||
if (e->particles[i].time >= e->particles[i].life) continue;
|
|
||||||
|
|
||||||
//if (e->warp_mask & gravmask)
|
|
||||||
// e->particles[i].v = HMM_AddV4(e->particles[i].v, g_accel);
|
|
||||||
|
|
||||||
e->particles[i].pos = HMM_AddV4(e->particles[i].pos, HMM_MulV4F(e->particles[i].v, dt));
|
|
||||||
e->particles[i].angle += e->particles[i].av*dt;
|
|
||||||
e->particles[i].time += dt;
|
|
||||||
e->particles[i].color = sample_sampler(&e->color, e->particles[i].time/e->particles[i].life);
|
|
||||||
e->particles[i].scale = e->scale;
|
|
||||||
|
|
||||||
if (e->particles[i].time >= e->particles[i].life)
|
|
||||||
arrdelswap(e->particles, i);
|
|
||||||
// else if (query_point(e->particles[i].pos.xy))
|
|
||||||
// arrdelswap(e->particles,i);
|
|
||||||
}
|
|
||||||
|
|
||||||
e->tte-=dt;
|
|
||||||
float step = lerp(e->explosiveness, e->life/e->max,0);
|
|
||||||
while (e->tte <= 0) {
|
|
||||||
e->tte += step;
|
|
||||||
if (!emitter_spawn(e, t)) break;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
#ifndef PARTICLE_H
|
|
||||||
#define PARTICLE_H
|
|
||||||
|
|
||||||
#include "HandmadeMath.h"
|
|
||||||
#include "warp.h"
|
|
||||||
#include "transform.h"
|
|
||||||
#include "texture.h"
|
|
||||||
#include "anim.h"
|
|
||||||
#include "gameobject.h"
|
|
||||||
#include "render.h"
|
|
||||||
|
|
||||||
typedef struct particle {
|
|
||||||
HMM_Vec4 pos;
|
|
||||||
HMM_Vec4 v; /* velocity */
|
|
||||||
float angle;
|
|
||||||
float av; /* angular velocity */
|
|
||||||
float scale;
|
|
||||||
double time;
|
|
||||||
double life;
|
|
||||||
HMM_Vec4 color;
|
|
||||||
} particle;
|
|
||||||
|
|
||||||
#define SPRAY 0
|
|
||||||
#define CLOUD 1
|
|
||||||
#define MESH 2
|
|
||||||
|
|
||||||
typedef struct par_vert {
|
|
||||||
HMM_Vec2 pos;
|
|
||||||
float angle;
|
|
||||||
float scale;
|
|
||||||
HMM_Vec4 color;
|
|
||||||
} par_vert;
|
|
||||||
|
|
||||||
typedef struct emitter {
|
|
||||||
struct particle *particles;
|
|
||||||
par_vert *verts;
|
|
||||||
HMM_Vec3 *mesh; /* list of points to optionally spawn from */
|
|
||||||
HMM_Vec3 *norm; /* norm at each point */
|
|
||||||
int type; /* spray, cloud, or mesh */
|
|
||||||
float explosiveness; /* 0 for a stream, 1 for all at once. Range of values allowed. */
|
|
||||||
int max; /* number of particles */
|
|
||||||
double life; /* how long a particle lasts */
|
|
||||||
double life_var;
|
|
||||||
/* SPRAY PARTICLE GEN */
|
|
||||||
float speed; /* initial speed of particle */
|
|
||||||
float variation; /* variation on speed */
|
|
||||||
float divergence; /* angular degree of variation from emitter normal, up to 1 */
|
|
||||||
float tumble; /* amount of random rotation of particles */
|
|
||||||
float tumble_rate; /* tumble rotation */
|
|
||||||
sampler color; /* color over particle lifetime */
|
|
||||||
float scale;
|
|
||||||
float scale_var;
|
|
||||||
float grow_for; /* seconds to grow from small until scale */
|
|
||||||
float shrink_for; /* seconds to shrink to small prior to its death */
|
|
||||||
/* ROTATION AND COLLISION */
|
|
||||||
int collision_mask; /* mask for collision */
|
|
||||||
float bounce; /* bounce back after collision */
|
|
||||||
/* PARTICLE SPAWN */
|
|
||||||
int die_after_collision;
|
|
||||||
float persist; /* how long to linger after death */
|
|
||||||
float persist_var;
|
|
||||||
/* TRAILS */
|
|
||||||
warpmask warp_mask;
|
|
||||||
double tte; /* time to emit */
|
|
||||||
sg_buffer buffer;
|
|
||||||
} emitter;
|
|
||||||
|
|
||||||
emitter *make_emitter();
|
|
||||||
void emitter_free(emitter *e);
|
|
||||||
|
|
||||||
void emitter_emit(emitter *e, int count, transform *t);
|
|
||||||
void emitter_step(emitter *e, double dt, transform *t);
|
|
||||||
void emitter_draw(emitter *e);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
#include "gameobject.h"
|
#include "gameobject.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "particle.h"
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include "stb_ds.h"
|
#include "stb_ds.h"
|
||||||
|
@ -149,8 +148,6 @@ void render_init() {
|
||||||
sg_trace_hooks hh = sg_install_trace_hooks(&hooks);
|
sg_trace_hooks hh = sg_install_trace_hooks(&hooks);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
font_init();
|
|
||||||
|
|
||||||
sg_features feat = sg_query_features();
|
sg_features feat = sg_query_features();
|
||||||
TOPLEFT = feat.origin_top_left;
|
TOPLEFT = feat.origin_top_left;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "jsffi.h"
|
#include "jsffi.h"
|
||||||
#include "stb_ds.h"
|
#include "stb_ds.h"
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
|
#include <sokol/sokol_time.h>
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ extern "C" {
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
extern JSContext *js;
|
extern JSContext *js;
|
||||||
|
extern JSRuntime *rt;
|
||||||
|
|
||||||
struct phys_cbs {
|
struct phys_cbs {
|
||||||
JSValue begin;
|
JSValue begin;
|
||||||
|
|
5885
source/engine/thirdparty/imgui/implot.cpp
vendored
Normal file
5885
source/engine/thirdparty/imgui/implot.cpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
1297
source/engine/thirdparty/imgui/implot.h
vendored
Normal file
1297
source/engine/thirdparty/imgui/implot.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
1669
source/engine/thirdparty/imgui/implot_internal.h
vendored
Normal file
1669
source/engine/thirdparty/imgui/implot_internal.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
2808
source/engine/thirdparty/imgui/implot_items.cpp
vendored
Normal file
2808
source/engine/thirdparty/imgui/implot_items.cpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
6
source/engine/thirdparty/quickjs/cutils.h
vendored
6
source/engine/thirdparty/quickjs/cutils.h
vendored
|
@ -51,6 +51,12 @@
|
||||||
#define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
|
#define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(_MSC_VER) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||||
|
#define minimum_length(n) static n
|
||||||
|
#else
|
||||||
|
#define minimum_length(n) n
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef int BOOL;
|
typedef int BOOL;
|
||||||
|
|
||||||
#ifndef FALSE
|
#ifndef FALSE
|
||||||
|
|
2
source/engine/thirdparty/quickjs/libbf.c
vendored
2
source/engine/thirdparty/quickjs/libbf.c
vendored
|
@ -136,6 +136,7 @@ static inline slimb_t ceil_div(slimb_t a, slimb_t b)
|
||||||
return a / b;
|
return a / b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_BF_DEC
|
||||||
/* b must be >= 1 */
|
/* b must be >= 1 */
|
||||||
static inline slimb_t floor_div(slimb_t a, slimb_t b)
|
static inline slimb_t floor_div(slimb_t a, slimb_t b)
|
||||||
{
|
{
|
||||||
|
@ -145,6 +146,7 @@ static inline slimb_t floor_div(slimb_t a, slimb_t b)
|
||||||
return (a - b + 1) / b;
|
return (a - b + 1) / b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* return r = a modulo b (0 <= r <= b - 1. b must be >= 1 */
|
/* return r = a modulo b (0 <= r <= b - 1. b must be >= 1 */
|
||||||
static inline limb_t smod(slimb_t a, slimb_t b)
|
static inline limb_t smod(slimb_t a, slimb_t b)
|
||||||
|
|
33
source/engine/thirdparty/quickjs/libregexp.c
vendored
33
source/engine/thirdparty/quickjs/libregexp.c
vendored
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "cutils.h"
|
#include "cutils.h"
|
||||||
#include "libregexp.h"
|
#include "libregexp.h"
|
||||||
|
#include "libunicode.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO:
|
TODO:
|
||||||
|
@ -141,32 +142,6 @@ static const uint16_t char_range_s[] = {
|
||||||
0xFEFF, 0xFEFF + 1,
|
0xFEFF, 0xFEFF + 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
BOOL lre_is_space(int c)
|
|
||||||
{
|
|
||||||
int i, n, low, high;
|
|
||||||
n = (countof(char_range_s) - 1) / 2;
|
|
||||||
for(i = 0; i < n; i++) {
|
|
||||||
low = char_range_s[2 * i + 1];
|
|
||||||
if (c < low)
|
|
||||||
return FALSE;
|
|
||||||
high = char_range_s[2 * i + 2];
|
|
||||||
if (c < high)
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t const lre_id_start_table_ascii[4] = {
|
|
||||||
/* $ A-Z _ a-z */
|
|
||||||
0x00000000, 0x00000010, 0x87FFFFFE, 0x07FFFFFE
|
|
||||||
};
|
|
||||||
|
|
||||||
uint32_t const lre_id_continue_table_ascii[4] = {
|
|
||||||
/* $ 0-9 A-Z _ a-z */
|
|
||||||
0x00000000, 0x03FF0010, 0x87FFFFFE, 0x07FFFFFE
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static const uint16_t char_range_w[] = {
|
static const uint16_t char_range_w[] = {
|
||||||
4,
|
4,
|
||||||
0x0030, 0x0039 + 1,
|
0x0030, 0x0039 + 1,
|
||||||
|
@ -186,7 +161,7 @@ typedef enum {
|
||||||
CHAR_RANGE_W,
|
CHAR_RANGE_W,
|
||||||
} CharRangeEnum;
|
} CharRangeEnum;
|
||||||
|
|
||||||
static const uint16_t *char_range_table[] = {
|
static const uint16_t * const char_range_table[] = {
|
||||||
char_range_d,
|
char_range_d,
|
||||||
char_range_s,
|
char_range_s,
|
||||||
char_range_w,
|
char_range_w,
|
||||||
|
@ -1513,15 +1488,13 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
|
||||||
|
|
||||||
if (dbuf_error(&s->byte_code))
|
if (dbuf_error(&s->byte_code))
|
||||||
goto out_of_memory;
|
goto out_of_memory;
|
||||||
|
}
|
||||||
/* the spec tells that if there is no advance when
|
/* the spec tells that if there is no advance when
|
||||||
running the atom after the first quant_min times,
|
running the atom after the first quant_min times,
|
||||||
then there is no match. We remove this test when we
|
then there is no match. We remove this test when we
|
||||||
are sure the atom always advances the position. */
|
are sure the atom always advances the position. */
|
||||||
add_zero_advance_check = re_need_check_advance(s->byte_code.buf + last_atom_start,
|
add_zero_advance_check = re_need_check_advance(s->byte_code.buf + last_atom_start,
|
||||||
s->byte_code.size - last_atom_start);
|
s->byte_code.size - last_atom_start);
|
||||||
} else {
|
|
||||||
add_zero_advance_check = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
int len, pos;
|
int len, pos;
|
||||||
|
|
43
source/engine/thirdparty/quickjs/libregexp.h
vendored
43
source/engine/thirdparty/quickjs/libregexp.h
vendored
|
@ -25,10 +25,7 @@
|
||||||
#define LIBREGEXP_H
|
#define LIBREGEXP_H
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include "libunicode.h"
|
|
||||||
|
|
||||||
#define LRE_BOOL int /* for documentation purposes */
|
|
||||||
|
|
||||||
#define LRE_FLAG_GLOBAL (1 << 0)
|
#define LRE_FLAG_GLOBAL (1 << 0)
|
||||||
#define LRE_FLAG_IGNORECASE (1 << 1)
|
#define LRE_FLAG_IGNORECASE (1 << 1)
|
||||||
|
@ -50,43 +47,9 @@ int lre_exec(uint8_t **capture,
|
||||||
int cbuf_type, void *opaque);
|
int cbuf_type, void *opaque);
|
||||||
|
|
||||||
int lre_parse_escape(const uint8_t **pp, int allow_utf16);
|
int lre_parse_escape(const uint8_t **pp, int allow_utf16);
|
||||||
LRE_BOOL lre_is_space(int c);
|
|
||||||
|
|
||||||
/* must be provided by the user */
|
/* must be provided by the user, return non zero if overflow */
|
||||||
LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);
|
int lre_check_stack_overflow(void *opaque, size_t alloca_size);
|
||||||
void *lre_realloc(void *opaque, void *ptr, size_t size);
|
void *lre_realloc(void *opaque, void *ptr, size_t size);
|
||||||
|
|
||||||
/* JS identifier test */
|
|
||||||
extern uint32_t const lre_id_start_table_ascii[4];
|
|
||||||
extern uint32_t const lre_id_continue_table_ascii[4];
|
|
||||||
|
|
||||||
static inline int lre_js_is_ident_first(int c)
|
|
||||||
{
|
|
||||||
if ((uint32_t)c < 128) {
|
|
||||||
return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
|
|
||||||
} else {
|
|
||||||
#ifdef CONFIG_ALL_UNICODE
|
|
||||||
return lre_is_id_start(c);
|
|
||||||
#else
|
|
||||||
return !lre_is_space(c);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int lre_js_is_ident_next(int c)
|
|
||||||
{
|
|
||||||
if ((uint32_t)c < 128) {
|
|
||||||
return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
|
|
||||||
} else {
|
|
||||||
/* ZWNJ and ZWJ are accepted in identifiers */
|
|
||||||
#ifdef CONFIG_ALL_UNICODE
|
|
||||||
return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
|
|
||||||
#else
|
|
||||||
return !lre_is_space(c) || c == 0x200C || c == 0x200D;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef LRE_BOOL
|
|
||||||
|
|
||||||
#endif /* LIBREGEXP_H */
|
#endif /* LIBREGEXP_H */
|
||||||
|
|
161
source/engine/thirdparty/quickjs/libunicode-table.h
vendored
161
source/engine/thirdparty/quickjs/libunicode-table.h
vendored
|
@ -189,9 +189,13 @@ static const uint8_t unicode_prop_Cased1_table[196] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t unicode_prop_Cased1_index[21] = {
|
static const uint8_t unicode_prop_Cased1_index[21] = {
|
||||||
0xb9, 0x02, 0xe0, 0xc0, 0x1d, 0x20, 0xe5, 0x2c,
|
0xb9, 0x02, 0xe0, // 002B9 at 39
|
||||||
0x20, 0xb1, 0x07, 0x21, 0xc1, 0xd6, 0x21, 0x4a,
|
0xc0, 0x1d, 0x20, // 01DC0 at 65
|
||||||
0xf1, 0x01, 0x8a, 0xf1, 0x01,
|
0xe5, 0x2c, 0x20, // 02CE5 at 97
|
||||||
|
0xb1, 0x07, 0x21, // 107B1 at 129
|
||||||
|
0xc1, 0xd6, 0x21, // 1D6C1 at 161
|
||||||
|
0x4a, 0xf1, 0x01, // 1F14A at 192
|
||||||
|
0x8a, 0xf1, 0x01, // 1F18A at 224 (upper bound)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t unicode_prop_Case_Ignorable_table[737] = {
|
static const uint8_t unicode_prop_Case_Ignorable_table[737] = {
|
||||||
|
@ -291,15 +295,29 @@ static const uint8_t unicode_prop_Case_Ignorable_table[737] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t unicode_prop_Case_Ignorable_index[69] = {
|
static const uint8_t unicode_prop_Case_Ignorable_index[69] = {
|
||||||
0xbe, 0x05, 0x00, 0xfe, 0x07, 0x00, 0x52, 0x0a,
|
0xbe, 0x05, 0x00, // 005BE at 32
|
||||||
0xa0, 0xc1, 0x0b, 0x00, 0x82, 0x0d, 0x00, 0x3f,
|
0xfe, 0x07, 0x00, // 007FE at 64
|
||||||
0x10, 0x80, 0xd4, 0x17, 0x40, 0xcf, 0x1a, 0x20,
|
0x52, 0x0a, 0xa0, // 00A52 at 101
|
||||||
0xf5, 0x1c, 0x00, 0x80, 0x20, 0x00, 0x16, 0xa0,
|
0xc1, 0x0b, 0x00, // 00BC1 at 128
|
||||||
0x00, 0xc6, 0xa8, 0x00, 0xc2, 0xaa, 0x60, 0x56,
|
0x82, 0x0d, 0x00, // 00D82 at 160
|
||||||
0xfe, 0x20, 0xb1, 0x07, 0x01, 0x75, 0x10, 0x01,
|
0x3f, 0x10, 0x80, // 0103F at 196
|
||||||
0xeb, 0x12, 0x21, 0x41, 0x16, 0x01, 0x5c, 0x1a,
|
0xd4, 0x17, 0x40, // 017D4 at 226
|
||||||
0x01, 0x43, 0x1f, 0x01, 0x2e, 0xcf, 0x41, 0x25,
|
0xcf, 0x1a, 0x20, // 01ACF at 257
|
||||||
0xe0, 0x01, 0xf0, 0x01, 0x0e,
|
0xf5, 0x1c, 0x00, // 01CF5 at 288
|
||||||
|
0x80, 0x20, 0x00, // 02080 at 320
|
||||||
|
0x16, 0xa0, 0x00, // 0A016 at 352
|
||||||
|
0xc6, 0xa8, 0x00, // 0A8C6 at 384
|
||||||
|
0xc2, 0xaa, 0x60, // 0AAC2 at 419
|
||||||
|
0x56, 0xfe, 0x20, // 0FE56 at 449
|
||||||
|
0xb1, 0x07, 0x01, // 107B1 at 480
|
||||||
|
0x75, 0x10, 0x01, // 11075 at 512
|
||||||
|
0xeb, 0x12, 0x21, // 112EB at 545
|
||||||
|
0x41, 0x16, 0x01, // 11641 at 576
|
||||||
|
0x5c, 0x1a, 0x01, // 11A5C at 608
|
||||||
|
0x43, 0x1f, 0x01, // 11F43 at 640
|
||||||
|
0x2e, 0xcf, 0x41, // 1CF2E at 674
|
||||||
|
0x25, 0xe0, 0x01, // 1E025 at 704
|
||||||
|
0xf0, 0x01, 0x0e, // E01F0 at 736 (upper bound)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t unicode_prop_ID_Start_table[1100] = {
|
static const uint8_t unicode_prop_ID_Start_table[1100] = {
|
||||||
|
@ -444,20 +462,41 @@ static const uint8_t unicode_prop_ID_Start_table[1100] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t unicode_prop_ID_Start_index[105] = {
|
static const uint8_t unicode_prop_ID_Start_index[105] = {
|
||||||
0xf6, 0x03, 0x20, 0xa6, 0x07, 0x00, 0xa9, 0x09,
|
0xf6, 0x03, 0x20, // 003F6 at 33
|
||||||
0x20, 0xb1, 0x0a, 0x00, 0xba, 0x0b, 0x20, 0x3b,
|
0xa6, 0x07, 0x00, // 007A6 at 64
|
||||||
0x0d, 0x20, 0xc7, 0x0e, 0x20, 0x49, 0x12, 0x00,
|
0xa9, 0x09, 0x20, // 009A9 at 97
|
||||||
0x9b, 0x16, 0x00, 0xac, 0x19, 0x00, 0xc0, 0x1d,
|
0xb1, 0x0a, 0x00, // 00AB1 at 128
|
||||||
0x80, 0x80, 0x20, 0x20, 0x70, 0x2d, 0x00, 0x00,
|
0xba, 0x0b, 0x20, // 00BBA at 161
|
||||||
0x32, 0x00, 0xda, 0xa7, 0x00, 0x4c, 0xaa, 0x20,
|
0x3b, 0x0d, 0x20, // 00D3B at 193
|
||||||
0xc7, 0xd7, 0x20, 0xfc, 0xfd, 0x20, 0x9d, 0x02,
|
0xc7, 0x0e, 0x20, // 00EC7 at 225
|
||||||
0x21, 0x96, 0x05, 0x01, 0xf3, 0x08, 0x01, 0xb3,
|
0x49, 0x12, 0x00, // 01249 at 256
|
||||||
0x0c, 0x21, 0x73, 0x11, 0x61, 0x34, 0x13, 0x01,
|
0x9b, 0x16, 0x00, // 0169B at 288
|
||||||
0x1b, 0x17, 0x21, 0x8a, 0x1a, 0x01, 0x34, 0x1f,
|
0xac, 0x19, 0x00, // 019AC at 320
|
||||||
0x21, 0xbf, 0x6a, 0x01, 0x23, 0xb1, 0xa1, 0xad,
|
0xc0, 0x1d, 0x80, // 01DC0 at 356
|
||||||
0xd4, 0x01, 0x6f, 0xd7, 0x01, 0xff, 0xe7, 0x61,
|
0x80, 0x20, 0x20, // 02080 at 385
|
||||||
0x5e, 0xee, 0x01, 0xe1, 0xeb, 0x22, 0xb0, 0x23,
|
0x70, 0x2d, 0x00, // 02D70 at 416
|
||||||
0x03,
|
0x00, 0x32, 0x00, // 03200 at 448
|
||||||
|
0xda, 0xa7, 0x00, // 0A7DA at 480
|
||||||
|
0x4c, 0xaa, 0x20, // 0AA4C at 513
|
||||||
|
0xc7, 0xd7, 0x20, // 0D7C7 at 545
|
||||||
|
0xfc, 0xfd, 0x20, // 0FDFC at 577
|
||||||
|
0x9d, 0x02, 0x21, // 1029D at 609
|
||||||
|
0x96, 0x05, 0x01, // 10596 at 640
|
||||||
|
0xf3, 0x08, 0x01, // 108F3 at 672
|
||||||
|
0xb3, 0x0c, 0x21, // 10CB3 at 705
|
||||||
|
0x73, 0x11, 0x61, // 11173 at 739
|
||||||
|
0x34, 0x13, 0x01, // 11334 at 768
|
||||||
|
0x1b, 0x17, 0x21, // 1171B at 801
|
||||||
|
0x8a, 0x1a, 0x01, // 11A8A at 832
|
||||||
|
0x34, 0x1f, 0x21, // 11F34 at 865
|
||||||
|
0xbf, 0x6a, 0x01, // 16ABF at 896
|
||||||
|
0x23, 0xb1, 0xa1, // 1B123 at 933
|
||||||
|
0xad, 0xd4, 0x01, // 1D4AD at 960
|
||||||
|
0x6f, 0xd7, 0x01, // 1D76F at 992
|
||||||
|
0xff, 0xe7, 0x61, // 1E7FF at 1027
|
||||||
|
0x5e, 0xee, 0x01, // 1EE5E at 1056
|
||||||
|
0xe1, 0xeb, 0x22, // 2EBE1 at 1089
|
||||||
|
0xb0, 0x23, 0x03, // 323B0 at 1120 (upper bound)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t unicode_prop_ID_Continue1_table[660] = {
|
static const uint8_t unicode_prop_ID_Continue1_table[660] = {
|
||||||
|
@ -547,14 +586,27 @@ static const uint8_t unicode_prop_ID_Continue1_table[660] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t unicode_prop_ID_Continue1_index[63] = {
|
static const uint8_t unicode_prop_ID_Continue1_index[63] = {
|
||||||
0xfa, 0x06, 0x00, 0x70, 0x09, 0x00, 0xf0, 0x0a,
|
0xfa, 0x06, 0x00, // 006FA at 32
|
||||||
0x40, 0x57, 0x0c, 0x00, 0xf0, 0x0d, 0x60, 0xc7,
|
0x70, 0x09, 0x00, // 00970 at 64
|
||||||
0x0f, 0x20, 0xea, 0x17, 0x40, 0x05, 0x1b, 0x00,
|
0xf0, 0x0a, 0x40, // 00AF0 at 98
|
||||||
0x41, 0x20, 0x00, 0x0c, 0xa8, 0x80, 0x37, 0xaa,
|
0x57, 0x0c, 0x00, // 00C57 at 128
|
||||||
0x20, 0x50, 0xfe, 0x20, 0x3a, 0x0d, 0x21, 0x74,
|
0xf0, 0x0d, 0x60, // 00DF0 at 163
|
||||||
0x11, 0x01, 0x5a, 0x14, 0x21, 0x44, 0x19, 0x81,
|
0xc7, 0x0f, 0x20, // 00FC7 at 193
|
||||||
0x5a, 0x1d, 0xa1, 0xf5, 0x6a, 0x21, 0x45, 0xd2,
|
0xea, 0x17, 0x40, // 017EA at 226
|
||||||
0x41, 0xaf, 0xe2, 0x21, 0xf0, 0x01, 0x0e,
|
0x05, 0x1b, 0x00, // 01B05 at 256
|
||||||
|
0x41, 0x20, 0x00, // 02041 at 288
|
||||||
|
0x0c, 0xa8, 0x80, // 0A80C at 324
|
||||||
|
0x37, 0xaa, 0x20, // 0AA37 at 353
|
||||||
|
0x50, 0xfe, 0x20, // 0FE50 at 385
|
||||||
|
0x3a, 0x0d, 0x21, // 10D3A at 417
|
||||||
|
0x74, 0x11, 0x01, // 11174 at 448
|
||||||
|
0x5a, 0x14, 0x21, // 1145A at 481
|
||||||
|
0x44, 0x19, 0x81, // 11944 at 516
|
||||||
|
0x5a, 0x1d, 0xa1, // 11D5A at 549
|
||||||
|
0xf5, 0x6a, 0x21, // 16AF5 at 577
|
||||||
|
0x45, 0xd2, 0x41, // 1D245 at 610
|
||||||
|
0xaf, 0xe2, 0x21, // 1E2AF at 641
|
||||||
|
0xf0, 0x01, 0x0e, // E01F0 at 672 (upper bound)
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_ALL_UNICODE
|
#ifdef CONFIG_ALL_UNICODE
|
||||||
|
@ -676,17 +728,35 @@ static const uint8_t unicode_cc_table[899] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t unicode_cc_index[87] = {
|
static const uint8_t unicode_cc_index[87] = {
|
||||||
0x4d, 0x03, 0x00, 0x97, 0x05, 0x20, 0xc6, 0x05,
|
0x4d, 0x03, 0x00, // 0034D at 32
|
||||||
0x00, 0xe7, 0x06, 0x00, 0x45, 0x07, 0x00, 0x9c,
|
0x97, 0x05, 0x20, // 00597 at 65
|
||||||
0x08, 0x00, 0x4d, 0x09, 0x00, 0x3c, 0x0b, 0x00,
|
0xc6, 0x05, 0x00, // 005C6 at 96
|
||||||
0x3d, 0x0d, 0x00, 0x36, 0x0f, 0x00, 0x38, 0x10,
|
0xe7, 0x06, 0x00, // 006E7 at 128
|
||||||
0x20, 0x3a, 0x19, 0x00, 0xcb, 0x1a, 0x20, 0xd3,
|
0x45, 0x07, 0x00, // 00745 at 160
|
||||||
0x1c, 0x00, 0xcf, 0x1d, 0x00, 0xe2, 0x20, 0x00,
|
0x9c, 0x08, 0x00, // 0089C at 192
|
||||||
0x2e, 0x30, 0x20, 0x2b, 0xa9, 0x20, 0xed, 0xab,
|
0x4d, 0x09, 0x00, // 0094D at 224
|
||||||
0x00, 0x39, 0x0a, 0x01, 0x51, 0x0f, 0x01, 0x73,
|
0x3c, 0x0b, 0x00, // 00B3C at 256
|
||||||
0x11, 0x01, 0x75, 0x13, 0x01, 0x2b, 0x17, 0x21,
|
0x3d, 0x0d, 0x00, // 00D3D at 288
|
||||||
0x3f, 0x1c, 0x21, 0x9e, 0xbc, 0x21, 0x08, 0xe0,
|
0x36, 0x0f, 0x00, // 00F36 at 320
|
||||||
0x01, 0x44, 0xe9, 0x01, 0x4b, 0xe9, 0x01,
|
0x38, 0x10, 0x20, // 01038 at 353
|
||||||
|
0x3a, 0x19, 0x00, // 0193A at 384
|
||||||
|
0xcb, 0x1a, 0x20, // 01ACB at 417
|
||||||
|
0xd3, 0x1c, 0x00, // 01CD3 at 448
|
||||||
|
0xcf, 0x1d, 0x00, // 01DCF at 480
|
||||||
|
0xe2, 0x20, 0x00, // 020E2 at 512
|
||||||
|
0x2e, 0x30, 0x20, // 0302E at 545
|
||||||
|
0x2b, 0xa9, 0x20, // 0A92B at 577
|
||||||
|
0xed, 0xab, 0x00, // 0ABED at 608
|
||||||
|
0x39, 0x0a, 0x01, // 10A39 at 640
|
||||||
|
0x51, 0x0f, 0x01, // 10F51 at 672
|
||||||
|
0x73, 0x11, 0x01, // 11173 at 704
|
||||||
|
0x75, 0x13, 0x01, // 11375 at 736
|
||||||
|
0x2b, 0x17, 0x21, // 1172B at 769
|
||||||
|
0x3f, 0x1c, 0x21, // 11C3F at 801
|
||||||
|
0x9e, 0xbc, 0x21, // 1BC9E at 833
|
||||||
|
0x08, 0xe0, 0x01, // 1E008 at 864
|
||||||
|
0x44, 0xe9, 0x01, // 1E944 at 896
|
||||||
|
0x4b, 0xe9, 0x01, // 1E94B at 928 (upper bound)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t unicode_decomp_table1[699] = {
|
static const uint32_t unicode_decomp_table1[699] = {
|
||||||
|
@ -4484,3 +4554,4 @@ static const uint16_t unicode_prop_len_table[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CONFIG_ALL_UNICODE */
|
#endif /* CONFIG_ALL_UNICODE */
|
||||||
|
/* 62 tables / 32261 bytes, 5 index / 345 bytes */
|
||||||
|
|
130
source/engine/thirdparty/quickjs/libunicode.c
vendored
130
source/engine/thirdparty/quickjs/libunicode.c
vendored
|
@ -262,11 +262,7 @@ int lre_canonicalize(uint32_t c, BOOL is_unicode)
|
||||||
|
|
||||||
static uint32_t get_le24(const uint8_t *ptr)
|
static uint32_t get_le24(const uint8_t *ptr)
|
||||||
{
|
{
|
||||||
#if defined(__x86__) || defined(__x86_64__)
|
|
||||||
return *(uint16_t *)ptr | (ptr[2] << 16);
|
|
||||||
#else
|
|
||||||
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
|
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define UNICODE_INDEX_BLOCK_LEN 32
|
#define UNICODE_INDEX_BLOCK_LEN 32
|
||||||
|
@ -317,6 +313,14 @@ static BOOL lre_is_in_table(uint32_t c, const uint8_t *table,
|
||||||
return FALSE; /* outside the table */
|
return FALSE; /* outside the table */
|
||||||
p = table + pos;
|
p = table + pos;
|
||||||
bit = 0;
|
bit = 0;
|
||||||
|
/* Compressed run length encoding:
|
||||||
|
00..3F: 2 packed lengths: 3-bit + 3-bit
|
||||||
|
40..5F: 5-bits plus extra byte for length
|
||||||
|
60..7F: 5-bits plus 2 extra bytes for length
|
||||||
|
80..FF: 7-bit length
|
||||||
|
lengths must be incremented to get character count
|
||||||
|
Ranges alternate between false and true return value.
|
||||||
|
*/
|
||||||
for(;;) {
|
for(;;) {
|
||||||
b = *p++;
|
b = *p++;
|
||||||
if (b < 64) {
|
if (b < 64) {
|
||||||
|
@ -833,6 +837,13 @@ static int unicode_get_cc(uint32_t c)
|
||||||
if (pos < 0)
|
if (pos < 0)
|
||||||
return 0;
|
return 0;
|
||||||
p = unicode_cc_table + pos;
|
p = unicode_cc_table + pos;
|
||||||
|
/* Compressed run length encoding:
|
||||||
|
- 2 high order bits are combining class type
|
||||||
|
- 0:0, 1:230, 2:extra byte linear progression, 3:extra byte
|
||||||
|
- 00..2F: range length (add 1)
|
||||||
|
- 30..37: 3-bit range-length + 1 extra byte
|
||||||
|
- 38..3F: 3-bit range-length + 2 extra byte
|
||||||
|
*/
|
||||||
for(;;) {
|
for(;;) {
|
||||||
b = *p++;
|
b = *p++;
|
||||||
type = b >> 6;
|
type = b >> 6;
|
||||||
|
@ -1185,6 +1196,15 @@ static int unicode_general_category1(CharRange *cr, uint32_t gc_mask)
|
||||||
p = unicode_gc_table;
|
p = unicode_gc_table;
|
||||||
p_end = unicode_gc_table + countof(unicode_gc_table);
|
p_end = unicode_gc_table + countof(unicode_gc_table);
|
||||||
c = 0;
|
c = 0;
|
||||||
|
/* Compressed range encoding:
|
||||||
|
initial byte:
|
||||||
|
bits 0..4: category number (special case 31)
|
||||||
|
bits 5..7: range length (add 1)
|
||||||
|
special case bits 5..7 == 7: read an extra byte
|
||||||
|
- 00..7F: range length (add 7 + 1)
|
||||||
|
- 80..BF: 6-bits plus extra byte for range length (add 7 + 128)
|
||||||
|
- C0..FF: 6-bits plus 2 extra bytes for range length (add 7 + 128 + 16384)
|
||||||
|
*/
|
||||||
while (p < p_end) {
|
while (p < p_end) {
|
||||||
b = *p++;
|
b = *p++;
|
||||||
n = b >> 5;
|
n = b >> 5;
|
||||||
|
@ -1238,6 +1258,14 @@ static int unicode_prop1(CharRange *cr, int prop_idx)
|
||||||
p_end = p + unicode_prop_len_table[prop_idx];
|
p_end = p + unicode_prop_len_table[prop_idx];
|
||||||
c = 0;
|
c = 0;
|
||||||
bit = 0;
|
bit = 0;
|
||||||
|
/* Compressed range encoding:
|
||||||
|
00..3F: 2 packed lengths: 3-bit + 3-bit
|
||||||
|
40..5F: 5-bits plus extra byte for length
|
||||||
|
60..7F: 5-bits plus 2 extra bytes for length
|
||||||
|
80..FF: 7-bit length
|
||||||
|
lengths must be incremented to get character count
|
||||||
|
Ranges alternate between false and true return value.
|
||||||
|
*/
|
||||||
while (p < p_end) {
|
while (p < p_end) {
|
||||||
c0 = c;
|
c0 = c;
|
||||||
b = *p++;
|
b = *p++;
|
||||||
|
@ -1786,3 +1814,97 @@ int unicode_prop(CharRange *cr, const char *prop_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_ALL_UNICODE */
|
#endif /* CONFIG_ALL_UNICODE */
|
||||||
|
|
||||||
|
/*---- lre codepoint categorizing functions ----*/
|
||||||
|
|
||||||
|
#define S UNICODE_C_SPACE
|
||||||
|
#define D UNICODE_C_DIGIT
|
||||||
|
#define X UNICODE_C_XDIGIT
|
||||||
|
#define U UNICODE_C_UPPER
|
||||||
|
#define L UNICODE_C_LOWER
|
||||||
|
#define _ UNICODE_C_UNDER
|
||||||
|
#define d UNICODE_C_DOLLAR
|
||||||
|
|
||||||
|
uint8_t const lre_ctype_bits[256] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, S, S, S, S, S, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
S, 0, 0, 0, d, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
X|D, X|D, X|D, X|D, X|D, X|D, X|D, X|D,
|
||||||
|
X|D, X|D, 0, 0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
0, X|U, X|U, X|U, X|U, X|U, X|U, U,
|
||||||
|
U, U, U, U, U, U, U, U,
|
||||||
|
U, U, U, U, U, U, U, U,
|
||||||
|
U, U, U, 0, 0, 0, 0, _,
|
||||||
|
|
||||||
|
0, X|L, X|L, X|L, X|L, X|L, X|L, L,
|
||||||
|
L, L, L, L, L, L, L, L,
|
||||||
|
L, L, L, L, L, L, L, L,
|
||||||
|
L, L, L, 0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
S, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef S
|
||||||
|
#undef D
|
||||||
|
#undef X
|
||||||
|
#undef U
|
||||||
|
#undef L
|
||||||
|
#undef _
|
||||||
|
#undef d
|
||||||
|
|
||||||
|
/* code point ranges for Zs,Zl or Zp property */
|
||||||
|
static const uint16_t char_range_s[] = {
|
||||||
|
10,
|
||||||
|
0x0009, 0x000D + 1,
|
||||||
|
0x0020, 0x0020 + 1,
|
||||||
|
0x00A0, 0x00A0 + 1,
|
||||||
|
0x1680, 0x1680 + 1,
|
||||||
|
0x2000, 0x200A + 1,
|
||||||
|
/* 2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;; */
|
||||||
|
/* 2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;; */
|
||||||
|
0x2028, 0x2029 + 1,
|
||||||
|
0x202F, 0x202F + 1,
|
||||||
|
0x205F, 0x205F + 1,
|
||||||
|
0x3000, 0x3000 + 1,
|
||||||
|
/* FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;; */
|
||||||
|
0xFEFF, 0xFEFF + 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOL lre_is_space_non_ascii(uint32_t c)
|
||||||
|
{
|
||||||
|
size_t i, n;
|
||||||
|
|
||||||
|
n = countof(char_range_s);
|
||||||
|
for(i = 5; i < n; i += 2) {
|
||||||
|
uint32_t low = char_range_s[i];
|
||||||
|
uint32_t high = char_range_s[i + 1];
|
||||||
|
if (c < low)
|
||||||
|
return FALSE;
|
||||||
|
if (c < high)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
103
source/engine/thirdparty/quickjs/libunicode.h
vendored
103
source/engine/thirdparty/quickjs/libunicode.h
vendored
|
@ -24,27 +24,13 @@
|
||||||
#ifndef LIBUNICODE_H
|
#ifndef LIBUNICODE_H
|
||||||
#define LIBUNICODE_H
|
#define LIBUNICODE_H
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define LRE_BOOL int /* for documentation purposes */
|
|
||||||
|
|
||||||
/* define it to include all the unicode tables (40KB larger) */
|
/* define it to include all the unicode tables (40KB larger) */
|
||||||
#define CONFIG_ALL_UNICODE
|
#define CONFIG_ALL_UNICODE
|
||||||
|
|
||||||
#define LRE_CC_RES_LEN_MAX 3
|
#define LRE_CC_RES_LEN_MAX 3
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
UNICODE_NFC,
|
|
||||||
UNICODE_NFD,
|
|
||||||
UNICODE_NFKC,
|
|
||||||
UNICODE_NFKD,
|
|
||||||
} UnicodeNormalizationEnum;
|
|
||||||
|
|
||||||
int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
|
|
||||||
int lre_canonicalize(uint32_t c, LRE_BOOL is_unicode);
|
|
||||||
LRE_BOOL lre_is_cased(uint32_t c);
|
|
||||||
LRE_BOOL lre_is_case_ignorable(uint32_t c);
|
|
||||||
|
|
||||||
/* char ranges */
|
/* char ranges */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -102,12 +88,14 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
|
||||||
|
|
||||||
int cr_invert(CharRange *cr);
|
int cr_invert(CharRange *cr);
|
||||||
|
|
||||||
int cr_regexp_canonicalize(CharRange *cr, LRE_BOOL is_unicode);
|
int cr_regexp_canonicalize(CharRange *cr, int is_unicode);
|
||||||
|
|
||||||
#ifdef CONFIG_ALL_UNICODE
|
typedef enum {
|
||||||
|
UNICODE_NFC,
|
||||||
LRE_BOOL lre_is_id_start(uint32_t c);
|
UNICODE_NFD,
|
||||||
LRE_BOOL lre_is_id_continue(uint32_t c);
|
UNICODE_NFKC,
|
||||||
|
UNICODE_NFKD,
|
||||||
|
} UnicodeNormalizationEnum;
|
||||||
|
|
||||||
int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
|
int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
|
||||||
UnicodeNormalizationEnum n_type,
|
UnicodeNormalizationEnum n_type,
|
||||||
|
@ -115,13 +103,80 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
|
||||||
|
|
||||||
/* Unicode character range functions */
|
/* Unicode character range functions */
|
||||||
|
|
||||||
int unicode_script(CharRange *cr,
|
int unicode_script(CharRange *cr, const char *script_name, int is_ext);
|
||||||
const char *script_name, LRE_BOOL is_ext);
|
|
||||||
int unicode_general_category(CharRange *cr, const char *gc_name);
|
int unicode_general_category(CharRange *cr, const char *gc_name);
|
||||||
int unicode_prop(CharRange *cr, const char *prop_name);
|
int unicode_prop(CharRange *cr, const char *prop_name);
|
||||||
|
|
||||||
#endif /* CONFIG_ALL_UNICODE */
|
int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
|
||||||
|
int lre_canonicalize(uint32_t c, int is_unicode);
|
||||||
|
|
||||||
#undef LRE_BOOL
|
/* Code point type categories */
|
||||||
|
enum {
|
||||||
|
UNICODE_C_SPACE = (1 << 0),
|
||||||
|
UNICODE_C_DIGIT = (1 << 1),
|
||||||
|
UNICODE_C_UPPER = (1 << 2),
|
||||||
|
UNICODE_C_LOWER = (1 << 3),
|
||||||
|
UNICODE_C_UNDER = (1 << 4),
|
||||||
|
UNICODE_C_DOLLAR = (1 << 5),
|
||||||
|
UNICODE_C_XDIGIT = (1 << 6),
|
||||||
|
};
|
||||||
|
extern uint8_t const lre_ctype_bits[256];
|
||||||
|
|
||||||
|
/* zero or non-zero return value */
|
||||||
|
int lre_is_cased(uint32_t c);
|
||||||
|
int lre_is_case_ignorable(uint32_t c);
|
||||||
|
int lre_is_id_start(uint32_t c);
|
||||||
|
int lre_is_id_continue(uint32_t c);
|
||||||
|
|
||||||
|
static inline int lre_is_space_byte(uint8_t c) {
|
||||||
|
return lre_ctype_bits[c] & UNICODE_C_SPACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int lre_is_id_start_byte(uint8_t c) {
|
||||||
|
return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER |
|
||||||
|
UNICODE_C_UNDER | UNICODE_C_DOLLAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int lre_is_id_continue_byte(uint8_t c) {
|
||||||
|
return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER |
|
||||||
|
UNICODE_C_UNDER | UNICODE_C_DOLLAR |
|
||||||
|
UNICODE_C_DIGIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lre_is_space_non_ascii(uint32_t c);
|
||||||
|
|
||||||
|
static inline int lre_is_space(uint32_t c) {
|
||||||
|
if (c < 256)
|
||||||
|
return lre_is_space_byte(c);
|
||||||
|
else
|
||||||
|
return lre_is_space_non_ascii(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int lre_js_is_ident_first(uint32_t c) {
|
||||||
|
if (c < 128) {
|
||||||
|
return lre_is_id_start_byte(c);
|
||||||
|
} else {
|
||||||
|
#ifdef CONFIG_ALL_UNICODE
|
||||||
|
return lre_is_id_start(c);
|
||||||
|
#else
|
||||||
|
return !lre_is_space_non_ascii(c);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int lre_js_is_ident_next(uint32_t c) {
|
||||||
|
if (c < 128) {
|
||||||
|
return lre_is_id_continue_byte(c);
|
||||||
|
} else {
|
||||||
|
/* ZWNJ and ZWJ are accepted in identifiers */
|
||||||
|
if (c >= 0x200C && c <= 0x200D)
|
||||||
|
return TRUE;
|
||||||
|
#ifdef CONFIG_ALL_UNICODE
|
||||||
|
return lre_is_id_continue(c);
|
||||||
|
#else
|
||||||
|
return !lre_is_space_non_ascii(c);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* LIBUNICODE_H */
|
#endif /* LIBUNICODE_H */
|
||||||
|
|
690
source/engine/thirdparty/quickjs/quickjs.c
vendored
690
source/engine/thirdparty/quickjs/quickjs.c
vendored
File diff suppressed because it is too large
Load diff
26
source/engine/thirdparty/quickjs/quickjs.h
vendored
26
source/engine/thirdparty/quickjs/quickjs.h
vendored
|
@ -92,6 +92,7 @@ typedef struct JSRefCountHeader {
|
||||||
} JSRefCountHeader;
|
} JSRefCountHeader;
|
||||||
|
|
||||||
void quickjs_set_dumpout(FILE *f);
|
void quickjs_set_dumpout(FILE *f);
|
||||||
|
void JS_SetInterruptRate(int count);
|
||||||
|
|
||||||
#define JS_FLOAT64_NAN NAN
|
#define JS_FLOAT64_NAN NAN
|
||||||
|
|
||||||
|
@ -635,7 +636,9 @@ static inline JS_BOOL JS_IsObject(JSValueConst v)
|
||||||
|
|
||||||
JSValue JS_Throw(JSContext *ctx, JSValue obj);
|
JSValue JS_Throw(JSContext *ctx, JSValue obj);
|
||||||
JSValue JS_GetException(JSContext *ctx);
|
JSValue JS_GetException(JSContext *ctx);
|
||||||
|
JS_BOOL JS_HasException(JSContext *ctx);
|
||||||
JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val);
|
JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val);
|
||||||
|
void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, JS_BOOL flag);
|
||||||
void JS_ResetUncatchableError(JSContext *ctx);
|
void JS_ResetUncatchableError(JSContext *ctx);
|
||||||
JSValue JS_NewError(JSContext *ctx);
|
JSValue JS_NewError(JSContext *ctx);
|
||||||
JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...);
|
JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...);
|
||||||
|
@ -684,6 +687,10 @@ static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v)
|
||||||
return (JSValue)v;
|
return (JSValue)v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS_BOOL JS_StrictEq(JSContext *ctx, JSValueConst op1, JSValueConst op2);
|
||||||
|
JS_BOOL JS_SameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2);
|
||||||
|
JS_BOOL JS_SameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2);
|
||||||
|
|
||||||
int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
|
int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
|
||||||
int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val);
|
int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val);
|
||||||
static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
|
static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
|
||||||
|
@ -726,6 +733,8 @@ JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, JS_BOOL val)
|
||||||
JSValue JS_NewArray(JSContext *ctx);
|
JSValue JS_NewArray(JSContext *ctx);
|
||||||
int JS_IsArray(JSContext *ctx, JSValueConst val);
|
int JS_IsArray(JSContext *ctx, JSValueConst val);
|
||||||
|
|
||||||
|
JSValue JS_NewDate(JSContext *ctx, double epoch_ms);
|
||||||
|
|
||||||
JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
|
JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
|
||||||
JSAtom prop, JSValueConst receiver,
|
JSAtom prop, JSValueConst receiver,
|
||||||
JS_BOOL throw_ref_error);
|
JS_BOOL throw_ref_error);
|
||||||
|
@ -824,6 +833,23 @@ JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len,
|
||||||
JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len);
|
JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len);
|
||||||
void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj);
|
void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj);
|
||||||
uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj);
|
uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj);
|
||||||
|
|
||||||
|
typedef enum JSTypedArrayEnum {
|
||||||
|
JS_TYPED_ARRAY_UINT8C = 0,
|
||||||
|
JS_TYPED_ARRAY_INT8,
|
||||||
|
JS_TYPED_ARRAY_UINT8,
|
||||||
|
JS_TYPED_ARRAY_INT16,
|
||||||
|
JS_TYPED_ARRAY_UINT16,
|
||||||
|
JS_TYPED_ARRAY_INT32,
|
||||||
|
JS_TYPED_ARRAY_UINT32,
|
||||||
|
JS_TYPED_ARRAY_BIG_INT64,
|
||||||
|
JS_TYPED_ARRAY_BIG_UINT64,
|
||||||
|
JS_TYPED_ARRAY_FLOAT32,
|
||||||
|
JS_TYPED_ARRAY_FLOAT64,
|
||||||
|
} JSTypedArrayEnum;
|
||||||
|
|
||||||
|
JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv,
|
||||||
|
JSTypedArrayEnum array_type);
|
||||||
JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj,
|
JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj,
|
||||||
size_t *pbyte_offset,
|
size_t *pbyte_offset,
|
||||||
size_t *pbyte_length,
|
size_t *pbyte_length,
|
||||||
|
|
22
source/engine/timer.c
Normal file
22
source/engine/timer.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
#include "stb_ds.h"
|
||||||
|
|
||||||
|
timer *timers;
|
||||||
|
|
||||||
|
timer *timer_make()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_free(timer *t)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_update(double dt)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < arrlen(timers); i++) {
|
||||||
|
timers[i].remain -= dt;
|
||||||
|
}
|
||||||
|
}
|
13
source/engine/timer.h
Normal file
13
source/engine/timer.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef TIMER_H
|
||||||
|
|
||||||
|
typedef struct timer {
|
||||||
|
double start;
|
||||||
|
double remain;
|
||||||
|
} timer;
|
||||||
|
|
||||||
|
|
||||||
|
timer *timer_make();
|
||||||
|
void timer_free(timer *t);
|
||||||
|
void timer_update(double dt);
|
||||||
|
|
||||||
|
#endif
|
|
@ -5,16 +5,21 @@
|
||||||
transform *make_transform()
|
transform *make_transform()
|
||||||
{
|
{
|
||||||
transform *t = calloc(sizeof(transform),1);
|
transform *t = calloc(sizeof(transform),1);
|
||||||
|
|
||||||
t->scale = (HMM_Vec3){1,1,1};
|
t->scale = (HMM_Vec3){1,1,1};
|
||||||
t->rotation = (HMM_Quat){0,0,0,1};
|
t->rotation = (HMM_Quat){0,0,0,1};
|
||||||
|
t->dirty = 1;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void transform_free(transform *t) { free(t); }
|
void transform_free(transform *t) { free(t); }
|
||||||
|
|
||||||
|
void transform_apply(transform *t) { t->dirty = 1; }
|
||||||
|
|
||||||
void transform_move(transform *t, HMM_Vec3 v)
|
void transform_move(transform *t, HMM_Vec3 v)
|
||||||
{
|
{
|
||||||
t->pos = HMM_AddV3(t->pos, v);
|
t->pos = HMM_AddV3(t->pos, v);
|
||||||
|
t->dirty = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
HMM_Vec3 transform_direction(transform *t, HMM_Vec3 dir)
|
HMM_Vec3 transform_direction(transform *t, HMM_Vec3 dir)
|
||||||
|
@ -42,7 +47,6 @@ HMM_Vec2 mat_right(HMM_Mat3 m) { return HMM_NormV2(m.Columns[0].XY); }
|
||||||
float vec_angle(HMM_Vec2 a, HMM_Vec2 b) { return acos(HMM_DotV2(a,b)/(HMM_LenV2(a)*HMM_LenV2(b))); }
|
float vec_angle(HMM_Vec2 a, HMM_Vec2 b) { return acos(HMM_DotV2(a,b)/(HMM_LenV2(a)*HMM_LenV2(b))); }
|
||||||
float vec_dirangle(HMM_Vec2 a, HMM_Vec2 b) { return atan2(b.x, b.y) - atan2(a.x, a.y); }
|
float vec_dirangle(HMM_Vec2 a, HMM_Vec2 b) { return atan2(b.x, b.y) - atan2(a.x, a.y); }
|
||||||
|
|
||||||
|
|
||||||
HMM_Vec3 mat3_t_pos(HMM_Mat4 m, HMM_Vec3 pos) { return HMM_MulM4V4(m, (HMM_Vec4){pos.X, pos.Y, pos.Z, 1}).XYZ; }
|
HMM_Vec3 mat3_t_pos(HMM_Mat4 m, HMM_Vec3 pos) { return HMM_MulM4V4(m, (HMM_Vec4){pos.X, pos.Y, pos.Z, 1}).XYZ; }
|
||||||
|
|
||||||
HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir)
|
HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir)
|
||||||
|
@ -51,8 +55,15 @@ HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir)
|
||||||
return mat3_t_pos(m, dir);
|
return mat3_t_pos(m, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
HMM_Mat4 transform2mat(transform t) {
|
HMM_Mat4 transform2mat(transform *t) {
|
||||||
return HMM_M4TRS(t.pos, t.rotation, t.scale);
|
return HMM_M4TRS(t->pos, t->rotation, t->scale);
|
||||||
|
|
||||||
|
if (t->dirty) {
|
||||||
|
t->cache = HMM_M4TRS(t->pos, t->rotation, t->scale);
|
||||||
|
t->dirty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t->cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
HMM_Quat angle2rotation(float angle)
|
HMM_Quat angle2rotation(float angle)
|
||||||
|
|
|
@ -12,6 +12,7 @@ typedef struct transform {
|
||||||
} transform;
|
} transform;
|
||||||
|
|
||||||
transform *make_transform();
|
transform *make_transform();
|
||||||
|
void transform_apply(transform *t);
|
||||||
void transform_free(transform *t);
|
void transform_free(transform *t);
|
||||||
|
|
||||||
#define VEC2_FMT "[%g,%g]"
|
#define VEC2_FMT "[%g,%g]"
|
||||||
|
@ -33,7 +34,7 @@ float vec_dirangle(HMM_Vec2 a, HMM_Vec2 b);
|
||||||
HMM_Vec3 mat3_t_pos(HMM_Mat4 m, HMM_Vec3 pos);
|
HMM_Vec3 mat3_t_pos(HMM_Mat4 m, HMM_Vec3 pos);
|
||||||
HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir);
|
HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir);
|
||||||
|
|
||||||
HMM_Mat4 transform2mat(transform t);
|
HMM_Mat4 transform2mat(transform *t);
|
||||||
transform mat2transform(HMM_Mat4 m);
|
transform mat2transform(HMM_Mat4 m);
|
||||||
|
|
||||||
HMM_Quat angle2rotation(float angle);
|
HMM_Quat angle2rotation(float angle);
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
#include "spline.h"
|
#include "spline.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "particle.h"
|
|
||||||
#include "simplex.h"
|
#include "simplex.h"
|
||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue