Annotation of Examples/AppKit/Backspace/SpaceView.m, revision 1.1

1.1     ! root        1: //  SpaceView.m
        !             2: //
        !             3: //  This class implements the flying starfield screen saver view.
        !             4: //
        !             5: //  You may freely copy, distribute, and reuse the code in this example.
        !             6: //  NeXT disclaims any warranty of any kind, expressed or  implied, as to its
        !             7: //  fitness for any particular use.
        !             8: 
        !             9: 
        !            10: #import "SpaceView.h"
        !            11: #import "Thinker.h"
        !            12: #import "psfuncts.h"
        !            13: 
        !            14: #import <dpsclient/wraps.h>
        !            15: #import <appkit/NXImage.h>
        !            16: #import <objc/zone.h>
        !            17: #import <mach/mach.h>
        !            18: #import <c.h>
        !            19: #import <libc.h>
        !            20: #import <math.h>
        !            21: 
        !            22: #define PI (3.141592653589)
        !            23: 
        !            24: @implementation SpaceView
        !            25: 
        !            26: //takes theta and distance and stuffs it into x &y for *p
        !            27: - convertToXY:(STAR *)p
        !            28: {
        !            29:        p->draw->x = floor(bounds.size.width / 2 + (p->distance * cos(p-> theta)));
        !            30:        p->draw->y = floor(bounds.size.height / 2 + (p->distance * sin(p-> theta)));
        !            31:        return self;
        !            32: }
        !            33: 
        !            34: 
        !            35: - oneStep
        !            36: {
        !            37:        int i, count, starsInArray = 0;
        !            38:        STAR *p;
        !            39:        NXPoint *t;
        !            40:        
        !            41:        if (nstars < NSTARS) [self addStar];
        !            42: 
        !            43:        for (i=0; i<nstars; i++)
        !            44:        {
        !            45:                p = &stars[i];
        !            46:                p->distance += p->delta;
        !            47:                p->delta *= p->ddelta;
        !            48: 
        !            49:                [self convertToXY:p];
        !            50: 
        !            51:                // only draw the star if it moved > 1 pixel
        !            52:                if (p->draw->x != p->erase->x || 
        !            53:                        p->draw->y != p->erase->y)
        !            54:                {
        !            55:                        BOOL mustErase = NO;
        !            56:                        // add star to the erasure array
        !            57:                        b[starsInArray] = *p->erase;
        !            58:                        bc[starsInArray] = p->c;
        !            59: 
        !            60:                        if (p->distance > p->changepoint[p->changemode])
        !            61:                        {
        !            62:                                (p->c)++;       // increment character for next star size
        !            63:                                (p->changemode)++;
        !            64:                        }
        !            65: 
        !            66:                        // clipping is off, so we must not draw outside view.
        !            67:                        // replace stars that go too far...
        !            68:                        if (p->draw->x < 0 ||
        !            69:                                p->draw->y < 0 ||
        !            70:                                p->draw->x + 7 > bounds.size.width ||
        !            71:                                p->draw->y + 7 > bounds.size.height)
        !            72:                        {
        !            73:                                [self replaceStarAt:i];
        !            74:                                mustErase = YES;
        !            75:                        }
        !            76: 
        !            77:                        w[starsInArray] = *p->draw;
        !            78:                        wc[starsInArray] = p->c;
        !            79:                        
        !            80:                        if (mustErase || [self allowStars:p]) starsInArray++;
        !            81:                
        !            82:                        t = p->draw; p->draw = p->erase; p->erase = t;
        !            83:                }
        !            84:        }
        !            85: 
        !            86:        bc[starsInArray] = wc[starsInArray] = 0;        //null terminate string
        !            87:        if (starsInArray)
        !            88:        {
        !            89:                for (i=0; i<(starsInArray-1); i++)
        !            90:                {
        !            91:                        bOffsets[i].x = b[i+1].x - b[i].x;
        !            92:                        bOffsets[i].y = b[i+1].y - b[i].y;
        !            93:                        wOffsets[i].x = w[i+1].x - w[i].x;
        !            94:                        wOffsets[i].y = w[i+1].y - w[i].y;
        !            95:                }
        !            96:                bOffsets[i].x = bOffsets[i].y = wOffsets[i].x = wOffsets[i].y = 0;
        !            97: 
        !            98:                count = 0;
        !            99:                while (count < starsInArray)
        !           100:                {       char tc;
        !           101:                        int j;
        !           102:                        // You get the best performance if you put out all the stars
        !           103:                        // at once.  This causes noticable flicker, so I put out 
        !           104:                        // 100 of the stars per iteration.  This gives reasonable speed
        !           105:                        // and flicker is hardly noticable.  Besides, stars
        !           106:                        // _should_ flicker a little...
        !           107:                
        !           108:                        int t = (starsInArray - count);
        !           109:                        i = (t < STARSPERIT)?t:STARSPERIT;
        !           110:                        j = i + count;
        !           111:                        
        !           112:                        PSsetgray(NX_BLACK);
        !           113:                        tc = bc[j]; bc[j] = 0;
        !           114:                        PSWXYShow(b[count].x, b[count].y, &bc[count], 
        !           115:                                (float *)(&bOffsets[count].x), i*2);
        !           116:                        bc[j] = tc;
        !           117:                        
        !           118:                        PSsetgray(NX_WHITE);
        !           119:                        tc = wc[j]; wc[j] = 0;
        !           120:                        PSWXYShow(w[count].x, w[count].y, &wc[count], 
        !           121:                                (float *)(&wOffsets[count].x), i*2);
        !           122:                        wc[j] = tc;
        !           123:                        
        !           124:                        count += STARSPERIT;
        !           125:                }
        !           126:        }
        !           127: 
        !           128:        return self;
        !           129: }
        !           130: 
        !           131: // returns yes if the star is outside the avoidance rectangle
        !           132: // this is really fast and loose but it works acceptibly well
        !           133: // ps I could just use NXIntersectsRect() but I want to avoid
        !           134: // trap overhead.  Call me paranoid...
        !           135: - (BOOL) allowStars:(const STAR *)p
        !           136: {
        !           137:        // just return if voidRect not set
        !           138:        if ((!voidRect.size.width) ||
        !           139:                p->draw->x < voidRect.origin.x ||
        !           140:                p->draw->y < voidRect.origin.y ||
        !           141:                p->draw->x+7 > voidRect.origin.x+voidRect.size.width ||
        !           142:                p->draw->y+7 > voidRect.origin.y+voidRect.size.height ||
        !           143: 
        !           144:                p->erase->x < voidRect.origin. x ||
        !           145:                p->erase->y < voidRect.origin. y ||
        !           146:                p->erase->x+7 > voidRect.origin.x+voidRect.size.width ||
        !           147:                p->erase->y+7 > voidRect.origin.y+voidRect.size.height) return YES;
        !           148: 
        !           149:        return NO;
        !           150: }
        !           151: 
        !           152: - initFrame:(const NXRect *)frameRect
        !           153: {
        !           154:        [super initFrame:frameRect];
        !           155:        [self allocateGState];          // For faster lock/unlockFocus
        !           156:        [self setClipping:NO];          // even faster...
        !           157:        [self setRadius];
        !           158:        loadPSProcedures();
        !           159:        PSWDefineFont("StarFont");
        !           160: 
        !           161:        return self;
        !           162: }
        !           163: 
        !           164: - drawSelf:(const NXRect *)rects :(int)rectCount
        !           165: {
        !           166:        // this drawself doesn't really draw the view at all.
        !           167:        // in fact it just promotes the window to screen depth...
        !           168: 
        !           169:        NXRect t = {0,0,1,1};
        !           170: 
        !           171:        PSsetrgbcolor(1,0,0);
        !           172:        NXRectFill(&t); //yucky trick for window depth promotion!
        !           173:        PSsetgray(NX_BLACK); NXRectFill(&t);
        !           174: 
        !           175:        PSselectfont("StarFont", 1.0);
        !           176: 
        !           177:        return self;
        !           178: }
        !           179: 
        !           180: - sizeTo:(NXCoord)width :(NXCoord)height
        !           181: {
        !           182:        [super sizeTo:width :height];
        !           183: 
        !           184:        if (oldSize.width != bounds.size.width ||
        !           185:                        oldSize.height != bounds.size.height)
        !           186:        {
        !           187:                oldSize.width = bounds.size.width;
        !           188:                oldSize.height = bounds.size.height;
        !           189:                [self setRadius];
        !           190:                nstars = 0;
        !           191:                [self display];
        !           192:        }
        !           193:        
        !           194:        return self;
        !           195: }
        !           196: 
        !           197: // only call addStar if there is room in the stars array!
        !           198: - addStar
        !           199: {
        !           200:        [self replaceStarAt:nstars++];
        !           201:        return self;
        !           202: }
        !           203: 
        !           204: - replaceStarAt:(int)index
        !           205: {
        !           206:        float dist, t;
        !           207:        int tries = 0;
        !           208:        STAR *p = &stars[index];
        !           209:        BOOL inBounds;
        !           210: 
        !           211:        p->draw = &p->r1;
        !           212:        p->erase = &p->r2;
        !           213: 
        !           214:        
        !           215:        do {
        !           216:                p->theta = randBetween(0,(2*PI));
        !           217: 
        !           218:                if (tries++ < 3) p->distance = randBetween(1, radius);
        !           219:                else p->distance = randBetween(1, p->distance);
        !           220: 
        !           221:                inBounds = YES;
        !           222:                [self convertToXY:p];
        !           223: 
        !           224:                if (p->draw->x < 0 || p->draw->y < 0 ||
        !           225:                        p->draw->x + 7 > bounds.size.width ||
        !           226:                        p->draw->y + 7 > bounds.size.height)
        !           227:                {
        !           228:                        inBounds = NO;
        !           229:                }
        !           230:        } while (!inBounds);
        !           231: 
        !           232:        p->delta = (0.2);
        !           233: 
        !           234:        p->ddelta = randBetween(1.0, 1.1);
        !           235: 
        !           236: 
        !           237: 
        !           238:        t = randBetween(0, (0.42*radius));
        !           239:        dist = MAX(20,t);
        !           240:        p->changepoint[0] = p->distance + 5;                    // to b
        !           241:        p->changepoint[1] = p->changepoint[0] - 5 + dist + dist;        // to c
        !           242: 
        !           243: 
        !           244:        p->changepoint[2] = p->changepoint[1] + dist;   // to d
        !           245:        p->changepoint[3] = p->changepoint[2] + dist;   // to e
        !           246:        p->changepoint[4] = p->changepoint[3] + dist;   // to f
        !           247:        p->changepoint[5] = 100000;                                             // never change to g
        !           248: 
        !           249:        p->changemode = 0;
        !           250:        
        !           251:        if ((++toggle) & 1) p->c = 'a';
        !           252:        else p->c = 'g';
        !           253: 
        !           254:        p->r2 = p->r1;
        !           255: 
        !           256:        return self;
        !           257: }
        !           258: 
        !           259: - setRadius
        !           260: {
        !           261:        float x = bounds.size.width;
        !           262:        float y = bounds.size.height;
        !           263:        radius = (sqrt(x*x + y*y))/2;
        !           264:        return self;
        !           265: }
        !           266: 
        !           267: - (const char *)windowTitle
        !           268: {
        !           269:        return "The Final Frontier";
        !           270: }
        !           271: 
        !           272: - setVoidRect:(const NXRect *)r
        !           273: {
        !           274:        voidRect = *r;
        !           275:        return self;
        !           276: }
        !           277: 
        !           278: - didLockFocus
        !           279: {
        !           280:        PSselectfont("StarFont", 1.0);
        !           281:        return self;
        !           282: }
        !           283: 
        !           284: - (BOOL)useBufferedWindow
        !           285: {      return NO;
        !           286: }
        !           287: 
        !           288: - inspector:sender
        !           289: {
        !           290:     return [sender spaceInspector];
        !           291: }
        !           292: 
        !           293: - (BOOL)ignoreMouseMovement
        !           294: {      return NO;
        !           295: }
        !           296: 
        !           297: - inspectorWillBeRemoved
        !           298: {      return self;    // just a prototype
        !           299: }
        !           300: 
        !           301: - inspectorInstalled
        !           302: {      return self;    // just a prototype
        !           303: }
        !           304: 
        !           305: @end
        !           306: 
        !           307: 
        !           308: 
        !           309: // this class is only used in the inspector, it animates
        !           310: // when it draws itself.
        !           311: 
        !           312: @implementation StaticSpaceView
        !           313: 
        !           314: - drawSelf:(const NXRect *)rects :(int)rectCount
        !           315: {
        !           316:        int i;
        !           317:        
        !           318:        if (!rects || !rectCount) return self;
        !           319:        
        !           320:        PSselectfont("StarFont", 1.0);
        !           321: 
        !           322:        PSsetgray(NX_BLACK);
        !           323:        NXRectFill(rects);
        !           324:        
        !           325:        for (i=0; i<20; i++)
        !           326:        {
        !           327:                [self oneStep];
        !           328:                [[self window] flushWindow];
        !           329:                NXPing();
        !           330:        }
        !           331: 
        !           332:        return self;
        !           333: }
        !           334: 
        !           335: - initFrame:(const NXRect *)frameRect
        !           336: {
        !           337:        [super initFrame:frameRect];
        !           338: 
        !           339:        while (nstars < NSTARS) [self addStar];
        !           340:        return self;
        !           341: }
        !           342: 
        !           343: - sizeTo:(NXCoord)width :(NXCoord)height
        !           344: {
        !           345:        [super sizeTo:width :height];
        !           346: 
        !           347:        nstars = 0;
        !           348:        while (nstars < NSTARS) [self addStar]; 
        !           349:        return self;
        !           350: }
        !           351: 
        !           352: @end
        !           353: 
        !           354: 
        !           355: 
        !           356: 
        !           357: 
        !           358: @implementation View(nonretainedFillMethod)
        !           359: 
        !           360: // I add this method as a category of View to be sure that all
        !           361: // my views implement it.  I really want to use nonretained windows
        !           362: // but they are drawn via drawSelf at all kinds of goofy times.  It
        !           363: // seems like the kit kind of throws up its hands when it doesn't have
        !           364: // a buffer to draw from, so you get a lot more drawSelfs than you need,
        !           365: // and sometimes you don't get them when you really want them.  I know
        !           366: // when I need the background filled in black, so I factor that out of
        !           367: // my drawSelf and then drawself only draws things that are already on
        !           368: // screen so you don't see it happen.  I will only call this method on
        !           369: // a nonretained (and full screen) window.
        !           370: 
        !           371: - fillBoundsWithBlack
        !           372: {
        !           373:        if ([self canDraw])
        !           374:        {
        !           375:                [self lockFocus];
        !           376:                PSsetgray(NX_BLACK);
        !           377:                NXRectFill(&bounds);
        !           378:                [self unlockFocus];
        !           379:        }
        !           380:        return self;
        !           381: }
        !           382: 
        !           383: @end

unix.superglobalmegacorp.com

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