Annotation of Examples/AppKit/BackspaceViews/Sperm/SpermView.m, revision 1.1

1.1     ! root        1: /*
        !             2:     The animation guts from a freely distributable X program:
        !             3:        xsperm.c
        !             4:        Drew Olbrich, Febrary 1991
        !             5:        Note --  This code originally served as a demonstration
        !             6:        of how to do animation under X.  The "guts" of the program
        !             7:        which draws the sperm are consequently located in one huge
        !             8:        chunk in the update_display() routine, and can be easily
        !             9:        cut out.
        !            10: 
        !            11:     The animation function wrapped in a NeXTstep View subclass by Ali Ozer, May 91
        !            12:        Very minor changes so this thing works as a screen saver module by sam streeper,
        !            13:        August 91
        !            14:     The "oneStep" method computes new locations.
        !            15: */
        !            16: 
        !            17: #import "SpermView.h"
        !            18: #import "Thinker.h"
        !            19: #import <appkit/appkit.h>
        !            20: 
        !            21: #define VEC_DOT(x, y) (x[0]*y[0] + x[1]*y[1])
        !            22: #define VEC_LEN(x) (sqrt(x[0]*x[0] + x[1]*x[1]))
        !            23: 
        !            24: #define VEC_SET(x, a, b) x[0] = a, x[1] = b
        !            25: #define VEC_COPY(y, x) y[0] = x[0], y[1] = x[1]
        !            26: #define VEC_NEG(x) x[0] = -x[0], x[1] = -x[1]
        !            27: #define VEC_ADD(z, x, y) z[0] = x[0] + y[0], z[1] = x[1] + y[1]
        !            28: #define VEC_SUB(z, x, y) z[0] = x[0] - y[0], z[1] = x[1] - y[1]
        !            29: #define VEC_MULT(x, a) x[0] *= a, x[1] *= a
        !            30: #define VEC_DIV(x, a) x[0] /= a, x[1] /= a
        !            31: #define VEC_ADDS(z, x, a, y) z[0] = x[0] + (a)*y[0], z[1] = x[1] + (a)*y[1]
        !            32: #define VEC_NORM(x) { double l = VEC_LEN(x); VEC_DIV(x, l); }
        !            33: 
        !            34: #define MINRAD 0.1
        !            35: #define RADSTEP 2.0
        !            36: #define MAXRAD (MINRAD * RADSTEP * RADSTEP * RADSTEP * RADSTEP * RADSTEP * RADSTEP)
        !            37: #define INITRAD (MINRAD * RADSTEP * RADSTEP * RADSTEP)
        !            38: 
        !            39: // RANDINT(n) returns an integer 0..n-1
        !            40: // RANDFLOAT(f) returns a float [0..f] (inclusive on both ends)
        !            41: 
        !            42: #define RANDINT(n) (random() % (n))
        !            43: #define RANDFLOAT(f) (((f) * (float)(random() & 0x0ffff)) / (float)0x0ffff)
        !            44: 
        !            45: @implementation SpermView
        !            46: 
        !            47: - initFrame:(const NXRect *)rect
        !            48: {
        !            49:        [super initFrame:rect];
        !            50: 
        !            51:        [self allocateGState];          // For faster lock/unlockFocus
        !            52: 
        !            53:     dir = 1.0;
        !            54:     rad = INITRAD;
        !            55:     [self getSpermCount];
        !            56:     [self getLineWidth];
        !            57:     [self getUseColor];
        !            58:        [inspectorPanel display];
        !            59: 
        !            60:     color = NX_COLORWHITE;
        !            61:        alreadyInitialized = NO;
        !            62:        randCount1 = 100;
        !            63:        randCount2 = 200;
        !            64:        
        !            65:     uPath = newUserPath();
        !            66: 
        !            67:     return self;
        !            68: }
        !            69: 
        !            70: - (void)initializeLine:(int)i
        !            71: {
        !            72:     double angle = RANDFLOAT(10.0) + 5.0;
        !            73:     prevX[i][0] = x[i][0] = (double) (RANDINT((int)NX_WIDTH(&bounds)));
        !            74:     prevX[i][1] = x[i][1] = (double) (RANDINT((int)NX_HEIGHT(&bounds)));
        !            75:     v[i][0] = RANDFLOAT(2.0) - 1.0;
        !            76:     v[i][1] = RANDFLOAT(2.0) - 1.0;    
        !            77:     sine[i] = sin(angle*M_PI/180.0);
        !            78:     cosine[i] = cos(angle*M_PI/180.0);
        !            79:     vel[i] = RANDFLOAT(4.0) + 4.0;
        !            80:     VEC_NORM(v[i]);
        !            81: }
        !            82: 
        !            83: - (void)getFocusFromEvent:(NXEvent *)event
        !            84: {
        !            85:     NXPoint loc = event->location;
        !            86:     [self convertPoint:&loc fromView:nil];
        !            87:     mouse[0] = loc.x;
        !            88:     mouse[1] = loc.y;
        !            89: }
        !            90: 
        !            91: - (BOOL)acceptsFirstMouse
        !            92: {      return YES;
        !            93: }
        !            94: 
        !            95: - mouseDown:(NXEvent *)event
        !            96: {
        !            97:     [self getFocusFromEvent:event];
        !            98:     return self;
        !            99: }
        !           100: 
        !           101: - effectOne
        !           102: {
        !           103:     VECTOR y;
        !           104:     int i;
        !           105: 
        !           106:     dir *= -1.0;
        !           107:     for (i = 0; i < MAXCOUNT; i++) {
        !           108:        VEC_COPY(y, v[i]);
        !           109:        if (dir == -1.0) {
        !           110:            v[i][0] = y[1];
        !           111:            v[i][1] = -y[0];
        !           112:        } else {
        !           113:            v[i][0] = -y[1];
        !           114:            v[i][1] = y[0];
        !           115:        }
        !           116:     }
        !           117:     return self;
        !           118: }
        !           119: 
        !           120: - effectTwo
        !           121: {
        !           122:     int i;
        !           123:     for (i = 0; i < MAXCOUNT; i++) {
        !           124:        v[i][0] = -v[i][0];
        !           125:     }
        !           126:     return self;
        !           127: }
        !           128: 
        !           129: - effectThree
        !           130: {
        !           131:     int i;
        !           132:     for (i = 0; i < MAXCOUNT; i++) {
        !           133:        v[i][1] = -v[i][1];
        !           134:     }
        !           135:     return self;
        !           136: }
        !           137: 
        !           138: - effectFour
        !           139: {
        !           140:     [self effectTwo];
        !           141:     [self effectThree];
        !           142:     return self;
        !           143: }
        !           144: 
        !           145: - effectFive
        !           146: {
        !           147:     [self effectOne];
        !           148:     [self effectFour];
        !           149:     return self;
        !           150: }
        !           151: 
        !           152: - effectSix
        !           153: {
        !           154:     rad = MIN(rad * RADSTEP, MAXRAD);
        !           155:     return self;
        !           156: }
        !           157: 
        !           158: - effectSeven
        !           159: {
        !           160:     rad = MAX(rad / RADSTEP, MINRAD);
        !           161:     return self;
        !           162: }
        !           163: 
        !           164: - doEffectNumber:(int)val
        !           165: {
        !           166:     switch (val) {
        !           167:        case 0: [self effectOne]; break;
        !           168:        case 1: [self effectTwo]; break;
        !           169:        case 2: [self effectThree]; break;
        !           170:        case 3: [self effectFour]; break;
        !           171:        case 4: [self effectFive]; break;
        !           172:        case 5: [self effectSix]; break;
        !           173:        case 6: [self effectSeven]; break;
        !           174:        default: break;
        !           175:     }
        !           176:     return self;
        !           177: }
        !           178: 
        !           179: - oneStep
        !           180: {
        !           181:     int i, cnt;
        !           182:        POINT lLeft, uRight;
        !           183:        NXRect eraseRect;
        !           184: 
        !           185:        uRight[0] = lLeft[0] = x[0][0];
        !           186:        uRight[1] = lLeft[1] = x[0][1];
        !           187: 
        !           188:        for (i = 0; i < count; i++) {
        !           189:            VECTOR w, y;
        !           190:            POINT p;
        !           191:            double r;
        !           192: 
        !           193:                for (cnt = 0; cnt < 2; cnt++) {
        !           194:                    if (prevX[i][cnt] < lLeft[cnt]) lLeft[cnt] = prevX[i][cnt];
        !           195:                    else if (prevX[i][cnt] > uRight[cnt]) uRight[cnt] = prevX[i][cnt];
        !           196:                    if (x[i][cnt] < lLeft[cnt]) lLeft[cnt] = x[i][cnt];
        !           197:                    else if (x[i][cnt] > uRight[cnt]) uRight[cnt] = x[i][cnt];
        !           198:                }
        !           199: 
        !           200:            prevX[i][0] = x[i][0];      /* old location */
        !           201:            prevX[i][1] = x[i][1];
        !           202:     
        !           203:            VEC_SUB(w, x[i], mouse);
        !           204:            VEC_NORM(w);
        !           205:            VEC_COPY(y, w);
        !           206:            w[0] = y[0]*cosine[i] - dir*y[1]*sine[i];
        !           207:            w[1] = y[1]*cosine[i] + dir*y[0]*sine[i];
        !           208:            VEC_ADDS(p, mouse, rad*(160.0 - vel[i]*20.0), w);
        !           209:     
        !           210:            VEC_SUB(w, p, x[i]);
        !           211:            r = VEC_LEN(w);
        !           212:            VEC_DIV(w, r);
        !           213:     
        !           214:            VEC_ADDS(v[i], v[i], 1.0, w);
        !           215:     
        !           216:            VEC_NORM(v[i]);
        !           217:            VEC_MULT(v[i], vel[i]);
        !           218:     
        !           219:            VEC_ADD(x[i], x[i], v[i]);
        !           220: 
        !           221:        }
        !           222: 
        !           223:     NXSetRect (&eraseRect, lLeft[0], lLeft[1], uRight[0]-lLeft[0], uRight[1]-lLeft[1]);
        !           224:     NXInsetRect (&eraseRect, -1.0-lineWidth, -1.0-lineWidth);
        !           225:        PSsetgray(0);
        !           226:        NXRectFill(&eraseRect);
        !           227: 
        !           228:        [self drawPath];
        !           229: 
        !           230:        if (--randCount1 < 0)
        !           231:        {
        !           232:                randCount1 = RANDINT(700);
        !           233:                mouse[0] = randBetween(0,bounds.size.width);
        !           234:                mouse[1] = randBetween(0,bounds.size.height);
        !           235:        }
        !           236:        if (--randCount2 < 0)
        !           237:        {
        !           238:                randCount2 = RANDINT(600);
        !           239:                [self doEffectNumber:(randCount2 % 7)];
        !           240:        }
        !           241:        return self;
        !           242: }
        !           243: 
        !           244: // Modify "orig" by upto plus or minus "by" keeping it in the specified range...
        !           245: 
        !           246: static float randMod(float orig, float by, float min, float max)
        !           247: {
        !           248:     orig = orig + RANDFLOAT(by * 2.0) - by;
        !           249:     return (orig < min) ? min : ((orig > max) ? max : orig);
        !           250: }
        !           251: 
        !           252: - drawPath
        !           253: {
        !           254:     int cnt;
        !           255: 
        !           256:     PSsetlinewidth (lineWidth);
        !           257:     if (useColors) {
        !           258:        color = NXConvertRGBToColor(randMod(NXRedComponent(color), 0.05, 0.0, 1.0),
        !           259:                randMod(NXGreenComponent(color), 0.05, 0.0, 1.0), 
        !           260:                randMod(NXBlueComponent(color), 0.05, 0.0, 1.0));
        !           261:     }
        !           262:        else color = NX_COLORWHITE;
        !           263:        
        !           264:     NXSetColor (color);
        !           265: 
        !           266:     beginUserPath(uPath, NO);
        !           267:     for (cnt = 0; cnt < count; cnt++) {
        !           268:        UPmoveto(uPath, (float)prevX[cnt][0], (float)prevX[cnt][1]);
        !           269:        UPlineto(uPath, (float)x[cnt][0], (float)x[cnt][1]);
        !           270:     }
        !           271:     closePath(uPath);
        !           272:     endUserPath(uPath, dps_ustroke);
        !           273:     sendUserPath(uPath);
        !           274: 
        !           275:     return self;
        !           276: }
        !           277:     
        !           278: - drawSelf:(const NXRect *)rects :(int)rectCount
        !           279: {
        !           280:        if (!rects || !rectCount) return self;
        !           281:        
        !           282:        PSsetgray(NX_BLACK);
        !           283:        NXRectFill(rects);
        !           284:     [self drawPath];
        !           285:        return self;
        !           286: }
        !           287: 
        !           288: - newWindow
        !           289: {
        !           290:     mouse[0] = randBetween(0,bounds.size.width);
        !           291:     mouse[1] = randBetween(0,bounds.size.height);
        !           292: 
        !           293:        return self;
        !           294: }
        !           295: 
        !           296: - free
        !           297: {
        !           298:     freeUserPath(uPath);
        !           299:     return [super free];
        !           300: }
        !           301: 
        !           302: - setNumLines:sender
        !           303: {
        !           304:     int           i;
        !           305:     int    oldCount = count;
        !           306:        char str[100];
        !           307: 
        !           308:     // set the number of lines
        !           309:     count = MIN(MAXCOUNT, MAX([sender intValue], 1));
        !           310: 
        !           311:     // initialize velocities & such
        !           312:     for (i = oldCount; i < count; i++) {
        !           313:                [self initializeLine:i];
        !           314:     }
        !           315: 
        !           316:     [self display];
        !           317: 
        !           318:        sprintf(str,"%d", count);
        !           319:        NXWriteDefault([NXApp appName], "SpermViewCount", str);
        !           320: 
        !           321:     return self;
        !           322: }
        !           323: 
        !           324: - getSpermCount
        !           325: {
        !           326:        const char *ptr;
        !           327:        int val;
        !           328: 
        !           329:        [spermCountSlider setMinValue: 10];
        !           330:        [spermCountSlider setMaxValue: MAXCOUNT];
        !           331:        
        !           332:        ptr = NXGetDefaultValue([NXApp appName], "SpermViewCount");
        !           333:        if (ptr)
        !           334:        {
        !           335:                sscanf(ptr,"%d",&val);
        !           336:                if (val >= 10 && val <= MAXCOUNT) count = val;
        !           337:                else count = MAXCOUNT;
        !           338:        }
        !           339:        else count = MAXCOUNT;
        !           340:        
        !           341:        return self;
        !           342: }
        !           343: 
        !           344: - setUseColor:sender
        !           345: {
        !           346:     useColors = [sender state];
        !           347: 
        !           348:        if (useColors)
        !           349:                NXWriteDefault([NXApp appName], "SpermViewColor", "Yes");
        !           350:        else
        !           351:                NXRemoveDefault([NXApp appName], "SpermViewColor");
        !           352: 
        !           353:     return self;
        !           354: }
        !           355: 
        !           356: - getUseColor
        !           357: {
        !           358:        const char *ptr;
        !           359:        
        !           360:        ptr = NXGetDefaultValue([NXApp appName], "SpermViewColor");
        !           361: 
        !           362:        if (!ptr || !strcmp(ptr,"No")) useColors = NO;
        !           363:        else useColors = YES;
        !           364:        
        !           365:        return self;
        !           366: }
        !           367: 
        !           368: - setLineWidth:sender
        !           369: {
        !           370:        char str[50];
        !           371: 
        !           372:     lineWidth = MAX([sender floatValue], 0.0);
        !           373:        sprintf(str,"%5.1f", lineWidth);
        !           374:        NXWriteDefault([NXApp appName], "SpermViewWidth", str);
        !           375: 
        !           376:     return self;
        !           377: }
        !           378: 
        !           379: - getLineWidth
        !           380: {
        !           381:        const char *ptr;
        !           382:        float val;
        !           383: 
        !           384:        [spermWidthSlider setMinValue: 0];
        !           385:        [spermWidthSlider setMaxValue: 8];
        !           386:        
        !           387:        ptr = NXGetDefaultValue([NXApp appName], "SpermViewWidth");
        !           388:        if (ptr)
        !           389:        {
        !           390:                sscanf(ptr,"%f",&val);
        !           391:                if (val >= 0 && val <= 8) lineWidth = val;
        !           392:                else lineWidth = 0;
        !           393:        }
        !           394:        else lineWidth = 0;
        !           395:        
        !           396:        return self;
        !           397: }
        !           398: 
        !           399: - sizeTo:(NXCoord)width :(NXCoord)height
        !           400: {
        !           401:        [super sizeTo:width :height];
        !           402:        
        !           403:        if (!alreadyInitialized)
        !           404:        {       int i;
        !           405:                mouse[0] = NX_MIDX(&bounds);
        !           406:                mouse[1] = NX_MIDY(&bounds);
        !           407: 
        !           408:                for (i = 0; i < MAXCOUNT; i++) {
        !           409:                        [self initializeLine:i];
        !           410:                }
        !           411:                alreadyInitialized = YES;
        !           412:        }
        !           413: 
        !           414:        [self newWindow];
        !           415:        return self;
        !           416: }
        !           417: 
        !           418: - (const char *)windowTitle
        !           419: {      return "Sperm";
        !           420: }
        !           421: 
        !           422: - (BOOL) useBufferedWindow;
        !           423: {      return YES;
        !           424: }
        !           425: 
        !           426: 
        !           427: - inspector:sender
        !           428: {
        !           429:     char buf[MAXPATHLEN];
        !           430:        
        !           431:     if (!inspectorPanel)
        !           432:        {
        !           433:                [NXBundle getPath:buf forResource:"sperm" ofType:"nib" inDirectory:[sender moduleDirectory:"Sperm"] withVersion:0];
        !           434:                [NXApp loadNibFile:buf owner:self withNames:NO];
        !           435: 
        !           436:                [spermCountSlider setIntValue:count];
        !           437:                [spermWidthSlider setFloatValue:lineWidth];
        !           438:                [colorButton setState: (useColors ? 1:0)];
        !           439:     }
        !           440:     return inspectorPanel;
        !           441: }
        !           442: 
        !           443: @end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.