Editor camera zoom and pan; fix mouse input signals; tex editor to own file; fix grid drawing
This commit is contained in:
parent
ef95b233e2
commit
e6ef147c40
|
@ -570,8 +570,6 @@ void draw_arrow(struct cpVect start, struct cpVect end, struct rgba color, int c
|
|||
void draw_grid(float width, float span, struct rgba color)
|
||||
{
|
||||
cpVect offset = cam_pos();
|
||||
offset.x -= mainwin.width/2;
|
||||
offset.y -= mainwin.height/2;
|
||||
offset = cpvmult(offset, 1/cam_zoom());
|
||||
|
||||
float ubo[4];
|
||||
|
|
|
@ -126,7 +126,7 @@ struct gameobject *js2go(JSValue v) {
|
|||
return id2go(js2int(v));
|
||||
}
|
||||
|
||||
struct sprite *js2sprite(JSValue v) { return id2go(js2int(v)); }
|
||||
struct sprite *js2sprite(JSValue v) { return id2sprite(js2int(v)); }
|
||||
|
||||
void *js2ptr(JSValue v) {
|
||||
void *p;
|
||||
|
@ -1100,7 +1100,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
|||
break;
|
||||
|
||||
case 126:
|
||||
mainwin.height = js2int(argv[2]);
|
||||
mainwin.height = js2int(argv[1]);
|
||||
break;
|
||||
|
||||
case 127:
|
||||
|
|
|
@ -29,6 +29,7 @@ JSValue jsaxis;
|
|||
JSValue jsany;
|
||||
JSValue jsmouse;
|
||||
JSValue jspos;
|
||||
JSValue jsmove;
|
||||
|
||||
cpVect mouse_pos = {0, 0};
|
||||
cpVect mouse_delta = {0, 0};
|
||||
|
@ -84,25 +85,35 @@ char *mb2str(int btn)
|
|||
{
|
||||
switch(btn) {
|
||||
case 0:
|
||||
return "lmouse";
|
||||
return "lm";
|
||||
break;
|
||||
case 1:
|
||||
return "rmouse";
|
||||
return "rm";
|
||||
break;
|
||||
case 2:
|
||||
return "mmouse";
|
||||
return "mm";
|
||||
break;
|
||||
}
|
||||
return "NULLMOUSE";
|
||||
}
|
||||
|
||||
void input_mouse(int btn, int state)
|
||||
void input_mouse(int btn, int state, uint32_t mod)
|
||||
{
|
||||
char out[16] = {0};
|
||||
snprintf(out, 16, "%s%s%s%s",
|
||||
mod & SAPP_MODIFIER_CTRL ? "C-" : "",
|
||||
mod & SAPP_MODIFIER_ALT ? "M-" : "",
|
||||
mod & SAPP_MODIFIER_SUPER ? "S-" : "",
|
||||
mb2str(btn)
|
||||
);
|
||||
|
||||
JSValue argv[3];
|
||||
argv[0] = JS_NewString(js, "emacs");
|
||||
argv[1] = input2js(mb2str(btn));
|
||||
argv[1] = JS_NewString(js, out);
|
||||
argv[2] = jsinputstate[state];
|
||||
script_callee(pawn_callee, 3, argv);
|
||||
script_callee(pawn_callee, 3, argv);
|
||||
JS_FreeValue(js, argv[0]);
|
||||
JS_FreeValue(js, argv[1]);
|
||||
}
|
||||
|
||||
void input_mouse_move(float x, float y, float dx, float dy)
|
||||
|
@ -114,10 +125,12 @@ void input_mouse_move(float x, float y, float dx, float dy)
|
|||
|
||||
JSValue argv[3];
|
||||
argv[0] = jsmouse;
|
||||
argv[1] = jspos;
|
||||
argv[1] = jsmove;
|
||||
argv[2] = vec2js(mouse_pos);
|
||||
script_callee(pawn_callee, 3, argv);
|
||||
argv[3] = vec2js(mouse_delta);
|
||||
script_callee(pawn_callee, 4, argv);
|
||||
JS_FreeValue(js, argv[2]);
|
||||
JS_FreeValue(js, argv[3]);
|
||||
}
|
||||
|
||||
void input_mouse_scroll(float x, float y)
|
||||
|
@ -218,6 +231,7 @@ void input_init() {
|
|||
jsany = str2js("any");
|
||||
jsmouse = str2js("mouse");
|
||||
jspos = str2js("pos");
|
||||
jsmove = str2js("move");
|
||||
|
||||
for (int i = 0; i < 512; i++)
|
||||
key_states[i] = INPUT_UP;
|
||||
|
@ -371,11 +385,6 @@ void cursor_show() { sapp_show_mouse(1); }
|
|||
int action_down(int key) { return key_states[key] == INPUT_DOWN; }
|
||||
int action_up(int key) { return key_states[key] == INPUT_UP; }
|
||||
|
||||
int want_quit() {
|
||||
return mquit;
|
||||
}
|
||||
|
||||
void quit() {
|
||||
exit(0);
|
||||
mquit = 1;
|
||||
sapp_quit();
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ void cursor_hide();
|
|||
void cursor_show();
|
||||
void set_mouse_mode(int mousemode);
|
||||
|
||||
void input_mouse(int btn, int state);
|
||||
void input_mouse(int btn, int state, uint32_t mod);
|
||||
void input_mouse_move(float x, float y, float dx, float dy);
|
||||
void input_mouse_scroll(float x, float y);
|
||||
void input_btn(int btn, int state, uint32_t mod);
|
||||
|
@ -39,7 +39,6 @@ int action_down(int key);
|
|||
void register_pawn(struct callee c);
|
||||
void register_gamepad(struct callee c);
|
||||
|
||||
int want_quit();
|
||||
void quit();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -87,6 +87,8 @@ void gif_rec_start(int w, int h, int cpf, int bitdepth)
|
|||
|
||||
void gif_rec_end(char *path)
|
||||
{
|
||||
if (!gif.rec) return;
|
||||
|
||||
MsfGifResult gif_res = msf_gif_end(&gif_state);
|
||||
if (gif_res.data) {
|
||||
FILE *f = fopen(path, "wb");
|
||||
|
@ -432,6 +434,7 @@ void full_2d_pass(struct window *window)
|
|||
|
||||
call_nk_gui();
|
||||
nuke_end();
|
||||
|
||||
}
|
||||
|
||||
void full_3d_pass(struct window *window)
|
||||
|
@ -479,11 +482,8 @@ void openglRender(struct window *window) {
|
|||
sg_apply_bindings(&crt_post.bind);
|
||||
sg_draw(0,6,1);
|
||||
|
||||
|
||||
|
||||
sg_end_pass();
|
||||
|
||||
|
||||
sg_commit();
|
||||
|
||||
debug_newframe();
|
||||
|
|
|
@ -112,7 +112,7 @@ void sprite_io(struct sprite *sprite, FILE *f, int read) {
|
|||
|
||||
void sprite_draw_all() {
|
||||
sg_apply_pipeline(pip_sprite);
|
||||
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(projection));
|
||||
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(projection));
|
||||
|
||||
static struct sprite **layers[5];
|
||||
|
||||
|
|
|
@ -199,8 +199,9 @@ void c_frame()
|
|||
gameobjects_cleanup();
|
||||
}
|
||||
|
||||
void c_clean() {};
|
||||
|
||||
void c_clean() {
|
||||
gif_rec_end("crash.gif");
|
||||
};
|
||||
|
||||
void c_event(const sapp_event *e)
|
||||
{
|
||||
|
@ -224,11 +225,11 @@ void c_event(const sapp_event *e)
|
|||
break;
|
||||
|
||||
case SAPP_EVENTTYPE_MOUSE_UP:
|
||||
input_mouse(e->mouse_button, INPUT_UP);
|
||||
input_mouse(e->mouse_button, INPUT_UP, e->modifiers);
|
||||
break;
|
||||
|
||||
case SAPP_EVENTTYPE_MOUSE_DOWN:
|
||||
input_mouse(e->mouse_button, INPUT_DOWN);
|
||||
input_mouse(e->mouse_button, INPUT_DOWN, e->modifiers);
|
||||
break;
|
||||
|
||||
case SAPP_EVENTTYPE_CHAR:
|
||||
|
|
|
@ -2,15 +2,11 @@
|
|||
Editor-only variables on objects
|
||||
selectable
|
||||
*/
|
||||
|
||||
prototypes.generate_ur('.');
|
||||
|
||||
/* This is the editor level & camera - NOT the currently edited level, but a level to hold editor things */
|
||||
var editor_level = gameobject.make(Primum);
|
||||
var editor_camera = camera2d.make(editor_level);
|
||||
editor_camera.save = false;
|
||||
|
||||
Game.view_camera(editor_camera);
|
||||
var editor_level = Primum.spawn(ur.arena);
|
||||
var editor_camera = Game.camera;
|
||||
|
||||
var editor_config = {
|
||||
grid_size: 100,
|
||||
|
@ -46,9 +42,8 @@ var editor = {
|
|||
/* Tries to select id */
|
||||
do_select(go) {
|
||||
var obj = go >= 0 ? Game.object(go) : undefined;
|
||||
if (obj)
|
||||
Log.warn(obj);
|
||||
if (!obj || !obj.selectable) return undefined;
|
||||
return obj;
|
||||
|
||||
if (this.working_layer > -1 && obj.draw_layer !== this.working_layer) return undefined;
|
||||
|
||||
|
@ -170,22 +165,13 @@ var editor = {
|
|||
var objs = x.slice();
|
||||
var duped = [];
|
||||
|
||||
objs.forEach(function(x,i) {
|
||||
if (x.file) {
|
||||
var newlevel = this.edit_level.addfile(x.file);
|
||||
newlevel.pos = x.pos;
|
||||
newlevel.angle = x.angle;
|
||||
duped.push(newlevel);
|
||||
} else {
|
||||
var newobj = this.edit_level.spawn(x.__proto__);
|
||||
duped.push(newobj);
|
||||
objs.forEach(function(x) {
|
||||
var newobj = this.edit_level.spawn(x.ur);
|
||||
dainty_assign(newobj, x);
|
||||
newobj.pos = x.pos;
|
||||
newobj.angle = x.angle;
|
||||
dainty_assign(newobj, x.prop_obj());
|
||||
}
|
||||
},this);
|
||||
|
||||
duped.forEach(function(x) { delete duped.varname; });
|
||||
duped.push(newobj);
|
||||
} ,this);
|
||||
|
||||
return duped.flat();
|
||||
},
|
||||
|
@ -226,44 +212,12 @@ var editor = {
|
|||
}
|
||||
},
|
||||
|
||||
input_up_pressed() {
|
||||
this.key_move([0,1]);
|
||||
},
|
||||
|
||||
input_up_rep() {
|
||||
this.input_up_pressed();
|
||||
},
|
||||
|
||||
input_left_pressed() {
|
||||
this.key_move([-1,0]);
|
||||
},
|
||||
|
||||
input_left_rep() {
|
||||
this.input_left_pressed();
|
||||
},
|
||||
|
||||
key_move(dir) {
|
||||
if (Keys.ctrl())
|
||||
this.selectlist.forEach(this.snapper(dir.scale(1.01), editor_config.grid_size));
|
||||
else
|
||||
this.selectlist.forEach(this.mover(dir.scale(this.step_amt())));
|
||||
},
|
||||
|
||||
input_right_pressed() {
|
||||
this.key_move([1,0]);
|
||||
},
|
||||
|
||||
input_right_rep() {
|
||||
this.input_right_pressed();
|
||||
},
|
||||
|
||||
input_down_pressed() {
|
||||
this.key_move([0,-1]);
|
||||
},
|
||||
|
||||
input_down_rep() {
|
||||
this.input_down_pressed();
|
||||
},
|
||||
|
||||
/* Snapmode
|
||||
0 No snap
|
||||
|
@ -344,17 +298,11 @@ var editor = {
|
|||
this.camera.zoom = zoom*1.3;
|
||||
},
|
||||
|
||||
z_start: 1,
|
||||
|
||||
z_start: undefined,
|
||||
grabselect: undefined,
|
||||
mousejoy: [0,0],
|
||||
joystart: [0,0],
|
||||
mousejoy: undefined,
|
||||
joystart: undefined,
|
||||
|
||||
input_mmouse_released() {
|
||||
Mouse.normal();
|
||||
this.grabselect = undefined;
|
||||
},
|
||||
|
||||
stash: "",
|
||||
|
||||
start_play_ed() {
|
||||
|
@ -369,29 +317,6 @@ var editor = {
|
|||
|
||||
moveoffsets: [],
|
||||
|
||||
// TODO: Unify so this works
|
||||
/* input_g_pressed() {
|
||||
if (this.sel_comp) {
|
||||
if ('pos' in this.sel_comp)
|
||||
this.moveoffset = this.sel_comp.pos.sub(screen2world(Mouse.pos));
|
||||
return;
|
||||
}
|
||||
},
|
||||
*/
|
||||
input_g_down() {
|
||||
if (Keys.alt()) return;
|
||||
if (this.sel_comp) {
|
||||
this.sel_comp.pos = this.moveoffset.add(screen2world(Mouse.pos));
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.moveoffsets.length === 0) return;
|
||||
|
||||
this.selectlist.forEach(function(x,i) {
|
||||
x.pos = this.moveoffsets[i].add(screen2world(Mouse.pos));
|
||||
}, this);
|
||||
},
|
||||
|
||||
scaleoffset: 0,
|
||||
startscales: [],
|
||||
selected_com: [0,0],
|
||||
|
@ -588,7 +513,6 @@ var editor = {
|
|||
GUI.text("WORKING LAYER: " + this.working_layer, [0,520]);
|
||||
GUI.text("MODE: " + this.edit_mode, [0,500]);
|
||||
|
||||
Debug.point(world2screen(this.edit_level.pos), 5, Color.yellow);
|
||||
if (this.cursor) {
|
||||
Debug.point(World2screen(this.cursor), 5, Color.green);
|
||||
|
||||
|
@ -678,7 +602,7 @@ var editor = {
|
|||
gui_img("icons/icons8-lock-16.png", world2screen(obj.pos));
|
||||
});
|
||||
|
||||
Debug.draw_grid(2, editor_config.grid_size/editor_camera.zoom, editor_config.grid_color);
|
||||
Debug.draw_grid(1, editor_config.grid_size/editor_camera.zoom, editor_config.grid_color);
|
||||
var startgrid = screen2world([-20,Window.height]).map(function(x) { return Math.snap(x, editor_config.grid_size); }, this);
|
||||
var endgrid = screen2world([Window.width, 0]);
|
||||
|
||||
|
@ -764,12 +688,11 @@ var editor = {
|
|||
|
||||
load(file) {
|
||||
if (this.edit_level) this.lvl_history.push(this.edit_level.ur);
|
||||
this.edit_level.kill();
|
||||
// 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);
|
||||
Primum.spawn(prototypes.get_ur(file));
|
||||
|
||||
this.unselect();
|
||||
},
|
||||
|
||||
|
@ -1279,13 +1202,6 @@ editor.inputs.rm = function() {
|
|||
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;
|
||||
|
||||
|
@ -1298,17 +1214,6 @@ editor.inputs.rm = function() {
|
|||
};
|
||||
|
||||
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);
|
||||
|
@ -1325,10 +1230,11 @@ editor.inputs.mm = function() {
|
|||
}
|
||||
|
||||
var grabobj = editor.try_select();
|
||||
if (Array.isArray(grabobj)) {
|
||||
/* if (Array.isArray(grabobj)) {
|
||||
editor.selectlist = grabobj;
|
||||
return;
|
||||
}
|
||||
*/
|
||||
editor.grabselect = undefined;
|
||||
if (!grabobj) return;
|
||||
|
||||
|
@ -1345,32 +1251,52 @@ editor.inputs.mm = function() {
|
|||
|
||||
editor.moveoffset = editor.grabselect.pos.sub(screen2world(Mouse.pos));
|
||||
};
|
||||
editor.inputs['C-mm'] = editor.inputs.mm;
|
||||
|
||||
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['C-M-mm'] = function() {
|
||||
editor.mousejoy = Mouse.pos;
|
||||
editor.joystart = editor.camera.pos;
|
||||
};
|
||||
|
||||
editor.inputs.mm.down = function() {
|
||||
if (Keys.shift() && !Keys.ctrl()) {
|
||||
this.cursor = Mouse.worldpos;
|
||||
return;
|
||||
}
|
||||
editor.inputs['C-M-rm'] = function() {
|
||||
editor.mousejoy = Mouse.pos;
|
||||
editor.z_start = editor.camera.zoom;
|
||||
Mouse.disabled();
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
editor.inputs['C-S-mm'] = function() { editor.cursor = find_com(editor.selectlist); };
|
||||
|
||||
editor.inputs.rm.released = function() {
|
||||
editor.mousejoy = undefined;
|
||||
editor.z_start = undefined;
|
||||
Mouse.normal();
|
||||
};
|
||||
|
||||
editor.inputs['S-mm'] = function() { this.cursor = Mouse.worldpos; };
|
||||
|
||||
editor.inputs.mm.released = function () {
|
||||
Mouse.normal();
|
||||
this.grabselect = undefined;
|
||||
editor.mousejoy = undefined;
|
||||
editor.joystart = undefined;
|
||||
};
|
||||
editor.inputs.mouse = {};
|
||||
editor.inputs.mouse.move = function(pos, dpos)
|
||||
{
|
||||
if (editor.mousejoy) {
|
||||
if (editor.z_start)
|
||||
editor.camera.zoom += dpos.y/500;
|
||||
else if (editor.joystart)
|
||||
editor.camera.pos = editor.camera.pos.add(dpos.scale(editor.camera.zoom).mapc(mult,[-1,1]));
|
||||
}
|
||||
|
||||
if (!this.grabselect) return;
|
||||
|
||||
if (this.grabselect) {
|
||||
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.";
|
||||
|
@ -1399,11 +1325,42 @@ 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() {
|
||||
if (this.sel_comp) {
|
||||
if ('pos' in this.sel_comp)
|
||||
this.moveoffset = this.sel_comp.pos.sub(screen2world(Mouse.pos));
|
||||
return;
|
||||
}
|
||||
|
||||
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 = []; };
|
||||
|
||||
editor.inputs.g.down = function() {
|
||||
if (this.sel_comp) {
|
||||
this.sel_comp.pos = this.moveoffset.add(screen2world(Mouse.pos));
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.moveoffsets.length === 0) return;
|
||||
|
||||
this.selectlist.forEach(function(x,i) {
|
||||
x.pos = this.moveoffsets[i].add(screen2world(Mouse.pos));
|
||||
}, this);
|
||||
};
|
||||
|
||||
editor.inputs.up = function() { this.key_move([0,1]); };
|
||||
editor.inputs.up.rep = true;
|
||||
|
||||
editor.inputs.left = function() { this.key_move([-1,0]); };
|
||||
editor.inputs.left.rep = true;
|
||||
|
||||
editor.inputs.right = function() { this.key_move([1,0]); };
|
||||
editor.inputs.right.rep = true;
|
||||
|
||||
editor.inputs.down = function() { this.key_move([0,-1]); };
|
||||
editor.inputs.down.rep = true;
|
||||
|
||||
editor.inputs.tab = function() {
|
||||
if (!this.selectlist.length === 1) return;
|
||||
if (!this.selectlist[0].components) return;
|
||||
|
@ -1666,341 +1623,7 @@ function proto_children(name) {
|
|||
return children;
|
||||
}
|
||||
|
||||
var texteditor = clone(inputpanel, {
|
||||
title: "text editor",
|
||||
_cursor:0, /* Text cursor: [char,line] */
|
||||
get cursor() { return this._cursor; },
|
||||
set cursor(x) {
|
||||
if (x > this.value.length)
|
||||
x = this.value.length;
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
|
||||
this._cursor = x;
|
||||
this.line = this.get_line();
|
||||
},
|
||||
|
||||
submit() {},
|
||||
|
||||
line: 0,
|
||||
killring: [],
|
||||
undos: [],
|
||||
startbuffer: "",
|
||||
|
||||
savestate() {
|
||||
this.undos.push(this.value.slice());
|
||||
},
|
||||
|
||||
popstate() {
|
||||
if (this.undos.length === 0) return;
|
||||
this.value = this.undos.pop();
|
||||
this.cursor = this.cursor;
|
||||
},
|
||||
|
||||
copy(start, end) {
|
||||
return this.value.slice(start,end);
|
||||
},
|
||||
|
||||
delete_line(p) {
|
||||
var ls = this.line_start(p);
|
||||
var le = this.line_end(p)+1;
|
||||
this.cut_span(ls,le);
|
||||
this.to_line_start();
|
||||
},
|
||||
|
||||
line_blank(p) {
|
||||
var ls = this.line_start(p);
|
||||
var le = this.line_end(p);
|
||||
var line = this.value.slice(ls, le);
|
||||
if (line.search(/[^\s]/g) === -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
},
|
||||
|
||||
get_line() {
|
||||
var line = 0;
|
||||
for (var i = 0; i < this.cursor; i++)
|
||||
if (this.value[i] === "\n")
|
||||
line++;
|
||||
|
||||
return line;
|
||||
},
|
||||
|
||||
start() {
|
||||
this.cursor = 0;
|
||||
this.startbuffer = this.value.slice();
|
||||
},
|
||||
|
||||
get dirty() {
|
||||
return this.startbuffer !== this.value;
|
||||
},
|
||||
|
||||
gui() {
|
||||
GUI.text_cursor(this.value, [100,700],1,this.cursor+1);
|
||||
GUI.text("C" + this.cursor + ":::L" + this.line + ":::" + (this.dirty ? "DIRTY" : "CLEAN"), [100,100], 1);
|
||||
},
|
||||
|
||||
insert_char(char) {
|
||||
this.value = this.value.slice(0,this.cursor) + char + this.value.slice(this.cursor);
|
||||
this.cursor++;
|
||||
},
|
||||
|
||||
input_enter_pressrep() {
|
||||
var white = this.line_starting_whitespace(this.cursor);
|
||||
this.insert_char('\n');
|
||||
|
||||
for (var i = 0; i < white; i++)
|
||||
this.insert_char(" ");
|
||||
|
||||
},
|
||||
|
||||
input_text(char) {
|
||||
if (Keys.ctrl() || Keys.alt()) return;
|
||||
this.insert_char(char);
|
||||
this.keycb();
|
||||
},
|
||||
|
||||
input_backspace_pressrep() {
|
||||
this.value = this.value.slice(0,this.cursor-1) + this.value.slice(this.cursor);
|
||||
this.cursor--;
|
||||
},
|
||||
|
||||
line_starting_whitespace(p) {
|
||||
var white = 0;
|
||||
var l = this.line_start(p);
|
||||
|
||||
while (this.value[l] === " ") {
|
||||
white++;
|
||||
l++;
|
||||
}
|
||||
|
||||
return white;
|
||||
},
|
||||
|
||||
cut_span(start, end) {
|
||||
if (end < start) return;
|
||||
this.savestate();
|
||||
var ret = this.value.slice(start,end);
|
||||
this.value = this.value.slice(0,start) + this.value.slice(end);
|
||||
if (start > this.cursor)
|
||||
return ret;
|
||||
|
||||
this.cursor -= ret.length;
|
||||
return ret;
|
||||
},
|
||||
|
||||
next_word(pos) {
|
||||
var v = this.value.slice(pos+1).search(/[^\w]\w/g);
|
||||
if (v === -1) return pos;
|
||||
return pos + v + 2;
|
||||
},
|
||||
|
||||
prev_word(pos) {
|
||||
while (this.value.slice(pos,pos+2).search(/[^\w]\w/g) === -1 && pos > 0)
|
||||
pos--;
|
||||
|
||||
return pos+1;
|
||||
},
|
||||
|
||||
end_of_word(pos) {
|
||||
var l = this.value.slice(pos).search(/\w[^\w]/g);
|
||||
return l+pos;
|
||||
},
|
||||
|
||||
get inset() {
|
||||
return this.cursor - this.value.prev('\n', this.cursor) - 1;
|
||||
},
|
||||
|
||||
line_start(p) {
|
||||
return this.value.prev('\n', p)+1;
|
||||
},
|
||||
|
||||
line_end(p) {
|
||||
return this.value.next('\n', p);
|
||||
},
|
||||
|
||||
next_line(p) {
|
||||
return this.value.next('\n',p)+1;
|
||||
},
|
||||
|
||||
prev_line(p) {
|
||||
return this.line_start(this.value.prev('\n', p));
|
||||
},
|
||||
|
||||
to_line_start() {
|
||||
this.cursor = this.value.prev('\n', this.cursor)+1;
|
||||
},
|
||||
|
||||
to_line_end() {
|
||||
var p = this.value.next('\n', this.cursor);
|
||||
if (p === -1)
|
||||
this.to_file_end();
|
||||
else
|
||||
this.cursor = p;
|
||||
},
|
||||
|
||||
line_width(pos) {
|
||||
var start = this.line_start(pos);
|
||||
var end = this.line_end(pos);
|
||||
if (end === -1)
|
||||
end = this.value.length;
|
||||
|
||||
return end-start;
|
||||
},
|
||||
|
||||
to_file_end() { this.cursor = this.value.length; },
|
||||
|
||||
to_file_start() { this.cursor = 0; },
|
||||
|
||||
desired_inset: 0,
|
||||
});
|
||||
|
||||
texteditor.inputs = {};
|
||||
texteditor.inputs['C-s'] = function() {
|
||||
editor.edit_level.script = texteditor.value;
|
||||
editor.save_current();
|
||||
texteditor.startbuffer = texteditor.value.slice();
|
||||
};
|
||||
texteditor.inputs['C-s'].doc = "Save script to file.";
|
||||
|
||||
texteditor.inputs['C-u'] = function() { this.popstate(); };
|
||||
texteditor.inputs['C-u'].doc = "Undo.";
|
||||
|
||||
texteditor.inputs['C-q'] = function() {
|
||||
var ws = this.prev_word(this.cursor);
|
||||
var we = this.end_of_word(this.cursor)+1;
|
||||
var find = this.copy(ws, we);
|
||||
var obj = editor.edit_level.varname2obj(find);
|
||||
|
||||
if (obj) {
|
||||
editor.unselect();
|
||||
editor.selectlist.push(obj);
|
||||
}
|
||||
};
|
||||
texteditor.inputs['C-q'].doc = "Select object of selected word.";
|
||||
|
||||
texteditor.inputs['C-o'] = function() {
|
||||
this.insert_char('\n');
|
||||
this.cursor--;
|
||||
};
|
||||
texteditor.inputs['C-o'].doc = "Insert newline.";
|
||||
texteditor.inputs['C-o'].rep = true;
|
||||
|
||||
texteditor.inputs['M-o'] = function() {
|
||||
while (this.line_blank(this.next_line(this.cursor)))
|
||||
this.delete_line(this.next_line(this.cursor));
|
||||
|
||||
while (this.line_blank(this.prev_line(this.cursor)))
|
||||
this.delete_line(this.prev_line(this.cursor));
|
||||
};
|
||||
texteditor.inputs['M-o'].doc = "Delete surround blank lines.";
|
||||
|
||||
texteditor.inputs['C-d'] = function () { this.value = this.value.slice(0,this.cursor) + this.value.slice(this.cursor+1); };
|
||||
texteditor.inputs['C-d'].doc = "Delete character.";
|
||||
|
||||
texteditor.inputs['M-d'] = function() { this.cut_span(this.cursor, this.end_of_word(this.cursor)+1); };
|
||||
texteditor.inputs['M-d'].doc = "Delete word.";
|
||||
|
||||
texteditor.inputs['C-a'] = function() {
|
||||
this.to_line_start();
|
||||
this.desired_inset = this.inset;
|
||||
};
|
||||
texteditor.inputs['C-a'].doc = "To start of line.";
|
||||
|
||||
texteditor.inputs['C-y'] = function() {
|
||||
if (this.killring.length === 0) return;
|
||||
this.insert_char(this.killring.pop());
|
||||
};
|
||||
texteditor.inputs['C-y'].doc = "Insert from killring.";
|
||||
|
||||
texteditor.inputs['C-e'] = function() {
|
||||
this.to_line_end();
|
||||
this.desired_inset = this.inset;
|
||||
};
|
||||
texteditor.inputs['C-e'].doc = "To line end.";
|
||||
|
||||
texteditor.inputs['C-k'] = function() {
|
||||
if (this.cursor === this.value.length-1) return;
|
||||
var killamt = this.value.next('\n', this.cursor) - this.cursor;
|
||||
var killed = this.cut_span(this.cursor-1, this.cursor+killamt);
|
||||
this.killring.push(killed);
|
||||
};
|
||||
texteditor.inputs['C-k'].doc = "Kill from cursor to end of line.";
|
||||
|
||||
texteditor.inputs['M-k'] = function() {
|
||||
var prevn = this.value.prev('\n', this.cursor);
|
||||
var killamt = this.cursor - prevn;
|
||||
var killed = this.cut_span(prevn+1, prevn+killamt);
|
||||
this.killring.push(killed);
|
||||
this.to_line_start();
|
||||
};
|
||||
texteditor.inputs['M-k'].doc = "Kill entire line the cursor is on.";
|
||||
|
||||
texteditor.inputs['C-b'] = function() {
|
||||
this.cursor--;
|
||||
this.desired_inset = this.inset;
|
||||
};
|
||||
texteditor.inputs['C-b'].rep = true;
|
||||
texteditor.inputs['M-b'] = function() {
|
||||
this.cursor = this.prev_word(this.cursor-2);
|
||||
this.desired_inset = this.inset;
|
||||
};
|
||||
texteditor.inputs['M-b'].rep = true;
|
||||
|
||||
texteditor.inputs['C-f'] = function() {
|
||||
this.cursor++;
|
||||
this.desired_inset = this.inset;
|
||||
};
|
||||
texteditor.inputs['C-f'].rep = true;
|
||||
texteditor.inputs['M-f'] = function() {
|
||||
this.cursor = this.next_word(this.cursor);
|
||||
this.desired_inset = this.inset;
|
||||
};
|
||||
texteditor.inputs['M-f'].rep = true;
|
||||
|
||||
texteditor.inputs['C-p'] = function() {
|
||||
if (this.cursor === 0) return;
|
||||
this.desired_inset = Math.max(this.desired_inset, this.inset);
|
||||
this.cursor = this.prev_line(this.cursor);
|
||||
var newlinew = this.line_width(this.cursor);
|
||||
this.cursor += Math.min(this.desired_inset, newlinew);
|
||||
};
|
||||
texteditor.inputs['C-p'].rep = true;
|
||||
|
||||
texteditor.inputs['M-p'] = function() {
|
||||
while (this.line_blank(this.cursor))
|
||||
this.cursor = this.prev_line(this.cursor);
|
||||
|
||||
while (!this.line_blank(this.cursor))
|
||||
this.cursor = this.prev_line(this.cursor);
|
||||
};
|
||||
texteditor.inputs['M-p'].doc = "Go up to next line with text on it.";
|
||||
texteditor.inputs['M-p'].rep = true;
|
||||
|
||||
texteditor.inputs['C-n'] = function() {
|
||||
if (this.cursor === this.value.length-1) return;
|
||||
if (this.value.next('\n', this.cursor) === -1) {
|
||||
this.to_file_end();
|
||||
return;
|
||||
}
|
||||
|
||||
this.desired_inset = Math.max(this.desired_inset, this.inset);
|
||||
this.cursor = this.next_line(this.cursor);
|
||||
var newlinew = this.line_width(this.cursor);
|
||||
this.cursor += Math.min(this.desired_inset, newlinew);
|
||||
};
|
||||
texteditor.inputs['C-n'].rep = true;
|
||||
|
||||
texteditor.inputs['M-n'] = function() {
|
||||
while (this.line_blank(this.cursor))
|
||||
this.cursor = this.next_line(this.cursor);
|
||||
|
||||
while (!this.line_blank(this.cursor))
|
||||
this.cursor = this.next_line(this.cursor);
|
||||
};
|
||||
texteditor.inputs['M-n'].doc = "Go down to next line with text on it.";
|
||||
texteditor.inputs['M-n'].rep = true;
|
||||
load("scripts/textedit.js");
|
||||
|
||||
var objectexplorer = copy(inputpanel, {
|
||||
title: "object explorer",
|
||||
|
@ -2429,4 +2052,3 @@ if (IO.exists("editor.config"))
|
|||
editor.edit_level = editor_level;
|
||||
|
||||
Game.stop();
|
||||
Game.render();
|
||||
|
|
|
@ -214,16 +214,18 @@ var Register = {
|
|||
},
|
||||
|
||||
kbm_input(mode, btn, state, ...args) {
|
||||
if (btn === 'lmouse') btn = 'lm';
|
||||
|
||||
if (btn === 'rmouse') btn = 'rm';
|
||||
|
||||
if (btn === 'mmouse') btn = 'mm';
|
||||
|
||||
if (state === 'released') {
|
||||
btn = btn.split('-').last;
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
case "emacs":
|
||||
Player.players[0].raw_input(btn, state, ...args);
|
||||
break;
|
||||
|
||||
case "mouse":
|
||||
Player.players[0].mouse_input(btn, state, ...args);
|
||||
break;
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -556,16 +558,17 @@ Register.update.register(Game.exec, Game);
|
|||
|
||||
//load("scripts/level.js");
|
||||
|
||||
|
||||
|
||||
load("scripts/entity.js");
|
||||
|
||||
var World = Object.create(gameobject);
|
||||
var Primum = World;
|
||||
var objects = [];
|
||||
Primum.tag = "PRIMUM";
|
||||
Primum.selectable = false;
|
||||
Primum.ur = { tag: "Primum" };
|
||||
Primum.objects = [];
|
||||
|
||||
World.remove_child = function(child) {
|
||||
objects.remove(child);
|
||||
this.objects.remove(child);
|
||||
}
|
||||
|
||||
World.add_child = function(child) {
|
||||
|
@ -633,29 +636,6 @@ function save_game_configs() {
|
|||
|
||||
load("scripts/physics.js");
|
||||
|
||||
var camera2d = gameobject.clone("camera2d", {
|
||||
phys: gameobject.bodytype.kinematic,
|
||||
speed: 300,
|
||||
|
||||
get zoom() { return this._zoom; },
|
||||
set zoom(x) {
|
||||
if (x <= 0) return;
|
||||
this._zoom = x;
|
||||
cmd(62, this._zoom);
|
||||
},
|
||||
_zoom: 1.0,
|
||||
speedmult: 1.0,
|
||||
|
||||
selectable: false,
|
||||
|
||||
view2world(pos) {
|
||||
return pos.mapc(mult, [1,-1]).add([-Window.width,Window.height].scale(0.5)).scale(this.zoom).add(this.pos);
|
||||
},
|
||||
|
||||
world2view(pos) {
|
||||
return pos.sub(this.pos).scale(1/this.zoom).add(Window.dimensions.scale(0.5));
|
||||
},
|
||||
});
|
||||
|
||||
Game.view_camera = function(cam)
|
||||
{
|
||||
|
@ -663,156 +643,9 @@ Game.view_camera = function(cam)
|
|||
cmd(61, Game.camera.body);
|
||||
}
|
||||
|
||||
Game.view_camera(camera2d.make(World));
|
||||
Game.view_camera(Primum.spawn(ur.camera2d));
|
||||
|
||||
win_make(Game.title, Game.resolution[0], Game.resolution[1]);
|
||||
|
||||
/* Default objects */
|
||||
var prototypes = {};
|
||||
prototypes.ur = {};
|
||||
prototypes.load_all = function()
|
||||
{
|
||||
if (IO.exists("proto.json"))
|
||||
prototypes = JSON.parse(IO.slurp("proto.json"));
|
||||
|
||||
for (var key in prototypes) {
|
||||
if (key in gameobjects)
|
||||
dainty_assign(gameobjects[key], prototypes[key]);
|
||||
else {
|
||||
/* Create this gameobject fresh */
|
||||
Log.info("Making new prototype: " + key + " from " + prototypes[key].from);
|
||||
var newproto = gameobjects[prototypes[key].from].clone(key);
|
||||
gameobjects[key] = newproto;
|
||||
|
||||
for (var pkey in newproto)
|
||||
if (typeof newproto[pkey] === 'object' && newproto[pkey] && 'clone' in newproto[pkey])
|
||||
newproto[pkey] = newproto[pkey].clone();
|
||||
|
||||
dainty_assign(gameobjects[key], prototypes[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prototypes.save_gameobjects = function() { slurpwrite(JSON.stringify(gameobjects,null,2), "proto.json"); };
|
||||
|
||||
prototypes.from_file = function(file)
|
||||
{
|
||||
if (!IO.exists(file)) {
|
||||
Log.error(`File ${file} does not exist.`);
|
||||
return;
|
||||
}
|
||||
|
||||
var newobj = gameobject.clone(file, {});
|
||||
var script = IO.slurp(file);
|
||||
|
||||
newobj.$ = {};
|
||||
var json = {};
|
||||
if (IO.exists(file.name() + ".json")) {
|
||||
json = JSON.parse(IO.slurp(file.name() + ".json"));
|
||||
Object.assign(newobj.$, json.$);
|
||||
delete json.$;
|
||||
}
|
||||
|
||||
compile_env(`var self = this; var $ = self.$; ${script}`, newobj, file);
|
||||
dainty_assign(newobj, json);
|
||||
|
||||
file = file.replaceAll('/', '.');
|
||||
var path = file.name().split('.');
|
||||
var nested_access = function(base, names) {
|
||||
for (var i = 0; i < names.length; i++)
|
||||
base = base[names[i]] = base[names[i]] || {};
|
||||
|
||||
return base;
|
||||
};
|
||||
var a = nested_access(ur, path);
|
||||
|
||||
a.tag = file.name();
|
||||
prototypes.list.push(a.tag);
|
||||
a.type = newobj;
|
||||
a.instances = [];
|
||||
newobj.ur = a;
|
||||
|
||||
return a;
|
||||
}
|
||||
prototypes.from_file.doc = "Create a new ur-type from a given script file.";
|
||||
prototypes.list = [];
|
||||
|
||||
prototypes.from_obj = function(name, obj)
|
||||
{
|
||||
var newobj = gameobject.clone(name, obj);
|
||||
prototypes.ur[name] = {
|
||||
tag: name,
|
||||
type: newobj
|
||||
};
|
||||
return prototypes.ur[name];
|
||||
}
|
||||
|
||||
prototypes.load_config = function(name)
|
||||
{
|
||||
if (!prototypes.ur[name])
|
||||
prototypes.ur[name] = gameobject.clone(name);
|
||||
|
||||
Log.warn(`Made new ur of name ${name}`);
|
||||
|
||||
return prototypes.ur[name];
|
||||
}
|
||||
|
||||
|
||||
prototypes.list_ur = function()
|
||||
{
|
||||
var list = [];
|
||||
function list_obj(obj, prefix)
|
||||
{
|
||||
prefix ??= "";
|
||||
var list = [];
|
||||
for (var e in obj) {
|
||||
list.push(prefix + e);
|
||||
Log.warn("Descending into " + e);
|
||||
list.concat(list_obj(obj[e], e + "."));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
return list_obj(ur);
|
||||
}
|
||||
|
||||
prototypes.get_ur = function(name)
|
||||
{
|
||||
if (!prototypes.ur[name]) {
|
||||
if (IO.exists(name + ".js"))
|
||||
prototypes.from_file(name + ".js");
|
||||
|
||||
prototypes.load_config(name);
|
||||
return prototypes.ur[name];
|
||||
} else
|
||||
return prototypes.ur[name];
|
||||
}
|
||||
|
||||
prototypes.from_obj("polygon2d", {
|
||||
polygon2d: polygon2d.clone(),
|
||||
});
|
||||
|
||||
prototypes.from_obj("edge2d", {
|
||||
edge2d: bucket.clone(),
|
||||
});
|
||||
|
||||
prototypes.from_obj("sprite", {
|
||||
sprite: sprite.clone(),
|
||||
});
|
||||
|
||||
prototypes.generate_ur = function(path)
|
||||
{
|
||||
var ob = IO.glob("*.js");
|
||||
ob = ob.concat(IO.glob("**/*.js"));
|
||||
ob = ob.filter(function(str) { return !str.startsWith("scripts"); });
|
||||
|
||||
ob.forEach(function(name) {
|
||||
if (name === "game.js") return;
|
||||
if (name === "play.js") return;
|
||||
|
||||
prototypes.from_file(name);
|
||||
});
|
||||
}
|
||||
|
||||
var ur = prototypes.ur;
|
||||
Window.width = 1280;
|
||||
Window.height = 720;
|
||||
|
|
|
@ -339,7 +339,7 @@ var gameobject = {
|
|||
};
|
||||
|
||||
obj.fullpath = function() {
|
||||
return `${obj.level.fullpath()}.${obj.name}`;
|
||||
return obj.ur.tag;
|
||||
};
|
||||
obj.deflock('toString');
|
||||
obj.defc('from', this.name);
|
||||
|
@ -450,3 +450,180 @@ var gameobject = {
|
|||
|
||||
var locks = ['height', 'width', 'visible', 'body', 'controlled', 'selectable', 'save', 'velocity', 'angularvelocity', 'alive', 'boundingbox', 'name', 'scale', 'angle', 'properties', 'moi', 'relpos', 'relangle', 'up', 'down', 'right', 'left', 'bodytype', 'gizmo', 'pos'];
|
||||
locks.forEach(x => gameobject.obscure(x));
|
||||
|
||||
|
||||
/* Default objects */
|
||||
var prototypes = {};
|
||||
prototypes.ur = {};
|
||||
prototypes.load_all = function()
|
||||
{
|
||||
if (IO.exists("proto.json"))
|
||||
prototypes = JSON.parse(IO.slurp("proto.json"));
|
||||
|
||||
for (var key in prototypes) {
|
||||
if (key in gameobjects)
|
||||
dainty_assign(gameobjects[key], prototypes[key]);
|
||||
else {
|
||||
/* Create this gameobject fresh */
|
||||
Log.info("Making new prototype: " + key + " from " + prototypes[key].from);
|
||||
var newproto = gameobjects[prototypes[key].from].clone(key);
|
||||
gameobjects[key] = newproto;
|
||||
|
||||
for (var pkey in newproto)
|
||||
if (typeof newproto[pkey] === 'object' && newproto[pkey] && 'clone' in newproto[pkey])
|
||||
newproto[pkey] = newproto[pkey].clone();
|
||||
|
||||
dainty_assign(gameobjects[key], prototypes[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prototypes.save_gameobjects = function() { slurpwrite(JSON.stringify(gameobjects,null,2), "proto.json"); };
|
||||
|
||||
prototypes.from_file = function(file)
|
||||
{
|
||||
if (!IO.exists(file)) {
|
||||
Log.error(`File ${file} does not exist.`);
|
||||
return;
|
||||
}
|
||||
|
||||
var newobj = gameobject.clone(file, {});
|
||||
var script = IO.slurp(file);
|
||||
|
||||
newobj.$ = {};
|
||||
var json = {};
|
||||
if (IO.exists(file.name() + ".json")) {
|
||||
json = JSON.parse(IO.slurp(file.name() + ".json"));
|
||||
Object.assign(newobj.$, json.$);
|
||||
delete json.$;
|
||||
}
|
||||
|
||||
compile_env(`var self = this; var $ = self.$; ${script}`, newobj, file);
|
||||
dainty_assign(newobj, json);
|
||||
|
||||
file = file.replaceAll('/', '.');
|
||||
var path = file.name().split('.');
|
||||
var nested_access = function(base, names) {
|
||||
for (var i = 0; i < names.length; i++)
|
||||
base = base[names[i]] = base[names[i]] || {};
|
||||
|
||||
return base;
|
||||
};
|
||||
var a = nested_access(ur, path);
|
||||
|
||||
a.tag = file.name();
|
||||
prototypes.list.push(a.tag);
|
||||
a.type = newobj;
|
||||
a.instances = [];
|
||||
newobj.ur = a;
|
||||
|
||||
return a;
|
||||
}
|
||||
prototypes.from_file.doc = "Create a new ur-type from a given script file.";
|
||||
prototypes.list = [];
|
||||
|
||||
prototypes.from_obj = function(name, obj)
|
||||
{
|
||||
var newobj = gameobject.clone(name, obj);
|
||||
prototypes.ur[name] = {
|
||||
tag: name,
|
||||
type: newobj
|
||||
};
|
||||
return prototypes.ur[name];
|
||||
}
|
||||
|
||||
prototypes.load_config = function(name)
|
||||
{
|
||||
if (!prototypes.ur[name])
|
||||
prototypes.ur[name] = gameobject.clone(name);
|
||||
|
||||
Log.warn(`Made new ur of name ${name}`);
|
||||
|
||||
return prototypes.ur[name];
|
||||
}
|
||||
|
||||
|
||||
prototypes.list_ur = function()
|
||||
{
|
||||
var list = [];
|
||||
function list_obj(obj, prefix)
|
||||
{
|
||||
prefix ??= "";
|
||||
var list = [];
|
||||
for (var e in obj) {
|
||||
list.push(prefix + e);
|
||||
Log.warn("Descending into " + e);
|
||||
list.concat(list_obj(obj[e], e + "."));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
return list_obj(ur);
|
||||
}
|
||||
|
||||
prototypes.get_ur = function(name)
|
||||
{
|
||||
if (!prototypes.ur[name]) {
|
||||
if (IO.exists(name + ".js"))
|
||||
prototypes.from_file(name + ".js");
|
||||
|
||||
prototypes.load_config(name);
|
||||
return prototypes.ur[name];
|
||||
} else
|
||||
return prototypes.ur[name];
|
||||
}
|
||||
|
||||
prototypes.from_obj("polygon2d", {
|
||||
polygon2d: polygon2d.clone(),
|
||||
});
|
||||
|
||||
prototypes.from_obj("edge2d", {
|
||||
edge2d: bucket.clone(),
|
||||
});
|
||||
|
||||
prototypes.from_obj("sprite", {
|
||||
sprite: sprite.clone(),
|
||||
});
|
||||
|
||||
prototypes.generate_ur = function(path)
|
||||
{
|
||||
var ob = IO.glob("*.js");
|
||||
ob = ob.concat(IO.glob("**/*.js"));
|
||||
ob = ob.filter(function(str) { return !str.startsWith("scripts"); });
|
||||
|
||||
ob.forEach(function(name) {
|
||||
if (name === "game.js") return;
|
||||
if (name === "play.js") return;
|
||||
|
||||
prototypes.from_file(name);
|
||||
});
|
||||
}
|
||||
|
||||
var ur = prototypes.ur;
|
||||
|
||||
prototypes.from_obj("camera2d", {
|
||||
phys: gameobject.bodytype.kinematic,
|
||||
speed: 300,
|
||||
|
||||
get zoom() { return this._zoom; },
|
||||
set zoom(x) {
|
||||
if (x <= 0) return;
|
||||
this._zoom = x;
|
||||
cmd(62, this._zoom);
|
||||
},
|
||||
_zoom: 1.0,
|
||||
speedmult: 1.0,
|
||||
|
||||
selectable: false,
|
||||
|
||||
view2world(pos) {
|
||||
return pos.mapc(mult, [1,-1]).add([-Window.width,Window.height].scale(0.5)).scale(this.zoom).add(this.pos);
|
||||
},
|
||||
|
||||
world2view(pos) {
|
||||
return pos.sub(this.pos).scale(1/this.zoom).add(Window.dimensions.scale(0.5));
|
||||
},
|
||||
});
|
||||
|
||||
prototypes.from_obj("arena", {});
|
||||
|
|
|
@ -108,6 +108,15 @@ var Player = {
|
|||
this.pawns.forEach(x => x[fn]?.(...args));
|
||||
},
|
||||
|
||||
mouse_input(type, ...args) {
|
||||
for (var pawn of this.pawns.reverse()) {
|
||||
if (typeof pawn.inputs?.mouse?.[type] === 'function') {
|
||||
pawn.inputs.mouse[type].call(pawn,...args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
raw_input(cmd, state, ...args) {
|
||||
for (var pawn of this.pawns.reverse()) {
|
||||
if (typeof pawn.inputs?.any === 'function') {
|
||||
|
|
335
source/scripts/textedit.js
Normal file
335
source/scripts/textedit.js
Normal file
|
@ -0,0 +1,335 @@
|
|||
var texteditor = clone(inputpanel, {
|
||||
title: "text editor",
|
||||
_cursor:0, /* Text cursor: [char,line] */
|
||||
get cursor() { return this._cursor; },
|
||||
set cursor(x) {
|
||||
if (x > this.value.length)
|
||||
x = this.value.length;
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
|
||||
this._cursor = x;
|
||||
this.line = this.get_line();
|
||||
},
|
||||
|
||||
submit() {},
|
||||
|
||||
line: 0,
|
||||
killring: [],
|
||||
undos: [],
|
||||
startbuffer: "",
|
||||
|
||||
savestate() {
|
||||
this.undos.push(this.value.slice());
|
||||
},
|
||||
|
||||
popstate() {
|
||||
if (this.undos.length === 0) return;
|
||||
this.value = this.undos.pop();
|
||||
this.cursor = this.cursor;
|
||||
},
|
||||
|
||||
copy(start, end) {
|
||||
return this.value.slice(start,end);
|
||||
},
|
||||
|
||||
delete_line(p) {
|
||||
var ls = this.line_start(p);
|
||||
var le = this.line_end(p)+1;
|
||||
this.cut_span(ls,le);
|
||||
this.to_line_start();
|
||||
},
|
||||
|
||||
line_blank(p) {
|
||||
var ls = this.line_start(p);
|
||||
var le = this.line_end(p);
|
||||
var line = this.value.slice(ls, le);
|
||||
if (line.search(/[^\s]/g) === -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
},
|
||||
|
||||
get_line() {
|
||||
var line = 0;
|
||||
for (var i = 0; i < this.cursor; i++)
|
||||
if (this.value[i] === "\n")
|
||||
line++;
|
||||
|
||||
return line;
|
||||
},
|
||||
|
||||
start() {
|
||||
this.cursor = 0;
|
||||
this.startbuffer = this.value.slice();
|
||||
},
|
||||
|
||||
get dirty() {
|
||||
return this.startbuffer !== this.value;
|
||||
},
|
||||
|
||||
gui() {
|
||||
GUI.text_cursor(this.value, [100,700],1,this.cursor+1);
|
||||
GUI.text("C" + this.cursor + ":::L" + this.line + ":::" + (this.dirty ? "DIRTY" : "CLEAN"), [100,100], 1);
|
||||
},
|
||||
|
||||
insert_char(char) {
|
||||
this.value = this.value.slice(0,this.cursor) + char + this.value.slice(this.cursor);
|
||||
this.cursor++;
|
||||
},
|
||||
|
||||
input_enter_pressrep() {
|
||||
var white = this.line_starting_whitespace(this.cursor);
|
||||
this.insert_char('\n');
|
||||
|
||||
for (var i = 0; i < white; i++)
|
||||
this.insert_char(" ");
|
||||
|
||||
},
|
||||
|
||||
input_text(char) {
|
||||
if (Keys.ctrl() || Keys.alt()) return;
|
||||
this.insert_char(char);
|
||||
this.keycb();
|
||||
},
|
||||
|
||||
input_backspace_pressrep() {
|
||||
this.value = this.value.slice(0,this.cursor-1) + this.value.slice(this.cursor);
|
||||
this.cursor--;
|
||||
},
|
||||
|
||||
line_starting_whitespace(p) {
|
||||
var white = 0;
|
||||
var l = this.line_start(p);
|
||||
|
||||
while (this.value[l] === " ") {
|
||||
white++;
|
||||
l++;
|
||||
}
|
||||
|
||||
return white;
|
||||
},
|
||||
|
||||
cut_span(start, end) {
|
||||
if (end < start) return;
|
||||
this.savestate();
|
||||
var ret = this.value.slice(start,end);
|
||||
this.value = this.value.slice(0,start) + this.value.slice(end);
|
||||
if (start > this.cursor)
|
||||
return ret;
|
||||
|
||||
this.cursor -= ret.length;
|
||||
return ret;
|
||||
},
|
||||
|
||||
next_word(pos) {
|
||||
var v = this.value.slice(pos+1).search(/[^\w]\w/g);
|
||||
if (v === -1) return pos;
|
||||
return pos + v + 2;
|
||||
},
|
||||
|
||||
prev_word(pos) {
|
||||
while (this.value.slice(pos,pos+2).search(/[^\w]\w/g) === -1 && pos > 0)
|
||||
pos--;
|
||||
|
||||
return pos+1;
|
||||
},
|
||||
|
||||
end_of_word(pos) {
|
||||
var l = this.value.slice(pos).search(/\w[^\w]/g);
|
||||
return l+pos;
|
||||
},
|
||||
|
||||
get inset() {
|
||||
return this.cursor - this.value.prev('\n', this.cursor) - 1;
|
||||
},
|
||||
|
||||
line_start(p) {
|
||||
return this.value.prev('\n', p)+1;
|
||||
},
|
||||
|
||||
line_end(p) {
|
||||
return this.value.next('\n', p);
|
||||
},
|
||||
|
||||
next_line(p) {
|
||||
return this.value.next('\n',p)+1;
|
||||
},
|
||||
|
||||
prev_line(p) {
|
||||
return this.line_start(this.value.prev('\n', p));
|
||||
},
|
||||
|
||||
to_line_start() {
|
||||
this.cursor = this.value.prev('\n', this.cursor)+1;
|
||||
},
|
||||
|
||||
to_line_end() {
|
||||
var p = this.value.next('\n', this.cursor);
|
||||
if (p === -1)
|
||||
this.to_file_end();
|
||||
else
|
||||
this.cursor = p;
|
||||
},
|
||||
|
||||
line_width(pos) {
|
||||
var start = this.line_start(pos);
|
||||
var end = this.line_end(pos);
|
||||
if (end === -1)
|
||||
end = this.value.length;
|
||||
|
||||
return end-start;
|
||||
},
|
||||
|
||||
to_file_end() { this.cursor = this.value.length; },
|
||||
|
||||
to_file_start() { this.cursor = 0; },
|
||||
|
||||
desired_inset: 0,
|
||||
});
|
||||
|
||||
texteditor.inputs = {};
|
||||
texteditor.inputs['C-s'] = function() {
|
||||
editor.edit_level.script = texteditor.value;
|
||||
editor.save_current();
|
||||
texteditor.startbuffer = texteditor.value.slice();
|
||||
};
|
||||
texteditor.inputs['C-s'].doc = "Save script to file.";
|
||||
|
||||
texteditor.inputs['C-u'] = function() { this.popstate(); };
|
||||
texteditor.inputs['C-u'].doc = "Undo.";
|
||||
|
||||
texteditor.inputs['C-q'] = function() {
|
||||
var ws = this.prev_word(this.cursor);
|
||||
var we = this.end_of_word(this.cursor)+1;
|
||||
var find = this.copy(ws, we);
|
||||
var obj = editor.edit_level.varname2obj(find);
|
||||
|
||||
if (obj) {
|
||||
editor.unselect();
|
||||
editor.selectlist.push(obj);
|
||||
}
|
||||
};
|
||||
texteditor.inputs['C-q'].doc = "Select object of selected word.";
|
||||
|
||||
texteditor.inputs['C-o'] = function() {
|
||||
this.insert_char('\n');
|
||||
this.cursor--;
|
||||
};
|
||||
texteditor.inputs['C-o'].doc = "Insert newline.";
|
||||
texteditor.inputs['C-o'].rep = true;
|
||||
|
||||
texteditor.inputs['M-o'] = function() {
|
||||
while (this.line_blank(this.next_line(this.cursor)))
|
||||
this.delete_line(this.next_line(this.cursor));
|
||||
|
||||
while (this.line_blank(this.prev_line(this.cursor)))
|
||||
this.delete_line(this.prev_line(this.cursor));
|
||||
};
|
||||
texteditor.inputs['M-o'].doc = "Delete surround blank lines.";
|
||||
|
||||
texteditor.inputs['C-d'] = function () { this.value = this.value.slice(0,this.cursor) + this.value.slice(this.cursor+1); };
|
||||
texteditor.inputs['C-d'].doc = "Delete character.";
|
||||
|
||||
texteditor.inputs['M-d'] = function() { this.cut_span(this.cursor, this.end_of_word(this.cursor)+1); };
|
||||
texteditor.inputs['M-d'].doc = "Delete word.";
|
||||
|
||||
texteditor.inputs['C-a'] = function() {
|
||||
this.to_line_start();
|
||||
this.desired_inset = this.inset;
|
||||
};
|
||||
texteditor.inputs['C-a'].doc = "To start of line.";
|
||||
|
||||
texteditor.inputs['C-y'] = function() {
|
||||
if (this.killring.length === 0) return;
|
||||
this.insert_char(this.killring.pop());
|
||||
};
|
||||
texteditor.inputs['C-y'].doc = "Insert from killring.";
|
||||
|
||||
texteditor.inputs['C-e'] = function() {
|
||||
this.to_line_end();
|
||||
this.desired_inset = this.inset;
|
||||
};
|
||||
texteditor.inputs['C-e'].doc = "To line end.";
|
||||
|
||||
texteditor.inputs['C-k'] = function() {
|
||||
if (this.cursor === this.value.length-1) return;
|
||||
var killamt = this.value.next('\n', this.cursor) - this.cursor;
|
||||
var killed = this.cut_span(this.cursor-1, this.cursor+killamt);
|
||||
this.killring.push(killed);
|
||||
};
|
||||
texteditor.inputs['C-k'].doc = "Kill from cursor to end of line.";
|
||||
|
||||
texteditor.inputs['M-k'] = function() {
|
||||
var prevn = this.value.prev('\n', this.cursor);
|
||||
var killamt = this.cursor - prevn;
|
||||
var killed = this.cut_span(prevn+1, prevn+killamt);
|
||||
this.killring.push(killed);
|
||||
this.to_line_start();
|
||||
};
|
||||
texteditor.inputs['M-k'].doc = "Kill entire line the cursor is on.";
|
||||
|
||||
texteditor.inputs['C-b'] = function() {
|
||||
this.cursor--;
|
||||
this.desired_inset = this.inset;
|
||||
};
|
||||
texteditor.inputs['C-b'].rep = true;
|
||||
texteditor.inputs['M-b'] = function() {
|
||||
this.cursor = this.prev_word(this.cursor-2);
|
||||
this.desired_inset = this.inset;
|
||||
};
|
||||
texteditor.inputs['M-b'].rep = true;
|
||||
|
||||
texteditor.inputs['C-f'] = function() {
|
||||
this.cursor++;
|
||||
this.desired_inset = this.inset;
|
||||
};
|
||||
texteditor.inputs['C-f'].rep = true;
|
||||
texteditor.inputs['M-f'] = function() {
|
||||
this.cursor = this.next_word(this.cursor);
|
||||
this.desired_inset = this.inset;
|
||||
};
|
||||
texteditor.inputs['M-f'].rep = true;
|
||||
|
||||
texteditor.inputs['C-p'] = function() {
|
||||
if (this.cursor === 0) return;
|
||||
this.desired_inset = Math.max(this.desired_inset, this.inset);
|
||||
this.cursor = this.prev_line(this.cursor);
|
||||
var newlinew = this.line_width(this.cursor);
|
||||
this.cursor += Math.min(this.desired_inset, newlinew);
|
||||
};
|
||||
texteditor.inputs['C-p'].rep = true;
|
||||
|
||||
texteditor.inputs['M-p'] = function() {
|
||||
while (this.line_blank(this.cursor))
|
||||
this.cursor = this.prev_line(this.cursor);
|
||||
|
||||
while (!this.line_blank(this.cursor))
|
||||
this.cursor = this.prev_line(this.cursor);
|
||||
};
|
||||
texteditor.inputs['M-p'].doc = "Go up to next line with text on it.";
|
||||
texteditor.inputs['M-p'].rep = true;
|
||||
|
||||
texteditor.inputs['C-n'] = function() {
|
||||
if (this.cursor === this.value.length-1) return;
|
||||
if (this.value.next('\n', this.cursor) === -1) {
|
||||
this.to_file_end();
|
||||
return;
|
||||
}
|
||||
|
||||
this.desired_inset = Math.max(this.desired_inset, this.inset);
|
||||
this.cursor = this.next_line(this.cursor);
|
||||
var newlinew = this.line_width(this.cursor);
|
||||
this.cursor += Math.min(this.desired_inset, newlinew);
|
||||
};
|
||||
texteditor.inputs['C-n'].rep = true;
|
||||
|
||||
texteditor.inputs['M-n'] = function() {
|
||||
while (this.line_blank(this.cursor))
|
||||
this.cursor = this.next_line(this.cursor);
|
||||
|
||||
while (!this.line_blank(this.cursor))
|
||||
this.cursor = this.next_line(this.cursor);
|
||||
};
|
||||
texteditor.inputs['M-n'].doc = "Go down to next line with text on it.";
|
||||
texteditor.inputs['M-n'].rep = true;
|
|
@ -5,7 +5,26 @@ out vec4 frag_color;
|
|||
|
||||
uniform sampler2D diffuse_texture;
|
||||
|
||||
float[] kernel = float[9](1.0/9.0,1.0/9.0,1.0/9.0,
|
||||
1.0/9.0,1.0/9.0,1.0/9.0,
|
||||
1.0/9.0,1.0/9.0,1.0/9.0);
|
||||
|
||||
void main()
|
||||
{
|
||||
frag_color = texture(diffuse_texture, TexCoords);
|
||||
return;
|
||||
|
||||
vec2 res = vec2(640,360);
|
||||
vec2 uv = gl_FragCoord.xy;
|
||||
vec2 screen = textureSize(diffuse_texture,0);
|
||||
vec3 acc = vec3(0);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
vec2 realRes = uv + vec2(i-1,j-1);
|
||||
acc += texture(diffuse_texture, realRes / res).rgb * kernel[i*3+j];
|
||||
}
|
||||
}
|
||||
|
||||
// frag_color = vec4(acc,1);
|
||||
}
|
||||
|
|
|
@ -12,11 +12,7 @@ uniform vec2 dimen;
|
|||
|
||||
void main()
|
||||
{
|
||||
// vec4 ipos = inverse(projection) * vec4(pos, 0.f, 1.f);
|
||||
apos = pos * dimen;
|
||||
// apos += offset;
|
||||
// apos = pos + offset;
|
||||
|
||||
apos = ((pos*0.5)*dimen) + offset;
|
||||
|
||||
gl_Position = vec4(pos, 0.f, 1.f);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue