create new entities in editor
This commit is contained in:
parent
1e432346ff
commit
1e9b5f6341
|
@ -4,6 +4,16 @@ this.view2world = function(pos) { return cmd(137,pos); };
|
|||
this.world2view = function(pos) { return cmd(136,pos); };
|
||||
this.realzoom = function() { return cmd(135); };
|
||||
|
||||
this.right = function()
|
||||
{
|
||||
return this.pos.x + (Window.width/2);
|
||||
}
|
||||
|
||||
this.left = function()
|
||||
{
|
||||
return this.pos.x - (Window.width/2);
|
||||
}
|
||||
|
||||
this.mixin({
|
||||
get zoom() {
|
||||
var z = Game.native.y / Window.dimensions.y;
|
||||
|
|
|
@ -817,8 +817,8 @@ component.circle2d.impl = Object.mix({
|
|||
set offset(x) { cmd_circle2d(1,this.id,x); },
|
||||
get offset() { return cmd_circle2d(3,this.id); },
|
||||
|
||||
get pos() { return this.offset; },
|
||||
set pos(x) { this.offset = x; },
|
||||
get pos() { return cmd_circle2d(3,this.id); },
|
||||
set pos(x) { cmd_circle2d(1,this.id,x); },
|
||||
|
||||
}, collider2d.impl);
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ var Gizmos = {
|
|||
},
|
||||
};
|
||||
|
||||
Object.assign(profile, {
|
||||
Object.assign(performance, {
|
||||
tick_now() { return cmd(127); },
|
||||
ns(ticks) { return cmd(128, ticks); },
|
||||
us(ticks) { return cmd(129, ticks); },
|
||||
|
@ -123,34 +123,43 @@ Object.assign(profile, {
|
|||
cpu(fn, times, q) {
|
||||
times ??= 1;
|
||||
q ??= "unnamed";
|
||||
var start = profile.tick_now();
|
||||
var start = performance.tick_now();
|
||||
for (var i = 0; i < times; i++)
|
||||
fn();
|
||||
|
||||
var elapsed = profile.tick_now() - start;
|
||||
var avgt = profile.best_t(elapsed/times);
|
||||
var totalt = profile.best_t(elapsed);
|
||||
var elapsed = performance.tick_now() - start;
|
||||
var avgt = performance.best_t(elapsed/times);
|
||||
var totalt = performance.best_t(elapsed);
|
||||
|
||||
console.say(`profile [${q}]: ${avgt.time.toFixed(3)} ${avgt.unit} average [${totalt.time.toFixed(3)} ${totalt.unit} for ${times} loops]`);
|
||||
console.say(`performance [${q}]: ${avgt.time.toFixed(3)} ${avgt.unit} average [${totalt.time.toFixed(3)} ${totalt.unit} for ${times} loops]`);
|
||||
},
|
||||
|
||||
get fps() { return sys_cmd(8); },
|
||||
|
||||
measure(fn, str) {
|
||||
str ??= 'unnamed';
|
||||
var start = performance.tick_now();
|
||||
fn();
|
||||
var elapsed = performance.tick_now()-start;
|
||||
elapsed = performance.best_t(elapsed);
|
||||
say(`performance [${str}]: ${elapsed.time.toFixed(3)} ${elapsed.unit}`);
|
||||
},
|
||||
});
|
||||
|
||||
profile.test = {
|
||||
barecall() { profile(0); },
|
||||
unpack_num(n) { profile(1,n); },
|
||||
unpack_array(n) { profile(2,n); },
|
||||
pack_num() { profile(3); },
|
||||
pack_string() { profile(6); },
|
||||
unpack_string(s) { profile(4,s); },
|
||||
unpack_32farr(a) { profile(5,a); },
|
||||
call_fn_n(fn1, n) { profile(7,fn1,n,fn2); },
|
||||
performance.test = {
|
||||
barecall() { performance(0); },
|
||||
unpack_num(n) { performance(1,n); },
|
||||
unpack_array(n) { performance(2,n); },
|
||||
pack_num() { performance(3); },
|
||||
pack_string() { performance(6); },
|
||||
unpack_string(s) { performance(4,s); },
|
||||
unpack_32farr(a) { performance(5,a); },
|
||||
call_fn_n(fn1, n) { performance(7,fn1,n,fn2); },
|
||||
};
|
||||
|
||||
profile.test.call_fn_n.doc = "Calls fn1 n times, and then fn2.";
|
||||
performance.test.call_fn_n.doc = "Calls fn1 n times, and then fn2.";
|
||||
|
||||
profile.cpu.doc = `Output the time it takes to do a given function n number of times. Provide 'q' as "ns", "us", or "ms" to output the time taken in the requested resolution.`;
|
||||
performance.cpu.doc = `Output the time it takes to do a given function n number of times. Provide 'q' as "ns", "us", or "ms" to output the time taken in the requested resolution.`;
|
||||
|
||||
/* These controls are available during editing, and during play of debug builds */
|
||||
var DebugControls = {};
|
||||
|
@ -347,4 +356,6 @@ Debug.api.print_doc = function(name)
|
|||
return {
|
||||
Debug,
|
||||
Time,
|
||||
Gizmos,
|
||||
performance
|
||||
}
|
||||
|
|
|
@ -521,8 +521,8 @@ var editor = {
|
|||
|
||||
lvl_history: [],
|
||||
|
||||
load(file) {
|
||||
var obj = editor.edit_level.spawn(Object.access(ur, file));
|
||||
load(urstr) {
|
||||
var obj = editor.edit_level.spawn(urstr);
|
||||
obj.set_worldpos(Mouse.worldpos);
|
||||
this.selectlist = [obj];
|
||||
},
|
||||
|
@ -537,12 +537,41 @@ var editor = {
|
|||
|
||||
/* Checking to save an entity as a subtype. */
|
||||
/* sub is the name of the (sub)type; obj is the object to save it as */
|
||||
/* if saving subtype of 'empty', it appears on the top level */
|
||||
saveas_check(sub, obj) {
|
||||
if (!sub) {
|
||||
console.warn(`Cannot save an object to an empty ur.`);
|
||||
return;
|
||||
if (!sub) return;
|
||||
obj ??= editor.selectlist[0];
|
||||
}
|
||||
|
||||
// var curur = prototypes.get_ur(sub);
|
||||
if (!obj) {
|
||||
console.warn(`Specify an obejct to save.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj.ur === 'empty') {
|
||||
/* make a new type path */
|
||||
if (Object.access(ur,sub)) {
|
||||
console.warn(`Ur named ${sub} already exists.`);
|
||||
return;
|
||||
}
|
||||
|
||||
var file = `${sub}.json`;
|
||||
io.slurpwrite(file, json.encode(obj.json_obj(),null,1));
|
||||
ur[sub] = {
|
||||
name: sub,
|
||||
data: file,
|
||||
proto: json.decode(json.encode(obj))
|
||||
}
|
||||
obj.ur = sub;
|
||||
|
||||
return;
|
||||
} else if (!sub.startswith(obj.ur)) {
|
||||
console.warn(`Cannot make an ur of type ${sub} from an object with the ur ${obj.ur}`);
|
||||
return;
|
||||
}
|
||||
|
||||
var curur = Object.access(ur,sub);
|
||||
|
||||
if (curur) {
|
||||
notifypanel.action = editor.saveas;
|
||||
|
@ -572,16 +601,32 @@ var editor = {
|
|||
},
|
||||
}
|
||||
|
||||
editor.new_object = function()
|
||||
{
|
||||
var obj = editor.edit_level.spawn();
|
||||
obj.set_worldpos(Mouse.worldpos);
|
||||
this.selectlist = [obj];
|
||||
return obj;
|
||||
}
|
||||
editor.new_object.doc = "Create an empty object.";
|
||||
|
||||
editor.new_from_img = function(path)
|
||||
{
|
||||
var o = editor.new_object();
|
||||
o.add_component(component.sprite).path = path;
|
||||
return o;
|
||||
}
|
||||
|
||||
editor.inputs = {};
|
||||
editor.inputs.drop = function(str) {
|
||||
str = str.slice(os.cwd().length+1);
|
||||
if (!Resources.is_image(str)) {
|
||||
console.warn("NOT AN IMAGE");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.selectlist.length === 0) {
|
||||
|
||||
}
|
||||
if (this.selectlist.length === 0)
|
||||
return editor.new_from_img(str);
|
||||
|
||||
if (this.sel_comp?.comp === 'sprite') {
|
||||
this.sel_comp.path = str;
|
||||
|
@ -821,19 +866,34 @@ editor.inputs['C-s'] = function() {
|
|||
} else if (editor.selectlist.length === 1)
|
||||
saveobj = editor.selectlist[0];
|
||||
|
||||
// saveobj.check_dirty();
|
||||
// if (!saveobj._ed.dirty) return;
|
||||
saveobj.check_dirty();
|
||||
if (!saveobj._ed.dirty) {
|
||||
console.warn(`Object ${saveobj.full_path()} does not need saved.`);
|
||||
return;
|
||||
}
|
||||
|
||||
var savejs = saveobj.json_obj();
|
||||
Object.merge(saveobj.__proto__, savejs);
|
||||
if (savejs.objects) saveobj.__proto__.objects = savejs.objects;
|
||||
// var path = prototypes.ur_stem(saveobj.ur.toString()) + ".json";
|
||||
path = "CHANGETHIS";
|
||||
var tur = saveobj.get_ur();
|
||||
if (!tur) {
|
||||
console.warn(`Can't save object because it has no ur.`);
|
||||
return;
|
||||
}
|
||||
if (!tur.data) {
|
||||
io.slurpwrite(tur.text.set_ext(".json"), json.encode(savejs,null,1));
|
||||
tur.data = tur.text.set_ext(".json");
|
||||
}
|
||||
else {
|
||||
var oldjs = json.decode(io.slurp(tur.data));
|
||||
Object.merge(oldjs, savejs);
|
||||
io.slurpwrite(tur.data, json.encode(oldjs,null,1));
|
||||
}
|
||||
|
||||
io.slurpwrite(path, JSON.stringify(saveobj.__proto__,null,1));
|
||||
console.warn(`Wrote to file ${path}`);
|
||||
Object.merge(tur.proto, savejs);
|
||||
saveobj.check_dirty();
|
||||
|
||||
Object.values(saveobj.objects).forEach(function(x) { x.check_dirty(); });
|
||||
// Object.values(saveobj.objects).forEach(function(x) { x.check_dirty(); });
|
||||
|
||||
return;
|
||||
|
||||
Game.all_objects(function(x) {
|
||||
if (typeof x !== 'object') return;
|
||||
|
@ -847,7 +907,12 @@ editor.inputs['C-s'].doc = "Save selected.";
|
|||
|
||||
editor.inputs['C-S'] = function() {
|
||||
if (editor.selectlist.length !== 1) return;
|
||||
saveaspanel.stem = this.selectlist[0].ur;
|
||||
if (this.selectlist[0].ur !== 'empty')
|
||||
saveaspanel.stem = this.selectlist[0].ur + ".";
|
||||
else
|
||||
saveaspanel.stem = "";
|
||||
|
||||
saveaspanel.obj = this.selectlist[0];
|
||||
editor.openpanel(saveaspanel);
|
||||
};
|
||||
editor.inputs['C-S'].doc = "Save selected as.";
|
||||
|
@ -864,11 +929,7 @@ editor.inputs.t.doc = "Lock selected objects to make them non selectable.";
|
|||
editor.inputs['M-t'] = function() { editor.edit_level.objects.forEach(function(x) { x._ed.selectable = true; }); };
|
||||
editor.inputs['M-t'].doc = "Unlock all objects in current level.";
|
||||
|
||||
editor.inputs['C-n'] = function() {
|
||||
console.warn(`Spawning a new object on ${editor.edit_level.toString()}`);
|
||||
editor.edit_level.spawn();
|
||||
};
|
||||
editor.inputs['C-n'].doc = "Create an empty object.";
|
||||
editor.inputs['C-n'] = editor.new_object;
|
||||
|
||||
editor.inputs['C-o'] = function() {
|
||||
editor.openpanel(openlevelpanel);
|
||||
|
@ -1823,13 +1884,17 @@ var openlevelpanel = Object.copy(inputpanel, {
|
|||
},
|
||||
});
|
||||
|
||||
/* Should set stem to the ur path folloed by a '.' before opening */
|
||||
var saveaspanel = Object.copy(inputpanel, {
|
||||
get title() { return `save level as: ${this.stem}.`; },
|
||||
get title() {
|
||||
var full = this.stem ? this.stem : "";
|
||||
return `save level as: ${full}.`;
|
||||
},
|
||||
|
||||
action() {
|
||||
var savename = "";
|
||||
if (this.stem) savename += this.stem + ".";
|
||||
editor.saveas_check(savename + this.value, this.obj);
|
||||
var saveur = this.value;
|
||||
if (this.stem) saveur = this.stem + saveur;
|
||||
editor.saveas_check(saveur, this.obj);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -236,7 +236,7 @@ Register.add_cb(10, "draw");
|
|||
|
||||
register(9, console.stack, this);
|
||||
|
||||
Register.gamepad_playermap[0] = player[0];
|
||||
Register.gamepad_playermap[0] = Player.players[0];
|
||||
|
||||
var Event = {
|
||||
events: {},
|
||||
|
@ -418,5 +418,3 @@ Game.view_camera = function(cam)
|
|||
Window.title(`Prosperon v${prosperon.version}`);
|
||||
Window.width = 1280;
|
||||
Window.height = 720;
|
||||
|
||||
|
||||
|
|
|
@ -150,10 +150,9 @@ var gameobject = {
|
|||
return undefined;
|
||||
},
|
||||
check_dirty() {
|
||||
// TODO: IMPLEMENT
|
||||
return;
|
||||
this._ed.urdiff = this.json_obj();
|
||||
this._ed.dirty = !Object.empty(this._ed.urdiff);
|
||||
return; // TODO: IMPLEMENT
|
||||
var lur = ur[this.master.ur];
|
||||
if (!lur) return;
|
||||
var lur = lur.objects[this.toString()];
|
||||
|
@ -306,6 +305,11 @@ var gameobject = {
|
|||
worldangle() { return Math.rad2turn(q_body(2,this.body)); },
|
||||
sworldangle(x) { set_body(0,this.body,Math.turn2rad(x)); },
|
||||
|
||||
get_ur() {
|
||||
// if (this.ur === 'empty') return undefined;
|
||||
return Object.access(ur,this.ur);
|
||||
},
|
||||
|
||||
/* spawn an entity
|
||||
text can be:
|
||||
the file path of a script
|
||||
|
@ -319,7 +323,7 @@ var gameobject = {
|
|||
text = text.name;
|
||||
|
||||
if (typeof text === 'undefined')
|
||||
ent.ur = "new";
|
||||
ent.ur = "empty";
|
||||
else if (typeof text !== 'string') {
|
||||
console.error(`Must pass in an ur type or a string to make an entity.`);
|
||||
return;
|
||||
|
@ -353,10 +357,14 @@ var gameobject = {
|
|||
cmd(113, ent.body, ent); // set the internal obj reference to this obj
|
||||
|
||||
Object.hide(ent, 'ur', 'body', 'components', 'objects', '_ed', 'timers', 'master');
|
||||
if (ent.ur === 'empty') {
|
||||
if (!ur.empty.proto) ur.empty.proto = json.decode(json.encode(ent));
|
||||
return ent;
|
||||
}
|
||||
|
||||
if (ent.ur === 'script')
|
||||
eval_env(io.slurp(text), ent, ent.ur);
|
||||
else if (ent.ur !== 'new')
|
||||
else
|
||||
apply_ur(ent.ur, ent);
|
||||
|
||||
for (var [prop,p] of Object.entries(ent)) {
|
||||
|
@ -369,16 +377,18 @@ var gameobject = {
|
|||
ent.components[prop] = ent[prop];
|
||||
};
|
||||
|
||||
|
||||
check_registers(ent);
|
||||
|
||||
if (typeof ent.load === 'function') ent.load();
|
||||
if (Game.playing())
|
||||
if (typeof ent.start === 'function') ent.start();
|
||||
|
||||
var mur = Object.access(ur,ent.ur);
|
||||
var mur = ent.get_ur();
|
||||
if (mur && !mur.proto)
|
||||
mur.proto = json.decode(json.encode(ent));
|
||||
|
||||
ent.sync();
|
||||
|
||||
if (!Object.empty(ent.objects)) {
|
||||
var o = ent.objects;
|
||||
delete ent.objects;
|
||||
|
@ -412,7 +422,7 @@ var gameobject = {
|
|||
var str = name.replaceAll('.', '_');
|
||||
var n = 1;
|
||||
var t = str;
|
||||
while (t in list) {
|
||||
while (list.indexOf(t) !== -1) {
|
||||
t = str + n;
|
||||
n++;
|
||||
}
|
||||
|
@ -531,7 +541,7 @@ var gameobject = {
|
|||
|
||||
/* The unique components of this object. Its diff. */
|
||||
json_obj() {
|
||||
var u = Object.access(ur,this.ur);
|
||||
var u = this.get_ur();
|
||||
if (!u) return {};
|
||||
var proto = u.proto;
|
||||
var thiso = json.decode(json.encode(this)); // TODO: SLOW. Used to ignore properties in toJSON of components.
|
||||
|
@ -566,7 +576,7 @@ var gameobject = {
|
|||
},
|
||||
|
||||
proto() {
|
||||
var u = Object.access(ur,this.ur);
|
||||
var u = this.get_ur();
|
||||
if (!u) return {};
|
||||
return u.proto;
|
||||
},
|
||||
|
@ -733,7 +743,10 @@ gameobject.doc = {
|
|||
rotary_limit: 'Limit the angle relative to the to body between min and max.',
|
||||
ratchet: 'Like a socket wrench, relative to to. ratch is the distance between clicks.',
|
||||
gear: 'Keeps the angular velocity ratio of this body and to constant. Ratio is the gear ratio.',
|
||||
motor: 'Keeps the relative angular velocity of this body to to at a constant rate. The most simple idea is for one of the bodies to be static, to the other is kept at rate.'
|
||||
motor: 'Keeps the relative angular velocity of this body to to at a constant rate. The most simple idea is for one of the bodies to be static, to the other is kept at rate.',
|
||||
layer: 'Bitmask for collision layers.',
|
||||
draw_layer: 'Layer for drawing. Higher numbers draw above lower ones.',
|
||||
warp_layer: 'Bitmask for selecting what warps should affect this entity.',
|
||||
};
|
||||
|
||||
var resavi = function(ur, path)
|
||||
|
@ -848,6 +861,10 @@ for (var file of io.glob("**.json")) {
|
|||
topur.data = file;
|
||||
}
|
||||
|
||||
ur.empty = {
|
||||
name: "empty"
|
||||
};
|
||||
|
||||
return {
|
||||
gameobject,
|
||||
ur
|
||||
|
|
|
@ -82,7 +82,6 @@ void go_shape_apply(cpBody *body, cpShape *shape, gameobject *go) {
|
|||
cpShapeFilter filter;
|
||||
filter.group = (cpCollisionType)go;
|
||||
filter.categories = 1<<go->layer | editor_cat;
|
||||
// filter.mask = CP_ALL_CATEGORIES;
|
||||
filter.mask = category_masks[go->layer] | editor_cat;
|
||||
// filter.mask = CP_ALL_CATEGORIES;
|
||||
cpShapeSetFilter(shape, filter);
|
||||
|
|
|
@ -2153,12 +2153,12 @@ JSValue duk_cmd_points(JSContext *js, JSValueConst this, int argc, JSValueConst
|
|||
|
||||
const char *STRTEST = "TEST STRING";
|
||||
|
||||
JSValue duk_profile_js2num(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||
JSValue duk_performance_js2num(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JSValue duk_profile(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||
JSValue duk_performance(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||
{
|
||||
int cmd = js2int(argv[0]);
|
||||
switch(cmd) {
|
||||
|
@ -2249,7 +2249,7 @@ void ffi_load() {
|
|||
|
||||
DUK_FUNC(inflate_cpv, 3)
|
||||
|
||||
DUK_FUNC(profile, 2)
|
||||
DUK_FUNC(performance, 2)
|
||||
|
||||
JS_FreeValue(js,globalThis);
|
||||
|
||||
|
|
Loading…
Reference in a new issue