Ur saving, ur subtyping

This commit is contained in:
John Alanbrook 2023-09-26 18:34:02 +00:00
parent db8e59a8eb
commit fe21b84785
4 changed files with 113 additions and 109 deletions

View file

@ -315,6 +315,13 @@ Object.defineProperty(String.prototype, 'shift', {
}
});
Object.defineProperty(String.prototype, 'strip_ext', {
value: function() {
var idx = this.lastIndexOf('.');
if (idx === -1) return this.slice();
return this.slice(0,idx);
}
});
Object.defineProperty(String.prototype, 'ext', {
value: function() {
@ -326,7 +333,7 @@ Object.defineProperty(String.prototype, 'ext', {
Object.defineProperty(String.prototype, 'set_ext', {
value: function(val) {
return this.dir() + "/" + this.name() + val;
return this.dir() + this.name() + val;
}
});
@ -348,7 +355,8 @@ Object.defineProperty(String.prototype, 'base', {
Object.defineProperty(String.prototype, 'dir', {
value: function() {
var e = this.lastIndexOf('/');
return this.slice(0, e);
if (e === -1) return "";
return this.slice(0, e+1);
}
});

View file

@ -424,23 +424,7 @@ return;
this.openpanel(saveaspanel);
return;
}
var lvl = this.edit_level.save();
Log.info("Saving level of size " + lvl.length + " bytes.");
slurpwrite(lvl, this.edit_level.file);
this.edit_level.filejson = lvl;
this.edit_level.check_dirty();
if (this.edit_level.script) {
var scriptfile = this.edit_level.file.replace('.lvl', '.js');
slurpwrite(this.edit_level.script, scriptfile);
}
Level.sync_file(this.edit_level.file);
},
clear_level() {
if (this.edit_level) {
@ -634,7 +618,6 @@ return;
var ur = prototypes.get_ur(file);
if (!ur) return;
var obj = editor.edit_level.spawn(ur);
Log.warn(`editor loading ur ${file} with type ${JSON.stringify(prototypes.get_ur(file),null,2)}`);
obj.pos = Mouse.worldpos;
this.selectlist = [obj];
},
@ -665,18 +648,25 @@ return;
group.forEach(function(x) { x.kill(); });
}
},
saveas_check(file) {
if (!file) return;
/* Checking to save an entity as a subtype. */
saveas_check(sub) {
if (!sub) return;
var curur = prototypes.get_ur(sub);
if (!file.endsWith(".lvl"))
file = file + ".lvl";
if (IO.exists(file)) {
if (curur) {
notifypanel.action = editor.saveas;
this.openpanel(gen_notify("Level already exists with that name. Overwrite?", this.saveas.bind(this, file)));
} else
this.saveas(file);
this.openpanel(gen_notify("Entity already exists with that name. Overwrite?", this.saveas.bind(this, sub)));
} else {
var path = sub.replaceAll('.', '/') + ".json";
IO.slurpwrite(JSON.stringify(editor.selectlist[0],null,1), path);
var t = editor.selectlist[0].transform();
editor.selectlist[0].kill();
editor.unselect();
editor.load(sub);
editor.selectlist[0].pos = t.pos;
editor.selectlist[0].angle = t.angle;
}
},
saveas(file) {
@ -718,16 +708,16 @@ editor.inputs['C-h'].doc = "Unhide all objects.";
editor.inputs['C-e'] = function() { editor.openpanel(assetexplorer); };
editor.inputs['C-e'].doc = "Open asset explorer.";
editor.inputs['C-l'] = function() { editor.openpanel(entitylistpanel, true); };
editor.inputs['C-l'] = function() { editor.openpanel(entitylistpanel); };
editor.inputs['C-l'].doc = "Open list of spawned entities.";
editor.inputs['C-i'] = function() {
/*editor.inputs['C-i'] = function() {
if (editor.selectlist.length !== 1) return;
objectexplorer.obj = editor.selectlist[0];
editor.openpanel(objectexplorer);
};
editor.inputs['C-i'].doc = "Open the object explorer for a selected object.";
*/
editor.inputs['C-d'] = function() {
if (editor.selectlist.length === 0) return;
var duped = editor.dup_objects(editor.selectlist);
@ -873,6 +863,13 @@ editor.inputs.escape = function() { editor.openpanel(quitpanel); }
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");
return;
if (editor.edit_level.level) {
if (!editor.edit_level.unique)
editor.save_current();
@ -889,6 +886,8 @@ editor.inputs['C-s'] = function() {
editor.inputs['C-s'].doc = "Save selected.";
editor.inputs['C-S'] = function() {
if (editor.selectlist.length !== 1) return;
saveaspanel.stem = this.selectlist[0].toString();
editor.openpanel(saveaspanel);
};
editor.inputs['C-S'].doc = "Save selected as.";
@ -1500,7 +1499,7 @@ var replpanel = Object.copy(inputpanel, {
ecode += this.value;
Log.say(this.value);
this.value = "";
var ret = eval(ecode);
var ret = function() {return eval(ecode);}.call(editor.selectlist[0]);
if (ret) Log.say(ret);
},
});
@ -1707,7 +1706,7 @@ var openlevelpanel = Object.copy(inputpanel, {
var saveaspanel = Object.copy(inputpanel, {
title: "save level as",
action() {
editor.saveas_check(this.value);
editor.saveas_check(this.stem + "." + this.value);
},
});

View file

@ -279,35 +279,7 @@ var gameobject = {
},
json_obj() {
function objdiff(from, to) {
if (!to) return from; // Everything on from is unique
var ret = {};
for (var key in from) {
if (!from[key] || !to[key]) continue;
if (typeof from[key] === 'function') continue;
if (typeof to === 'object' && !(key in to)) continue;
if (typeof from[key] === 'object') {
if ('ur' in from[key]) {
var urdiff = objdiff(from[key],from[key].ur);
if (urdiff && !urdiff.empty) ret[key] = urdiff;
continue;
}
var diff = objdiff(from[key], to[key]);
if (diff && !diff.empty) ret[key] = diff;
continue;
}
if (from[key] !== to[key])
ret[key] = from[key];
}
if (ret.empty) return undefined;
return ret;
}
var ur = Object.create(this.ur);
Object.assign(ur,objdiff(this,this.ur));
return ur;
return JSON.parse(JSON.stringify(this));
},
make_ur() {
@ -317,6 +289,13 @@ var gameobject = {
return thisur;
},
transform() {
var t = {};
t.pos = this.pos;
t.angle = this.angle;
return t;
},
dup(diff) {
var n = this.level.spawn(this.ur);
Object.totalmerge(n, this.make_ur());
@ -468,49 +447,65 @@ for (var key in prototypes) {
prototypes.save_gameobjects = function() { slurpwrite(JSON.stringify(gameobjects,null,2), "proto.json"); };
/* Makes a new ur-type from a file. The file can define components. */
/* Makes a new ur-type from disk. If the ur doesn't exist, it searches on the disk to create it. */
prototypes.from_file = function(file)
{
if (!IO.exists(file)) {
Log.error(`File ${file} does not exist.`);
return;
}
var urpath = prototypes.file2ur(file);
var urpath = file;
var path = urpath.split('.');
if (path.length > 1 && (path.at(-1) === path.at(-2))) {
return prototypes.get_ur(path.at(-1));
}
var upperur = gameobject.ur;
if (path.length > 1) {
var upperpath = path.slice(0,-1);
upperur = prototypes.get_ur(upperpath.join('/'));
if (!upperur) {
Log.error(`Attempted to create an UR ${urpath}, but ${upperpath} is not a defined UR.`);
return undefined;
}
}
var newur = Object.create(upperur);
var script = IO.slurp(file);
file = file.replaceAll('.','/');
var json = {};
if (IO.exists(file.name() + ".json"))
json = JSON.parse(IO.slurp(file.name() + ".json"));
var jsfile = file + ".js";
var jsonfile = file + ".json";
var script = undefined;
var json = undefined;
if (IO.exists(jsfile))
script = IO.slurp(jsfile);
else {
jsfile = urpath + "/" + path.at(-1) + ".js";
if (IO.exists(jsfile)) script = IO.slurp(jsfile);
}
if (IO.exists(jsonfile))
json = JSON.parse(IO.slurp(jsonfile));
else {
jsonfile = urpath + "/" + path.at(-1) + ".json";
if (IO.exists(jsonfile)) json = JSON.parse(IO.slurp(jsonfile));
}
if (!json && !script) {
Log.warn(`Could not make ur from ${file}`);
return undefined;
}
if (script)
compile_env(script, newur, file);
compile_env(script, newur, file);
json ??= {};
Object.merge(newur,json);
file = file.replaceAll('/', '.');
var nested_access = function(base, names) {
for (var i = 0; i < names.length; i++)
base = base[names[i]] = base[names[i]] || {};
return base;
};
prototypes.list.push(urpath);
newur.toString = function() { return urpath; };
ur[urpath] = nested_access(ur,path);
Object.assign(ur[urpath], newur);
nested_access(ur,path).__proto__ = newur.__proto__;
ur[urpath] = newur;
return ur[path];
return ur[urpath];
}
prototypes.from_file.doc = "Create a new ur-type from a given script file.";
prototypes.list = [];
@ -532,7 +527,6 @@ prototypes.list_ur = function()
var list = [];
for (var e in obj) {
list.push(prefix + e);
Log.warn("Descending into " + e);
list.concat(list_obj(obj[e], e + "."));
}
@ -542,38 +536,43 @@ prototypes.list_ur = function()
return list_obj(ur);
}
prototypes.file2ur(file)
prototypes.file2ur = function(file)
{
file = file.strip_ext();
file = file.replaceAll('/','.');
return file.name();
return file;
}
/* Returns an ur, or makes it, for any given type of path
could be a file on a disk like ball/big.js
could be an ur path like ball.big
*/
prototypes.get_ur = function(name)
{
var urpath = prototypes.file2ur(name);
if (!prototypes.ur[name]) {
if (IO.exists(name.name() + ".js")) {
prototypes.from_file(name.name() + ".js");
return prototypes.ur[name];
} else {
var urpath = name;
if (urpath.includes('/'))
urpath = prototypes.file2ur(name);
if (!prototypes.ur[urpath]) {
var ur = prototypes.from_file(urpath);
Log.warn(`tried to make ${urpath}`);
if (ur)
return ur;
else {
Log.warn(`Could not find prototype using name ${name}.`);
return undefined;
}
} else
return prototypes.ur[name];
return prototypes.ur[urpath];
}
prototypes.generate_ur = function(path)
{
var ob = IO.glob("**.js");
ob = ob.filter(function(str) { return !str.startsWith("scripts"); });
ob.forEach(function(name) {
if (name === "game.js") return;
if (name === "play.js") return;
Log.warn("generating for " + name);
prototypes.get_ur(name);
});
ob = ob.concat(IO.glob("**.json"));
ob = ob.filter(function(path) { return path !== "game.js" && path !== "play.js" });
ob = ob.map(function(path) { return path.set_ext(""); });
ob.forEach(function(name) { prototypes.get_ur(name); });
}
var ur = prototypes.ur;

View file

@ -63,8 +63,6 @@ void mYughLog(int category, int priority, int line, const char *file, const char
// js_stacktrace();
}
if (priority >= 2)
print_stacktrace();
#endif
}