diff options
author | Steve Bennett <steveb@workware.net.au> | 2020-12-30 13:54:59 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2021-01-01 16:54:26 +1000 |
commit | 8e818b3a5ee8647b746bf7ce7d601ca42b6a0ec4 (patch) | |
tree | 22c44e4d9e1f7fcb5f92c45ddb5924d3372ea4f5 /jim-sdl.c | |
parent | 3b834e42ee5887f85d10d7e50814b29d1b81a09f (diff) | |
download | jimtcl-8e818b3a5ee8647b746bf7ce7d601ca42b6a0ec4.zip jimtcl-8e818b3a5ee8647b746bf7ce7d601ca42b6a0ec4.tar.gz jimtcl-8e818b3a5ee8647b746bf7ce7d601ca42b6a0ec4.tar.bz2 |
sdl: convert to using jim-subcmd
And add:
- poll ?script?
- optional window title
Signed-off-by: Steve Bennett <steveb@workware.net.au>
Diffstat (limited to 'jim-sdl.c')
-rw-r--r-- | jim-sdl.c | 434 |
1 files changed, 282 insertions, 152 deletions
@@ -44,6 +44,9 @@ #endif #include <jim.h> +#include <jim-subcmd.h> + +static int jim_sdl_initialised; typedef struct JimSdlSurface { @@ -54,7 +57,6 @@ typedef struct JimSdlSurface #else SDL_Surface *screen; #endif - long background[4]; } JimSdlSurface; static void JimSdlSetError(Jim_Interp *interp) @@ -100,182 +102,312 @@ static void JimSdlClear(JimSdlSurface *jss, int r, int g, int b, int alpha) #endif } -/* Calls to commands created via [sdl.surface] are implemented by this - * C command. */ -static int JimSdlHandlerCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +/* Process the event loop, throwing away all events except quit. + * On quit, return JIM_EXIT. + * If necessary, this can be caught with catch -exit { ... } + */ +static int JimSdlPoll(Jim_Interp *interp) +{ + SDL_Event e; + while (SDL_PollEvent(&e)) { + if (e.type == SDL_QUIT) { + Jim_SetResultInt(interp, 0); + return JIM_EXIT; + } + } + return JIM_OK; +} + +static int jim_sdl_subcmd_free(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_DeleteCommand(interp, argv[0]); + return JIM_OK; +} + +/* [sdl flip] - present the current image, clear the new image, poll for events. + * Returns JIM_EXIT on quit event + */ +static int jim_sdl_subcmd_flip(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { JimSdlSurface *jss = Jim_CmdPrivData(interp); - int option; - static const char * const options[] = { - "free", "flip", "pixel", "rectangle", "box", "line", "aaline", - "circle", "aacircle", "fcircle", "clear", NULL - }; - enum - { OPT_FREE, OPT_FLIP, OPT_PIXEL, OPT_RECTANGLE, OPT_BOX, OPT_LINE, - OPT_AALINE, OPT_CIRCLE, OPT_AACIRCLE, OPT_FCIRCLE, OPT_CLEAR - }; - - if (argc < 2) { - Jim_WrongNumArgs(interp, 1, argv, "method ?args ...?"); +#if SDL_MAJOR_VERSION == 2 + SDL_RenderPresent(jss->screen); +#else + SDL_Flip(jss->screen); +#endif + JimSdlClear(jss, 0, 0, 0, SDL_ALPHA_OPAQUE); + + return JimSdlPoll(interp); +} + +/* [sdl poll ?script?] - present the current image, poll for events. + * Returns JIM_EXIT on quit event or JIM_OK if all events processed. + * + * If the script is given, evaluates the script on each poll loop until + * either quit event is received or the script returns something other than JIM_OK. + */ +static int jim_sdl_subcmd_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int ret = JIM_OK; +#if SDL_MAJOR_VERSION == 2 + JimSdlSurface *jss = Jim_CmdPrivData(interp); + SDL_RenderPresent(jss->screen); +#endif + while (ret == JIM_OK) { + ret = JimSdlPoll(interp); + if (ret != JIM_OK || argc != 1) { + break; + } + ret = Jim_EvalObj(interp, argv[0]); + } + return ret; +} + +static int jim_sdl_subcmd_clear(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + JimSdlSurface *jss = Jim_CmdPrivData(interp); + long vals[4]; + if (JimSdlGetLongs(interp, argc, argv, vals) != JIM_OK) { return JIM_ERR; } - if (Jim_GetEnum(interp, argv[1], options, &option, "SDL surface method", JIM_ERRMSG) != JIM_OK) + if (argc == 3) { + vals[3] = SDL_ALPHA_OPAQUE; + } + JimSdlClear(jss, vals[0], vals[1], vals[2], vals[3]); + return JIM_OK; +} + +static int jim_sdl_subcmd_pixel(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + JimSdlSurface *jss = Jim_CmdPrivData(interp); + long vals[6]; + if (JimSdlGetLongs(interp, argc, argv, vals) != JIM_OK) { return JIM_ERR; - if (option == OPT_PIXEL) { - /* PIXEL */ - /* x, y, red, green, blue, alpha = 255 */ - long vals[7]; + } + if (argc == 5) { + vals[5] = SDL_ALPHA_OPAQUE; + } + pixelRGBA(jss->screen, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5]); + return JIM_OK; +} - if (argc != 7 && argc != 8) { - Jim_WrongNumArgs(interp, 2, argv, "x y red green blue ?alpha?"); - return JIM_ERR; - } - if (JimSdlGetLongs(interp, argc - 3, argv + 3, vals) != JIM_OK) { - return JIM_ERR; - } - pixelRGBA(jss->screen, vals[0], vals[1], vals[2], vals[3], vals[4], argc == 8 ? vals[5] : SDL_ALPHA_OPAQUE); - return JIM_OK; +static int jim_sdl_subcmd_circle(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + JimSdlSurface *jss = Jim_CmdPrivData(interp); + long vals[7]; + if (JimSdlGetLongs(interp, argc, argv, vals) != JIM_OK) { + return JIM_ERR; + } + if (argc == 6) { + vals[6] = SDL_ALPHA_OPAQUE; } - else if (option == OPT_RECTANGLE || option == OPT_BOX || - option == OPT_LINE || option == OPT_AALINE) { - /* RECTANGLE, BOX, LINE, AALINE */ - long x1, y1, x2, y2, red, green, blue, alpha = 255; + circleRGBA(jss->screen, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6]); + return JIM_OK; +} - if (argc != 9 && argc != 10) { - Jim_WrongNumArgs(interp, 2, argv, "x y red green blue ?alpha?"); - return JIM_ERR; - } - if (Jim_GetLong(interp, argv[2], &x1) != JIM_OK || - Jim_GetLong(interp, argv[3], &y1) != JIM_OK || - Jim_GetLong(interp, argv[4], &x2) != JIM_OK || - Jim_GetLong(interp, argv[5], &y2) != JIM_OK || - Jim_GetLong(interp, argv[6], &red) != JIM_OK || - Jim_GetLong(interp, argv[7], &green) != JIM_OK || - Jim_GetLong(interp, argv[8], &blue) != JIM_OK) { - return JIM_ERR; - } - if (argc == 10 && Jim_GetLong(interp, argv[9], &alpha) != JIM_OK) - return JIM_ERR; - switch (option) { - case OPT_RECTANGLE: - rectangleRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); - break; - case OPT_BOX: - boxRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); - break; - case OPT_LINE: - lineRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); - break; - case OPT_AALINE: - aalineRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); - break; - } - return JIM_OK; +static int jim_sdl_subcmd_aacircle(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + JimSdlSurface *jss = Jim_CmdPrivData(interp); + long vals[7]; + if (JimSdlGetLongs(interp, argc, argv, vals) != JIM_OK) { + return JIM_ERR; } - else if (option == OPT_CIRCLE || option == OPT_AACIRCLE || option == OPT_FCIRCLE) { - /* CIRCLE, AACIRCLE, FCIRCLE */ - long x, y, radius, red, green, blue, alpha = 255; + if (argc == 6) { + vals[6] = SDL_ALPHA_OPAQUE; + } + aacircleRGBA(jss->screen, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6]); + return JIM_OK; +} - if (argc != 8 && argc != 9) { - Jim_WrongNumArgs(interp, 2, argv, "x y radius red green blue ?alpha?"); - return JIM_ERR; - } - if (Jim_GetLong(interp, argv[2], &x) != JIM_OK || - Jim_GetLong(interp, argv[3], &y) != JIM_OK || - Jim_GetLong(interp, argv[4], &radius) != JIM_OK || - Jim_GetLong(interp, argv[5], &red) != JIM_OK || - Jim_GetLong(interp, argv[6], &green) != JIM_OK || - Jim_GetLong(interp, argv[7], &blue) != JIM_OK) { - return JIM_ERR; - } - if (argc == 9 && Jim_GetLong(interp, argv[8], &alpha) != JIM_OK) - return JIM_ERR; - switch (option) { - case OPT_CIRCLE: - circleRGBA(jss->screen, x, y, radius, red, green, blue, alpha); - break; - case OPT_AACIRCLE: - aacircleRGBA(jss->screen, x, y, radius, red, green, blue, alpha); - break; - case OPT_FCIRCLE: - filledCircleRGBA(jss->screen, x, y, radius, red, green, blue, alpha); - break; - } - return JIM_OK; +static int jim_sdl_subcmd_fcircle(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + JimSdlSurface *jss = Jim_CmdPrivData(interp); + long vals[7]; + if (JimSdlGetLongs(interp, argc, argv, vals) != JIM_OK) { + return JIM_ERR; } - else if (option == OPT_FREE) { - /* FREE */ - if (argc != 2) { - Jim_WrongNumArgs(interp, 2, argv, ""); - return JIM_ERR; - } - Jim_DeleteCommand(interp, argv[0]); - return JIM_OK; + if (argc == 6) { + vals[6] = SDL_ALPHA_OPAQUE; } - else if (option == OPT_CLEAR) { - long vals[4]; - if (argc != 5 && argc != 6) { - Jim_WrongNumArgs(interp, 2, argv, "red green blue ?alpha?"); - return JIM_ERR; - } - if (JimSdlGetLongs(interp, argc - 2, argv + 2, vals) != JIM_OK) { - return JIM_ERR; - } - if (argc == 5) { - vals[3] = SDL_ALPHA_OPAQUE; - } - JimSdlClear(jss, vals[0], vals[1], vals[2], vals[3]); + filledCircleRGBA(jss->screen, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6]); + return JIM_OK; +} + +static int jim_sdl_subcmd_rectangle(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + JimSdlSurface *jss = Jim_CmdPrivData(interp); + long vals[8]; + if (JimSdlGetLongs(interp, argc, argv, vals) != JIM_OK) { + return JIM_ERR; } - else if (option == OPT_FLIP) { - /* FLIP */ - if (argc != 2) { - Jim_WrongNumArgs(interp, 2, argv, ""); - return JIM_ERR; - } - { - SDL_Event e; -#if SDL_MAJOR_VERSION == 2 - SDL_RenderPresent(jss->screen); -#else - SDL_Flip(jss->screen); -#endif - JimSdlClear(jss, 0, 0, 0, SDL_ALPHA_OPAQUE); - /* Throw away all events except quit, and pass this back as JIM_EXIT. - * If necessary, this can be caught with catch -exit { ... } - */ - while (SDL_PollEvent(&e)) { - if (e.type == SDL_QUIT) { - Jim_SetResultInt(interp, 0); - return JIM_EXIT; - } - } - } - return JIM_OK; + if (argc == 7) { + vals[7] = SDL_ALPHA_OPAQUE; } + rectangleRGBA(jss->screen, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7]); return JIM_OK; } +static int jim_sdl_subcmd_box(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + JimSdlSurface *jss = Jim_CmdPrivData(interp); + long vals[8]; + if (JimSdlGetLongs(interp, argc, argv, vals) != JIM_OK) { + return JIM_ERR; + } + if (argc == 7) { + vals[7] = SDL_ALPHA_OPAQUE; + } + boxRGBA(jss->screen, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7]); + return JIM_OK; +} + +static int jim_sdl_subcmd_line(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + JimSdlSurface *jss = Jim_CmdPrivData(interp); + long vals[8]; + if (JimSdlGetLongs(interp, argc, argv, vals) != JIM_OK) { + return JIM_ERR; + } + if (argc == 7) { + vals[7] = SDL_ALPHA_OPAQUE; + } + lineRGBA(jss->screen, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7]); + return JIM_OK; +} + +static int jim_sdl_subcmd_aaline(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + JimSdlSurface *jss = Jim_CmdPrivData(interp); + long vals[8]; + if (JimSdlGetLongs(interp, argc, argv, vals) != JIM_OK) { + return JIM_ERR; + } + if (argc == 7) { + vals[7] = SDL_ALPHA_OPAQUE; + } + aalineRGBA(jss->screen, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7]); + return JIM_OK; +} + +static const jim_subcmd_type sdl_command_table[] = { + { "free", + NULL, + jim_sdl_subcmd_free, + 0, + 0, + JIM_MODFLAG_FULLARGV, + }, + { "flip", + NULL, + jim_sdl_subcmd_flip, + 0, + 0, + }, + { "poll", + "?script?", + jim_sdl_subcmd_poll, + 0, + 1, + }, + { "clear", + "red green blue ?alpha?", + jim_sdl_subcmd_clear, + 3, + 4, + }, + { "pixel", + "x y red green blue ?alpha?", + jim_sdl_subcmd_pixel, + 5, + 6, + }, + { "circle", + "x y radius red green blue ?alpha?", + jim_sdl_subcmd_circle, + 6, + 7, + }, + { "aacircle", + "x y radius red green blue ?alpha?", + jim_sdl_subcmd_aacircle, + 6, + 7, + }, + { "fcircle", + "x y radius red green blue ?alpha?", + jim_sdl_subcmd_fcircle, + 6, + 7, + }, + { "rectangle", + "x1 y1 x2 y2 red green blue ?alpha?", + jim_sdl_subcmd_rectangle, + 7, + 8, + }, + { "box", + "x1 y1 x2 y2 red green blue ?alpha?", + jim_sdl_subcmd_box, + 7, + 8, + }, + { "line", + "x1 y1 x2 y2 red green blue ?alpha?", + jim_sdl_subcmd_line, + 7, + 8, + }, + { "aaline", + "x1 y1 x2 y2 red green blue ?alpha?", + jim_sdl_subcmd_aaline, + 7, + 8, + }, + { NULL } +}; + +/* Calls to commands created via [sdl.surface] are implemented by this + * C command. */ +static int JimSdlHandlerCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, sdl_command_table, argc, argv); + + return Jim_CallSubCmd(interp, ct, argc, argv); +} + static int JimSdlSurfaceCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { JimSdlSurface *jss; char buf[128]; - long xres, yres; + long vals[2]; + const char *title; - if (argc != 3) { - Jim_WrongNumArgs(interp, 1, argv, "xres yres"); + if (argc != 3 && argc != 4) { + Jim_WrongNumArgs(interp, 1, argv, "xres yres ?title?"); return JIM_ERR; } - if (Jim_GetLong(interp, argv[1], &xres) != JIM_OK || - Jim_GetLong(interp, argv[2], &yres) != JIM_OK) + + if (JimSdlGetLongs(interp, 2, argv + 1, vals) != JIM_OK) { return JIM_ERR; + } + + if (!jim_sdl_initialised) { + jim_sdl_initialised++; + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + JimSdlSetError(interp); + return JIM_ERR; + } + atexit(SDL_Quit); + } + + title = (argc == 4) ? Jim_String(argv[3]) : "sdl"; jss = Jim_Alloc(sizeof(*jss)); memset(jss, 0, sizeof(*jss)); - jss->background[3] = SDL_ALPHA_OPAQUE; #if SDL_MAJOR_VERSION == 2 /* Try to create the surface */ - jss->win = SDL_CreateWindow("sdl", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, xres, yres, 0); + jss->win = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, vals[0], vals[1], 0); if (jss->win) { jss->screen = SDL_CreateRenderer(jss->win, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); if (jss->screen) { @@ -287,7 +419,10 @@ static int JimSdlSurfaceCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar } } #else - jss->screen = SDL_SetVideoMode(xres, yres, 32, SDL_SWSURFACE | SDL_ANYFORMAT); + jss->screen = SDL_SetVideoMode(vals[0], vals[1], 32, SDL_SWSURFACE | SDL_ANYFORMAT); + if (jss->screen) { + SDL_WM_SetCaption(title, title); + } #endif if (jss->screen) { JimSdlClear(jss, 0, 0, 0, SDL_ALPHA_OPAQUE); @@ -310,11 +445,6 @@ int Jim_sdlInit(Jim_Interp *interp) if (Jim_PackageProvide(interp, "sdl", "1.0", JIM_ERRMSG)) return JIM_ERR; - if (SDL_Init(SDL_INIT_VIDEO) < 0) { - JimSdlSetError(interp); - return JIM_ERR; - } - atexit(SDL_Quit); Jim_CreateCommand(interp, "sdl.screen", JimSdlSurfaceCommand, NULL, NULL); return JIM_OK; } |