|
|
1.1 root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.