📄 app_shell.cpp
字号:
void App_Shell::bitmap_mode_end() {
glEnable(GL_CULL_FACE);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
draw_mode = MODE_NONE;
}
void App_Shell::text_mode_begin(Font *font) {
if (font == NULL) return;
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, screen_width, 0, screen_height, 0, -100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDepthFunc(GL_ALWAYS);
glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, font->texture_handle);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/*
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST);
*/
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glEnable(GL_TEXTURE_2D);
GLfloat ambient[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
draw_mode = MODE_TEXT;
}
void App_Shell::text_mode_end() {
glEnable(GL_CULL_FACE);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
draw_mode = MODE_NONE;
}
bool App_Shell::init(int width, int height) {
loaded_textures = new List();
mouse_button_1_is_down = false;
mouse_button_2_is_down = false;
last_frame_time = 0;
screen_width = width;
screen_height = height;
show_mouse_pointer = true;
center_mouse_pointer = false;
mouse_pointer_x = 0;
mouse_pointer_y = 0;
mouse_pointer_delta_x = 0;
mouse_pointer_delta_y = 0;
draw_mode = MODE_NONE;
// Init time.
global_base_time = get_time_reading();
// Init other stuff.
bool success;
success = init_gl();
if (!success) return false;
init_textures();
init_modelview_transform();
return true;
}
void App_Shell::init_modelview_transform() {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
float pos_x = 0;
float pos_y = 0;
float pos_z = 5;
gluLookAt(pos_x, pos_y, pos_z, 0, 0, 0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90, (float)screen_width / (float)screen_height,
0.4f, 1000.0f);
}
///// OpenGL stuff here
const char *window_class_name = "AppShellWindowClass";
HWND get_hwnd(App_Shell *shell) {
return *(HWND *)&shell->hwnd;
}
bool App_Shell::init_gl() {
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = global_hinstance;
wc.hIcon = LoadIcon(NULL, "APPICON");
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = window_class_name;
// Register the window class
if (RegisterClass(&wc) == 0) return false;
extern char *app_name;
HWND app_hwnd;
app_hwnd = CreateWindow(window_class_name,
app_name,
WS_OVERLAPPEDWINDOW,
0, 0,
screen_width, screen_height,
NULL,
NULL,
global_hinstance,
NULL);
assert(global_dc != 0);
hwnd = (void *)app_hwnd;
// Display the window
ShowWindow(app_hwnd, SW_SHOW);
UpdateWindow(app_hwnd);
wglMakeCurrent(global_dc, global_gl_rc);
glViewport(0, 0, screen_width, screen_height);
return true;
}
double App_Shell::get_time() {
LARGE_INTEGER time = get_time_reading();
time.QuadPart = time.QuadPart - global_base_time.QuadPart;
return (double)time.QuadPart * 0.001;
}
void App_Shell::sleep(float seconds) {
Sleep(seconds * 1000);
}
void set_pixel_format(HDC dc) {
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // Size
1, // Version
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
24, // 24-bit color
0, 0, 0, 0, 0, 0, // A bunch of unused stuff.
0, 0,
0, 0, 0, 0, 0,
32, // Z-buffer depth
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0 };
int format = ChoosePixelFormat(dc, &pfd);
SetPixelFormat(dc, format, &pfd);
}
static int translate_ascii_code(WPARAM wParam) {
switch (wParam) {
// Hacky keybindings so that we don't have to define a bunch of
// OS-independent constants for these, like we would if we
// were writing a real game input system.
case VK_LEFT:
case VK_PRIOR:
return App_Shell::ARROW_LEFT;
case VK_RIGHT:
case VK_NEXT:
return App_Shell::ARROW_RIGHT;
case VK_UP:
return App_Shell::ARROW_UP;
case VK_DOWN:
return App_Shell::ARROW_DOWN;
case VK_DELETE:
return ')';
default:
return wParam;
}
}
LRESULT CALLBACK WindowProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam) {
switch (message) {
case WM_CREATE:
global_dc = GetDC(hWnd);
set_pixel_format(global_dc);
// Make a rendering context.
global_gl_rc = wglCreateContext(global_dc);
assert(global_gl_rc != NULL);
BOOL succ;
succ = wglMakeCurrent(global_dc, global_gl_rc);
assert(succ);
break;
case WM_DESTROY:
wglMakeCurrent(global_dc, NULL);
wglDeleteContext(global_gl_rc);
if (global_palette != NULL) DeleteObject(global_palette);
ReleaseDC(hWnd, global_dc);
PostQuitMessage(0);
break;
case WM_ACTIVATEAPP:
if (wParam) app_is_active = true;
else app_is_active = false;
break;
case WM_SIZE: {
int width, height;
width = LOWORD(lParam);
height = HIWORD(lParam);
wglMakeCurrent(global_dc, global_gl_rc);
glViewport(0, 0, width, height);
app_shell->screen_width = width;
app_shell->screen_height = height;
break;
}
case WM_KEYDOWN: {
extern void handle_keydown(int);
int ascii_code;
ascii_code = translate_ascii_code(wParam);
handle_keydown(ascii_code);
break;
}
case WM_KEYUP: {
extern void handle_keyup(int);
int ascii_code;
ascii_code = translate_ascii_code(wParam);
handle_keyup(ascii_code);
break;
}
case WM_PAINT:
ValidateRect(hWnd,NULL);
break;
case WM_QUERYNEWPALETTE:
if (global_palette) {
int nRet;
SelectPalette(global_dc, global_palette, FALSE);
nRet = RealizePalette(global_dc);
InvalidateRect(hWnd, NULL, FALSE);
return nRet;
}
break;
case WM_PALETTECHANGED:
if ((global_palette != NULL) && ((HWND)wParam != hWnd)) {
SelectPalette(global_dc, global_palette, FALSE);
RealizePalette(global_dc);
UpdateColors(global_dc);
return 0;
}
break;
case WM_LBUTTONDOWN:
app_shell->mouse_button_1_is_down = true;
break;
case WM_LBUTTONUP:
app_shell->mouse_button_1_is_down = false;
break;
case WM_RBUTTONDOWN:
app_shell->mouse_button_2_is_down = true;
break;
case WM_RBUTTONUP:
app_shell->mouse_button_2_is_down = false;
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
double App_Shell::get_dt() {
return dt;
}
void do_beginning_of_frame_stuff() {
// Compute dt...
double now = app_shell->get_time();
if (app_shell->last_frame_time == 0) {
app_shell->dt = 0.05f; // Arbitrary bootstrap value!
} else {
app_shell->dt = now - app_shell->last_frame_time;
}
app_shell->last_frame_time = now;
}
void do_end_of_frame_stuff() {
// Do mouse stuff...
// Constrain the mouse pointer to the screen and make it invisible
// Don't actually screw with the mouse if we don't have focus.
if (!app_is_active) return;
if (!app_shell->show_mouse_pointer) {
int count = ShowCursor(FALSE);
while (count < -1) {
ShowCursor(TRUE);
count++;
}
} else {
int count = ShowCursor(TRUE);
while (count > 1) {
ShowCursor(FALSE);
count--;
}
}
HWND hwnd = (HWND)app_shell->hwnd;
RECT rect;
GetClientRect(hwnd, &rect);
POINT point;
point.x = 0;
point.y = 0;
ClientToScreen(hwnd, &point);
rect.left += point.x;
rect.right += point.x;
rect.top += point.y;
rect.bottom += point.y;
ClipCursor(&rect);
if (app_shell->center_mouse_pointer) {
// Put the pointer in the middle of the screen
int cx = (rect.left + rect.right) / 2;
int cy = (rect.bottom + rect.top) / 2;
POINT old_point;
GetCursorPos(&old_point);
SetCursorPos(cx, cy);
app_shell->mouse_pointer_delta_x = old_point.x - cx;
app_shell->mouse_pointer_delta_y = cy - old_point.y;
}
}
void draw_one_frame() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
extern void draw_scene();
draw_scene();
SwapBuffers(global_dc);
}
int PASCAL WinMain(HINSTANCE hinst, HINSTANCE,
LPSTR command_line, int ShowMode) {
global_hinstance = hinst;
// get the user's specified display parameters, or defaults
// the shortened names work because of the default value
app_shell = new App_Shell();
bool success = app_shell->init(DEFAULT_WIDTH, DEFAULT_HEIGHT);
assert(success);
extern void app_init(int argc, char **argv);
if (command_line[0] != '\0') {
app_init(1, &command_line);
} else {
app_init(0, &command_line);
}
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
double last_time = 0;
MSG msg;
while (1) {
HWND hwnd = get_hwnd(app_shell);
assert(hwnd);
// Do time stuff.
// Do mouse pointer stuff.
POINT point;
BOOL success = GetCursorPos(&point);
assert(success);
if (success) {
RECT client_rect;
GetClientRect(hwnd, &client_rect);
POINT upper_left;
upper_left.x = 0;
upper_left.y = 0;
POINT lower_right;
lower_right.x = client_rect.right;
lower_right.y = client_rect.bottom;
ClientToScreen(hwnd, &upper_left);
ClientToScreen(hwnd, &lower_right);
int cursor_x = point.x - upper_left.x;
int cursor_y = lower_right.y - point.y;
app_shell->mouse_pointer_x = cursor_x;
app_shell->mouse_pointer_y = cursor_y;
}
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
do_beginning_of_frame_stuff();
if (app_is_active) {
draw_one_frame();
} else {
WaitMessage();
}
do_end_of_frame_stuff();
}
}
return msg.wParam;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -