Editor mouse works; remove level.js
This commit is contained in:
parent
6b73624c12
commit
b9316dbbe6
|
@ -34,7 +34,7 @@ struct gameobject *id2go(int id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int body2id(cpBody *body) {
|
int body2id(cpBody *body) {
|
||||||
return *(int*)cpBodyGetUserData(body);
|
return (int)cpBodyGetUserData(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpBody *id2body(int id) {
|
cpBody *id2body(int id) {
|
||||||
|
|
|
@ -98,10 +98,11 @@ char *mb2str(int btn)
|
||||||
|
|
||||||
void input_mouse(int btn, int state)
|
void input_mouse(int btn, int state)
|
||||||
{
|
{
|
||||||
JSValue argv[2];
|
JSValue argv[3];
|
||||||
argv[0] = input2js(mb2str(btn));
|
argv[0] = JS_NewString(js, "emacs");
|
||||||
argv[1] = jsinputstate[btn];
|
argv[1] = input2js(mb2str(btn));
|
||||||
script_callee(pawn_callee, 2, argv);
|
argv[2] = jsinputstate[state];
|
||||||
|
script_callee(pawn_callee, 3, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void input_mouse_move(float x, float y, float dx, float dy)
|
void input_mouse_move(float x, float y, float dx, float dy)
|
||||||
|
|
|
@ -413,9 +413,6 @@ void openglRender(struct window *window) {
|
||||||
|
|
||||||
sg_end_pass();
|
sg_end_pass();
|
||||||
|
|
||||||
sg_begin_default_pass(&pass_action, gif_w, gif_h);
|
|
||||||
sg_apply_pipeline(
|
|
||||||
|
|
||||||
sg_begin_default_pass(&pass_action, window->width, window->height);
|
sg_begin_default_pass(&pass_action, window->width, window->height);
|
||||||
sg_apply_pipeline(crt_post.pipe);
|
sg_apply_pipeline(crt_post.pipe);
|
||||||
sg_apply_bindings(&crt_post.bind);
|
sg_apply_bindings(&crt_post.bind);
|
||||||
|
|
|
@ -152,10 +152,14 @@ int frame_fps() {
|
||||||
return 1.0/sapp_frame_duration();
|
return 1.0/sapp_frame_duration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double low_fps = 1/24.0; /* Chosen because of apple's 24 hz mode */
|
||||||
|
static double low_fps_c = 0.0;
|
||||||
|
|
||||||
void c_frame()
|
void c_frame()
|
||||||
{
|
{
|
||||||
double elapsed = sapp_frame_duration();
|
double elapsed = sapp_frame_duration();
|
||||||
appTime += elapsed;
|
appTime += elapsed;
|
||||||
|
low_fps_c += elapsed;
|
||||||
|
|
||||||
input_poll(0);
|
input_poll(0);
|
||||||
|
|
||||||
|
@ -181,9 +185,10 @@ void c_frame()
|
||||||
sim_pause();
|
sim_pause();
|
||||||
render_dirty = 1;
|
render_dirty = 1;
|
||||||
}
|
}
|
||||||
|
low_fps_c = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sim_play == SIM_PLAY || render_dirty) {
|
if (sim_play == SIM_PLAY || render_dirty || low_fps_c >= low_fps) {
|
||||||
prof_start(&prof_draw);
|
prof_start(&prof_draw);
|
||||||
window_render(&mainwin);
|
window_render(&mainwin);
|
||||||
prof(&prof_draw);
|
prof(&prof_draw);
|
||||||
|
|
|
@ -27,15 +27,15 @@ var configs = {
|
||||||
|
|
||||||
var editor = {
|
var editor = {
|
||||||
dbgdraw: false,
|
dbgdraw: false,
|
||||||
selected: null,
|
selected: undefined,
|
||||||
selectlist: [],
|
selectlist: [],
|
||||||
moveoffset: [0,0],
|
moveoffset: [0,0],
|
||||||
startrot: 0,
|
startrot: 0,
|
||||||
rotoffset: 0,
|
rotoffset: 0,
|
||||||
camera: editor_camera,
|
camera: editor_camera,
|
||||||
edit_level: {}, /* The current level that is being edited */
|
edit_level: {}, /* The current level that is being edited */
|
||||||
working_layer: -1,
|
working_layer: 0,
|
||||||
cursor: null,
|
cursor: undefined,
|
||||||
edit_mode: "basic",
|
edit_mode: "basic",
|
||||||
|
|
||||||
try_select() { /* nullify true if it should set selected to null if it doesn't find an object */
|
try_select() { /* nullify true if it should set selected to null if it doesn't find an object */
|
||||||
|
@ -45,10 +45,12 @@ var editor = {
|
||||||
|
|
||||||
/* Tries to select id */
|
/* Tries to select id */
|
||||||
do_select(go) {
|
do_select(go) {
|
||||||
var obj = go >= 0 ? Game.object(go) : null;
|
var obj = go >= 0 ? Game.object(go) : undefined;
|
||||||
if (!obj || !obj.selectable) return null;
|
if (obj)
|
||||||
|
Log.warn(obj);
|
||||||
|
if (!obj || !obj.selectable) return undefined;
|
||||||
|
|
||||||
if (this.working_layer > -1 && obj.draw_layer !== this.working_layer) return null;
|
if (this.working_layer > -1 && obj.draw_layer !== this.working_layer) return undefined;
|
||||||
|
|
||||||
if (obj.level !== this.edit_level) {
|
if (obj.level !== this.edit_level) {
|
||||||
var testlevel = obj.level;
|
var testlevel = obj.level;
|
||||||
|
@ -62,7 +64,7 @@ var editor = {
|
||||||
return obj;
|
return obj;
|
||||||
},
|
},
|
||||||
|
|
||||||
curpanel: null,
|
curpanel: undefined,
|
||||||
|
|
||||||
check_level_nested() {
|
check_level_nested() {
|
||||||
if (this.edit_level.level) {
|
if (this.edit_level.level) {
|
||||||
|
@ -99,7 +101,7 @@ var editor = {
|
||||||
|
|
||||||
protos[this.selectlist[0].__proto__.name] = pobj;
|
protos[this.selectlist[0].__proto__.name] = pobj;
|
||||||
Log.warn(JSON.stringify(protos));
|
Log.warn(JSON.stringify(protos));
|
||||||
slurpwrite(JSON.stringify(protos, null, 2), "proto.json");
|
slurpwrite(JSON.stringify(protos, undefined, 2), "proto.json");
|
||||||
|
|
||||||
/* Save object changes to parent */
|
/* Save object changes to parent */
|
||||||
dainty_assign(this.selectlist[0].__proto__, tobj);
|
dainty_assign(this.selectlist[0].__proto__, tobj);
|
||||||
|
@ -202,71 +204,6 @@ var editor = {
|
||||||
return {c: c, wh: wh};
|
return {c: c, wh: wh};
|
||||||
},
|
},
|
||||||
|
|
||||||
input_lmouse_released() {
|
|
||||||
Mouse.normal();
|
|
||||||
if (!this.sel_start) return;
|
|
||||||
|
|
||||||
if (this.sel_comp) {
|
|
||||||
this.sel_start = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var selects = [];
|
|
||||||
|
|
||||||
/* TODO: selects somehow gets undefined objects in here */
|
|
||||||
if (screen2world(Mouse.pos).equal(this.sel_start)) {
|
|
||||||
var sel = this.try_select();
|
|
||||||
if (sel) selects.push(sel);
|
|
||||||
} else {
|
|
||||||
var box = this.points2cwh(this.sel_start, screen2world(Mouse.pos));
|
|
||||||
|
|
||||||
box.pos = box.c;
|
|
||||||
|
|
||||||
var hits = physics.box_query(box);
|
|
||||||
|
|
||||||
hits.forEach(function(x, i) {
|
|
||||||
var obj = this.do_select(x);
|
|
||||||
if (obj)
|
|
||||||
selects.push(obj);
|
|
||||||
},this);
|
|
||||||
|
|
||||||
var levels = this.edit_level.objects.filter(function(x) { return x.file; });
|
|
||||||
var lvlpos = [];
|
|
||||||
levels.forEach(function(x) { lvlpos.push(x.pos); });
|
|
||||||
var lvlhits = physics.box_point_query(box, lvlpos);
|
|
||||||
|
|
||||||
lvlhits.forEach(function(x) { selects.push(levels[x]); });
|
|
||||||
}
|
|
||||||
|
|
||||||
this.sel_start = null;
|
|
||||||
selects = selects.flat();
|
|
||||||
selects = selects.unique();
|
|
||||||
|
|
||||||
if (selects.empty) return;
|
|
||||||
|
|
||||||
if (Keys.shift()) {
|
|
||||||
selects.forEach(function(x) {
|
|
||||||
this.selectlist.push_unique(x);
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Keys.ctrl()) {
|
|
||||||
selects.forEach(function(x) {
|
|
||||||
this.selectlist.remove(x);
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
editor.selectlist = [];
|
|
||||||
selects.forEach(function(x) {
|
|
||||||
if (x !== null)
|
|
||||||
this.selectlist.push(x);
|
|
||||||
}, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
mover(amt, snap) {
|
mover(amt, snap) {
|
||||||
return function(go) { go.pos = go.pos.add(amt)};
|
return function(go) { go.pos = go.pos.add(amt)};
|
||||||
},
|
},
|
||||||
|
@ -350,13 +287,13 @@ var editor = {
|
||||||
|
|
||||||
unselect() {
|
unselect() {
|
||||||
editor.selectlist = [];
|
editor.selectlist = [];
|
||||||
this.grabselect = null;
|
this.grabselect = undefined;
|
||||||
this.sel_comp = null;
|
this.sel_comp = undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
sel_comp: null,
|
sel_comp: undefined,
|
||||||
comp_info: false,
|
comp_info: false,
|
||||||
brush_obj: null,
|
brush_obj: undefined,
|
||||||
|
|
||||||
camera_recalls: {},
|
camera_recalls: {},
|
||||||
camera_recall_stack: [],
|
camera_recall_stack: [],
|
||||||
|
@ -407,119 +344,17 @@ var editor = {
|
||||||
this.camera.zoom = zoom*1.3;
|
this.camera.zoom = zoom*1.3;
|
||||||
},
|
},
|
||||||
|
|
||||||
input_rmouse_down() {
|
|
||||||
if (Keys.ctrl() && Keys.alt())
|
|
||||||
this.camera.zoom = this.z_start * (1 + (Mouse.pos[1] - this.mousejoy[1])/500);
|
|
||||||
},
|
|
||||||
|
|
||||||
z_start: 1,
|
z_start: 1,
|
||||||
|
|
||||||
input_rmouse_released() {
|
grabselect: undefined,
|
||||||
Mouse.normal();
|
|
||||||
},
|
|
||||||
|
|
||||||
input_rmouse_pressed() {
|
|
||||||
if (Keys.shift()) {
|
|
||||||
this.cursor = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Keys.ctrl() && Keys.alt()) {
|
|
||||||
this.mousejoy = Mouse.pos;
|
|
||||||
this.z_start = this.camera.zoom;
|
|
||||||
Mouse.disabled();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.brush_obj)
|
|
||||||
this.brush_obj = null;
|
|
||||||
|
|
||||||
if (this.sel_comp) {
|
|
||||||
this.sel_comp = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.unselect();
|
|
||||||
},
|
|
||||||
|
|
||||||
grabselect: null,
|
|
||||||
mousejoy: [0,0],
|
mousejoy: [0,0],
|
||||||
joystart: [0,0],
|
joystart: [0,0],
|
||||||
|
|
||||||
input_mmouse_pressed() {
|
|
||||||
if (Keys.ctrl() && Keys.alt()) {
|
|
||||||
this.mousejoy = Mouse.pos;
|
|
||||||
this.joystart = this.camera.pos;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Keys.shift() && Keys.ctrl()) {
|
|
||||||
this.cursor = find_com(this.selectlist);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.brush_obj) {
|
|
||||||
this.selectlist = this.dup_objects([this.brush_obj]);
|
|
||||||
this.selectlist[0].pos = screen2world(Mouse.pos);
|
|
||||||
this.grabselect = this.selectlist[0];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.sel_comp && 'pick' in this.sel_comp) {
|
|
||||||
this.grabselect = this.sel_comp.pick(screen2world(Mouse.pos));
|
|
||||||
if (!this.grabselect) return;
|
|
||||||
|
|
||||||
this.moveoffset = this.sel_comp.gameobject.this2world(this.grabselect).sub(screen2world(Mouse.pos));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var grabobj = this.try_select();
|
|
||||||
if (Array.isArray(grabobj)) {
|
|
||||||
this.selectlist = grabobj;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.grabselect = null;
|
|
||||||
if (!grabobj) return;
|
|
||||||
|
|
||||||
if (Keys.ctrl()) {
|
|
||||||
grabobj = this.dup_objects([grabobj])[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.grabselect = grabobj;
|
|
||||||
|
|
||||||
if (!this.selectlist.includes(grabobj)) {
|
|
||||||
editor.selectlist = [];
|
|
||||||
editor.selectlist.push(grabobj);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.moveoffset = this.grabselect.pos.sub(screen2world(Mouse.pos));
|
|
||||||
},
|
|
||||||
|
|
||||||
input_mmouse_released() {
|
input_mmouse_released() {
|
||||||
Mouse.normal();
|
Mouse.normal();
|
||||||
this.grabselect = null;
|
this.grabselect = undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
input_mmouse_down() {
|
|
||||||
if (Keys.shift() && !Keys.ctrl()) {
|
|
||||||
this.cursor = Mouse.worldpos;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Keys.alt() && Keys.ctrl()) {
|
|
||||||
this.camera.pos = this.joystart.add(Mouse.pos.sub(this.mousejoy).mapc(mult, [-1,1]).scale(editor_camera.zoom));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.grabselect) return;
|
|
||||||
|
|
||||||
if ('pos' in this.grabselect)
|
|
||||||
this.grabselect.pos = this.moveoffset.add(screen2world(Mouse.pos));
|
|
||||||
else
|
|
||||||
this.grabselect.set(this.selectlist[0].world2this(this.moveoffset.add(screen2world(Mouse.pos))));
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
stash: "",
|
stash: "",
|
||||||
|
|
||||||
start_play_ed() {
|
start_play_ed() {
|
||||||
|
@ -569,7 +404,7 @@ var editor = {
|
||||||
|
|
||||||
var stolen = this;
|
var stolen = this;
|
||||||
if (dontsteal)
|
if (dontsteal)
|
||||||
stolen = null;
|
stolen = undefined;
|
||||||
|
|
||||||
this.curpanel.open(stolen);
|
this.curpanel.open(stolen);
|
||||||
},
|
},
|
||||||
|
@ -584,59 +419,11 @@ var editor = {
|
||||||
this.curpanels = this.curpanels.filter(function(x) { return x.on; });
|
this.curpanels = this.curpanels.filter(function(x) { return x.on; });
|
||||||
},
|
},
|
||||||
|
|
||||||
input_s_down() {
|
|
||||||
if (!this.scaleoffset) return;
|
|
||||||
var offf = this.cursor ? this.cursor : this.selected_com;
|
|
||||||
var dist = Vector.length(screen2world(Mouse.pos).sub(offf));
|
|
||||||
var scalediff = dist/this.scaleoffset;
|
|
||||||
|
|
||||||
if (this.sel_comp) {
|
|
||||||
if (!('scale' in this.sel_comp)) return;
|
|
||||||
this.sel_comp.scale = this.startscales[0] * scalediff;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.selectlist.forEach(function(x, i) {
|
|
||||||
x.scale = this.startscales[i] * scalediff;
|
|
||||||
if (this.cursor)
|
|
||||||
x.pos = this.cursor.add(this.startoffs[i].scale(scalediff));
|
|
||||||
}, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
input_s_released() {
|
|
||||||
this.scaleoffset = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
startrots: [],
|
startrots: [],
|
||||||
startpos: [],
|
startpos: [],
|
||||||
startoffs: [],
|
startoffs: [],
|
||||||
|
|
||||||
input_r_down() {
|
|
||||||
if (this.sel_comp && 'angle' in this.sel_comp) {
|
|
||||||
if (!('angle' in this.sel_comp)) return;
|
|
||||||
var relpos = screen2world(Mouse.pos).sub(this.sel_comp.gameobject.pos);
|
|
||||||
var anglediff = Math.rad2deg(Math.atan2(relpos.y, relpos.x)) - this.startoffset;
|
|
||||||
this.sel_comp.angle = this.startrot + anglediff;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.startrots.empty) return;
|
|
||||||
|
|
||||||
var offf = this.cursor ? this.cursor : this.selected_com;
|
|
||||||
var relpos = screen2world(Mouse.pos).sub(offf);
|
|
||||||
var anglediff = Math.rad2deg(Math.atan2(relpos[1], relpos[0]) - this.startoffset);
|
|
||||||
|
|
||||||
if (this.cursor) {
|
|
||||||
this.selectlist.forEach(function(x, i) {
|
|
||||||
x.angle = this.startrots[i] + anglediff;
|
|
||||||
x.pos = offf.add(this.startoffs[i].rotate(Math.deg2rad(anglediff)));
|
|
||||||
}, this);
|
|
||||||
} else {
|
|
||||||
this.selectlist.forEach(function(x,i) {
|
|
||||||
x.angle = this.startrots[i]+anglediff;
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
snapshots: [],
|
snapshots: [],
|
||||||
curlvl: {}, /* What the level currently looks like on file */
|
curlvl: {}, /* What the level currently looks like on file */
|
||||||
|
|
||||||
|
@ -777,7 +564,7 @@ var editor = {
|
||||||
this.edit_level = Level.create();
|
this.edit_level = Level.create();
|
||||||
},
|
},
|
||||||
|
|
||||||
_sel_comp: null,
|
_sel_comp: undefined,
|
||||||
get sel_comp() { return this._sel_comp; },
|
get sel_comp() { return this._sel_comp; },
|
||||||
set sel_comp(x) {
|
set sel_comp(x) {
|
||||||
if (this._sel_comp)
|
if (this._sel_comp)
|
||||||
|
@ -830,7 +617,7 @@ var editor = {
|
||||||
var ypos = 200;
|
var ypos = 200;
|
||||||
var lvlcolor = Color.white;
|
var lvlcolor = Color.white;
|
||||||
while (clvl) {
|
while (clvl) {
|
||||||
var lvlstr = clvl.file ? clvl.file : "NEW LEVEL";
|
var lvlstr = clvl.file ? clvl.file : "NEW ENTITY";
|
||||||
if (clvl.unique)
|
if (clvl.unique)
|
||||||
lvlstr += "#";
|
lvlstr += "#";
|
||||||
else if (clvl.dirty)
|
else if (clvl.dirty)
|
||||||
|
@ -976,10 +763,13 @@ var editor = {
|
||||||
lvl_history: [],
|
lvl_history: [],
|
||||||
|
|
||||||
load(file) {
|
load(file) {
|
||||||
if (this.edit_level) this.lvl_history.push(this.edit_level.file);
|
if (this.edit_level) this.lvl_history.push(this.edit_level.ur);
|
||||||
this.edit_level.clear();
|
this.edit_level.kill();
|
||||||
this.edit_level = Level.loadfile(file);
|
// this.edit_level = Level.loadfile(file);
|
||||||
this.curlvl = this.edit_level.save();
|
// this.curlvl = this.edit_level.save();
|
||||||
|
this.edit_level = Primum.spawn(prototypes.get_ur(file));
|
||||||
|
Log.warn(`Loaded file ${file}`);
|
||||||
|
Log.warn(this.edit_level.pos);
|
||||||
this.unselect();
|
this.unselect();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1178,6 +968,32 @@ editor.inputs.r = function() {
|
||||||
};
|
};
|
||||||
editor.inputs.r.doc = "Rotate selected using the mouse while held down.";
|
editor.inputs.r.doc = "Rotate selected using the mouse while held down.";
|
||||||
|
|
||||||
|
editor.inputs.r.down = function() {
|
||||||
|
if (this.sel_comp && 'angle' in this.sel_comp) {
|
||||||
|
if (!('angle' in this.sel_comp)) return;
|
||||||
|
var relpos = screen2world(Mouse.pos).sub(this.sel_comp.gameobject.pos);
|
||||||
|
var anglediff = Math.rad2deg(Math.atan2(relpos.y, relpos.x)) - this.startoffset;
|
||||||
|
this.sel_comp.angle = this.startrot + anglediff;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.startrots.empty) return;
|
||||||
|
|
||||||
|
var offf = this.cursor ? this.cursor : this.selected_com;
|
||||||
|
var relpos = screen2world(Mouse.pos).sub(offf);
|
||||||
|
var anglediff = Math.rad2deg(Math.atan2(relpos[1], relpos[0]) - this.startoffset);
|
||||||
|
|
||||||
|
if (this.cursor) {
|
||||||
|
this.selectlist.forEach(function(x, i) {
|
||||||
|
x.angle = this.startrots[i] + anglediff;
|
||||||
|
x.pos = offf.add(this.startoffs[i].rotate(Math.deg2rad(anglediff)));
|
||||||
|
}, this);
|
||||||
|
} else {
|
||||||
|
this.selectlist.forEach(function(x,i) {
|
||||||
|
x.angle = this.startrots[i]+anglediff;
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
editor.inputs['C-p'] = function() {
|
editor.inputs['C-p'] = function() {
|
||||||
if (!Game.playing()) {
|
if (!Game.playing()) {
|
||||||
editor.start_play_ed();
|
editor.start_play_ed();
|
||||||
|
@ -1391,6 +1207,171 @@ editor.inputs['M-j'].doc = "Remove variable names from selected objects.";
|
||||||
editor.inputs.lm = function() { editor.sel_start = screen2world(Mouse.pos); };
|
editor.inputs.lm = function() { editor.sel_start = screen2world(Mouse.pos); };
|
||||||
editor.inputs.lm.doc = "Selection box.";
|
editor.inputs.lm.doc = "Selection box.";
|
||||||
|
|
||||||
|
editor.inputs.lm.released = function() {
|
||||||
|
Mouse.normal();
|
||||||
|
|
||||||
|
if (!editor.sel_start) return;
|
||||||
|
|
||||||
|
if (editor.sel_comp) {
|
||||||
|
editor.sel_start = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var selects = [];
|
||||||
|
|
||||||
|
/* TODO: selects somehow gets undefined objects in here */
|
||||||
|
if (screen2world(Mouse.pos).equal(editor.sel_start)) {
|
||||||
|
var sel = editor.try_select();
|
||||||
|
if (sel) selects.push(sel);
|
||||||
|
} else {
|
||||||
|
var box = editor.points2cwh(editor.sel_start, screen2world(Mouse.pos));
|
||||||
|
|
||||||
|
box.pos = box.c;
|
||||||
|
|
||||||
|
var hits = physics.box_query(box);
|
||||||
|
|
||||||
|
hits.forEach(function(x, i) {
|
||||||
|
var obj = editor.do_select(x);
|
||||||
|
if (obj)
|
||||||
|
selects.push(obj);
|
||||||
|
},editor);
|
||||||
|
|
||||||
|
var levels = editor.edit_level.objects.filter(function(x) { return x.file; });
|
||||||
|
var lvlpos = [];
|
||||||
|
levels.forEach(function(x) { lvlpos.push(x.pos); });
|
||||||
|
var lvlhits = physics.box_point_query(box, lvlpos);
|
||||||
|
|
||||||
|
lvlhits.forEach(function(x) { selects.push(levels[x]); });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sel_start = undefined;
|
||||||
|
selects = selects.flat();
|
||||||
|
selects = selects.unique();
|
||||||
|
|
||||||
|
if (selects.empty) return;
|
||||||
|
|
||||||
|
if (Keys.shift()) {
|
||||||
|
selects.forEach(function(x) {
|
||||||
|
this.selectlist.push_unique(x);
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Keys.ctrl()) {
|
||||||
|
selects.forEach(function(x) {
|
||||||
|
this.selectlist.remove(x);
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.selectlist = [];
|
||||||
|
selects.forEach(function(x) {
|
||||||
|
if (x !== undefined)
|
||||||
|
this.selectlist.push(x);
|
||||||
|
}, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.inputs.rm = function() {
|
||||||
|
if (Keys.shift()) {
|
||||||
|
editor.cursor = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Keys.ctrl() && Keys.alt()) {
|
||||||
|
editor.mousejoy = Mouse.pos;
|
||||||
|
editor.z_start = editor.camera.zoom;
|
||||||
|
Mouse.disabled();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editor.brush_obj)
|
||||||
|
editor.brush_obj = undefined;
|
||||||
|
|
||||||
|
if (editor.sel_comp) {
|
||||||
|
editor.sel_comp = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.unselect();
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.inputs.mm = function() {
|
||||||
|
if (Keys.ctrl() && Keys.alt()) {
|
||||||
|
editor.mousejoy = Mouse.pos;
|
||||||
|
editor.joystart = editor.camera.pos;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Keys.shift() && Keys.ctrl()) {
|
||||||
|
editor.cursor = find_com(editor.selectlist);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editor.brush_obj) {
|
||||||
|
editor.selectlist = editor.dup_objects([editor.brush_obj]);
|
||||||
|
editor.selectlist[0].pos = screen2world(Mouse.pos);
|
||||||
|
editor.grabselect = editor.selectlist[0];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editor.sel_comp && 'pick' in editor.sel_comp) {
|
||||||
|
editor.grabselect = editor.sel_comp.pick(screen2world(Mouse.pos));
|
||||||
|
if (!editor.grabselect) return;
|
||||||
|
|
||||||
|
editor.moveoffset = editor.sel_comp.gameobject.editor2world(editor.grabselect).sub(screen2world(Mouse.pos));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var grabobj = editor.try_select();
|
||||||
|
if (Array.isArray(grabobj)) {
|
||||||
|
editor.selectlist = grabobj;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
editor.grabselect = undefined;
|
||||||
|
if (!grabobj) return;
|
||||||
|
|
||||||
|
if (Keys.ctrl()) {
|
||||||
|
grabobj = editor.dup_objects([grabobj])[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.grabselect = grabobj;
|
||||||
|
|
||||||
|
if (!editor.selectlist.includes(grabobj)) {
|
||||||
|
editor.selectlist = [];
|
||||||
|
editor.selectlist.push(grabobj);
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.moveoffset = editor.grabselect.pos.sub(screen2world(Mouse.pos));
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.inputs.rm.down = function() {
|
||||||
|
if (Keys.ctrl() && Keys.alt())
|
||||||
|
this.camera.zoom = this.z_start * (1 + (Mouse.pos[1] - this.mousejoy[1])/500);
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.inputs.mm.down = function() {
|
||||||
|
if (Keys.shift() && !Keys.ctrl()) {
|
||||||
|
this.cursor = Mouse.worldpos;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Keys.alt() && Keys.ctrl()) {
|
||||||
|
this.camera.pos = this.joystart.add(Mouse.pos.sub(this.mousejoy).mapc(mult, [-1,1]).scale(editor_camera.zoom));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.grabselect) return;
|
||||||
|
|
||||||
|
if ('pos' in this.grabselect)
|
||||||
|
this.grabselect.pos = this.moveoffset.add(screen2world(Mouse.pos));
|
||||||
|
else
|
||||||
|
this.grabselect.set(this.selectlist[0].world2this(this.moveoffset.add(screen2world(Mouse.pos))));
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.inputs.mm.released = function () { Mouse.normal(); };
|
||||||
|
|
||||||
editor.inputs['C-M-S-lm'] = function() { editor.selectlist[0].set_center(screen2world(Mouse.pos)); };
|
editor.inputs['C-M-S-lm'] = function() { editor.selectlist[0].set_center(screen2world(Mouse.pos)); };
|
||||||
editor.inputs['C-M-S-lm'].doc = "Set world center to mouse position.";
|
editor.inputs['C-M-S-lm'].doc = "Set world center to mouse position.";
|
||||||
|
|
||||||
|
@ -1418,9 +1399,7 @@ editor.inputs['C-S-g'] = function() { editor.openpanel(groupsaveaspanel); };
|
||||||
editor.inputs['C-S-g'].doc = "Save selected objects as a new level.";
|
editor.inputs['C-S-g'].doc = "Save selected objects as a new level.";
|
||||||
|
|
||||||
editor.inputs.g = function() {
|
editor.inputs.g = function() {
|
||||||
this.selectlist.forEach(function(x,i) {
|
editor.selectlist.forEach(function(x,i) { editor.moveoffsets[i] = x.pos.sub(screen2world(Mouse.pos)); } );
|
||||||
this.moveoffsets[i] = x.pos.sub(screen2world(Mouse.pos));
|
|
||||||
}, this);
|
|
||||||
};
|
};
|
||||||
editor.inputs.g.doc = "Move selected objects.";
|
editor.inputs.g.doc = "Move selected objects.";
|
||||||
editor.inputs.g.released = function() { editor.moveoffsets = []; };
|
editor.inputs.g.released = function() { editor.moveoffsets = []; };
|
||||||
|
@ -1436,7 +1415,7 @@ editor.inputs.tab = function() {
|
||||||
else {
|
else {
|
||||||
var idx = sel.findIndex(this.sel_comp) + 1;
|
var idx = sel.findIndex(this.sel_comp) + 1;
|
||||||
if (idx >= Object.keys(sel).length)
|
if (idx >= Object.keys(sel).length)
|
||||||
this.sel_comp = null;
|
this.sel_comp = undefined;
|
||||||
else
|
else
|
||||||
this.sel_comp = sel.nth(idx);
|
this.sel_comp = sel.nth(idx);
|
||||||
}
|
}
|
||||||
|
@ -1444,6 +1423,7 @@ editor.inputs.tab = function() {
|
||||||
editor.inputs.tab.doc = "Cycle through selected object's components.";
|
editor.inputs.tab.doc = "Cycle through selected object's components.";
|
||||||
|
|
||||||
editor.inputs['C-g'] = function() {
|
editor.inputs['C-g'] = function() {
|
||||||
|
if (!this.selectlist) return;
|
||||||
this.selectlist = this.dup_objects(this.selectlist);
|
this.selectlist = this.dup_objects(this.selectlist);
|
||||||
editor.inputs.g();
|
editor.inputs.g();
|
||||||
};
|
};
|
||||||
|
@ -1497,7 +1477,7 @@ brushmode.inputs.lm.doc = "Paste selected brush.";
|
||||||
|
|
||||||
brushmode.inputs.b = function() {
|
brushmode.inputs.b = function() {
|
||||||
if (editor.brush_obj) {
|
if (editor.brush_obj) {
|
||||||
editor.brush_obj = null;
|
editor.brush_obj = undefined;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1532,6 +1512,27 @@ editor.inputs.s = function() {
|
||||||
};
|
};
|
||||||
editor.inputs.s.doc = "Scale selected.";
|
editor.inputs.s.doc = "Scale selected.";
|
||||||
|
|
||||||
|
editor.inputs.s.down = function() {
|
||||||
|
if (!this.scaleoffset) return;
|
||||||
|
var offf = this.cursor ? this.cursor : this.selected_com;
|
||||||
|
var dist = Vector.length(screen2world(Mouse.pos).sub(offf));
|
||||||
|
var scalediff = dist/this.scaleoffset;
|
||||||
|
|
||||||
|
if (this.sel_comp) {
|
||||||
|
if (!('scale' in this.sel_comp)) return;
|
||||||
|
this.sel_comp.scale = this.startscales[0] * scalediff;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectlist.forEach(function(x, i) {
|
||||||
|
x.scale = this.startscales[i] * scalediff;
|
||||||
|
if (this.cursor)
|
||||||
|
x.pos = this.cursor.add(this.startoffs[i].scale(scalediff));
|
||||||
|
}, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.inputs.s.released = function() { this.scaleoffset = undefined; };
|
||||||
|
|
||||||
var inputpanel = {
|
var inputpanel = {
|
||||||
title: "untitled",
|
title: "untitled",
|
||||||
value: "",
|
value: "",
|
||||||
|
@ -1579,7 +1580,7 @@ var inputpanel = {
|
||||||
Player.players[0].uncontrol(this);
|
Player.players[0].uncontrol(this);
|
||||||
if (this.stolen) {
|
if (this.stolen) {
|
||||||
Player.players[0].control(this.stolen);
|
Player.players[0].control(this.stolen);
|
||||||
this.stolen = null;
|
this.stolen = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.on = false;
|
this.on = false;
|
||||||
|
@ -2003,7 +2004,7 @@ texteditor.inputs['M-n'].rep = true;
|
||||||
|
|
||||||
var objectexplorer = copy(inputpanel, {
|
var objectexplorer = copy(inputpanel, {
|
||||||
title: "object explorer",
|
title: "object explorer",
|
||||||
obj: null,
|
obj: undefined,
|
||||||
previous: [],
|
previous: [],
|
||||||
start() {
|
start() {
|
||||||
this.previous = [];
|
this.previous = [];
|
||||||
|
@ -2322,7 +2323,7 @@ function tab_complete(val, list) {
|
||||||
return check[0];
|
return check[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
var ret = null;
|
var ret = undefined;
|
||||||
var i = val.length;
|
var i = val.length;
|
||||||
while (!ret && !check.empty) {
|
while (!ret && !check.empty) {
|
||||||
|
|
||||||
|
|
|
@ -190,51 +190,6 @@ var Render = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
var Mouse = {
|
|
||||||
get pos() {
|
|
||||||
return cmd(45);
|
|
||||||
},
|
|
||||||
|
|
||||||
get screenpos() {
|
|
||||||
var p = this.pos;
|
|
||||||
p.y = Window.dimensions.y - p.y;
|
|
||||||
return p;
|
|
||||||
},
|
|
||||||
|
|
||||||
get worldpos() {
|
|
||||||
return screen2world(cmd(45));
|
|
||||||
},
|
|
||||||
|
|
||||||
disabled() {
|
|
||||||
cmd(46, 212995);
|
|
||||||
},
|
|
||||||
|
|
||||||
hidden() {
|
|
||||||
cmd(46, 212994);
|
|
||||||
},
|
|
||||||
|
|
||||||
normal() {
|
|
||||||
cmd(46, 212993);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var Keys = {
|
|
||||||
shift() {
|
|
||||||
return cmd(50, 340);// || cmd(50, 344);
|
|
||||||
},
|
|
||||||
|
|
||||||
ctrl() {
|
|
||||||
return cmd(50, 341);// || cmd(50, 344);
|
|
||||||
},
|
|
||||||
|
|
||||||
alt() {
|
|
||||||
return cmd(50, 342);// || cmd(50, 346);
|
|
||||||
},
|
|
||||||
|
|
||||||
super() {
|
|
||||||
return cmd(50, 343);// || cmd(50, 347);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
load("scripts/physics.js");
|
load("scripts/physics.js");
|
||||||
load("scripts/input.js");
|
load("scripts/input.js");
|
||||||
|
@ -259,17 +214,17 @@ var Register = {
|
||||||
},
|
},
|
||||||
|
|
||||||
kbm_input(mode, btn, state, ...args) {
|
kbm_input(mode, btn, state, ...args) {
|
||||||
|
if (btn === 'lmouse') btn = 'lm';
|
||||||
|
|
||||||
|
if (btn === 'rmouse') btn = 'rm';
|
||||||
|
|
||||||
|
if (btn === 'mmouse') btn = 'mm';
|
||||||
|
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case "emacs":
|
case "emacs":
|
||||||
Player.players[0].raw_input(btn, state, ...args);
|
Player.players[0].raw_input(btn, state, ...args);
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (btn === 'lmouse')
|
|
||||||
btn = 'lm';
|
|
||||||
|
|
||||||
if (btn === 'rmouse')
|
|
||||||
btn = 'rm';
|
|
||||||
},
|
},
|
||||||
|
|
||||||
gamepad_playermap: [],
|
gamepad_playermap: [],
|
||||||
|
@ -775,6 +730,7 @@ prototypes.from_file = function(file)
|
||||||
prototypes.list.push(a.tag);
|
prototypes.list.push(a.tag);
|
||||||
a.type = newobj;
|
a.type = newobj;
|
||||||
a.instances = [];
|
a.instances = [];
|
||||||
|
newobj.ur = a;
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
|
@ -334,7 +334,8 @@ var gameobject = {
|
||||||
delete props[key];
|
delete props[key];
|
||||||
|
|
||||||
var edited = !props.empty;
|
var edited = !props.empty;
|
||||||
return (edited ? "#" : "") + obj.name + " object " + obj.body + ", layer " + obj.draw_layer + ", phys " + obj.layer;
|
// return (edited ? "#" : "") + obj.name + " object " + obj.body + ", layer " + obj.draw_layer + ", phys " + obj.layer;
|
||||||
|
return obj.ur.tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
obj.fullpath = function() {
|
obj.fullpath = function() {
|
||||||
|
@ -349,6 +350,7 @@ var gameobject = {
|
||||||
this.elasticity) );
|
this.elasticity) );
|
||||||
obj.sync();
|
obj.sync();
|
||||||
obj.defn('components', {});
|
obj.defn('components', {});
|
||||||
|
Game.register_obj(obj);
|
||||||
|
|
||||||
var objects = [];
|
var objects = [];
|
||||||
obj.objects = objects;
|
obj.objects = objects;
|
||||||
|
|
|
@ -1,9 +1,54 @@
|
||||||
|
|
||||||
var Input = {
|
var Input = {
|
||||||
setgame() { cmd(77); },
|
setgame() { cmd(77); },
|
||||||
setnuke() { cmd(78); },
|
setnuke() { cmd(78); },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var Mouse = {
|
||||||
|
get pos() {
|
||||||
|
return cmd(45);
|
||||||
|
},
|
||||||
|
|
||||||
|
get screenpos() {
|
||||||
|
var p = this.pos;
|
||||||
|
p.y = Window.dimensions.y - p.y;
|
||||||
|
return p;
|
||||||
|
},
|
||||||
|
|
||||||
|
get worldpos() {
|
||||||
|
return screen2world(cmd(45));
|
||||||
|
},
|
||||||
|
|
||||||
|
disabled() {
|
||||||
|
cmd(46, 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
hidden() {
|
||||||
|
cmd(46, 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
normal() {
|
||||||
|
cmd(46, 0);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var Keys = {
|
||||||
|
shift() {
|
||||||
|
return cmd(50, 340);// || cmd(50, 344);
|
||||||
|
},
|
||||||
|
|
||||||
|
ctrl() {
|
||||||
|
return cmd(50, 341);// || cmd(50, 344);
|
||||||
|
},
|
||||||
|
|
||||||
|
alt() {
|
||||||
|
return cmd(50, 342);// || cmd(50, 346);
|
||||||
|
},
|
||||||
|
|
||||||
|
super() {
|
||||||
|
return cmd(50, 343);// || cmd(50, 347);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
Input.state2str = function(state) {
|
Input.state2str = function(state) {
|
||||||
if (typeof state === 'string') return state;
|
if (typeof state === 'string') return state;
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
|
|
@ -1,510 +0,0 @@
|
||||||
var Level = {
|
|
||||||
levels: [],
|
|
||||||
objects: [],
|
|
||||||
alive: true,
|
|
||||||
selectable: true,
|
|
||||||
toString() {
|
|
||||||
if (this.file)
|
|
||||||
return this.file;
|
|
||||||
|
|
||||||
return "Loose level";
|
|
||||||
},
|
|
||||||
|
|
||||||
fullpath() {
|
|
||||||
//return `${this.level.fullpath()}.${this.name}`;
|
|
||||||
},
|
|
||||||
|
|
||||||
get boundingbox() {
|
|
||||||
return bb_from_objects(this.objects);
|
|
||||||
},
|
|
||||||
|
|
||||||
varname2obj(varname) {
|
|
||||||
for (var i = 0; i < this.objects.length; i++)
|
|
||||||
if (this.objects[i].varname === varname)
|
|
||||||
return this.objects[i];
|
|
||||||
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
run() {
|
|
||||||
// TODO: If an object does not have a varname, give it one based on its parent
|
|
||||||
this.objects.forEach(function(x) {
|
|
||||||
if (x.hasOwn('varname')) {
|
|
||||||
scene[x.varname] = x;
|
|
||||||
this[x.varname] = x;
|
|
||||||
}
|
|
||||||
},this);
|
|
||||||
|
|
||||||
var script = IO.slurp(this.scriptfile);
|
|
||||||
compile_env(`var self = this;${script}`, this, this.scriptfile);
|
|
||||||
|
|
||||||
if (typeof this.update === 'function')
|
|
||||||
Register.update.register(this.update, this);
|
|
||||||
|
|
||||||
if (typeof this.gui === 'function')
|
|
||||||
Register.gui.register(this.gui, this);
|
|
||||||
|
|
||||||
if (typeof this.nk_gui === 'function')
|
|
||||||
register_nk_gui(this.nk_gui, this);
|
|
||||||
|
|
||||||
if (typeof this.inputs === 'object') {
|
|
||||||
Player.players[0].control(this);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
revert() {
|
|
||||||
delete this.unique;
|
|
||||||
this.load(this.filelvl);
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Returns how many objects this level created are still alive */
|
|
||||||
object_count() {
|
|
||||||
return objects.length();
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Save a list of objects into file, with pos acting as the relative placement */
|
|
||||||
saveas(objects, file, pos) {
|
|
||||||
if (!pos) pos = find_com(objects);
|
|
||||||
|
|
||||||
objects.forEach(function(obj) {
|
|
||||||
obj.pos = obj.pos.sub(pos);
|
|
||||||
});
|
|
||||||
|
|
||||||
var newlvl = Level.create();
|
|
||||||
|
|
||||||
objects.forEach(function(x) { newlvl.register(x); });
|
|
||||||
|
|
||||||
var save = newlvl.save();
|
|
||||||
slurpwrite(save, file);
|
|
||||||
},
|
|
||||||
|
|
||||||
clean() {
|
|
||||||
for (var key in this.objects)
|
|
||||||
clean_object(this.objects[key]);
|
|
||||||
|
|
||||||
for (var key in gameobjects)
|
|
||||||
clean_object(gameobjects[key]);
|
|
||||||
},
|
|
||||||
|
|
||||||
sync_file(file) {
|
|
||||||
var openlvls = this.levels.filter(function(x) { return x.file === file && x !== editor.edit_level; });
|
|
||||||
|
|
||||||
openlvls.forEach(function(x) {
|
|
||||||
x.clear();
|
|
||||||
x.load(IO.slurp(x.file));
|
|
||||||
x.flipdirty = true;
|
|
||||||
x.sync();
|
|
||||||
x.flipdirty = false;
|
|
||||||
x.check_dirty();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
save() {
|
|
||||||
this.clean();
|
|
||||||
var pos = this.pos;
|
|
||||||
var angle = this.angle;
|
|
||||||
|
|
||||||
this.pos = [0,0];
|
|
||||||
this.angle = 0;
|
|
||||||
if (this.flipx) {
|
|
||||||
this.objects.forEach(function(obj) {
|
|
||||||
this.mirror_x_obj(obj);
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.flipy) {
|
|
||||||
this.objects.forEach(function(obj) {
|
|
||||||
this.mirror_y_obj(obj);
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
var savereturn = JSON.stringify(this.objects, replacer_empty_nil, 1);
|
|
||||||
|
|
||||||
if (this.flipx) {
|
|
||||||
this.objects.forEach(function(obj) {
|
|
||||||
this.mirror_x_obj(obj);
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.flipy) {
|
|
||||||
this.objects.forEach(function(obj) {
|
|
||||||
this.mirror_y_obj(obj);
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.pos = pos;
|
|
||||||
this.angle = angle;
|
|
||||||
return savereturn;
|
|
||||||
},
|
|
||||||
|
|
||||||
mirror_x_obj(obj) {
|
|
||||||
obj.flipx = !obj.flipx;
|
|
||||||
var rp = obj.relpos;
|
|
||||||
obj.pos = [-rp.x, rp.y].add(this.pos);
|
|
||||||
obj.angle = -obj.angle;
|
|
||||||
},
|
|
||||||
|
|
||||||
mirror_y_obj(obj) {
|
|
||||||
var rp = obj.relpos;
|
|
||||||
obj.pos = [rp.x, -rp.y].add(this.pos);
|
|
||||||
obj.angle = -obj.angle;
|
|
||||||
},
|
|
||||||
|
|
||||||
/* TODO: Remove this; make it work without */
|
|
||||||
toJSON() {
|
|
||||||
var obj = {};
|
|
||||||
obj.file = this.file;
|
|
||||||
obj.pos = this._pos;
|
|
||||||
obj.angle = this._angle;
|
|
||||||
obj.from = "group";
|
|
||||||
obj.flipx = this.flipx;
|
|
||||||
obj.flipy = this.flipy;
|
|
||||||
obj.scale = this.scale;
|
|
||||||
|
|
||||||
if (this.varname)
|
|
||||||
obj.varname = this.varname;
|
|
||||||
|
|
||||||
if (!this.unique)
|
|
||||||
return obj;
|
|
||||||
|
|
||||||
obj.objects = {};
|
|
||||||
|
|
||||||
this.objects.forEach(function(x,i) {
|
|
||||||
obj.objects[i] = {};
|
|
||||||
var adiff = Math.abs(x.relangle - this.filelvl[i]._angle) > 1e-5;
|
|
||||||
if (adiff)
|
|
||||||
obj.objects[i].angle = x.relangle;
|
|
||||||
|
|
||||||
var pdiff = Vector.equal(x.relpos, this.filelvl[i]._pos, 1e-5);
|
|
||||||
if (!pdiff)
|
|
||||||
obj.objects[i].pos = x._pos.sub(this.pos);
|
|
||||||
|
|
||||||
if (obj.objects[i].empty)
|
|
||||||
delete obj.objects[i];
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
},
|
|
||||||
|
|
||||||
register(obj) {
|
|
||||||
if (obj.level)
|
|
||||||
obj.level.unregister(obj);
|
|
||||||
|
|
||||||
this.objects.push(obj);
|
|
||||||
},
|
|
||||||
|
|
||||||
make() {
|
|
||||||
return Level.loadfile(this.file, this.pos);
|
|
||||||
},
|
|
||||||
|
|
||||||
spawn(prefab) {
|
|
||||||
if (typeof prefab === 'string') {
|
|
||||||
var newobj = this.addfile(prefab);
|
|
||||||
return newobj;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newobj = prefab.make();
|
|
||||||
newobj.defn('level', this);
|
|
||||||
this.objects.push(newobj);
|
|
||||||
Game.register_obj(newobj);
|
|
||||||
newobj.setup?.();
|
|
||||||
newobj.start?.();
|
|
||||||
if (newobj.update)
|
|
||||||
Register.update.register(newobj.update, newobj);
|
|
||||||
return newobj;
|
|
||||||
},
|
|
||||||
|
|
||||||
dup(level) {
|
|
||||||
level ??= this.level;
|
|
||||||
var n = level.spawn(this.from);
|
|
||||||
/* TODO: Assign this's properties to the dup */
|
|
||||||
return ;n
|
|
||||||
},
|
|
||||||
|
|
||||||
create() {
|
|
||||||
var newlevel = Object.create(this);
|
|
||||||
newlevel.objects = [];
|
|
||||||
newlevel._pos = [0,0];
|
|
||||||
newlevel._angle = 0;
|
|
||||||
newlevel.color = Color.green;
|
|
||||||
/* newlevel.toString = function() {
|
|
||||||
return (newlevel.unique ? "#" : "") + newlevel.file;
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
newlevel.filejson = newlevel.save();
|
|
||||||
return newlevel;
|
|
||||||
},
|
|
||||||
|
|
||||||
addfile(file) {
|
|
||||||
/* TODO: Register this as a prefab for caching */
|
|
||||||
var lvl = this.loadfile(file);
|
|
||||||
this.objects.push(lvl);
|
|
||||||
lvl.level = this;
|
|
||||||
return lvl;
|
|
||||||
},
|
|
||||||
|
|
||||||
check_dirty() {
|
|
||||||
this.dirty = this.save() !== this.filejson;
|
|
||||||
},
|
|
||||||
|
|
||||||
add_child(obj) {
|
|
||||||
obj.unparent();
|
|
||||||
this.objects.push(obj);
|
|
||||||
obj.level = this;
|
|
||||||
},
|
|
||||||
|
|
||||||
start() {
|
|
||||||
this.objects.forEach(function(x) { if ('start' in x) x.start(); });
|
|
||||||
},
|
|
||||||
|
|
||||||
loadlevel(file) {
|
|
||||||
var lvl = Level.loadfile(file);
|
|
||||||
if (lvl && Game.playing())
|
|
||||||
lvl.start();
|
|
||||||
|
|
||||||
return lvl;
|
|
||||||
},
|
|
||||||
|
|
||||||
loadfile(file) {
|
|
||||||
if (!file.endsWith(".lvl")) file = file + ".lvl";
|
|
||||||
var newlevel = Level.create();
|
|
||||||
|
|
||||||
if (IO.exists(file)) {
|
|
||||||
newlevel.filejson = IO.slurp(file);
|
|
||||||
|
|
||||||
try {
|
|
||||||
newlevel.filelvl = JSON.parse(newlevel.filejson);
|
|
||||||
newlevel.load(newlevel.filelvl);
|
|
||||||
} catch (e) {
|
|
||||||
newlevel.ed_gizmo = function() { GUI.text("Invalid level file: " + newlevel.file, world2screen(newlevel.pos), 1, Color.red); };
|
|
||||||
newlevel.selectable = false;
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
newlevel.file = file;
|
|
||||||
newlevel.dirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var scriptfile = file.replace('.lvl', '.js');
|
|
||||||
if (IO.exists(scriptfile)) {
|
|
||||||
newlevel.script = IO.slurp(scriptfile);
|
|
||||||
newlevel.scriptfile = scriptfile;
|
|
||||||
}
|
|
||||||
|
|
||||||
newlevel.from = scriptfile.replace('.js','');
|
|
||||||
newlevel.file = newlevel.from;
|
|
||||||
newlevel.run();
|
|
||||||
|
|
||||||
return newlevel;
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Spawns all objects specified in the lvl json object */
|
|
||||||
load(lvl) {
|
|
||||||
this.clear();
|
|
||||||
this.levels.push_unique(this);
|
|
||||||
|
|
||||||
if (!lvl) {
|
|
||||||
Log.warn("Level is " + lvl + ". Need a better formed one.");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var opos = this.pos;
|
|
||||||
var oangle = this.angle;
|
|
||||||
this.pos = [0,0];
|
|
||||||
this.angle = 0;
|
|
||||||
|
|
||||||
var objs;
|
|
||||||
var created = [];
|
|
||||||
|
|
||||||
if (typeof lvl === 'string')
|
|
||||||
objs = JSON.parse(lvl);
|
|
||||||
else
|
|
||||||
objs = lvl;
|
|
||||||
|
|
||||||
if (typeof objs === 'object')
|
|
||||||
objs = objs.array();
|
|
||||||
|
|
||||||
objs.forEach(x => {
|
|
||||||
if (x.from === 'group') {
|
|
||||||
var loadedlevel = Level.loadfile(x.file);
|
|
||||||
if (!loadedlevel) {
|
|
||||||
Log.error("Error loading level: file " + x.file + " not found.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!IO.exists(x.file)) {
|
|
||||||
loadedlevel.ed_gizmo = function() { GUI.text("MISSING LEVEL " + x.file, world2screen(loadedlevel.pos) ,1, Color.red) };
|
|
||||||
}
|
|
||||||
var objs = x.objects;
|
|
||||||
delete x.objects;
|
|
||||||
Object.assign(loadedlevel, x);
|
|
||||||
|
|
||||||
if (objs) {
|
|
||||||
objs.array().forEach(function(x, i) {
|
|
||||||
if (x.pos)
|
|
||||||
loadedlevel.objects[i].pos = x.pos.add(loadedlevel.pos);
|
|
||||||
|
|
||||||
if (x.angle)
|
|
||||||
loadedlevel.objects[i].angle = x.angle + loadedlevel.angle;
|
|
||||||
});
|
|
||||||
|
|
||||||
loadedlevel.unique = true;
|
|
||||||
}
|
|
||||||
loadedlevel.level = this;
|
|
||||||
loadedlevel.sync();
|
|
||||||
created.push(loadedlevel);
|
|
||||||
this.objects.push(loadedlevel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var prototype = gameobjects[x.from];
|
|
||||||
if (!prototype) {
|
|
||||||
Log.error(`Prototype for ${x.from} does not exist.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newobj = this.spawn(gameobjects[x.from]);
|
|
||||||
|
|
||||||
delete x.from;
|
|
||||||
|
|
||||||
dainty_assign(newobj, x);
|
|
||||||
|
|
||||||
if (x._pos)
|
|
||||||
newobj.pos = x._pos;
|
|
||||||
|
|
||||||
|
|
||||||
if (x._angle)
|
|
||||||
newobj.angle = x._angle;
|
|
||||||
for (var key in newobj.components)
|
|
||||||
if ('sync' in newobj.components[key]) newobj.components[key].sync();
|
|
||||||
|
|
||||||
newobj.sync();
|
|
||||||
|
|
||||||
created.push(newobj);
|
|
||||||
});
|
|
||||||
|
|
||||||
created.forEach(function(x) {
|
|
||||||
if (x.varname)
|
|
||||||
this[x.varname] = x;
|
|
||||||
},this);
|
|
||||||
|
|
||||||
this.pos = opos;
|
|
||||||
this.angle = oangle;
|
|
||||||
|
|
||||||
return created;
|
|
||||||
},
|
|
||||||
|
|
||||||
clear() {
|
|
||||||
for (var i = this.objects.length-1; i >= 0; i--)
|
|
||||||
if (this.objects[i].alive)
|
|
||||||
this.objects[i].kill();
|
|
||||||
|
|
||||||
this.levels.remove(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
clear_all() {
|
|
||||||
this.levels.forEach(function(x) { x.kill(); });
|
|
||||||
},
|
|
||||||
|
|
||||||
kill() {
|
|
||||||
if (this.level)
|
|
||||||
this.level.unregister(this);
|
|
||||||
|
|
||||||
Register.unregister_obj(this);
|
|
||||||
|
|
||||||
this.clear();
|
|
||||||
},
|
|
||||||
|
|
||||||
unregister(obj) {
|
|
||||||
var removed = this.objects.remove(obj);
|
|
||||||
|
|
||||||
if (removed && obj.varname)
|
|
||||||
delete this[obj.varname];
|
|
||||||
},
|
|
||||||
|
|
||||||
remove_child(child) {
|
|
||||||
this.objects.remove(child);
|
|
||||||
},
|
|
||||||
|
|
||||||
get pos() { return this._pos; },
|
|
||||||
set pos(x) {
|
|
||||||
var diff = x.sub(this._pos);
|
|
||||||
this.objects.forEach(function(x) { x.pos = x.pos.add(diff); });
|
|
||||||
this._pos = x;
|
|
||||||
},
|
|
||||||
|
|
||||||
get angle() { return this._angle; },
|
|
||||||
set angle(x) {
|
|
||||||
var diff = x - this._angle;
|
|
||||||
this.objects.forEach(function(x) {
|
|
||||||
x.angle = x.angle + diff;
|
|
||||||
var pos = x.pos.sub(this.pos);
|
|
||||||
var r = Vector.length(pos);
|
|
||||||
var p = Math.rad2deg(Math.atan2(pos.y, pos.x));
|
|
||||||
p += diff;
|
|
||||||
p = Math.deg2rad(p);
|
|
||||||
x.pos = this.pos.add([r*Math.cos(p), r*Math.sin(p)]);
|
|
||||||
},this);
|
|
||||||
this._angle = x;
|
|
||||||
},
|
|
||||||
|
|
||||||
flipdirty: false,
|
|
||||||
|
|
||||||
sync() {
|
|
||||||
this.flipx = this.flipx;
|
|
||||||
this.flipy = this.flipy;
|
|
||||||
},
|
|
||||||
|
|
||||||
_flipx: false,
|
|
||||||
get flipx() { return this._flipx; },
|
|
||||||
set flipx(x) {
|
|
||||||
if (this._flipx === x && (!x || !this.flipdirty)) return;
|
|
||||||
this._flipx = x;
|
|
||||||
|
|
||||||
this.objects.forEach(function(obj) {
|
|
||||||
obj.flipx = !obj.flipx;
|
|
||||||
var rp = obj.relpos;
|
|
||||||
obj.pos = [-rp.x, rp.y].add(this.pos);
|
|
||||||
obj.angle = -obj.angle;
|
|
||||||
},this);
|
|
||||||
},
|
|
||||||
|
|
||||||
_flipy: false,
|
|
||||||
get flipy() { return this._flipy; },
|
|
||||||
set flipy(x) {
|
|
||||||
if (this._flipy === x && (!x || !this.flipdirty)) return;
|
|
||||||
this._flipy = x;
|
|
||||||
|
|
||||||
this.objects.forEach(function(obj) {
|
|
||||||
var rp = obj.relpos;
|
|
||||||
obj.pos = [rp.x, -rp.y].add(this.pos);
|
|
||||||
obj.angle = -obj.angle;
|
|
||||||
},this);
|
|
||||||
},
|
|
||||||
|
|
||||||
_scale: 1.0,
|
|
||||||
get scale() { return this._scale; },
|
|
||||||
set scale(x) {
|
|
||||||
var diff = (x - this._scale) + 1;
|
|
||||||
this._scale = x;
|
|
||||||
|
|
||||||
this.objects.forEach(function(obj) {
|
|
||||||
obj.scale *= diff;
|
|
||||||
obj.relpos = obj.relpos.scale(diff);
|
|
||||||
}, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
get up() {
|
|
||||||
return [0,1].rotate(Math.deg2rad(this.angle));
|
|
||||||
},
|
|
||||||
|
|
||||||
get down() {
|
|
||||||
return [0,-1].rotate(Math.deg2rad(this.angle));
|
|
||||||
},
|
|
||||||
|
|
||||||
get right() {
|
|
||||||
return [1,0].rotate(Math.deg2rad(this.angle));
|
|
||||||
},
|
|
||||||
|
|
||||||
get left() {
|
|
||||||
return [-1,0].rotate(Math.deg2rad(this.angle));
|
|
||||||
},
|
|
||||||
};
|
|
Loading…
Reference in a new issue