SHOW:
|
|
- or go back to the newest paste.
1 | //cl /EHsc /O2 DuneGroundEdit.cpp gdi32.lib user32.lib opengl32.lib comdlg32.lib | |
2 | #include <windows.h> | |
3 | #include <GL/gl.h> | |
4 | #include <GL/glu.h> | |
5 | #include <stdio.h> | |
6 | #include <time.h> | |
7 | #include "dunes.h" | |
8 | #include "dunestructures.h" | |
9 | #include <vector> | |
10 | ||
11 | #define GET_X_LPARAM(a) ((short)LOWORD(a)) | |
12 | #define GET_Y_LPARAM(a) ((short)HIWORD(a)) | |
13 | ||
14 | unsigned short PlaneB[0x1000/2]; | |
15 | - | bool showgray = false; |
15 | + | |
16 | POINT camera = {0,0}; | |
17 | POINT mouse; | |
18 | double zoom = 1; | |
19 | bool showgrey = false; | |
20 | bool showunits = true; | |
21 | int state = 0; | |
22 | int drawtype = 0; | |
23 | int drawsize = 1; | |
24 | bool drawinverse = false; | |
25 | ||
26 | struct Ground | |
27 | { | |
28 | int width; | |
29 | int height; | |
30 | double *data; | |
31 | Ground(int _width, int _height) | |
32 | { | |
33 | width = _width; | |
34 | height = _height; | |
35 | data = (double *)malloc(width*height*sizeof(double)); | |
36 | for (int x=0; x<width; ++x) | |
37 | for (int y=0; y<height; ++y) | |
38 | (*this)[x][y] = 0; | |
39 | } | |
40 | ||
41 | bool in(int x, int y) | |
42 | { | |
43 | if (x<0 | |
44 | || y<0 | |
45 | || x>=width | |
46 | || y>=height) | |
47 | return false; | |
48 | return true; | |
49 | } | |
50 | ||
51 | double *operator [](int x) | |
52 | { | |
53 | return data+x*height; | |
54 | } | |
55 | ||
56 | ~Ground() | |
57 | { | |
58 | if (data) | |
59 | free(data); | |
60 | } | |
61 | }; | |
62 | ||
63 | struct DuneGround | |
64 | { | |
65 | enum Types {Dust, Ground, SpiceLow, SpiceHigh, Dune}; | |
66 | int width; | |
67 | int height; | |
68 | BYTE *data; | |
69 | BYTE *types; | |
70 | DuneGround(int _width, int _height) | |
71 | { | |
72 | width = _width; | |
73 | height = _height; | |
74 | data = (BYTE *)malloc(width*height*sizeof(BYTE)); | |
75 | types = (BYTE *)malloc(twidth()*theight()*sizeof(BYTE)); | |
76 | Clear(); | |
77 | } | |
78 | ||
79 | ~DuneGround() | |
80 | { | |
81 | if (data) | |
82 | - | free(data); |
82 | + | |
83 | if (types) | |
84 | free(types); | |
85 | } | |
86 | ||
87 | DuneGround(const DuneGround & g) | |
88 | { | |
89 | data = 0; | |
90 | types = 0; | |
91 | - | /*struct Point |
91 | + | width = 0; |
92 | height = 0; | |
93 | - | double x,y; |
93 | + | (*this) = g; |
94 | - | }*/ |
94 | + | |
95 | ||
96 | const DuneGround & operator = (const DuneGround &g) | |
97 | { | |
98 | if (width != g.width | |
99 | || height != g.height) | |
100 | { | |
101 | if (data) | |
102 | free(data); | |
103 | if (types) | |
104 | free(types); | |
105 | data = (BYTE *)malloc(g.width*g.height*sizeof(BYTE)); | |
106 | types = (BYTE *)malloc(g.twidth()*g.theight()*sizeof(BYTE)); | |
107 | } | |
108 | width = g.width; | |
109 | height = g.height; | |
110 | - | void LocalPick(int x, int y, int type); |
110 | + | |
111 | memcpy(types,g.types,twidth()*theight()*sizeof(BYTE)); | |
112 | return (*this); | |
113 | } | |
114 | ||
115 | void Clear() | |
116 | { | |
117 | for (int x=0; x<width; ++x) | |
118 | for (int y=0; y<height; ++y) | |
119 | (*this)[x][y] = 0xB0; | |
120 | for (int x=0; x<twidth(); ++x) | |
121 | for (int y=0; y<theight(); ++y) | |
122 | this->t(x,y) = Dust; | |
123 | } | |
124 | ||
125 | inline int twidth() const | |
126 | { | |
127 | return width*2+1; | |
128 | } | |
129 | ||
130 | - | WNDCLASS wc; |
130 | + | inline int theight() const |
131 | - | HWND hWnd; |
131 | + | |
132 | - | HDC hDC; |
132 | + | return height*2+1; |
133 | - | HGLRC hRC; |
133 | + | |
134 | - | MSG msg; |
134 | + | |
135 | - | BOOL bQuit = FALSE; |
135 | + | inline bool tin(int x, int y) const |
136 | { | |
137 | - | // register window class |
137 | + | return (x>=0 && y>=0 && x<twidth() && y<theight()); |
138 | - | wc.style = CS_OWNDC; |
138 | + | |
139 | - | wc.lpfnWndProc = WndProc; |
139 | + | |
140 | - | wc.cbClsExtra = 0; |
140 | + | inline bool in(int x, int y) const |
141 | - | wc.cbWndExtra = 0; |
141 | + | |
142 | - | wc.hInstance = hInstance; |
142 | + | return (x>=0 && y>=0 && x<width && y<height); |
143 | - | wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); |
143 | + | |
144 | - | wc.hCursor = LoadCursor( NULL, IDC_ARROW ); |
144 | + | |
145 | - | wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); |
145 | + | void Draw(int x, int y, BYTE type) |
146 | - | wc.lpszMenuName = NULL; |
146 | + | |
147 | - | wc.lpszClassName = "GLSample"; |
147 | + | // 0 1 2 |
148 | - | RegisterClass( &wc ); |
148 | + | // 0 1 2 3 4 5 6 |
149 | this->t(x,y) = type; | |
150 | - | // create main window |
150 | + | if (in(x/2, y/2)) |
151 | - | hWnd = CreateWindow( |
151 | + | Correct(x/2, y/2, type); |
152 | - | "GLSample", "OpenGL Texture Sample", |
152 | + | if (in(x/2-1, y/2)) |
153 | - | WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE | WS_MAXIMIZEBOX | WS_THICKFRAME, |
153 | + | Correct(x/2-1,y/2,type); |
154 | - | 0, 0, 800, 600, |
154 | + | if (in(x/2, y/2-1)) |
155 | - | NULL, NULL, hInstance, NULL ); |
155 | + | Correct(x/2,y/2-1,type); |
156 | if (in(x/2-1, y/2-1)) | |
157 | - | // enable OpenGL for the window |
157 | + | Correct(x/2-1-1,y/2-1,type); |
158 | - | EnableOpenGL( hWnd, &hDC, &hRC ); |
158 | + | |
159 | - | UpdateViewport( hWnd); |
159 | + | |
160 | ||
161 | - | // load our texture |
161 | + | void Correct(int x, int y, BYTE type_draw) |
162 | - | GroundTiles = LoadTextureRAW( "tex1.bmp", TRUE ); |
162 | + | |
163 | - | //LoadMap("map_18.bin"); |
163 | + | if (type_draw == Ground) |
164 | { | |
165 | - | srand(time(0)); |
165 | + | |
166 | - | GroundGrey = GenerateGround(); |
166 | + | |
167 | - | //texture = LoadVRAM( "vram.bin", "pal.bin" ); |
167 | + | if (t(i+x*2,j+y*2) != Ground |
168 | && t(i+x*2,j+y*2) != Dust) | |
169 | - | int startTime = GetTickCount(); |
169 | + | Draw(i+x*2,j+y*2,Dust); |
170 | - | int prevTime = startTime; |
170 | + | |
171 | if (type_draw == SpiceLow) | |
172 | - | // program main loop |
172 | + | |
173 | - | while ( !bQuit ) { |
173 | + | |
174 | for (int j=0; j<3; ++j) | |
175 | - | // check for messages |
175 | + | if (t(i+x*2,j+y*2) != SpiceLow |
176 | - | if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { |
176 | + | && t(i+x*2,j+y*2) != SpiceHigh |
177 | && t(i+x*2,j+y*2) != Dust) | |
178 | - | // handle or dispatch messages |
178 | + | Draw(i+x*2,j+y*2,Dust); |
179 | - | if ( msg.message == WM_QUIT ) { |
179 | + | |
180 | - | bQuit = TRUE; |
180 | + | if (type_draw == SpiceHigh) |
181 | - | } else { |
181 | + | |
182 | - | TranslateMessage( &msg ); |
182 | + | |
183 | - | DispatchMessage( &msg ); |
183 | + | |
184 | - | } |
184 | + | if (t(i+x*2,j+y*2) != SpiceHigh |
185 | && t(i+x*2,j+y*2) != SpiceLow) | |
186 | - | } else { |
186 | + | Draw(i+x*2,j+y*2,SpiceLow); |
187 | - | int n = GetTickCount(); |
187 | + | |
188 | - | if (n - prevTime > 1000/40) |
188 | + | if (type_draw == SpiceHigh) |
189 | { | |
190 | - | Render(hWnd, hDC); |
190 | + | |
191 | - | prevTime = n; |
191 | + | |
192 | if (t(i+x*2,j+y*2) != SpiceHigh | |
193 | && t(i+x*2,j+y*2) != SpiceLow) | |
194 | - | Sleep(1); |
194 | + | Draw(i+x*2,j+y*2,SpiceLow); |
195 | - | } |
195 | + | |
196 | if (type_draw == Dune) | |
197 | - | } |
197 | + | |
198 | for (int i=0; i<3; ++i) | |
199 | - | // free the texture |
199 | + | |
200 | - | FreeTexture( GroundTiles ); |
200 | + | if (t(i+x*2,j+y*2) != Dune |
201 | - | FreeTexture( GroundGrey ); |
201 | + | && t(i+x*2,j+y*2) != Dust) |
202 | Draw(i+x*2,j+y*2,Dust); | |
203 | - | // shutdown OpenGL |
203 | + | /*int k = GetK(x,y,Dune); |
204 | - | DisableOpenGL( hWnd, hDC, hRC ); |
204 | + | int mask = dunemask[k]; |
205 | for (int i=0; i<3; ++i) | |
206 | - | // destroy the window explicitly |
206 | + | |
207 | - | DestroyWindow( hWnd ); |
207 | + | |
208 | if ((mask & (1<<(i+j*3))) | |
209 | - | return msg.wParam; |
209 | + | && t(i+x*2,j+y*2) != Dune) |
210 | Draw(i+x*2,j+y*2,Dune); | |
211 | if (!(mask & (1<<(i+j*3))) | |
212 | && t(i+x*2,j+y*2) == Dune) | |
213 | Draw(i+x*2,j+y*2,Dust); | |
214 | }*/ | |
215 | } | |
216 | for (int i=-1; i<2; ++i) | |
217 | for (int j=-1; j<2; ++j) | |
218 | - | double cx = int((camera.x+mouse.x-(rc.right/2))/32.0/zoom); |
218 | + | if (in(x+i,y+j)) |
219 | - | double cy = int((camera.y+mouse.y-(rc.bottom/2))/32.0/zoom); |
219 | + | Update(x+i, y+j); |
220 | - | if (state == 1 |
220 | + | |
221 | - | && (int)(cx*2) <64*2+1 && (int)(cx*2)>=0 |
221 | + | |
222 | - | && (int)(cy*2) <64*2+1 && (int)(cy*2)>=0) |
222 | + | int GetK(int x, int y, BYTE type) |
223 | - | LocalPick(cx*2,cy*2,drawtype);//RangeGround(g[(int)(cx*2)][(int)(cy*2)]);*/ |
223 | + | |
224 | int mask = 0; | |
225 | int k = 0; | |
226 | for (int i=0; i<3; ++i) | |
227 | for (int j=0; j<3; ++j) | |
228 | if (t(i+x*2,j+y*2) == type) | |
229 | mask |= 1<<(i+j*3); | |
230 | //1 2 4 | |
231 | //8 16 32 | |
232 | //64 128 256 | |
233 | if ( type == Dune ) | |
234 | { | |
235 | - | // tiles |
235 | + | k = 0; |
236 | - | /*double tw = 1.0/64; |
236 | + | int min = 10; |
237 | - | for (int i=0; i<32; ++i) |
237 | + | for (int i=0; i<256; ++i) |
238 | if (dunemask[i] != -1) | |
239 | - | for (int j=0; j<64; ++j) |
239 | + | |
240 | int d = DunemaskDist((dunemask[i] & DUNE_MASK), (mask & DUNE_MASK)); | |
241 | - | int id = PlaneB[i*64+j]&0x7FF; |
241 | + | if (((dunemask[i] & DUNE_MASK) & (mask & DUNE_MASK)) == (mask & DUNE_MASK) |
242 | - | int idx = id&63; |
242 | + | && d < min) |
243 | - | int idy = id>>6; |
243 | + | { |
244 | - | glTexCoord2d(tw*(idx+0),tw*(idy+0)); glVertex2d(-1.0+tw*j,+1.0-tw*i); |
244 | + | k = i; |
245 | - | glTexCoord2d(tw*(idx+1),tw*(idy+0)); glVertex2d(-1.0+tw*(j+1),+1.0-tw*i); |
245 | + | min = d; |
246 | - | glTexCoord2d(tw*(idx+1),tw*(idy+1)); glVertex2d(-1.0+tw*(j+1),+1.0-tw*(i+1)); |
246 | + | } |
247 | - | glTexCoord2d(tw*(idx+0),tw*(idy+1)); glVertex2d(-1.0+tw*j,+1.0-tw*(i+1)); |
247 | + | |
248 | for (int i=0; i<256; ++i) | |
249 | if (dunemask[i] != -1) | |
250 | - | glTexCoord2d(0.0,0.0); glVertex2d(-8.0,+8.0); |
250 | + | |
251 | - | glTexCoord2d(1.0,0.0); glVertex2d(+8.0,+8.0); |
251 | + | if (((dunemask[k] & DUNE_MASK)|(mask&16)) == (dunemask[i] & DUNE_MASKMID)) |
252 | - | glTexCoord2d(1.0,1.0); glVertex2d(+8.0,-8.0); |
252 | + | k = i; |
253 | - | glTexCoord2d(0.0,1.0); glVertex2d(-8.0,-8.0);*/ |
253 | + | |
254 | if (k == 0x9C && (mask & 2)) | |
255 | k = 0x60; | |
256 | - | for (int i=0; i<64; ++i) |
256 | + | if (dunemask[k] == 0) |
257 | k = 0; | |
258 | - | for (int j=0; j<64; ++j) |
258 | + | |
259 | else | |
260 | - | int id; |
260 | + | |
261 | - | if (state == 1) |
261 | + | |
262 | - | id = duneGroundNew[j][i]; |
262 | + | |
263 | if ( (mask&(4+32+256)) == (4+32+256)) | |
264 | - | id = duneGround[j][i]; |
264 | + | |
265 | if ( (mask&(64+128+256)) == (64+128+256)) | |
266 | k |= 4; | |
267 | - | glTexCoord2d(tw*(idx+0),1-tw*(idy+0)); glVertex2d(j,-i); |
267 | + | |
268 | - | glTexCoord2d(tw*(idx+1),1-tw*(idy+0)); glVertex2d(j+1,-i); |
268 | + | |
269 | - | glTexCoord2d(tw*(idx+1),1-tw*(idy+1)); glVertex2d(j+1,-(i+1)); |
269 | + | |
270 | - | glTexCoord2d(tw*(idx+0),1-tw*(idy+1)); glVertex2d(j,-(i+1)); |
270 | + | if ( type == Ground && k == 0 && (mask & 16)) // point |
271 | k = 16; | |
272 | if ( k == 3 && !(mask & 16)) | |
273 | k = 17; | |
274 | if ( k == 6 && !(mask & 16)) | |
275 | k = 18; | |
276 | - | if (showgray) |
276 | + | |
277 | k = 20; | |
278 | - | glBindTexture( GL_TEXTURE_2D, GroundGrey ); |
278 | + | |
279 | k = 19; | |
280 | - | glTexCoord2d(0,0); glVertex2d(0,-0); |
280 | + | |
281 | - | glTexCoord2d(1,0); glVertex2d(64,-0); |
281 | + | return k; |
282 | - | glTexCoord2d(1,1); glVertex2d(64,-64); |
282 | + | |
283 | - | glTexCoord2d(0,1); glVertex2d(0,-64); |
283 | + | void Update(int x, int y) |
284 | { | |
285 | int types_mask = 0; | |
286 | for (int type = 0; type < 5; ++type) | |
287 | - | /*glBindTexture( GL_TEXTURE_2D, texture ); |
287 | + | |
288 | bool was = false; | |
289 | for (int i=0; i<3; ++i) | |
290 | - | glTexCoord2d(tw*(3+0),1-tw*(0+0)); glVertex2d(cx,-cy); |
290 | + | |
291 | - | glTexCoord2d(tw*(3+1),1-tw*(0+0)); glVertex2d(cx+1,-cy); |
291 | + | if (t(i+x*2,j+y*2) == type) |
292 | - | glTexCoord2d(tw*(3+1),1-tw*(0+1)); glVertex2d(cx+1,-cy-1); |
292 | + | was = true; |
293 | - | glTexCoord2d(tw*(3+0),1-tw*(0+1)); glVertex2d(cx,-cy-1); |
293 | + | if (was) |
294 | - | glEnd();*/ |
294 | + | types_mask |= 1<<type; |
295 | } | |
296 | ||
297 | int k = 0; | |
298 | int mask = 0; | |
299 | int id = 0xB0; | |
300 | if (types_mask & (1<<Ground)) | |
301 | { | |
302 | k = GetK(x,y,Ground); | |
303 | - | // load a 256x256 RGB .RAW file as a texture |
303 | + | id = 0x80+k; |
304 | if (k == 0) | |
305 | id = 0xB0; | |
306 | - | GLuint texture; |
306 | + | if ( k == 16) // point |
307 | - | int width, height; |
307 | + | |
308 | - | BYTE * data; |
308 | + | if ( k == 17) |
309 | - | FILE * file; |
309 | + | |
310 | - | FILE *f; |
310 | + | if ( k == 18) |
311 | - | BYTE tmp; |
311 | + | |
312 | - | int i; |
312 | + | if ( k == 20) |
313 | id = 0x3F; | |
314 | - | // open texture data |
314 | + | if ( k == 19) |
315 | - | file = fopen( filename, "rb" ); |
315 | + | |
316 | - | if ( file == NULL ) return 0; |
316 | + | |
317 | ||
318 | - | // allocate buffer |
318 | + | if (types_mask & (1<<SpiceLow)) |
319 | - | width = 512; |
319 | + | |
320 | - | height = 512; |
320 | + | k = GetK(x,y,SpiceLow); |
321 | - | data = (BYTE*)malloc( width * height * 3 ); |
321 | + | id = 0xB0+k; |
322 | if ( k == 17) | |
323 | - | // read texture data |
323 | + | id = 0x40; |
324 | if ( k == 18) | |
325 | - | fseek( file, 0x36, SEEK_SET); |
325 | + | id = 0x41; |
326 | - | fread( data, width * height * 3, 1, file ); |
326 | + | if ( k == 20) |
327 | - | fclose( file ); |
327 | + | id = 0x43; |
328 | if ( k == 19) | |
329 | - | for (i=0; i<width*height; ++i) |
329 | + | id = 0x42; |
330 | - | { |
330 | + | |
331 | ||
332 | if (types_mask & (1<<SpiceHigh)) | |
333 | { | |
334 | - | } |
334 | + | k = GetK(x,y,SpiceHigh); |
335 | id = 0xC0+k; | |
336 | - | // allocate a texture name |
336 | + | if ( k == 17 ) |
337 | - | glGenTextures( 1, &texture ); |
337 | + | id = 0x44; |
338 | if ( k == 18 ) | |
339 | - | // select our current texture |
339 | + | id = 0x45; |
340 | - | glBindTexture( GL_TEXTURE_2D, texture ); |
340 | + | if ( k == 20 ) |
341 | id = 0x47; | |
342 | - | // select modulate to mix texture with color for shading |
342 | + | if ( k == 19 ) |
343 | - | glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); |
343 | + | id = 0x46; |
344 | } | |
345 | - | // when texture area is small, bilinear filter the closest MIP map |
345 | + | if (types_mask & (1<<Dune)) |
346 | - | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); |
346 | + | |
347 | - | |
347 | + | k = GetK(x,y,Dune); |
348 | - | // when texture area is large, bilinear filter the first MIP map |
348 | + | if (k) |
349 | - | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); |
349 | + | id = k; |
350 | //id = 0x9F; | |
351 | - | // if wrap is true, the texture wraps over at the edges (repeat) |
351 | + | |
352 | - | // ... false, the texture ends at the edges (clamp) |
352 | + | (*this)[x][y] = id; |
353 | - | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, |
353 | + | |
354 | - | wrap ? GL_REPEAT : GL_CLAMP ); |
354 | + | |
355 | - | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, |
355 | + | void SetTileMask(int x, int y) |
356 | - | wrap ? GL_REPEAT : GL_CLAMP ); |
356 | + | |
357 | int id = (*this)[x][y]; | |
358 | - | // build our texture MIP maps |
358 | + | int type = Dust; |
359 | - | //gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, |
359 | + | int mask = 0; |
360 | - | // height, GL_RGB, GL_UNSIGNED_BYTE, data ); |
360 | + | int k = 0; |
361 | - | glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, |
361 | + | if (id > 0x80 && id <= 0x8F) |
362 | - | height, 0, GL_RGB, GL_UNSIGNED_BYTE, data ); |
362 | + | |
363 | type = Ground; k = id-0x80; | |
364 | - | // free buffer |
364 | + | |
365 | - | free( data ); |
365 | + | if (id == 0x80) |
366 | { | |
367 | - | return texture; |
367 | + | type = Ground; k = 16; |
368 | } | |
369 | if (id == 0x3C) | |
370 | { | |
371 | type = Ground; k = 17; | |
372 | } | |
373 | if (id == 0x3D) | |
374 | { | |
375 | type = Ground; k = 18; | |
376 | } | |
377 | if (id == 0x3F) | |
378 | { | |
379 | type = Ground; k = 20; | |
380 | } | |
381 | if (id == 0x3E) | |
382 | { | |
383 | type = Ground; k = 19; | |
384 | } | |
385 | ||
386 | if (id == 0x80) | |
387 | { | |
388 | type = Ground; k = 16; | |
389 | } | |
390 | ||
391 | if (id > 0xB0 && id <= 0xBF) | |
392 | { | |
393 | type = SpiceLow; k = id-0xB0; | |
394 | } | |
395 | ||
396 | if (id == 0x40) | |
397 | { | |
398 | type = SpiceLow; k = 17; | |
399 | } | |
400 | if (id == 0x41) | |
401 | { | |
402 | type = SpiceLow; k = 18; | |
403 | } | |
404 | - | void LocalPick(int x, int y, int type) |
404 | + | if (id == 0x43) |
405 | { | |
406 | - | static bool was[2*64+1][2*64+1]; |
406 | + | type = SpiceLow; k = 20; |
407 | } | |
408 | - | for (int i=0; i<2*64+1; ++i) |
408 | + | if (id == 0x42) |
409 | - | for (int j=0; j<2*64+1; ++j) |
409 | + | |
410 | - | was[i][j] = false; |
410 | + | type = SpiceLow; k = 19; |
411 | } | |
412 | ||
413 | if (id > 0xC0 && id <= 0xCF) | |
414 | - | double z = g[x][y]; |
414 | + | |
415 | type = SpiceHigh; k = id-0xC0; | |
416 | } | |
417 | ||
418 | if (id == 0x44) | |
419 | { | |
420 | type = SpiceHigh; k = 17; | |
421 | } | |
422 | if (id == 0x45) | |
423 | { | |
424 | - | if (X[s]+i>=0 && X[s]+i<2*64+1 |
424 | + | type = SpiceHigh; k = 18; |
425 | - | && Y[s]+j>=0 && Y[s]+j<2*64+1 |
425 | + | |
426 | if (id == 0x47) | |
427 | - | && g[X[s]+i][Y[s]+j]>=z) |
427 | + | |
428 | type = SpiceHigh; k = 20; | |
429 | } | |
430 | if (id == 0x46) | |
431 | { | |
432 | type = SpiceHigh; k = 19; | |
433 | } | |
434 | ||
435 | if (type != Dust) | |
436 | { | |
437 | if (k<16) | |
438 | { | |
439 | mask = 0; | |
440 | if (k & 1) | |
441 | mask |= (1+2+4); | |
442 | if (k & 2) | |
443 | mask |= (4+32+256); | |
444 | - | if (was[i+x*2][j+y*2]) |
444 | + | if (k & 4) |
445 | mask |= (64+128+256); | |
446 | if (k & 8) | |
447 | mask |= (1+8+64); | |
448 | if (k != 1 | |
449 | && k != 2 | |
450 | && k != 4 | |
451 | && k != 8) | |
452 | mask |= 16; | |
453 | } | |
454 | else | |
455 | { | |
456 | if (k == 16) | |
457 | mask = 16; | |
458 | if (k == 17) | |
459 | - | int id = duneGround[x][y]; |
459 | + | mask = make_dunemask(1,1,1,0,0,1,0,0,1); |
460 | - | if ( type == 0 ) |
460 | + | if (k == 18) |
461 | mask = make_dunemask(0,0,1,0,0,1,1,1,1); | |
462 | - | id = 0x80+k; |
462 | + | if (k == 20) |
463 | - | if ( k == 0) |
463 | + | mask = make_dunemask(1,0,0,1,0,0,1,1,1); |
464 | - | id = duneGround[x][y]; |
464 | + | if (k == 19) |
465 | - | if ( k == 0 && (mask & 16)) // point |
465 | + | mask = make_dunemask(1,1,1,1,0,0,1,0,0); |
466 | - | id = 0x80; |
466 | + | |
467 | - | if ( k == 3 && !(mask & 16)) |
467 | + | |
468 | - | id = 0x3C; |
468 | + | |
469 | - | if ( k == 6 && !(mask & 16)) |
469 | + | for (int i=0; i<256; ++i) |
470 | - | id = 0x3D; |
470 | + | if (dunemask[i] != -1 && i == id) |
471 | - | if ( k == 12 && !(mask & 16)) |
471 | + | |
472 | - | id = 0x3F; |
472 | + | mask = dunemask[i]; |
473 | - | if ( k == 9 && !(mask & 16)) |
473 | + | type = Dune; |
474 | - | id = 0x3E; |
474 | + | |
475 | int a = type; | |
476 | - | if ( type == 1 ) |
476 | + | int b = Dust; |
477 | if (type == SpiceHigh) | |
478 | - | id = 0xB0+k; |
478 | + | b = SpiceLow; |
479 | - | if ( k == 0) |
479 | + | for (int i=0; i<3; ++i) |
480 | - | id = duneGround[x][y]; |
480 | + | for (int j=0; j<3; ++j) |
481 | - | if ( k == 3 && !(mask & 16)) |
481 | + | if (mask & (1<<(i+j*3))) |
482 | - | id = 0x40; |
482 | + | t(i+x*2,j+y*2) = a; |
483 | - | if ( k == 6 && !(mask & 16)) |
483 | + | else |
484 | - | id = 0x41; |
484 | + | |
485 | - | if ( k == 12 && !(mask & 16)) |
485 | + | if (b == SpiceLow && t(i+x*2,j+y*2) != SpiceLow) |
486 | - | id = 0x43; |
486 | + | t(i+x*2,j+y*2) = b; |
487 | - | if ( k == 9 && !(mask & 16)) |
487 | + | |
488 | - | id = 0x42; |
488 | + | |
489 | ||
490 | - | if ( type == 2 ) |
490 | + | |
491 | { | |
492 | - | id = 0xC0+k; |
492 | + | |
493 | - | if ( k == 0) |
493 | + | |
494 | - | id = duneGround[x][y]; |
494 | + | |
495 | - | if ( k == 3 && !(mask & 16)) |
495 | + | BYTE & t(int x,int y) |
496 | - | id = 0x44; |
496 | + | |
497 | - | if ( k == 6 && !(mask & 16)) |
497 | + | return types[y*twidth()+x]; |
498 | - | id = 0x45; |
498 | + | |
499 | - | if ( k == 12 && !(mask & 16)) |
499 | + | |
500 | - | id = 0x47; |
500 | + | |
501 | - | if ( k == 9 && !(mask & 16)) |
501 | + | struct DuneUnit |
502 | - | id = 0x46; |
502 | + | |
503 | short house; | |
504 | - | duneGroundNew[x][y] = id; |
504 | + | short id; |
505 | short life; | |
506 | short pos; | |
507 | short angle; | |
508 | short ai; | |
509 | }; | |
510 | ||
511 | struct DuneStructure | |
512 | { | |
513 | short flag; | |
514 | short house; | |
515 | short id; | |
516 | short life; | |
517 | short pos; | |
518 | }; | |
519 | ||
520 | DuneGround duneGround(64,64); | |
521 | DuneGround duneGroundNew(64,64); | |
522 | std::vector<DuneUnit> Units; | |
523 | std::vector<DuneStructure> Structures; | |
524 | ||
525 | Ground g(2*64+1,2*64+1); | |
526 | GLuint GroundTiles; | |
527 | GLuint GroundGrey; | |
528 | GLuint StructuresTexture; | |
529 | ||
530 | // Declarations ////////////////////////////////////////////////////// | |
531 | ||
532 | LPCSTR OpenFile(HWND hWnd, LPCSTR title); | |
533 | LPCSTR SaveFile(HWND hWnd, LPCSTR title); | |
534 | GLuint LoadTextureRAW( const char * filename, int wrap ); | |
535 | GLuint LoadGreyTexture( const char * filename); | |
536 | GLuint LoadVRAM( const char * vram, const char * pal); | |
537 | GLuint GenerateGround(); | |
538 | GLuint MakeGreyTexture(); | |
539 | void ChangeState(int _state); | |
540 | void RangeGround(double z); | |
541 | void LocalPick(int x, int y, int type, double z, bool inverse); | |
542 | void LoadMap( const char * filename ); | |
543 | void LoadMission( const char * filename ); | |
544 | void SaveMap( const char * filename ); | |
545 | void FreeTexture( GLuint texture ); | |
546 | ||
547 | LRESULT CALLBACK WndProc( HWND hWnd, UINT message, | |
548 | WPARAM wParam, LPARAM lParam ); | |
549 | ||
550 | VOID EnableOpenGL( HWND hWnd, HDC * hDC, HGLRC * hRC ); | |
551 | VOID DisableOpenGL( HWND hWnd, HDC hDC, HGLRC hRC ); | |
552 | void UpdateViewport(HWND hWnd); | |
553 | void Render(HWND hWnd, HDC hDC); | |
554 | ||
555 | // WinMain /////////////////////////////////////////////////////////// | |
556 | ||
557 | int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, | |
558 | - | GenerateGroundRecursive(g, 0, 0, g.width-1, g.height-1); |
558 | + | |
559 | { | |
560 | WNDCLASS wc; | |
561 | HWND hWnd; | |
562 | HDC hDC; | |
563 | HGLRC hRC; | |
564 | MSG msg; | |
565 | BOOL bQuit = FALSE; | |
566 | ||
567 | // register window class | |
568 | wc.style = CS_OWNDC; | |
569 | wc.lpfnWndProc = WndProc; | |
570 | wc.cbClsExtra = 0; | |
571 | wc.cbWndExtra = 0; | |
572 | wc.hInstance = hInstance; | |
573 | wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); | |
574 | wc.hCursor = LoadCursor( NULL, IDC_ARROW ); | |
575 | wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); | |
576 | wc.lpszMenuName = NULL; | |
577 | wc.lpszClassName = "DuneGroundEditor"; | |
578 | RegisterClass( &wc ); | |
579 | ||
580 | DunemaskInit(); | |
581 | ||
582 | // create main window | |
583 | hWnd = CreateWindow( | |
584 | "DuneGroundEditor", "DuneGroundEditor", | |
585 | WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME, | |
586 | 0, 0, 800, 600, | |
587 | NULL, NULL, hInstance, NULL ); | |
588 | ||
589 | // enable OpenGL for the window | |
590 | EnableOpenGL( hWnd, &hDC, &hRC ); | |
591 | UpdateViewport( hWnd); | |
592 | ||
593 | // load our texture | |
594 | GroundTiles = LoadTextureRAW( "tex1.bmp", TRUE ); | |
595 | StructuresTexture = LoadTextureRAW( "structures.bmp", TRUE); | |
596 | srand(time(0)); | |
597 | GroundGrey = GenerateGround(); | |
598 | ||
599 | int startTime = GetTickCount(); | |
600 | int prevTime = startTime; | |
601 | ||
602 | - | for (int y=0; y<64; ++y) |
602 | + | // program main loop |
603 | - | for (int x=0; x<64; ++x) |
603 | + | while ( !bQuit ) |
604 | { | |
605 | // check for messages | |
606 | if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) | |
607 | { | |
608 | // handle or dispatch messages | |
609 | if ( msg.message == WM_QUIT ) | |
610 | { | |
611 | bQuit = TRUE; | |
612 | } | |
613 | else | |
614 | { | |
615 | TranslateMessage( &msg ); | |
616 | - | for (int y=0; y<64; ++y) |
616 | + | DispatchMessage( &msg ); |
617 | - | for (int x=0; x<64; ++x) |
617 | + | |
618 | } | |
619 | else | |
620 | { | |
621 | int n = GetTickCount(); | |
622 | if (n - prevTime > 1000/40) | |
623 | { | |
624 | Render(hWnd, hDC); | |
625 | prevTime = n; | |
626 | } | |
627 | else | |
628 | Sleep(1); | |
629 | } | |
630 | } | |
631 | ||
632 | // free the texture | |
633 | FreeTexture( GroundTiles ); | |
634 | FreeTexture( GroundGrey ); | |
635 | ||
636 | // shutdown OpenGL | |
637 | DisableOpenGL( hWnd, hDC, hRC ); | |
638 | ||
639 | // destroy the window explicitly | |
640 | DestroyWindow( hWnd ); | |
641 | ||
642 | return msg.wParam; | |
643 | ||
644 | } | |
645 | ||
646 | void Render(HWND hWnd, HDC hDC) | |
647 | - | duneGroundNew = duneGround; |
647 | + | |
648 | // OpenGL animation code goes here | |
649 | RECT rc; | |
650 | GetClientRect(hWnd,&rc); | |
651 | double cx = (camera.x+mouse.x-(rc.right/2))/32.0/zoom*2+0.5; | |
652 | double cy = (camera.y+mouse.y-(rc.bottom/2))/32.0/zoom*2+0.5; | |
653 | if (state == 2 && duneGround.tin(cx,cy)) | |
654 | { | |
655 | int x = cx; | |
656 | int y = cy; | |
657 | double n = 0; | |
658 | double z = 0; | |
659 | for (int i=0; i<2; ++i) | |
660 | for (int j=0; j<2; ++j) | |
661 | if ( duneGround.tin(x+i,y+j) ) | |
662 | { | |
663 | double w = (1-(cx-x-i))*(1-(cy-y-j)); | |
664 | n += w; | |
665 | z += w*g[x+i][y+j]; | |
666 | } | |
667 | z /= n; | |
668 | LocalPick(cx,cy,drawtype,z,drawinverse);//RangeGround(g[(int)(cx*2)][(int)(cy*2)]);*/ | |
669 | } | |
670 | ||
671 | glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); | |
672 | glClear( GL_COLOR_BUFFER_BIT ); | |
673 | ||
674 | // setup texture mapping | |
675 | glEnable( GL_TEXTURE_2D ); | |
676 | glBindTexture( GL_TEXTURE_2D, GroundTiles ); | |
677 | ||
678 | glPushMatrix(); | |
679 | - | SaveMap("map.bin"); |
679 | + | |
680 | ||
681 | GetClientRect(hWnd, &rc); | |
682 | double tw = 1.0/16; | |
683 | //else | |
684 | { | |
685 | for (int i=0; i<duneGround.width; ++i) | |
686 | { | |
687 | - | ChangeState(state^1); |
687 | + | for (int j=0; j<duneGround.height; ++j) |
688 | { | |
689 | int id; | |
690 | if (state == 2) | |
691 | id = duneGroundNew[j][i]; | |
692 | else | |
693 | id = duneGround[j][i]; | |
694 | int idx = id&15; | |
695 | int idy = (id>>4); | |
696 | glTexCoord2d(tw*(idx+0),1-tw*(idy+0)); glVertex2d(j,-i); | |
697 | glTexCoord2d(tw*(idx+1),1-tw*(idy+0)); glVertex2d(j+1,-i); | |
698 | glTexCoord2d(tw*(idx+1),1-tw*(idy+1)); glVertex2d(j+1,-(i+1)); | |
699 | glTexCoord2d(tw*(idx+0),1-tw*(idy+1)); glVertex2d(j,-(i+1)); | |
700 | } | |
701 | } | |
702 | - | for (int x=0; x<duneGround.width; ++x) |
702 | + | |
703 | - | for (int y=0; y<duneGround.height; ++y) |
703 | + | |
704 | - | duneGround[x][y] = 0xB0; |
704 | + | |
705 | if (state == 1) | |
706 | { | |
707 | glEnable( GL_BLEND ); | |
708 | - | showgray = !showgray; |
708 | + | glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); |
709 | glColor4f(1.f,1.f,1.f,0.5f); | |
710 | glBegin( GL_QUADS ); | |
711 | for (int y=0; y<duneGround.theight(); ++y) | |
712 | { | |
713 | for (int x=0; x<duneGround.twidth(); ++x) | |
714 | { | |
715 | static int tid[]={0xB0,0x8F,0xC0,0xCF,0x9F}; | |
716 | int id = duneGround.t(x,y); | |
717 | id = tid[id]; | |
718 | int idx = id&15; | |
719 | int idy = (id>>4); | |
720 | glTexCoord2d(tw*(idx+0),1-tw*(idy+0)); glVertex2d(x*0.5-0.25,-(y*0.5-0.25)); | |
721 | glTexCoord2d(tw*(idx+1),1-tw*(idy+0)); glVertex2d(x*0.5+0.5-0.25,-(y*0.5-0.25)); | |
722 | glTexCoord2d(tw*(idx+1),1-tw*(idy+1)); glVertex2d(x*0.5+0.5-0.25,-(y*0.5+0.5-0.25)); | |
723 | glTexCoord2d(tw*(idx+0),1-tw*(idy+1)); glVertex2d(x*0.5-0.25,-(y*0.5+0.5-0.25)); | |
724 | } | |
725 | } | |
726 | glEnd(); | |
727 | glDisable( GL_BLEND ); | |
728 | } | |
729 | ||
730 | if (showunits) | |
731 | { | |
732 | glBindTexture( GL_TEXTURE_2D, StructuresTexture ); | |
733 | glBegin( GL_QUADS ); | |
734 | for (int i = 0; i < Structures.size(); ++i) | |
735 | { | |
736 | int x = (Structures[i].pos&0x3F); | |
737 | int y = (Structures[i].pos/0x40); | |
738 | int id = Structures[i].id; | |
739 | auto si = StructureDrawInfos[id]; | |
740 | glTexCoord2d((si.x+ 0)/512.0,1-(si.y+ 0)/512.0); glVertex2d(x, -y); | |
741 | glTexCoord2d((si.x+si.width)/512.0,1-(si.y+ 0)/512.0); glVertex2d(x+si.width/32,-y); | |
742 | glTexCoord2d((si.x+si.width)/512.0,1-(si.y+si.height)/512.0); glVertex2d(x+si.width/32,-(y+si.height/32)); | |
743 | - | int cx = int((camera.x+mouse.x-(rc.right/2))/32.0/zoom); |
743 | + | glTexCoord2d((si.x+ 0)/512.0,1-(si.y+si.height)/512.0); glVertex2d(x, -(y+si.height/32)); |
744 | - | int cy = int((camera.y+mouse.y-(rc.bottom/2))/32.0/zoom); |
744 | + | |
745 | - | if (state == 1) |
745 | + | glEnd(); |
746 | ||
747 | ||
748 | glBindTexture( GL_TEXTURE_2D, GroundGrey ); | |
749 | glBegin( GL_QUADS ); | |
750 | for (int i = 0; i < Units.size(); ++i) | |
751 | { | |
752 | int x = (Units[i].pos&0x3F); | |
753 | - | int xPos = mouse.x; mouse.x = GET_X_LPARAM(lParam); |
753 | + | int y = (Units[i].pos/0x40); |
754 | - | int yPos = mouse.y; mouse.y = GET_Y_LPARAM(lParam); |
754 | + | int id = Units[i].id; |
755 | - | camera.x -= mouse.x-xPos; |
755 | + | |
756 | - | camera.y -= mouse.y-yPos; |
756 | + | |
757 | glTexCoord2d(tw*(idx+0),1-tw*(idy+0)); glVertex2d(x,-y); | |
758 | glTexCoord2d(tw*(idx+1),1-tw*(idy+0)); glVertex2d(x+1,-y); | |
759 | glTexCoord2d(tw*(idx+1),1-tw*(idy+1)); glVertex2d(x+1,-(y+1)); | |
760 | glTexCoord2d(tw*(idx+0),1-tw*(idy+1)); glVertex2d(x,-(y+1)); | |
761 | } | |
762 | glEnd(); | |
763 | } | |
764 | ||
765 | if (showgrey) | |
766 | { | |
767 | glBindTexture( GL_TEXTURE_2D, GroundGrey ); | |
768 | glBegin( GL_QUADS ); | |
769 | glTexCoord2d(0,0); glVertex2d(0,-0); | |
770 | glTexCoord2d(1,0); glVertex2d(64,-0); | |
771 | - | // OpenGL //////////////////////////////////////////////////////////// |
771 | + | glTexCoord2d(1,1); glVertex2d(64,-64); |
772 | glTexCoord2d(0,1); glVertex2d(0,-64); | |
773 | glEnd(); | |
774 | } | |
775 | ||
776 | glPopMatrix(); | |
777 | ||
778 | SwapBuffers( hDC ); | |
779 | } | |
780 | ||
781 | ||
782 | // Texture /////////////////////////////////////////////////////////// | |
783 | ||
784 | // load a 512x512 24 bit RGB .BMP file as a texture | |
785 | GLuint LoadTextureRAW( const char * filename, int wrap ) | |
786 | { | |
787 | GLuint texture; | |
788 | int width, height; | |
789 | BYTE * data; | |
790 | FILE * file; | |
791 | FILE *f; | |
792 | BYTE tmp; | |
793 | int i; | |
794 | ||
795 | // open texture data | |
796 | file = fopen( filename, "rb" ); | |
797 | if ( file == NULL ) return 0; | |
798 | ||
799 | // allocate buffer | |
800 | width = 512; | |
801 | height = 512; | |
802 | data = (BYTE*)malloc( width * height * 3 ); | |
803 | ||
804 | // read texture data | |
805 | ||
806 | fseek( file, 0x36, SEEK_SET); | |
807 | fread( data, width * height * 3, 1, file ); | |
808 | fclose( file ); | |
809 | ||
810 | for (i=0; i<width*height; ++i) | |
811 | { | |
812 | tmp = data[i*3]; | |
813 | data[i*3] = data[i*3+2]; | |
814 | data[i*3+2] = tmp; | |
815 | } | |
816 | ||
817 | // allocate a texture name | |
818 | glGenTextures( 1, &texture ); | |
819 | ||
820 | // select our current texture | |
821 | glBindTexture( GL_TEXTURE_2D, texture ); | |
822 | ||
823 | // select modulate to mix texture with color for shading | |
824 | glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); | |
825 | ||
826 | // when texture area is small, bilinear filter the closest MIP map | |
827 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); | |
828 | ||
829 | // when texture area is large, bilinear filter the first MIP map | |
830 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); | |
831 | ||
832 | // if wrap is true, the texture wraps over at the edges (repeat) | |
833 | // ... false, the texture ends at the edges (clamp) | |
834 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, | |
835 | wrap ? GL_REPEAT : GL_CLAMP ); | |
836 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, | |
837 | wrap ? GL_REPEAT : GL_CLAMP ); | |
838 | ||
839 | glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, | |
840 | height, 0, GL_RGB, GL_UNSIGNED_BYTE, data ); | |
841 | ||
842 | // free buffer | |
843 | free( data ); | |
844 | ||
845 | return texture; | |
846 | ||
847 | } | |
848 | ||
849 | GLuint LoadGreyTexture( const char * filename ) | |
850 | { | |
851 | GLuint texture; | |
852 | int width, height; | |
853 | BYTE * data; | |
854 | FILE * file; | |
855 | FILE *f; | |
856 | BYTE tmp; | |
857 | int i; | |
858 | ||
859 | // open texture data | |
860 | file = fopen( filename, "rb" ); | |
861 | if ( file == NULL ) return 0; | |
862 | ||
863 | // allocate buffer | |
864 | width = 128; | |
865 | height = 128; | |
866 | data = (BYTE*)malloc( width * height * 4 ); | |
867 | ||
868 | // read texture data | |
869 | ||
870 | fseek( file, 0x36, SEEK_SET); | |
871 | fread( data, width * height * 3, 1, file ); | |
872 | fclose( file ); | |
873 | ||
874 | for (i=0; i<width*height; ++i) | |
875 | { | |
876 | int all = 0; | |
877 | for (int j=0; j<3; ++j) | |
878 | all += data[i*3+j]; | |
879 | all /= 3; | |
880 | g[i%width][width - 1 - i/width] = all/255.0; | |
881 | } | |
882 | ||
883 | free(data); | |
884 | ||
885 | return MakeGreyTexture(); | |
886 | } | |
887 | ||
888 | double randf() | |
889 | { | |
890 | return rand()/double(RAND_MAX); | |
891 | } | |
892 | ||
893 | // Midpoint displacement | |
894 | void GenerateGroundRecursive(Ground &g, int x, int y, int width, int height) | |
895 | { | |
896 | if (width <= 1 || height <= 1) | |
897 | return; | |
898 | double a,b,c,d; | |
899 | a = g[x ][y ]; | |
900 | b = g[x+width][y ]; | |
901 | c = g[x ][y+height]; | |
902 | d = g[x+width][y+height]; | |
903 | ||
904 | g[(x + (x + width))/2][ y ] = (a + b)/2; | |
905 | g[ x ][(y + (y + height))/2] = (a + c)/2; | |
906 | g[(x + (x + width))/2][ y + height ] = (c + d)/2; | |
907 | g[ x + width ][(y + (y + height))/2] = (b + d)/2; | |
908 | ||
909 | double z = (a+b+c+d)/4+((-1+randf()*2)*width/64/2); | |
910 | if (z > 1) | |
911 | z = 1; | |
912 | if (z < 0) | |
913 | z = 0; | |
914 | g[(x + (x + width))/2][(y + (y + height))/2] = z; | |
915 | ||
916 | GenerateGroundRecursive(g, x , y , width/2, height/2); | |
917 | GenerateGroundRecursive(g, x + width/2, y , width/2, height/2); | |
918 | GenerateGroundRecursive(g, x , y + height/2, width/2, height/2); | |
919 | GenerateGroundRecursive(g, x + width/2, y + height/2, width/2, height/2); | |
920 | } | |
921 | ||
922 | void LocalPick(int x, int y, int type, double z, bool inverse) | |
923 | { | |
924 | /*static std::vector<bool> was(129*129); | |
925 | if (was.size() != duneGround.width * duneGround.height) | |
926 | was.resize(duneGround.width * duneGround.height); | |
927 | ||
928 | was.assign(was.size(), false);*/ | |
929 | static bool was[129][129]; | |
930 | memset(was,0,sizeof(was)); | |
931 | ||
932 | duneGroundNew = duneGround; | |
933 | ||
934 | static int X[(2*64+1)*(2*64+1)]; | |
935 | static int Y[(2*64+1)*(2*64+1)]; | |
936 | int s = 0,e = 0; | |
937 | X[e] = x; | |
938 | Y[e] = y; | |
939 | was[x][y] = true; | |
940 | ++e; | |
941 | while (s < e) | |
942 | { | |
943 | for (int i=-1; i<2; ++i) | |
944 | for (int j=-1; j<2; ++j) | |
945 | if (duneGround.tin(X[s]+i, Y[s]+j) | |
946 | && !was[X[s]+i][Y[s]+j] | |
947 | && ((!inverse && g[X[s]+i][Y[s]+j]>=z) || (inverse && g[X[s]+i][Y[s]+j]<=z) )) | |
948 | { | |
949 | X[e] = X[s]+i; | |
950 | Y[e] = Y[s]+j; | |
951 | was[X[e]][Y[e]] = true; | |
952 | duneGroundNew.Draw(X[e],Y[e],type); | |
953 | ++e; | |
954 | } | |
955 | ++s; | |
956 | } | |
957 | //char str[50]; | |
958 | //sprintf(str,"%d %d < %d", s, e, (2*64+1)*(2*64+1)); | |
959 | //MessageBox(NULL,"Oo",str,MB_OK); | |
960 | } | |
961 | ||
962 | void RangeGround(double z) | |
963 | { | |
964 | for (int x=0; x<64; ++x) | |
965 | { | |
966 | for (int y=0; y<64; ++y) | |
967 | { | |
968 | int mask = 0; | |
969 | for (int i=0; i<3; ++i) | |
970 | for (int j=0; j<3; ++j) | |
971 | if (g[i+x*2][j+y*2]>z) | |
972 | mask |= 1<<(i+j*3); | |
973 | int k = 0; | |
974 | //1 2 4 | |
975 | //8 16 32 | |
976 | //64 128 256 | |
977 | if ( (mask&(1+2+4)) == (1+2+4)) | |
978 | k++; | |
979 | if ( (mask&(4+32+256)) == (4+32+256)) | |
980 | k |= 2; | |
981 | if ( (mask&(64+128+256)) == (64+128+256)) | |
982 | k |= 4; | |
983 | if ( (mask&(1+8+64)) == (1+8+64)) | |
984 | k |= 8; | |
985 | int id = 0x80+k; | |
986 | if ( k == 0) | |
987 | id = 0xB0; | |
988 | if ( k == 0 && (mask & 16)) | |
989 | id = 0x80; | |
990 | if ( k == 3 && !(mask & 16)) | |
991 | id = 0x3C; | |
992 | if ( k == 6 && !(mask & 16)) | |
993 | id = 0x3D; | |
994 | if ( k == 12 && !(mask & 16)) | |
995 | id = 0x3F; | |
996 | if ( k == 9 && !(mask & 16)) | |
997 | id = 0x3E; | |
998 | ||
999 | duneGround[x][y] = id; | |
1000 | } | |
1001 | } | |
1002 | } | |
1003 | ||
1004 | // Diamond Square algorithm | |
1005 | void GenerateGroundCycle(Ground &g, int width) | |
1006 | { | |
1007 | for (int step = width; step >= 1; step/=2) | |
1008 | { | |
1009 | int step2 = step/2; | |
1010 | for (int y=step2; y<width; y+=step) | |
1011 | { | |
1012 | for (int x=step2; x<width; x+=step) | |
1013 | { | |
1014 | g[x][y] = (g[x-step2][y-step2] | |
1015 | + g[x+step2][y-step2] | |
1016 | + g[x-step2][y+step2] | |
1017 | + g[x+step2][y+step2])/4 + ((-1+randf()*2)*step2/64); | |
1018 | if (g[x][y]>1) | |
1019 | g[x][y]=1; | |
1020 | if (g[x][y]<0) | |
1021 | g[x][y]=0; | |
1022 | } | |
1023 | } | |
1024 | ||
1025 | for (int z=0; z<2; ++z) | |
1026 | { | |
1027 | for (int y=z*step2; y<width; y+=step) | |
1028 | { | |
1029 | for (int x=(1-z)*step2; x<width; x+=step) | |
1030 | { | |
1031 | double h = 0; | |
1032 | int n = 0; | |
1033 | if (g.in(x-step2,y)) | |
1034 | { | |
1035 | h += g[x-step2][y]; | |
1036 | ++n; | |
1037 | } | |
1038 | if (g.in(x+step2,y)) | |
1039 | { | |
1040 | h += g[x+step2][y]; | |
1041 | ++n; | |
1042 | } | |
1043 | if (g.in(x,y-step2)) | |
1044 | { | |
1045 | h += g[x][y-step2]; | |
1046 | ++n; | |
1047 | } | |
1048 | if (g.in(x,y+step2)) | |
1049 | { | |
1050 | h += g[x][y+step2]; | |
1051 | ++n; | |
1052 | } | |
1053 | h /= n; | |
1054 | h += ((-1+randf()*2)*step2/64); | |
1055 | if (h>1) | |
1056 | h=1; | |
1057 | if (h<0) | |
1058 | h=0; | |
1059 | g[x][y] = h; | |
1060 | } | |
1061 | } | |
1062 | } | |
1063 | } | |
1064 | } | |
1065 | ||
1066 | GLuint GenerateGround() | |
1067 | { | |
1068 | g[ 0][ 0] = randf(); | |
1069 | g[g.width-1][ 0] = randf(); | |
1070 | g[ 0][g.height-1] = randf(); | |
1071 | g[g.width-1][g.height-1] = randf(); | |
1072 | ||
1073 | //GenerateGroundRecursive(g, 0, 0, g.width-1, g.height-1); | |
1074 | GenerateGroundCycle(g, g.width-1); | |
1075 | ||
1076 | return MakeGreyTexture(); | |
1077 | } | |
1078 | ||
1079 | GLuint MakeGreyTexture() | |
1080 | { | |
1081 | BYTE *data = (BYTE*)malloc( (g.width-1) * (g.height-1) * 3 ); | |
1082 | ||
1083 | for (int x=0; x<g.width-1; ++x) | |
1084 | { | |
1085 | for (int y=0; y<g.height-1; ++y) | |
1086 | { | |
1087 | for (int i=0; i<3; ++i) | |
1088 | data[(x + y*(g.width-1))*3 + i] = g[x][y]*255; | |
1089 | } | |
1090 | } | |
1091 | ||
1092 | GLuint texture; | |
1093 | glGenTextures( 1, &texture ); | |
1094 | ||
1095 | glBindTexture( GL_TEXTURE_2D, texture ); | |
1096 | ||
1097 | glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); | |
1098 | ||
1099 | // when texture area is small, bilinear filter the closest MIP map | |
1100 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); | |
1101 | ||
1102 | // when texture area is large, bilinear filter the first MIP map | |
1103 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); | |
1104 | ||
1105 | // if wrap is true, the texture wraps over at the edges (repeat) | |
1106 | // ... false, the texture ends at the edges (clamp) | |
1107 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); | |
1108 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); | |
1109 | ||
1110 | glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, g.width-1, g.height-1, 0, GL_RGB, GL_UNSIGNED_BYTE, data ); | |
1111 | ||
1112 | free(data); | |
1113 | ||
1114 | return texture; | |
1115 | } | |
1116 | ||
1117 | void LoadMap( const char * filename ) | |
1118 | { | |
1119 | FILE *f = fopen(filename, "rb"); | |
1120 | if (!f) | |
1121 | return; | |
1122 | BYTE tmp; | |
1123 | duneGround.Clear(); | |
1124 | for (int y=0; y<duneGround.height; ++y) | |
1125 | for (int x=0; x<duneGround.width; ++x) | |
1126 | { | |
1127 | fread(&tmp,1,1,f); | |
1128 | duneGround[x][y]=tmp; | |
1129 | duneGround.SetTileMask(x,y); | |
1130 | } | |
1131 | fclose(f); | |
1132 | } | |
1133 | ||
1134 | void SaveMap( const char * filename ) | |
1135 | { | |
1136 | FILE *f = fopen(filename,"wb"); | |
1137 | if (!f) | |
1138 | return; | |
1139 | for (int y=0; y<duneGround.height; ++y) | |
1140 | for (int x=0; x<duneGround.width; ++x) | |
1141 | fwrite(&duneGround[x][y],1,1,f); | |
1142 | fclose(f); | |
1143 | } | |
1144 | ||
1145 | void LoadMission( const char * filename ) | |
1146 | { | |
1147 | FILE *f = fopen(filename, "rb"); | |
1148 | if (!f) | |
1149 | return; | |
1150 | //FILE *log = fopen("log.txt","w"); | |
1151 | BYTE buff[20]; | |
1152 | Units.clear(); | |
1153 | Structures.clear(); | |
1154 | DuneUnit unit; | |
1155 | DuneStructure structure; | |
1156 | for (;;) | |
1157 | { | |
1158 | BYTE cmd; | |
1159 | BYTE subcmd; | |
1160 | if (!fread(&cmd,1,1,f)) | |
1161 | break; | |
1162 | fread(&subcmd,1,1,f); | |
1163 | //fprintf(log,"cmd = %d, subcmd = %d, offset = %X\n",cmd,subcmd,ftell(f)-2); | |
1164 | if (cmd & 0x80) | |
1165 | break; | |
1166 | switch(cmd) | |
1167 | { | |
1168 | // Settings | |
1169 | case 0: | |
1170 | switch(subcmd) | |
1171 | { | |
1172 | // LosePicture | |
1173 | case 0: | |
1174 | // WinPicture | |
1175 | case 1: | |
1176 | // BriefPicture | |
1177 | case 2: | |
1178 | fread(buff,1,2,f); | |
1179 | fseek(f,(buff[0]<<8)|buff[1],SEEK_CUR); | |
1180 | break; | |
1181 | ||
1182 | // TimeOut | |
1183 | case 3: | |
1184 | // MapScale | |
1185 | case 4: | |
1186 | // CursorPos | |
1187 | case 5: | |
1188 | // TacticalPos | |
1189 | case 6: | |
1190 | // LoseFlags | |
1191 | case 7: | |
1192 | // WinFlags | |
1193 | case 8: | |
1194 | fread(buff,1,2,f); | |
1195 | break; | |
1196 | } | |
1197 | break; | |
1198 | // MAP | |
1199 | case 1: | |
1200 | switch(subcmd) | |
1201 | { | |
1202 | // Bloom | |
1203 | case 'B': | |
1204 | // Field | |
1205 | case 'F': | |
1206 | fread(buff,1,2,f); | |
1207 | fseek(f,((buff[0]<<8)|buff[1])*2,SEEK_CUR); | |
1208 | break; | |
1209 | case 'S': | |
1210 | fread(buff,1,2,f); | |
1211 | //sprintf(buff,"%d",((buff[0]<<8)|buff[1])); | |
1212 | //MessageBox(NULL,buff,"Seed",MB_OK); | |
1213 | break; | |
1214 | } | |
1215 | break; | |
1216 | // Harkonnen | |
1217 | case 2: | |
1218 | // Atreides | |
1219 | case 3: | |
1220 | // Ordos | |
1221 | case 4: | |
1222 | // Fremen | |
1223 | case 5: | |
1224 | switch(subcmd) | |
1225 | { | |
1226 | // Quota | |
1227 | case 'Q': | |
1228 | // Credits | |
1229 | case 'C': | |
1230 | // Brain | |
1231 | case 'B': | |
1232 | // MaxUnits | |
1233 | case 'M': | |
1234 | fread(buff,1,2,f); | |
1235 | //sprintf(buff,"%d(%X)%c",cmd,ftell(f),subcmd); | |
1236 | //MessageBox(NULL,buff,"House",MB_OK); | |
1237 | break; | |
1238 | } | |
1239 | break; | |
1240 | // Starport (subcmd = unit) | |
1241 | case 6: | |
1242 | fread(buff,1,2,f); | |
1243 | break; | |
1244 | // Teams ( subcmd = team id ) | |
1245 | case 7: | |
1246 | fseek(f,5*2,SEEK_CUR); | |
1247 | break; | |
1248 | // Units ( subcmd = unk ) | |
1249 | case 8: | |
1250 | fread(buff,1,6*2,f); | |
1251 | unit.house = (buff[ 0]<<8) | buff[ 1]; | |
1252 | unit.id = (buff[ 2]<<8) | buff[ 3]; | |
1253 | unit.life = (buff[ 4]<<8) | buff[ 5]; | |
1254 | unit.pos = (buff[ 6]<<8) | buff[ 7]; | |
1255 | unit.angle = (buff[ 8]<<8) | buff[ 9]; | |
1256 | unit.ai = (buff[10]<<8) | buff[12]; | |
1257 | Units.push_back(unit); | |
1258 | break; | |
1259 | // Structures ( subcmd = unk ) | |
1260 | case 9: | |
1261 | if (subcmd == 'G') | |
1262 | { | |
1263 | fread(buff,1,3*2,f); | |
1264 | structure.pos = (buff[ 0]<<8) | buff[ 1]; | |
1265 | structure.house = (buff[ 2]<<8) | buff[ 3]; | |
1266 | structure.id = (buff[ 4]<<8) | buff[ 5]; | |
1267 | } | |
1268 | else | |
1269 | { | |
1270 | fread(buff,1,5*2,f); | |
1271 | structure.flag = (buff[ 0]<<8) | buff[ 1]; | |
1272 | structure.house = (buff[ 2]<<8) | buff[ 3]; | |
1273 | structure.id = (buff[ 4]<<8) | buff[ 5]; | |
1274 | structure.life = (buff[ 6]<<8) | buff[ 7]; | |
1275 | structure.pos = (buff[ 8]<<8) | buff[ 9]; | |
1276 | } | |
1277 | Structures.push_back(structure); | |
1278 | break; | |
1279 | // Reinforcements | |
1280 | case 10: | |
1281 | fread(buff,1,4*2,f); | |
1282 | break; | |
1283 | } | |
1284 | } | |
1285 | fclose(f); | |
1286 | //fclose(log); | |
1287 | //sprintf((char*)buff,"%d",Units.size()); | |
1288 | //MessageBox(NULL,(char*)buff,"Units.size()",MB_OK); | |
1289 | } | |
1290 | ||
1291 | void FreeTexture( GLuint texture ) | |
1292 | { | |
1293 | glDeleteTextures( 1, &texture ); | |
1294 | } | |
1295 | ||
1296 | bool mousedown = false; | |
1297 | ||
1298 | void UpdateViewport(HWND hWnd) | |
1299 | { | |
1300 | RECT rc; | |
1301 | GetClientRect(hWnd, &rc); | |
1302 | glViewport( 0, 0, rc.right, rc.bottom); | |
1303 | glMatrixMode( GL_PROJECTION ); | |
1304 | glLoadIdentity(); | |
1305 | //gluOrtho2D( 0,0,500,500);//camera.x, camera.y, camera.x+rc.right, camera.y+rc.bottom); | |
1306 | double scale = 1/32.0/zoom; | |
1307 | glScalef(64.0/rc.right*zoom,64.0/rc.bottom*zoom,1); | |
1308 | glTranslatef( -camera.x*scale, camera.y*scale, 0); | |
1309 | glMatrixMode( GL_MODELVIEW ); | |
1310 | } | |
1311 | ||
1312 | void ChangeState(int _state) | |
1313 | { | |
1314 | if (state == _state) | |
1315 | return; | |
1316 | state = _state; | |
1317 | } | |
1318 | ||
1319 | int CurrentMap = 0; | |
1320 | ||
1321 | void TryQuit(HWND hWnd) | |
1322 | { | |
1323 | int ret = MessageBox(hWnd,"Do you want to save map?","DuneGroundEditor",MB_YESNOCANCEL); | |
1324 | if (ret == IDYES) | |
1325 | { | |
1326 | LPCSTR filename = SaveFile(hWnd, NULL); | |
1327 | if (filename) | |
1328 | { | |
1329 | SaveMap(filename); | |
1330 | PostQuitMessage( 0 ); | |
1331 | } | |
1332 | } | |
1333 | if (ret == IDNO) | |
1334 | PostQuitMessage( 0 ); | |
1335 | } | |
1336 | // Window Proc /////////////////////////////////////////////////////// | |
1337 | ||
1338 | LRESULT CALLBACK WndProc( HWND hWnd, UINT message, | |
1339 | WPARAM wParam, LPARAM lParam ) | |
1340 | { | |
1341 | switch ( message ) { | |
1342 | ||
1343 | case WM_CREATE: | |
1344 | return 0; | |
1345 | ||
1346 | case WM_CLOSE: | |
1347 | TryQuit(hWnd); | |
1348 | return 0; | |
1349 | ||
1350 | case WM_SIZE: | |
1351 | UpdateViewport(hWnd); | |
1352 | break; | |
1353 | ||
1354 | case WM_DESTROY: | |
1355 | return 0; | |
1356 | ||
1357 | case WM_KEYDOWN: | |
1358 | switch ( wParam ) { | |
1359 | ||
1360 | case VK_ESCAPE: | |
1361 | if (state == 0) | |
1362 | TryQuit(hWnd); | |
1363 | else | |
1364 | ChangeState(0); | |
1365 | return 0; | |
1366 | ||
1367 | case 'O': | |
1368 | { | |
1369 | LPCSTR filename = OpenFile(hWnd, "Choose Map"); | |
1370 | if (filename) | |
1371 | LoadMap(filename); | |
1372 | } | |
1373 | return 0; | |
1374 | ||
1375 | case 'M': | |
1376 | { | |
1377 | LPCSTR filename = OpenFile(hWnd, "Choose Mission"); | |
1378 | if (filename) | |
1379 | LoadMission(filename); | |
1380 | } | |
1381 | return 0; | |
1382 | ||
1383 | case 'S': | |
1384 | { | |
1385 | LPCSTR filename = SaveFile(hWnd, NULL); | |
1386 | if (filename) | |
1387 | SaveMap(filename); | |
1388 | } | |
1389 | return 0; | |
1390 | case 'G': | |
1391 | { | |
1392 | LPCSTR filename = OpenFile(hWnd, "Choose Grey Bitmap"); | |
1393 | if (filename) | |
1394 | { | |
1395 | FreeTexture(GroundGrey); | |
1396 | GroundGrey = LoadGreyTexture(filename); | |
1397 | } | |
1398 | } | |
1399 | return 0; | |
1400 | ||
1401 | case 'R': | |
1402 | FreeTexture(GroundGrey); | |
1403 | GroundGrey = GenerateGround(); | |
1404 | return 0; | |
1405 | case 'E': | |
1406 | if (state == 2) | |
1407 | ChangeState(1); | |
1408 | else | |
1409 | ChangeState(state^1); | |
1410 | return 0; | |
1411 | case 'F': | |
1412 | if (state == 2) | |
1413 | ChangeState(0); | |
1414 | else | |
1415 | ChangeState(2); | |
1416 | return 0; | |
1417 | case 'I': | |
1418 | drawinverse = !drawinverse; | |
1419 | return 0; | |
1420 | case '0': | |
1421 | drawtype = 0; | |
1422 | return 0; | |
1423 | case '1': | |
1424 | drawtype = 1; | |
1425 | return 0; | |
1426 | case '2': | |
1427 | drawtype = 2; | |
1428 | return 0; | |
1429 | case '3': | |
1430 | drawtype = 3; | |
1431 | return 0; | |
1432 | case '4': | |
1433 | drawtype = 4; | |
1434 | return 0; | |
1435 | case 'Q': | |
1436 | --drawsize; | |
1437 | if (drawsize == 0) | |
1438 | drawsize = 1; | |
1439 | return 0; | |
1440 | case 'W': | |
1441 | ++drawsize; | |
1442 | return 0; | |
1443 | case 'C': | |
1444 | if (MessageBox(hWnd,"Do you really want to clear map?","DuneGroundEditor",MB_YESNO) == IDYES) | |
1445 | duneGround.Clear(); | |
1446 | return 0; | |
1447 | ||
1448 | case VK_SPACE: | |
1449 | showgrey = !showgrey; | |
1450 | return 0; | |
1451 | case 'U': | |
1452 | showunits = !showunits; | |
1453 | return 0; | |
1454 | } | |
1455 | return 0; | |
1456 | ||
1457 | case WM_MOUSEWHEEL: | |
1458 | { | |
1459 | RECT rc; | |
1460 | GetClientRect(hWnd,&rc); | |
1461 | mouse.x = GET_X_LPARAM(lParam); | |
1462 | mouse.y = GET_Y_LPARAM(lParam); | |
1463 | short zDelta = HIWORD(wParam); | |
1464 | if (zDelta > 0) | |
1465 | { | |
1466 | zoom *= 1.2; | |
1467 | camera.x *= 1.2;//(camera.x + mouse.x) * (zoom/(zoom-0.1)) - mouse.x; | |
1468 | camera.y *= 1.2;//(camera.y + mouse.y) * (zoom/(zoom-0.1)) - mouse.y; | |
1469 | } | |
1470 | else | |
1471 | { | |
1472 | zoom /= 1.2; | |
1473 | camera.x /= 1.2; | |
1474 | camera.y /= 1.2; | |
1475 | } | |
1476 | ||
1477 | UpdateViewport(hWnd); | |
1478 | } | |
1479 | break; | |
1480 | case WM_LBUTTONDOWN: | |
1481 | { | |
1482 | SetCapture(hWnd); | |
1483 | mouse.x = GET_X_LPARAM(lParam); | |
1484 | mouse.y = GET_Y_LPARAM(lParam); | |
1485 | //RECT rc; | |
1486 | //GetClientRect(hWnd,&rc); | |
1487 | //double cx = ((camera.x+mouse.x-(rc.right/2))/32.0/zoom); | |
1488 | //double cy = ((camera.y+mouse.y-(rc.bottom/2))/32.0/zoom); | |
1489 | if (state == 2) | |
1490 | { | |
1491 | duneGround = duneGroundNew; | |
1492 | ChangeState(0); | |
1493 | } | |
1494 | } | |
1495 | break; | |
1496 | case WM_MOUSEMOVE: | |
1497 | { | |
1498 | POINT pos = mouse; | |
1499 | mouse.x = GET_X_LPARAM(lParam); | |
1500 | mouse.y = GET_Y_LPARAM(lParam); | |
1501 | RECT rc; | |
1502 | GetClientRect(hWnd,&rc); | |
1503 | ||
1504 | if (mousedown) | |
1505 | { | |
1506 | camera.x -= mouse.x-pos.x; | |
1507 | camera.y -= mouse.y-pos.y; | |
1508 | UpdateViewport(hWnd); | |
1509 | } | |
1510 | ||
1511 | double cx = ((camera.x+mouse.x-(rc.right/2))/32.0/zoom)*2+0.5; | |
1512 | double cy = ((camera.y+mouse.y-(rc.bottom/2))/32.0/zoom)*2+0.5; | |
1513 | if (state == 1 && duneGround.tin(cx,cy) && (GetKeyState(VK_LBUTTON) & 0x80)) | |
1514 | { | |
1515 | for (int x=0; x<drawsize; ++x) | |
1516 | for (int y=0; y<drawsize; ++y) | |
1517 | if (duneGround.tin(cx+x,cx+y)) | |
1518 | duneGround.Draw(cx+x,cy+y,drawtype); | |
1519 | } | |
1520 | } | |
1521 | break; | |
1522 | case WM_LBUTTONUP: | |
1523 | ReleaseCapture(); | |
1524 | break; | |
1525 | case WM_RBUTTONDOWN: | |
1526 | SetCapture(hWnd); | |
1527 | mouse.x = GET_X_LPARAM(lParam); | |
1528 | mouse.y = GET_Y_LPARAM(lParam); | |
1529 | mousedown = true; | |
1530 | break; | |
1531 | case WM_RBUTTONUP: | |
1532 | ReleaseCapture(); | |
1533 | mousedown = false; | |
1534 | break; | |
1535 | } | |
1536 | return DefWindowProc( hWnd, message, wParam, lParam ); | |
1537 | } | |
1538 | ||
1539 | ||
1540 | // Dialogs | |
1541 | ||
1542 | LPCSTR OpenFile(HWND hWnd, LPCSTR title) | |
1543 | { | |
1544 | OPENFILENAME opn; | |
1545 | memset(&opn, 0, sizeof(opn)); | |
1546 | opn.lStructSize = sizeof(opn); | |
1547 | opn.hwndOwner = hWnd; | |
1548 | opn.lpstrFilter = "All Files\0*.*\0\0"; | |
1549 | opn.nFilterIndex = 1; | |
1550 | static char filename[MAX_PATH]; | |
1551 | filename[0] = 0; | |
1552 | opn.lpstrFile = filename; | |
1553 | opn.nMaxFile = MAX_PATH; | |
1554 | opn.lpstrTitle = title; | |
1555 | opn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR; | |
1556 | if (GetOpenFileName(&opn)) | |
1557 | return filename; | |
1558 | return NULL; | |
1559 | } | |
1560 | ||
1561 | LPCSTR SaveFile(HWND hWnd, LPCSTR title) | |
1562 | { | |
1563 | OPENFILENAME opn; | |
1564 | memset(&opn, 0, sizeof(opn)); | |
1565 | opn.lStructSize = sizeof(opn); | |
1566 | opn.hwndOwner = hWnd; | |
1567 | opn.lpstrFilter = "All Files\0*.*\0\0"; | |
1568 | opn.nFilterIndex = 1; | |
1569 | static char filename[MAX_PATH]; | |
1570 | filename[0] = 0; | |
1571 | opn.lpstrFile = filename; | |
1572 | opn.nMaxFile = MAX_PATH; | |
1573 | opn.lpstrTitle = title; | |
1574 | opn.Flags = OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR; | |
1575 | if (GetSaveFileName(&opn)) | |
1576 | return filename; | |
1577 | return NULL; | |
1578 | } | |
1579 | ||
1580 | // Enable OpenGL | |
1581 | ||
1582 | VOID EnableOpenGL( HWND hWnd, HDC * hDC, HGLRC * hRC ) | |
1583 | { | |
1584 | PIXELFORMATDESCRIPTOR pfd; | |
1585 | int iFormat; | |
1586 | ||
1587 | // get the device context (DC) | |
1588 | *hDC = GetDC( hWnd ); | |
1589 | ||
1590 | // set the pixel format for the DC | |
1591 | ZeroMemory( &pfd, sizeof( pfd ) ); | |
1592 | pfd.nSize = sizeof( pfd ); | |
1593 | pfd.nVersion = 1; | |
1594 | pfd.dwFlags = PFD_DRAW_TO_WINDOW | | |
1595 | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; | |
1596 | pfd.iPixelType = PFD_TYPE_RGBA; | |
1597 | pfd.cColorBits = 24; | |
1598 | pfd.cDepthBits = 16; | |
1599 | pfd.iLayerType = PFD_MAIN_PLANE; | |
1600 | iFormat = ChoosePixelFormat( *hDC, &pfd ); | |
1601 | SetPixelFormat( *hDC, iFormat, &pfd ); | |
1602 | ||
1603 | // create and enable the render context (RC) | |
1604 | *hRC = wglCreateContext( *hDC ); | |
1605 | wglMakeCurrent( *hDC, *hRC ); | |
1606 | ||
1607 | } | |
1608 | ||
1609 | // Disable OpenGL | |
1610 | ||
1611 | VOID DisableOpenGL( HWND hWnd, HDC hDC, HGLRC hRC ) | |
1612 | { | |
1613 | wglMakeCurrent( NULL, NULL ); | |
1614 | wglDeleteContext( hRC ); | |
1615 | ReleaseDC( hWnd, hDC ); | |
1616 | } |