diff --git a/scripts/base.js b/scripts/base.js index e6a5908..a8934a1 100644 --- a/scripts/base.js +++ b/scripts/base.js @@ -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); } }); diff --git a/scripts/editor.js b/scripts/editor.js index c5c157f..b9f4a9e 100644 --- a/scripts/editor.js +++ b/scripts/editor.js @@ -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); }, }); diff --git a/scripts/entity.js b/scripts/entity.js index 0139000..dc45f82 100644 --- a/scripts/entity.js +++ b/scripts/entity.js @@ -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; diff --git a/source/engine/debug/log.c b/source/engine/debug/log.c index f801ebe..80f0d96 100644 --- a/source/engine/debug/log.c +++ b/source/engine/debug/log.c @@ -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 }