Fix Object.merge; add many color palettes, normalize color fns

This commit is contained in:
John Alanbrook 2023-09-23 17:35:02 +00:00
parent 721abd6a8f
commit 174a9ed586
12 changed files with 157 additions and 135 deletions

View file

@ -19,23 +19,15 @@ URIError = {};
Object.complete_assign = function(target, source) Object.complete_assign = function(target, source)
{ {
var descriptors = {};
var assigns = {};
if (typeof source === 'undefined') return target; if (typeof source === 'undefined') return target;
Object.keys(source).forEach(function (k) {
var desc = Object.getOwnPropertyDescriptor(source, k);
if (desc.value) { Object.keys(source).forEach(function (k) {
if (typeof desc.value === 'object' && desc.value.hasOwn('value')) if (Object.isAccessor(source,k))
descriptors[k] = desc.value; Object.defineProperty(target, k, Object.getOwnPropertyDescriptor(source,k));
else else
assigns[k] = desc.value; target[k] = source[k];
} else
descriptors[k] = desc;
}); });
Object.defineProperties(target, descriptors);
Object.assign(target, assigns);
return target; return target;
}; };
@ -72,54 +64,36 @@ Object.dainty_assign = function(target, source)
Object.isAccessor = function(obj, prop) Object.isAccessor = function(obj, prop)
{ {
var prop = Object.getOwnPropertyDescriptor(obj,prop); var desc = Object.getOwnPropertyDescriptor(obj,prop);
if (prop) return false; if (!desc) return false;
return true; if (desc.get || desc.set) return true;
return false;
} }
Object.mergekey = function(o1,o2,k)
{
if (typeof(o2[k]) === 'object') {
if (Array.isArray(o2[k]))
o1[k] = o2[k].slice();
else
Object.merge(o1[k], o2[k]);
} else
o1[k] = o2[k];
}
/* Same as merge from Ruby */ /* Same as merge from Ruby */
Object.merge = function(target, ...objs) Object.merge = function(target, ...objs)
{ {
var objmerge = function(tar, obj)
{
for (var key of Object.keys(obj)) {
if (typeof obj[key] === 'object') {
if (tar[key]) {
objmerge(tar[key], obj[key]);
continue;
}
else {
tar[key] = obj[key];
continue;
}
}
tar[key] = obj[key];
}
}
for (var obj of objs) for (var obj of objs)
objmerge(target,obj); for (var key of Object.keys(obj))
Object.mergekey(target,obj,key);
} }
Object.totalmerge = function(target, ...objs) Object.totalmerge = function(target, ...objs)
{ {
for (var obj of objs) { for (var obj of objs)
for (var key in obj) { for (var key in obj)
if (typeof obj[key] === 'object') { Object.mergekey(target,obj,key);
if (typeof target[key] === 'object') {
if (Object.isAccessor(target,key))
target[key] = obj[key];
else
Object.merge(target[key], obj[key]);
}
else
target[key] = obj[key];
} else
target[key] = obj[key];
}
}
} }
/* Returns a new object with undefined, null, and empty values removed. */ /* Returns a new object with undefined, null, and empty values removed. */

View file

