many fixes to editor
This commit is contained in:
parent
32268fc25d
commit
403771d7f8
|
@ -216,6 +216,15 @@ The ur[fn::A German prefix meaning primitive, original, or earliest.] system is
|
||||||
|
|
||||||
When prosperon starts, it searches for urs by name. Any file ending in ".jso" or ".json" will be interpereted as an ur, with same named jso and json being applied as (text, config) for an ur. A jso or json alone also constitute an ur.
|
When prosperon starts, it searches for urs by name. Any file ending in ".jso" or ".json" will be interpereted as an ur, with same named jso and json being applied as (text, config) for an ur. A jso or json alone also constitute an ur.
|
||||||
|
|
||||||
|
An ur can also be defined by a json file. If an ur is found, it takes predecent over auto generated urs. The json of an ur looks like this:
|
||||||
|
|
||||||
|
| field | description |
|
||||||
|
|----|----|
|
||||||
|
| text | Path to a script file, or array of script files, to apply to the object |
|
||||||
|
| data | Path to a json file, or array of json files, to apply to the object |
|
||||||
|
|
||||||
|
Any ur file with this sort of json creates an ur which can be created in the game. A file named "box.ur" will be ingested and be available as "ur.box". When saving differences, it creates a json file with the same name as an ur (in this case, "box.json").
|
||||||
|
|
||||||
#+begin_scholium
|
#+begin_scholium
|
||||||
Create an ur from the *hello* files above, and then spawn it.
|
Create an ur from the *hello* files above, and then spawn it.
|
||||||
#+begin_src
|
#+begin_src
|
||||||
|
@ -225,6 +234,10 @@ Primum.spawn(ur.hello);
|
||||||
When creating an actor from source files, all of its setup must take place. In this example, the setup happens during *ur.create*, and spawning is simply a matter of prototyping it.
|
When creating an actor from source files, all of its setup must take place. In this example, the setup happens during *ur.create*, and spawning is simply a matter of prototyping it.
|
||||||
#+end_scholium
|
#+end_scholium
|
||||||
|
|
||||||
|
This method allows high composability of game objects.
|
||||||
|
|
||||||
|
If an entity is created without an ur, is ur is defined as its given text and data. It cannot be saved. It must be given a new ur name.
|
||||||
|
|
||||||
Each ur has the following fields.
|
Each ur has the following fields.
|
||||||
|
|
||||||
| field | description |
|
| field | description |
|
||||||
|
|
|
@ -882,6 +882,11 @@ Object.defineProperty(String.prototype, 'uc', { value: function() { return this.
|
||||||
Object.defineProperty(String.prototype, 'lc', {value:function() { return this.toLowerCase(); }});
|
Object.defineProperty(String.prototype, 'lc', {value:function() { return this.toLowerCase(); }});
|
||||||
|
|
||||||
/* ARRAY DEFS */
|
/* ARRAY DEFS */
|
||||||
|
Object.defineProperty(Array.prototype, 'aspect', {
|
||||||
|
value: function() {
|
||||||
|
return this.x/this.y;
|
||||||
|
}
|
||||||
|
});
|
||||||
Object.defineProperty(Array.prototype, 'copy', {
|
Object.defineProperty(Array.prototype, 'copy', {
|
||||||
value: function() {
|
value: function() {
|
||||||
var c = [];
|
var c = [];
|
||||||
|
|
|
@ -1,20 +1,35 @@
|
||||||
this.phys = physics.kinematic;
|
this.phys = physics.kinematic;
|
||||||
this.dir_view2world = function(dir) { return dir.scale(this.zoom); };
|
this.dir_view2world = function(dir) { return dir.scale(this.zoom); };
|
||||||
this.view2world = function(pos) {
|
this.view2world = function(pos) {
|
||||||
|
var useren = window.rendersize.scale(this.zoom);
|
||||||
|
if (window.mode === window.modetypes.stretch) {
|
||||||
pos = pos.scale([window.rendersize.x/window.size.x, window.rendersize.y/window.size.y]);
|
pos = pos.scale([window.rendersize.x/window.size.x, window.rendersize.y/window.size.y]);
|
||||||
pos = pos.sub(window.rendersize.scale(0.5));
|
pos = pos.sub(window.rendersize.scale(0.5));
|
||||||
pos = pos.scale(this.zoom);
|
pos = pos.scale(this.zoom);
|
||||||
pos = pos.add(this.pos);
|
pos = pos.add(this.pos);
|
||||||
|
}
|
||||||
|
if (window.mode === window.modetypes.full) {
|
||||||
|
pos = pos.sub(window.size.scale(0.5));
|
||||||
|
pos = pos.scale(this.zoom);
|
||||||
|
pos = pos.add(this.pos);
|
||||||
|
}
|
||||||
return pos;
|
return pos;
|
||||||
};
|
};
|
||||||
this.world2view = function(pos) {
|
this.world2view = function(pos) {
|
||||||
|
if (window.mode === window.modetypes.stretch) {
|
||||||
pos = pos.sub(this.pos);
|
pos = pos.sub(this.pos);
|
||||||
pos = pos.scale(1.0/this.zoom);
|
pos = pos.scale(1.0/this.zoom);
|
||||||
pos = pos.add(window.rendersize.scale(0.5));
|
pos = pos.add(window.rendersize.scale(0.5));
|
||||||
|
}
|
||||||
|
if (window.mode === window.modetypes.full) {
|
||||||
|
pos = pos.sub(this.pos);
|
||||||
|
pos = pos.scale(1/this.zoom);
|
||||||
|
pos = pos.add(window.size.scale(0.5));
|
||||||
|
}
|
||||||
return pos;
|
return pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.screenright = function() { return this.view2world(window.size).x; }
|
this.screenright = function() { return this.view2world(window.size).x; }
|
||||||
this.screenleft = function() { return this.pos.x - (window.rendersize.x/2); }
|
this.screenleft = function() { return this.view2world([0,0]).x; }
|
||||||
|
|
||||||
this.zoom = 1;
|
this.zoom = 1;
|
||||||
|
|
|
@ -425,7 +425,7 @@ component.polygon2d = Object.copy(collider2d, {
|
||||||
|
|
||||||
gizmo() {
|
gizmo() {
|
||||||
this.spoints().forEach(x => render.point(this.gameobject.this2screen(x), 3, Color.green));
|
this.spoints().forEach(x => render.point(this.gameobject.this2screen(x), 3, Color.green));
|
||||||
this.points.forEach((x,i)=>render.coordinate(this.gameobject.this2screen(x), i));
|
this.points.forEach((x,i)=>render.coordinate(this.gameobject.this2screen(x)));
|
||||||
},
|
},
|
||||||
|
|
||||||
pick(pos) {
|
pick(pos) {
|
||||||
|
@ -589,11 +589,11 @@ component.edge2d = Object.copy(collider2d, {
|
||||||
this.points.forEach((x,i) => render.coordinate(this.gameobject.this2screen(x)));
|
this.points.forEach((x,i) => render.coordinate(this.gameobject.this2screen(x)));
|
||||||
} else {
|
} else {
|
||||||
for (var i = 0; i < this.points.length; i += 3)
|
for (var i = 0; i < this.points.length; i += 3)
|
||||||
render.coordinate(this.gameobject.this2screen(this.points[i]), i, Color.teal);
|
render.coordinate(this.gameobject.this2screen(this.points[i]), 1, Color.teal);
|
||||||
|
|
||||||
for (var i = 1; i < this.points.length; i+=3) {
|
for (var i = 1; i < this.points.length; i+=3) {
|
||||||
render.coordinate(this.gameobject.this2screen(this.points[i]), i, Color.green);
|
render.coordinate(this.gameobject.this2screen(this.points[i]), 1, Color.green);
|
||||||
render.coordinate(this.gameobject.this2screen(this.points[i+1]), i+1, Color.green);
|
render.coordinate(this.gameobject.this2screen(this.points[i+1]), 1, Color.green);
|
||||||
render.line([this.gameobject.this2screen(this.points[i-1]), this.gameobject.this2screen(this.points[i])], Color.yellow);
|
render.line([this.gameobject.this2screen(this.points[i-1]), this.gameobject.this2screen(this.points[i])], Color.yellow);
|
||||||
render.line([this.gameobject.this2screen(this.points[i+1]), this.gameobject.this2screen(this.points[i+2])], Color.yellow);
|
render.line([this.gameobject.this2screen(this.points[i+1]), this.gameobject.this2screen(this.points[i+2])], Color.yellow);
|
||||||
}
|
}
|
||||||
|
@ -707,7 +707,6 @@ component.edge2d.impl = Object.mix(collider2d.impl, {
|
||||||
var bucket = component.edge2d;
|
var bucket = component.edge2d;
|
||||||
bucket.spoints.doc = "Returns the controls points after modifiers are applied, such as it being hollow or mirrored on its axises.";
|
bucket.spoints.doc = "Returns the controls points after modifiers are applied, such as it being hollow or mirrored on its axises.";
|
||||||
bucket.inputs = {};
|
bucket.inputs = {};
|
||||||
//bucket.inputs.post = function() { this.sync(); };
|
|
||||||
bucket.inputs.h = function() { this.hollow = !this.hollow; };
|
bucket.inputs.h = function() { this.hollow = !this.hollow; };
|
||||||
bucket.inputs.h.doc = "Toggle hollow.";
|
bucket.inputs.h.doc = "Toggle hollow.";
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
selectable
|
selectable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
window.mode = window.modetypes.full;
|
|
||||||
game.loadurs();
|
game.loadurs();
|
||||||
|
|
||||||
console.info(`window size: ${window.size}, render size: ${window.rendersize}`);
|
console.info(`window size: ${window.size}, render size: ${window.rendersize}`);
|
||||||
|
@ -11,6 +10,8 @@ console.info(`window size: ${window.size}, render size: ${window.rendersize}`);
|
||||||
player[0].control(debug);
|
player[0].control(debug);
|
||||||
Register.gui.register(debug.draw, debug);
|
Register.gui.register(debug.draw, debug);
|
||||||
|
|
||||||
|
var show_frame = true;
|
||||||
|
|
||||||
var editor = {
|
var editor = {
|
||||||
toString() { return "editor"; },
|
toString() { return "editor"; },
|
||||||
grid_size: 100,
|
grid_size: 100,
|
||||||
|
@ -38,8 +39,7 @@ var editor = {
|
||||||
return this.do_select(go);
|
return this.do_select(go);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Tries to select id */
|
do_select(obj) { /* select an object, if it is selectable given the current editor state */
|
||||||
do_select(obj) {
|
|
||||||
if (!obj) return;
|
if (!obj) return;
|
||||||
if (!obj._ed.selectable) return undefined;
|
if (!obj._ed.selectable) return undefined;
|
||||||
|
|
||||||
|
@ -394,13 +394,16 @@ var editor = {
|
||||||
|
|
||||||
gui() {
|
gui() {
|
||||||
/* Clean out killed objects */
|
/* Clean out killed objects */
|
||||||
|
if (show_frame)
|
||||||
|
render.line(shape.box(window.rendersize.x, window.rendersize.y).wrapped(1).map(p => game.camera.world2view(p)), Color.yellow);
|
||||||
|
|
||||||
render.text([0,0], game.camera.world2view([0,0]));
|
render.text([0,0], game.camera.world2view([0,0]));
|
||||||
|
|
||||||
render.text("WORKING LAYER: " + this.working_layer, [0,520]);
|
render.text("WORKING LAYER: " + this.working_layer, [0,520]);
|
||||||
render.text("MODE: " + this.edit_mode, [0,500]);
|
render.text("MODE: " + this.edit_mode, [0,500]);
|
||||||
|
|
||||||
if (this.comp_info && this.sel_comp)
|
if (this.comp_info && this.sel_comp)
|
||||||
render.text(Input.print_pawn_kbm(this.sel_comp,false), [100,700],1);
|
render.text(input.print_pawn_kbm(this.sel_comp,false), [100,700],1);
|
||||||
|
|
||||||
render.cross(editor.edit_level.screenpos(),3,Color.blue);
|
render.cross(editor.edit_level.screenpos(),3,Color.blue);
|
||||||
|
|
||||||
|
@ -530,7 +533,6 @@ var editor = {
|
||||||
var obj = editor.edit_level.spawn(mur);
|
var obj = editor.edit_level.spawn(mur);
|
||||||
obj.set_worldpos(input.mouse.worldpos());
|
obj.set_worldpos(input.mouse.worldpos());
|
||||||
this.selectlist = [obj];
|
this.selectlist = [obj];
|
||||||
console.warn(`made something and now the selected objects is ${this.selectlist.length} long.`);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
load_prev() {
|
load_prev() {
|
||||||
|
@ -567,7 +569,7 @@ var editor = {
|
||||||
ur[sub] = {
|
ur[sub] = {
|
||||||
name: sub,
|
name: sub,
|
||||||
data: file,
|
data: file,
|
||||||
proto: json.decode(json.encode(obj))
|
fresh: json.decode(json.encode(obj))
|
||||||
}
|
}
|
||||||
obj.ur = sub;
|
obj.ur = sub;
|
||||||
|
|
||||||
|
@ -667,7 +669,8 @@ editor.inputs.f9 = function() { os.capture( "capture.bmp", 0, 0, 500, 500); }
|
||||||
|
|
||||||
editor.inputs.release_post = function() {
|
editor.inputs.release_post = function() {
|
||||||
editor.snapshot();
|
editor.snapshot();
|
||||||
editor.edit_level.check_dirty();
|
|
||||||
|
editor.selectlist?.forEach(x => x.check_dirty());
|
||||||
|
|
||||||
/* snap all objects to be pixel perfect */
|
/* snap all objects to be pixel perfect */
|
||||||
game.all_objects(o => o.pos = o.pos.map(x => Math.round(x)), editor.edit_level);
|
game.all_objects(o => o.pos = o.pos.map(x => Math.round(x)), editor.edit_level);
|
||||||
|
@ -765,11 +768,11 @@ editor.inputs.m = function() {
|
||||||
};
|
};
|
||||||
editor.inputs.m.doc = "Mirror selected objects on the X axis.";
|
editor.inputs.m.doc = "Mirror selected objects on the X axis.";
|
||||||
|
|
||||||
|
|
||||||
editor.inputs.q = function() { editor.comp_info = !editor.comp_info; };
|
editor.inputs.q = function() { editor.comp_info = !editor.comp_info; };
|
||||||
editor.inputs.q.doc = "Toggle help for the selected component.";
|
editor.inputs.q.doc = "Toggle help for the selected component.";
|
||||||
|
|
||||||
editor.inputs.f = function() {
|
editor.inputs.f = function() {
|
||||||
|
return;
|
||||||
if (editor.selectlist.length === 0) return;
|
if (editor.selectlist.length === 0) return;
|
||||||
var bb = editor.selectlist[0].boundingbox();
|
var bb = editor.selectlist[0].boundingbox();
|
||||||
editor.selectlist.forEach(function(obj) { bb = bbox.expand(bb, obj.boundingbox()); });
|
editor.selectlist.forEach(function(obj) { bb = bbox.expand(bb, obj.boundingbox()); });
|
||||||
|
@ -787,6 +790,7 @@ editor.inputs['C-f'] = function() {
|
||||||
editor.inputs['C-f'].doc = "Tunnel into the selected level object to edit it.";
|
editor.inputs['C-f'].doc = "Tunnel into the selected level object to edit it.";
|
||||||
|
|
||||||
editor.inputs['C-F'] = function() {
|
editor.inputs['C-F'] = function() {
|
||||||
|
console.info("PRESSED C-F");
|
||||||
if (editor.edit_level.master === world) return;
|
if (editor.edit_level.master === world) return;
|
||||||
|
|
||||||
editor.edit_level = editor.edit_level.master;
|
editor.edit_level = editor.edit_level.master;
|
||||||
|
@ -901,14 +905,13 @@ editor.inputs['C-s'] = function() {
|
||||||
if (!tur.data) {
|
if (!tur.data) {
|
||||||
io.slurpwrite(tur.text.set_ext(".json"), json.encode(savejs,null,1));
|
io.slurpwrite(tur.text.set_ext(".json"), json.encode(savejs,null,1));
|
||||||
tur.data = tur.text.set_ext(".json");
|
tur.data = tur.text.set_ext(".json");
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
var oldjs = json.decode(io.slurp(tur.data));
|
var oldjs = json.decode(io.slurp(tur.data));
|
||||||
Object.merge(oldjs, savejs);
|
Object.merge(oldjs, savejs);
|
||||||
io.slurpwrite(tur.data, json.encode(oldjs,null,1));
|
io.slurpwrite(tur.data, json.encode(oldjs,null,1));
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.merge(tur.proto, savejs);
|
Object.merge(tur.fresh, savejs);
|
||||||
saveobj.check_dirty();
|
saveobj.check_dirty();
|
||||||
|
|
||||||
// Object.values(saveobj.objects).forEach(function(x) { x.check_dirty(); });
|
// Object.values(saveobj.objects).forEach(function(x) { x.check_dirty(); });
|
||||||
|
@ -1484,6 +1487,7 @@ var inputpanel = {
|
||||||
};
|
};
|
||||||
|
|
||||||
inputpanel.inputs = {};
|
inputpanel.inputs = {};
|
||||||
|
inputpanel.inputs.block = true;
|
||||||
|
|
||||||
inputpanel.inputs.post = function() { this.keycb(); }
|
inputpanel.inputs.post = function() { this.keycb(); }
|
||||||
|
|
||||||
|
|
|
@ -241,7 +241,7 @@ global.mixin("scripts/render");
|
||||||
global.mixin("scripts/debug");
|
global.mixin("scripts/debug");
|
||||||
|
|
||||||
var frame_t = profile.secs(profile.now());
|
var frame_t = profile.secs(profile.now());
|
||||||
var phys_step = 1/60;
|
var phys_step = 1/240;
|
||||||
|
|
||||||
var sim = {};
|
var sim = {};
|
||||||
sim.mode = "play";
|
sim.mode = "play";
|
||||||
|
@ -280,7 +280,6 @@ function process()
|
||||||
prosperon.update(dt*game.timescale);
|
prosperon.update(dt*game.timescale);
|
||||||
if (sim.mode === "step")
|
if (sim.mode === "step")
|
||||||
sim.pause();
|
sim.pause();
|
||||||
}
|
|
||||||
|
|
||||||
physlag += dt;
|
physlag += dt;
|
||||||
|
|
||||||
|
@ -289,6 +288,7 @@ function process()
|
||||||
prosperon.phys2d_step(phys_step*game.timescale);
|
prosperon.phys2d_step(phys_step*game.timescale);
|
||||||
prosperon.physupdate(phys_step*game.timescale);
|
prosperon.physupdate(phys_step*game.timescale);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!game.camera)
|
if (!game.camera)
|
||||||
prosperon.window_render(world, 1);
|
prosperon.window_render(world, 1);
|
||||||
|
@ -312,8 +312,6 @@ function process()
|
||||||
|
|
||||||
game.timescale = 1;
|
game.timescale = 1;
|
||||||
|
|
||||||
game.all_objects = function(fn, startobj) {
|
|
||||||
startobj ??= world;
|
|
||||||
var eachobj = function(obj,fn)
|
var eachobj = function(obj,fn)
|
||||||
{
|
{
|
||||||
fn(obj);
|
fn(obj);
|
||||||
|
@ -321,6 +319,8 @@ game.all_objects = function(fn, startobj) {
|
||||||
eachobj(obj.objects[o],fn);
|
eachobj(obj.objects[o],fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
game.all_objects = function(fn, startobj) {
|
||||||
|
startobj ??= world;
|
||||||
eachobj(startobj,fn);
|
eachobj(startobj,fn);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -529,11 +529,13 @@ var Event = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// window.rendersize is the resolution the game renders at
|
||||||
|
// window.size is the physical size of the window on the desktop
|
||||||
window.modetypes = {
|
window.modetypes = {
|
||||||
stretch: 0, // stretch to fill window
|
stretch: 0, // stretch render to fill window
|
||||||
keep: 1, // keep exact dimensions
|
keep: 1, // keep render exact dimensions, with no stretching
|
||||||
width: 2, // keep width
|
width: 2, // keep render at width
|
||||||
height: 3, // keep height
|
height: 3, // keep render at height
|
||||||
expand: 4, // expand width or height
|
expand: 4, // expand width or height
|
||||||
full: 5 // expand out beyond window
|
full: 5 // expand out beyond window
|
||||||
};
|
};
|
||||||
|
@ -546,8 +548,6 @@ global.mixin("scripts/spline");
|
||||||
global.mixin("scripts/components");
|
global.mixin("scripts/components");
|
||||||
|
|
||||||
window.doc = {};
|
window.doc = {};
|
||||||
window.doc.width = "Width of the game window.";
|
|
||||||
window.doc.height = "Height of the game window.";
|
|
||||||
window.doc.dimensions = "Window width and height packaged in an array [width,height]";
|
window.doc.dimensions = "Window width and height packaged in an array [width,height]";
|
||||||
window.doc.title = "Name in the title bar of the window.";
|
window.doc.title = "Name in the title bar of the window.";
|
||||||
window.doc.boundingbox = "Boundingbox of the window, with top and right being its height and width.";
|
window.doc.boundingbox = "Boundingbox of the window, with top and right being its height and width.";
|
||||||
|
@ -557,7 +557,6 @@ global.mixin("scripts/entity");
|
||||||
|
|
||||||
function world_start() {
|
function world_start() {
|
||||||
globalThis.world = os.make_gameobject();
|
globalThis.world = os.make_gameobject();
|
||||||
world.setref(world);
|
|
||||||
world.objects = {};
|
world.objects = {};
|
||||||
world.toString = function() { return "world"; };
|
world.toString = function() { return "world"; };
|
||||||
world.ur = "world";
|
world.ur = "world";
|
||||||
|
|
|
@ -10,8 +10,6 @@ function obj_unique_name(name, obj) {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
var urcache = {};
|
|
||||||
|
|
||||||
var gameobject_impl = {
|
var gameobject_impl = {
|
||||||
get pos() {
|
get pos() {
|
||||||
assert(this.master, `Entity ${this.toString()} has no master.`);
|
assert(this.master, `Entity ${this.toString()} has no master.`);
|
||||||
|
@ -74,7 +72,7 @@ var gameobject = {
|
||||||
this._ed.urdiff = this.json_obj();
|
this._ed.urdiff = this.json_obj();
|
||||||
this._ed.dirty = !Object.empty(this._ed.urdiff);
|
this._ed.dirty = !Object.empty(this._ed.urdiff);
|
||||||
return; // TODO: IMPLEMENT
|
return; // TODO: IMPLEMENT
|
||||||
var lur = ur[this.master.ur];
|
var lur = this.master.ur;
|
||||||
if (!lur) return;
|
if (!lur) return;
|
||||||
var lur = lur.objects[this.toString()];
|
var lur = lur.objects[this.toString()];
|
||||||
var d = ediff(this._ed.urdiff, lur);
|
var d = ediff(this._ed.urdiff, lur);
|
||||||
|
@ -93,8 +91,9 @@ var gameobject = {
|
||||||
},
|
},
|
||||||
|
|
||||||
urstr() {
|
urstr() {
|
||||||
if (this._ed.dirty) return "*" + this.ur;
|
var str = this.ur.name;
|
||||||
return this.ur;
|
if (this._ed.dirty) str = "*" + str;
|
||||||
|
return str;
|
||||||
},
|
},
|
||||||
|
|
||||||
full_path() {
|
full_path() {
|
||||||
|
@ -213,11 +212,7 @@ var gameobject = {
|
||||||
},
|
},
|
||||||
|
|
||||||
cry(file) {
|
cry(file) {
|
||||||
this.crying = audio.play(file, audio.bus.sfx);
|
return audio.cry(file);
|
||||||
var killfn = () => { this.crying = undefined;
|
|
||||||
console.warn("killed"); }
|
|
||||||
this.crying.hook = killfn;
|
|
||||||
return killfn;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
gscale() { return this.scale; },
|
gscale() { return this.scale; },
|
||||||
|
@ -239,7 +234,7 @@ var gameobject = {
|
||||||
worldangle() { return this.angle; },
|
worldangle() { return this.angle; },
|
||||||
sworldangle(x) { this.angle = x; },
|
sworldangle(x) { this.angle = x; },
|
||||||
|
|
||||||
get_ur() { return urcache[this.ur]; },
|
get_ur() { return this.ur; },
|
||||||
|
|
||||||
/* spawn an entity
|
/* spawn an entity
|
||||||
text can be:
|
text can be:
|
||||||
|
@ -250,24 +245,33 @@ var gameobject = {
|
||||||
spawn(text, config, callback) {
|
spawn(text, config, callback) {
|
||||||
var ent = os.make_gameobject();
|
var ent = os.make_gameobject();
|
||||||
ent.guid = prosperon.guid();
|
ent.guid = prosperon.guid();
|
||||||
ent.setref(ent);
|
|
||||||
ent.components = {};
|
ent.components = {};
|
||||||
ent.objects = {};
|
ent.objects = {};
|
||||||
ent.timers = [];
|
ent.timers = [];
|
||||||
|
|
||||||
if (typeof text === 'object' && text) // assume it's an ur
|
if (typeof text === 'object' && text) // assume it's an ur
|
||||||
{
|
ent.ur = text;
|
||||||
config = text.data;
|
else
|
||||||
ent.ur = text.name;
|
ent.ur = getur(text, config);
|
||||||
text = text.text;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (text)
|
text = ent.ur.text;
|
||||||
|
config = [ent.ur.data, config];
|
||||||
|
|
||||||
|
if (typeof text === 'string')
|
||||||
use(text, ent);
|
use(text, ent);
|
||||||
if (config)
|
else if (Array.isArray(text))
|
||||||
Object.assign(ent, json.decode(io.slurp(config)));
|
text.forEach(path => use(path,ent));
|
||||||
|
|
||||||
|
if (typeof config === 'string')
|
||||||
|
Object.assign(ent, json.decode(Resources.replstrs(config)));
|
||||||
|
else if (Array.isArray(config))
|
||||||
|
config.forEach(function(path) {
|
||||||
|
if (typeof path === 'string')
|
||||||
|
Object.assign(ent, json.decode(Resources.replstrs(path)));
|
||||||
|
else if (typeof path === 'object')
|
||||||
|
Object.assign(ent,path);
|
||||||
|
});
|
||||||
|
|
||||||
ent.ur ??= text + "+" + config;
|
|
||||||
ent.reparent(this);
|
ent.reparent(this);
|
||||||
|
|
||||||
for (var [prop, p] of Object.entries(ent)) {
|
for (var [prop, p] of Object.entries(ent)) {
|
||||||
|
@ -296,8 +300,7 @@ var gameobject = {
|
||||||
selectable: true,
|
selectable: true,
|
||||||
dirty: false,
|
dirty: false,
|
||||||
inst: false,
|
inst: false,
|
||||||
urdiff: {},
|
urdiff: {}
|
||||||
fresh: json.decode(json.encode(ent)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.hide(ent, '_ed');
|
Object.hide(ent, '_ed');
|
||||||
|
@ -308,12 +311,10 @@ var gameobject = {
|
||||||
var o = ent.objects;
|
var o = ent.objects;
|
||||||
delete ent.objects;
|
delete ent.objects;
|
||||||
for (var i in o) {
|
for (var i in o) {
|
||||||
console.info(`MAKING ${i}`);
|
var newur = o[i].ur;
|
||||||
var n = ent.spawn(ur[o[i].ur]);
|
|
||||||
ent.rename_obj(n.toString(), i);
|
|
||||||
delete o[i].ur;
|
delete o[i].ur;
|
||||||
Object.assign(n, o[i]);
|
var n = ent.spawn(ur[newur], o[i]);
|
||||||
n.sync();
|
ent.rename_obj(n.toString(), i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,6 +322,8 @@ var gameobject = {
|
||||||
|
|
||||||
if (callback) callback(ent);
|
if (callback) callback(ent);
|
||||||
|
|
||||||
|
ent.ur.fresh ??= json.decode(json.encode(ent));
|
||||||
|
|
||||||
return ent;
|
return ent;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -349,7 +352,7 @@ var gameobject = {
|
||||||
return t;
|
return t;
|
||||||
};
|
};
|
||||||
|
|
||||||
var name = unique_name(Object.keys(parent.objects), this.ur);
|
var name = unique_name(Object.keys(parent.objects), this.ur.name);
|
||||||
|
|
||||||
parent.objects[name] = this;
|
parent.objects[name] = this;
|
||||||
parent[name] = this;
|
parent[name] = this;
|
||||||
|
@ -446,7 +449,7 @@ var gameobject = {
|
||||||
|
|
||||||
/* The unique components of this object. Its diff. */
|
/* The unique components of this object. Its diff. */
|
||||||
json_obj() {
|
json_obj() {
|
||||||
var fresh = this._ed.fresh;
|
var fresh = this.ur.fresh;
|
||||||
var thiso = json.decode(json.encode(this)); // TODO: SLOW. Used to ignore properties in toJSON of components.
|
var thiso = json.decode(json.encode(this)); // TODO: SLOW. Used to ignore properties in toJSON of components.
|
||||||
var d = ediff(thiso, fresh);
|
var d = ediff(thiso, fresh);
|
||||||
|
|
||||||
|
@ -473,7 +476,7 @@ var gameobject = {
|
||||||
/* The object needed to store an object as an instance of a master */
|
/* The object needed to store an object as an instance of a master */
|
||||||
instance_obj() {
|
instance_obj() {
|
||||||
var t = this.transform();
|
var t = this.transform();
|
||||||
t.ur = this.ur;
|
t.ur = this.ur.name;
|
||||||
return t;
|
return t;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -484,7 +487,7 @@ var gameobject = {
|
||||||
t.angle = Math.places(this.angle, 4);
|
t.angle = Math.places(this.angle, 4);
|
||||||
if (t.angle === 0) delete t.angle;
|
if (t.angle === 0) delete t.angle;
|
||||||
t.scale = this.scale;
|
t.scale = this.scale;
|
||||||
t.scale = t.scale.map((x, i) => x / this._ed.fresh.scale[i]);
|
t.scale = t.scale.map((x, i) => x / this.ur.fresh.scale[i]);
|
||||||
t.scale = t.scale.map(x => Math.places(x, 3));
|
t.scale = t.scale.map(x => Math.places(x, 3));
|
||||||
if (t.scale.every(x => x === 1)) delete t.scale;
|
if (t.scale.every(x => x === 1)) delete t.scale;
|
||||||
return t;
|
return t;
|
||||||
|
@ -499,7 +502,7 @@ var gameobject = {
|
||||||
},
|
},
|
||||||
|
|
||||||
dup(diff) {
|
dup(diff) {
|
||||||
var n = this.master.spawn(this.__proto__);
|
var n = this.master.spawn(this.ur);
|
||||||
Object.totalmerge(n, this.instance_obj());
|
Object.totalmerge(n, this.instance_obj());
|
||||||
return n;
|
return n;
|
||||||
},
|
},
|
||||||
|
@ -592,9 +595,8 @@ var gameobject = {
|
||||||
function go_init() {
|
function go_init() {
|
||||||
var gop = os.make_gameobject().__proto__;
|
var gop = os.make_gameobject().__proto__;
|
||||||
Object.mixin(gop, gameobject);
|
Object.mixin(gop, gameobject);
|
||||||
var gsync = gop.sync;
|
|
||||||
gop.sync = function() {
|
gop.sync = function() {
|
||||||
gsync.call(this);
|
this.selfsync();
|
||||||
this.components.forEach(function(x) { x.sync?.(); });
|
this.components.forEach(function(x) { x.sync?.(); });
|
||||||
this.objects.forEach(function(x) { x.sync?.(); });
|
this.objects.forEach(function(x) { x.sync?.(); });
|
||||||
}
|
}
|
||||||
|
@ -734,10 +736,33 @@ function file2fqn(file) {
|
||||||
return ur[fqn];
|
return ur[fqn];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var getur = function(text, data)
|
||||||
|
{
|
||||||
|
var urstr = text + "+" + data;
|
||||||
|
if (!ur[urstr]) {
|
||||||
|
ur[urstr] = {
|
||||||
|
name: urstr,
|
||||||
|
text: text,
|
||||||
|
data: data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ur[urstr];
|
||||||
|
}
|
||||||
|
|
||||||
game.loadurs = function() {
|
game.loadurs = function() {
|
||||||
ur = {};
|
ur = {};
|
||||||
ur._list = [];
|
ur._list = [];
|
||||||
/* FIND ALL URS IN A PROJECT */
|
/* FIND ALL URS IN A PROJECT */
|
||||||
|
for (var file of io.glob("**.ur")) {
|
||||||
|
var urname = file.name();
|
||||||
|
if (ur[urname]) {
|
||||||
|
console.warn(`Tried to make another ur with the name ${urname} from ${file}, but it already exists.`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var urjson = json.decode(io.slurp(file));
|
||||||
|
urjson.name = urname;
|
||||||
|
ur[urname] = urjson;
|
||||||
|
}
|
||||||
for (var file of io.glob("**.jso")) {
|
for (var file of io.glob("**.jso")) {
|
||||||
if (file[0] === '.' || file[0] === '_') continue;
|
if (file[0] === '.' || file[0] === '_') continue;
|
||||||
var topur = file2fqn(file);
|
var topur = file2fqn(file);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
var audio = {};
|
var audio = {};
|
||||||
|
var cries = {};
|
||||||
|
|
||||||
audio.samplerate = dspsound.samplerate();
|
audio.samplerate = dspsound.samplerate();
|
||||||
audio.play = function(file,bus) {
|
audio.play = function(file,bus) {
|
||||||
|
@ -10,6 +11,7 @@ audio.play = function(file,bus) {
|
||||||
}
|
}
|
||||||
var src = audio.dsp.source(file);
|
var src = audio.dsp.source(file);
|
||||||
src.plugin(bus);
|
src.plugin(bus);
|
||||||
|
src.guid = prosperon.guid();
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
audio.bus = {};
|
audio.bus = {};
|
||||||
|
@ -17,15 +19,24 @@ audio.bus.master = dspsound.master();
|
||||||
audio.dsp = {};
|
audio.dsp = {};
|
||||||
audio.dsp = dspsound;
|
audio.dsp = dspsound;
|
||||||
|
|
||||||
var cries = [];
|
|
||||||
audio.cry = function(file)
|
audio.cry = function(file)
|
||||||
{
|
{
|
||||||
var player = audio.play(file);
|
var player = audio.play(file);
|
||||||
cries.push(player);
|
player.guid = prosperon.guid();
|
||||||
var hook = function() { console.warn("ENDED SOUND!!!!"); cries.remove(player); player = undefined; hook = undefined;}
|
cries[player.guid] = player;
|
||||||
player.hook = hook;
|
player.ended = function() { delete cries[player.guid]; player = undefined; }
|
||||||
|
return player.ended;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var killer = Register.appupdate.register(function() {
|
||||||
|
for (var i in cries) {
|
||||||
|
var cry = cries[i];
|
||||||
|
if (!cry.ended) continue;
|
||||||
|
if (cry.frame < cry.lastframe || cry.frame === cry.lastframe) cry.ended();
|
||||||
|
cry.lastframe = cry.frame;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var song;
|
var song;
|
||||||
|
|
||||||
audio.music = function(file, fade) {
|
audio.music = function(file, fade) {
|
||||||
|
|
|
@ -193,9 +193,13 @@ Cmdline.register_order("edit", function() {
|
||||||
|
|
||||||
window.size = [1280, 720];
|
window.size = [1280, 720];
|
||||||
|
|
||||||
|
window.mode = window.modetypes.full;
|
||||||
|
sim.pause();
|
||||||
|
|
||||||
game.engine_start(function() {
|
game.engine_start(function() {
|
||||||
global.mixin("scripts/editor.js");
|
global.mixin("scripts/editor.js");
|
||||||
use("editorconfig.js");
|
use("editorconfig.js");
|
||||||
|
use("config.js");
|
||||||
editor.enter_editor();
|
editor.enter_editor();
|
||||||
});
|
});
|
||||||
}, "Edit the project in this folder. Give it the name of an UR to edit that specific object.", "?UR?");
|
}, "Edit the project in this folder. Give it the name of an UR to edit that specific object.", "?UR?");
|
||||||
|
|
|
@ -530,7 +530,6 @@ int shape_get_sensor(struct phys2d_shape *shape) {
|
||||||
if (!shape->shape) {
|
if (!shape->shape) {
|
||||||
struct phys2d_edge *edge = shape->data;
|
struct phys2d_edge *edge = shape->data;
|
||||||
if (arrlen(edge->shapes) > 0) return cpShapeGetSensor(edge->shapes[0]);
|
if (arrlen(edge->shapes) > 0) return cpShapeGetSensor(edge->shapes[0]);
|
||||||
YughWarn("Attempted to get the sensor of an edge with no shapes. It has %d points.", arrlen(edge->points));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -244,7 +244,7 @@ void text_flush(HMM_Mat4 *proj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgba color) {
|
void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgba color) {
|
||||||
if (curchar+1 >= max_chars)
|
if (curchar-10 >= max_chars)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct rgba colorbox = {0,0,0,255};
|
struct rgba colorbox = {0,0,0,255};
|
||||||
|
|
|
@ -61,10 +61,6 @@ const char *js2str(JSValue v) {
|
||||||
return JS_ToCString(js, v);
|
return JS_ToCString(js, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* support functions for these macros when they involve a JSValue */
|
|
||||||
JSValue js2JSValue(JSValue v) { return v; }
|
|
||||||
JSValue JSValue2js(JSValue v) { return v; }
|
|
||||||
|
|
||||||
QJSCLASS(gameobject)
|
QJSCLASS(gameobject)
|
||||||
QJSCLASS(emitter)
|
QJSCLASS(emitter)
|
||||||
QJSCLASS(dsp_node)
|
QJSCLASS(dsp_node)
|
||||||
|
@ -1082,14 +1078,12 @@ static const JSCFunctionListEntry js_dsp_node_funcs[] = {
|
||||||
JSC_GETSET(sound, loop, boolean)
|
JSC_GETSET(sound, loop, boolean)
|
||||||
JSC_GETSET(sound, timescale, number)
|
JSC_GETSET(sound, timescale, number)
|
||||||
JSC_GETSET(sound, frame, number)
|
JSC_GETSET(sound, frame, number)
|
||||||
JSC_GETSET_HOOK(sound, hook)
|
|
||||||
JSC_CCALL(sound_frames, return number2js(js2sound(this)->data->frames))
|
JSC_CCALL(sound_frames, return number2js(js2sound(this)->data->frames))
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_sound_funcs[] = {
|
static const JSCFunctionListEntry js_sound_funcs[] = {
|
||||||
CGETSET_ADD(sound, loop),
|
CGETSET_ADD(sound, loop),
|
||||||
CGETSET_ADD(sound, timescale),
|
CGETSET_ADD(sound, timescale),
|
||||||
CGETSET_ADD(sound, frame),
|
CGETSET_ADD(sound, frame),
|
||||||
CGETSET_ADD(sound, hook),
|
|
||||||
MIST_FUNC_DEF(sound, frames, 0),
|
MIST_FUNC_DEF(sound, frames, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1164,8 +1158,7 @@ JSC_GETSET(gameobject, maxvelocity, number)
|
||||||
JSC_GETSET(gameobject, maxangularvelocity, number)
|
JSC_GETSET(gameobject, maxangularvelocity, number)
|
||||||
JSC_GETSET(gameobject, warp_filter, bitmask)
|
JSC_GETSET(gameobject, warp_filter, bitmask)
|
||||||
JSC_GETSET(gameobject, drawlayer, number)
|
JSC_GETSET(gameobject, drawlayer, number)
|
||||||
JSC_CCALL(gameobject_setref, js2gameobject(this)->ref = argv[0]);
|
JSC_CCALL(gameobject_selfsync, gameobject_apply(js2gameobject(this)))
|
||||||
JSC_CCALL(gameobject_sync, gameobject_apply(js2gameobject(this)))
|
|
||||||
JSC_CCALL(gameobject_in_air, return boolean2js(phys2d_in_air(js2gameobject(this)->body)))
|
JSC_CCALL(gameobject_in_air, return boolean2js(phys2d_in_air(js2gameobject(this)->body)))
|
||||||
JSC_CCALL(gameobject_world2this, return vec22js(world2go(js2gameobject(this), js2vec2(argv[0]))))
|
JSC_CCALL(gameobject_world2this, return vec22js(world2go(js2gameobject(this), js2vec2(argv[0]))))
|
||||||
JSC_CCALL(gameobject_this2world, return vec22js(go2world(js2gameobject(this), js2vec2(argv[0]))))
|
JSC_CCALL(gameobject_this2world, return vec22js(go2world(js2gameobject(this), js2vec2(argv[0]))))
|
||||||
|
@ -1200,8 +1193,7 @@ static const JSCFunctionListEntry js_gameobject_funcs[] = {
|
||||||
MIST_FUNC_DEF(gameobject, this2world, 1),
|
MIST_FUNC_DEF(gameobject, this2world, 1),
|
||||||
MIST_FUNC_DEF(gameobject, dir_world2this, 1),
|
MIST_FUNC_DEF(gameobject, dir_world2this, 1),
|
||||||
MIST_FUNC_DEF(gameobject, dir_this2world, 1),
|
MIST_FUNC_DEF(gameobject, dir_this2world, 1),
|
||||||
MIST_FUNC_DEF(gameobject,setref,1),
|
MIST_FUNC_DEF(gameobject, selfsync, 0),
|
||||||
MIST_FUNC_DEF(gameobject, sync, 0),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JSC_CCALL(joint_pin, return constraint2js(constraint_make(cpPinJointNew(js2gameobject(argv[0])->body, js2gameobject(argv[1])->body, cpvzero,cpvzero))))
|
JSC_CCALL(joint_pin, return constraint2js(constraint_make(cpPinJointNew(js2gameobject(argv[0])->body, js2gameobject(argv[1])->body, cpvzero,cpvzero))))
|
||||||
|
@ -1454,6 +1446,7 @@ JSC_CCALL(os_sprite,
|
||||||
JSC_CCALL(os_make_gameobject,
|
JSC_CCALL(os_make_gameobject,
|
||||||
ret = gameobject2js(MakeGameobject());
|
ret = gameobject2js(MakeGameobject());
|
||||||
JS_SetPropertyFunctionList(js, ret, js_gameobject_funcs, countof(js_gameobject_funcs));
|
JS_SetPropertyFunctionList(js, ret, js_gameobject_funcs, countof(js_gameobject_funcs));
|
||||||
|
js2gameobject(ret)->ref = ret;
|
||||||
return ret;
|
return ret;
|
||||||
)
|
)
|
||||||
JSC_CCALL(os_make_circle2d,
|
JSC_CCALL(os_make_circle2d,
|
||||||
|
|
|
@ -278,13 +278,11 @@ void sound_fillbuf(struct sound *s, soundbyte *buf, int n) {
|
||||||
if(end) {
|
if(end) {
|
||||||
if (s->loop)
|
if (s->loop)
|
||||||
s->frame = 0;
|
s->frame = 0;
|
||||||
script_call_sym(s->hook,0,NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_source(struct sound *s)
|
void free_source(struct sound *s)
|
||||||
{
|
{
|
||||||
JS_FreeValue(js, s->hook);
|
|
||||||
src_delete(s->src);
|
src_delete(s->src);
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
|
@ -305,7 +303,6 @@ struct dsp_node *dsp_source(const char *path)
|
||||||
self->loop = false;
|
self->loop = false;
|
||||||
self->src = src_callback_new(src_cb, SRC_SINC_MEDIUM_QUALITY, 2, NULL, self);
|
self->src = src_callback_new(src_cb, SRC_SINC_MEDIUM_QUALITY, 2, NULL, self);
|
||||||
self->timescale = 1;
|
self->timescale = 1;
|
||||||
self->hook = JS_UNDEFINED;
|
|
||||||
dsp_node *n = make_node(self, sound_fillbuf, free_source);
|
dsp_node *n = make_node(self, sound_fillbuf, free_source);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ typedef struct sound {
|
||||||
int loop;
|
int loop;
|
||||||
float timescale;
|
float timescale;
|
||||||
SRC_STATE *src;
|
SRC_STATE *src;
|
||||||
JSValue hook;
|
|
||||||
} sound;
|
} sound;
|
||||||
|
|
||||||
/* Represents a sound file source, fulled loaded*/
|
/* Represents a sound file source, fulled loaded*/
|
||||||
|
|
2
source/engine/thirdparty/quickjs/quickjs.c
vendored
2
source/engine/thirdparty/quickjs/quickjs.c
vendored
|
@ -112,7 +112,7 @@ void quickjs_set_dumpout(FILE *f)
|
||||||
//#define DUMP_READ_OBJECT
|
//#define DUMP_READ_OBJECT
|
||||||
|
|
||||||
#ifdef DUMP
|
#ifdef DUMP
|
||||||
#define DUMP_FREE
|
//#define DUMP_FREE
|
||||||
#define DUMP_MEM
|
#define DUMP_MEM
|
||||||
#define DUMP_CLOSURE
|
#define DUMP_CLOSURE
|
||||||
#define DUMP_GC
|
#define DUMP_GC
|
||||||
|
|
Loading…
Reference in a new issue