1 /* anemon, 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 +----------------------------------------------------------------------*/
33 #include "screenhack.h"
36 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
38 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
41 /*-----------------------------------------------------------------------+
43 +-----------------------------------------------------------------------*/
46 #define TWO_PI (2.0 * M_PI)
47 #define RND(x) (random() % (x))
56 static Pixmap b,ba,bb;
58 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
59 static XdbeBackBuffer backb;
60 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
63 arms, /* number of arms */
64 finpoints; /* final number of points in each array. */
65 static long delay; /* usecs to wait between updates. */
67 static int scrWidth, scrHeight;
68 static GC gcDraw, gcClear;
75 typedef unsigned short bool;
87 static vPend *vPendage; /* 3D representation of appendages */
88 static appDef *appD; /* defaults */
89 static vPend *vCurr, *vNext;
92 static double turn, turndelta;
94 static int mx, my; /* max screen coordinates. */
102 /*-----------------------------------------------------------------------+
104 +-----------------------------------------------------------------------*/
106 char *progclass = "Anemone";
108 char *defaults [] = {
109 ".background: black",
116 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
118 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
123 XrmOptionDescRec options [] = {
124 { "-arms", ".arms", XrmoptionSepArg, 0 },
125 { "-finpoints", ".finpoints", XrmoptionSepArg, 0 },
126 { "-delay", ".delay", XrmoptionSepArg, 0 },
127 { "-width", ".width", XrmoptionSepArg, 0 },
128 { "-withdraw", ".withdraw", XrmoptionSepArg, 0 },
129 { "-turnspeed", ".turnspeed", XrmoptionSepArg, 0 },
132 int options_size = (sizeof (options) / sizeof (options[0]));
134 /*-----------------------------------------------------------------------+
135 | PRIVATE FUNCTIONS |
136 +-----------------------------------------------------------------------*/
143 if ((ret = malloc(size)) == NULL) {
144 fprintf(stderr, "anemone: out of memory\n");
155 /*int marginx, marginy; */
157 /*double scalex, scaley;*/
164 /* each appendage will have: colour,
165 number of points, and a grow or shrink indicator */
167 /* added: growth rate 1-10 (smaller==faster growth) */
168 /* each appendage needs virtual coords (x,y,z) with y and z combining to
171 vPendage = (vPend *) xmalloc((finpoints + 1) * sizeof(vPend) * arms);
172 appD = (appDef *) xmalloc(sizeof(appDef) * arms);
175 for (i = 0; i < arms; i++) {
177 vCurr = vPendage + (finpoints + 1) * i;
180 aCurr->col = (long)RND(256)*RND(256)+32768;
182 aCurr->growth=finpoints/2+RND(finpoints/2);
183 aCurr->rate=RND(11)*RND(11);
198 /* start the arm going outwards */
199 vCurr->sx=vCurr->x/5;
200 vCurr->sy=(vCurr->y-my/2)/5;
201 vCurr->sz=(vCurr->z)/5;
204 vNext->x=vCurr->x+vCurr->sx;
205 vNext->y=vCurr->y+vCurr->sy;
206 vNext->z=vCurr->z+vCurr->sz;
213 XWindowAttributes wa;
217 width = get_integer_resource("width", "Integer");
218 arms = get_integer_resource("arms", "Integer");
219 finpoints = get_integer_resource("finpoints", "Integer");
220 delay = get_integer_resource("delay", "Integer");
221 withdraw = get_integer_resource("withdraw", "Integer");
222 turndelta = get_float_resource("turnspeed", "float")/100000;
227 b=ba=bb=0; /* double-buffer to reduce flicker */
228 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
229 b = backb = xdbe_get_backbuffer (dpy, window, XdbeUndefined);
230 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
233 XGetWindowAttributes(dpy, window, &wa);
235 scrHeight = wa.height;
237 gcDraw = XCreateGC(dpy, window, GCForeground, &gcv);
238 gcv.foreground = get_pixel_resource("background", "Background", dpy, cmap);
239 gcClear = XCreateGC(dpy, window, GCForeground, &gcv);
244 ba = XCreatePixmap (dpy, window, scrWidth, scrHeight, wa.depth);
245 bb = XCreatePixmap (dpy, window, scrWidth, scrHeight, wa.depth);
254 if (ba) XFillRectangle (dpy, ba, gcClear, 0, 0, scrWidth, scrHeight);
255 if (bb) XFillRectangle (dpy, bb, gcClear, 0, 0, scrWidth, scrHeight);
257 XClearWindow(dpy, window);
258 XSetLineAttributes(dpy, gcDraw, width, LineSolid, CapRound, JoinBevel);
268 int withdrawall=RND(withdraw);
270 for (i = 0; i< arms; i++) {
273 aCurr->growth=-finpoints;
274 turndelta=-turndelta;
277 else if (withdrawall<11) aCurr->growth=-aCurr->numpt;
279 else if (RND(100)<aCurr->rate) {
280 if (aCurr->growth>0) {
281 if (!(--aCurr->growth)) aCurr->growth=-RND(finpoints)-1;
282 vCurr = vPendage + (finpoints + 1) * i + aCurr->numpt-1;
283 if (aCurr->numpt<finpoints - 1) {
287 vNext->sx=vCurr->sx+RND(3)-1;
288 vNext->sy=vCurr->sy+RND(3)-1;
289 vNext->sz=vCurr->sz+RND(3)-1;
291 vCurr->x=vNext->x+vNext->sx;
292 vCurr->y=vNext->y+vNext->sy;
293 vCurr->z=vNext->z+vNext->sz;
302 drawImage(Drawable curr_window, double sint, double cost)
304 int q,numpt,mx2=mx/2;
305 double cx,cy,cz,nx,ny,nz;
307 if ((numpt=aCurr->numpt)==1) return;
308 XSetForeground(dpy, gcDraw, aCurr->col);
317 for (q = 0; q < numpt-1; q++) {
318 nx=vNext->x+2-RND(5);
319 ny=vNext->y+2-RND(5);
320 nz=vNext->z+2-RND(5);
322 XDrawLine(dpy, curr_window, gcDraw,mx2+cx*cost-cz*sint, cy, mx2+nx*cost-nz*sint, ny);
330 XSetLineAttributes(dpy, gcDraw, width*3, LineSolid, CapRound, JoinBevel);
331 XDrawLine(dpy, curr_window, gcDraw,mx/2+cx*cost-cz*sint, cy, mx/2+nx*cost-nz*sint, ny);
332 XSetLineAttributes(dpy, gcDraw, width, LineSolid, CapRound, JoinBevel);
337 animateAnemone(Drawable curr_window)
340 double sint=sin(turn),cost=cos(turn);
343 for (i = 0; i< arms; i++) {
344 vCurr=vPendage + (finpoints + 1) * i;
345 if (RND(25)<aCurr->rate) {
346 if (aCurr->growth<0) {
347 aCurr->numpt-=aCurr->numpt>1;
348 if (!(++aCurr->growth)) aCurr->growth=RND(finpoints-aCurr->numpt)+1;
351 drawImage(curr_window, sint, cost);
358 if (turn>=TWO_PI) turn-=TWO_PI;
361 /*-----------------------------------------------------------------------+
363 +-----------------------------------------------------------------------*/
366 screenhack(Display *disp, Window win)
375 XFillRectangle (dpy, b, gcClear, 0, 0, scrWidth, scrHeight);
379 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
382 XdbeSwapInfo info[1];
383 info[0].swap_window = window;
384 info[0].swap_action = XdbeUndefined;
385 XdbeSwapBuffers (dpy, info, 1);
388 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
391 XCopyArea (dpy, b, window, gcClear, 0, 0,
392 scrWidth, scrHeight, 0, 0);
393 b = (b == ba ? bb : ba);
396 screenhack_handle_events (dpy);