spline fixes

This commit is contained in:
John Alanbrook 2023-12-20 23:20:29 +00:00
parent a8ee53ec33
commit a03143463e
20 changed files with 134 additions and 118 deletions

View file

@ -51,7 +51,7 @@ ifdef NQOA
endif endif
ifeq ($(DBG),1) ifeq ($(DBG),1)
CPPFLAGS += -g -fsanitize=address CPPFLAGS += -g #-fsanitize=address
INFO += _dbg INFO += _dbg
else else
CPPFLAGS += -DNDEBUG CPPFLAGS += -DNDEBUG

View file

@ -787,12 +787,9 @@ Object.defineProperty(String.prototype, 'pct', {
}); });
Object.defineProperty(String.prototype, 'uc', { value: function() { return this.toUpperCase(); } }); Object.defineProperty(String.prototype, 'uc', { value: function() { return this.toUpperCase(); } });
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, 'copy', { Object.defineProperty(Array.prototype, 'copy', {
value: function() { value: function() {
var c = []; var c = [];
@ -1199,6 +1196,10 @@ Math.grab_from_points = function(pos, points, slop) {
return idx; return idx;
}; };
Math.nearest = function(n, incr)
{
return Math.round(n/incr)*incr;
}
Number.prec = function(num) Number.prec = function(num)
{ {
@ -1426,6 +1427,10 @@ var Vector = {
return vec.sub(p.scale(2*Vector.dot(vec, p))); return vec.sub(p.scale(2*Vector.dot(vec, p)));
}, },
reflect_point(vec, point) {
return point.add(vec.sub(point).scale(-1));
},
}; };
/* POINT ASSISTANCE */ /* POINT ASSISTANCE */

View file

@ -97,14 +97,13 @@ component.sprite.impl = {
set layer(x) { cmd(60, this.id, x); }, set layer(x) { cmd(60, this.id, x); },
get layer() { return undefined; }, get layer() { return undefined; },
emissive(x) { cmd(170, this.id, x); }, emissive(x) { cmd(170, this.id, x); },
pick() { return this; },
move(d) { this.pos = this.pos.add(d); },
boundingbox() { boundingbox() {
return cwh2bb([0,0],[0,0]);
var dim = this.dimensions(); var dim = this.dimensions();
dim = dim.scale(this.gameobject.scale); dim = dim.scale(this.gameobject.gscale());
var realpos = this.pos.copy(); var realpos = dim.scale(0.5).add(this.pos);
realpos.x = realpos.x * dim.x + (dim.x/2);
realpos.y = realpos.y * dim.y + (dim.y/2);
return cwh2bb(realpos,dim); return cwh2bb(realpos,dim);
}, },
@ -123,6 +122,7 @@ component.model = Object.copy(component, {
component.model.impl = { component.model.impl = {
set path(x) { cmd(149, this.id, x); }, set path(x) { cmd(149, this.id, x); },
draw() { cmd(150, this.id); }, draw() { cmd(150, this.id); },
kill() { cmd(213, this.id); },
}; };
var sprite = component.sprite; var sprite = component.sprite;
@ -134,15 +134,15 @@ sprite.doc = {
}; };
sprite.inputs = {}; sprite.inputs = {};
sprite.inputs.kp9 = function() { this.pos = [0,0]; }; sprite.inputs.kp9 = function() { this.pos = this.dimensions().scale([0,0]); };
sprite.inputs.kp8 = function() { this.pos = [-0.5, 0]; }; sprite.inputs.kp8 = function() { this.pos = this.dimensions().scale([-0.5, 0]); };
sprite.inputs.kp7 = function() { this.pos = [-1,0]; }; sprite.inputs.kp7 = function() { this.pos = this.dimensions().scale([-1,0]); };
sprite.inputs.kp6 = function() { this.pos = [0,-0.5]; }; sprite.inputs.kp6 = function() { this.pos = this.dimensions().scale([0,-0.5]); };
sprite.inputs.kp5 = function() { this.pos = [-0.5,-0.5]; }; sprite.inputs.kp5 = function() { this.pos = this.dimensions().scale([-0.5,-0.5]); };
sprite.inputs.kp4 = function() { this.pos = [-1,-0.5]; }; sprite.inputs.kp4 = function() { this.pos = this.dimensions().scale([-1,-0.5]); };
sprite.inputs.kp3 = function() { this.pos = [0, -1]; }; sprite.inputs.kp3 = function() { this.pos = this.dimensions().scale([0, -1]); };
sprite.inputs.kp2 = function() { this.pos = [-0.5,-1]; }; sprite.inputs.kp2 = function() { this.pos = this.dimensions().scale([-0.5,-1]); };
sprite.inputs.kp1 = function() { this.pos = [-1,-1]; }; sprite.inputs.kp1 = function() { this.pos = this.dimensions().scale([-1,-1]); };
Object.seal(sprite); Object.seal(sprite);
var SpriteAnim = { var SpriteAnim = {
@ -535,8 +535,6 @@ polygon2d.inputs['C-b'] = function() {
}; };
polygon2d.inputs['C-b'].doc = "Freeze mirroring in place."; polygon2d.inputs['C-b'].doc = "Freeze mirroring in place.";
//Object.freeze(polygon2d);
component.edge2d = Object.copy(collider2d, { component.edge2d = Object.copy(collider2d, {
dimensions:2, dimensions:2,
thickness:0, thickness:0,
@ -544,7 +542,7 @@ component.edge2d = Object.copy(collider2d, {
type: Spline.type.catmull, type: Spline.type.catmull,
C: 1, /* when in bezier, continuity required. 0, 1 or 2. */ C: 1, /* when in bezier, continuity required. 0, 1 or 2. */
looped: false, looped: false,
angle: 3, /* maximum angle between two segments */ angle: 0.5, /* smaller for smoother bezier */
flipx: false, flipx: false,
flipy: false, flipy: false,
@ -559,8 +557,10 @@ component.edge2d = Object.copy(collider2d, {
var spoints = this.cpoints.slice(); var spoints = this.cpoints.slice();
if (this.flipx) { if (this.flipx) {
var endcap = Spline.is_bezier(this.type) ? spoints.length-2 : spoints.length-1; if (Spline.is_bezier(this.type))
for (var i = endcap; i >= 0; i--) { spoints.push(Vector.reflect_point(spoints.at(-2), spoints.at(-1)));
for (var i = spoints.length-1; i >= 0; i--) {
var newpoint = spoints[i].slice(); var newpoint = spoints[i].slice();
newpoint.x = -newpoint.x; newpoint.x = -newpoint.x;
spoints.push(newpoint); spoints.push(newpoint);
@ -568,6 +568,9 @@ component.edge2d = Object.copy(collider2d, {
} }
if (this.flipy) { if (this.flipy) {
if (Spline.is_bezier(this.type))
spoints.push(Vector.reflect(point(spoints.at(-2),spoints.at(-1))));
for (var i = spoints.length-1; i >= 0; i--) { for (var i = spoints.length-1; i >= 0; i--) {
var newpoint = spoints[i].slice(); var newpoint = spoints[i].slice();
newpoint.y = -newpoint.y; newpoint.y = -newpoint.y;
@ -611,6 +614,9 @@ component.edge2d = Object.copy(collider2d, {
return Spline.sample_angle(this.type, spoints,this.angle); return Spline.sample_angle(this.type, spoints,this.angle);
} }
if (this.looped && Spline.is_bezier(this.type))
spoints = Spline.bezier_loop(spoints);
return Spline.sample_angle(this.type, spoints, this.angle); return Spline.sample_angle(this.type, spoints, this.angle);
}, },
@ -875,7 +881,6 @@ component.circle2d = Object.copy(collider2d, {
toString() { return "circle2d"; }, toString() { return "circle2d"; },
boundingbox() { boundingbox() {
var diameter = this.radius*2*this.gameobject.scale;
return cwh2bb(this.offset.scale(this.gameobject.scale), [this.radius,this.radius]); return cwh2bb(this.offset.scale(this.gameobject.scale), [this.radius,this.radius]);
}, },

View file

@ -389,8 +389,6 @@ var editor = {
Debug.boundingbox(bb, Color.Editor.select.alpha(0.1)); Debug.boundingbox(bb, Color.Editor.select.alpha(0.1));
Shape.line(bb2points(bb).wrapped(1), Color.white); Shape.line(bb2points(bb).wrapped(1), Color.white);
} }
}, },
gui() { gui() {
@ -459,8 +457,8 @@ var editor = {
Object.entries(thiso.objects).forEach(function(x) { Object.entries(thiso.objects).forEach(function(x) {
var p = x[1].namestr(); var p = x[1].namestr();
GUI.text(p, x[1].screenpos().add([0,16]),1,editor.color_depths[depth]); GUI.text(p, x[1].screenpos().add([0,16]),1,editor.color_depths[depth]);
Shape.circle(x[1].screenpos(),10,Color.blue); Shape.circle(x[1].screenpos(),10,Color.blue.alpha(0.3));
Shape.arrow(x[1].screenpos(), x[1].screenpos().add([0,50]), Color.red, 10); Shape.arrow(x[1].screenpos(), x[1].screenpos().add(x[1].up().scale(15)), Color.red, 10);
}); });
var mg = physics.pos_query(Mouse.worldpos,10); var mg = physics.pos_query(Mouse.worldpos,10);
@ -470,6 +468,9 @@ var editor = {
GUI.text(p, Mouse.screenpos(),1,Color.teal); GUI.text(p, Mouse.screenpos(),1,Color.teal);
} }
if (this.rotlist.length === 1)
GUI.text(Math.trunc(this.rotlist[0].obj.angle), Mouse.screenpos(), 1, Color.teal);
if (this.selectlist.length === 1) { if (this.selectlist.length === 1) {
var i = 1; var i = 1;
for (var key in this.selectlist[0].components) { for (var key in this.selectlist[0].components) {
@ -1143,6 +1144,8 @@ editor.inputs.mouse.move = function(pos, dpos)
editor.rotlist?.forEach(function(x) { editor.rotlist?.forEach(function(x) {
var anglediff = Math.atan2(relpos.y, relpos.x) - x.rotoffset; var anglediff = Math.atan2(relpos.y, relpos.x) - x.rotoffset;
x.obj.angle = x.angle + Math.rad2deg(anglediff); x.obj.angle = x.angle + Math.rad2deg(anglediff);
if (Keys.shift())
x.obj.angle = Math.nearest(x.obj.angle, 45);
if (x.pos) if (x.pos)
x.obj.pos = x.pos.sub(x.offset).add(x.offset.rotate(anglediff)); x.obj.pos = x.pos.sub(x.offset).add(x.offset.rotate(anglediff));
}); });
@ -1151,7 +1154,6 @@ editor.inputs.mouse.move = function(pos, dpos)
editor.inputs.mouse.scroll = function(scroll) editor.inputs.mouse.scroll = function(scroll)
{ {
scroll.y *= -1; scroll.y *= -1;
// editor.grabselect?.forEach(x => x.move(Game.camera.dir_view2world(scroll)));
editor.camera.move(Game.camera.dir_view2world(scroll.scale(-3))); editor.camera.move(Game.camera.dir_view2world(scroll.scale(-3)));
} }

View file

@ -234,42 +234,15 @@ register(9, Log.stack, this);
Register.gamepad_playermap[0] = Player.players[0]; Register.gamepad_playermap[0] = Player.players[0];
var Signal = { var Signal = {
signals: [],
obj_begin(fn, obj, go) { obj_begin(fn, obj, go) {
this.signals.push([fn, obj]);
register_collide(0, fn, obj, go.body); register_collide(0, fn, obj, go.body);
}, },
obj_separate(fn, obj, go) { obj_separate(fn, obj, go) {
this.signals.push([fn,obj]);
register_collide(3,fn,obj,go.body); register_collide(3,fn,obj,go.body);
}, },
clear_obj(obj) {
this.signals.filter(function(x) { return x[1] !== obj; });
},
c:{},
register(name, fn) {
if (!this.c[name])
this.c[name] = [];
this.c[name].push(fn);
},
call(name, ...args) {
if (this.c[name])
this.c[name].forEach(function(fn) { fn.call(this, ...args); });
},
}; };
var game_quit = function()
{
Primum.kill();
}
Signal.register("quit", game_quit);
var Event = { var Event = {
events: {}, events: {},
@ -282,6 +255,10 @@ var Event = {
this.events[name] = this.events[name].filter(x => x[0] !== obj); this.events[name] = this.events[name].filter(x => x[0] !== obj);
}, },
rm_obj(obj) {
Object.keys(this.events).forEach(name => Event.unobserve(name,obj));
},
notify(name) { notify(name) {
if (!this.events[name]) return; if (!this.events[name]) return;
this.events[name].forEach(function(x) { this.events[name].forEach(function(x) {
@ -290,6 +267,8 @@ var Event = {
}, },
}; };
Event.observe('quit', undefined, function() { Primum.kill(); });
var Window = { var Window = {
fullscreen(f) { cmd(145, f); }, fullscreen(f) { cmd(145, f); },
set width(w) { cmd(125, w); }, set width(w) { cmd(125, w); },
@ -337,6 +316,14 @@ Spline.sample_angle = function(type, points, angle) {
return spline_cmd(0, type, points[0].length, points, angle); return spline_cmd(0, type, points[0].length, points, angle);
} }
Spline.bezier_loop = function(cp)
{
cp.push(Vector.reflect_point(cp.at(-2),cp.at(-1)));
cp.push(Vector.reflect_point(cp[1],cp[0]));
cp.push(cp[0].slice());
return cp;
}
Spline.is_bezier = function(t) { return t === Spline.type.bezier; } Spline.is_bezier = function(t) { return t === Spline.type.bezier; }
Spline.is_catmull = function(t) { return t === Spline.type.catmull; } Spline.is_catmull = function(t) { return t === Spline.type.catmull; }
@ -448,6 +435,10 @@ var Game = {
edit: true, edit: true,
object_count() {
return cmd(214);
},
all_objects(fn) { all_objects(fn) {
/* Wind down from Primum */ /* Wind down from Primum */
}, },
@ -463,7 +454,7 @@ var Game = {
}, },
/* List of all objects spawned that have a specific tag */ /* List of all objects spawned that have a specific tag */
find_tag(tag) { find_tag(tag){
}, },

View file

@ -191,7 +191,7 @@ var gameobject = {
set_gravity(x) { cmd(167, this.body, x); }, set_gravity(x) { cmd(167, this.body, x); },
set timescale(x) { cmd(168,this.body,x); }, set timescale(x) { cmd(168,this.body,x); },
get timescale() { return cmd(169,this.body); }, get timescale() { return cmd(169,this.body); },
set phys(x) { console.warn(`Setting phys to ${x}`); set_body(1, this.body, x); }, set phys(x) { set_body(1, this.body, x); },
get phys() { return q_body(0,this.body); }, get phys() { return q_body(0,this.body); },
get velocity() { return q_body(3, this.body); }, get velocity() { return q_body(3, this.body); },
set velocity(x) { set_body(9, this.body, x); }, set velocity(x) { set_body(9, this.body, x); },
@ -411,7 +411,12 @@ var gameobject = {
/* Bounding box of the object in world dimensions */ /* Bounding box of the object in world dimensions */
boundingbox() { boundingbox() {
var boxes = []; var boxes = [];
boxes.push({t:0, r:0,b:0,l:0}); boxes.push({
t:0,
r:0,
b:0,
l:0
});
for (var key in this.components) { for (var key in this.components) {
if ('boundingbox' in this.components[key]) if ('boundingbox' in this.components[key])
@ -420,23 +425,11 @@ var gameobject = {
for (var key in this.objects) for (var key in this.objects)
boxes.push(this.objects[key].boundingbox()); boxes.push(this.objects[key].boundingbox());
if (boxes.empty) return cwh2bb([0,0], [0,0]); var bb = boxes.shift();
var bb = boxes[0]; boxes.forEach(function(x) { bb = bb_expand(bb, x); });
boxes.forEach(function(x) { bb = movebb(bb, this.pos);
bb = bb_expand(bb, x);
});
var cwh = bb2cwh(bb);
if (!bb) return;
if (this.flipx) cwh.c.x *= -1;
if (this.flipy) cwh.c.y *= -1;
cwh.c = cwh.c.add(this.pos);
bb = cwh2bb(cwh.c, cwh.wh);
return bb ? bb : cwh2bb([0,0], [0,0]); return bb ? bb : cwh2bb([0,0], [0,0]);
}, },
@ -519,8 +512,6 @@ var gameobject = {
this.level = undefined; this.level = undefined;
} }
Player.do_uncontrol(this); Player.do_uncontrol(this);
Register.unregister_obj(this); Register.unregister_obj(this);
@ -536,6 +527,7 @@ var gameobject = {
this.clear(); this.clear();
this.objects = undefined; this.objects = undefined;
Event.rm_obj(this);
if (typeof this.stop === 'function') if (typeof this.stop === 'function')
this.stop(); this.stop();
@ -633,16 +625,12 @@ var gameobject = {
}, },
register_hit(fn, obj) { register_hit(fn, obj) {
if (!obj) obj ??= this;
obj = this;
Signal.obj_begin(fn, obj, this); Signal.obj_begin(fn, obj, this);
}, },
register_separate(fn, obj) { register_separate(fn, obj) {
if (!obj) obj ??= this;
obj = this;
Signal.obj_separate(fn,obj,this); Signal.obj_separate(fn,obj,this);
}, },
} }

View file

@ -4,18 +4,11 @@ function compile_env(str, env, file)
return cmd(123, str, env, file); return cmd(123, str, env, file);
} }
function fcompile_env(file, env) function fcompile_env(file, env) { return compile_env(IO.slurp(file), env, file); }
{
return compile_env(IO.slurp(file), env, file);
}
var OS = { var OS = {};
get cwd() { return cmd(144); }, OS.cwd = function() { return cmd(144); }
}; OS.exec = function(s) { cmd(143, s); }
OS.exec = function(s)
{
cmd(143, s);
}
var Resources = {}; var Resources = {};
Resources.images = ["png", "jpg", "jpeg", "gif"]; Resources.images = ["png", "jpg", "jpeg", "gif"];

View file

@ -20,6 +20,7 @@
#define CGLTF_IMPLEMENTATION #define CGLTF_IMPLEMENTATION
#include <cgltf.h> #include <cgltf.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -32,6 +33,8 @@ static struct {
struct model *value; struct model *value;
} *modelhash = NULL; } *modelhash = NULL;
struct drawmodel **models = NULL;
static void processnode(); static void processnode();
static void processmesh(); static void processmesh();
static void processtexture(); static void processtexture();
@ -116,6 +119,8 @@ unsigned short pack_short_texcoord(float x, float y)
return (((unsigned short)yc) << 8) | xc; return (((unsigned short)yc) << 8) | xc;
} }
unsigned short pack_short_tex(float c) { return c * USHRT_MAX; }
uint32_t pack_int10_n2(float *norm) uint32_t pack_int10_n2(float *norm)
{ {
uint32_t ni[3]; uint32_t ni[3];
@ -157,9 +162,10 @@ void mesh_add_material(mesh *mesh, cgltf_material *mat)
sg_buffer texcoord_floats(float *f, int verts, int comp) sg_buffer texcoord_floats(float *f, int verts, int comp)
{ {
unsigned short packed[verts]; int n = verts*comp;
for (int i = 0, v = 0; v < verts; i+=comp, v++) unsigned short packed[n];
packed[v] = pack_short_texcoord(f[i], f[i+1]); for (int i = 0, v = 0; i < n; i++)
packed[i] = pack_short_tex(f[i]);
return sg_make_buffer(&(sg_buffer_desc){ return sg_make_buffer(&(sg_buffer_desc){
.data.ptr = packed, .data.ptr = packed,
@ -390,9 +396,16 @@ struct drawmodel *make_drawmodel(gameobject *go)
dm->model = NULL; dm->model = NULL;
dm->amodel = HMM_M4D(1.f); dm->amodel = HMM_M4D(1.f);
dm->go = go; dm->go = go;
arrpush(models,dm);
return dm; return dm;
} }
void model_draw_all()
{
for (int i = 0; i < arrlen(models); i++)
draw_drawmodel(models[i]);
}
void draw_drawmodel(struct drawmodel *dm) void draw_drawmodel(struct drawmodel *dm)
{ {
if (!dm->model) return; if (!dm->model) return;
@ -401,5 +414,15 @@ void draw_drawmodel(struct drawmodel *dm)
draw_model(dm->model, rst); draw_model(dm->model, rst);
} }
void free_drawmodel(struct drawmodel *dm) { free(dm); } void free_drawmodel(struct drawmodel *dm) {
int rm;
for (int i = 0; i < arrlen(models); i++)
if (models[i] == dm) {
rm = i;
break;
}
arrdelswap(models,rm);
free(dm);
}

View file

@ -53,6 +53,7 @@ void model_init();
struct drawmodel *make_drawmodel(gameobject *go); struct drawmodel *make_drawmodel(gameobject *go);
void draw_drawmodel(struct drawmodel *dm); void draw_drawmodel(struct drawmodel *dm);
void model_draw_all();
void free_drawmodel(struct drawmodel *dm); void free_drawmodel(struct drawmodel *dm);
#endif #endif

View file

@ -62,7 +62,7 @@ void mYughLog(int category, int priority, int line, const char *file, const char
char *buffer = malloc(len); char *buffer = malloc(len);
sprintf(buffer, logfmt, file, line, logstr[priority], catstr[category], msg); sprintf(buffer, logfmt, file, line, logstr[priority], catstr[category], msg);
fprintf(stderr, buffer); fprintf(stderr, "%s", buffer);
fflush(stderr); fflush(stderr);
free(msg); free(msg);

View file

@ -303,7 +303,7 @@ struct boundingbox text_bb(const unsigned char *text, float scale, float lw, flo
while (!isspace(*line) && *line != '\0') { while (!isspace(*line) && *line != '\0') {
wordWidth += font->Characters[*line].Advance * tracking * scale; wordWidth += font->Characters[*line].Advance * tracking * scale;
line++; line++;
} }
if (lw > 0 && (cursor.X + wordWidth) >= lw) { if (lw > 0 && (cursor.X + wordWidth) >= lw) {

View file

@ -25,7 +25,7 @@ struct sFont {
int descent; int descent;
int linegap; int linegap;
float emscale; float emscale;
struct Character Characters[127]; struct Character Characters[255];
sg_image texID; sg_image texID;
}; };

View file

@ -10,6 +10,8 @@
static gameobject **gameobjects; static gameobject **gameobjects;
int go_count() { return arrlen(gameobjects); }
gameobject *body2go(cpBody *body) { return cpBodyGetUserData(body); } gameobject *body2go(cpBody *body) { return cpBodyGetUserData(body); }
gameobject *shape2go(cpShape *shape) { return ((struct phys2d_shape *)cpShapeGetUserData(shape))->go; } gameobject *shape2go(cpShape *shape) { return ((struct phys2d_shape *)cpShapeGetUserData(shape))->go; }

View file

@ -53,6 +53,7 @@ struct gameobject {
typedef struct gameobject gameobject; typedef struct gameobject gameobject;
gameobject *MakeGameobject(); gameobject *MakeGameobject();
int go_count();
void gameobject_apply(gameobject *go); void gameobject_apply(gameobject *go);
void gameobject_free(gameobject *go); void gameobject_free(gameobject *go);
void gameobjects_cleanup(); void gameobjects_cleanup();

View file

@ -1120,7 +1120,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
case 143: case 143:
str = JS_ToCString(js, argv[1]); str = JS_ToCString(js, argv[1]);
// system(str); system(str);
break; break;
case 144: case 144:
@ -1349,6 +1349,12 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
case 212: case 212:
ret = jsdst(); ret = jsdst();
break; break;
case 213:
free_drawmodel(js2ptr(argv[1]));
break;
case 214:
ret = int2js(go_count());
break;
} }
if (str) if (str)

View file

@ -509,6 +509,7 @@ void full_2d_pass(struct window *window)
hudproj = HMM_Orthographic_LH_ZO(0, window->rwidth, 0, window->rheight, -1.f, 1.f); hudproj = HMM_Orthographic_LH_ZO(0, window->rwidth, 0, window->rheight, -1.f, 1.f);
sprite_draw_all(); sprite_draw_all();
model_draw_all();
call_draw(); call_draw();
//// DEBUG //// DEBUG

View file

@ -249,7 +249,7 @@ char *slurp_text(const char *filename, size_t *size)
int cp(char *p1, char *p2) int cp(char *p1, char *p2)
{ {
long len; size_t len;
void *data = slurp_file(p1, &len); void *data = slurp_file(p1, &len);
FILE *f = fopen_mkdir(p2, "w"); FILE *f = fopen_mkdir(p2, "w");

View file

@ -72,6 +72,7 @@ void script_startup() {
void script_stop() void script_stop()
{ {
timers_free(); timers_free();
script_evalf("Event.notify('quit');");
send_signal("quit",0,NULL); send_signal("quit",0,NULL);
for (int i = 0; i < shlen(jsstrs); i++) for (int i = 0; i < shlen(jsstrs); i++)

View file

@ -79,12 +79,9 @@ static int sim_play = SIM_PLAY;
int editor_mode = 0; int editor_mode = 0;
const char *engine_info() #define ENGINEINFO "Yugine version " VER ", " INFO " build.\nCopyright 2022-2024."
{
static char str[100]; const char *engine_info() { return ENGINEINFO; }
snprintf(str, 100, "Yugine version %s, %s build.\nCopyright 2022-2023 odplot productions LLC.\n", VER, INFO);
return str;
}
static int argc; static int argc;
static char **args; static char **args;

View file

@ -39,14 +39,6 @@ in float radius;
void main() void main()
{ {
if (segsize<0)
return;
float f = atan(coords.y, coords.x) + PI;
if (mod(f, segsize) < segsize/2)
discard;
float px = 1/radius; float px = 1/radius;
float R1 = 1.f; float R1 = 1.f;
float R2 = 1.0 - fill; float R2 = 1.0 - fill;
@ -57,6 +49,14 @@ void main()
float sm2 = smoothstep(R2-px,R2,dist); float sm2 = smoothstep(R2-px,R2,dist);
float a = sm*sm2; float a = sm*sm2;
color = mix(vec4(0,0,0,0), fcolor, a); color = mix(vec4(0,0,0,0), fcolor, a);
if (segsize<0)
return;
float f = atan(coords.y, coords.x) + PI;
if (mod(f, segsize) < segsize/2)
discard;
} }
@end @end