proper proto chaining in ur construction

This commit is contained in:
John Alanbrook 2023-10-05 18:33:43 +00:00
parent 8c69dfd71f
commit 03f209ddef
14 changed files with 163 additions and 102 deletions

View file

@ -19,7 +19,7 @@ URIError = {};
Object.mixin = function(target, source)
{
if (typeof source === 'undefined') return target;
if (typeof source !== 'object') return target;
Object.keys(source).forEach(function (k) {
if (Object.isAccessor(source,k))
@ -40,26 +40,19 @@ Object.deepfreeze = function(obj)
Object.freeze(obj);
}
/* Goes through each key and overwrites if it's present, adds if it is not */
/* Goes through each key and overwrites if it's present */
Object.dainty_assign = function(target, source)
{
for (var key in source) {
if (typeof source[key] === 'function') {
target[key] = source[key];
continue;
}
if (!Object.hasOwn(target, key)) continue;
if (!Object.getOwnPropertyDescriptor(target, key).writable) continue;
Object.keys(target).forEach(function(key) {
if (!(key in source)) return;
if (Array.isArray(target[key]))
target[key] = source[key];
else if (typeof target[key] === 'object')
Object.dainty_assign(target[key], source[key]);
else {
else
target[key] = source[key];
}
}
});
}
Object.isObject = function(o)

View file

@ -702,10 +702,14 @@ component.circle2d = Object.copy(collider2d, {
make(go) {
var circle = Object.create(this);
circle.gameobject = go;
Object.assign(circle, make_circle2d(go.body));
Object.mixin(circle,this.impl);
Object.hide(circle, 'gameobject', 'id', 'shape', 'scale');
for (var key in this.impl)
if (this[key]) circle[key] = this[key];
return circle;
},
});

View file

@ -90,6 +90,7 @@ function positive_diff(from, to)
function vdiff(from,to)
{
if (typeof from === 'function') return undefined;
if (typeof from === 'number') {
var a = Number.prec(from);
return a === to ? undefined : a;
@ -110,16 +111,12 @@ function gdiff(from, to) {
Object.entries(from).forEach(function([k,v]) {
if (typeof v === 'function') return;
if (!Object.isAccessor(from, k)) {
obj[k] = v;
return;
}
var diff = vdiff(v, to[k]);
if (diff) {
if (Array.isArray(v))
obj[k] = Object.values(diff);
else
else if (!diff.empty)
obj[k] = diff;
}
});

View file

@ -1278,6 +1278,7 @@ var inputpanel = {
},
open(steal) {
Log.warn(gameobject.angle);
this.on = true;
this.value = "";
if (steal) {
@ -1320,6 +1321,11 @@ var inputpanel = {
keycb() {},
caret: 0,
reset_value() {
this.value = "";
this.caret = 0;
},
input_backspace_pressrep() {
this.value = this.value.slice(0,-1);
@ -1340,8 +1346,12 @@ inputpanel.inputs['C-b'] = function() {
if (this.caret === 0) return;
this.caret--;
};
inputpanel.inputs['C-f'] = function() {
if (this.caret === this.value.length) return;
this.caret++;
};
inputpanel.inputs['C-a'] = function() { this.caret = 0; };
inputpanel.inputs['C-f'] = function() { this.caret = this.value.length; };
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);
@ -1351,6 +1361,10 @@ inputpanel.inputs.backspace = function() {
inputpanel.inputs.backspace.rep = true;
inputpanel.inputs.enter = function() { this.submit(); }
inputpanel.inputs['C-k'] = function() {
this.value = this.value.slice(0,this.caret);
};
function proto_count_lvls(name)
{
@ -1431,8 +1445,7 @@ var replpanel = Object.copy(inputpanel, {
this.value = "";
this.caret = 0;
var ret = function() {return eval(ecode);}.call(repl_obj);
if (ret)
Log.say(ret);
Log.say(ret);
},
});
@ -1442,7 +1455,7 @@ replpanel.inputs['C-p'] = function()
if (this.prevmark >= this.prevthis.length) return;
this.prevmark++;
this.value = this.prevthis[this.prevmark];
this.inputs['C-f'].call(this);
this.inputs['C-e'].call(this);
}
replpanel.inputs['C-n'] = function()
@ -1454,7 +1467,7 @@ replpanel.inputs['C-n'] = function()
} else
this.value = this.prevthis[this.prevmark];
this.inputs['C-f'].call(this);
this.inputs['C-e'].call(this);
}
var objectexplorer = Object.copy(inputpanel, {
@ -1462,6 +1475,7 @@ var objectexplorer = Object.copy(inputpanel, {
obj: undefined,
previous: [],
start() {
this.previous = [];
Input.setnuke();
},
@ -1632,14 +1646,21 @@ var openlevelpanel = Object.copy(inputpanel, {
this.value = this.assets[0];
return true;
},
start() {
this.allassets = prototypes.list.sort();
this.assets = this.allassets.slice();
var click_ur = function(btn) {
Log.warn(btn.str);
this.value = btn.str;
this.keycb();
this.submit();
};
click_ur = click_ur.bind(this);
this.mumlist = [];
this.assets.forEach(function(x) {
this.mumlist[x] = Mum.text({str:x});
this.mumlist[x] = Mum.text({str:x, action:click_ur,selectable: true, hovered:{color:Color.red}});
}, this);
},
@ -1653,9 +1674,9 @@ var openlevelpanel = Object.copy(inputpanel, {
},
guibody() {
var a = [Mum.text({str:this.value,color:Color.green})];
var a = [Mum.text({str:this.value,color:Color.green, caret:this.caret})];
var b = a.concat(Object.values(this.mumlist));
return Mum.column({items:b});
return Mum.column({items:b, offset:[0,-10]});
},
});
@ -1845,6 +1866,10 @@ Player.players[0].control(editor);
Register.gui.register(editor.ed_gui, editor);
Debug.register_call(editor.ed_debug, editor);
Register.update.register(gui_controls.update, gui_controls);
Player.players[0].control(gui_controls);
if (IO.exists("editor.config"))
load_configs("editor.config");
@ -1854,4 +1879,5 @@ editor.camera = Game.camera;
Game.stop();
Game.editor_mode(true);
load("editorconfig.js");

View file

@ -691,6 +691,9 @@ load("scripts/entity.js");
var preprimum = {};
preprimum.objects = {};
preprimum.worldpos = function() { return [0,0]; };
preprimum.pos = [0,0];
preprimum.angle = 0;
var World = gameobject.make(preprimum);
var Primum = World;
Primum.level = undefined;

View file

@ -47,9 +47,9 @@ var gameobject = {
},
set pos(x) {
this.set_worldpos(x); return;
this.set_worldpos(Vector.rotate(x,Math.deg2rad(this.level.angle)).add(this.level.worldpos()));
},
get pos() {
var offset = this.worldpos().sub(this.level.worldpos());
return Vector.rotate(offset, -Math.deg2rad(this.level.angle));
@ -84,14 +84,15 @@ var gameobject = {
get angle() { return Math.rad2deg(q_body(2,this.body))%360; },
set angle(x) {
var diff = x - this.angle;
var thatpos = this.pos;
this.objects.forEach(function(x) {
x.angle = x.angle + diff;
var pos = x.pos.sub(this.pos);
var pos = x.pos.sub(thatpos);
var r = Vector.length(pos);
var p = Math.rad2deg(Math.atan2(pos.y, pos.x));
p += diff;
p = Math.deg2rad(p);
x.pos = this.pos.add([r*Math.cos(p), r*Math.sin(p)]);
x.set_worldpos(thatpos.add([r*Math.cos(p), r*Math.sin(p)]));
}, this);
set_body(0,this.body, Math.deg2rad(x));
@ -298,11 +299,6 @@ var gameobject = {
delete d.angle;
delete d.velocity;
delete d.angularvelocity;
d.components = [];
this.components.forEach(function(x) {
var c = gdiff(x, x.__proto__);
if (c) d.components.push(c);
});
return d;
},
@ -313,7 +309,8 @@ var gameobject = {
},
level_obj() {
var json = this.json_obj();
var json = gdiff(this,this.__proto__);
var objects = {};
this.__proto__.objects ??= {};
if (!Object.keys(this.objects).equal(Object.keys(this.__proto__.objects))) {
@ -417,6 +414,7 @@ var gameobject = {
obj.components = {};
obj.objects = {};
Object.mixin(obj, gameobject.impl);
Object.hide(obj, 'components');
Object.hide(obj, 'objects');
obj._ed = {};
@ -433,36 +431,26 @@ var gameobject = {
for (var prop in this) {
var p = this[prop];
if (typeof p !== 'object') continue;
if ('ur' in p) {
obj[prop] = obj.spawn(prototypes.get_ur(p.ur));
obj.rename_obj(obj[prop].toString(), prop);
Object.hide(obj, prop);
} else if ('comp' in p) {
Log.warn(p);
obj[prop] = Object.assign(component[p.comp].make(obj), p);
if (typeof p.make === 'function') {
obj[prop] = p.make(obj);
obj.components[prop] = obj[prop];
Object.hide(obj,prop);
}
};
};
if (this.objects) {
for (var prop in this.objects) {
Log.warn(this.objects[prop]);
continue;
var o = this.objects[prop];
var newobj = obj.spawn(prototypes.get_ur(o.ur));
if (!newobj) continue;
obj.rename_obj(newobj.toString(), prop);
Object.assign(newobj,o);
}
}
for (var p in this.impl) {
if (Object.isAccessor(this.impl, p))
obj[p] = this[p];
}
Object.dainty_assign(obj, this);
obj.components.forEach(function(x) { if ('sync' in x) x.sync(); });
gameobject.check_registers(obj);
if (typeof obj.start === 'function') obj.start();
@ -576,9 +564,17 @@ prototypes.from_file = function(file)
json ??= {};
Object.merge(newur,json);
for (var p in newur)
if (Object.isObject(newur[p]) && Object.isObject(upperur[p]))
newur[p].__proto__ = upperur[p];
Object.entries(newur).forEach(function([k,v]) {
if (Object.isObject(v) && Object.isObject(upperur[k]))
v.__proto__ = upperur[k];
});
Object.values(newur).forEach(function(v) {
if (typeof v !== 'object') return;
if (!v.comp) return;
v.__proto__ = component[v.comp];
delete v.comp;
});
newur.__proto__ = upperur;
newur.instances = [];
@ -708,33 +704,32 @@ prototypes.from_obj("arena", {});
prototypes.resavi = function(ur, path)
{
if (!ur) return path;
if (path[0] === '/') return path;
if (!ur) return path;
if (path[0] === '/') return path;
var res = ur.replaceAll('.', '/');
var dir = path.dir();
if (res.startsWith(dir))
return path.base();
return path;
var res = ur.replaceAll('.', '/');
var dir = path.dir();
if (res.startsWith(dir))
return path.base();
return path;
}
prototypes.resani = function(ur, path)
{
if (!path) return "";
Log.warn(`Sanitizing ${path} from ${ur}`);
if (!ur) return path;
if (path[0] === '/') return path.slice(1);
if (!ur) return path;
if (path[0] === '/') return path.slice(1);
var res = ur.replaceAll('.', '/');
var restry = res + "/" + path;
while (!IO.exists(restry)) {
res = res.updir() + "/";
if (res === "/")
return path;
var res = ur.replaceAll('.', '/');
var restry = res + "/" + path;
while (!IO.exists(restry)) {
res = res.updir() + "/";
if (res === "/")
return path;
restry = res + path;
}
return restry;
restry = res + path;
}
return restry;
}

View file

@ -64,15 +64,50 @@ var GUI = {
}
};
var gui_controls = {};
gui_controls.update = function() { };
gui_controls.options = [];
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;
}
});
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);
this.selected.action(this.selected);
}
};
var Mum = {
padding:[0,0], /* Each element inset with this padding on all sides */
offset:[0,0],
font: "fonts/LessPerfectDOSVGA.ttf",
selectable: false,
selected: false,
font_size: 1,
text_align: "left",
scale: 1,
angle: 0,
anchor: [0,1],
hovered: {},
text_shadow: {
pos: [0,0],
color: Color.white,
@ -85,39 +120,48 @@ var Mum = {
image_repeat: false,
image_repeat_offset: [0,0],
debug: false, /* set to true to draw debug boxes */
make(def) {
var n = Object.create(this);
Object.assign(n, def);
return n;
},
prestart() {
this.hovered.__proto__ = this;
},
start() {},
extend(def) {
var n = Object.create(this);
Object.assign(n, def);
return function(def) { var p = n.make(def); p.start(); return p; };
return function(def) {
var p = n.make(def);
p.prestart();
p.start();
return p;
};
},
}
Mum.text = Mum.extend({
draw(cursor) {
if (this.hide) return;
if (this.selectable) gui_controls.options.push_unique(this);
this.caret ??= -1;
/* if (!this.bb)
this.calc_bb(cursor);
else
this.update_bb(cursor);
*/
if (this.selected) {
Object.assign(this,this.hovered);
this.calc_bb(cursor);
}
*/
var params = this.selected ? this.hovered : this;
this.calc_bb(cursor);
var aa = [0,1].sub(this.anchor);
var pos = cursor.add(this.wh.scale(aa)).add(this.offset);
ui_text(this.str, pos, this.font_size, this.color, this.width, this.caret);
var aa = [0,1].sub(params.anchor);
var pos = cursor.add(params.wh.scale(aa)).add(params.offset);
ui_text(params.str, pos, params.font_size, params.color, params.width, params.caret);
},
update_bb(cursor) {
@ -127,8 +171,8 @@ Mum.text = Mum.extend({
calc_bb(cursor) {
var bb = cmd(118,this.str, this.font_size, this.width);
this.wh = bb2wh(bb);
var pos = cursor.sub(this.wh.scale(this.anchor));
this.bb = movebb(bb,pos);
var pos = cursor.add(this.wh.scale([0,1].sub(this.anchor))).add(this.offset);
this.bb = movebb(bb,pos.add([this.wh.x/2,0]));
},
start() {
this.calc_bb([0,0]);
@ -187,6 +231,7 @@ Mum.image = Mum.extend({
Mum.column = Mum.extend({
draw(cursor) {
if (this.hide) return;
cursor = cursor.add(this.offset);
this.items.forEach(function(item) {
if (item.hide) return;

View file

@ -8,12 +8,6 @@ var Mouse = {
return cmd(45);
},
get screenpos() {
var p = this.pos;
p.y = Window.dimensions.y - p.y;
return p;
},
get worldpos() {
return screen2world(cmd(45));
},
@ -114,7 +108,8 @@ var Player = {
if (typeof pawn.inputs?.mouse?.[type] === 'function') {
pawn.inputs.mouse[type].call(pawn,...args);
pawn.inputs.post?.call(pawn);
return;
if (!pawn.inputs.fallthru)
return;
}
}
},
@ -124,7 +119,8 @@ var Player = {
if (typeof pawn.inputs?.char === 'function') {
pawn.inputs.char.call(pawn, c);
pawn.inputs.post?.call(pawn);
return;
if (!pawn.inputs.fallthru)
return;
}
};
},
@ -133,7 +129,8 @@ var Player = {
for (var pawn of this.pawns.reversed()) {
if (typeof pawn.inputs?.any === 'function') {
pawn.inputs.any(cmd);
return;
if (!pawn.inputs.fallthru)
return;
}
if (!pawn.inputs?.[cmd]) continue;
@ -156,7 +153,8 @@ var Player = {
if (typeof fn === 'function') {
fn.call(pawn, ... args);
pawn.inputs.post?.call(pawn);
return;
if (!pawn.inputs.fallthru)
return;
}
}
},

View file

@ -68,9 +68,10 @@ var texteditor = Object.copy(inputpanel, {
return this.startbuffer !== this.value;
},
gui() {
GUI.text_cursor(this.value, [100,700],1,this.cursor+1);
GUI.text("C" + this.cursor + ":::L" + this.line + ":::" + (this.dirty ? "DIRTY" : "CLEAN"), [100,100], 1);
guibody() {
return [
Mum.text({str:this.value, caret:this.cursor, offset:[0,-16]}),
];
},
insert_char(char) {

View file

@ -119,7 +119,7 @@ void input_mouse(int btn, int state, uint32_t mod)
void input_mouse_move(float x, float y, float dx, float dy, uint32_t mod)
{
mouse_pos.x = x;
mouse_pos.y = y;
mouse_pos.y = mainwin.height - y;
mouse_delta.x = dx;
mouse_delta.y = -dy;

View file

@ -475,9 +475,8 @@ HMM_Vec2 world2screen(HMM_Vec2 pos)
HMM_Vec2 screen2world(HMM_Vec2 pos)
{
pos.Y *= -1;
pos = HMM_ScaleV2(pos, 1/mainwin.dpi);
pos = HMM_AddV2(pos, HMM_V2(-mainwin.rwidth/2.0, mainwin.rheight/2.0));
pos = HMM_SubV2(pos, HMM_V2(mainwin.rwidth/2.0, mainwin.rheight/2.0));
pos = HMM_ScaleV2(pos, zoom);
pos = HMM_AddV2(pos, HMM_V2(cam_pos().x, cam_pos().y));
return pos;