X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Ffluidballs.c;h=3e39af090763e55e2f7e1a1c0327de52498301d6;hb=39809ded547bdbb08207d3e514950425215b4410;hp=f0954fc2a55022e842f72298a5782d5a1f750536;hpb=49f5b54f312fe4ac2e9bc47581a72451bd0e8439;p=xscreensaver diff --git a/hacks/fluidballs.c b/hacks/fluidballs.c index f0954fc2..3e39af09 100644 --- a/hacks/fluidballs.c +++ b/hacks/fluidballs.c @@ -94,10 +94,11 @@ static void draw_fps_string (b_state *state) { XFillRectangle (state->dpy, state->b, state->erase_gc, - 0, state->xgwa.height - state->font_height, - state->xgwa.width, state->font_height); + 0, state->xgwa.height - state->font_height*3 - 20, + state->xgwa.width, state->font_height*3 + 20); XDrawImageString (state->dpy, state->b, state->font_gc, - 0, state->xgwa.height - state->font_baseline, + 10, state->xgwa.height - state->font_height*2 - + state->font_baseline - 10, state->fps_str, strlen(state->fps_str)); } @@ -132,7 +133,8 @@ check_window_moved (b_state *state) state->xmin = wx; state->ymin = wy; state->xmax = state->xmin + state->xgwa.width; - state->ymax = state->ymin + state->xgwa.height - state->font_height; + state->ymax = state->ymin + state->xgwa.height - (state->font_height*3) - + (state->font_height ? 22 : 0); if (state->dbuf && (state->ba)) { @@ -154,8 +156,8 @@ check_window_moved (b_state *state) XClearWindow (state->dpy, state->window); else if (state->fps_p && oymax != state->ymax) XFillRectangle (state->dpy, state->b, state->erase_gc, - 0, state->xgwa.height - state->font_height, - state->xgwa.width, state->font_height); + 0, state->xgwa.height - state->font_height*3, + state->xgwa.width, state->font_height*3); } } @@ -226,7 +228,7 @@ fluidballs_init (Display *dpy, Window window) state->dbuf = get_boolean_resource (dpy, "doubleBuffer", "Boolean"); -# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ +# ifdef HAVE_JWXYZ /* Don't second-guess Quartz's double-buffering */ state->dbuf = False; # endif @@ -294,6 +296,12 @@ fluidballs_init (Display *dpy, Window window) state->max_radius = get_float_resource (dpy, "size", "Size") / 2; if (state->max_radius < 1.0) state->max_radius = 1.0; + if (state->xgwa.width < 100 || state->xgwa.height < 100) /* tiny window */ + { + if (state->max_radius > 5) + state->max_radius = 5; + } + state->random_sizes_p = get_boolean_resource (dpy, "random", "Random"); /* If the initial window size is too small to hold all these balls, @@ -326,16 +334,21 @@ fluidballs_init (Display *dpy, Window window) state->shake_p = get_boolean_resource (dpy, "shake", "Shake"); state->shake_threshold = get_float_resource (dpy, "shakeThreshold", "ShakeThreshold"); + state->time_tick = 999999; + +# ifdef HAVE_MOBILE /* Always obey real-world gravity */ + state->shake_p = False; +# endif + state->fps_p = get_boolean_resource (dpy, "doFPS", "DoFPS"); if (state->fps_p) { XFontStruct *font; - char *fontname = get_string_resource (dpy, "font", "Font"); - const char *def_font = "fixed"; - if (!fontname || !*fontname) fontname = (char *)def_font; + char *fontname = get_string_resource (dpy, "fpsFont", "Font"); + if (!fontname) fontname = "-*-courier-bold-r-normal-*-180-*"; font = XLoadQueryFont (dpy, fontname); - if (!font) font = XLoadQueryFont (dpy, def_font); + if (!font) font = XLoadQueryFont (dpy, "fixed"); if (!font) exit(-1); gcv.font = font->fid; gcv.foreground = get_pixel_resource(state->dpy, state->xgwa.colormap, @@ -442,6 +455,21 @@ check_wall_clock (b_state *state, float max_d) state->time_since_shake += (now.tv_sec - state->last_time.tv_sec); +# ifdef HAVE_MOBILE /* Always obey real-world gravity */ + { + float a = fabs (fabs(state->accx) > fabs(state->accy) + ? state->accx : state->accy); + int rot = current_device_rotation(); + switch (rot) { + case 0: case 360: state->accx = 0; state->accy = a; break; + case -90: state->accx = -a; state->accy = 0; break; + case 90: state->accx = a; state->accy = 0; break; + case 180: case -180: state->accx = 0; state->accy = -a; break; + default: break; + } + } +# endif /* HAVE_MOBILE */ + if (state->fps_p) { float elapsed = ((now.tv_sec + (now.tv_usec / 1000000.0)) - @@ -449,9 +477,8 @@ check_wall_clock (b_state *state, float max_d) float fps = state->frame_count / elapsed; float cps = state->collision_count / elapsed; - sprintf (state->fps_str, - " FPS: %.2f Collisions: %.3f/frame Max motion: %.3f", - fps, cps/fps, max_d); + sprintf (state->fps_str, "Collisions: %.3f/frame Max motion: %.3f", + cps/fps, max_d); draw_fps_string(state); } @@ -468,28 +495,32 @@ static void repaint_balls (b_state *state) { int a; +# ifndef HAVE_JWXYZ int x1a, x2a, y1a, y2a; +# endif int x1b, x2b, y1b, y2b; float max_d = 0; -#ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ +#ifdef HAVE_JWXYZ /* Don't second-guess Quartz's double-buffering */ XClearWindow (state->dpy, state->b); #endif for (a=1; a <= state->count; a++) { GC gc; +# ifndef HAVE_JWXYZ x1a = (state->opx[a] - state->r[a] - state->xmin); y1a = (state->opy[a] - state->r[a] - state->ymin); x2a = (state->opx[a] + state->r[a] - state->xmin); y2a = (state->opy[a] + state->r[a] - state->ymin); +# endif x1b = (state->px[a] - state->r[a] - state->xmin); y1b = (state->py[a] - state->r[a] - state->ymin); x2b = (state->px[a] + state->r[a] - state->xmin); y2b = (state->py[a] + state->r[a] - state->ymin); -#ifndef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ +#ifndef HAVE_JWXYZ /* Don't second-guess Quartz's double-buffering */ #ifdef HAVE_DOUBLE_BUFFER_EXTENSION if (!state->dbeclear_p || !state->backb) #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ @@ -502,7 +533,7 @@ repaint_balls (b_state *state) 0, 360*64); } } -#endif /* !HAVE_COCOA */ +#endif /* !HAVE_JWXYZ */ if (state->mouse_ball == a) gc = state->draw_gc2; @@ -715,17 +746,29 @@ fluidballs_event (Display *dpy, Window window, void *closure, XEvent *event) return True; } else - for (i=1; i <= state->count; i++) - { - float d = ((state->px[i] - rx) * (state->px[i] - rx) + - (state->py[i] - ry) * (state->py[i] - ry)); - float r = state->r[i]; - if (d < r*r) + { + /* When trying to pick up a ball, first look for a click directly + inside the ball; but if we don't find it, expand the radius + outward until we find something nearby. + */ + float max = state->max_radius * 4; + float step = max / 10; + float r2; + for (r2 = step; r2 < max; r2 += step) { + for (i = 1; i <= state->count; i++) { - state->mouse_ball = i; - return True; + float d = ((state->px[i] - rx) * (state->px[i] - rx) + + (state->py[i] - ry) * (state->py[i] - ry)); + float r = state->r[i]; + if (r2 > r) r = r2; + if (d < r*r) + { + state->mouse_ball = i; + return True; + } } } + } return True; } else if (event->xany.type == ButtonRelease) /* drop the ball */ @@ -765,7 +808,6 @@ static const char *fluidballs_defaults [] = { ".foreground: yellow", ".textColor: yellow", "*mouseForeground: white", - ".font: -*-helvetica-*-r-*-*-*-180-*-*-p-*-*-*", "*delay: 10000", "*count: 300", "*size: 25", @@ -774,7 +816,6 @@ static const char *fluidballs_defaults [] = { "*wind: 0.00", "*elasticity: 0.97", "*timeScale: 1.0", - "*doFPS: False", "*shake: True", "*shakeThreshold: 0.015", "*doubleBuffer: True", @@ -782,6 +823,9 @@ static const char *fluidballs_defaults [] = { "*useDBE: True", "*useDBEClear: True", #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ +#ifdef HAVE_MOBILE + "*ignoreRotation: True", +#endif 0 }; @@ -793,8 +837,6 @@ static XrmOptionDescRec fluidballs_options [] = { { "-gravity", ".gravity", XrmoptionSepArg, 0 }, { "-wind", ".wind", XrmoptionSepArg, 0 }, { "-elasticity", ".elasticity", XrmoptionSepArg, 0 }, - { "-fps", ".doFPS", XrmoptionNoArg, "True" }, - { "-no-fps", ".doFPS", XrmoptionNoArg, "False" }, { "-shake", ".shake", XrmoptionNoArg, "True" }, { "-no-shake", ".shake", XrmoptionNoArg, "False" }, { "-random", ".random", XrmoptionNoArg, "True" }, @@ -806,4 +848,4 @@ static XrmOptionDescRec fluidballs_options [] = { }; -XSCREENSAVER_MODULE ("Fluidballs", fluidballs) +XSCREENSAVER_MODULE ("FluidBalls", fluidballs)