From b9316dbbe6aa3a6b0d8361997de38e393b94a29d Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Mon, 11 Sep 2023 22:09:21 +0000 Subject: [PATCH] Editor mouse works; remove level.js --- source/engine/gameobject.c | 2 +- source/engine/input.c | 9 +- source/engine/render.c | 3 - source/engine/yugine.c | 7 +- source/scripts/editor.js | 489 +++++++++++++++++------------------ source/scripts/engine.js | 58 +---- source/scripts/entity.js | 4 +- source/scripts/input.js | 47 +++- source/scripts/level.js | 510 ------------------------------------- 9 files changed, 313 insertions(+), 816 deletions(-) delete mode 100644 source/scripts/level.js diff --git a/source/engine/gameobject.c b/source/engine/gameobject.c index 5d6301e..94d74c5 100644 --- a/source/engine/gameobject.c +++ b/source/engine/gameobject.c @@ -34,7 +34,7 @@ struct gameobject *id2go(int id) { } int body2id(cpBody *body) { - return *(int*)cpBodyGetUserData(body); + return (int)cpBodyGetUserData(body); } cpBody *id2body(int id) { diff --git a/source/engine/input.c b/source/engine/input.c index 9937eaa..2b143d7 100644 --- a/source/engine/input.c +++ b/source/engine/input.c @@ -98,10 +98,11 @@ char *mb2str(int btn) void input_mouse(int btn, int state) { - JSValue argv[2]; - argv[0] = input2js(mb2str(btn)); - argv[1] = jsinputstate[btn]; - script_callee(pawn_callee, 2, argv); + JSValue argv[3]; + argv[0] = JS_NewString(js, "emacs"); + argv[1] = input2js(mb2str(btn)); + argv[2] = jsinputstate[state]; + script_callee(pawn_callee, 3, argv); } void input_mouse_move(float x, float y, float dx, float dy) diff --git a/source/engine/render.c b/source/engine/render.c index 4c481d8..71f33af 100644 --- a/source/engine/render.c +++ b/source/engine/render.c @@ -413,9 +413,6 @@ void openglRender(struct window *window) { 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_apply_pipeline(crt_post.pipe); sg_apply_bindings(&crt_post.bind); diff --git a/source/engine/yugine.c b/source/engine/yugine.c index ecdba59..32acf4c 100644 --- a/source/engine/yugine.c +++ b/source/engine/yugine.c @@ -152,10 +152,14 @@ int frame_fps() { 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() { double elapsed = sapp_frame_duration(); appTime += elapsed; + low_fps_c += elapsed; input_poll(0); @@ -181,9 +185,10 @@ void c_frame() sim_pause(); 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); window_render(&mainwin); prof(&prof_draw); diff --git a/source/scripts/editor.js b/source/scripts/editor.js index ff3229b..ffa182a 100644 --- a/source/scripts/editor.js +++ b/source/scripts/editor.js @@ -27,15 +27,15 @@ var configs = { var editor = { dbgdraw: false, - selected: null, + selected: undefined, selectlist: [], moveoffset: [0,0], startrot: 0, rotoffset: 0, camera: editor_camera, edit_level: {}, /* The current level that is being edited */ - working_layer: -1, - cursor: null, + working_layer: 0, + cursor: undefined, edit_mode: "basic", 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 */ do_select(go) { - var obj = go >= 0 ? Game.object(go) : null; - if (!obj || !obj.selectable) return null; + var obj = go >= 0 ? Game.object(go) : undefined; + 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) { var testlevel = obj.level; @@ -62,7 +64,7 @@ var editor = { return obj; }, - curpanel: null, + curpanel: undefined, check_level_nested() { if (this.edit_level.level) { @@ -99,7 +101,7 @@ var editor = { protos[this.selectlist[0].__proto__.name] = pobj; 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 */ dainty_assign(this.selectlist[0].__proto__, tobj); @@ -201,71 +203,6 @@ var editor = { wh[1] = Math.abs(end[1] - start[1]); 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) { return function(go) { go.pos = go.pos.add(amt)}; @@ -350,13 +287,13 @@ var editor = { unselect() { editor.selectlist = []; - this.grabselect = null; - this.sel_comp = null; + this.grabselect = undefined; + this.sel_comp = undefined; }, - sel_comp: null, + sel_comp: undefined, comp_info: false, - brush_obj: null, + brush_obj: undefined, camera_recalls: {}, camera_recall_stack: [], @@ -407,119 +344,17 @@ var editor = { 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, - input_rmouse_released() { - 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, + grabselect: undefined, mousejoy: [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() { 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: "", start_play_ed() { @@ -569,7 +404,7 @@ var editor = { var stolen = this; if (dontsteal) - stolen = null; + stolen = undefined; this.curpanel.open(stolen); }, @@ -584,59 +419,11 @@ var editor = { 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: [], startpos: [], 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: [], curlvl: {}, /* What the level currently looks like on file */ @@ -777,7 +564,7 @@ var editor = { this.edit_level = Level.create(); }, - _sel_comp: null, + _sel_comp: undefined, get sel_comp() { return this._sel_comp; }, set sel_comp(x) { if (this._sel_comp) @@ -830,7 +617,7 @@ var editor = { var ypos = 200; var lvlcolor = Color.white; while (clvl) { - var lvlstr = clvl.file ? clvl.file : "NEW LEVEL"; + var lvlstr = clvl.file ? clvl.file : "NEW ENTITY"; if (clvl.unique) lvlstr += "#"; else if (clvl.dirty) @@ -976,10 +763,13 @@ var editor = { lvl_history: [], load(file) { - if (this.edit_level) this.lvl_history.push(this.edit_level.file); - this.edit_level.clear(); - this.edit_level = Level.loadfile(file); - this.curlvl = this.edit_level.save(); + if (this.edit_level) this.lvl_history.push(this.edit_level.ur); + this.edit_level.kill(); +// this.edit_level = Level.loadfile(file); +// 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(); }, @@ -1178,6 +968,32 @@ editor.inputs.r = function() { }; 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() { if (!Game.playing()) { 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.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'].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.g = function() { - this.selectlist.forEach(function(x,i) { - this.moveoffsets[i] = x.pos.sub(screen2world(Mouse.pos)); - }, this); + editor.selectlist.forEach(function(x,i) { editor.moveoffsets[i] = x.pos.sub(screen2world(Mouse.pos)); } ); }; editor.inputs.g.doc = "Move selected objects."; editor.inputs.g.released = function() { editor.moveoffsets = []; }; @@ -1436,7 +1415,7 @@ editor.inputs.tab = function() { else { var idx = sel.findIndex(this.sel_comp) + 1; if (idx >= Object.keys(sel).length) - this.sel_comp = null; + this.sel_comp = undefined; else 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['C-g'] = function() { + if (!this.selectlist) return; this.selectlist = this.dup_objects(this.selectlist); editor.inputs.g(); }; @@ -1497,7 +1477,7 @@ brushmode.inputs.lm.doc = "Paste selected brush."; brushmode.inputs.b = function() { if (editor.brush_obj) { - editor.brush_obj = null; + editor.brush_obj = undefined; return; } @@ -1532,6 +1512,27 @@ editor.inputs.s = function() { }; 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 = { title: "untitled", value: "", @@ -1579,7 +1580,7 @@ var inputpanel = { Player.players[0].uncontrol(this); if (this.stolen) { Player.players[0].control(this.stolen); - this.stolen = null; + this.stolen = undefined; } this.on = false; @@ -2003,7 +2004,7 @@ texteditor.inputs['M-n'].rep = true; var objectexplorer = copy(inputpanel, { title: "object explorer", - obj: null, + obj: undefined, previous: [], start() { this.previous = []; @@ -2322,7 +2323,7 @@ function tab_complete(val, list) { return check[0]; } - var ret = null; + var ret = undefined; var i = val.length; while (!ret && !check.empty) { diff --git a/source/scripts/engine.js b/source/scripts/engine.js index efdd992..7874c43 100644 --- a/source/scripts/engine.js +++ b/source/scripts/engine.js @@ -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/input.js"); @@ -259,17 +214,17 @@ var Register = { }, kbm_input(mode, btn, state, ...args) { + if (btn === 'lmouse') btn = 'lm'; + + if (btn === 'rmouse') btn = 'rm'; + + if (btn === 'mmouse') btn = 'mm'; + switch(mode) { case "emacs": Player.players[0].raw_input(btn, state, ...args); break; }; - - if (btn === 'lmouse') - btn = 'lm'; - - if (btn === 'rmouse') - btn = 'rm'; }, gamepad_playermap: [], @@ -775,6 +730,7 @@ prototypes.from_file = function(file) prototypes.list.push(a.tag); a.type = newobj; a.instances = []; + newobj.ur = a; return a; } diff --git a/source/scripts/entity.js b/source/scripts/entity.js index 4e9ade0..4e1e5d5 100644 --- a/source/scripts/entity.js +++ b/source/scripts/entity.js @@ -334,7 +334,8 @@ var gameobject = { delete props[key]; 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() { @@ -349,6 +350,7 @@ var gameobject = { this.elasticity) ); obj.sync(); obj.defn('components', {}); + Game.register_obj(obj); var objects = []; obj.objects = objects; diff --git a/source/scripts/input.js b/source/scripts/input.js index 9ae5844..39ca4be 100644 --- a/source/scripts/input.js +++ b/source/scripts/input.js @@ -1,9 +1,54 @@ - var Input = { setgame() { cmd(77); }, 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) { if (typeof state === 'string') return state; switch (state) { diff --git a/source/scripts/level.js b/source/scripts/level.js deleted file mode 100644 index 2d1ece2..0000000 --- a/source/scripts/level.js +++ /dev/null @@ -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)); - }, -};