@ -35,14 +35,12 @@ component.sprite = {
make(go) { make(go) {
var nsprite = Object.create(component.sprite.maker); var nsprite = Object.create(component.sprite.maker);
Object.assign(nsprite, make_sprite(go)); Object.assign(nsprite, make_sprite(go));
Object.assign(nsprite, this);
nsprite.ur = this; nsprite.ur = this;
return nsprite; return nsprite;
}, },
}; };
component.sprite.maker = Object.copy(component, { component.sprite.maker = Object.copy(component, {
name: "sprite",
set path(x) { cmd(12,this.id,x,this.rect); }, set path(x) { cmd(12,this.id,x,this.rect); },
get visible() { return this.enabled; }, get visible() { return this.enabled; },
set visible(x) { this.enabled = x; }, set visible(x) { this.enabled = x; },
@ -73,6 +71,8 @@ component.sprite.maker = Object.copy(component, {
height() { return cmd(64,this.path).y; }, height() { return cmd(64,this.path).y; },
}); });
Object.freeze(sprite);
var sprite = component.sprite.maker; var sprite = component.sprite.maker;
sprite.inputs = {}; sprite.inputs = {};
@ -85,11 +85,10 @@ sprite.inputs.kp4 = function() { this.pos = [-1,-0.5]; };
sprite.inputs.kp3 = function() { this.pos = [0, -1]; }; sprite.inputs.kp3 = function() { this.pos = [0, -1]; };
sprite.inputs.kp2 = function() { this.pos = [-0.5,-1]; }; sprite.inputs.kp2 = function() { this.pos = [-0.5,-1]; };
sprite.inputs.kp1 = function() { this.pos = [-1,-1]; }; sprite.inputs.kp1 = function() { this.pos = [-1,-1]; };
Object.seal(sprite);
/* Container to play sprites and anim2ds */ /* Container to play sprites and anim2ds */
component.char2d = Object.copy(sprite, { component.char2d = Object.copy(sprite, {
name: "char 2d",
frame2rect(frames, frame) { frame2rect(frames, frame) {
var rect = {s0:0,s1:1,t0:0,t1:1}; var rect = {s0:0,s1:1,t0:0,t1:1};
@ -100,8 +99,6 @@ component.char2d = Object.copy(sprite, {
return rect; return rect;
}, },
make(go) {
var char = Object.copy(this, {
get enabled() { return cmd(114,this.id); }, get enabled() { return cmd(114,this.id); },
set enabled(x) { cmd(20,this.id,x); }, set enabled(x) { cmd(20,this.id,x); },
set color(x) { cmd(96,this.id,x); }, set color(x) { cmd(96,this.id,x); },
@ -128,8 +125,12 @@ component.char2d = Object.copy(sprite, {
}, },
kill() { cmd(9,this.id); }, kill() { cmd(9,this.id); },
}); ur: {
},
make(go) {
var char = Object.create(this);
char.curplaying = char.anims.array()[0]; char.curplaying = char.anims.array()[0];
char.obscure('curplaying'); char.obscure('curplaying');
char.id = make_sprite(go, char.curplaying.path, this.pos); char.id = make_sprite(go, char.curplaying.path, this.pos);
@ -247,29 +248,26 @@ collider2d.inputs['M-t'] = function() { this.enabled = !this.enabled; }
collider2d.inputs['M-t'].doc = "Toggle if this collider is enabled."; collider2d.inputs['M-t'].doc = "Toggle if this collider is enabled.";
component.polygon2d = Object.copy(collider2d, { component.polygon2d = Object.copy(collider2d, {
name: "polygon 2d",
points: [], points: [],
ur: {
flipx: false, flipx: false,
flipy: false, flipy: false
},
make(go) { sync() {
var poly = Object.create(this); cmd_poly2d(0, this.id, this.spoints);
Object.assign(poly, make_poly2d(go, this.points)); },
Object.assign(poly, this.make_fns);
Object.assign(poly, {
boundingbox() { boundingbox() {
return points2bb(this.spoints); return points2bb(this.spoints);
}, },
sync() { cmd_poly2d(0, this.id, this.spoints); } make(go) {
}); var poly = Object.create(this);
Object.assign(poly, make_poly2d(go, this.points));
poly.defn('points', this.points.copy()); poly.defn('points', this.points.copy());
Object.defineProperty(poly, 'id', {enumerable:false});
Object.defineProperty(poly, 'shape', {enumerable:false});
poly.sync(); poly.sync();
return poly; return poly;
@ -604,10 +602,12 @@ bucket.inputs.rb.doc = "Rotate the points CW.";
bucket.inputs.rb.rep = true; bucket.inputs.rb.rep = true;
component.circle2d = Object.copy(collider2d, { component.circle2d = Object.copy(collider2d, {
name: "circle 2d",
set radius(x) { cmd_circle2d(0,this.id,x); }, set radius(x) { cmd_circle2d(0,this.id,x); },
get radius() { return cmd_circle2d(2,this.id); }, get radius() { return cmd_circle2d(2,this.id); },
set scale(x) { this.radius = x; },
get scale() { return this.radius; },
set offset(x) { cmd_circle2d(1,this.id,x); }, set offset(x) { cmd_circle2d(1,this.id,x); },
get offset() { return cmd_circle2d(3,this.id); }, get offset() { return cmd_circle2d(3,this.id); },
@ -619,9 +619,6 @@ component.circle2d = Object.copy(collider2d, {
make(go) { make(go) {
var circle = Object.create(this); var circle = Object.create(this);
Object.assign(circle, make_circle2d(go, circle.radius, circle.offset)); Object.assign(circle, make_circle2d(go, circle.radius, circle.offset));
circle.radius = 10;
circle.offset = [0,0];
return circle; return circle;
}, },
@ -669,5 +666,3 @@ var Resources = {
}, },
}; };
Log.warn("bottom of components");

View file

@ -85,7 +85,7 @@ var Debug = {
draw() { draw() {
if (this.draw_bb) if (this.draw_bb)
Game.objects.forEach(function(x) { Debug.boundingbox(x.boundingbox(), [255,255,255,10]); }); Game.objects.forEach(function(x) { Debug.boundingbox(x.boundingbox(), Color.Debug.boundingbox.alpha(0.05)); });
if (Game.paused()) gui_text("PAUSED", [0,0],1); if (Game.paused()) gui_text("PAUSED", [0,0],1);
@ -97,7 +97,7 @@ var Debug = {
if (this.draw_names) if (this.draw_names)
Game.objects.forEach(function(x) { Game.objects.forEach(function(x) {
GUI.text(x, world2screen(x.pos).add([0,32]), 1, [84,110,255]); GUI.text(x, world2screen(x.pos).add([0,32]), 1, Color.Debug.names);
}); });
if (Debug.Options.gif.rec) { if (Debug.Options.gif.rec) {

View file

@ -561,7 +561,7 @@ return;
GUI.image("icons/icons8-lock-16.png", world2screen(obj.pos)); GUI.image("icons/icons8-lock-16.png", world2screen(obj.pos));
}); });
Debug.draw_grid(1, editor_config.grid_size/editor.camera.zoom, editor_config.grid_color); Debug.draw_grid(1, editor_config.grid_size/editor.camera.zoom, Color.Editor.grid.alpha(0.3));
var startgrid = screen2world([-20,Window.height]).map(function(x) { return Math.snap(x, editor_config.grid_size); }); var startgrid = screen2world([-20,Window.height]).map(function(x) { return Math.snap(x, editor_config.grid_size); });
var endgrid = screen2world([Window.width, 0]); var endgrid = screen2world([Window.width, 0]);
@ -595,7 +595,7 @@ return;
wh[0] /= editor.camera.zoom; wh[0] /= editor.camera.zoom;
wh[1] /= editor.camera.zoom; wh[1] /= editor.camera.zoom;
var bb = cwh2bb(world2screen(c),wh); var bb = cwh2bb(world2screen(c),wh);
Debug.boundingbox(bb, [255,255,55,10]); Debug.boundingbox(bb, Color.Editor.select.alpha(0.1));
Debug.line(bb2points(bb).wrapped(1), Color.white); Debug.line(bb2points(bb).wrapped(1), Color.white);
} }

View file

@ -31,25 +31,25 @@ load("scripts/diff.js");
Log.level = 1; Log.level = 1;
var Color = { var Color = {
white: [255,255,255,255], white: [255,255,255],
black: [0,0,0,255], black: [0,0,0],
blue: [84,110,255,255], blue: [84,110,255],
green: [120,255,10,255], green: [120,255,10],
yellow: [251,255,43,255], yellow: [251,255,43],
red: [255,36,20,255], red: [255,36,20],
teal: [96, 252, 237,255], teal: [96, 252, 237],
gray: [181,181,181,255], gray: [181,181,181],
cyan: [0,255,255], cyan: [0,255,255],
purple: [162,93,227], purple: [162,93,227],
}; };
Color.Arkanoid = { Color.Arkanoid = {
orange: [255,143,0,255], orange: [255,143,0],
teal: [0,255,255,255], teal: [0,255,255],
green: [0,255,0,255], green: [0,255,0],
red: [255,0,0,255], red: [255,0,0],
blue: [0,112,255,255], blue: [0,112,255],
purple: [255,0,255,255], purple: [255,0,255],
yellow: [255,255,0], yellow: [255,255,0],
silver: [157,157,157], silver: [157,157,157],
gold: [188,174,0], gold: [188,174,0],
@ -81,6 +81,50 @@ Color.Apple = {
blue: [0,156,223] blue: [0,156,223]
}; };
Color.Debug = {
boundingbox: Color.white,
names: [84,110,255],
};
Color.Editor = {
grid: [99,255,128],
select: [255,255,55],
newgroup: [120,255,10],
};
/* Detects the format of all colors and munges them into a floating point format */
Color.normalize = function(c) {
var add_a = function(a) {
var n = this.slice();
n.a = a;
return n;
};
for (var p of Object.keys(c)) {
var fmt = "nrm";
if (typeof c[p] !== 'object') continue;
if (!Array.isArray(c[p])) {
Color.normalize(c[p]);
continue;
}
for (var color of c[p]) {
if (color > 1) {
fmt = "8b";
break;
}
}
switch(fmt) {
case "8b":
c[p] = c[p].map(function(x) { return x/255; });
}
c[p].alpha = add_a;
}
};
Color.normalize(Color);
Object.deepfreeze(Color); Object.deepfreeze(Color);
var ColorMap = {}; var ColorMap = {};
@ -140,6 +184,8 @@ ColorMap.Viridis = ColorMap.makemap({
1: [253,231,37] 1: [253,231,37]
}); });
Color.normalize(ColorMap);
ColorMap.sample = function(t, map) ColorMap.sample = function(t, map)
{ {
map ??= this; map ??= this;
@ -634,7 +680,7 @@ var Game = {
}; };
if (newgroup.file) if (newgroup.file)
newgroup.color = [120,255,10]; newgroup.color = Color.Editor.newgroup;
return newgroup; return newgroup;
}, },

View file

@ -497,7 +497,6 @@ prototypes.from_obj = function(name, obj)
{ {
var newobj = Object.copy(gameobject.ur, obj); var newobj = Object.copy(gameobject.ur, obj);
prototypes.ur[name] = newobj; prototypes.ur[name] = newobj;
Log.say(Object.keys(newobj));
newobj.toString = function() { return name; }; newobj.toString = function() { return name; };
return prototypes.ur[name]; return prototypes.ur[name];
} }

View file

@ -1,9 +1,8 @@
var GUI = { var GUI = {
text(str, pos, size, color, wrap) { text(str, pos, size, color, wrap) {
size = size ? size : 1; size ??= 1;
color ??= Color.white;
color = color ? color : [255,255,255,255]; wrap ??= -1;
wrap = wrap ? wrap : -1;
var bb = cmd(118, str, size, wrap); var bb = cmd(118, str, size, wrap);
var opos = [bb.r, bb.t]; var opos = [bb.r, bb.t];
@ -14,7 +13,7 @@ var GUI = {
}, },
text_cursor(str, pos, size, cursor) { text_cursor(str, pos, size, cursor) {
cursor_text(str,pos,size,[255,255,255],cursor); cursor_text(str,pos,size,Color.white,cursor);
}, },
image(path,pos) { image(path,pos) {
@ -70,10 +69,10 @@ var GUI = {
anchor: [0,0], anchor: [0,0],
text_shadow: { text_shadow: {
pos: [0,0], pos: [0,0],
color: [255,255,255,255] color: Color.white,
}, },
text_outline: 1, /* outline in pixels */ text_outline: 1, /* outline in pixels */
color: [255,255,255,255], color: Color.white,
margin: [5,5], /* Distance between elements for things like columns */ margin: [5,5], /* Distance between elements for things like columns */
width: 0, width: 0,
height: 0, height: 0,

View file

@ -559,8 +559,8 @@ void draw_grid(float width, float span, struct rgba color)
sg_apply_pipeline(grid_pipe); sg_apply_pipeline(grid_pipe);
sg_apply_bindings(&grid_bind); sg_apply_bindings(&grid_bind);
float col[4];
float col[4] = { color.r/255.0 ,color.g/255.0 ,color.b/255.0 ,color.a/255.0 }; rgba2floats(col,color);
fs_params_t pt; fs_params_t pt;
pt.thickness = (float)width; pt.thickness = (float)width;

View file

@ -161,12 +161,12 @@ struct rgba js2color(JSValue v) {
JSValue c[4]; JSValue c[4];
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
c[i] = js_arridx(v,i); c[i] = js_arridx(v,i);
unsigned char a = JS_IsUndefined(c[3]) ? 255 : js2int(c[3]); float a = JS_IsUndefined(c[3]) ? 1.0 : js2number(c[3]);
struct rgba color = { struct rgba color = {
.r = js2int(c[0]), .r = js2number(c[0])*RGBA_MAX,
.g = js2int(c[1]), .g = js2number(c[1])*RGBA_MAX,
.b = js2int(c[2]), .b = js2number(c[2])*RGBA_MAX,
.a = a, .a = a*RGBA_MAX,
}; };
return color; return color;

View file

@ -15,6 +15,8 @@
#include "sokol/sokol_gfx.h" #include "sokol/sokol_gfx.h"
#include "HandmadeMath.h" #include "HandmadeMath.h"
#define RGBA_MAX 255
struct mCamera; struct mCamera;
struct window; struct window;
@ -126,10 +128,10 @@ static struct boundingbox cwh2bb(HMM_Vec2 c, HMM_Vec2 wh) {
static float *rgba2floats(float *r, struct rgba c) static float *rgba2floats(float *r, struct rgba c)
{ {
r[0] = c.r / 255.0; r[0] = (float)c.r / RGBA_MAX;
r[1] = c.g / 255.0; r[1] = (float)c.g / RGBA_MAX;
r[2] = c.b / 255.0; r[2] = (float)c.b / RGBA_MAX;
r[3] = c.a / 255.0; r[3] = (float)c.a / RGBA_MAX;
return r; return r;
} }

View file

@ -202,17 +202,12 @@ int fexists(char *path)
return 0; return 0;
} }
void *slurp_file(const char *filename, size_t *size) void *os_slurp(const char *file, size_t *size)
{ {
if (cdb_find(&game_cdb, filename, strlen(filename)))
return cdb_slurp(&game_cdb, filename, size);
else if (cdb_find(&corecdb, filename, strlen(filename)))
return cdb_slurp(&corecdb, filename, size);
FILE *f; FILE *f;
jump: jump:
f = fopen(filename, "rb"); f = fopen(file, "rb");
if (!f) return NULL; if (!f) return NULL;
@ -228,6 +223,18 @@ void *slurp_file(const char *filename, size_t *size)
return slurp; return slurp;
} }
void *slurp_file(const char *filename, size_t *size)
{
if (!access(filename, R_OK))
return os_slurp(filename, size);
else if (cdb_find(&game_cdb, filename, strlen(filename)))
return cdb_slurp(&game_cdb, filename, size);
else if (cdb_find(&corecdb, filename, strlen(filename)))
return cdb_slurp(&corecdb, filename, size);
return NULL;
}
char *slurp_text(const char *filename, size_t *size) char *slurp_text(const char *filename, size_t *size)
{ {
size_t len; size_t len;

View file

@ -98,7 +98,7 @@ void script_evalf(const char *format, ...)
} }
uint8_t *compile_script(const char *file, size_t *len) { uint8_t *compile_script(const char *file, size_t *len) {
const char *script = slurp_text(file, len); char *script = slurp_text(file, len);
JSValue obj = JS_Eval(js, script, *len, file, JS_EVAL_FLAG_COMPILE_ONLY | JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAGS); JSValue obj = JS_Eval(js, script, *len, file, JS_EVAL_FLAG_COMPILE_ONLY | JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAGS);
free(script); free(script);
size_t out_len; size_t out_len;