From 272719736ce4596ae306492c4cba2221ce9f9d75 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Thu, 5 Oct 2023 22:30:17 +0000 Subject: [PATCH] easier saving --- scripts/base.js | 5 ++- scripts/components.js | 82 ++++++++++++++++++++++++------------- scripts/debug.js | 2 +- scripts/diff.js | 85 ++++++++++++++++----------------------- scripts/editor.js | 9 ++--- scripts/engine.js | 1 + scripts/entity.js | 85 +++++++++++---------------------------- source/engine/2dphysics.c | 9 ++++- source/engine/ffi.c | 1 + 9 files changed, 129 insertions(+), 150 deletions(-) diff --git a/scripts/base.js b/scripts/base.js index 0c92fd5..88202c4 100644 --- a/scripts/base.js +++ b/scripts/base.js @@ -45,9 +45,10 @@ Object.dainty_assign = function(target, source) { Object.keys(target).forEach(function(key) { if (!(key in source)) return; + if (typeof target[key] === 'function') return; if (Array.isArray(target[key])) - target[key] = source[key]; + target[key] = deep_copy(source[key]); else if (typeof target[key] === 'object') Object.dainty_assign(target[key], source[key]); else @@ -736,7 +737,7 @@ Math.angledist = function (a1, a2) { return wrap; }; Math.angledist.doc = "Find the shortest angle between two angles."; - +Math.patan2 = function(p) { return Math.atan2(p.y,p.x); }; Math.deg2rad = function(deg) { return deg * 0.0174533; }; Math.rad2deg = function(rad) { return rad / 0.0174533; }; Math.randomint = function(max) { return Math.clamp(Math.floor(Math.random() * max), 0, max-1); }; diff --git a/scripts/components.js b/scripts/components.js index 7f6d89d..70bc30d 100644 --- a/scripts/components.js +++ b/scripts/components.js @@ -24,6 +24,13 @@ var component = { }, }; +component.assign_impl = function(o) +{ + for (var key in o.impl) + if (typeof o[key] !== 'undefined' && typeof o[key] !== 'function') + o[key] = o.impl[key]; +} + component.sprite = Object.copy(component, { pos:[0,0], color:[1,1,1], @@ -37,20 +44,23 @@ component.sprite = Object.copy(component, { nsprite.gameobject = go; Object.assign(nsprite, make_sprite(go.body)); Object.mixin(nsprite, component.sprite.impl); + nsprite.kill = component.sprite.impl.kill; + Object.hide(nsprite, 'gameobject', 'id'); for (var p in component.sprite.impl) - if (typeof this[p] !== 'undefined') + if (typeof this[p] !== 'undefined' && typeof this[p] !== 'function') nsprite[p] = this[p]; + return nsprite; }, }); component.sprite.impl = { set path(x) { - cmd(12,this.id,prototypes.resani(this.gameobject.ur, x),this.rect); + cmd(12,this.id,prototypes.resani(this.gameobject.__proto__.toString(), x),this.rect); }, get path() { - return prototypes.resavi(this.gameobject.ur, cmd(116,this.id)); + return prototypes.resavi(this.gameobject.__proto__.toString(), cmd(116,this.id)); }, hide() { this.enabled = false; }, show() { this.enabled = true; }, @@ -324,9 +334,7 @@ collider2d.inputs['M-t'] = function() { this.enabled = !this.enabled; } collider2d.inputs['M-t'].doc = "Toggle if this collider is enabled."; component.polygon2d = Object.copy(collider2d, { - sync() { - cmd_poly2d(0, this.id, this.spoints); - }, + toString() { return "poly2d"; }, boundingbox() { return points2bb(this.spoints); @@ -339,9 +347,13 @@ component.polygon2d = Object.copy(collider2d, { poly.flipx = false; poly.flipy = false; Object.assign(poly, make_poly2d(go.body, poly.points)); + Object.mixin(poly, poly.impl); + Object.hide(poly, 'id', 'shape', 'gameobject', 'flipx', 'flipy'); return poly; }, + points:[], + /* EDITOR */ get spoints() { var spoints = this.points.slice(); @@ -361,7 +373,6 @@ component.polygon2d = Object.copy(collider2d, { spoints.push(newpoint); }); } - return spoints; }, @@ -376,6 +387,9 @@ component.polygon2d = Object.copy(collider2d, { }, pick(pos) { + if (!Object.hasOwn(this,'points')) + this.points = deep_copy(this.__proto__.points); + var p = Gizmos.pick_gameobject_points(pos, this.gameobject, this.points); if (p) { return { @@ -390,11 +404,16 @@ component.polygon2d = Object.copy(collider2d, { return undefined; }, - +}); + +component.polygon2d.impl = { + sync() { + cmd_poly2d(0, this.id, this.spoints); + }, query() { return cmd(80, this.shape); }, -}); +}; var polygon2d = component.polygon2d; @@ -424,11 +443,13 @@ polygon2d.inputs['C-b'] = function() { }; polygon2d.inputs['C-b'].doc = "Freeze mirroring in place."; -Object.freeze(polygon2d); +//Object.freeze(polygon2d); component.edge2d = Object.copy(collider2d, { degrees:2, dimensions:2, + thickness:0, + points: [], /* open: 0 clamped: 1 beziers: 2 @@ -444,6 +465,7 @@ component.edge2d = Object.copy(collider2d, { flipx: false, flipy: false, + toString() { return "edge2d"; }, hollow: false, hollowt: 0, @@ -508,11 +530,6 @@ component.edge2d = Object.copy(collider2d, { return spline_cmd(0, this.degrees, this.dimensions, this.type, spoints, n); }, - set thickness(x) { - cmd_edge2d(1,this.id,x); - }, - - get thickness() { return cmd(112,this.id); }, samples: 10, @@ -523,20 +540,14 @@ component.edge2d = Object.copy(collider2d, { make(go) { var edge = Object.create(this); edge.gameobject = go; - edge.cpoints = []; - edge.points = []; - Object.assign(edge, make_edge2d(go.body, edge.points, 0)); - edge.thickness = 0; +// edge.cpoints = []; +// edge.points = []; + Object.assign(edge, make_edge2d(go.body, edge.points, 0)); + Object.mixin(edge,edge.impl); + Object.hide(edge, 'gameobject', 'id', 'shape'); return edge; }, - sync() { - var sensor = this.sensor; - this.points = this.sample(this.samples); - cmd_edge2d(0,this.id,this.points); - this.sensor = sensor; - }, - /* EDITOR */ gizmo() { this.spoints.forEach(function(x) { @@ -565,6 +576,19 @@ component.edge2d = Object.copy(collider2d, { }, }); +component.edge2d.impl = { + set thickness(x) { + cmd_edge2d(1,this.id,x); + }, + get thickness() { return cmd(112,this.id); }, + sync() { + var sensor = this.sensor; + this.points = this.sample(this.samples); + cmd_edge2d(0,this.id,this.points); + this.sensor = sensor; + }, +}; + var bucket = component.edge2d; bucket.inputs = {}; bucket.inputs.h = function() { this.hollow = !this.hollow; }; @@ -684,7 +708,7 @@ component.circle2d = Object.copy(collider2d, { set radius(x) { cmd_circle2d(0,this.id,x); }, get radius() { return cmd_circle2d(2,this.id); }, - set scale(x) { Log.warn(x);this.radius = x; }, + set scale(x) { this.radius = x; }, get scale() { return this.radius; }, set offset(x) { cmd_circle2d(1,this.id,x); }, @@ -707,8 +731,10 @@ component.circle2d = Object.copy(collider2d, { Object.assign(circle, make_circle2d(go.body)); Object.mixin(circle,this.impl); Object.hide(circle, 'gameobject', 'id', 'shape', 'scale'); + component.assign_impl(circle); for (var key in this.impl) - if (this[key]) circle[key] = this[key]; + if (typeof this[key] !== 'undefined' && typeof this[key] !== 'function') + if (this[key]) circle[key] = this[key]; return circle; }, diff --git a/scripts/debug.js b/scripts/debug.js index 31c9711..cf12e67 100644 --- a/scripts/debug.js +++ b/scripts/debug.js @@ -47,7 +47,7 @@ var Debug = { numbered_point(pos, n) { Debug.point(world2screen(pos), 3); - gui_text(n, world2screen(pos).add([0,4]), 1); + GUI.text(n, world2screen(pos).add([0,4]), 1); }, phys_drawing: false, diff --git a/scripts/diff.js b/scripts/diff.js index 437fd62..fffb3aa 100644 --- a/scripts/diff.js +++ b/scripts/diff.js @@ -83,60 +83,43 @@ function diffassign(target, from) { } }; -function positive_diff(from, to) +function ediff(from,to) { - var diff = {}; -} + var ret = {}; + + Object.entries(from).forEach(function([key,v]) { + if (typeof v === 'function') return; + if (typeof v === 'undefined') return; -function vdiff(from,to) -{ - if (typeof from === 'function') return undefined; - if (typeof from === 'number') { - var a = Number.prec(from); - return a === to ? undefined : a; - } + if (Array.isArray(v)) { + if (!Array.isArray(to[key]) || v.length !== to[key].length) + ret[key] = Object.values(ediff(v, [])); - if (typeof from === 'object') { - var ret = {}; - Object.keys(from).forEach(function(k) { - var diff = vdiff(from[k], to[k]); - if (diff) ret[k] = diff; - }); - return ret.empty ? undefined : ret; - } -} + var diff = ediff(from[key], to[key]); + if (diff && !diff.empty) + ret[key] = Object.values(ediff(v,[])); -function gdiff(from, to) { - var obj = {}; - - Object.entries(from).forEach(function([k,v]) { - if (typeof v === 'function') return; - - var diff = vdiff(v, to[k]); - if (diff) { - if (Array.isArray(v)) - obj[k] = Object.values(diff); - else if (!diff.empty) - obj[k] = diff; + return; } + + if (typeof v === 'object') { + var diff = ediff(v, to[key]); + if (diff && !diff.empty) + ret[key] = diff; + return; + } + + if (typeof v === 'number') { + var a = Number.prec(v); + if (!to || a !== to[key]) + ret[key] = a; + return; + } + + if (!to || v !== to[key]) + ret[key] = v; }); - - return obj; -}; - -function diff(from, to) { - var obj = {}; - - for (var e in to) { - if (typeof to[e] === 'object' && from.hasOwnProperty(e)) { - obj[e] = diff(from[e], to[e]); - if (obj[e].empty) - delete obj[e]; - } else { - if (from[e] !== to[e]) - obj[e] = to[e]; - } - } - - return obj; -}; + + if (ret.empty) return undefined; + return ret; +} diff --git a/scripts/editor.js b/scripts/editor.js index a236cb9..8360de6 100644 --- a/scripts/editor.js +++ b/scripts/editor.js @@ -421,7 +421,7 @@ var editor = { this.selectlist.forEach(function(x) { var sname = x.__proto__.toString(); - if (!x.json_obj().empty) + if (!x.level_obj().empty) x._ed.dirty = true; else x._ed.dirty = false; @@ -789,12 +789,12 @@ editor.inputs['C-s'] = function() { }; if (editor.selectlist.length !== 1 || !editor.selectlist[0]._ed.dirty) return; - Object.merge(editor.selectlist[0].ur, editor.selectlist[0].level_obj()); + Object.merge(editor.selectlist[0].__proto__, editor.selectlist[0].level_obj()); var path = editor.selectlist[0].ur.toString(); path = path.replaceAll('.','/'); path = path + "/" + path.name() + ".json"; - IO.slurpwrite(JSON.stringify(editor.selectlist[0].ur,null,1), path); + IO.slurpwrite(JSON.stringify(editor.selectlist[0].__proto__,null,1), path); }; editor.inputs['C-s'].doc = "Save selected."; @@ -1273,12 +1273,11 @@ var inputpanel = { guibody() { return [ Mum.text({str:this.value, color:Color.green}), - Mum.button({str:"Submit", action:this.submit}) +// Mum.button({str:"Submit", action:this.submit}) ]; }, open(steal) { - Log.warn(gameobject.angle); this.on = true; this.value = ""; if (steal) { diff --git a/scripts/engine.js b/scripts/engine.js index 22a411f..7bd5a2e 100644 --- a/scripts/engine.js +++ b/scripts/engine.js @@ -692,6 +692,7 @@ load("scripts/entity.js"); var preprimum = {}; preprimum.objects = {}; preprimum.worldpos = function() { return [0,0]; }; +preprimum.worldangle = function() { return 0; }; preprimum.pos = [0,0]; preprimum.angle = 0; var World = gameobject.make(preprimum); diff --git a/scripts/entity.js b/scripts/entity.js index c7cebd8..889b149 100644 --- a/scripts/entity.js +++ b/scripts/entity.js @@ -81,21 +81,30 @@ var gameobject = { set_body(2,this.body,x); }, - get angle() { return Math.rad2deg(q_body(2,this.body))%360; }, + worldangle() { return Math.rad2deg(q_body(2,this.body))%360; }, + get angle() { + if (!this.level) return this.worldangle(); + return this.worldangle() - this.level.worldangle(); + }, 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(thatpos); - var r = Vector.length(pos); - var p = Math.rad2deg(Math.atan2(pos.y, pos.x)); + x.rotate(diff); +// x.angle = x.angle + diff; + var opos = x.pos; + var r = Vector.length(opos); + var p = Math.rad2deg(Math.atan2(opos.y, opos.x)); p += diff; p = Math.deg2rad(p); - x.set_worldpos(thatpos.add([r*Math.cos(p), r*Math.sin(p)])); + x.pos = [r*Math.cos(p), r*Math.sin(p)]; }, this); - set_body(0,this.body, Math.deg2rad(x)); + set_body(0,this.body, Math.deg2rad(x - this.level.worldangle())); + }, + + rotate(x) { + this.angle = this.angle + x; }, @@ -164,7 +173,7 @@ var gameobject = { /* Make a unique object the same as its prototype */ revert() { - Object.totalmerge(this,this.__proto__); + Object.merge(this,this.__proto__); }, check_registers(obj) { @@ -249,52 +258,8 @@ var gameobject = { return bb ? bb : cwh2bb([0,0], [0,0]); }, - diff(from, to) { - var ret = {}; - - for (var key in from) { - if (!Object.hasOwn(from, key) && !Object.isAccessor(from,key)) continue; - if (typeof from[key] === 'undefined' || typeof to[key] === 'undefined') continue; - if (typeof from[key] === 'function') continue; -// if (typeof to === 'object' && !(key in to)) continue; - - if (Array.isArray(from[key])) { - if (!Array.isArray(to[key])) - ret[key] = Object.values(gameobject.diff(from[key], [])); - - if (from[key].length !== to[key].length) - ret[key] = Object.values(gameobject.diff(from[key], [])); - - var diff = gameobject.diff(from[key], to[key]); - if (diff && !diff.empty) - ret[key] = Object.values(diff); - - continue; - } - - if (typeof from[key] === 'object') { - var diff = gameobject.diff(from[key], to[key]); - if (diff && !diff.empty) - ret[key] = diff; - continue; - } - - if (typeof from[key] === 'number') { - var a = Number.prec(from[key]); - if (a !== to[key]) - ret[key] = a; - continue; - } - - if (from[key] !== to[key]) - ret[key] = from[key]; - } - if (ret.empty) return undefined; - return ret; - }, - json_obj() { - var d = gdiff(this,this.__proto__); + var d = ediff(this,this.__proto__); delete d.pos; delete d.angle; delete d.velocity; @@ -309,7 +274,7 @@ var gameobject = { }, level_obj() { - var json = gdiff(this,this.__proto__); + var json = this.json_obj(); var objects = {}; this.__proto__.objects ??= {}; @@ -321,7 +286,7 @@ var gameobject = { } else { for (var o in this.objects) { var obj = this.objects[o].json_obj(); - Object.assign(obj, gameobject.diff(this.objects[o].transform(), this.__proto__.objects[o])); + Object.assign(obj, ediff(this.objects[o].transform(), this.__proto__.objects[o])); if (!obj.empty) objects[o] = obj; } @@ -414,11 +379,12 @@ var gameobject = { obj.components = {}; obj.objects = {}; Object.mixin(obj, gameobject.impl); - Object.hide(obj, 'components'); Object.hide(obj, 'objects'); obj._ed = {}; Object.hide(obj, '_ed'); + obj.ur = this.toString(); + Object.hide(obj,'ur'); Game.register_obj(obj); @@ -440,13 +406,12 @@ var gameobject = { if (this.objects) { for (var prop in this.objects) { var o = this.objects[prop]; - var newobj = obj.spawn(prototypes.get_ur(o.ur)); + var newobj = obj.spawn(o.ur); if (!newobj) continue; obj.rename_obj(newobj.toString(), prop); Object.assign(newobj,o); } } - Object.dainty_assign(obj, this); obj.components.forEach(function(x) { if ('sync' in x) x.sync(); }); @@ -467,7 +432,6 @@ var gameobject = { Log.warn(`Already an object with name ${newname}.`); return; } - Log.warn(`Renaming from ${name} to ${newname}.`); this.objects[newname] = this.objects[name]; delete this.objects[name]; @@ -573,15 +537,14 @@ prototypes.from_file = function(file) if (typeof v !== 'object') return; if (!v.comp) return; v.__proto__ = component[v.comp]; - delete v.comp; }); newur.__proto__ = upperur; newur.instances = []; + Object.hide(newur, 'instances'); prototypes.list.push(urpath); newur.toString = function() { return urpath; }; - newur.ur = urpath; ur[urpath] = newur; return ur[urpath]; diff --git a/source/engine/2dphysics.c b/source/engine/2dphysics.c index 6516205..365b0fa 100644 --- a/source/engine/2dphysics.c +++ b/source/engine/2dphysics.c @@ -390,8 +390,13 @@ void phys2d_polyaddvert(struct phys2d_poly *poly) { void phys2d_poly_setverts(struct phys2d_poly *poly, cpVect *verts) { if (!verts) return; - arrfree(poly->points); - poly->points = verts; + if (poly->points) + arrfree(poly->points); + + arrsetlen(poly->points, arrlen(verts)); + for (int i = 0; i < arrlen(verts); i++) + poly->points[i] = verts[i]; + phys2d_applypoly(poly); } diff --git a/source/engine/ffi.c b/source/engine/ffi.c index 02d6611..7fb4d6e 100644 --- a/source/engine/ffi.c +++ b/source/engine/ffi.c @@ -229,6 +229,7 @@ cpBitmask js2bitmask(JSValue v) { cpVect *cpvecarr = NULL; +/* Must be freed */ cpVect *js2cpvec2arr(JSValue v) { if (cpvecarr) arrfree(cpvecarr);