circle and sprites work with saves
This commit is contained in:
parent
fe21b84785
commit
1143b9b3dc
|
@ -333,7 +333,8 @@ Object.defineProperty(String.prototype, 'ext', {
|
||||||
|
|
||||||
Object.defineProperty(String.prototype, 'set_ext', {
|
Object.defineProperty(String.prototype, 'set_ext', {
|
||||||
value: function(val) {
|
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() {
|
value: function() {
|
||||||
var e = this.lastIndexOf('/');
|
var e = this.lastIndexOf('/');
|
||||||
if (e === -1) return "";
|
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 */
|
/* ARRAY DEFS */
|
||||||
|
|
||||||
|
|
|
@ -22,15 +22,46 @@ var component = {
|
||||||
extend(spec) {
|
extend(spec) {
|
||||||
return Object.copy(this, 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 = {
|
component.sprite = {
|
||||||
pos:[0,0],
|
pos:[0,0],
|
||||||
color:[1,1,1],
|
color:[1,1,1],
|
||||||
layer:0,
|
layer:0,
|
||||||
enabled:true,
|
enabled:true,
|
||||||
|
path: "",
|
||||||
toString() { return "sprite"; },
|
toString() { return "sprite"; },
|
||||||
make(go) {
|
make(go) {
|
||||||
var nsprite = Object.create(component.sprite.maker);
|
var nsprite = Object.create(component.sprite.maker);
|
||||||
|
@ -42,7 +73,13 @@ component.sprite = {
|
||||||
};
|
};
|
||||||
|
|
||||||
component.sprite.maker = Object.copy(component, {
|
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; },
|
get visible() { return this.enabled; },
|
||||||
set visible(x) { this.enabled = x; },
|
set visible(x) { this.enabled = x; },
|
||||||
asset(str) { this.path = str; },
|
asset(str) { this.path = str; },
|
||||||
|
@ -690,6 +727,8 @@ component.circle2d = Object.copy(collider2d, {
|
||||||
var circle = Object.create(this);
|
var circle = Object.create(this);
|
||||||
circle.gameobject = go;
|
circle.gameobject = go;
|
||||||
Object.assign(circle, make_circle2d(go.body, circle.radius, circle.offset));
|
Object.assign(circle, make_circle2d(go.body, circle.radius, circle.offset));
|
||||||
|
Object.merge(circle, this.ur);
|
||||||
|
|
||||||
return circle;
|
return circle;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -73,91 +73,6 @@ var editor = {
|
||||||
|
|
||||||
programmode: false,
|
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) {
|
dup_objects(x) {
|
||||||
var objs = x.slice();
|
var objs = x.slice();
|
||||||
var duped = [];
|
var duped = [];
|
||||||
|
@ -504,7 +419,7 @@ return;
|
||||||
this.selectlist.forEach(function(x) {
|
this.selectlist.forEach(function(x) {
|
||||||
var color = x.color ? x.color : Color.white;
|
var color = x.color ? x.color : Color.white;
|
||||||
var sname = x.ur.toString();
|
var sname = x.ur.toString();
|
||||||
if (!x.save_obj().empty)
|
if (!x.json_obj().empty)
|
||||||
x.dirty = true;
|
x.dirty = true;
|
||||||
else
|
else
|
||||||
x.dirty = false;
|
x.dirty = false;
|
||||||
|
@ -668,15 +583,6 @@ return;
|
||||||
editor.selectlist[0].angle = t.angle;
|
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 = {};
|
editor.inputs = {};
|
||||||
|
@ -864,10 +770,11 @@ editor.inputs.escape.doc = "Quit editor.";
|
||||||
|
|
||||||
editor.inputs['C-s'] = function() {
|
editor.inputs['C-s'] = function() {
|
||||||
if (editor.selectlist.length !== 1 || !editor.selectlist[0].dirty) return;
|
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());
|
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;
|
return;
|
||||||
|
|
||||||
if (editor.edit_level.level) {
|
if (editor.edit_level.level) {
|
||||||
|
@ -1715,13 +1622,6 @@ var groupsaveaspanel = Object.copy(inputpanel, {
|
||||||
action() { editor.groupsaveas(editor.selectlist, this.value); }
|
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, {
|
var savetypeas = Object.copy(inputpanel, {
|
||||||
title: "save type as",
|
title: "save type as",
|
||||||
action() {
|
action() {
|
||||||
|
|
|
@ -94,20 +94,11 @@ var gameobject = {
|
||||||
return bb.t-bb.b;
|
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 */
|
/* Make a unique object the same as its prototype */
|
||||||
revert() {
|
revert() {
|
||||||
var save = this.save_obj();
|
var t = this.transform();
|
||||||
for (var key in save)
|
Object.totalmerge(this,this.ur);
|
||||||
this[key] = this.ur[key];
|
Object.merge(this,t);
|
||||||
},
|
},
|
||||||
|
|
||||||
gui() {
|
gui() {
|
||||||
|
@ -368,12 +359,11 @@ var gameobject = {
|
||||||
if ('ur' in p) {
|
if ('ur' in p) {
|
||||||
obj[prop] = obj.spawn(prototypes.get_ur(p.ur));
|
obj[prop] = obj.spawn(prototypes.get_ur(p.ur));
|
||||||
obj.$[prop] = obj[prop];
|
obj.$[prop] = obj[prop];
|
||||||
} else if ('make' in p) {
|
|
||||||
obj[prop] = p.make(obj);
|
|
||||||
obj.components[prop] = obj[prop];
|
|
||||||
} else if ('comp' in p) {
|
} else if ('comp' in p) {
|
||||||
obj[prop] = component[p.comp].make(obj);
|
obj[prop] = component[p.comp].make(obj);
|
||||||
obj.components[prop] = obj[prop];
|
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(jsfile)) script = IO.slurp(jsfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IO.exists(jsonfile))
|
if (IO.exists(jsonfile)) {
|
||||||
|
try {
|
||||||
json = JSON.parse(IO.slurp(jsonfile));
|
json = JSON.parse(IO.slurp(jsonfile));
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
Log.warn(`JSON in file ${jsonfile} is malformed.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
jsonfile = urpath + "/" + path.at(-1) + ".json";
|
jsonfile = urpath + "/" + path.at(-1) + ".json";
|
||||||
if (IO.exists(jsonfile)) json = JSON.parse(IO.slurp(jsonfile));
|
if (IO.exists(jsonfile)) json = JSON.parse(IO.slurp(jsonfile));
|
||||||
|
@ -555,7 +551,6 @@ prototypes.get_ur = function(name)
|
||||||
|
|
||||||
if (!prototypes.ur[urpath]) {
|
if (!prototypes.ur[urpath]) {
|
||||||
var ur = prototypes.from_file(urpath);
|
var ur = prototypes.from_file(urpath);
|
||||||
Log.warn(`tried to make ${urpath}`);
|
|
||||||
if (ur)
|
if (ur)
|
||||||
return ur;
|
return ur;
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -201,6 +201,7 @@ struct phys2d_circle *Make2DCircle(int go) {
|
||||||
new->shape.shape = cpSpaceAddShape(space, cpCircleShapeNew(id2go(go)->body, new->radius, cpvzero));
|
new->shape.shape = cpSpaceAddShape(space, cpCircleShapeNew(id2go(go)->body, new->radius, cpvzero));
|
||||||
new->shape.debugdraw = phys2d_dbgdrawcircle;
|
new->shape.debugdraw = phys2d_dbgdrawcircle;
|
||||||
new->shape.moi = phys2d_circle_moi;
|
new->shape.moi = phys2d_circle_moi;
|
||||||
|
new->shape.apply = phys2d_applycircle;
|
||||||
init_phys2dshape(&new->shape, go, new);
|
init_phys2dshape(&new->shape, go, new);
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
|
|
|
@ -21,13 +21,13 @@ extern struct rgba kinematic_color;
|
||||||
extern struct rgba static_color;
|
extern struct rgba static_color;
|
||||||
extern struct rgba sleep_color;
|
extern struct rgba sleep_color;
|
||||||
|
|
||||||
|
|
||||||
struct phys2d_shape {
|
struct phys2d_shape {
|
||||||
cpShape *shape;
|
cpShape *shape;
|
||||||
int go;
|
int go;
|
||||||
void *data;
|
void *data;
|
||||||
void (*debugdraw)(void *data);
|
void (*debugdraw)(void *data);
|
||||||
float (*moi)(void *data, float mass);
|
float (*moi)(void *data, float mass);
|
||||||
|
void (*apply)(void *data);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Circles are the fastest collier type */
|
/* Circles are the fastest collier type */
|
||||||
|
|
|
@ -707,6 +707,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
|
|
||||||
case 36:
|
case 36:
|
||||||
id2go(js2int(argv[1]))->scale = js2number(argv[2]);
|
id2go(js2int(argv[1]))->scale = js2number(argv[2]);
|
||||||
|
gameobject_apply(id2go(js2int(argv[1])));
|
||||||
cpSpaceReindexShapesForBody(space, id2go(js2int(argv[1]))->body);
|
cpSpaceReindexShapesForBody(space, id2go(js2int(argv[1]))->body);
|
||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,10 @@ void go_shape_apply(cpBody *body, cpShape *shape, struct gameobject *go) {
|
||||||
filter.categories = CP_ALL_CATEGORIES;//1<<go->layer;
|
filter.categories = CP_ALL_CATEGORIES;//1<<go->layer;
|
||||||
filter.mask = CP_ALL_CATEGORIES;//category_masks[go->layer];
|
filter.mask = CP_ALL_CATEGORIES;//category_masks[go->layer];
|
||||||
cpShapeSetFilter(shape, filter);
|
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) {
|
void go_shape_moi(cpBody *body, cpShape *shape, struct gameobject *go) {
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
|
|
||||||
|
@ -248,8 +249,34 @@ char *slurp_text(const char *filename, size_t *size)
|
||||||
return retstr;
|
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) {
|
int slurp_write(const char *txt, const char *filename) {
|
||||||
FILE *f = fopen(filename, "w");
|
FILE *f = fopen_mkdir(filename, "w");
|
||||||
if (!f) return 1;
|
if (!f) return 1;
|
||||||
|
|
||||||
fputs(txt, f);
|
fputs(txt, f);
|
||||||
|
|
Loading…
Reference in a new issue