aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/sdlcircles.tcl28
-rw-r--r--examples/sdltest.tcl58
-rw-r--r--jim-sdl.c434
3 files changed, 348 insertions, 172 deletions
diff --git a/examples/sdlcircles.tcl b/examples/sdlcircles.tcl
new file mode 100644
index 0000000..8d1274d
--- /dev/null
+++ b/examples/sdlcircles.tcl
@@ -0,0 +1,28 @@
+package require sdl
+
+set xres 1024
+set yres 768
+set s [sdl.screen $xres $yres "Jim SDL Circles"]
+
+proc drawlist {s list} {
+ foreach item $list {
+ $s {*}$item
+ }
+}
+
+proc rand_circle {xres yres maxradius alpha} {
+ list fcircle [rand $xres] [rand $yres] [rand $maxradius] [rand 256] [rand 256] [rand 256] $alpha
+}
+
+loop i 0 200 {
+ set commands {}
+ loop j 0 1000 {
+ lappend commands [rand_circle $xres $yres 40 100]
+ if {$j % 50 == 0} {
+ #$s clear 200 200 200
+ drawlist $s $commands
+ $s flip
+ sleep 0.1
+ }
+ }
+}
diff --git a/examples/sdltest.tcl b/examples/sdltest.tcl
index 6607574..cf42d88 100644
--- a/examples/sdltest.tcl
+++ b/examples/sdltest.tcl
@@ -1,28 +1,46 @@
package require sdl
-set xres 1024
-set yres 768
+# Basic test of all sdl commands
+
+set xres 640
+set yres 384
set s [sdl.screen $xres $yres]
-proc drawlist {s list} {
- foreach item $list {
- $s {*}$item
- }
-}
+set cyan {0 255 255 200}
+set yellow {255 255 0 200}
+set red {255 0 0 200}
+set green {0 255 0 200}
+set grey {50 50 50 200}
+set white {255 255 255}
+set blue {0 0 255 200}
+
+$s clear {*}$grey
-proc rand_circle {xres yres maxradius alpha} {
- list fcircle [rand $xres] [rand $yres] [rand $maxradius] [rand 256] [rand 256] [rand 256] $alpha
+$s fcircle 320 280 40 {*}$cyan
+$s circle 320 280 60 {*}$yellow
+$s aacircle 320 280 80 {*}$green
+
+$s rectangle 200 100 300 180 {*}$cyan
+$s box 210 110 290 170 {*}$yellow
+
+set x 20
+set y 20
+set dy 10
+set dx 10
+foreach i [range 50] {
+ set nx $($x + $dx)
+ set ny $($y + $dy)
+ $s line $x $y $nx $ny {*}$green
+ $s aaline $x $($y+30) $nx $($ny+30) {*}$red
+ set x $nx
+ set y $ny
+ set dy $(-$dy)
}
-loop i 0 200 {
- set commands {}
- loop j 0 1000 {
- lappend commands [rand_circle $xres $yres 40 100]
- if {$j % 50 == 0} {
- #$s clear 200 200 200
- drawlist $s $commands
- $s flip
- sleep 0.1
- }
- }
+$s rectangle 50 200 150 300 {*}$yellow
+foreach i [range 500] {
+ $s pixel $([rand 100] + 50) $([rand 100] + 200) {*}$white
}
+
+$s poll { sleep 0.25 }
+$s free
diff --git a/jim-sdl.c b/jim-sdl.c
index be4fe41..32b2a20 100644
--- a/jim-sdl.c
+++ b/jim-sdl.c
@@ -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;
}