proper saving

This commit is contained in:
John Alanbrook 2023-10-10 22:37:58 +00:00
parent 661d29a01c
commit cff5483325
11 changed files with 171 additions and 144 deletions

View file

@ -67,21 +67,33 @@ Object.deepfreeze = function(obj)
}
/* Goes through each key and overwrites if it's present */
/*
Object.dainty_assign = function(target, source)
{
Object.keys(source).forEach(function(key) {
if (!(key in target)) return;
if (typeof source[key] === 'function') return;
Object.keys(target).forEach(function(key) {
if (!(key in source)) return;
if (typeof target[key] === 'function') return;
if (Array.isArray(source[key]))
if (Array.isArray(target[key]))
target[key] = deep_copy(source[key]);
else if (typeof source[key] === 'object')
else if (typeof target[key] === 'object')
Object.dainty_assign(target[key], source[key]);
else {
Log.warn(`set key ${key}`);
else
target[key] = source[key];
}
});
}
*/
Object.dainty_assign = function(target, source)
{
Object.keys(source).forEach(function(k) {
if (!(k in target)) return;
if (Array.isArray(source[k]))
target[k] = deep_copy(source[k]);
else if (Object.isObject(source[k]))
Object.dainty_assign(target[k], source[k]);
else
target[k] = source[k];
});
}
@ -421,7 +433,11 @@ Object.defineProperty(String.prototype, 'tofirst', {
});
Object.defineProperty(String.prototype, 'name', {
value: function() { return this.fromlast('/').tolast('.'); }
value: function() {
var idx = this.indexOf('/');
if (idx === -1)
return this.tolast('.');
return this.fromlast('/').tolast('.'); }
});
Object.defineProperty(String.prototype, 'base', {

View file

@ -1,3 +1,16 @@
function assign_impl(obj, impl)
{
var tmp = {};
for (var key in impl)
if (typeof obj[key] !== 'undefined' && typeof obj[key] !== 'function')
tmp[key] = obj[key];
Object.mixin(obj, impl);
for (var key in tmp)
obj[key] = tmp[key];
}
var component = {
components: [],
toString() {
@ -11,9 +24,20 @@ var component = {
enabled: true,
enable() { this.enabled = true; },
disable() { this.enabled = false; },
hides: ['gameobject', 'id'],
make(go) {
var nc = Object.create(this);
nc.gameobject = go;
Object.assign(nc, this._enghook(go.body));
assign_impl(nc,this.impl);
Object.hide(nc, ...this.hides);
return nc;
},
make(go) { },
kill() { Log.info("Kill not created for this component yet"); },
sync() {},
gui() { },
gizmo() { },
@ -24,13 +48,6 @@ 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],
@ -39,30 +56,17 @@ component.sprite = Object.copy(component, {
path: "",
rect: {s0:0, s1: 1, t0: 0, t1: 1},
toString() { return "sprite"; },
make(go) {
var nsprite = Object.create(this);
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' && typeof this[p] !== 'function')
nsprite[p] = this[p];
return nsprite;
},
_enghook: make_sprite,
});
component.sprite.impl = {
set path(x) {
Log.warn(x);
cmd(12,this.id,prototypes.resani(this.gameobject.__proto__.toString(), x),this.rect);
},
get path() {
return prototypes.resavi(this.gameobject.__proto__.toString(), cmd(116,this.id));
},
toString() { return "sprite"; },
hide() { this.enabled = false; },
show() { this.enabled = true; },
asset(str) { this.path = str; },
@ -336,23 +340,15 @@ collider2d.inputs['M-t'].doc = "Toggle if this collider is enabled.";
component.polygon2d = Object.copy(collider2d, {
toString() { return "poly2d"; },
flipx: false,
flipy: false,
boundingbox() {
return points2bb(this.spoints);
},
make(go) {
var poly = Object.create(this);
poly.gameobject = go;
poly.points = [];
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;
},
hides: ['id', 'shape', 'gameobject'],
_enghook: make_poly2d,
points:[],
/* EDITOR */
@ -726,21 +722,9 @@ component.circle2d = Object.copy(collider2d, {
var diameter = this.radius*2*this.gameobject.scale;
return cwh2bb(this.offset.scale(this.gameobject.scale), [this.radius,this.radius]);
},
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');
component.assign_impl(circle);
for (var key in this.impl)
if (typeof this[key] !== 'undefined' && typeof this[key] !== 'function')
if (this[key]) circle[key] = this[key];
return circle;
},
hides: ['gameobject', 'id', 'shape', 'scale'],
_enghook: make_circle2d,
});
/* ASSETS */

View file

@ -122,6 +122,7 @@ function ediff(from,to)
if (!to || v !== to[key])
ret[key] = v;
});
if (ret.empty) return undefined;
return ret;
}

View file

@ -197,7 +197,7 @@ var editor = {
stash: undefined,
start_play_ed() {
this.stash = this.edit_level.level_obj();
this.stash = this.edit_level.json_obj();
this.edit_level.kill();
// load_configs("game.config");
Game.play();
@ -444,7 +444,7 @@ var editor = {
this.selectlist.forEach(function(x) {
var sname = x.__proto__.toString();
if (!x.level_obj().empty)
if (!x.json_obj().empty)
x._ed.dirty = true;
else
x._ed.dirty = false;
@ -480,7 +480,7 @@ var editor = {
var i = 1;
for (var key in this.selectlist[0].components) {
var selected = this.sel_comp === this.selectlist[0].components[key];
var str = (selected ? ">" : " ") + key + " [" + this.selectlist[0].components[key].name + "]";
var str = (selected ? ">" : " ") + key + " [" + this.selectlist[0].components[key].toString() + "]";
GUI.text(str, world2screen(this.selectlist[0].worldpos()).add([0,-16*(i++)]));
}
@ -610,7 +610,7 @@ var editor = {
this.openpanel(gen_notify("Entity already exists with that name. Delete first."));
} else {
var path = sub.replaceAll('.', '/') + ".json";
var saveobj = obj.level_obj();
var saveobj = obj.json_obj();
IO.slurpwrite(JSON.stringify(saveobj,null,1), path);
@ -822,12 +822,15 @@ editor.inputs['C-s'] = function() {
};
if (editor.selectlist.length !== 1 || !editor.selectlist[0]._ed.dirty) return;
Object.merge(editor.selectlist[0].__proto__, editor.selectlist[0].level_obj());
var saveobj = editor.selectlist[0].json_obj();
Object.merge(editor.selectlist[0].__proto__, saveobj);
editor.selectlist[0].__proto__.objects = saveobj.objects;
var path = editor.selectlist[0].ur.toString();
path = path.replaceAll('.','/');
path = path + "/" + path.name() + ".json";
IO.slurpwrite(JSON.stringify(editor.selectlist[0].__proto__,null,1), path);
Log.warn(`Wrote to file ${path}`);
};
editor.inputs['C-s'].doc = "Save selected.";

View file

@ -716,6 +716,7 @@ preprimum.scale = 1;
preprimum.gscale = function() { return 1; };
preprimum.pos = [0,0];
preprimum.angle = 0;
preprimum.remove_obj = function() {};
var World = preprimum.make(preprimum);
var Primum = World;
Primum.level = undefined;

View file

@ -130,7 +130,11 @@ var gameobject = {
alive() { return this.body >= 0; },
in_air() { return q_body(7, this.body);},
on_ground() { return !this.in_air(); },
spawn(ur) {
spawn_from_instance(inst) {
var ur = prototypes.get_ur(inst.ur);
},
spawn(ur, data) {
if (typeof ur === 'string')
ur = prototypes.get_ur(ur);
if (!ur) {
@ -138,31 +142,47 @@ var gameobject = {
return undefined;
}
var go = ur.make(this);
var go = ur.make(this, data);
return go;
},
/* Reparent 'this' to be 'parent's child */
reparent(parent) {
if (this.level === parent)
this.level.remove_obj(this);
var name = parent.objects.push(this);
this.toString = function() { return name; };
return;
this.level?.remove_obj(this);
if (this.level)
this.level.objects.remove(this);
this.level = parent;
function unique_name(list, obj) {
var str = obj.toString().replaceAll('.', '_');
var n = 1;
var t = str;
while (Object.hasOwn(list, t)) {
t = str + n;
n++;
}
return t;
};
var name = unique_name(parent.objects, this.ur);
parent.objects[name] = this;
this.toString = function() { return name; };
},
remove_obj(obj) {
delete this[obj.toString()];
this.objects.remove(obj);
if (this[obj.toString()] === this.objects[obj.toString()])
delete this[obj.toString()];
delete this.objects[obj.toString()];
},
},
draw_layer: 1,
components: [],
objects: [],
components: {},
objects: {},
level: undefined,
hide() { this.components.forEach(function(x) { x.hide(); }); this.objects.forEach(function(x) { x.hide(); }); },
@ -194,6 +214,7 @@ var gameobject = {
/* Make a unique object the same as its prototype */
revert() {
Object.merge(this,this.__proto__);
this.sync();
},
check_registers(obj) {
@ -243,7 +264,10 @@ var gameobject = {
disable() { this.components.forEach(function(x) { x.disable(); });},
enable() { this.components.forEach(function(x) { x.enable(); });},
sync() { },
sync() {
this.components.forEach(function(x) { x.sync(); });
this.objects.forEach(function(x) { x.sync(); });
},
/* Bounding box of the object in world dimensions */
@ -285,20 +309,13 @@ var gameobject = {
var objects = {};
this.__proto__.objects ??= {};
if (!Object.keys(this.objects).equal(Object.keys(this.__proto__.objects))) {
for (var o in this.objects) {
objects[o] = this.objects[o].transform_obj();
objects[o].ur = this.objects[o].ur.toString();
}
} else {
for (var o in this.objects) {
var obj = ediff(this.objects[o].transform_obj(),
this.__proto__.objects[o]);
if (obj) objects[o] = obj;
}
}
if (!objects.empty)
d.objects = objects;
var curobjs = {};
for (var o in this.objects)
curobjs[o] = this.objects[o].instance_obj();
var odiff = ediff(curobjs, this.__proto__.objects);
if (odiff)
d.objects = curobjs;
delete d.pos;
delete d.angle;
@ -307,16 +324,18 @@ var gameobject = {
return d;
},
instance_obj() {
var t = this.transform_obj();
t.ur = this.ur;
return t;
},
transform_obj() {
var t = this.json_obj();
Object.assign(t, this.transform());
return t;
},
level_obj() {
return this.json_obj();
},
ur_obj() {
var ur = this.json_obj();
for (var k in ur)
@ -389,32 +408,29 @@ var gameobject = {
left() { return [-1,0].rotate(Math.deg2rad(this.angle));},
instances: [],
make(level) {
make(level, data) {
level ??= Primum;
var obj = Object.create(this);
obj.level = level;
this.instances.push(obj);
obj.body = make_gameobject();
Object.hide(obj, 'body');
obj.components = {};
obj.objects = {};
Object.mixin(obj, gameobject.impl);
Object.hide(obj, 'components');
Object.hide(obj, 'objects');
assign_impl(obj, gameobject.impl);
obj._ed = {
selectable: true,
dirty: false,
};
Object.hide(obj, '_ed');
obj.ur = this.toString();
Object.hide(obj,'ur');
Game.register_obj(obj);
cmd(113, obj.body, obj); // set the internal obj reference to this obj
obj.level = undefined;
obj.reparent(level);
Object.hide(obj, 'level')
Object.hide(obj, 'ur','body', 'components', 'objects', '_ed', 'level');
for (var prop in this) {
var p = this[prop];
@ -423,20 +439,19 @@ var gameobject = {
obj[prop] = p.make(obj);
obj.components[prop] = obj[prop];
}
};
};
if (this.objects) {
for (var prop in this.objects) {
var o = this.objects[prop];
var newobj = obj.spawn(o.ur);
var newobj = obj.spawn(o.ur, o);
if (!newobj) continue;
obj.rename_obj(newobj.toString(), prop);
}
}
Object.dainty_assign(obj, this);
obj.components.forEach(function(x) { if ('sync' in x) x.sync(); });
obj.sync();
gameobject.check_registers(obj);
@ -448,10 +463,11 @@ var gameobject = {
make_objs(objs) {
for (var prop in objs) {
var o = objs[prop];
var newobj = this.spawn(o.ur);
var newobj = this.spawn(o.ur, o);
if (!newobj) continue;
this.rename_obj(newobj.toString(), prop);
Object.assign(newobj,o);
Log.warn(`setting object ${prop} to ${JSON.stringify(o)}`);
// Object.assign(newobj,o);
}
},
@ -488,29 +504,6 @@ gameobject.impl.spawn.doc = `Spawn an entity of type 'ur' on this entity. Return
/* Default objects */
var prototypes = {};
prototypes.ur = {};
prototypes.load_all = function()
{
if (IO.exists("proto.json"))
prototypes = JSON.parse(IO.slurp("proto.json"));
for (var key in prototypes) {
if (key in gameobjects)
Object.dainty_assign(gameobjects[key], prototypes[key]);
else {
/* Create this gameobject fresh */
Log.info("Making new prototype: " + key + " from " + prototypes[key].from);
var newproto = gameobjects[prototypes[key].from].clone(key);
gameobjects[key] = newproto;
for (var pkey in newproto)
if (typeof newproto[pkey] === 'object' && newproto[pkey] && 'clone' in newproto[pkey])
newproto[pkey] = newproto[pkey].clone();
Object.dainty_assign(gameobjects[key], prototypes[key]);
}
}
}
prototypes.save_gameobjects = function() { slurpwrite(JSON.stringify(gameobjects,null,2), "proto.json"); };
/* Makes a new ur-type from disk. If the ur doesn't exist, it searches on the disk to create it. */
@ -534,7 +527,7 @@ prototypes.from_file = function(file)
}
}
var newur = {};//Object.create(upperur);
var newur = {};
file = file.replaceAll('.','/');
@ -548,7 +541,7 @@ prototypes.from_file = function(file)
try {
if (jsonfile) json = JSON.parse(IO.slurp(jsonfile));
} catch(e) {
Log.warn(e);
Log.warn(`Unable to create json from ${jsonfile}`);
}
if (!json && !script) {

View file

@ -92,6 +92,11 @@ JSValue str2js(const char *c) {
return JS_NewString(js, c);
}
const char *js2str(JSValue v)
{
return JS_ToCString(js, v);
}
JSValue strarr2js(const char **c)
{
JSValue arr = JS_NewArray(js);
@ -289,6 +294,29 @@ JSValue duk_ui_text(JSContext *js, JSValueConst this, int argc, JSValueConst *ar
return ret;
}
int js_print_exception(JSValue v)
{
#ifndef NDEBUG
if (!JS_IsException(v))
return 0;
JSValue ex = JS_GetException(js);
const char *name = JS_ToCString(js, js_getpropstr(ex, "name"));
const char *msg = js2str(js_getpropstr(ex, "message"));
const char *stack = js2str(js_getpropstr(ex, "stack"));
int line = 0;
mYughLog(LOG_SCRIPT, LOG_ERROR, line, "script", "%s :: %s\n%s", name, msg, stack);
JS_FreeCString(js, name);
JS_FreeCString(js, msg);
JS_FreeCString(js, stack);
JS_FreeValue(js,ex);
return 1;
#endif
return 0;
}
JSValue duk_gui_img(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
const char *img = JS_ToCString(js, argv[0]);
gui_draw_img(img, js2hmmv2(argv[1]), js2hmmv2(argv[2]), js2number(argv[3]), js2bool(argv[4]), js2hmmv2(argv[5]), 1.0, js2color(argv[6]));
@ -1469,8 +1497,7 @@ JSValue duk_cmd_circle2d(JSContext *js, JSValueConst this, int argc, JSValueCons
JSValue duk_make_poly2d(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
int go = js2int(argv[0]);
struct phys2d_poly *poly = Make2DPoly(go);
phys2d_poly_setverts(poly, js2cpvec2arr(argv[1]));
phys2d_poly_setverts(poly, NULL);
JSValue polyval = JS_NewObject(js);
js_setprop_str(polyval, "id", ptr2js(poly));
js_setprop_str(polyval, "shape", ptr2js(&poly->shape));
@ -1625,7 +1652,7 @@ void ffi_load() {
DUK_FUNC(cmd_box2d, 6)
DUK_FUNC(make_circle2d, 1)
DUK_FUNC(cmd_circle2d, 6)
DUK_FUNC(make_poly2d, 2)
DUK_FUNC(make_poly2d, 1)
DUK_FUNC(cmd_poly2d, 6)
DUK_FUNC(make_edge2d, 3)
DUK_FUNC(cmd_edge2d, 6)

View file

@ -12,6 +12,7 @@ cpVect js2vec2(JSValue v);
JSValue bitmask2js(cpBitmask mask);
cpBitmask js2bitmask(JSValue v);
int js_print_exception(JSValue v);
struct rgba js2color(JSValue v);
double js2number(JSValue v);

View file

@ -63,7 +63,7 @@ void script_gc()
JSValue num_cache[100] = {0};
int js_print_exception(JSValue v) {
/*int js_print_exception(JSValue v) {
#ifndef NDEBUG
if (JS_IsException(v)) {
JSValue exception = JS_GetException(js);
@ -73,7 +73,7 @@ int js_print_exception(JSValue v) {
return 0;
}
JSValue val = JS_GetPropertyStr(js, exception, "stack");
JSValue val = JS_ToCStringJS_GetPropertyStr(js, exception, "stack");
const char *name = JS_ToCString(js, JS_GetPropertyStr(js, exception, "name"));
const char *msg = JS_ToCString(js, JS_GetPropertyStr(js, exception, "message"));
const char *stack = JS_ToCString(js, val);
@ -90,7 +90,7 @@ int js_print_exception(JSValue v) {
#endif
return 0;
}
*/
void script_run(const char *script, const char *file) {
JSValue obj = JS_Eval(js, script, strlen(script), file, JS_EVAL_FLAGS);
js_print_exception(obj);

View file

@ -236,6 +236,7 @@ void tex_draw(struct Texture *tex, HMM_Vec2 pos, float angle, HMM_Vec2 size, HMM
}
bind_sprite.fs.images[0] = tex->id;
// YughWarn("Draw sprite %s at %g, %g", tex_get_path(tex), sposes[0].X, sposes[0].Y);
sg_append_buffer(bind_sprite.vertex_buffers[0], SG_RANGE_REF(verts));
sg_apply_bindings(&bind_sprite);

View file

@ -26,7 +26,7 @@ uniform sampler smp;
void main()
{
color = fcolor * texture(sampler2D(image,smp), texcoords);
color = texture(sampler2D(image,smp), texcoords);
if (color.a <= 0.1f)
discard;