Last active
December 18, 2015 03:29
-
-
Save gszauer/5718473 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "BackBuffer.h" | |
#pragma comment (lib,"Gdiplus.lib") | |
using namespace Gdiplus; | |
GDIBackBuffer* g_pBackBuffer = 0; | |
void InitGDIBitmap(GDIBitmap& b) { | |
b.path.clear(); | |
b.refCount = 0; | |
b.width = 0; | |
b.height = 0; | |
b.bitmap = 0; | |
b.brush = 0; | |
} | |
GDIBackBuffer::GDIBackBuffer() { | |
m_nScreenWidth = 0; | |
m_nScreenHeight = 0; | |
m_nWidthReciprical = 0.0f; | |
m_nHeightReciprical = 0.0f; | |
m_hWnd = (HWND)0; | |
m_hInstance = (HINSTANCE)0; | |
m_hDc = (HDC)0; | |
m_hBitmap = (HBITMAP)0; | |
m_hOldBitmap = (HBITMAP)0; | |
} | |
GDIBackBuffer::~GDIBackBuffer() { } | |
GDIBackBuffer* GDIBackBuffer::GetInstance() { | |
static GDIBackBuffer staticBuffer; | |
return &staticBuffer; | |
} | |
void GDIBackBuffer::Initialize(HWND hWnd, HINSTANCE hInstance, HDC hDc) { | |
m_hWnd = hWnd; | |
m_hInstance = hInstance; | |
m_hWndDc = hDc; | |
g_pBackBuffer = GDIBackBuffer::GetInstance(); | |
RECT clientRect; | |
GetClientRect(hWnd, &clientRect); | |
m_nScreenWidth = clientRect.right - clientRect.left; | |
m_nScreenHeight = clientRect.bottom - clientRect.top; | |
m_nWidthReciprical = 1.0f / float(m_nScreenWidth); | |
m_nHeightReciprical = 1.0f / float(m_nScreenHeight); | |
m_hDc = CreateCompatibleDC(NULL); | |
m_hBitmap = CreateCompatibleBitmap(m_hWndDc, m_nScreenWidth, m_nScreenHeight); | |
m_hOldBitmap = (HBITMAP)SelectObject(m_hDc, m_hBitmap); | |
m_vLoadedBitmaps.clear(); | |
GdiplusStartup(&m_gdiToken, &m_gdiStartupInput, NULL); | |
m_gdiGraphics = new Graphics(m_hDc); | |
m_gdiSolidBrush = new SolidBrush(Color::Black); | |
m_gdiPen = new Pen(Color::Black); | |
m_gdiFont = new Font(Gdiplus::FontFamily::GenericSansSerif(), 12); | |
} | |
void GDIBackBuffer::Shutdown() { | |
for (int i = int(m_vLoadedBitmaps.size()) - 1; i >= 0; --i) | |
UnloadImage(i); | |
m_vLoadedBitmaps.clear(); | |
delete m_gdiFont; | |
delete m_gdiPen; | |
delete m_gdiSolidBrush; | |
delete m_gdiGraphics; | |
GdiplusShutdown(m_gdiToken); | |
SelectObject(m_hDc, m_hOldBitmap); | |
DeleteObject(m_hBitmap); | |
DeleteDC(m_hDc); | |
} | |
int GDIBackBuffer::LoadImage(std::string path) { | |
unsigned int size = m_vLoadedBitmaps.size(); | |
int itemIndex = -1; | |
for (unsigned int i = 0; i < size; ++i) { | |
if (m_vLoadedBitmaps[i].path == path) { | |
m_vLoadedBitmaps[i].refCount += 1; | |
return i; | |
} | |
if (m_vLoadedBitmaps[i].refCount == 0) { | |
if (itemIndex == -1) { | |
itemIndex = i; | |
} | |
} | |
} | |
if (itemIndex == -1) { | |
GDIBitmap newBitmap; | |
InitGDIBitmap(newBitmap); | |
m_vLoadedBitmaps.push_back(newBitmap); | |
itemIndex = int(size); | |
} | |
m_vLoadedBitmaps[itemIndex].path = path; | |
m_vLoadedBitmaps[itemIndex].refCount = 1; | |
std::wstring unicodeFilename(path.length(), L' '); | |
std::copy(path.begin(), path.end(), unicodeFilename.begin()); | |
m_vLoadedBitmaps[itemIndex].bitmap = Bitmap::FromFile(unicodeFilename.c_str(), false); | |
//m_vLoadedBitmaps[itemIndex].bitmap.RotateFlip(Gdiplus::RotateNoneFlipY); | |
m_vLoadedBitmaps[itemIndex].width = int(m_vLoadedBitmaps[itemIndex].bitmap->GetWidth()); | |
m_vLoadedBitmaps[itemIndex].height = int(m_vLoadedBitmaps[itemIndex].bitmap->GetHeight()); | |
m_vLoadedBitmaps[itemIndex].brush = new TextureBrush(m_vLoadedBitmaps[itemIndex].bitmap); | |
return itemIndex; | |
} | |
void GDIBackBuffer::UnloadImage(int imageId) { | |
m_vLoadedBitmaps[imageId].refCount -= 1; | |
if (m_vLoadedBitmaps[imageId].refCount > 0) | |
return; | |
m_vLoadedBitmaps[imageId].refCount = 0; | |
m_vLoadedBitmaps[imageId].path.clear(); | |
m_vLoadedBitmaps[imageId].width = 0; | |
m_vLoadedBitmaps[imageId].height = 0; | |
delete m_vLoadedBitmaps[imageId].brush; | |
m_vLoadedBitmaps[imageId].brush = 0; | |
delete m_vLoadedBitmaps[imageId].bitmap; | |
m_vLoadedBitmaps[imageId].bitmap = 0; | |
} | |
void GDIBackBuffer::BlitImage(int imageId, int x_dest, int y_dest, int width, int height, int x_source, int y_source, int source_w, int source_h) { | |
if (width == -1 && height == -1) { | |
width = m_vLoadedBitmaps[imageId].width; | |
height = m_vLoadedBitmaps[imageId].height; | |
} | |
if (source_w == -1 && source_h == -1) { | |
source_w = width; | |
source_h = height; | |
} | |
Point dest[2]; | |
dest[0].X = x_dest; | |
dest[0].Y = y_dest; | |
dest[1].X = x_dest + width; | |
dest[1].Y = y_dest + width; | |
m_gdiGraphics->DrawImage(m_vLoadedBitmaps[imageId].bitmap, dest, 2, x_source, y_source, source_w, source_h, UnitPixel, NULL, NULL, NULL); | |
} | |
void GDIBackBuffer::PutPixel(int x, int y, COLORREF color) { | |
m_gdiSolidBrush->SetColor(Color(GetRValue(color), GetGValue(color), GetBValue(color))); | |
m_gdiGraphics->FillRectangle(m_gdiSolidBrush, x, y, 1, 1); | |
} | |
void GDIBackBuffer::PutPixel(int x, int y, int r, int g, int b) { | |
PutPixel(x, y, RGB(BYTE(r), BYTE(g), BYTE(b))); | |
} | |
void GDIBackBuffer::DrawLine(int x1, int y1, int x2, int y2, int r, int g, int b) { | |
DrawLine(x1, y1, x2, y2, RGB(BYTE(r), BYTE(g), BYTE(b))); | |
} | |
void GDIBackBuffer::DrawLine(int x1, int y1, int x2, int y2, COLORREF color) { | |
m_gdiPen->SetColor(Color(GetRValue(color), GetGValue(color), GetBValue(color))); | |
m_gdiGraphics->DrawLine(m_gdiPen, x1, y1, x2, y2); | |
} | |
void GDIBackBuffer::DrawTriangle(int* points, int r, int g, int b) { | |
DrawTriangle(points, RGB(BYTE(r), BYTE(g), BYTE(b))); | |
} | |
void GDIBackBuffer::DrawTriangle(int* points, COLORREF color) { | |
m_gdiPen->SetColor(Color(GetRValue(color), GetGValue(color), GetBValue(color))); | |
Point triangle[3]; | |
triangle[0].X = points[0]; | |
triangle[0].Y = points[1]; | |
triangle[1].X = points[2]; | |
triangle[1].Y = points[3]; | |
triangle[2].X = points[4]; | |
triangle[2].Y = points[5]; | |
m_gdiGraphics->DrawPolygon(m_gdiPen, triangle, 3); | |
} | |
void GDIBackBuffer::FillTriangle(int* points, int r, int g, int b) { | |
m_gdiSolidBrush->SetColor(Color(BYTE(r), BYTE(g), BYTE(b))); | |
Point triangle[3]; | |
triangle[0].X = points[0]; | |
triangle[0].Y = points[1]; | |
triangle[1].X = points[2]; | |
triangle[1].Y = points[3]; | |
triangle[2].X = points[4]; | |
triangle[2].Y = points[5]; | |
m_gdiGraphics->FillPolygon(m_gdiSolidBrush, triangle, 3); | |
} | |
void GDIBackBuffer::FillTriangle(int* points, int imageId) { | |
Point triangle[3]; | |
triangle[0].X = points[0]; | |
triangle[0].Y = points[1]; | |
triangle[1].X = points[2]; | |
triangle[1].Y = points[3]; | |
triangle[2].X = points[4]; | |
triangle[2].Y = points[5]; | |
m_gdiGraphics->FillPolygon(m_vLoadedBitmaps[imageId].brush, triangle, 3); | |
} | |
void GDIBackBuffer::DrawSquare(int x, int y, int w, int h, int r, int g, int b) { | |
DrawSquare(x, y, w, h, RGB(BYTE(r), BYTE(g), BYTE(b))); | |
} | |
void GDIBackBuffer::DrawSquare(int x, int y, int w, int h, COLORREF color) { | |
m_gdiPen->SetColor(Color(GetRValue(color), GetGValue(color), GetBValue(color))); | |
m_gdiGraphics->DrawRectangle(m_gdiPen, x, y, w, h); | |
} | |
void GDIBackBuffer::FillSquare(int x, int y, int w, int h, int r, int g, int b) { | |
m_gdiSolidBrush->SetColor(Color(BYTE(r), BYTE(g), BYTE(b))); | |
m_gdiGraphics->FillRectangle(m_gdiSolidBrush, x, y, w, h); | |
} | |
void GDIBackBuffer::FillSquare(int x, int y, int w, int h, int imageId) { | |
m_gdiGraphics->FillRectangle(m_vLoadedBitmaps[imageId].brush, x, y, w, h); | |
} | |
void GDIBackBuffer::DrawSphere(int x, int y, int rad, int r, int g, int b) { | |
DrawSphere(x, y, rad, RGB(BYTE(r), BYTE(g), BYTE(b))); | |
} | |
void GDIBackBuffer::DrawSphere(int x, int y, int rad, COLORREF color) { | |
m_gdiPen->SetColor(Color(GetRValue(color), GetGValue(color), GetBValue(color))); | |
m_gdiGraphics->DrawEllipse(m_gdiPen, x - (rad / 2), y - (rad / 2), rad, rad); | |
} | |
void GDIBackBuffer::FillSphere(int x, int y, int rad, int r, int g, int b) { | |
m_gdiSolidBrush->SetColor(Color(BYTE(r), BYTE(g), BYTE(b))); | |
m_gdiGraphics->FillEllipse(m_gdiSolidBrush, x - (rad / 2), y - (rad / 2), rad, rad); | |
} | |
void GDIBackBuffer::FillSphere(int x, int y, int rad, int imageId) { | |
m_gdiGraphics->FillEllipse(m_vLoadedBitmaps[imageId].brush, x - (rad / 2), y - (rad / 2), rad, rad); | |
} | |
void GDIBackBuffer::Text(int x, int y, int r, int g, int b, std::string text) { | |
std::wstring wideString(text.length(), L' '); | |
std::copy(text.begin(), text.end(), wideString.begin()); | |
m_gdiSolidBrush->SetColor(Color(BYTE(r), BYTE(g), BYTE(b))); | |
m_gdiGraphics->DrawString(wideString.c_str(), wideString.size(), m_gdiFont, PointF(x, y), m_gdiSolidBrush); | |
} | |
void GDIBackBuffer::Text(int x, int y, COLORREF color, std::string text) { | |
std::wstring wideString(text.length(), L' '); | |
std::copy(text.begin(), text.end(), wideString.begin()); | |
m_gdiSolidBrush->SetColor(Color(GetRValue(color), GetGValue(color), GetBValue(color))); | |
m_gdiGraphics->DrawString(wideString.c_str(), wideString.size(), m_gdiFont, PointF(x, y), m_gdiSolidBrush); | |
} | |
void GDIBackBuffer::Clear() { | |
m_gdiSolidBrush->SetColor(Color::White); | |
m_gdiGraphics->FillRectangle(m_gdiSolidBrush, 0, 0, m_nScreenWidth, m_nScreenHeight); | |
} | |
void GDIBackBuffer::Clear(int r, int g, int b) { | |
m_gdiSolidBrush->SetColor(Color(BYTE(r), BYTE(g), BYTE(b))); | |
m_gdiGraphics->FillRectangle(m_gdiSolidBrush, 0, 0, m_nScreenWidth, m_nScreenHeight); | |
} | |
void GDIBackBuffer::Clear(COLORREF color) { | |
m_gdiSolidBrush->SetColor(Color(GetRValue(color), GetGValue(color), GetBValue(color))); | |
m_gdiGraphics->FillRectangle(m_gdiSolidBrush, 0, 0, m_nScreenWidth, m_nScreenHeight); | |
} | |
void GDIBackBuffer::Present() { | |
BitBlt(m_hWndDc, 0, 0, m_nScreenWidth, m_nScreenHeight, m_hDc, 0, 0, SRCCOPY); | |
/*POINT dest[3]; | |
dest[0].x = 0; | |
dest[0].y = m_nScreenHeight; | |
dest[1].x = m_nScreenWidth; | |
dest[1].y = m_nScreenHeight; | |
dest[2].x = 0; | |
dest[2].y = 0; | |
PlgBlt(m_hWndDc, dest, m_hDc, 0, 0, m_nScreenWidth, m_nScreenHeight, 0, 0, 0);*/ | |
} | |
void GDIBackBuffer::Resize(int width, int height) { | |
RECT clientRect; | |
GetClientRect(m_hWnd, &clientRect); | |
m_nScreenWidth = clientRect.right - clientRect.left; | |
m_nScreenHeight = clientRect.bottom - clientRect.top; | |
m_nWidthReciprical = 1.0f / float(m_nScreenWidth); | |
m_nHeightReciprical = 1.0f / float(m_nScreenHeight); | |
SelectObject(m_hDc, m_hOldBitmap); | |
DeleteObject(m_hBitmap); | |
DeleteDC(m_hDc); | |
m_hDc = CreateCompatibleDC(NULL); | |
m_hBitmap = CreateCompatibleBitmap(m_hWndDc, m_nScreenWidth, m_nScreenHeight); | |
m_hOldBitmap = (HBITMAP)SelectObject(m_hDc, m_hBitmap); | |
delete m_gdiGraphics; | |
m_gdiGraphics = new Graphics(m_hDc); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _H_BACKBUFFER_ | |
#define _H_BACKBUFFER_ | |
#include <windows.h> | |
#include <string> | |
#include <vector> | |
#include <gdiplus.h> | |
typedef struct t_bitmap { | |
std::string path; | |
int refCount; | |
int width; | |
int height; | |
//HDC hdc; | |
//HBITMAP bitmap; | |
//HBITMAP oldBitmap; | |
Gdiplus::Bitmap* bitmap; | |
Gdiplus::TextureBrush* brush; | |
} GDIBitmap; | |
void InitGDIBitmap(GDIBitmap& b); | |
class GDIBackBuffer { | |
protected: | |
int m_nScreenWidth; | |
int m_nScreenHeight; | |
float m_nWidthReciprical; | |
float m_nHeightReciprical; | |
HWND m_hWnd; | |
HDC m_hWndDc; | |
HINSTANCE m_hInstance; | |
HDC m_hDc; | |
HBITMAP m_hBitmap; | |
HBITMAP m_hOldBitmap; | |
std::vector<GDIBitmap> m_vLoadedBitmaps; | |
Gdiplus::Graphics* m_gdiGraphics; | |
Gdiplus::GdiplusStartupInput m_gdiStartupInput; | |
ULONG_PTR m_gdiToken; | |
Gdiplus::SolidBrush* m_gdiSolidBrush; | |
Gdiplus::Pen* m_gdiPen; | |
Gdiplus::Font* m_gdiFont; | |
protected: | |
GDIBackBuffer(); | |
GDIBackBuffer(const GDIBackBuffer&); | |
GDIBackBuffer& operator=(const GDIBackBuffer&); | |
public: | |
static GDIBackBuffer* GetInstance(); | |
~GDIBackBuffer(); | |
void Initialize(HWND hWnd, HINSTANCE hInstance, HDC hDc); | |
void Shutdown(); | |
int LoadImage(std::string path); | |
void UnloadImage(int imageId); | |
void BlitImage(int imageId, int x_dest, int y_dest, int width = -1, int height = -1, | |
int x_source = 0, int y_source = 0, int source_w = -1, int source_h = -1); | |
void PutPixel(int x, int y, int r, int g, int b); | |
void PutPixel(int x, int y, COLORREF color); | |
void DrawLine(int x1, int y1, int x2, int y2, int r, int g, int b); | |
void DrawLine(int x1, int y1, int x2, int y2, COLORREF color); | |
void DrawTriangle(int* points, int r, int g, int b); | |
void DrawTriangle(int* points, COLORREF color); | |
void FillTriangle(int* points, int r, int g, int b); | |
void FillTriangle(int* points, int imageId); | |
void DrawSquare(int x, int y, int w, int h, int r, int g, int b); | |
void DrawSquare(int x, int y, int w, int h, COLORREF color); | |
void FillSquare(int x, int y, int w, int h, int r, int g, int b); | |
void FillSquare(int x, int y, int w, int h, int imageId); | |
void DrawSphere(int x, int y, int rad, int r, int g, int b); | |
void DrawSphere(int x, int y, int rad, COLORREF color); | |
void FillSphere(int x, int y, int rad, int r, int g, int b); | |
void FillSphere(int x, int y, int rad, int imageId); | |
void Text(int x, int y, int r, int g, int b, std::string text); | |
void Text(int x, int y, COLORREF color, std::string text); | |
void Clear(); | |
void Clear(int r, int g, int b); | |
void Clear(COLORREF color); | |
void Present(); | |
void Resize(int width, int height); | |
}; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <stdlib.h> | |
#include "BackBuffer.h" | |
#include "BackBufferLua.h" | |
// Include win main | |
#define WINDOW_WIDTH 800 | |
#define WINDOW_HEIGHT 600 | |
#define TARGET_FPS 60 | |
#define WND_CLASSNAME "WIN32IMGUI" | |
#define WND_TITLE "Win32 IMGUI: Base" | |
HWND g_hWnd; | |
HINSTANCE g_hInstance; | |
GDIBackBuffer* g_pGdiBackBuffer; | |
//////////////////////////////////////////////////////////////////// | |
// Hook | |
void Initialize() { } | |
void Update() { | |
g_pGdiBackBuffer->Clear(RGB(0, 255, 0)); | |
g_pGdiBackBuffer->Text(20, 20, RGB(255, 0, 0), "Hello World"); | |
g_pGdiBackBuffer->Present(); | |
} | |
void Shutdown() { } | |
void Resize(int width, int height) { | |
//g_pGdiBackBuffer->Resize(width, height); | |
} | |
//////////////////////////////////////////////////////////////////// | |
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); | |
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { | |
const int SKIP_TICKS = 1000 / TARGET_FPS; | |
DWORD next_game_tick = GetTickCount(); | |
int sleep_time = 0; | |
MSG msg; HDC hdc; | |
g_hInstance = hInstance; | |
WNDCLASSEX wndclass; | |
wndclass.cbSize = sizeof(WNDCLASSEX); | |
wndclass.style = CS_HREDRAW | CS_VREDRAW; | |
wndclass.lpfnWndProc = WndProc; | |
wndclass.cbClsExtra = 0; | |
wndclass.cbWndExtra = 0; | |
wndclass.hInstance = hInstance; | |
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); | |
wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); | |
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); | |
wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); | |
wndclass.lpszMenuName = 0; | |
wndclass.lpszClassName = WND_CLASSNAME; | |
RegisterClassEx(&wndclass); | |
RECT windowRect; | |
SetRect(&windowRect, (GetSystemMetrics(SM_CXSCREEN) / 2) - (WINDOW_WIDTH / 2), (GetSystemMetrics(SM_CYSCREEN) / 2) - (WINDOW_HEIGHT / 2), (GetSystemMetrics(SM_CXSCREEN) / 2) + (WINDOW_WIDTH / 2), (GetSystemMetrics(SM_CYSCREEN) / 2) + (WINDOW_HEIGHT / 2)); | |
AdjustWindowRectEx(&windowRect, WS_VISIBLE | WS_OVERLAPPEDWINDOW, FALSE, 0); | |
g_hWnd = CreateWindowEx(0, WND_CLASSNAME, WND_TITLE, WS_VISIBLE | WS_OVERLAPPEDWINDOW, windowRect.left, windowRect.top, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, NULL, NULL, hInstance, szCmdLine); | |
hdc = GetDC(g_hWnd); | |
g_pGdiBackBuffer = GDIBackBuffer::GetInstance(); | |
ExposeToLua::GDIBBLuaPointer = g_pGdiBackBuffer; | |
g_pGdiBackBuffer->Initialize(g_hWnd, g_hInstance, hdc); | |
Initialize(); | |
ShowWindow(g_hWnd, SW_SHOW); | |
UpdateWindow(g_hWnd); | |
while (true) { | |
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { | |
if (msg.message == WM_QUIT) | |
break; | |
TranslateMessage(&msg); | |
DispatchMessage(&msg); | |
} | |
next_game_tick += SKIP_TICKS; | |
sleep_time = next_game_tick - GetTickCount(); | |
if(sleep_time >= 0) | |
Sleep(sleep_time); | |
Update(); | |
} | |
Shutdown(); | |
g_pGdiBackBuffer->Shutdown(); | |
ReleaseDC(g_hWnd, hdc); | |
return (int)msg.wParam; | |
} | |
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { | |
RECT window = { 0 }; | |
switch (iMsg) { | |
case WM_CLOSE: | |
DestroyWindow(hwnd); | |
break; | |
case WM_DESTROY: | |
PostQuitMessage(0); | |
break; | |
case WM_SIZE: | |
GetClientRect(hwnd, &window); | |
Resize(int(window.right - window.left), int(window.bottom - window.top)); | |
break; | |
case WM_PAINT: | |
case WM_ERASEBKGND: | |
return 0; | |
} | |
return DefWindowProc(hwnd, iMsg, wParam, lParam); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment