repl tab completion; rgb text coloring
This commit is contained in:
parent
9701cd2b4a
commit
5db00e9019
150
scripts/base.js
150
scripts/base.js
|
@ -10,12 +10,38 @@
|
|||
In addition to the removal of a bunch of stuff as seen here.
|
||||
Access prototypes through __proto__ instead of the long-winded Object.getProtoTypeOf.
|
||||
*/
|
||||
var FNRM = function() { Log.error("removed"); };
|
||||
Object.getPrototypeOf = FNRM;
|
||||
Object.setPrototypeOf = FNRM;
|
||||
Reflect = {};
|
||||
Symbol = {};
|
||||
URIError = {};
|
||||
|
||||
Object.getPrototypeOf = undefined;
|
||||
Object.setPrototypeOf = undefined;
|
||||
Reflect = undefined;
|
||||
Symbol = undefined;
|
||||
URIError = undefined;
|
||||
Proxy = undefined;
|
||||
Map = undefined;
|
||||
WeakMap = undefined;
|
||||
Promise = undefined;
|
||||
Set = undefined;
|
||||
WeakSet = undefined;
|
||||
|
||||
Object.methods = function(o)
|
||||
{
|
||||
var m = [];
|
||||
Object.keys(o).forEach(function(k) {
|
||||
if (typeof o[k] === 'function') m.push(k);
|
||||
});
|
||||
return m;
|
||||
}
|
||||
|
||||
Object.rkeys = function(o)
|
||||
{
|
||||
var keys = [];
|
||||
Object.keys(o).forEach(function(key) {
|
||||
keys.push(key);
|
||||
if (Object.isObject(o[key]))
|
||||
keys.push(Object.rkeys(o[key]));
|
||||
});
|
||||
return keys;
|
||||
}
|
||||
|
||||
Object.mixin = function(target, source)
|
||||
{
|
||||
|
@ -356,49 +382,51 @@ Object.defineProperty(String.prototype, 'shift', {
|
|||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'strip_ext', {
|
||||
value: function() {
|
||||
var idx = this.lastIndexOf('.');
|
||||
value: function() { return this.tolast('.'); }
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'ext', {
|
||||
value: function() { return this.fromlast('.'); }
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'set_ext', {
|
||||
value: function(val) { return this.strip_ext() + val; }
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'fromlast', {
|
||||
value: function(val) {
|
||||
var idx = this.lastIndexOf(val);
|
||||
if (idx === -1) return "";
|
||||
return this.slice(idx+1);
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'tolast', {
|
||||
value: function(val) {
|
||||
var idx = this.lastIndexOf(val);
|
||||
if (idx === -1) return this.slice();
|
||||
return this.slice(0,idx);
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'ext', {
|
||||
value: function() {
|
||||
var idx = this.lastIndexOf('.');
|
||||
if (idx === -1) return undefined;
|
||||
return this.slice(idx);
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'set_ext', {
|
||||
Object.defineProperty(String.prototype, 'tofirst', {
|
||||
value: function(val) {
|
||||
var s = this.strip_ext();
|
||||
return s + val;
|
||||
var idx = this.indexOf(val);
|
||||
if (idx === -1) return this.slice();
|
||||
return this.slice(0,idx);
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'name', {
|
||||
value: function() {
|
||||
var s = this.lastIndexOf('/');
|
||||
var e = this.lastIndexOf('.');
|
||||
if (e === -1) e = this.length;
|
||||
return this.slice(s+1,e);
|
||||
}
|
||||
value: function() { return this.fromlast('/').tolast('.'); }
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'base', {
|
||||
value: function() {
|
||||
return this.slice(this.lastIndexOf('/')+1);
|
||||
}
|
||||
value: function() { return this.fromlast('/'); }
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'dir', {
|
||||
value: function() {
|
||||
var e = this.lastIndexOf('/');
|
||||
if (e === -1) return "";
|
||||
return this.slice(0, e);
|
||||
}
|
||||
value: function() { return this.tolast('/'); }
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'updir', {
|
||||
|
@ -411,6 +439,25 @@ Object.defineProperty(String.prototype, 'updir', {
|
|||
}
|
||||
});
|
||||
|
||||
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, 'uc', { value: function() { return this.toUpperCase(); } });
|
||||
|
||||
Object.defineProperty(String.prototype, 'lc', {value:function() { return this.toLowerCase(); }});
|
||||
|
||||
|
||||
/* ARRAY DEFS */
|
||||
|
||||
Object.defineProperty(Array.prototype, 'copy', {
|
||||
|
@ -425,6 +472,36 @@ Object.defineProperty(Array.prototype, 'copy', {
|
|||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(Array.prototype, 'dofilter', {
|
||||
value: function(fn) {
|
||||
var j = 0;
|
||||
this.forEach(function(val,i) {
|
||||
if (fn(val)) {
|
||||
if (i !== j) this[j] = val;
|
||||
j++;
|
||||
}
|
||||
}, this);
|
||||
this.length = j;
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function filterInPlace(a, condition, thisArg) {
|
||||
let j = 0;
|
||||
|
||||
a.forEach((e, i) => {
|
||||
if (condition.call(thisArg, e, i, a)) {
|
||||
if (i!==j) a[j] = e;
|
||||
j++;
|
||||
}
|
||||
});
|
||||
|
||||
a.length = j;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
Object.defineProperty(Array.prototype, 'reversed', {
|
||||
value: function() {
|
||||
var c = this.slice();
|
||||
|
@ -693,6 +770,13 @@ Number.prec = function(num)
|
|||
return parseFloat(num.toFixed(3));
|
||||
}
|
||||
|
||||
Number.hex = function(n)
|
||||
{
|
||||
var s = Math.floor(n).toString(16);
|
||||
if (s.length === 1) s = '0' + s;
|
||||
return s.uc();
|
||||
}
|
||||
|
||||
Object.defineProperty(Object.prototype, 'lerp',{
|
||||
value: function(to, t) {
|
||||
var self = this;
|
||||
|
|
|
@ -1278,7 +1278,7 @@ var inputpanel = {
|
|||
padding:[5,-15],
|
||||
|
||||
gui() {
|
||||
this.win = Mum.window({width:this.wh.x,height:this.wh.y, color:Color.black.alpha(0.1), anchor:this.anchor, padding:this.padding});
|
||||
this.win ??= Mum.window({width:this.wh.x,height:this.wh.y, color:Color.black.alpha(0.1), anchor:this.anchor, padding:this.padding});
|
||||
var itms = this.guibody();
|
||||
if (!Array.isArray(itms)) itms = [itms];
|
||||
if (this.title)
|
||||
|
@ -1356,29 +1356,44 @@ var inputpanel = {
|
|||
};
|
||||
|
||||
inputpanel.inputs = {};
|
||||
|
||||
inputpanel.inputs.post = function()
|
||||
{
|
||||
this.keycb();
|
||||
}
|
||||
|
||||
inputpanel.inputs.char = function(c) {
|
||||
this.value = this.value.slice(0,this.caret) + c + this.value.slice(this.caret);
|
||||
this.caret++;
|
||||
this.keycb();
|
||||
}
|
||||
inputpanel.inputs['C-d'] = function() { this.value = this.value.slice(0,this.caret) + this.value.slice(this.caret+1); };
|
||||
inputpanel.inputs.tab = function() { this.value = tab_complete(this.value, this.assets); this.caret = this.value.length;}
|
||||
inputpanel.inputs['C-d'].rep = true;
|
||||
inputpanel.inputs.tab = function() {
|
||||
this.value = tab_complete(this.value, this.assets);
|
||||
this.caret = this.value.length;
|
||||
}
|
||||
inputpanel.inputs.escape = function() { this.close(); }
|
||||
inputpanel.inputs['C-b'] = function() {
|
||||
if (this.caret === 0) return;
|
||||
this.caret--;
|
||||
};
|
||||
inputpanel.inputs['C-b'].rep = true;
|
||||
inputpanel.inputs['C-u'] = function()
|
||||
{
|
||||
this.value = this.value.slice(this.caret);
|
||||
this.caret = 0;
|
||||
}
|
||||
inputpanel.inputs['C-f'] = function() {
|
||||
if (this.caret === this.value.length) return;
|
||||
this.caret++;
|
||||
};
|
||||
inputpanel.inputs['C-f'].rep = true;
|
||||
inputpanel.inputs['C-a'] = function() { this.caret = 0; };
|
||||
inputpanel.inputs['C-e'] = function() { this.caret = this.value.length; };
|
||||
inputpanel.inputs.backspace = function() {
|
||||
if (this.caret === 0) return;
|
||||
this.value = this.value.slice(0,this.caret-1) + this.value.slice(this.caret);
|
||||
this.caret--;
|
||||
this.keycb();
|
||||
};
|
||||
inputpanel.inputs.backspace.rep = true;
|
||||
inputpanel.inputs.enter = function() { this.submit(); }
|
||||
|
@ -1387,7 +1402,6 @@ inputpanel.inputs['C-k'] = function() {
|
|||
this.value = this.value.slice(0,this.caret);
|
||||
};
|
||||
|
||||
|
||||
function proto_count_lvls(name)
|
||||
{
|
||||
if (!this.occs) this.occs = {};
|
||||
|
@ -1440,13 +1454,15 @@ var replpanel = Object.copy(inputpanel, {
|
|||
pos: [50,50],
|
||||
anchor: [0,0],
|
||||
padding: [0,0],
|
||||
scrolloffset: [0,0],
|
||||
|
||||
guibody() {
|
||||
this.win.selectable = true;
|
||||
var log = cmd(84);
|
||||
log = log.slice(-500);
|
||||
log = log.slice(-5000);
|
||||
|
||||
return [
|
||||
Mum.text({str:log, anchor:[0,0], offset:[0,-300]}),
|
||||
Mum.text({str:log, anchor:[0,0], offset:[0,-300].sub(this.scrolloffset), selectable: true}),
|
||||
Mum.text({str:this.value,color:Color.green, offset:[0,-290], caret: this.caret})
|
||||
];
|
||||
},
|
||||
|
@ -1470,9 +1486,72 @@ var replpanel = Object.copy(inputpanel, {
|
|||
var ret = function() {return eval(ecode);}.call(repl_obj);
|
||||
Log.say(ret);
|
||||
},
|
||||
|
||||
resetscroll() {
|
||||
this.scrolloffset.y = 0;
|
||||
},
|
||||
});
|
||||
|
||||
replpanel.inputs = Object.create(inputpanel.inputs);
|
||||
replpanel.inputs.tab = function() {
|
||||
this.resetscroll();
|
||||
var obj = globalThis;
|
||||
var keys = [];
|
||||
var keyobj = this.value.tolast('.');
|
||||
var o = this.value.tolast('.');
|
||||
var stub = this.value.fromlast('.');
|
||||
var replobj = (editor.selectlist.length === 1) ? "editor.selectlist[0]" : "editor.edit_level";
|
||||
|
||||
if (this.value.startswith("this."))
|
||||
keyobj = keyobj.replace("this", replobj);
|
||||
|
||||
if (!this.value.includes('.')) keys.push("this");
|
||||
|
||||
if (eval(`typeof ${keyobj.tofirst('.')}`) === 'object' && eval(`typeof ${keyobj.replace('.', '?.')}`) === 'object') {
|
||||
Log.warn("set obj to " + keyobj);
|
||||
obj = eval(keyobj);
|
||||
}
|
||||
else if (this.value.includes('.')){
|
||||
Log.say(`${this.value} is not an object.`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (var k in obj)
|
||||
keys.push(k)
|
||||
|
||||
var comp = "";
|
||||
if (stub)
|
||||
comp = tab_complete(stub, keys);
|
||||
else if (!this.value.includes('.'))
|
||||
comp = tab_complete(o, keys);
|
||||
else
|
||||
comp = tab_complete("",keys);
|
||||
|
||||
if (stub)
|
||||
this.value = o + '.' + comp;
|
||||
else if (this.value.endswith('.'))
|
||||
this.value = o + '.' + comp;
|
||||
else
|
||||
this.value = comp;
|
||||
|
||||
this.caret = this.value.length;
|
||||
|
||||
keys = keys.sort();
|
||||
|
||||
keys = keys.map(function(x) {
|
||||
if (typeof obj[x] === 'function')
|
||||
return Esc.color(Color.Apple.orange) + x + Esc.reset;
|
||||
if (Object.isObject(obj[x]))
|
||||
return Esc.color(Color.Apple.purple) + x + Esc.reset;
|
||||
if (Array.isArray(obj[x]))
|
||||
return Esc.color(Color.Apple.green) + x + Esc.reset;
|
||||
|
||||
return x;
|
||||
});
|
||||
|
||||
if (keys.length > 1)
|
||||
Log.say(keys.join(', '));
|
||||
};
|
||||
replpanel.inputs['C-p'] = function()
|
||||
{
|
||||
if (this.prevmark >= this.prevthis.length) return;
|
||||
|
@ -1493,6 +1572,40 @@ replpanel.inputs['C-n'] = function()
|
|||
this.inputs['C-e'].call(this);
|
||||
}
|
||||
|
||||
replpanel.inputs.mouse = {};
|
||||
replpanel.inputs.mouse.scroll = function(scroll)
|
||||
{
|
||||
if (!this.win.selected) return;
|
||||
|
||||
this.scrolloffset.y += scroll.y;
|
||||
if (this.scrolloffset.y < 0) this.scrolloffset.y = 0;
|
||||
}
|
||||
|
||||
replpanel.inputs.up = function()
|
||||
{
|
||||
this.scrolloffset.y += 40;
|
||||
}
|
||||
replpanel.inputs.up.rep = true;
|
||||
replpanel.inputs.down = function()
|
||||
{
|
||||
this.scrolloffset.y -= 40;
|
||||
if (this.scrolloffset.y < 0) this.scrolloffset.y = 0;
|
||||
}
|
||||
replpanel.inputs.down.rep = true;
|
||||
|
||||
replpanel.inputs.pgup = function()
|
||||
{
|
||||
this.scrolloffset.y += 300;
|
||||
}
|
||||
replpanel.inputs.pgup.rep = true;
|
||||
|
||||
replpanel.inputs.pgdown = function()
|
||||
{
|
||||
this.scrolloffset.y -= 300;
|
||||
if (this.scrolloffset.y < 0) this.scrolloffset.y = 0;
|
||||
}
|
||||
replpanel.inputs.pgdown.rep = true;
|
||||
|
||||
var objectexplorer = Object.copy(inputpanel, {
|
||||
title: "object explorer",
|
||||
obj: undefined,
|
||||
|
@ -1778,29 +1891,27 @@ var assetexplorer = Object.copy(openlevelpanel, {
|
|||
});
|
||||
|
||||
function tab_complete(val, list) {
|
||||
var check = list.filter(function(x) { return x.startsWith(val); }, this);
|
||||
if (check.length === 1) {
|
||||
list = check;
|
||||
return check[0];
|
||||
if (!val) return val;
|
||||
list.dofilter(function(x) { return x.startsWith(val); });
|
||||
Log.warn(list);
|
||||
Log.warn(val);
|
||||
if (list.length === 1) {
|
||||
return list[0];
|
||||
}
|
||||
|
||||
var ret = undefined;
|
||||
var i = val.length;
|
||||
while (!ret && !check.empty) {
|
||||
|
||||
var char = check[0][i];
|
||||
if (!check.every(function(x) { return x[i] === char; }))
|
||||
ret = check[0].slice(0, i);
|
||||
while (!ret && !list.empty) {
|
||||
var char = list[0][i];
|
||||
if (!list.every(function(x) { return x[i] === char; }))
|
||||
ret = list[0].slice(0, i);
|
||||
else {
|
||||
i++;
|
||||
check = check.filter(function(x) { return x.length-1 > i; });
|
||||
list.dofilter(function(x) { return x.length-1 > i; });
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret) return val;
|
||||
|
||||
list = check;
|
||||
return ret;
|
||||
return ret ? ret : val;
|
||||
}
|
||||
|
||||
var texgui = Object.copy(inputpanel, {
|
||||
|
|
|
@ -43,6 +43,25 @@ var Color = {
|
|||
purple: [162,93,227],
|
||||
};
|
||||
|
||||
Color.tohtml = function(v)
|
||||
{
|
||||
var html = v.map(function(n) { return Number.hex(n*255); });
|
||||
return "#" + html.join('');
|
||||
}
|
||||
|
||||
Color.toesc = function(v)
|
||||
{
|
||||
return Esc.color(v);
|
||||
}
|
||||
|
||||
var Esc = {};
|
||||
Esc.reset = "\x1b[0";
|
||||
Esc.color = function(v) {
|
||||
var c = v.map(function(n) { return Math.floor(n*255); });
|
||||
var truecolor = "\x1b[38;2;" + c.join(';') + ';';
|
||||
return truecolor;
|
||||
}
|
||||
|
||||
Color.Arkanoid = {
|
||||
orange: [255,143,0],
|
||||
teal: [0,255,255],
|
||||
|
|
|
@ -183,6 +183,14 @@ var gameobject = {
|
|||
return bb.t-bb.b;
|
||||
},
|
||||
|
||||
move(vec) {
|
||||
this.pos = this.pos.add(vec);
|
||||
},
|
||||
|
||||
rotate(amt) {
|
||||
this.angle += amt;
|
||||
},
|
||||
|
||||
/* Make a unique object the same as its prototype */
|
||||
revert() {
|
||||
Object.merge(this,this.__proto__);
|
||||
|
@ -529,7 +537,11 @@ prototypes.from_file = function(file)
|
|||
var json = undefined;
|
||||
|
||||
if (jsfile) script = IO.slurp(jsfile);
|
||||
if (jsonfile) json = JSON.parse(IO.slurp(jsonfile));
|
||||
try {
|
||||
if (jsonfile) json = JSON.parse(IO.slurp(jsonfile));
|
||||
} catch(e) {
|
||||
Log.warn(e);
|
||||
}
|
||||
|
||||
if (!json && !script) {
|
||||
Log.warn(`Could not make ur from ${file}`);
|
||||
|
|
|
@ -67,33 +67,34 @@ var GUI = {
|
|||
var gui_controls = {};
|
||||
gui_controls.update = function() { };
|
||||
|
||||
gui_controls.options = [];
|
||||
gui_controls.set_mum = function(mum)
|
||||
{
|
||||
mum.selected = true;
|
||||
|
||||
if (this.selected && this.selected !== mum)
|
||||
this.selected.selected = false;
|
||||
|
||||
this.selected = mum;
|
||||
}
|
||||
gui_controls.check_bb = function(mum)
|
||||
{
|
||||
if (pointinbb(mum.bb, Mouse.pos))
|
||||
gui_controls.set_mum(mum);
|
||||
}
|
||||
gui_controls.inputs = {};
|
||||
gui_controls.inputs.fallthru = false;
|
||||
gui_controls.inputs.mouse = {};
|
||||
gui_controls.inputs.mouse.move = function(pos,dpos)
|
||||
{
|
||||
var newsel = undefined;
|
||||
this.options.forEach(function(x) {
|
||||
if (pointinbb(x.bb,pos)) {
|
||||
newsel = x;
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
gui_controls.inputs.mouse.scroll = function(scroll)
|
||||
{
|
||||
|
||||
if (this.selected && this.selected !== newsel)
|
||||
this.selected.selected = false;
|
||||
|
||||
this.selected = newsel;
|
||||
if (this.selected)
|
||||
this.selected.selected = true;
|
||||
}
|
||||
|
||||
gui_controls.inputs.lm = function() {
|
||||
if (this.selected) {
|
||||
Log.warn(this.selected.str);
|
||||
if (this.selected && this.selected.action)
|
||||
this.selected.action(this.selected);
|
||||
}
|
||||
};
|
||||
|
||||
var Mum = {
|
||||
|
@ -153,7 +154,7 @@ Mum.text = Mum.extend({
|
|||
draw(cursor, cnt) {
|
||||
cnt ??= Mum;
|
||||
if (this.hide) return;
|
||||
if (this.selectable) gui_controls.options.push_unique(this);
|
||||
if (this.selectable) gui_controls.check_bb(this);
|
||||
this.caret ??= -1;
|
||||
|
||||
/* if (!this.bb)
|
||||
|
@ -209,7 +210,7 @@ Mum.window = Mum.extend({
|
|||
GUI.flush();
|
||||
GUI.scissor(p.x,p.y,this.wh.x,this.wh.y);
|
||||
this.max_width = this.width;
|
||||
|
||||
if (this.selectable) gui_controls.check_bb(this);
|
||||
var pos = [this.bb.l, this.bb.t].add(this.padding);
|
||||
this.items.forEach(function(item) {
|
||||
if (item.hide) return;
|
||||
|
|
|
@ -19,11 +19,11 @@ var Music = {
|
|||
var Sound = {
|
||||
sounds: [], /* array of loaded sound files */
|
||||
play(file) {
|
||||
// var s = Object.create(Sound);
|
||||
// s.path = file;
|
||||
// s.play();
|
||||
if (!IO.exists(file)) {
|
||||
Log.warn(`Cannot play sound ${file}: does not exist.`);
|
||||
return;
|
||||
}
|
||||
this.id = cmd(14,file);
|
||||
//return s;
|
||||
},
|
||||
|
||||
music(midi, sf) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
var texteditor = Object.copy(inputpanel, {
|
||||
title: "text editor",
|
||||
wh: [700,500],
|
||||
_cursor:0, /* Text cursor: [char,line] */
|
||||
get cursor() { return this._cursor; },
|
||||
set cursor(x) {
|
||||
|
@ -68,8 +69,11 @@ var texteditor = Object.copy(inputpanel, {
|
|||
return this.startbuffer !== this.value;
|
||||
},
|
||||
|
||||
src: "NEW FILE",
|
||||
|
||||
guibody() {
|
||||
return [
|
||||
Mum.text({str:`EDITING ${this.src}`}),
|
||||
Mum.text({str:this.value, caret:this.cursor, offset:[0,-16]}),
|
||||
];
|
||||
},
|
||||
|
@ -170,6 +174,7 @@ var texteditor = Object.copy(inputpanel, {
|
|||
});
|
||||
|
||||
texteditor.inputs = {};
|
||||
|
||||
texteditor.inputs.char = function(char) {
|
||||
this.insert_char(char);
|
||||
this.keycb();
|
||||
|
@ -192,11 +197,11 @@ texteditor.inputs.backspace.rep = true;
|
|||
|
||||
|
||||
texteditor.inputs['C-s'] = function() {
|
||||
editor.edit_level.script = texteditor.value;
|
||||
editor.save_current();
|
||||
texteditor.startbuffer = texteditor.value.slice();
|
||||
if (this.srctype === 'function') {
|
||||
eval(`${this.src} = ${this.value}`);
|
||||
}
|
||||
};
|
||||
texteditor.inputs['C-s'].doc = "Save script to file.";
|
||||
texteditor.inputs['C-s'].doc = "Save edited text.";
|
||||
|
||||
texteditor.inputs['C-u'] = function() { this.popstate(); };
|
||||
texteditor.inputs['C-u'].doc = "Undo.";
|
||||
|
@ -335,3 +340,17 @@ texteditor.inputs['M-n'] = function() {
|
|||
};
|
||||
texteditor.inputs['M-n'].doc = "Go down to next line with text on it.";
|
||||
texteditor.inputs['M-n'].rep = true;
|
||||
|
||||
texteditor.open_fn = function(fnstr)
|
||||
{
|
||||
var fn = eval(fnstr);
|
||||
if (!fn) {
|
||||
Log.warn(`${fnstr} is not a function.`);
|
||||
return;
|
||||
}
|
||||
this.src = fnstr;
|
||||
this.srctype = "function";
|
||||
editor.openpanel(this);
|
||||
this.value = fn;
|
||||
this.cursor = 0;
|
||||
}
|
||||
|
|
|
@ -277,7 +277,7 @@ JSValue vecarr2js(cpVect *points, int n) {
|
|||
}
|
||||
|
||||
JSValue duk_ui_text(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
|
||||
const char *s = JS_ToCString(js, argv[0]);
|
||||
const unsigned char *s = JS_ToCString(js, argv[0]);
|
||||
HMM_Vec2 pos = js2hmmv2(argv[1]);
|
||||
|
||||
float size = js2number(argv[2]);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
struct sFont *font;
|
||||
|
||||
#define max_chars 4000
|
||||
#define max_chars 10000
|
||||
|
||||
static sg_shader fontshader;
|
||||
static sg_bindings bind_text;
|
||||
|
@ -139,7 +139,7 @@ struct sFont *MakeFont(const char *fontfile, int height) {
|
|||
|
||||
stbtt_GetFontVMetrics(&fontinfo, &newfont->ascent, &newfont->descent, &newfont->linegap);
|
||||
newfont->emscale = stbtt_ScaleForMappingEmToPixels(&fontinfo, 16);
|
||||
newfont->linegap = (newfont->ascent - newfont->descent) * 1.5*newfont->emscale/2;
|
||||
newfont->linegap = (newfont->ascent - newfont->descent) * newfont->emscale;
|
||||
|
||||
newfont->texID = sg_make_image(&(sg_image_desc){
|
||||
.type = SG_IMAGETYPE_2D,
|
||||
|
@ -246,8 +246,37 @@ void text_settype(struct sFont *mfont) {
|
|||
font = mfont;
|
||||
}
|
||||
|
||||
struct boundingbox text_bb(const char *text, float scale, float lw, float tracking)
|
||||
unsigned char *esc_color(unsigned char *c, struct rgba *color, struct rgba defc)
|
||||
{
|
||||
struct rgba d;
|
||||
if (!color) color = &d;
|
||||
if (*c != '\e') c;
|
||||
c++;
|
||||
if (*c != '[') return c;
|
||||
c++;
|
||||
if (*c == '0') {
|
||||
*color = defc;
|
||||
c++;
|
||||
return c;
|
||||
}
|
||||
else if (!strncmp(c, "38;2;", 5)) {
|
||||
c += 5;
|
||||
*color = (struct rgba){0,0,0,255};
|
||||
color->r = atoi(c);
|
||||
c = strchr(c, ';')+1;
|
||||
color->g = atoi(c);
|
||||
c = strchr(c,';')+1;
|
||||
color->b = atoi(c);
|
||||
c = strchr(c,';')+1;
|
||||
return c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
struct boundingbox text_bb(const unsigned char *text, float scale, float lw, float tracking)
|
||||
{
|
||||
struct rgba dummy;
|
||||
HMM_Vec2 cursor = {0,0};
|
||||
const unsigned char *c = text;
|
||||
const unsigned char *line, *wordstart, *drawstart;
|
||||
|
@ -262,6 +291,9 @@ struct boundingbox text_bb(const char *text, float scale, float lw, float tracki
|
|||
cursor.X = 0;
|
||||
line++;
|
||||
} else {
|
||||
if (*line == '\e')
|
||||
line = esc_color(line, NULL, dummy);
|
||||
|
||||
wordstart = line;
|
||||
int wordWidth = 0;
|
||||
|
||||
|
@ -276,6 +308,9 @@ struct boundingbox text_bb(const char *text, float scale, float lw, float tracki
|
|||
}
|
||||
|
||||
while (wordstart < line) {
|
||||
if (*wordstart == '\e')
|
||||
line = esc_color(wordstart, NULL, dummy);
|
||||
|
||||
cursor.X += font->Characters[*wordstart].Advance * tracking * scale;
|
||||
wordstart++;
|
||||
}
|
||||
|
@ -291,38 +326,42 @@ void check_caret(int caret, int l, HMM_Vec2 pos, float scale, struct rgba color)
|
|||
draw_char_box(font->Characters[0], pos, scale, color);
|
||||
}
|
||||
|
||||
|
||||
/* pos given in screen coordinates */
|
||||
int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, float lw, int caret, float tracking) {
|
||||
int renderText(const unsigned char *text, HMM_Vec2 pos, float scale, struct rgba color, float lw, int caret, float tracking) {
|
||||
int len = strlen(text);
|
||||
|
||||
HMM_Vec2 cursor = pos;
|
||||
|
||||
int l = 0;
|
||||
const unsigned char *line, *wordstart, *drawstart;
|
||||
line = drawstart = (unsigned char *)text;
|
||||
|
||||
struct rgba usecolor = color;
|
||||
check_caret(caret, l, cursor, scale, usecolor);
|
||||
check_caret(caret, line-drawstart, cursor, scale, usecolor);
|
||||
|
||||
while (line[l] != '\0') {
|
||||
if (isblank(line[l])) {
|
||||
sdrawCharacter(font->Characters[line[l]], cursor, scale, usecolor);
|
||||
cursor.X += font->Characters[line[l]].Advance * tracking * scale;
|
||||
l++;
|
||||
check_caret(caret, l, cursor, scale, usecolor);
|
||||
} else if (isspace(line[l])) {
|
||||
sdrawCharacter(font->Characters[line[l]], cursor, scale, usecolor);
|
||||
while (*line != '\0') {
|
||||
if (isblank(*line)) {
|
||||
sdrawCharacter(font->Characters[*line], cursor, scale, usecolor);
|
||||
cursor.X += font->Characters[*line].Advance * tracking * scale;
|
||||
line++;
|
||||
check_caret(caret, line-drawstart, cursor, scale, usecolor);
|
||||
} else if (isspace(*line)) {
|
||||
sdrawCharacter(font->Characters[*line], cursor, scale, usecolor);
|
||||
cursor.Y -= scale * font->linegap;
|
||||
cursor.X = pos.X;
|
||||
l++;
|
||||
check_caret(caret, l, cursor, scale, usecolor);
|
||||
line++;
|
||||
check_caret(caret, line-drawstart, cursor, scale, usecolor);
|
||||
} else {
|
||||
wordstart = &line[l];
|
||||
if (*line == '\e')
|
||||
line = esc_color(line, &usecolor, color);
|
||||
|
||||
wordstart = line;
|
||||
int wordWidth = 0;
|
||||
|
||||
while (!isspace(line[l]) && line[l] != '\0') {
|
||||
wordWidth += font->Characters[line[l]].Advance * tracking * scale;
|
||||
l++;
|
||||
while (!isspace(*line) && *line != '\0') {
|
||||
|
||||
wordWidth += font->Characters[*line].Advance * tracking * scale;
|
||||
line++;
|
||||
}
|
||||
|
||||
if (lw > 0 && (cursor.X + wordWidth - pos.X) >= lw) {
|
||||
|
@ -330,11 +369,14 @@ int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, f
|
|||
cursor.Y -= scale * font->linegap;
|
||||
}
|
||||
|
||||
while (wordstart < &line[l]) {
|
||||
while (wordstart < line) {
|
||||
if (*wordstart == '\e')
|
||||
wordstart = esc_color(wordstart, &usecolor, color);
|
||||
|
||||
sdrawCharacter(font->Characters[*wordstart], cursor, scale, usecolor);
|
||||
cursor.X += font->Characters[*wordstart].Advance * tracking * scale;
|
||||
wordstart++;
|
||||
check_caret(caret, wordstart-line, cursor, scale, usecolor);
|
||||
check_caret(caret, wordstart-drawstart, cursor, scale, usecolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ void font_init();
|
|||
struct sFont *MakeFont(const char *fontfile, int height);
|
||||
void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgba color);
|
||||
void text_settype(struct sFont *font);
|
||||
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);
|
||||
struct boundingbox text_bb(const unsigned char *text, float scale, float lw, float tracking);
|
||||
int renderText(const unsigned char *text, HMM_Vec2 pos, float scale, struct rgba color, float lw, int caret, float tracking);
|
||||
|
||||
// void text_frame();
|
||||
void text_flush(HMM_Mat4 *proj);
|
||||
|
|
|
@ -279,90 +279,52 @@ const char *keyname_extd(int key) {
|
|||
switch (key) {
|
||||
case SAPP_KEYCODE_ENTER:
|
||||
return "enter";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_ESCAPE:
|
||||
return "escape";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_DELETE:
|
||||
return "delete";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_INSERT:
|
||||
return "insert";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_TAB:
|
||||
return "tab";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_RIGHT:
|
||||
return "right";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_LEFT:
|
||||
return "left";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_UP:
|
||||
return "up";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_DOWN:
|
||||
return "down";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_LEFT_SHIFT:
|
||||
return "lshift";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_RIGHT_SHIFT:
|
||||
return "rshift";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_LEFT_CONTROL:
|
||||
return "lctrl";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_LEFT_ALT:
|
||||
return "lalt";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_RIGHT_CONTROL:
|
||||
return "rctrl";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_RIGHT_ALT:
|
||||
return "ralt";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_SPACE:
|
||||
return "space";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_KP_ADD:
|
||||
return "plus";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_KP_SUBTRACT:
|
||||
return "minus";
|
||||
break;
|
||||
case SAPP_KEYCODE_GRAVE_ACCENT:
|
||||
return "`";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_LEFT_BRACKET:
|
||||
return "lbracket";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_RIGHT_BRACKET:
|
||||
return "rbracket";
|
||||
break;
|
||||
|
||||
case SAPP_KEYCODE_BACKSPACE:
|
||||
return "backspace";
|
||||
break;
|
||||
case SAPP_KEYCODE_PAGE_UP:
|
||||
return "pgup";
|
||||
case SAPP_KEYCODE_PAGE_DOWN:
|
||||
return "pgdown";
|
||||
}
|
||||
|
||||
if (key >= 32 && key <=90) {
|
||||
|
@ -372,7 +334,6 @@ const char *keyname_extd(int key) {
|
|||
return keybuf;
|
||||
}
|
||||
|
||||
|
||||
return "NULL";
|
||||
}
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ struct wav *make_sound(const char *wav) {
|
|||
void *raw = slurp_file(wav, &rawlen);
|
||||
if (!raw) {
|
||||
YughError("Could not find file %s.", wav);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!strcmp(ext, "wav"))
|
||||
|
|
Loading…
Reference in a new issue