Wang Tiling
A Simple Wang Tiling Generator
CMain.cpp
Go to the documentation of this file.
1
3
4// MIT License
5//
6// Copyright (c) 2020 Ian Parberry
7//
8// Permission is hereby granted, free of charge, to any person obtaining a copy
9// of this software and associated documentation files (the "Software"), to
10// deal in the Software without restriction, including without limitation the
11// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12// sell copies of the Software, and to permit persons to whom the Software is
13// furnished to do so, subject to the following conditions:
14//
15// The above copyright notice and this permission notice shall be included in
16// all copies or substantial portions of the Software.
17//
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24// IN THE SOFTWARE.
25
26#include "CMain.h"
27#include "WindowsHelpers.h"
28
30// Constructors and destructors
31
32#pragma region Constructors and destructors
33
38
39CMain::CMain(const HWND hwnd):
40 m_hWnd(hwnd)
41{
42 m_gdiplusToken = InitGDIPlus(); //initialize GDI+
43 CreateMenus(); //create the menu bar
44 m_pWangTiler = new CWangTiler(16, 16); //create the Wang tiler
45
46 if(FAILED(LoadTileSet(IDM_TILESET_DEFAULT, 8))) //load the default tile set
47 FatalAppExit(0, "One or more default tileset images are missing.");
48
49 Generate(); //generate a Wang tiling
50 Draw(); //draw it to the bitmap
51} //constructor
52
54
56 delete m_pWangTiler;
57 delete m_pBitmap;
58
59 for(UINT i=0; i<m_nNumTiles; i++)
60 delete m_pTile[i];
61 delete [] m_pTile;
62
63 Gdiplus::GdiplusShutdown(m_gdiplusToken);
64} //destructor
65
66#pragma endregion Constructors and destructors
67
69// Drawing functions
70
71#pragma region Drawing functions
72
76
78 PAINTSTRUCT ps; //paint structure
79 HDC hdc = BeginPaint(m_hWnd, &ps); //device context
80 Gdiplus::Graphics graphics(hdc); //GDI+ graphics object
81
82 //bitmap width and height
83
84 const int nBitmapWidth = m_pBitmap->GetWidth();
85 const int nBitmapHeight = m_pBitmap->GetHeight();
86
87 //get client rectangle
88
89 RECT rectClient; //for client rectangle
90 GetClientRect(m_hWnd, &rectClient); //get client rectangle
91 const int nClientWidth = rectClient.right - rectClient.left; //client width
92 const int nClientHeight = rectClient.bottom - rectClient.top; //client height
93
94 //compute destination rectangle
95
96 const int nDestSide = min(nClientWidth, nClientHeight); //dest width and ht
97
98 const int width = min(nDestSide, nBitmapWidth); //dest rect width
99 const int height = min(nDestSide, nBitmapHeight); //dest rect height
100
101 const int x = max(0, nClientWidth - width)/2; //x margin
102 const int y = max(0, nClientHeight - height)/2; //y margin
103
104 Gdiplus::Rect rectDest(x, y, width, height); //destination rectangle
105
106 //draw image to destination rectangle then clean up
107
108 graphics.DrawImage(m_pBitmap, rectDest);
109
110 EndPaint(m_hWnd, &ps); //this must be done last
111} //OnPaint
112
116
118 const UINT nTileWidth = m_pTile[0]->GetWidth();
119 const UINT nTileHeight = m_pTile[0]->GetHeight();
120
121 if(m_pBitmap == nullptr){
122 const int w = int(nTileWidth*m_pWangTiler->GetWidth());
123 const int h = int(nTileHeight*m_pWangTiler->GetHeight());
124 m_pBitmap = new Gdiplus::Bitmap(w, h);
125 } //if
126
127 const size_t nGridWidth = m_pWangTiler->GetWidth();
128 const size_t nGridHeight = m_pWangTiler->GetHeight();
129
130 Gdiplus::Rect r;
131 r.Width = nTileWidth;
132 r.Height = nTileHeight;
133
134 Gdiplus::Graphics graphics(m_pBitmap);
135 graphics.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
136
137 for(size_t i=0; i<nGridHeight; i++){
138 for(size_t j=0; j<nGridWidth; j++){
139 const size_t index = (*m_pWangTiler)(i, j);
140 graphics.DrawImage(m_pTile[index], r);
141 r.X += nTileWidth; //next column
142 } //for
143
144 r.Y += nTileHeight; //next row
145 r.X = 0; //first column
146 } //for
147} //Draw
148
149#pragma endregion Drawing functions
150
152// Menu functions
153
154#pragma region Menu functions
155
158
160 HMENU hMenubar = CreateMenu();
161
162 CreateFileMenu(hMenubar);
164 CreateHelpMenu(hMenubar);
165
166 SetMenu(m_hWnd, hMenubar);
167} //CreateMenus
168
169#pragma endregion Menu functions
170
172// Other functions
173
181
182HRESULT CMain::LoadTileSet(const UINT idm, const UINT n){
183 UINT i = 0;
184 bool error = false;
185 std::wstring filename;
186 Gdiplus::Bitmap** temp = new Gdiplus::Bitmap*[n];
187
188 if(m_nNumTiles != n){
189 for(UINT i=0; i<m_nNumTiles; i++)
190 delete m_pTile[i];
191 delete [] m_pTile;
192
193 m_pTile = new Gdiplus::Bitmap*[n];
194 for(UINT i=0; i<n; i++)
195 m_pTile[i] = nullptr;
196
197 m_nNumTiles = n;
198 } //if
199
200 for(i=0; i<n && !error; i++){ //for each tile
201 filename = L"tiles\\"; //file name
202
203 switch(idm){
204 case IDM_TILESET_DEFAULT: filename += L"default"; break;
205 case IDM_TILESET_FLOWER: filename += L"flowers"; break;
206 case IDM_TILESET_MUD: filename += L"mud"; break;
207 case IDM_TILESET_GRASS: filename += L"grass"; break;
208 } //switch
209
210 filename += std::wstring(L"\\") + std::to_wstring(i) + L".png";
211
212 temp[i] = Gdiplus::Bitmap::FromFile(filename.c_str()); //load tile
213 error = temp[i]->GetLastStatus() != Gdiplus::Ok;
214 } //for
215
216 //error handling
217
218 if(error){ //fail
219 std::wstring s = L"Error loading file " + filename;
220 MessageBoxW(m_hWnd, s.c_str(), L"Error", MB_ICONERROR | MB_OK);
221
222 for(UINT j=0; j<i; j++)
223 delete temp[j];
224 } //if
225
226 else{ //success
227 for(UINT j=0; j<n; j++){ //copy tile pointers to m_pTile
228 delete m_pTile[j];
229 m_pTile[j] = temp[j];
230 } //for
231
232 //unset menu checkmarks then check the one we want
233 CheckMenuItem(m_hTilesetMenu, IDM_TILESET_DEFAULT, MF_UNCHECKED);
234 CheckMenuItem(m_hTilesetMenu, IDM_TILESET_FLOWER, MF_UNCHECKED);
235 CheckMenuItem(m_hTilesetMenu, IDM_TILESET_MUD, MF_UNCHECKED);
236 CheckMenuItem(m_hTilesetMenu, IDM_TILESET_GRASS, MF_UNCHECKED);
237
238 CheckMenuItem(m_hTilesetMenu, idm, MF_CHECKED);
239 } //else
240
241 delete [] temp;
242 return error? E_FAIL: S_OK;
243} //LoadTileSet
244
246
249} //Generate
250
254
255Gdiplus::Bitmap* CMain::GetBitmap(){
256 return m_pBitmap;
257} //GetBitmap
Interface for the main class CMain.
HMENU CreateTilesetMenu(HMENU hParent)
Create Tileset menu.
void CreateFileMenu(HMENU hParent)
Create File menu.
ULONG_PTR InitGDIPlus()
Initialize GDI+.
void CreateHelpMenu(HMENU hParent)
Create Help menu.
Interface for some helpful Windows-specific functions.
#define IDM_TILESET_FLOWER
Menu id for flower tileset.
#define IDM_TILESET_GRASS
Menu id for grass tileset.
#define IDM_TILESET_MUD
Menu id for dirt tileset.
#define IDM_TILESET_DEFAULT
Menu id for default tileset.
HRESULT LoadTileSet(const UINT idm, const UINT n)
Load tileset.
Definition: CMain.cpp:182
CWangTiler * m_pWangTiler
Pointer to the Wang tiler.
Definition: CMain.h:48
void CreateMenus()
Create menus.
Definition: CMain.cpp:159
UINT m_nNumTiles
Number of tiles in tileset.
Definition: CMain.h:50
Gdiplus::Bitmap ** m_pTile
The tile pointer array.
Definition: CMain.h:49
~CMain()
Destructor.
Definition: CMain.cpp:55
void Draw()
Draw the Wang tiling.
Definition: CMain.cpp:117
void Generate()
Generate a Wang tiling.
Definition: CMain.cpp:247
CMain(const HWND hwnd)
Constructor.
Definition: CMain.cpp:39
ULONG_PTR m_gdiplusToken
GDI+ token.
Definition: CMain.h:44
Gdiplus::Bitmap * GetBitmap()
Get pointer to bitmap.
Definition: CMain.cpp:255
HMENU m_hTilesetMenu
Handle to the Generate menu.
Definition: CMain.h:42
Gdiplus::Bitmap * m_pBitmap
Pointer to a bitmap image.
Definition: CMain.h:46
void OnPaint()
Paint the client area of the window.
Definition: CMain.cpp:77
HWND m_hWnd
Window handle.
Definition: CMain.h:41
Wang tiler.
Definition: WangTiler.h:37
void Generate()
Generate tiling.
Definition: WangTiler.cpp:72
const size_t GetHeight() const
Get height in tiles.
Definition: WangTiler.cpp:107
const size_t GetWidth() const
Get width in tiles.
Definition: WangTiler.cpp:100