Advertisement
r57shell

Dune2GroundEdit

Sep 25th, 2013
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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.  
  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);
  83.         if (types)
  84.             free(types);
  85.     }
  86.    
  87.     DuneGround(const DuneGround & g)
  88.     {
  89.         data = 0;
  90.         types = 0;
  91.         width = 0;
  92.         height = 0;
  93.         (*this) = g;
  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.         memcpy(data,g.data,width*height*sizeof(BYTE));
  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.     inline int theight() const
  131.     {
  132.         return height*2+1;
  133.     }
  134.    
  135.     inline bool tin(int x, int y) const
  136.     {
  137.         return (x>=0 && y>=0 && x<twidth() && y<theight());
  138.     }
  139.    
  140.     inline bool in(int x, int y) const
  141.     {
  142.         return (x>=0 && y>=0 && x<width && y<height);
  143.     }
  144.    
  145.     void Draw(int x, int y, BYTE type)
  146.     {
  147.         //   0   1   2
  148.         // 0 1 2 3 4 5 6
  149.         this->t(x,y) = type;
  150.         if (in(x/2, y/2))
  151.             Correct(x/2, y/2, type);
  152.         if (in(x/2-1, y/2))
  153.             Correct(x/2-1,y/2,type);
  154.         if (in(x/2, y/2-1))
  155.             Correct(x/2,y/2-1,type);
  156.         if (in(x/2-1, y/2-1))
  157.             Correct(x/2-1-1,y/2-1,type);
  158.        
  159.     }
  160.    
  161.     void Correct(int x, int y, BYTE type_draw)
  162.     {
  163.         if (type_draw == Ground)
  164.         {
  165.             for (int i=0; i<3; ++i)
  166.                 for (int j=0; j<3; ++j)
  167.                     if (t(i+x*2,j+y*2) != Ground
  168.                      && t(i+x*2,j+y*2) != Dust)
  169.                         Draw(i+x*2,j+y*2,Dust);
  170.         }
  171.         if (type_draw == SpiceLow)
  172.         {
  173.             for (int i=0; i<3; ++i)
  174.                 for (int j=0; j<3; ++j)
  175.                     if (t(i+x*2,j+y*2) != SpiceLow
  176.                      && t(i+x*2,j+y*2) != SpiceHigh
  177.                      && t(i+x*2,j+y*2) != Dust)
  178.                         Draw(i+x*2,j+y*2,Dust);
  179.         }
  180.         if (type_draw == SpiceHigh)
  181.         {
  182.             for (int i=0; i<3; ++i)
  183.                 for (int j=0; j<3; ++j)
  184.                     if (t(i+x*2,j+y*2) != SpiceHigh
  185.                      && t(i+x*2,j+y*2) != SpiceLow)
  186.                         Draw(i+x*2,j+y*2,SpiceLow);
  187.         }
  188.         if (type_draw == SpiceHigh)
  189.         {
  190.             for (int i=0; i<3; ++i)
  191.                 for (int j=0; j<3; ++j)
  192.                     if (t(i+x*2,j+y*2) != SpiceHigh
  193.                      && t(i+x*2,j+y*2) != SpiceLow)
  194.                         Draw(i+x*2,j+y*2,SpiceLow);
  195.         }
  196.         if (type_draw == Dune)
  197.         {
  198.             for (int i=0; i<3; ++i)
  199.                 for (int j=0; j<3; ++j)
  200.                     if (t(i+x*2,j+y*2) != Dune
  201.                      && t(i+x*2,j+y*2) != Dust)
  202.                         Draw(i+x*2,j+y*2,Dust);
  203.             /*int k = GetK(x,y,Dune);
  204.             int mask = dunemask[k];
  205.             for (int i=0; i<3; ++i)
  206.                 for (int j=0; j<3; ++j)
  207.                 {
  208.                     if ((mask & (1<<(i+j*3)))
  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.                 if (in(x+i,y+j))
  219.                     Update(x+i, y+j);
  220.     }
  221.    
  222.     int GetK(int x, int y, BYTE type)
  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.             k = 0;
  236.             int min = 10;
  237.             for (int i=0; i<256; ++i)
  238.                 if (dunemask[i] != -1)
  239.                 {
  240.                     int d = DunemaskDist((dunemask[i] & DUNE_MASK), (mask & DUNE_MASK));
  241.                     if (((dunemask[i] & DUNE_MASK) & (mask & DUNE_MASK)) == (mask & DUNE_MASK)
  242.                      && d < min)
  243.                     {
  244.                         k = i;
  245.                         min = d;
  246.                     }
  247.                 }
  248.             for (int i=0; i<256; ++i)
  249.                 if (dunemask[i] != -1)
  250.                 {
  251.                     if (((dunemask[k] & DUNE_MASK)|(mask&16)) == (dunemask[i] & DUNE_MASKMID))
  252.                         k = i;
  253.                 }
  254.             if (k == 0x9C && (mask & 2))
  255.                 k = 0x60;
  256.             if (dunemask[k] == 0)
  257.                 k = 0;
  258.         }
  259.         else
  260.         {
  261.             if ( (mask&(1+2+4)) == (1+2+4))
  262.                 k++;
  263.             if ( (mask&(4+32+256)) == (4+32+256))
  264.                 k |= 2;
  265.             if ( (mask&(64+128+256)) == (64+128+256))
  266.                 k |= 4;
  267.             if ( (mask&(1+8+64)) == (1+8+64))
  268.                 k |= 8;
  269.            
  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 ( k == 12 && !(mask & 16))
  277.                 k = 20;
  278.             if ( k == 9 && !(mask & 16))
  279.                 k = 19;
  280.         }
  281.         return k;
  282.     }
  283.     void Update(int x, int y)
  284.     {
  285.         int types_mask = 0;
  286.         for (int type = 0; type < 5; ++type)
  287.         {
  288.             bool was = false;
  289.             for (int i=0; i<3; ++i)
  290.                 for (int j=0; j<3; ++j)
  291.                     if (t(i+x*2,j+y*2) == type)
  292.                         was = true;
  293.             if (was)
  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.             id = 0x80+k;
  304.             if (k == 0)
  305.                 id = 0xB0;
  306.             if ( k == 16) // point
  307.                 id = 0x80;
  308.             if ( k == 17)
  309.                 id = 0x3C;
  310.             if ( k == 18)
  311.                 id = 0x3D;
  312.             if ( k == 20)
  313.                 id = 0x3F;
  314.             if ( k == 19)
  315.                 id = 0x3E;
  316.         }
  317.        
  318.         if (types_mask & (1<<SpiceLow))
  319.         {
  320.             k = GetK(x,y,SpiceLow);
  321.             id = 0xB0+k;
  322.             if ( k == 17)
  323.                 id = 0x40;
  324.             if ( k == 18)
  325.                 id = 0x41;
  326.             if ( k == 20)
  327.                 id = 0x43;
  328.             if ( k == 19)
  329.                 id = 0x42;
  330.         }
  331.        
  332.         if (types_mask & (1<<SpiceHigh))
  333.         {
  334.             k = GetK(x,y,SpiceHigh);
  335.             id = 0xC0+k;
  336.             if ( k == 17 )
  337.                 id = 0x44;
  338.             if ( k == 18 )
  339.                 id = 0x45;
  340.             if ( k == 20 )
  341.                 id = 0x47;
  342.             if ( k == 19 )
  343.                 id = 0x46;
  344.         }
  345.         if (types_mask & (1<<Dune))
  346.         {
  347.             k = GetK(x,y,Dune);
  348.             if (k)
  349.                 id = k;
  350.             //id = 0x9F;
  351.         }
  352.         (*this)[x][y] = id;
  353.     }
  354.    
  355.     void SetTileMask(int x, int y)
  356.     {
  357.         int id = (*this)[x][y];
  358.         int type = Dust;
  359.         int mask = 0;
  360.         int k = 0;
  361.         if (id > 0x80 && id <= 0x8F)
  362.         {
  363.             type = Ground; k = id-0x80;
  364.         }
  365.         if (id == 0x80)
  366.         {
  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.         if (id == 0x43)
  405.         {
  406.             type = SpiceLow; k = 20;
  407.         }
  408.         if (id == 0x42)
  409.         {
  410.             type = SpiceLow; k = 19;
  411.         }
  412.        
  413.         if (id > 0xC0 && id <= 0xCF)
  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.             type = SpiceHigh; k = 18;
  425.         }
  426.         if (id == 0x47)
  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 (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.                     mask = make_dunemask(1,1,1,0,0,1,0,0,1);
  460.                 if (k == 18)
  461.                     mask = make_dunemask(0,0,1,0,0,1,1,1,1);
  462.                 if (k == 20)
  463.                     mask = make_dunemask(1,0,0,1,0,0,1,1,1);
  464.                 if (k == 19)
  465.                     mask = make_dunemask(1,1,1,1,0,0,1,0,0);
  466.             }
  467.         }
  468.  
  469.         for (int i=0; i<256; ++i)
  470.             if (dunemask[i] != -1 && i == id)
  471.             {
  472.                 mask = dunemask[i];
  473.                 type = Dune;
  474.             }
  475.         int a = type;
  476.         int b = Dust;
  477.         if (type == SpiceHigh)
  478.             b = SpiceLow;
  479.         for (int i=0; i<3; ++i)
  480.             for (int j=0; j<3; ++j)
  481.                 if (mask & (1<<(i+j*3)))
  482.                     t(i+x*2,j+y*2) = a;
  483.                 else
  484.                 {
  485.                     if (b == SpiceLow && t(i+x*2,j+y*2) != SpiceLow)
  486.                         t(i+x*2,j+y*2) = b;
  487.                 }
  488.     }
  489.    
  490.     BYTE *operator [](int x)
  491.     {
  492.         return data+x*height;
  493.     }
  494.    
  495.     BYTE & t(int x,int y)
  496.     {
  497.         return types[y*twidth()+x];
  498.     }
  499. };
  500.  
  501. struct DuneUnit
  502. {
  503.     short house;
  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.                     LPSTR lpCmdLine, int iCmdShow )
  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.     // program main loop
  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.                 DispatchMessage( &msg );
  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. {
  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.     glBegin( GL_QUADS );
  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.             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.     }
  703.     glEnd();
  704.    
  705.     if (state == 1)
  706.     {
  707.         glEnable( GL_BLEND );
  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.             glTexCoord2d((si.x+       0)/512.0,1-(si.y+si.height)/512.0); glVertex2d(x,            -(y+si.height/32));
  744.         }
  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 y = (Units[i].pos/0x40);
  754.             int id = Units[i].id;
  755.             int idx = id&15;
  756.             int idy = (id>>4);
  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.               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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement