instance saving
This commit is contained in:
parent
264a365a1a
commit
0fcc2286fa
2
Makefile
2
Makefile
|
@ -179,7 +179,7 @@ api.md: $(DOCMD)
|
||||||
@(echo "# API"; cat $^) > $@
|
@(echo "# API"; cat $^) > $@
|
||||||
@rm $^
|
@rm $^
|
||||||
|
|
||||||
INPUT = editor component.sprite component.polygon2d component.edge2d component.circle2d
|
INPUT = editor DebugControls component.sprite component.polygon2d component.edge2d component.circle2d
|
||||||
INPUTMD := $(addsuffix .input.md, $(INPUT))
|
INPUTMD := $(addsuffix .input.md, $(INPUT))
|
||||||
input.md: $(INPUTMD)
|
input.md: $(INPUTMD)
|
||||||
@(echo "# Input"; cat $^) > $@
|
@(echo "# Input"; cat $^) > $@
|
||||||
|
|
192
docs/editor.md
192
docs/editor.md
|
@ -1,185 +1,43 @@
|
||||||
# Yugine Editor
|
# Primum Editor
|
||||||
|
|
||||||
The main editor view is made up of objects. Each object can have a
|
The main editor view is made up of objects. Each object can have a number of components attached to it. When an object is selected, its name, position, and list of components are listed.
|
||||||
number of components attached to it. When an object is selected, its
|
|
||||||
name, position, and list of components are listed.
|
|
||||||
|
|
||||||
The editor edits either entities or components. When it is started, there is no edited level.
|
In addition, a window showing each entity underneath that entity are shown.
|
||||||
|
|
||||||
## Basic controls
|
## The desktop
|
||||||
|Ctrl-Z|Undo|
|
|
||||||
|Ctrl-Shift-Z|Redo|
|
|
||||||
|Ctrl-A|Select all|
|
|
||||||
|Ctrl-S|Save|
|
|
||||||
|Ctrl-N|New|
|
|
||||||
|Ctrl-O|Open level|
|
|
||||||
|Ctrl-X|Cut|
|
|
||||||
|Ctrl-C|Copy|
|
|
||||||
|Ctrl-V|Paste|
|
|
||||||
|Alt-O|Add level to current level|
|
|
||||||
|Alt-A|or Alt-P Add a prefab|
|
|
||||||
|Ctrl-I|Objects on the level|
|
|
||||||
|Ctrl-E|Asset viewer. When on a component like a sprite, serves to select that sprite's texture|
|
|
||||||
|Ctrl-[|Downsize grid|
|
|
||||||
|Ctrl-]|Upsize grid|
|
|
||||||
|Backtick|REPL|
|
|
||||||
|Ctrl-[1-9]|to set camera positions|
|
|
||||||
|[1-9]|to recall camera positions|
|
|
||||||
|0|Set camera to home view|
|
|
||||||
|ESC|quit|
|
|
||||||
|Alt-1|Normal view|
|
|
||||||
|Alt-2|Wireframe view|
|
|
||||||
|Shift-Middle|Set editor cursor to mouse position (Cursor affects how objects rotate)|
|
|
||||||
|Shift-Ctrl-Middle|Set cursor to object selection|
|
|
||||||
|Shift-Right|Remove cursor|
|
|
||||||
|
|
||||||
## Editor Mode select
|
The desktop is the topmost object that exists in the editor. Instead of editing specific files, you simply load them into your desktop, and go from there. This makes it easier to see two different entities simultaneously so you can ensure changes to one are congruous with the vision for the others.
|
||||||
|
|
||||||
|Alt-F1|Basic mode|
|
## Ur-types
|
||||||
|Alt-F2|Brush mode|
|
|
||||||
- Clicking will place what is on clipboard
|
|
||||||
|
|
||||||
## Object controls
|
Ur-types are what are loaded into the game world. They are templates for creating entities.
|
||||||
|
|
||||||
|G|Translate|
|
## *'s and %'s
|
||||||
|Alt-G|Snap objects to cursor|
|
|
||||||
|S|Scale|
|
|
||||||
|R|Rotate|
|
|
||||||
|Ctrl-P|Save object changes to prefab|
|
|
||||||
|Ctrl-shift-P|Save object changes as a unique prefab ("Parent")|
|
|
||||||
|Ctrl-shift-T|Save object changes to a side prefab ("Type")|
|
|
||||||
|Ctrl-J|Bake name to expose to level script|
|
|
||||||
|Alt-J|Remove baked name|
|
|
||||||
|Ctrl-Y|Show obj chain|
|
|
||||||
|Alt-Y|Start prototype explorer|
|
|
||||||
|Ctrl-U|Revert object or component to match prototype|
|
|
||||||
|Alt-U|Make object unique. If a level, allows setting of internal object position and rotation.|
|
|
||||||
|Ctrl-shift-G|Save group as a level|
|
|
||||||
|Arrows|Translate 1 px|
|
|
||||||
|Shift-Arrows|Translate 10 px|
|
|
||||||
|Tab|Select component|
|
|
||||||
|F|Zoom to object(s)|
|
|
||||||
|Ctrl-F|Focus on a selected sublevel. Edit and save it in place.|
|
|
||||||
|Ctrl-Shift-F|Go up one level in the editing chain.|
|
|
||||||
|M|Flip horizontally|
|
|
||||||
|Ctrl-M|Flip vertically|
|
|
||||||
|Ctrl-D|Duplicate|
|
|
||||||
|H|Hide|
|
|
||||||
|Ctrl-H|Unhide all|
|
|
||||||
|T|Lock|
|
|
||||||
|Alt-T|Unlock all|
|
|
||||||
|Q|Toggle component help|
|
|
||||||
|Ctrl-Shift-Alt-Click|Set object center|
|
|
||||||
|
|
||||||
## Mouse controls
|
When a '*' is seen next to an entity's name, that means it is altered compared to its ur-type and is unsaved. There are a number of ways to take care of a '*'. If you do not do one of the below, something on the entity will be lost.
|
||||||
|
|
||||||
|Left|Select|
|
- Changes can be saved to the ur-type. This makes all other entities derived from the ur-type change.
|
||||||
|Middle|Quick grab|
|
- Changes can be saved as a sub ur-type. This creates a brand new type that can then be reused over and over again.
|
||||||
|Right|Unselect|
|
- Changes can be saved by saving the containing ur-type. Ur-types remember variances in the entities it 'owns'.
|
||||||
|
|
||||||
## Level controls
|
When an entity is different from its ur-type, but the variance is saved due to its container, its name is preceded by a '%'.
|
||||||
|Ctrl-L|Open level script|
|
|
||||||
|
|
||||||
## Game controls
|
The function 'revert()' can be called on any entity to make it like its ur-type again.
|
||||||
|F1|Debug draw|
|
|
||||||
|F2|Config menu|
|
|
||||||
|F3|Show bounding boxes|
|
|
||||||
|F4|Show gizmos|
|
|
||||||
|F5|Start|
|
|
||||||
|F6|Pause|
|
|
||||||
|F7|Stop|
|
|
||||||
|F10|Toggle slow motion|
|
|
||||||
|
|
||||||
== Components
|
## Levels?
|
||||||
Components all have their own set of controls. Many act similar to
|
|
||||||
objects. If a component has a position attribute, it will react as
|
|
||||||
expected to object grabbing; same with scaling, rotation, and so on.
|
|
||||||
|
|
||||||
If a component uses an asset, the asset viewer will serve to pick new
|
The concept of a 'level', a collection of spawned entities, is handled simply by creating sub ur-types of an empty entity.
|
||||||
assets for it.
|
|
||||||
|
|
||||||
## Spline controls
|
## Editing level, ur-types, parents, children, etc
|
||||||
|Ctrl-click|Add a point|
|
|
||||||
|Shift-click|remove a point|
|
|
||||||
|+,-|Increase or decrease spline segments|
|
|
||||||
|Ctrl-+,-|Increase or decrease spline degrees. Put this to 1 for the spline to go point to point|
|
|
||||||
|Alt-B,V|Increase or decrease spline thickness|
|
|
||||||
|
|
||||||
.Collider controls
|
lvl1
|
||||||
|Alt-S|Toggle sensor|
|
tablebase
|
||||||
|
%flipper
|
||||||
|
|
||||||
## Yugine Programming
|
In this case, tablebase is saving a modified flipper.
|
||||||
|
|
||||||
### Object functions
|
lvl1
|
||||||
|
%tablebase
|
||||||
|
%flipper
|
||||||
|
|
||||||
* start(): Called when the object is created, before the first update is ran
|
This is ambiguous. lvl1 could be storing the flipper's diff, or tablebase could be. Additionally, tablebase could have a unique flipper, and then lvl1 also alters it.
|
||||||
* update(dt): Called once per frame
|
|
||||||
* physupdate(dt): Called once per physics calculation
|
|
||||||
* stop(): Called when the object is killed
|
|
||||||
* collide(hit): Called when this object collides with another. If on a collider, specific to that collider
|
|
||||||
- hit.hit: Gameobject ID of what's being hit
|
|
||||||
- hit.velocity: Velocity of impact
|
|
||||||
- hit.normal: Normal of impact
|
|
||||||
|
|
||||||
### Colliders
|
|
||||||
Colliders visually look different based on their status. Objects can
|
|
||||||
be in one of three states
|
|
||||||
|
|
||||||
- Dynamic: respond to physics
|
|
||||||
- Kinematic: modeled with infinite momentum. An "unstoppable force"
|
|
||||||
controlled by a user.
|
|
||||||
- Static: modeled with infinite mass. An "immovable object" that
|
|
||||||
shouldn't move.
|
|
||||||
|
|
||||||
Objects can then have colliders on them, each collider being a sensor,
|
|
||||||
or solid. Sensors respond to collision signals, while solid ones also
|
|
||||||
do not let objects through.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Input
|
|
||||||
Input works by adding functions to an object, and then "controlling"
|
|
||||||
them. The format for a function is "input_[key]_[action]". [Action]
|
|
||||||
can be any of
|
|
||||||
|
|
||||||
- down: Called once per frame the key is down
|
|
||||||
- pressed: Called when the key is pressed
|
|
||||||
- released: called when the key is released
|
|
||||||
|
|
||||||
For example, "input_p_pressed()" will be called when p is pressed, and not again
|
|
||||||
until it is released and pressed again.
|
|
||||||
|
|
||||||
### Your game
|
|
||||||
|
|
||||||
When the engine runs, it executes config.js, and then game.js. A
|
|
||||||
window should be created in config.js, and custom code for prototypes
|
|
||||||
should be executed.
|
|
||||||
|
|
||||||
game.js is the place to open your first level.
|
|
||||||
|
|
||||||
### Levels
|
|
||||||
|
|
||||||
A level is a collection of objects. A level has a script associated
|
|
||||||
with it. The script is ran when the level is loaded.
|
|
||||||
|
|
||||||
Levels can be added to other levels. Each is independent and unique.
|
|
||||||
In this way, complicated behavior can easily be added up. For example,
|
|
||||||
a world might have a door that opens with a lever. The door and lever
|
|
||||||
can be saved off as their own level, and the level script can contain
|
|
||||||
the code that causes the door to open when the lever is thrown. Then,
|
|
||||||
as many door-lever levels can be added to your game as you want.
|
|
||||||
|
|
||||||
The two primary ways to add objects to the game are World.spawn, and
|
|
||||||
Level.add. World.spawn creates a single object in the world, Level.add
|
|
||||||
adds an entire level, along with its script.
|
|
||||||
|
|
||||||
Levels also can be checked for "completion". A level can be loaded
|
|
||||||
over many frames, and only have all of its contents appear once it's
|
|
||||||
finished loading. World.spawn is immediate.
|
|
||||||
|
|
||||||
Level.clear removes the level from the game world.
|
|
||||||
|
|
||||||
.Level scripting
|
|
||||||
Each level has a script which is ran when the level is loaded, or the
|
|
||||||
game is played. A single object declared in it called "scene" can be
|
|
||||||
used to expose itself to the rest of the game.
|
|
||||||
|
|
|
@ -213,6 +213,19 @@ Object.hide = function(obj,...props)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.unhide = function(obj, ...props)
|
||||||
|
{
|
||||||
|
for (var prop of props) {
|
||||||
|
var p = Object.getOwnPropertyDescriptor(obj,prop);
|
||||||
|
if (!p) {
|
||||||
|
Log.warn(`No property of name ${prop}.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p.enumerable = true;
|
||||||
|
Object.defineProperty(obj, prop, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Object.defineProperty(Object.prototype, 'obscure', {
|
Object.defineProperty(Object.prototype, 'obscure', {
|
||||||
value: function(name) {
|
value: function(name) {
|
||||||
Object.defineProperty(this, name, { enumerable: false });
|
Object.defineProperty(this, name, { enumerable: false });
|
||||||
|
@ -999,7 +1012,7 @@ var Vector = {
|
||||||
var p = Vector.angle(v) + angle;
|
var p = Vector.angle(v) + angle;
|
||||||
return [r*Math.cos(p), r*Math.sin(p)];
|
return [r*Math.cos(p), r*Math.sin(p)];
|
||||||
},
|
},
|
||||||
|
|
||||||
equal(v1, v2, tol) {
|
equal(v1, v2, tol) {
|
||||||
if (!tol)
|
if (!tol)
|
||||||
return v1.equal(v2);
|
return v1.equal(v2);
|
||||||
|
|
|
@ -7,6 +7,8 @@ function assign_impl(obj, impl)
|
||||||
|
|
||||||
Object.mixin(obj, impl);
|
Object.mixin(obj, impl);
|
||||||
|
|
||||||
|
if (obj.sync) obj.sync();
|
||||||
|
|
||||||
for (var key in tmp)
|
for (var key in tmp)
|
||||||
obj[key] = tmp[key];
|
obj[key] = tmp[key];
|
||||||
}
|
}
|
||||||
|
@ -31,6 +33,7 @@ var component = {
|
||||||
var nc = Object.create(this);
|
var nc = Object.create(this);
|
||||||
nc.gameobject = go;
|
nc.gameobject = go;
|
||||||
Object.assign(nc, this._enghook(go.body));
|
Object.assign(nc, this._enghook(go.body));
|
||||||
|
nc.sync();
|
||||||
assign_impl(nc,this.impl);
|
assign_impl(nc,this.impl);
|
||||||
Object.hide(nc, ...this.hides);
|
Object.hide(nc, ...this.hides);
|
||||||
return nc;
|
return nc;
|
||||||
|
@ -580,8 +583,8 @@ component.edge2d = Object.copy(collider2d, {
|
||||||
});
|
});
|
||||||
|
|
||||||
component.edge2d.impl = {
|
component.edge2d.impl = {
|
||||||
set sensor(x) { cmd(18,this.shape,x); },
|
set sensor(x) { cmd(18,this.shape,x); },
|
||||||
get sensor() { return cmd(21,this.shape); },
|
get sensor() { return cmd(21,this.shape); },
|
||||||
|
|
||||||
set thickness(x) {
|
set thickness(x) {
|
||||||
cmd_edge2d(1,this.id,x);
|
cmd_edge2d(1,this.id,x);
|
||||||
|
|
|
@ -92,7 +92,7 @@ var Debug = {
|
||||||
if (this.draw_gizmos)
|
if (this.draw_gizmos)
|
||||||
Game.objects.forEach(function(x) {
|
Game.objects.forEach(function(x) {
|
||||||
if (!x.icon) return;
|
if (!x.icon) return;
|
||||||
gui_img(x.icon, world2screen(x.pos));
|
GUI.image(x.icon, world2screen(x.pos));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.draw_names)
|
if (this.draw_names)
|
||||||
|
@ -101,8 +101,8 @@ var Debug = {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Debug.Options.gif.rec) {
|
if (Debug.Options.gif.rec) {
|
||||||
gui_text("REC", [0,40], 1);
|
GUI.text("REC", [0,40], 1);
|
||||||
gui_text(Time.seconds_to_timecode(Time.time - Debug.Options.gif.start_time, Debug.Options.gif.fps), [0,30], 1);
|
GUI.text(Time.seconds_to_timecode(Time.time - Debug.Options.gif.start_time, Debug.Options.gif.fps), [0,30], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
GUI.text(Game.playing() ? "PLAYING"
|
GUI.text(Game.playing() ? "PLAYING"
|
||||||
|
@ -323,6 +323,7 @@ API.print_doc = function(name)
|
||||||
else if (typeof obj.doc === 'string') mdoc += obj.doc + "\n";
|
else if (typeof obj.doc === 'string') mdoc += obj.doc + "\n";
|
||||||
for (var key in obj) {
|
for (var key in obj) {
|
||||||
if (key === 'doc') continue;
|
if (key === 'doc') continue;
|
||||||
|
if (key === 'toString') continue;
|
||||||
mdoc += API.doc_entry(obj, key);
|
mdoc += API.doc_entry(obj, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
117
scripts/diff.js
117
scripts/diff.js
|
@ -83,7 +83,12 @@ function diffassign(target, from) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function ediff(from,to)
|
function diffkey(from,to,key)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function objdiff(from,to)
|
||||||
{
|
{
|
||||||
var ret = {};
|
var ret = {};
|
||||||
|
|
||||||
|
@ -126,3 +131,113 @@ function ediff(from,to)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function valdiff(from,to)
|
||||||
|
{
|
||||||
|
if (typeof from !== typeof to) return from;
|
||||||
|
if (typeof from === 'function') return undefined;
|
||||||
|
if (typeof from === 'undefined') return undefined;
|
||||||
|
|
||||||
|
if (typeof from === 'number') {
|
||||||
|
if (Number.prec(from) !== Number.prec(to))
|
||||||
|
return to;
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof from === 'object')
|
||||||
|
return ediff(from,to);
|
||||||
|
|
||||||
|
if (from !== to) return to;
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function ediff(from,to)
|
||||||
|
{
|
||||||
|
var ret = {};
|
||||||
|
|
||||||
|
if (!to)
|
||||||
|
// return ediff(from, {});
|
||||||
|
return deep_copy(from);
|
||||||
|
|
||||||
|
Object.entries(from).forEach(function([key,v]) {
|
||||||
|
if (typeof v === 'function') return;
|
||||||
|
if (typeof v === 'undefined') return;
|
||||||
|
|
||||||
|
if (Array.isArray(v)) {
|
||||||
|
if (!Array.isArray(to[key]) || v.length !== to[key].length)
|
||||||
|
ret[key] = Object.values(ediff(v, []));
|
||||||
|
|
||||||
|
var diff = ediff(from[key], to[key]);
|
||||||
|
if (diff && !diff.empty)
|
||||||
|
ret[key] = Object.values(ediff(v,[]));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof v === 'object') {
|
||||||
|
var diff = ediff(v, to[key]);
|
||||||
|
if (diff && !diff.empty)
|
||||||
|
ret[key] = diff;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof v === 'number') {
|
||||||
|
var a = Number.prec(v);
|
||||||
|
if (!to || a !== to[key])
|
||||||
|
ret[key] = a;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!to || v !== to[key])
|
||||||
|
ret[key] = v;
|
||||||
|
});
|
||||||
|
if (ret.empty) return undefined;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ediff.doc = "Given a from and to object, returns an object that, if applied to from, will make it the same as to. Does not include deletion; it is only additive.";
|
||||||
|
|
||||||
|
function subdiff(from,to)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
subdiff.doc = "Given a from and to object, returns a list of properties that must be deleted from the 'from' object to make it like the 'to' object.";
|
||||||
|
|
||||||
|
function samediff(from, to)
|
||||||
|
{
|
||||||
|
var same = [];
|
||||||
|
if (!to) return same;
|
||||||
|
if (typeof to !== 'object') {
|
||||||
|
Log.warn("'To' must be an object. Got " + to);
|
||||||
|
return same;
|
||||||
|
}
|
||||||
|
Object.keys(from).forEach(function(k) {
|
||||||
|
if (Object.isObject(from[k])) {
|
||||||
|
samediff(from[k], to[k]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (Array.isArray(from[k])) {
|
||||||
|
// var d = valdiff(from[k], to[k]);
|
||||||
|
// if (!d)
|
||||||
|
// }
|
||||||
|
|
||||||
|
var d = valdiff(from[k], to[k]);
|
||||||
|
if (!d)
|
||||||
|
delete from[k];
|
||||||
|
});
|
||||||
|
|
||||||
|
return same;
|
||||||
|
}
|
||||||
|
|
||||||
|
samediff.doc = "Given a from and to object, returns an array of keys that are the same on from as on to.";
|
||||||
|
|
||||||
|
function cleandiff(from, to)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -39,6 +39,10 @@ var editor = {
|
||||||
return this.edit_level;
|
return this.edit_level;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get_that() {
|
||||||
|
return this.selectlist.length === 1 ? this.selectlist[0] : this.get_this();
|
||||||
|
},
|
||||||
|
|
||||||
try_select() { /* nullify true if it should set selected to null if it doesn't find an object */
|
try_select() { /* nullify true if it should set selected to null if it doesn't find an object */
|
||||||
var go = physics.pos_query(Mouse.worldpos);
|
var go = physics.pos_query(Mouse.worldpos);
|
||||||
return this.do_select(go);
|
return this.do_select(go);
|
||||||
|
@ -437,13 +441,19 @@ var editor = {
|
||||||
|
|
||||||
var ypos = 200;
|
var ypos = 200;
|
||||||
var depth = 0;
|
var depth = 0;
|
||||||
|
var alldirty = false;
|
||||||
|
for (var lvl of lvlchain) {
|
||||||
|
if (alldirty)
|
||||||
|
lvl._ed.dirty = true;
|
||||||
|
else {
|
||||||
|
lvl._ed.check_dirty();
|
||||||
|
if (lvl._ed.dirty) alldirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
lvlchain.reverse();
|
lvlchain.reverse();
|
||||||
lvlchain.forEach(function(x,i) {
|
lvlchain.forEach(function(x,i) {
|
||||||
depth = i;
|
depth = i;
|
||||||
var lvlstr = x.toString();
|
var lvlstr = x._ed.namestr();
|
||||||
x._ed.check_dirty();
|
|
||||||
if (x._ed.dirty)
|
|
||||||
lvlstr += "*";
|
|
||||||
if (i === lvlchain.length-1) lvlstr += "[this]";
|
if (i === lvlchain.length-1) lvlstr += "[this]";
|
||||||
GUI.text(lvlstr, [0, ypos], 1, editor.color_depths[depth]);
|
GUI.text(lvlstr, [0, ypos], 1, editor.color_depths[depth]);
|
||||||
|
|
||||||
|
@ -468,8 +478,7 @@ var editor = {
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.entries(thiso.objects).forEach(function(x) {
|
Object.entries(thiso.objects).forEach(function(x) {
|
||||||
var p = x[0];
|
var p = x[1]._ed.namestr();
|
||||||
if (x[1]._ed.dirty) p += "*";
|
|
||||||
GUI.text(p, world2screen(x[1].worldpos()),1,editor.color_depths[depth]);
|
GUI.text(p, world2screen(x[1].worldpos()),1,editor.color_depths[depth]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -542,6 +551,23 @@ var editor = {
|
||||||
this.curpanels.forEach(function(x) {
|
this.curpanels.forEach(function(x) {
|
||||||
if (x.on) x.gui();
|
if (x.on) x.gui();
|
||||||
});
|
});
|
||||||
|
/*
|
||||||
|
var o = editor.get_that();
|
||||||
|
|
||||||
|
var pos = [6,600];
|
||||||
|
var offset = [0,0];
|
||||||
|
var os = Object.entries(o.objects);
|
||||||
|
|
||||||
|
GUI.text(o.toString(), pos.add(offset));
|
||||||
|
offset = offset.add([5,-16]);
|
||||||
|
|
||||||
|
os.forEach(function(x) {
|
||||||
|
GUI.text(x.toString(), pos.add(offset));
|
||||||
|
offset = offset.add([0,-16]);
|
||||||
|
});
|
||||||
|
|
||||||
|
GUI.text(JSON.stringify(o._ed.urdiff,null,1), [500,500]);
|
||||||
|
*/
|
||||||
},
|
},
|
||||||
|
|
||||||
ed_debug() {
|
ed_debug() {
|
||||||
|
@ -830,18 +856,20 @@ editor.inputs['C-s'] = function() {
|
||||||
} else if (editor.selectlist.length === 1)
|
} else if (editor.selectlist.length === 1)
|
||||||
saveobj = editor.selectlist[0];
|
saveobj = editor.selectlist[0];
|
||||||
|
|
||||||
saveobj._ed.check_dirty();
|
// saveobj._ed.check_dirty();
|
||||||
if (!saveobj._ed.dirty) return;
|
// if (!saveobj._ed.dirty) return;
|
||||||
|
|
||||||
var savejs = saveobj.json_obj();
|
var savejs = saveobj.json_obj();
|
||||||
Object.merge(saveobj.__proto__, savejs);
|
Object.merge(saveobj.__proto__, savejs);
|
||||||
saveobj.__proto__.objects = savejs.objects;
|
if (savejs.objects) saveobj.__proto__.objects = savejs.objects;
|
||||||
var path = saveobj.ur.toString();
|
var path = saveobj.ur.toString();
|
||||||
path = path.replaceAll('.','/');
|
path = path.replaceAll('.','/');
|
||||||
path = path + "/" + path.name() + ".json";
|
path = path + "/" + path.name() + ".json";
|
||||||
|
|
||||||
IO.slurpwrite(JSON.stringify(saveobj.__proto__,null,1), path);
|
IO.slurpwrite(JSON.stringify(saveobj.__proto__,null,1), path);
|
||||||
Log.warn(`Wrote to file ${path}`);
|
Log.warn(`Wrote to file ${path}`);
|
||||||
|
|
||||||
|
Object.values(saveobj.objects).forEach(function(x) { x._ed.check_dirty(); });
|
||||||
};
|
};
|
||||||
editor.inputs['C-s'].doc = "Save selected.";
|
editor.inputs['C-s'].doc = "Save selected.";
|
||||||
|
|
||||||
|
@ -1431,6 +1459,11 @@ inputpanel.inputs['C-k'] = function() {
|
||||||
this.value = this.value.slice(0,this.caret);
|
this.value = this.value.slice(0,this.caret);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inputpanel.inputs.lm = function()
|
||||||
|
{
|
||||||
|
gui_controls.check_submit();
|
||||||
|
}
|
||||||
|
|
||||||
load("scripts/textedit.js");
|
load("scripts/textedit.js");
|
||||||
|
|
||||||
var replpanel = Object.copy(inputpanel, {
|
var replpanel = Object.copy(inputpanel, {
|
||||||
|
@ -1633,7 +1666,8 @@ var objectexplorer = Object.copy(inputpanel, {
|
||||||
|
|
||||||
guibody() {
|
guibody() {
|
||||||
var items = [];
|
var items = [];
|
||||||
items.push(Mum.text({str:"Examining " + this.obj}));
|
items.push(Mum.text({str:"Examining " + this.obj.toString()}));
|
||||||
|
return items;
|
||||||
|
|
||||||
var n = 0;
|
var n = 0;
|
||||||
var curobj = this.obj;
|
var curobj = this.obj;
|
||||||
|
@ -1779,7 +1813,10 @@ var openlevelpanel = Object.copy(inputpanel, {
|
||||||
},
|
},
|
||||||
|
|
||||||
keycb() {
|
keycb() {
|
||||||
this.assets = this.allassets.filter(x => x.search(this.value) !== -1);
|
if(this.value)
|
||||||
|
this.assets = this.allassets.filter(x => x.startswith(this.value));
|
||||||
|
else
|
||||||
|
this.assets = this.allassets.slice();
|
||||||
for (var m in this.mumlist)
|
for (var m in this.mumlist)
|
||||||
this.mumlist[m].hide = true;
|
this.mumlist[m].hide = true;
|
||||||
this.assets.forEach(function(x) {
|
this.assets.forEach(function(x) {
|
||||||
|
@ -1956,11 +1993,6 @@ limited_editor.inputs['C-q'] = function()
|
||||||
editor.enter_editor();
|
editor.enter_editor();
|
||||||
}
|
}
|
||||||
|
|
||||||
limited_editor.inputs['M-q'] = function()
|
|
||||||
{
|
|
||||||
editor.enter_editor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is used for editing during a paused game */
|
/* This is used for editing during a paused game */
|
||||||
var limited_editing = {};
|
var limited_editing = {};
|
||||||
limited_editing.inputs = {};
|
limited_editing.inputs = {};
|
||||||
|
|
|
@ -787,6 +787,7 @@ Primum.level = undefined;
|
||||||
Primum.toString = function() { return "Primum"; };
|
Primum.toString = function() { return "Primum"; };
|
||||||
Primum._ed.selectable = false;
|
Primum._ed.selectable = false;
|
||||||
Primum._ed.check_dirty = function() { };
|
Primum._ed.check_dirty = function() { };
|
||||||
|
Primum._ed.dirty = false;
|
||||||
globalThis.World.reparent = function(parent) { Log.warn("Cannot reparent the Primum."); }
|
globalThis.World.reparent = function(parent) { Log.warn("Cannot reparent the Primum."); }
|
||||||
Game.view_camera(Primum.spawn(ur.camera2d));
|
Game.view_camera(Primum.spawn(ur.camera2d));
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ var gameobject = {
|
||||||
this.objects = {};
|
this.objects = {};
|
||||||
},
|
},
|
||||||
gscale() { return cmd(103,this.body); },
|
gscale() { return cmd(103,this.body); },
|
||||||
|
sgscale(x) { cmd(36,this.body,x) },
|
||||||
get scale() {
|
get scale() {
|
||||||
if (!this.level) return this.gscale();
|
if (!this.level) return this.gscale();
|
||||||
return this.gscale()/this.level.gscale();
|
return this.gscale()/this.level.gscale();
|
||||||
|
@ -42,11 +43,11 @@ var gameobject = {
|
||||||
set scale(x) {
|
set scale(x) {
|
||||||
if (this.level)
|
if (this.level)
|
||||||
x *= this.level.gscale();
|
x *= this.level.gscale();
|
||||||
var pct = x/this.scale;
|
var pct = x/this.gscale();
|
||||||
cmd(36, this.body, x);
|
cmd(36, this.body, x);
|
||||||
|
|
||||||
this.objects?.forEach(function(obj) {
|
this.objects?.forEach(function(obj) {
|
||||||
obj.scale *= pct;
|
obj.sgscale(obj.gscale()*pct);
|
||||||
obj.pos = obj.pos.scale(pct);
|
obj.pos = obj.pos.scale(pct);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -75,12 +76,15 @@ var gameobject = {
|
||||||
},
|
},
|
||||||
|
|
||||||
set pos(x) {
|
set pos(x) {
|
||||||
this.set_worldpos(Vector.rotate(x,Math.deg2rad(this.level.angle)).add(this.level.worldpos()));
|
this.set_worldpos(Vector.rotate(x.scale(this.level.gscale()),Math.deg2rad(this.level.worldangle())).add(this.level.worldpos()));
|
||||||
},
|
},
|
||||||
|
|
||||||
get pos() {
|
get pos() {
|
||||||
|
if (!this.level) return this.worldpos();
|
||||||
var offset = this.worldpos().sub(this.level.worldpos());
|
var offset = this.worldpos().sub(this.level.worldpos());
|
||||||
return Vector.rotate(offset, -Math.deg2rad(this.level.angle));
|
offset = Vector.rotate(offset, -Math.deg2rad(this.level.angle));
|
||||||
|
offset = offset.scale(1/this.level.gscale());
|
||||||
|
return offset;
|
||||||
},
|
},
|
||||||
get elasticity() { return cmd(107,this.body); },
|
get elasticity() { return cmd(107,this.body); },
|
||||||
set elasticity(x) { cmd(106,this.body,x); },
|
set elasticity(x) { cmd(106,this.body,x); },
|
||||||
|
@ -110,6 +114,7 @@ var gameobject = {
|
||||||
},
|
},
|
||||||
|
|
||||||
worldangle() { return Math.rad2deg(q_body(2,this.body))%360; },
|
worldangle() { return Math.rad2deg(q_body(2,this.body))%360; },
|
||||||
|
sworldangle(x) { set_body(0,this.body,Math.deg2rad(x)); },
|
||||||
get angle() {
|
get angle() {
|
||||||
if (!this.level) return this.worldangle();
|
if (!this.level) return this.worldangle();
|
||||||
return this.worldangle() - this.level.worldangle();
|
return this.worldangle() - this.level.worldangle();
|
||||||
|
@ -126,26 +131,16 @@ var gameobject = {
|
||||||
p += diff;
|
p += diff;
|
||||||
p = Math.deg2rad(p);
|
p = Math.deg2rad(p);
|
||||||
x.pos = [r*Math.cos(p), r*Math.sin(p)];
|
x.pos = [r*Math.cos(p), r*Math.sin(p)];
|
||||||
}, this);
|
});
|
||||||
|
|
||||||
set_body(0,this.body, Math.deg2rad(x - this.level.worldangle()));
|
set_body(0,this.body, Math.deg2rad(x - this.level.worldangle()));
|
||||||
},
|
},
|
||||||
|
|
||||||
rotate(x) {
|
rotate(x) {
|
||||||
this.angle = this.angle + x;
|
this.sworldangle(this.worldangle()+x);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
pulse(vec) { set_body(4, this.body, vec);},
|
|
||||||
|
|
||||||
shove(vec) { set_body(12,this.body,vec);},
|
|
||||||
world2this(pos) { return cmd(70, this.body, pos); },
|
|
||||||
this2world(pos) { return cmd(71, this.body,pos); },
|
|
||||||
set layer(x) { cmd(75,this.body,x); },
|
|
||||||
get layer() { return 0; },
|
|
||||||
alive() { return this.body >= 0; },
|
|
||||||
in_air() { return q_body(7, this.body);},
|
|
||||||
on_ground() { return !this.in_air(); },
|
|
||||||
spawn_from_instance(inst) {
|
spawn_from_instance(inst) {
|
||||||
return this.spawn(inst.ur, inst);
|
return this.spawn(inst.ur, inst);
|
||||||
},
|
},
|
||||||
|
@ -159,6 +154,7 @@ var gameobject = {
|
||||||
}
|
}
|
||||||
|
|
||||||
var go = ur.make(this, data);
|
var go = ur.make(this, data);
|
||||||
|
Object.hide(this, go.toString());
|
||||||
return go;
|
return go;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -204,6 +200,16 @@ var gameobject = {
|
||||||
objects: {},
|
objects: {},
|
||||||
level: undefined,
|
level: undefined,
|
||||||
|
|
||||||
|
pulse(vec) { set_body(4, this.body, vec);},
|
||||||
|
shove(vec) { set_body(12,this.body,vec);},
|
||||||
|
world2this(pos) { return cmd(70, this.body, pos); },
|
||||||
|
this2world(pos) { return cmd(71, this.body,pos); },
|
||||||
|
set layer(x) { cmd(75,this.body,x); },
|
||||||
|
get layer() { return 0; },
|
||||||
|
alive() { return this.body >= 0; },
|
||||||
|
in_air() { return q_body(7, this.body);},
|
||||||
|
on_ground() { return !this.in_air(); },
|
||||||
|
|
||||||
hide() { this.components.forEach(function(x) { x.hide(); }); this.objects.forEach(function(x) { x.hide(); }); },
|
hide() { this.components.forEach(function(x) { x.hide(); }); this.objects.forEach(function(x) { x.hide(); }); },
|
||||||
show() { this.components.forEach(function(x) { x.show(); }); this.objects.forEach(function(x) { x.show(); }); },
|
show() { this.components.forEach(function(x) { x.show(); }); this.objects.forEach(function(x) { x.show(); }); },
|
||||||
|
|
||||||
|
@ -262,8 +268,6 @@ var gameobject = {
|
||||||
register_collide(1, x.collide, x, obj.body, x.shape);
|
register_collide(1, x.collide, x, obj.body, x.shape);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
pos: [0,0],
|
|
||||||
angle:0,
|
|
||||||
phys:1,
|
phys:1,
|
||||||
flipx:false,
|
flipx:false,
|
||||||
flipy:false,
|
flipy:false,
|
||||||
|
@ -271,8 +275,6 @@ var gameobject = {
|
||||||
elasticity:0.5,
|
elasticity:0.5,
|
||||||
friction:1,
|
friction:1,
|
||||||
mass:1,
|
mass:1,
|
||||||
velocity:[0,0],
|
|
||||||
angularvelocity:0,
|
|
||||||
layer:0,
|
layer:0,
|
||||||
worldpos() { return [0,0]; },
|
worldpos() { return [0,0]; },
|
||||||
|
|
||||||
|
@ -342,6 +344,10 @@ var gameobject = {
|
||||||
delete d.angularvelocity;
|
delete d.angularvelocity;
|
||||||
return d;
|
return d;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
full_obj() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
transform_obj() {
|
transform_obj() {
|
||||||
var t = this.json_obj();
|
var t = this.json_obj();
|
||||||
|
@ -439,6 +445,7 @@ var gameobject = {
|
||||||
var obj = Object.create(this);
|
var obj = Object.create(this);
|
||||||
obj.make = undefined;
|
obj.make = undefined;
|
||||||
obj.level = level;
|
obj.level = level;
|
||||||
|
// obj.toJSON = obj.transform_obj;
|
||||||
// this.instances.push(obj);
|
// this.instances.push(obj);
|
||||||
// Log.warn(`Made an object from ${this.toString()}`);
|
// Log.warn(`Made an object from ${this.toString()}`);
|
||||||
// Log.warn(this.instances.length);
|
// Log.warn(this.instances.length);
|
||||||
|
@ -448,8 +455,32 @@ var gameobject = {
|
||||||
assign_impl(obj, gameobject.impl);
|
assign_impl(obj, gameobject.impl);
|
||||||
obj._ed = {
|
obj._ed = {
|
||||||
selectable: true,
|
selectable: true,
|
||||||
check_dirty() { this.dirty = !obj.json_obj().empty; },
|
check_dirty() {
|
||||||
|
this.urdiff = obj.json_obj();
|
||||||
|
this.dirty = !this.urdiff.empty;
|
||||||
|
if (!obj.level) return;
|
||||||
|
var lur = ur[obj.level.ur];
|
||||||
|
if (!lur) return;
|
||||||
|
var lur = lur.objects[obj.toString()];
|
||||||
|
var d = ediff(this.urdiff,lur);
|
||||||
|
if (!d || d.empty)
|
||||||
|
this.inst = true;
|
||||||
|
else
|
||||||
|
this.inst = false;
|
||||||
|
},
|
||||||
|
|
||||||
dirty: false,
|
dirty: false,
|
||||||
|
inst: false,
|
||||||
|
model: Object.create(this),
|
||||||
|
urdiff: {},
|
||||||
|
namestr() {
|
||||||
|
var s = obj.toString();
|
||||||
|
if (this.dirty)
|
||||||
|
if (this.inst) s += "#";
|
||||||
|
else s += "*";
|
||||||
|
|
||||||
|
return s;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
obj.ur = this.toString();
|
obj.ur = this.toString();
|
||||||
|
|
||||||
|
@ -466,11 +497,9 @@ var gameobject = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.objects) {
|
if (this.objects)
|
||||||
obj.make_objs(this.objects);
|
obj.make_objs(this.objects);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
obj.level = undefined;
|
obj.level = undefined;
|
||||||
obj.reparent(level);
|
obj.reparent(level);
|
||||||
|
|
||||||
|
@ -503,12 +532,17 @@ var gameobject = {
|
||||||
Log.warn(`No object with name ${name}. Could not rename to ${newname}.`);
|
Log.warn(`No object with name ${name}. Could not rename to ${newname}.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (name === newname) {
|
||||||
|
Object.hide(this, name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.objects[newname])
|
if (this.objects[newname])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.objects[newname] = this.objects[name];
|
this.objects[newname] = this.objects[name];
|
||||||
this[newname] = this[name];
|
this[newname] = this[name];
|
||||||
this[newname].toString = function() { return newname; };
|
this[newname].toString = function() { return newname; };
|
||||||
|
Object.hide(this, newname);
|
||||||
delete this.objects[name];
|
delete this.objects[name];
|
||||||
delete this[name];
|
delete this[name];
|
||||||
return this.objects[newname];
|
return this.objects[newname];
|
||||||
|
|
|
@ -66,7 +66,7 @@ var GUI = {
|
||||||
};
|
};
|
||||||
|
|
||||||
var gui_controls = {};
|
var gui_controls = {};
|
||||||
//gui_controls.toString = function() { return "GUI controls"; };
|
gui_controls.toString = function() { return "GUI controls"; };
|
||||||
gui_controls.update = function() { };
|
gui_controls.update = function() { };
|
||||||
|
|
||||||
gui_controls.set_mum = function(mum)
|
gui_controls.set_mum = function(mum)
|
||||||
|
@ -93,10 +93,10 @@ gui_controls.inputs.mouse.scroll = function(scroll)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
gui_controls.inputs.lm = function() {
|
gui_controls.check_submit = function() {
|
||||||
if (this.selected && this.selected.action)
|
if (this.selected && this.selected.action)
|
||||||
this.selected.action(this.selected);
|
this.selected.action(this.selected);
|
||||||
};
|
}
|
||||||
|
|
||||||
var Mum = {
|
var Mum = {
|
||||||
padding:[0,0], /* Each element inset with this padding on all sides */
|
padding:[0,0], /* Each element inset with this padding on all sides */
|
||||||
|
|
|
@ -211,7 +211,7 @@ Cmdline.register_cmd("b", function(str) {
|
||||||
}, "Pack the game into the given name.");
|
}, "Pack the game into the given name.");
|
||||||
|
|
||||||
Cmdline.register_cmd("e", function(pawn) {
|
Cmdline.register_cmd("e", function(pawn) {
|
||||||
run("scripts/editor.js");
|
load("scripts/editor.js");
|
||||||
Log.write(`## Input for ${pawn}\n`);
|
Log.write(`## Input for ${pawn}\n`);
|
||||||
eval(`Log.write(Input.print_md_kbm(${pawn}));`);
|
eval(`Log.write(Input.print_md_kbm(${pawn}));`);
|
||||||
STD.exit(0);
|
STD.exit(0);
|
||||||
|
@ -223,7 +223,36 @@ Cmdline.register_cmd("t", function() {
|
||||||
}, "Test suite.");
|
}, "Test suite.");
|
||||||
|
|
||||||
Cmdline.register_cmd("d", function(obj) {
|
Cmdline.register_cmd("d", function(obj) {
|
||||||
run("scripts/editor.js");
|
load("scripts/editor.js");
|
||||||
Log.say(API.print_doc(obj[0]));
|
Log.say(API.print_doc(obj[0]));
|
||||||
STD.exit(0);
|
STD.exit(0);
|
||||||
}, "Print documentation for an object.");
|
}, "Print documentation for an object.");
|
||||||
|
|
||||||
|
Cmdline.register_cmd("cjson", function(json) {
|
||||||
|
var f = json[0];
|
||||||
|
if (!IO.exists(f)) {
|
||||||
|
Log.warn(`File ${f} does not exist.`);
|
||||||
|
STD.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
prototypes.generate_ur();
|
||||||
|
|
||||||
|
var j = JSON.parse(IO.slurp(f));
|
||||||
|
|
||||||
|
for (var k in j) {
|
||||||
|
if (k in j.objects)
|
||||||
|
delete j[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.warn(j);
|
||||||
|
|
||||||
|
for (var k in j.objects) {
|
||||||
|
var o = j.objects[k];
|
||||||
|
samediff(o, ur[o.ur]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.say(j);
|
||||||
|
// IO.slurpwrite(JSON.stringify(j,undefined,2), f);
|
||||||
|
|
||||||
|
STD.exit(0);
|
||||||
|
}, "Clean up a jso file.");
|
||||||
|
|
|
@ -588,7 +588,7 @@ 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]);
|
||||||
|
YughError("Attempted to get the sensor of an edge with no shapes. It has %d points.", arrlen(edge->points));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,17 @@ FILE *logfile = NULL;
|
||||||
char *consolelog;
|
char *consolelog;
|
||||||
FILE *consolefp;
|
FILE *consolefp;
|
||||||
|
|
||||||
|
static FILE *sout;
|
||||||
|
|
||||||
void log_init()
|
void log_init()
|
||||||
{
|
{
|
||||||
consolelog = malloc(CONSOLE_BUF+1);
|
consolelog = malloc(CONSOLE_BUF+1);
|
||||||
consolefp = fmemopen(consolelog, CONSOLE_BUF+1,"w");
|
consolefp = fmemopen(consolelog, CONSOLE_BUF+1,"w");
|
||||||
|
sout = fdopen(dup(stdout),"w");
|
||||||
|
sout = stdout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *logfmt = "%s:%d: %s, %s: %s\n";
|
||||||
void mYughLog(int category, int priority, int line, const char *file, const char *message, ...)
|
void mYughLog(int category, int priority, int line, const char *file, const char *message, ...)
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -46,18 +51,24 @@ void mYughLog(int category, int priority, int line, const char *file, const char
|
||||||
|
|
||||||
double ticks = (double)clock()/CLOCKS_PER_SEC;
|
double ticks = (double)clock()/CLOCKS_PER_SEC;
|
||||||
|
|
||||||
va_list args;
|
va_list args, arg2;
|
||||||
va_start(args, message);
|
va_start(args, message);
|
||||||
char msgbuffer[ERROR_BUFFER] = { '\0' };
|
va_copy(arg2, args);
|
||||||
vsnprintf(msgbuffer, ERROR_BUFFER, message, args);
|
int len = vsnprintf(NULL, 0, message, args)+1;
|
||||||
|
char *msg = malloc(len);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
vsprintf(msg, message, arg2);
|
||||||
|
va_end(arg2);
|
||||||
char buffer[ERROR_BUFFER] = { '\0' };
|
|
||||||
snprintf(buffer, ERROR_BUFFER, "%s:%d: %s, %s: %s\n", file, line, logstr[priority], catstr[category], msgbuffer);
|
len = snprintf(NULL, 0, logfmt, file,line,logstr[priority], catstr[category], msg)+1;
|
||||||
|
char *buffer = malloc(len);
|
||||||
|
sprintf(buffer, logfmt, file, line, logstr[priority], catstr[category], msg);
|
||||||
|
|
||||||
fprintf(stderr, buffer);
|
fprintf(stderr, buffer);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
||||||
|
free(msg);
|
||||||
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -65,8 +76,8 @@ void mYughLog(int category, int priority, int line, const char *file, const char
|
||||||
|
|
||||||
void log_print(const char *str)
|
void log_print(const char *str)
|
||||||
{
|
{
|
||||||
fprintf(stdout, "%s", str);
|
fprintf(sout, "%s", str);
|
||||||
fflush(stdout);
|
fflush(sout);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
strncat(consolelog, str, CONSOLE_BUF);
|
strncat(consolelog, str, CONSOLE_BUF);
|
||||||
|
@ -106,5 +117,5 @@ void log_cat(FILE *f) {
|
||||||
|
|
||||||
void sg_logging(const char *tag, uint32_t lvl, uint32_t id, const char *msg, uint32_t line, const char *file, void *data) {
|
void sg_logging(const char *tag, uint32_t lvl, uint32_t id, const char *msg, uint32_t line, const char *file, void *data) {
|
||||||
lvl = 3-lvl;
|
lvl = 3-lvl;
|
||||||
mYughLog(2, lvl, line, file, "tag: %s, msg: %s", tag, msg);
|
mYughLog(2, lvl, line, file, "tag: %s, id: %d, msg: %s", tag, id, msg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1564,7 +1564,10 @@ JSValue duk_cmd_edge2d(JSContext *js, JSValueConst this, int argc, JSValueConst
|
||||||
int cmd = js2int(argv[0]);
|
int cmd = js2int(argv[0]);
|
||||||
struct phys2d_edge *edge = js2ptr(argv[1]);
|
struct phys2d_edge *edge = js2ptr(argv[1]);
|
||||||
|
|
||||||
if (!edge) return JS_NULL;
|
if (!edge) {
|
||||||
|
YughError("Attempted to do a cmd on edge %p. Not found.", edge);
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
|
@ -191,6 +191,7 @@ void trace_init_image(sg_image id, const sg_image_desc *d, void *data)
|
||||||
|
|
||||||
void trace_make_shader(const sg_shader_desc *d, sg_shader result, void *data)
|
void trace_make_shader(const sg_shader_desc *d, sg_shader result, void *data)
|
||||||
{
|
{
|
||||||
|
YughInfo("Making shader %s", d->label);
|
||||||
if (sg_query_shader_state(result) == SG_RESOURCESTATE_FAILED)
|
if (sg_query_shader_state(result) == SG_RESOURCESTATE_FAILED)
|
||||||
YughError("FAILED MAKING A SHADER: %s\n%s\n%s", d->label);
|
YughError("FAILED MAKING A SHADER: %s\n%s\n%s", d->label);
|
||||||
}
|
}
|
||||||
|
@ -218,7 +219,7 @@ void trace_make_pipeline(const sg_pipeline_desc *d, sg_pipeline result, void *da
|
||||||
|
|
||||||
void trace_apply_pipeline(sg_pipeline pip, void *data)
|
void trace_apply_pipeline(sg_pipeline pip, void *data)
|
||||||
{
|
{
|
||||||
YughInfo("Applying pipeline %d", pip);
|
// YughInfo("Applying pipeline %d", pip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void trace_fail_pipeline(sg_pipeline pip, void *data)
|
void trace_fail_pipeline(sg_pipeline pip, void *data)
|
||||||
|
|
|
@ -24,7 +24,7 @@ JSRuntime *rt = NULL;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT
|
#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT
|
||||||
#else
|
#else
|
||||||
#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT | JS_EVAL_FLAG_STRIP
|
#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT// | JS_EVAL_FLAG_STRIP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@vs vs
|
@vs vs
|
||||||
in vec2 vertex;
|
in vec2 vertex;
|
||||||
in vec2 uv;
|
in vec2 uv;
|
||||||
in vec4 vColor;
|
in vec4 vc;
|
||||||
|
|
||||||
out vec2 texcoords;
|
out vec2 texcoords;
|
||||||
out vec4 fcolor;
|
out vec4 fcolor;
|
||||||
|
@ -10,7 +10,7 @@ uniform vs_p { mat4 proj; };
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
fcolor = vColor;
|
fcolor = vc;
|
||||||
texcoords = uv;
|
texcoords = uv;
|
||||||
gl_Position = proj * vec4(vertex, 0.0, 1.0);
|
gl_Position = proj * vec4(vertex, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,11 @@ uniform sampler smp;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
color = texture(sampler2D(image,smp), texcoords);
|
color = texture(sampler2D(image,smp), texcoords);
|
||||||
|
|
||||||
if (color.a <= 0.1f)
|
if (color.a <= 0.1f)
|
||||||
discard;
|
discard;
|
||||||
|
|
||||||
|
color = mix(color, fcolor, 0.01);
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue