1 /* anemone, Copyright (c) 2001 Gabriel Finch
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 /*------------------------------------------------------------------------
15 | MODULE OF xscreensaver
17 | DESCRIPTION Anemone.
19 | WRITTEN BY Gabriel Finch
23 | MODIFICATIONS june 2001 started
25 +----------------------------------------------------------------------*/
29 #include "screenhack.h"
32 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
34 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
37 /*-----------------------------------------------------------------------+
39 +-----------------------------------------------------------------------*/
42 #define TWO_PI (2.0 * M_PI)
43 #define RND(x) (random() % (x))
66 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
68 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
70 int arms; /* number of arms */
71 int finpoints; /* final number of points in each array. */
72 long delay; /* usecs to wait between updates. */
74 int scrWidth, scrHeight;
80 vPend *vPendage; /* 3D representation of appendages */
81 appDef *appD; /* defaults */
85 double turn, turndelta;
87 int mx, my; /* max screen coordinates. */
98 /*-----------------------------------------------------------------------+
100 +-----------------------------------------------------------------------*/
104 /*-----------------------------------------------------------------------+
105 | PRIVATE FUNCTIONS |
106 +-----------------------------------------------------------------------*/
113 if ((ret = malloc(size)) == NULL) {
114 fprintf(stderr, "anemone: out of memory\n");
122 initAppendages(struct state *st)
125 /*int marginx, marginy; */
127 /*double scalex, scaley;*/
131 st->mx = st->scrWidth - 1;
132 st->my = st->scrHeight - 1;
134 /* each appendage will have: colour,
135 number of points, and a grow or shrink indicator */
137 /* added: growth rate 1-10 (smaller==faster growth) */
138 /* each appendage needs virtual coords (x,y,z) with y and z combining to
141 st->vPendage = (vPend *) xmalloc((st->finpoints + 1) * sizeof(vPend) * st->arms);
142 st->appD = (appDef *) xmalloc(sizeof(appDef) * st->arms);
145 for (i = 0; i < st->arms; i++) {
146 st->aCurr = st->appD + i;
147 st->vCurr = st->vPendage + (st->finpoints + 1) * i;
148 st->vNext = st->vCurr + 1;
150 st->aCurr->col = st->colors[random() % st->ncolors].pixel;
151 st->aCurr->numpt = 1;
152 st->aCurr->growth = st->finpoints / 2 + RND(st->finpoints / 2);
153 st->aCurr->rate = RND(11) * RND(11);
156 x = (1 - RND(1001) / 500);
157 y = (1 - RND(1001) / 500);
158 z = (1 - RND(1001) / 500);
159 dist = x * x + y * y + z * z;
160 } while (dist >= 1.);
162 st->vCurr->x = x * 200;
163 st->vCurr->y = st->my / 2 + y * 200;
164 st->vCurr->z = 0 + z * 200;
166 /* start the arm going outwards */
167 st->vCurr->sx = st->vCurr->x / 5;
168 st->vCurr->sy = (st->vCurr->y - st->my / 2) / 5;
169 st->vCurr->sz = (st->vCurr->z) / 5;
172 st->vNext->x = st->vCurr->x + st->vCurr->sx;
173 st->vNext->y = st->vCurr->y + st->vCurr->sy;
174 st->vNext->z = st->vCurr->z + st->vCurr->sz;
179 anemone_init (Display *disp, Window window)
181 struct state *st = (struct state *) calloc (1, sizeof(*st));
182 XWindowAttributes wa;
187 st->width = get_integer_resource(st->dpy, "width", "Integer");
188 st->arms = get_integer_resource(st->dpy, "arms", "Integer");
189 st->finpoints = get_integer_resource(st->dpy, "finpoints", "Integer");
190 st->delay = get_integer_resource(st->dpy, "delay", "Integer");
191 st->withdraw = get_integer_resource(st->dpy, "withdraw", "Integer");
192 st->turndelta = get_float_resource(st->dpy, "turnspeed", "float") / 100000;
196 # ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */
200 st->b = st->ba = st->bb = 0; /* double-buffer to reduce flicker */
201 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
202 st->b = st->backb = xdbe_get_backbuffer (st->dpy, window, XdbeUndefined);
203 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
206 XGetWindowAttributes(st->dpy, window, &wa);
207 st->scrWidth = wa.width;
208 st->scrHeight = wa.height;
209 st->cmap = wa.colormap;
211 st->ncolors = get_integer_resource (st->dpy, "colors", "Colors");
213 st->colors = (XColor *) malloc(sizeof(*st->colors) * (st->ncolors+1));
214 make_smooth_colormap (wa.screen, wa.visual, st->cmap,
215 st->colors, &st->ncolors,
218 st->gcDraw = XCreateGC(st->dpy, window, 0, &st->gcv);
219 st->gcv.foreground = get_pixel_resource(st->dpy, st->cmap,
220 "background", "Background");
221 st->gcClear = XCreateGC(st->dpy, window, GCForeground, &st->gcv);
226 st->ba = XCreatePixmap (st->dpy, window, st->scrWidth, st->scrHeight, wa.depth);
227 st->bb = XCreatePixmap (st->dpy, window, st->scrWidth, st->scrHeight, wa.depth);
236 if (st->ba) XFillRectangle (st->dpy, st->ba, st->gcClear, 0, 0, st->scrWidth, st->scrHeight);
237 if (st->bb) XFillRectangle (st->dpy, st->bb, st->gcClear, 0, 0, st->scrWidth, st->scrHeight);
239 XClearWindow(st->dpy, window);
240 XSetLineAttributes(st->dpy, st->gcDraw, st->width, LineSolid, CapRound, JoinBevel);
249 createPoints(struct state *st)
252 int withdrawall = RND(st->withdraw);
254 for (i = 0; i< st->arms; i++) {
255 st->aCurr = st->appD + i;
257 st->aCurr->growth = -st->finpoints;
258 st->turndelta = -st->turndelta;
261 else if (withdrawall<11) st->aCurr->growth = -st->aCurr->numpt;
263 else if (RND(100)<st->aCurr->rate) {
264 if (st->aCurr->growth>0) {
265 if (!(--st->aCurr->growth)) st->aCurr->growth = -RND(st->finpoints) - 1;
266 st->vCurr = st->vPendage + (st->finpoints + 1) * i + st->aCurr->numpt - 1;
267 if (st->aCurr->numpt<st->finpoints - 1) {
269 st->vNext = st->vCurr + 1;
271 st->vNext->sx = st->vCurr->sx + RND(3) - 1;
272 st->vNext->sy = st->vCurr->sy + RND(3) - 1;
273 st->vNext->sz = st->vCurr->sz + RND(3) - 1;
274 st->vCurr = st->vNext + 1;
275 st->vCurr->x = st->vNext->x + st->vNext->sx;
276 st->vCurr->y = st->vNext->y + st->vNext->sy;
277 st->vCurr->z = st->vNext->z + st->vNext->sz;
286 drawImage(struct state *st, Drawable curr_window, double sint, double cost)
288 int q,numpt,mx2 = st->mx / 2;
289 double cx,cy,cz,nx = 0,ny = 0,nz = 0;
291 if ((numpt = st->aCurr->numpt)==1) return;
292 XSetForeground(st->dpy, st->gcDraw, st->aCurr->col);
294 st->vNext = st->vCurr + 1;
301 for (q = 0; q < numpt - 1; q++) {
302 nx = st->vNext->x + 2 - RND(5);
303 ny = st->vNext->y + 2 - RND(5);
304 nz = st->vNext->z + 2 - RND(5);
306 XDrawLine(st->dpy, curr_window, st->gcDraw,
307 mx2 + cx * cost - cz * sint, cy,
308 mx2 + nx * cost - nz * sint, ny);
316 XSetLineAttributes(st->dpy, st->gcDraw, st->width * 3,
317 LineSolid, CapRound, JoinBevel);
318 XDrawLine(st->dpy, curr_window, st->gcDraw,
319 st->mx / 2 + cx * cost - cz * sint, cy,
320 st->mx / 2 + nx * cost - nz * sint, ny);
321 XSetLineAttributes(st->dpy, st->gcDraw, st->width,
322 LineSolid, CapRound, JoinBevel);
327 animateAnemone(struct state *st, Drawable curr_window)
330 double sint = sin(st->turn),cost = cos(st->turn);
332 st->aCurr = st->appD;
333 for (i = 0; i< st->arms; i++) {
334 st->vCurr = st->vPendage + (st->finpoints + 1) * i;
335 if (RND(25)<st->aCurr->rate) {
336 if (st->aCurr->growth<0) {
337 st->aCurr->numpt -= st->aCurr->numpt>1;
338 if (!(++st->aCurr->growth)) st->aCurr->growth = RND(st->finpoints - st->aCurr->numpt) + 1;
341 drawImage(st, curr_window, sint, cost);
342 st->turn += st->turndelta;
347 if (st->turn >= TWO_PI) st->turn -= TWO_PI;
351 anemone_draw (Display *dpy, Window window, void *closure)
353 struct state *st = (struct state *) closure;
355 XFillRectangle (st->dpy, st->b, st->gcClear, 0, 0, st->scrWidth, st->scrHeight);
357 animateAnemone(st, st->b);
359 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
362 XdbeSwapInfo info[1];
363 info[0].swap_window = window;
364 info[0].swap_action = XdbeUndefined;
365 XdbeSwapBuffers (st->dpy, info, 1);
368 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
371 XCopyArea (st->dpy, st->b, window, st->gcClear, 0, 0,
372 st->scrWidth, st->scrHeight, 0, 0);
373 st->b = (st->b == st->ba ? st->bb : st->ba);
381 anemone_reshape (Display *dpy, Window window, void *closure,
382 unsigned int w, unsigned int h)
384 struct state *st = (struct state *) closure;
389 XWindowAttributes wa;
390 XGetWindowAttributes(dpy, window, &wa);
391 if (st->ba) XFreePixmap (dpy, st->ba);
392 if (st->bb) XFreePixmap (dpy, st->bb);
393 st->ba = XCreatePixmap (dpy, window, st->scrWidth, st->scrHeight, wa.depth);
394 st->bb = XCreatePixmap (dpy, window, st->scrWidth, st->scrHeight, wa.depth);
401 anemone_event (Display *dpy, Window window, void *closure, XEvent *event)
407 anemone_free (Display *dpy, Window window, void *closure)
409 struct state *st = (struct state *) closure;
410 if (st->vPendage) free (st->vPendage);
411 if (st->appD) free (st->appD);
417 static const char *anemone_defaults [] = {
418 ".background: black",
426 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
428 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
430 "*ignoreRotation: True",
436 static XrmOptionDescRec anemone_options [] = {
437 { "-arms", ".arms", XrmoptionSepArg, 0 },
438 { "-finpoints", ".finpoints", XrmoptionSepArg, 0 },
439 { "-delay", ".delay", XrmoptionSepArg, 0 },
440 { "-width", ".width", XrmoptionSepArg, 0 },
441 { "-withdraw", ".withdraw", XrmoptionSepArg, 0 },
442 { "-turnspeed", ".turnspeed", XrmoptionSepArg, 0 },
443 { "-colors", ".colors", XrmoptionSepArg, 0 },
448 XSCREENSAVER_MODULE ("Anemone", anemone)