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)
{
var descriptors = {};
var assigns = {};
if (typeof source === 'undefined') return target;
Object.keys(source).forEach(function (k) {
var desc = Object.getOwnPropertyDescriptor(source, k);
if (desc.value) {
if (typeof desc.value === 'object' && desc.value.hasOwn('value'))
descriptors[k] = desc.value;
else
assigns[k] = desc.value;
} else
descriptors[k] = desc;
if (Object.isAccessor(source,k))
Object.defineProperty(target, k, Object.getOwnPropertyDescriptor(source,k));
else
target[k] = source[k];
});
Object.defineProperties(target, descriptors);
Object.assign(target, assigns);
return target;
};
@ -72,54 +64,36 @@ Object.dainty_assign = function(target, source)
Object.isAccessor = function(obj, prop)
{
var prop = Object.getOwnPropertyDescriptor(obj,prop);
if (prop) return false;
return true;
var desc = Object.getOwnPropertyDescriptor(obj,prop);
if (!desc) return false;
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 */
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)
objmerge(target,obj);
for (var key of Object.keys(obj))
Object.mergekey(target,obj,key);
}
Object.totalmerge = function(target, ...objs)
{
for (var obj of objs) {
for (var key in obj) {
if (typeof obj[key] === 'object') {
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];
}
}
for (var obj of objs)
for (var key in obj)
Object.mergekey(target,obj,key);
}
/* Returns a new object with undefined, null, and empty values removed. */

View file

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

View file

@ -85,7 +85,7 @@ var Debug = {
draw() {
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);
@ -97,7 +97,7 @@ var Debug = {
if (this.draw_names)
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) {

View file

@ -561,7 +561,7 @@ return;
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 endgrid = screen2world([Window.width, 0]);
@ -595,7 +595,7 @@ return;
wh[0] /= editor.camera.zoom;
wh[1] /= editor.camera.zoom;
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);
}

View file

@ -31,25 +31,25 @@ load("scripts/diff.js");
Log.level = 1;
var Color = {
white: [255,255,255,255],
black: [0,0,0,255],
blue: [84,110,255,255],
green: [120,255,10,255],
yellow: [251,255,43,255],
red: [255,36,20,255],
teal: [96, 252, 237,255],
gray: [181,181,181,255],
white: [255,255,255],
black: [0,0,0],
blue: [84,110,255],
green: [120,255,10],
yellow: [251,255,43],
red: [255,36,20],
teal: [96, 252, 237],
gray: [181,181,181],
cyan: [0,255,255],
purple: [162,93,227],
};
Color.Arkanoid = {
orange: [255,143,0,255],
teal: [0,255,255,255],
green: [0,255,0,255],
red: [255,0,0,255],
blue: [0,112,255,255],
purple: [255,0,255,255],
orange: [255,143,0],
teal: [0,255,255],
green: [0,255,0],
red: [255,0,0],
blue: [0,112,255],
purple: [255,0,255],
yellow: [255,255,0],
silver: [157,157,157],
gold: [188,174,0],
@ -81,6 +81,50 @@ Color.Apple = {
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);
var ColorMap = {};
@ -140,6 +184,8 @@ ColorMap.Viridis = ColorMap.makemap({
1: [253,231,37]
});
Color.normalize(ColorMap);
ColorMap.sample = function(t, map)
{
map ??= this;
@ -634,7 +680,7 @@ var Game = {
};
if (newgroup.file)
newgroup.color = [120,255,10];
newgroup.color = Color.Editor.newgroup;
return newgroup;
},

View file

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

View file

@ -1,9 +1,8 @@
var GUI = {
text(str, pos, size, color, wrap) {
size = size ? size : 1;
color = color ? color : [255,255,255,255];
wrap = wrap ? wrap : -1;
size ??= 1;
color ??= Color.white;
wrap ??= -1;
var bb = cmd(118, str, size, wrap);
var opos = [bb.r, bb.t];
@ -14,7 +13,7 @@ var GUI = {
},
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) {
@ -70,10 +69,10 @@ var GUI = {
anchor: [0,0],
text_shadow: {
pos: [0,0],
color: [255,255,255,255]
color: Color.white,
},
text_outline: 1, /* outline in pixels */
color: [255,255,255,255],
color: Color.white,
margin: [5,5], /* Distance between elements for things like columns */
width: 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_bindings(&grid_bind);
float col[4] = { color.r/255.0 ,color.g/255.0 ,color.b/255.0 ,color.a/255.0 };
float col[4];
rgba2floats(col,color);
fs_params_t pt;
pt.thickness = (float)width;

View file

@ -161,12 +161,12 @@ struct rgba js2color(JSValue v) {
JSValue c[4];
for (int i = 0; i < 4; 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 = {
.r = js2int(c[0]),
.g = js2int(c[1]),
.b = js2int(c[2]),
.a = a,
.r = js2number(c[0])*RGBA_MAX,
.g = js2number(c[1])*RGBA_MAX,
.b = js2number(c[2])*RGBA_MAX,
.a = a*RGBA_MAX,
};
return color;

View file

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

View file

@ -202,17 +202,12 @@ int fexists(char *path)
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;
jump:
f = fopen(filename, "rb");
f = fopen(file, "rb");
if (!f) return NULL;
@ -228,6 +223,18 @@ void *slurp_file(const char *filename, size_t *size)
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)
{
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) {
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);
free(script);
size_t out_len;