circle and sprites work with saves

This commit is contained in:
John Alanbrook 2023-09-26 22:07:51 +00:00
parent fe21b84785
commit 1143b9b3dc
9 changed files with 103 additions and 129 deletions

View file

@ -333,7 +333,8 @@ Object.defineProperty(String.prototype, 'ext', {
Object.defineProperty(String.prototype, 'set_ext', {
value: function(val) {
return this.dir() + this.name() + val;
var s = this.strip_ext();
return s + val;
}
});
@ -356,10 +357,16 @@ Object.defineProperty(String.prototype, 'dir', {
value: function() {
var e = this.lastIndexOf('/');
if (e === -1) return "";
return this.slice(0, e+1);
return this.slice(0, e);
}
});
Object.defineProperty(String.prototype, 'updir', {
value: function() {
var dir = this.dir();
return dir.dir();
}
});
/* ARRAY DEFS */

View file

@ -22,15 +22,46 @@ var component = {
extend(spec) {
return Object.copy(this, spec);
},
/* Given a relative path, return the full path */
resani(path) {
if (!this.gameobject) return path;
if (path[0] === '/') return path.slice(1);
var res = this.gameobject.ur.toString();
res = res.replaceAll('.', '/');
var restry = res + "/" + path;
while (!IO.exists(restry)) {
res = res.updir() + "/";
if (res === "/")
return path;
restry = res + path;
}
return restry;
},
/* Given the full path, return the most relative path */
resavi(path) {
if (!this.gameobject) return path;
if (path[0] === '/') return path;
var res = this.gameobject.ur.toString();
res = res.replaceAll('.', '/');
if (!path.startsWith(res))
return path;
return path.replace(res, "").slice(1);
},
};
component.toJSON = ur_json;
//component.toJSON = ur_json;
component.sprite = {
pos:[0,0],
color:[1,1,1],
layer:0,
enabled:true,
path: "",
toString() { return "sprite"; },
make(go) {
var nsprite = Object.create(component.sprite.maker);
@ -42,7 +73,13 @@ component.sprite = {
};
component.sprite.maker = Object.copy(component, {
set path(x) { cmd(12,this.id,x,this.rect); },
set path(x) {
x = this.resani(x);
cmd(12,this.id,x,this.rect);
},
get path() {
return cmd(116,this.id);
},
get visible() { return this.enabled; },
set visible(x) { this.enabled = x; },
asset(str) { this.path = str; },
@ -690,6 +727,8 @@ component.circle2d = Object.copy(collider2d, {
var circle = Object.create(this);
circle.gameobject = go;
Object.assign(circle, make_circle2d(go.body, circle.radius, circle.offset));
Object.merge(circle, this.ur);
return circle;
},

View file

@ -73,91 +73,6 @@ var editor = {
programmode: false,
delete_empty_reviver(key, val) {
if (typeof val === 'object' && val.empty)
return undefined;
return val;
},
save_proto() {
if (this.selectlist.length !== 1) return;
Log.warn(`Saving prototype ${this.selectlist[0].toString()}`);
var protos = JSON.parse(IO.slurp("proto.json"));
var tobj = this.selectlist[0].prop_obj();
var pobj = this.selectlist[0].__proto__.prop_obj();
Log.warn("Going to deep merge.");
deep_merge(pobj, tobj);
Log.warn("Finished deep merge.");
pobj.from = this.selectlist[0].__proto__.from;
protos[this.selectlist[0].__proto__.name] = pobj;
Log.warn(JSON.stringify(protos));
slurpwrite(JSON.stringify(protos, undefined, 2), "proto.json");
/* Save object changes to parent */
Object.dainty_assign(this.selectlist[0].__proto__, tobj);
/* Remove the local from this object */
unmerge(this.selectlist[0], tobj);
/* Now sync all objects */
Game.objects.forEach(x => x.sync());
},
/* Save the selected object as a new prototype, extending the chain */
save_proto_as(name) {
if (name in gameobjects) {
Log.info("Already an object with name '" + name + "'. Choose another one.");
return;
}
var newp = this.selectlist[0].__proto__.clone(name);
for (var key in newp)
if (typeof newp[key] === 'object' && 'clone' in newp[key])
newp[key] = newp[key].clone();
Object.dainty_assign(newp, this.selectlist[0].prop_obj());
this.selectlist[0].kill();
var gopos = this.selectlist[0].pos;
this.unselect();
var proto = this.edit_level.spawn(gameobjects[name]);
this.selectlist.push(proto);
this.save_proto();
proto.pos = gopos;
},
/* Save selected object as a new prototype, replacing the current prototype */
save_type_as(name) {
if (name in gameobjects) {
Log.info("Already an object with name '" + name + "'. Choose another one.");
return;
}
var newp = this.selectlist[0].__proto__.__proto__.clone(name);
for (var key in newp)
if (typeof newp[key] === 'object' && 'clone' in newp[key])
newp[key] = newp[key].clone();
var tobj = this.selectlist[0].prop_obj();
var pobj = this.selectlist[0].__proto__.prop_obj();
deep_merge(pobj, tobj);
Object.dainty_assign(newp, pobj);
this.selectlist[0].kill();
this.unselect();
var proto = this.edit_level.spawn(gameobjects[name]);
this.selectlist.push(proto);
this.save_proto();
},
dup_objects(x) {
var objs = x.slice();
var duped = [];
@ -504,7 +419,7 @@ return;
this.selectlist.forEach(function(x) {
var color = x.color ? x.color : Color.white;
var sname = x.ur.toString();
if (!x.save_obj().empty)
if (!x.json_obj().empty)
x.dirty = true;
else
x.dirty = false;
@ -668,15 +583,6 @@ return;
editor.selectlist[0].angle = t.angle;
}
},
saveas(file) {
if (!file) return;
Log.info("made it");
this.edit_level.file = file;
this.save_current();
},
}
editor.inputs = {};
@ -864,10 +770,11 @@ editor.inputs.escape.doc = "Quit editor.";
editor.inputs['C-s'] = function() {
if (editor.selectlist.length !== 1 || !editor.selectlist[0].dirty) return;
Log.warn(`Saving ur for ${editor.selectlist[0].toString()}`);
Object.merge(editor.selectlist[0].ur, editor.selectlist[0].json_obj());
IO.slurpwrite(JSON.stringify(editor.selectlist[0].ur,null,1), editor.selectlist[0].toString() + ".json");
var path = editor.selectlist[0].toString();
path = path.replaceAll('.','/');
path = path + "/" + path.name() + ".json";
IO.slurpwrite(JSON.stringify(editor.selectlist[0].ur,null,1), path);
return;
if (editor.edit_level.level) {
@ -1715,13 +1622,6 @@ var groupsaveaspanel = Object.copy(inputpanel, {
action() { editor.groupsaveas(editor.selectlist, this.value); }
});
var saveprototypeas = Object.copy(inputpanel, {
title: "save prototype as",
action() {
editor.save_proto_as(this.value);
},
});
var savetypeas = Object.copy(inputpanel, {
title: "save type as",
action() {

View file

@ -94,20 +94,11 @@ var gameobject = {
return bb.t-bb.b;
},
save_obj() {
var json = JSON.stringify(this);
if (!json) return {};
var o = JSON.parse(json);
delete o.pos;
delete o.angle;
return o;
},
/* Make a unique object the same as its prototype */
revert() {
var save = this.save_obj();
for (var key in save)
this[key] = this.ur[key];
var t = this.transform();
Object.totalmerge(this,this.ur);
Object.merge(this,t);
},
gui() {
@ -368,12 +359,11 @@ var gameobject = {
if ('ur' in p) {
obj[prop] = obj.spawn(prototypes.get_ur(p.ur));
obj.$[prop] = obj[prop];
} else if ('make' in p) {
obj[prop] = p.make(obj);
obj.components[prop] = obj[prop];
} else if ('comp' in p) {
obj[prop] = component[p.comp].make(obj);
obj.components[prop] = obj[prop];
obj[prop].ur = Object.create(obj[prop].ur);
Object.totalmerge(obj[prop].ur, p);
}
};
@ -483,8 +473,14 @@ prototypes.from_file = function(file)
if (IO.exists(jsfile)) script = IO.slurp(jsfile);
}
if (IO.exists(jsonfile))
json = JSON.parse(IO.slurp(jsonfile));
if (IO.exists(jsonfile)) {
try {
json = JSON.parse(IO.slurp(jsonfile));
}
catch(e) {
Log.warn(`JSON in file ${jsonfile} is malformed.`);
}
}
else {
jsonfile = urpath + "/" + path.at(-1) + ".json";
if (IO.exists(jsonfile)) json = JSON.parse(IO.slurp(jsonfile));
@ -555,7 +551,6 @@ prototypes.get_ur = function(name)
if (!prototypes.ur[urpath]) {
var ur = prototypes.from_file(urpath);
Log.warn(`tried to make ${urpath}`);
if (ur)
return ur;
else {

View file

@ -201,6 +201,7 @@ struct phys2d_circle *Make2DCircle(int go) {
new->shape.shape = cpSpaceAddShape(space, cpCircleShapeNew(id2go(go)->body, new->radius, cpvzero));
new->shape.debugdraw = phys2d_dbgdrawcircle;
new->shape.moi = phys2d_circle_moi;
new->shape.apply = phys2d_applycircle;
init_phys2dshape(&new->shape, go, new);
return new;

View file

@ -21,13 +21,13 @@ extern struct rgba kinematic_color;
extern struct rgba static_color;
extern struct rgba sleep_color;
struct phys2d_shape {
cpShape *shape;
int go;
void *data;
void (*debugdraw)(void *data);
float (*moi)(void *data, float mass);
void (*apply)(void *data);
};
/* Circles are the fastest collier type */

View file

@ -707,6 +707,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
case 36:
id2go(js2int(argv[1]))->scale = js2number(argv[2]);
gameobject_apply(id2go(js2int(argv[1])));
cpSpaceReindexShapesForBody(space, id2go(js2int(argv[1]))->body);
return JS_NULL;

View file

@ -95,6 +95,10 @@ void go_shape_apply(cpBody *body, cpShape *shape, struct gameobject *go) {
filter.categories = CP_ALL_CATEGORIES;//1<<go->layer;
filter.mask = CP_ALL_CATEGORIES;//category_masks[go->layer];
cpShapeSetFilter(shape, filter);
struct phys2d_shape *ape = cpShapeGetUserData(shape);
if (ape)
ape->apply(ape->data);
}
void go_shape_moi(cpBody *body, cpShape *shape, struct gameobject *go) {

View file

@ -10,6 +10,7 @@
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include "font.h"
@ -248,8 +249,34 @@ char *slurp_text(const char *filename, size_t *size)
return retstr;
}
void rek_mkdir(char *path) {
char *sep = strrchr(path, '/');
if(sep != NULL) {
*sep = 0;
rek_mkdir(path);
*sep = '/';
}
#if defined __WIN32
if(mkdir(path) && errno != EEXIST)
#else
if (mkdir(path, 0777) && errno != EEXIST)
#endif
printf("error while trying to create '%s'\n%m\n", path);
}
FILE *fopen_mkdir(char *path, char *mode) {
char *sep = strrchr(path, '/');
if(sep) {
char *path0 = strdup(path);
path0[ sep - path ] = 0;
rek_mkdir(path0);
free(path0);
}
return fopen(path,mode);
}
int slurp_write(const char *txt, const char *filename) {
FILE *f = fopen(filename, "w");
FILE *f = fopen_mkdir(filename, "w");
if (!f) return 1;
fputs(txt, f);