home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Examples / AppKit / BackspaceViews / WorldSpace / WorldSpaceView.m < prev   
Encoding:
Text File  |  1993-06-18  |  6.4 KB  |  315 lines

  1.  
  2. #import <math.h>
  3. #import <libc.h>
  4. #import <c.h>
  5. #import <defaults/defaults.h>
  6. #import <sys/file.h>
  7. #import <appkit/appkit.h>
  8. #import "WorldSpaceView.h"
  9. #import "SpaceView.h"
  10. #import "Thinker.h"
  11.  
  12. @implementation WorldSpaceView
  13.  
  14. // x & y periods in milliseconds
  15. #define X_PERIOD 20000.0
  16. #define Y_PERIOD 19000.0
  17. #define DEFAULT_FPS 20
  18.  
  19. #define PI 3.1415926535
  20.  
  21. // #define MAX_IMAGE_WIDTH 200
  22. // #define MAX_IMAGE_HEIGHT 150
  23. #define MAX_IMAGE_WIDTH 256
  24. #define MAX_IMAGE_HEIGHT 256
  25.  
  26. #define MAX_X_SPEED (26)
  27. #define MAX_Y_SPEED (26)
  28.  
  29. #define BUFFER_WIDTH (MAX_IMAGE_WIDTH + MAX_X_SPEED + 1)
  30. #define BUFFER_HEIGHT (MAX_IMAGE_HEIGHT + MAX_Y_SPEED + 1)
  31.  
  32.  
  33.  
  34. // move the world to its new position
  35. - oneStep
  36. {
  37.     NXRect black = {0,0,0,0};
  38.     NXRect ballRect;
  39.     BRECT new;
  40.     
  41.     then = now;
  42.     now = currentTimeInMs();
  43.     // now += 30;
  44.  
  45.     // calculate new ball x & y position
  46.     xpos = ((1 + sin(((float)now) / X_PERIOD * 2. * PI))/2.0) 
  47.         * maxCoord.x;
  48.     ypos = ((1 + sin(((float)now) / Y_PERIOD * 2. * PI))/2.0) 
  49.         * maxCoord.y;
  50.     
  51.     
  52.     if (xpos < (old.l - MAX_X_SPEED)) xpos = old.l - MAX_X_SPEED;
  53.     else if (xpos > (old.l + MAX_X_SPEED)) xpos = old.l + MAX_X_SPEED;
  54.  
  55.     if (ypos < (old.b - MAX_Y_SPEED)) ypos = old.b - MAX_Y_SPEED;
  56.     else if (ypos > (old.b + MAX_Y_SPEED)) ypos = old.b + MAX_Y_SPEED;
  57.  
  58.  
  59.     /* animate by selecting a new image to blit */
  60.  
  61.     [self incrementImageNumber];
  62.     
  63.     new.l = floor(xpos);
  64.     new.b = floor(ypos);
  65.     new.r = new.l + imageSize.width;
  66.     new.t = new.b + imageSize.height;
  67.     
  68.     ballRect.origin.x = 0;
  69.     ballRect.origin.y = 0;
  70.     ballRect.size.width = imageSize.width;
  71.     ballRect.size.height = imageSize.height;
  72.     
  73.     redrawTo.x = MIN(new.l, old.l);
  74.     redrawTo.y = MIN(new.b, old.b);
  75.  
  76.     redraw.origin.x = 0;
  77.     redraw.origin.y = 0;
  78.     redraw.size.width = (MAX(new.r, old.r)) - redrawTo.x + 1;
  79.     redraw.size.height = (MAX(new.t, old.t)) - redrawTo.y + 1;
  80.     
  81.     black.size= redraw.size;
  82.  
  83.     [buffer lockFocus];
  84.     PSsetgray(0);
  85.     NXRectFill(&black);
  86.     
  87.     ballTo.x = new.l - redrawTo.x;
  88.     ballTo.y = new.b - redrawTo.y;
  89.  
  90.     [currentImage composite:NX_SOVER fromRect:&ballRect toPoint:&ballTo];
  91.     [buffer unlockFocus];
  92.     
  93.     
  94.     // Now bring it onto the screen
  95.     
  96.     [buffer composite:NX_COPY fromRect:&redraw toPoint:&redrawTo];
  97.  
  98.     old = new;
  99.  
  100.     // now put in the stars...
  101.     
  102.     avoid.origin = redrawTo;
  103.     [mySpaceView setVoidRect:&avoid];
  104.     [mySpaceView oneStep];
  105.  
  106.     return self;
  107. }
  108.  
  109.  
  110.  
  111. static char *basename(char *path, const char *suffix)
  112. {
  113.     char *begin, *end, *name;
  114.     int len;
  115.     
  116.     if (strlen(path) < strlen(suffix)) {
  117.         end = begin = path;
  118.     }
  119.     else {
  120.     begin = rindex(path, '/');
  121.     if (begin) begin++;
  122.         else begin = path;
  123.     
  124.     end = path+strlen(path)-strlen(suffix);
  125.     if (0 != strcmp(end, suffix))
  126.         end = path+strlen(path);
  127.     
  128.     if (end < begin) end = begin;
  129.     }
  130.     len = end-begin;
  131.     name = malloc(len+1);
  132.     strncpy(name, begin, len);
  133.     name[len] = '\0';
  134.     return name;
  135. }
  136.  
  137.  
  138. static BOOL noAnimFile = FALSE;
  139.  
  140. - initFrame:(const NXRect *)frameRect
  141. {
  142.     char moduleDirectory[1024];
  143.     const char *animSpeed, *animFile, *animName;
  144.     char animFrame[1024];
  145.     int i, f;
  146.     id local_image;
  147.  
  148.     NXRect black = {0, 0, BUFFER_WIDTH, BUFFER_HEIGHT };
  149.  
  150.     [super initFrame:frameRect];
  151.     [self allocateGState];        // For faster lock/unlockFocus
  152.     [self setClipping:NO];        // even faster...
  153.  
  154.     //in this case, I only need one buffer for several Views
  155.     if (!(buffer = [NXImage findImageNamed:"worldBuffer"]))
  156.     {
  157.         buffer = [[NXImage alloc] initSize:&black.size];
  158.         [buffer setName:"worldBuffer"];
  159.     }
  160.     
  161.     if ([buffer lockFocus])
  162.     {
  163.         PSsetgray(0);
  164.         NXRectFill(&black);
  165.         [buffer unlockFocus];
  166.     }
  167.  
  168.  
  169.     animSpeed = NXGetDefaultValue([NXApp appName], "animSpeed");
  170.     if (animSpeed == NULL) framesPerSecond = DEFAULT_FPS;
  171.     else framesPerSecond = atoi(animSpeed);
  172.  
  173.     animFile = NXGetDefaultValue([NXApp appName], "animFile");
  174.     if (animFile == NULL)
  175.     {
  176.         sprintf(moduleDirectory,"%s/Globe.anim",
  177.             [(BSThinker()) moduleDirectory:"WorldSpace"]);
  178.         animFile = moduleDirectory;
  179.     }
  180.     animName = basename((char *)animFile, ".anim");
  181.    
  182.     imageList = [[List alloc] init];
  183.  
  184.     /* construct the image list */
  185.     for (i=0; ; i++)
  186.     {
  187.         sprintf(animFrame, "%s/%s.%d.tiff", animFile, animName, i+1);
  188.         if (!(local_image = [NXImage findImageNamed:animFrame]))
  189.         {
  190.             if ((f=open(animFrame, O_RDONLY)) < 0) break;
  191.             close(f);
  192.  
  193.             local_image = [[NXImage alloc] initFromFile:animFrame];
  194.             if (local_image == NULL) break;    // never null, even if no file
  195.             [local_image setName:animFrame];
  196.         }
  197.  
  198.         [imageList addObject:local_image];
  199.         if (i == 0) [local_image getSize: &imageSize];
  200.     }
  201.     numberOfFrames = i;
  202.     currentFrame = 0;
  203.     
  204.     if (numberOfFrames == 0)
  205.     {
  206.         if (!noAnimFile)
  207.         NXRunAlertPanel([NXApp appName], "Could not open %s",
  208.                 NULL, NULL, NULL, animFile);
  209.         noAnimFile = TRUE;
  210.         return nil;
  211.     }
  212.  
  213.     nextRotationTime = 0;
  214.  
  215.     [self newViewSize];
  216.  
  217.     mySpaceView = [[SpaceView alloc] initFrame:frameRect];
  218.     avoid.size = imageSize;
  219.  
  220.     return self;
  221. }
  222.  
  223. - sizeTo:(NXCoord)width :(NXCoord)height
  224. {
  225.     [super sizeTo:width :height];
  226.     [mySpaceView sizeTo:width :height];
  227.     [self newViewSize];
  228.     return self;
  229. }
  230.  
  231. - drawSelf:(const NXRect *)rects :(int)rectCount
  232. {
  233.     // if (!rects || !rectCount) return self;
  234.     
  235.     //PSsetgray(0);
  236.     //NXRectFill(rects);
  237.     
  238.     //NXRectClip(rects);
  239.  
  240.     return self;
  241. }
  242.  
  243. - newViewSize
  244. {
  245.     //this is called every time View size changes
  246.     NXRect black = {0, 0, BUFFER_WIDTH, BUFFER_HEIGHT };
  247.  
  248.     then = now = currentTimeInMs();
  249.  
  250.     if (oldSize.width == bounds.size.width &&
  251.             oldSize.height == bounds.size.height)
  252.         return self;
  253.     else
  254.     {
  255.         oldSize.width = bounds.size.width;
  256.         oldSize.height = bounds.size.height;
  257.     }
  258.     
  259.     maxCoord.x = bounds.size.width - imageSize.width;
  260.     maxCoord.y = bounds.size.height - imageSize.height;
  261.     if (maxCoord.x < 0) maxCoord.x = 0;
  262.     if (maxCoord.y < 0) maxCoord.y = 0;
  263.  
  264.  
  265.     old.l = old.r = maxCoord.x/2;
  266.     old.b = old.t = maxCoord.y/2;
  267.     ballTo.x = ballTo.y = 0;
  268.  
  269.     if ([buffer lockFocus])
  270.     {
  271.         PSsetgray(0);
  272.         NXRectFill(&black);
  273.         [buffer unlockFocus];
  274.     }
  275.  
  276.     return self;
  277. }
  278.  
  279. - incrementImageNumber
  280. {
  281.     if (now > nextRotationTime)
  282.     {
  283.         if (++currentFrame >= numberOfFrames) currentFrame = 0;
  284.         currentImage = [imageList objectAt:currentFrame];
  285.         nextRotationTime = now + 1000/framesPerSecond;
  286.     }
  287.  
  288.     return self;
  289. }
  290.  
  291. - (const char *)windowTitle
  292. {
  293.     return "World in Space";
  294. }
  295.  
  296. - didLockFocus
  297. {
  298.     [mySpaceView didLockFocus];
  299.     return self;
  300. }
  301.  
  302. - inspector:sender
  303. {
  304.     char buf[MAXPATHLEN];
  305.     
  306.     if (!sharedInspectorPanel)
  307.     {
  308.         [NXBundle getPath:buf forResource:"WorldSpace" ofType:"nib" inDirectory:[sender moduleDirectory:"WorldSpace"] withVersion:0];
  309.         [NXApp loadNibFile:buf owner:self withNames:NO];
  310.     }
  311.     return sharedInspectorPanel;
  312. }
  313.  
  314. @end
  315.