ref: 4338bb921e84cfb5186fe60950cf5704f997d2c2
parent: 6d347772d007e854bfcbdaecbb38abd7ef56ac6f
author: sirjofri <[email protected]>
date: Tue May 14 07:32:47 EDT 2024
adds timer support, adds blitter support (untested)
--- a/plan9.c
+++ b/plan9.c
@@ -13,6 +13,7 @@
#endif
//#define DIRECTDRAW
+//#define PROFILE
struct frontend {
Image *image;
@@ -27,8 +28,16 @@
int timeractive;
};
+struct blitter {
+ Image *blimg;
+};
+
frontend *fe = nil;
+struct proftimes {
+ long draw;
+} ptimes;
+
void
frontend_default_colour(frontend *fe, float *output)
{
@@ -90,7 +99,6 @@
}
char *showcmd = "c_game show";
-#define ugf chanprint(fe->cs->ctl, showcmd);
static void p9_draw_text(void *handle, int x, int y, int fonttype, int fontsize, int align, int color, const char *text)
{
@@ -99,7 +107,6 @@
string(screen, addpt(Pt(x, y), fe->ZP), fe->colors[color], ZP, font, text);
#else
string(fe->image, Pt(x, y), fe->colors[color], ZP, font, text);
- ugf;
#endif
}
@@ -111,7 +118,6 @@
draw(screen, rectaddpt(Rect(x, y, x+w, y+h), fe->ZP), fe->colors[color], nil, ZP);
#else
draw(fe->image, Rect(x, y, x+w, y+h), fe->colors[color], nil, ZP);
- ugf;
#endif
}
@@ -120,10 +126,9 @@
{
frontend *fe = (frontend*)handle;
#ifdef DIRECTDRAW
- line(screen, addpt(Pt(x1, y1), fe->ZP), addpt(Pt(x2, y2), fe->ZP), Endsquare, Endsquare, 1, fe->colors[color], ZP);
+ line(screen, addpt(Pt(x1, y1), fe->ZP), addpt(Pt(x2, y2), fe->ZP), Endsquare, Endsquare, 0, fe->colors[color], ZP);
#else
- line(fe->image, Pt(x1, y1), Pt(x2, y2), Endsquare, Endsquare, 1, fe->colors[color], ZP);
- ugf;
+ line(fe->image, Pt(x1, y1), Pt(x2, y2), Endsquare, Endsquare, 0, fe->colors[color], ZP);
#endif
}
@@ -132,10 +137,9 @@
{
frontend *fe = (frontend*)handle;
#ifdef DIRECTDRAW
- line(screen, addpt(Pt(x1, y1), fe->ZP), addpt(Pt(x2, y2), fe->ZP), Endsquare, Endsquare, thickness, fe->colors[color], ZP);
+ line(screen, addpt(Pt(x1, y1), fe->ZP), addpt(Pt(x2, y2), fe->ZP), Endsquare, Endsquare, thickness-1, fe->colors[color], ZP);
#else
- line(fe->image, Pt(x1, y1), Pt(x2, y2), Endsquare, Endsquare, thickness, fe->colors[color], ZP);
- ugf;
+ line(fe->image, Pt(x1, y1), Pt(x2, y2), Endsquare, Endsquare, thickness-1, fe->colors[color], ZP);
#endif
}
@@ -166,7 +170,6 @@
fillpoly(fe->image, points, npoints, 0, fe->colors[fillcolor], ZP);
if (outlinecolor > 0)
poly(fe->image, points, npoints, Endsquare, Endsquare, 1, fe->colors[outlinecolor], ZP);
- ugf;
#endif
free(points);
@@ -184,7 +187,6 @@
Point c = Pt(cx, cy);
fillellipse(fe->image, c, radius, radius, fe->colors[fillcolor], ZP);
ellipse(fe->image, c, radius, radius, 0, fe->colors[outlinecolor], ZP);
- ugf;
#endif
}
@@ -191,28 +193,43 @@
static void
p9_draw_update(void *handle, int x, int y, int w, int h)
{
- frontend *fe = (frontend*)handle;
- chanprint(fe->cs->ctl, showcmd);
+ //frontend *fe = (frontend*)handle;
+ //print("draw_update\n");
+ //chanprint(fe->cs->ctl, showcmd);
}
static void
p9_clip(void *handle, int x, int y, int w, int h)
{
+ frontend *fe = (frontend*)handle;
+ fe->image->clipr = Rect(x, y, x + w, y + h);
}
static void
p9_unclip(void *handle)
{
+ frontend *fe = (frontend*)handle;
+ fe->image->clipr = fe->image->r;
}
+long drawtime;
+
static void
p9_start_draw(void *handle)
{
+#ifdef PROFILE
+ drawtime = times(nil);
+#endif
}
static void
p9_end_draw(void *handle)
{
+ frontend *fe = (frontend*)handle;
+ chanprint(fe->cs->ctl, showcmd);
+#ifdef PROFILE
+ ptimes.draw = times(nil) - drawtime;
+#endif
}
static void
@@ -226,22 +243,31 @@
static blitter*
p9_blitter_new(void *handle, int w, int h)
{
- return nil;
+ blitter *bl;
+ bl = malloc(sizeof(blitter));
+ bl->blimg = allocimage(display, Rect(0, 0, w, h), screen->chan, 0, 0);
+ return bl;
}
static void
p9_blitter_free(void *handle, blitter *bl)
{
+ freeimage(bl->blimg);
+ free(bl);
}
static void
p9_blitter_save(void *handle, blitter *bl, int x, int y)
{
+ frontend *fe = (frontend*)handle;
+ draw(bl->blimg, Rect(x, y, x + bl->blimg->r.max.x, y + bl->blimg->r.max.y), fe->image, nil, Pt(x, y)); // fix ZP if needed
}
static void
p9_blitter_load(void *handle, blitter *bl, int x, int y)
{
+ frontend *fe = (frontend*)handle;
+ draw(fe->image, Rect(x, y, x + bl->blimg->r.max.x, y + bl->blimg->r.max.y), bl->blimg, nil, Pt(x, y));
}
static const drawing_api p9_drawing = {
@@ -319,8 +345,9 @@
b_settings = createtextbutton(cs, "b_settings");
p = stringsize(font, "settings");
- chanprint(cs->ctl, "b_settings text settings");
+ chanprint(cs->ctl, "b_settings border 1");
chanprint(cs->ctl, "b_settings align center");
+ chanprint(cs->ctl, "b_settings text settings");
chanprint(cs->ctl, "b_settings size %d %d 500 %d", p.x, p.y, p.y);
c_settings = createcolumn(cs, "c_settings");
controlwire(c_settings, "event", c);
@@ -337,24 +364,6 @@
}
void
-timerthread(void *v)
-{
- Channel *c;
- long totaltime;
- long newtime;
-
- c = v;
- totaltime = times(nil);
-
- for (;;) {
- sleep(100); /* minimum tick time */
- newtime = times(nil);
- chanprint(c, "tick: %ld\n", newtime - totaltime);
- totaltime = newtime;
- }
-}
-
-void
initfe(frontend *fe)
{
float *colors;
@@ -386,9 +395,6 @@
namectlimage(display->white, "i_white");
namectlimage(fe->background, "background");
initui(fe->cs, fe->c);
-
- // needs different timer option - atnotify(2) / alarm(2) ?
- //threadcreate(timerthread, fe->c, 4096);
}
int windowset = 0;
@@ -563,6 +569,9 @@
case 'q':
case 127:
return 1; /* return 1 to quit */
+ case 'n':
+ midend_process_key(fe->me, 0, 0, UI_NEWGAME);
+ break;
default:
if (k >= 0 && midend_process_key(fe->me, 0, 0, k) == PKR_QUIT)
return 1;
@@ -573,12 +582,45 @@
void
tick(float delta)
{
+ char msg[128];
+
if (fe->timeractive) {
midend_timer(fe->me, delta);
}
+
+#ifdef PROFILE
+ snprint(msg, 128, "draw: %ld", ptimes.draw);
+ chanprint(fe->cs->ctl, "l_status value %q", msg);
+#endif
}
+typedef struct Tickinfo Tickinfo;
+struct Tickinfo {
+ long totaltime;
+ long lasttick;
+ float delta;
+};
+
void
+timerproc(void *v)
+{
+ Channel *c;
+ Tickinfo ti;
+ long newtime;
+
+ c = v;
+ ti.totaltime = times(nil);
+
+ for (;;) {
+ sleep(20);
+ newtime = times(nil);
+ ti.delta = (newtime - ti.totaltime) / 1000.;
+ ti.totaltime = newtime;
+ send(c, &ti.delta);
+ }
+}
+
+void
threadmain(int argc, char **argv)
{
int x, y, n, r;
@@ -590,6 +632,12 @@
Channel *c;
config_item *cfg;
int changedprefs = 0;
+ float delta;
+ Alt a[] = {
+ { nil, &s, CHANRCV },
+ { nil, &delta, CHANRCV },
+ { nil, nil, CHANEND },
+ };
fe = new_window();
@@ -632,55 +680,63 @@
midend_new_game(fe->me);
resizecontrolset(fe->cs);
+ a[0].c = fe->c;
+ a[1].c = chancreate(sizeof(float), 0);
+
+ proccreate(timerproc, a[1].c, 4096);
+
for (;;) {
- s = recvp(fe->c);
- n = tokenize(s, args, nelem(args));
-
- if (strcmp(args[0], "c_settings:") == 0) {
- print("c_settings event: %s\n", args[1]);
- } else
- if (strcmp(args[0], "c_game:") == 0) {
- if (strcmp(args[1], "mouse") == 0) {
- x = atoi(args[2]+1) - fe->ZP.x; /* ignore '[' */
- y = atoi(args[3]) - fe->ZP.y;
- n = atoi(args[4]);
- r = -1;
- if ( (lastmouse&1) && !(n&1))
- r = midend_process_key(fe->me, x, y, LEFT_RELEASE);
- if (!(lastmouse&1) && (n&1))
- r = midend_process_key(fe->me, x, y, LEFT_BUTTON);
- if ( (lastmouse&2) && !(n&2))
- r = midend_process_key(fe->me, x, y, MIDDLE_RELEASE);
- if (!(lastmouse&2) && (n&2))
- r = midend_process_key(fe->me, x, y, MIDDLE_BUTTON);
- if ( (lastmouse&4) && !(n&4))
- r = midend_process_key(fe->me, x, y, RIGHT_RELEASE);
- if (!(lastmouse&4) && (n&2))
- r = midend_process_key(fe->me, x, y, RIGHT_BUTTON);
- if (r >= 0) {
- chanprint(fe->cs->ctl, showcmd);
+ switch (alt(a)) {
+ case 0: /* libcontrol event channel */
+ n = tokenize(s, args, nelem(args));
+
+ if (strcmp(args[0], "c_settings:") == 0) {
+ print("c_settings event: %s\n", args[1]);
+ } else
+ if (strcmp(args[0], "c_game:") == 0) {
+ if (strcmp(args[1], "mouse") == 0) {
+ x = atoi(args[2]+1) - fe->ZP.x; /* ignore '[' */
+ y = atoi(args[3]) - fe->ZP.y;
+ n = atoi(args[4]);
+ r = -1;
+ if ( (lastmouse&1) && !(n&1))
+ r = midend_process_key(fe->me, x, y, LEFT_RELEASE);
+ if (!(lastmouse&1) && (n&1))
+ r = midend_process_key(fe->me, x, y, LEFT_BUTTON);
+ if ( (lastmouse&2) && !(n&2))
+ r = midend_process_key(fe->me, x, y, MIDDLE_RELEASE);
+ if (!(lastmouse&2) && (n&2))
+ r = midend_process_key(fe->me, x, y, MIDDLE_BUTTON);
+ if ( (lastmouse&4) && !(n&4))
+ r = midend_process_key(fe->me, x, y, RIGHT_RELEASE);
+ if (!(lastmouse&4) && (n&2))
+ r = midend_process_key(fe->me, x, y, RIGHT_BUTTON);
+ if (r >= 0) {
+ chanprint(fe->cs->ctl, showcmd);
+ }
+ lastmouse = n;
+ } else
+ if (strcmp(args[1], "key") == 0) {
+ l = strtol(args[2], nil, 0);
+ if (keyev(l))
+ goto Out;
}
- lastmouse = n;
} else
- if (strcmp(args[1], "key") == 0) {
- l = strtol(args[2], nil, 0);
- if (keyev(l))
- break;
- }
- } else
- if (strcmp(args[0], "b_game:") == 0) {
- showframe(0);
- chanprint(fe->cs->ctl, "b_game value 0");
- } else
- if (strcmp(args[0], "b_settings:") == 0) {
- showframe(1);
- chanprint(fe->cs->ctl, "b_settings value 0");
- } else
- if (strcmp(args[0], "tick:") == 0) {
- l = strtol(args[1], nil, 0);
- tick(l / 1000.);
- } else
- print("event from %s: %s\n", args[0], args[1]);
+ if (strcmp(args[0], "b_game:") == 0) {
+ showframe(0);
+ chanprint(fe->cs->ctl, "b_game value 0");
+ } else
+ if (strcmp(args[0], "b_settings:") == 0) {
+ showframe(1);
+ chanprint(fe->cs->ctl, "b_settings value 0");
+ } else
+ print("event from %s: %s\n", args[0], args[1]);
+ break;
+ case 1: /* timer */
+ tick(delta);
+ break;
+ }
}
+Out:
threadexitsall(nil);
}