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 | } |