.. _program_listing_file_blam_main.cpp: Program Listing for File main.cpp ================================= |exhale_lsh| :ref:`Return to documentation for file ` (``blam\main.cpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // Blamite Engine - Entry point for Blamite engine // // (c) Elaztek Studios 2016-2018 // #include "core.h" // External includes #include #include // Internal includes #include "components/content/fonts/fonts.h" #include "components/core/blam_ui/blam_ui.h" #include "components/core/cache/cache.h" #include "components/core/config/config.h" #include "components/core/debug_ui/debug_colors.h" #include "components/core/debug_ui/debug_ui.h" #include "components/core/dialogs/dialogs.h" #include "components/core/engine_definitions/engine_definitions.h" #include "components/core/error/error.h" #include "components/core/logger/logger.h" #include "components/core/placeholders/placeholders.h" #include "components/core/utils/converters/converters.h" #include "components/core/utils/io/io.h" #include "components/core/utils/res/res.h" #include "components/core/utils/utilities.h" #include "components/discord/m_discord.h" #include "components/haloscript/haloscript.h" #include "components/input/keyboard.h" #include "components/networking/messages.h" #include "components/networking/socket.h" #include "components/rendering/directx11/render_stack/render_stack.h" #include "components/rendering/directx11/render_stack/stack_types/blam_ui/console.hpp" #include "components/rendering/directx11/render_stack/stack_types/blam_ui/debug_menu.hpp" #include "components/rendering/directx11/render_stack/stack_types/blam_ui/fpscounter.hpp" #include "components/rendering/rendering.h" #include "version_data.h" #include "components/3rdparty/imgui/formats/imgui_impl_win32.h" #include "components/3rdparty/imgui/formats/dx11/imgui_impl_dx11.h" //extern "C" int __cdecl myPuts(const char* message); // ImGUI data BlamRendering::RenderStack::ImGUIObject* imgui; bool imgui_initialized = false; // Blam UI data BlamRendering::RenderStack::ConsoleUI* console; // Window data WNDCLASSEX wc; HWND hwndGoto = NULL; HWND main_hwnd = NULL; HINSTANCE hInst; HCURSOR cursor; const wchar_t* window_name; // Socket data UINT8* socketBuffer; Blam::Network::Socket sock; Blam::LinearAllocator allocator; UINT32 bytesReceived; Blam::Endpoint from; extern bool isConnected; // Threading data std::thread render_thread; bool use_separate_render_thread = false; // Forward declarations INT_PTR CALLBACK FirstbootDialog(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); void cleanup_resources(LPCWSTR ver_conv, WNDCLASSEX wc); extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT WINAPI MainWindowProcedure(HWND window_handle, UINT message, WPARAM wParam, LPARAM lParam) { //handle imgui input if (ImGui_ImplWin32_WndProcHandler(window_handle, message, wParam, lParam)) { return true; } //if imgui doesnt handle input, then its our job to do so switch (message) { case WM_QUIT: { cleanup_resources(window_name, wc); return 0; } case WM_SIZE: { //resize Direct3D render target upon window resize if (BlamRendering::DirectX::GetD3DDevice() != NULL && wParam != SIZE_MINIMIZED) { BlamRendering::DirectX::HandleWindowResize(lParam); } return 0; } case WM_KEYDOWN: { return Blam::Input::HandleKeyPress(wParam); } case WM_CHAR: { return Blam::Input::HandleCharacterInput(wParam); } case WM_KEYUP: { //key released return 0; } case WM_SYSCOMMAND: { // Disable ALT application menu if ((wParam & 0xfff0) == SC_KEYMENU) { return 0; } break; } case WM_COMMAND: { switch (LOWORD(wParam)) { case ID_HELP_CREDITS: { if (!IsWindow(hwndGoto)) { hwndGoto = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PROPPAGE_MEDIUM), window_handle, NULL); ShowWindow(hwndGoto, SW_SHOW); } break; } case ID_HELP_ABOUT: { Blam::Dialogs::AboutDialogProcedure(hInst, window_handle); break; } case ID_TEST_SHOW_FIRSTBOOT: { Blam::Dialogs::FirstbootDialogProcedure(hInst, window_handle); break; } case ID_TEST_ERROR: { Blam::Dialogs::ErrorDialogProcedure(hInst, window_handle, "This is a test error."); break; } case ID_TEST_FONTTEST: { Blam::Dialogs::FontTestDialogProcedure(hInst, window_handle); break; } case ID_TEST_IDD: { Blam::Dialogs::ErrorDialogProcedure(hInst, window_handle, "this shit was literally fucking garbage (tell halo to replace with IDD_PROPPAGE_MEDIUM thing just to finally put it in it's place)"); break; } case ID_TEST_RESTOREIMGUI: { if (!BlamRendering::RenderStack::ContainsImGUIObject()) { BlamRendering::RenderStack::ImGUIObject* imgui_obj = new BlamRendering::RenderStack::ImGUIObject(); BlamRendering::RenderStack::AddToStack("imgui", imgui_obj); } else { Blam::DebugUI::ShowErrorDialog("imgui already present", "imgui is already present in the render stack"); } break; } case ID_FILE_EXIT: { DestroyWindow(window_handle); break; } default: { return DefWindowProc(window_handle, message, wParam, lParam); } } return 0L; } case WM_DESTROY: { PostQuitMessage(0); return 0; } } return DefWindowProc(window_handle, message, wParam, lParam); } int main(int args_count, char *args[]) { //assign hInstance hInst = GetModuleHandle(NULL); //int e = myPuts("are we connected"); Blam::Config::LoadConfig(); //load console color configuration { if (Blam::Config::GetConfig()->GetString("console_color_set") == "classic") { Blam::Utils::IO::CreateFileFromResource(CONFIG_COLOR_NAME, IDR_CON_COL_BUNGIE, "CFG", false); } else if (Blam::Config::GetConfig()->GetString("console_color_set") == "new") { Blam::Utils::IO::CreateFileFromResource(CONFIG_COLOR_NAME, IDR_CON_COL_NEW, "CFG", false); } else { if (!Blam::Utils::IO::file_exists(CONFIG_COLOR_NAME)) { Blam::Utils::IO::CreateFileFromResource(CONFIG_COLOR_NAME, IDR_CON_COL_NEW, "CFG", false); } } Blam::Config::LoadConfig(CONFIG_COLOR_NAME); } // Start logger { //Load configuration placeholders Blam::Placeholders::LoadPlaceholders(); //Initialize logger InternalUI::Colors::RegisterDefaultColors(); Blam::Logger::PrepareLogger(); Blam::Logger::PrintStartupHeader(); Blam::Logger::Queue::Flush(); Blam::LogEvent("Engine root set to '" + Blam::Config::GetConfig()->GetString("game_data_root") + "'"); Blam::LogEvent("User data root set to '" + Blam::Config::GetConfig()->GetString("user_data_root") + "'"); Blam::Logger::LogEvent("color log test", true, WSV_NONE, 255, 76, 255); } // Create gvars.xml then load it { Blam::Utils::IO::CreateFileFromResource(Blam::Config::GetConfig()->GetString("game_data_root") + GVARS_FILE, IDR_GVARS_XML, "XML", false); BlamScript::Globals::LoadGlobalsFromFile(); } // Initialize debug menu { std::string debug_menu_path = Blam::Config::GetConfig()->GetString("game_data_root") + "" + "./" + DEBUG_MENU_FILE + ".xml"; if (!Blam::Utils::IO::file_exists(debug_menu_path)) { if (Blam::Config::GetConfig()->GetBoolean("autoGenerateNewDebugMenuFile")) { Blam::Utils::IO::CreateFileFromResource(debug_menu_path, IDR_DEBUG_MENU_INIT_XML, "XML", false); } else { Blam::Logger::LogEvent("### WARNING unable to find debug_menu_init.xml, and automatic generation is disabled in config! this may result in the debug menu not being functional.", WSV_WARNING); } } Blam::DebugMenu::InitializeDebugMenu(); } // Check whether to show firstboot dialog if (Blam::Config::GetConfig()->GetBoolean("show_firstboot") == true) { //show firstboot dialog } // Create application window { std::wstring version = Blam::Converters::ConvertStringToWstring(Blam::EngineDefs::GetVersion()); window_name = version.c_str(); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_CLASSDC; wc.lpfnWndProc = MainWindowProcedure; wc.cbClsExtra = 0L; wc.cbWndExtra = 0L; wc.hInstance = hInst; wc.hIcon = NULL; wc.hCursor = NULL; wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = window_name; wc.hIconSm = NULL; //check whether or not to enable windows menubar if (Blam::Config::GetConfig()->GetBoolean("show_windows_menubar") == true) { wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); } //check whether or not to use a custom cursor if (Blam::Config::GetConfig()->GetBoolean("use_custom_cursor")) { cursor = LoadCursor(hInst, MAKEINTRESOURCE(IDC_POINTER)); if (cursor) { wc.hCursor = cursor; SetCursor(cursor); } else { Blam::LogEvent("### WARNING failed to load cursor resource"); BL_LOGEVT_RGB("", true, WSV_WARNING, 255, 255, 0); Blam::Error::ShowLastErrorInfo("LoadCursorW", Blam::Error::ErrorDisplayType::Log); } } RegisterClassEx(&wc); main_hwnd = CreateWindow(window_name, window_name, WS_OVERLAPPEDWINDOW, 0, 0, 1920, 1040, NULL, NULL, wc.hInstance, NULL); if (Blam::Config::GetConfig()->GetBoolean("use_themed_windows") == false) { SetWindowTheme(main_hwnd, L" ", L" "); } } //initialize netcode if enabled if (Blam::Config::GetConfig()->GetBoolean("use_netcode") == true) { Blam::linearAllocCreate(&allocator, 16 * 1024 * 1024); Blam::LogEvent("### WARNING netcode is experimental!"); if (Blam::Network::Init()) { Blam::Network::Start(&sock, &allocator); Blam::LogEvent("Blam::Network - Initialized!"); socketBuffer = Blam::linearAlloc(&allocator, 2048); Blam::Endpoint endpoint = {}; endpoint.address = (127 << 24) | (0 << 16) | (0 << 8) | 1; endpoint.port = 6536; UINT32 ClientHelloSize = Blam::Network::ClientHelloMessage(socketBuffer); if (Blam::Network::Send(&sock, socketBuffer, ClientHelloSize, &endpoint)) { Blam::LogEvent("Successfully sent message!"); isConnected = true; } } } // Initialize DirectX { HRESULT hr = BlamRendering::DirectX::Initialize(main_hwnd); if (FAILED(hr)) { Blam::Logger::LogEvent("### ERROR failed to initialize DirectX! details: '" + std::string(Blam::Error::GetStringFromHResult(hr)) + "'", WSV_CRITICAL); cleanup_resources(window_name, wc); return -45; } } //Show application window ShowWindow(main_hwnd, SW_MAXIMIZE); UpdateWindow(main_hwnd); //Setup ImGUI { IMGUI_CHECKVERSION(); // Setup ImGui binding ImGui::CreateContext(); Blam::LogEvent("Getting I/O for ImGUI"); // Load Fonts // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) ImGuiIO& io = ImGui::GetIO(); //(void)io; ImGui_ImplWin32_Init(main_hwnd); imgui_initialized = ImGui_ImplDX11_Init(BlamRendering::DirectX::GetD3DDevice(), BlamRendering::DirectX::GetD3DContext()); if (Blam::Config::GetConfig()->GetBoolean("enable_imgui_gamepad_nav")) { Blam::LogEvent("imgui gamepad navigation enabled"); io.ConfigFlags += ImGuiConfigFlags_NavEnableGamepad; } //load font for imgui { float font_size = Blam::Config::GetConfig()->GetFloat("sys_font_size"); std::string font_path_str = "./maps/fonts/" + Blam::Config::GetConfig()->GetString("sys_font"); if (Blam::Config::GetConfig()->GetBoolean("sys_font_force_extension") == true) { font_path_str = font_path_str + ".bin"; } const char* font_path = font_path_str.c_str(); Blam::Logger::LogEvent("Loading standard front from " + font_path_str); ImFont* font0 = io.Fonts->AddFontFromFileTTF(font_path_str.c_str(), font_size); } Blam::LogEvent("Setting UI theme: Elaztek"); InternalUI::load_elaztek_styles(); if (BlamRendering::DirectX::RenderTargetClearing() == false) { Blam::LogEvent("############################################"); Blam::LogEvent("# Render target clearing is DISABLED! #"); Blam::LogEvent("# You will notice some visual distortion #"); Blam::LogEvent("# and other visual errors! #"); Blam::LogEvent("############################################"); } BlamRendering::SetClearColor(ImColor(114, 144, 154)); imgui = new BlamRendering::RenderStack::ImGUIObject(); BlamRendering::RenderStack::AddToStack("imgui", imgui); InternalUI::Initialize(); } Blam::LogEvent("ENGINE_VERSION: " + std::string(Blam::EngineDefs::GetVersion())); Blam::LogEvent("UI_VERSION: " + std::string(InternalUI::GetVersion())); Blam::LogEvent("IMGUI_VERSION: " + std::string(ImGui::GetVersion())); //Blam::LogEvent("Beginning init"); //Load blamscript (this shit really sucks and is useless) { Blam::Logger::LogEvent("Initializing blamscript (TODO: rewrite all this shit)"); BlamScript::InitCSC(); BlamScript::InitHSC(); } //load content { //Blam::Content::Fonts::LoadFont("./maps/fonts/" + Blam::Config::GetConfig()->GetString("ui_default_font")); //Blam::Content::Fonts::LoadFont("./maps/fonts/conduit"); //Blam::Content::Fonts::LoadFont("./maps/fonts/arial-12"); //Blam::Content::Fonts::LoadFont("./maps/fonts/denmark-80"); Blam::Content::Fonts::LoadAllFonts(); } //Initialize Discord Rich Presence { Blam::DiscordRPC::InitDiscord(); Blam::DiscordRPC::UpdatePresence(ENGINE_VERSION, "Using the Blamite Engine"); } bool debug = Blam::Config::GetConfig()->GetBoolean("debugMode"); use_separate_render_thread = Blam::Config::GetConfig()->GetBoolean("use_separate_render_thread"); if (use_separate_render_thread) { Blam::Logger::LogEvent("### NOTICE rendering is being handled on a separate thread!"); render_thread = std::thread(BlamRendering::DirectX::RenderThread, debug); render_thread.detach(); } // Load built-in console commands Blam::Console::RegisterBuiltinCommands(); // Create custom ui elements (console, fps counter) { BlamRendering::RenderStack::FPSCounter* fpscounter = new BlamRendering::RenderStack::FPSCounter(); BlamRendering::RenderStack::AddToStack("fps_counter", fpscounter); console = new BlamRendering::RenderStack::ConsoleUI(); BlamRendering::RenderStack::AddToStack("console", console); BlamRendering::RenderStack::DebugMenu* debug_menu = new BlamRendering::RenderStack::DebugMenu(); BlamRendering::RenderStack::AddToStack("debug_menu", debug_menu); } // Run any startup commands in init.txt { if (Blam::Utils::IO::file_exists("./init.txt")) { std::vector startup_commands = Blam::Utils::IO::GetFileContentsAsLines("./init.txt"); for (int i = 0; i < startup_commands.size(); i++) { Blam::Console::RunCommandLine(startup_commands.at(i)); } } } // Main application loop MSG msg; ZeroMemory(&msg, sizeof(msg)); while (msg.message != WM_QUIT) { Blam::Tick::tick(); if (cursor) { //SetCursor(cursor); } if (debug == true) { //Blam::DebugUIKeyListener(); } if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); continue; } if (!use_separate_render_thread) { BlamRendering::DirectX::RenderLoop(debug); BlamRendering::DirectX::GetDXGISwapChain()->Present(1, 0); } Blam::Network::HandleReceive(&sock, socketBuffer, 2048, &bytesReceived, &from); Blam::Logger::Queue::Flush(); } cleanup_resources(window_name, wc); return 0; } void cleanup_resources(LPCWSTR ver_conv, WNDCLASSEX wc) { if (use_separate_render_thread) { Blam::Logger::LogEvent("stopping render thread"); BlamRendering::DirectX::ShutdownRenderThread(); while (BlamRendering::DirectX::HasRenderThreadStopped() == false) { //wait for render thread to stop } } BlamRendering::RenderStack::Cleanup(); Blam::LogEvent("Shutting down discord"); Blam::DiscordRPC::ShutdownDiscord(); if (imgui_initialized) { Blam::LogEvent("Shutting down ImGUI and cleaning up D3D device"); ImGui_ImplDX11_Shutdown(); ImGui_ImplWin32_Shutdown(); ImGui::DestroyContext(); } else { Blam::LogEvent("### INFO engine shutting down before imgui init"); } InternalUI::Shutdown(); //delete imgui; //delete console; Blam::Console::Cleanup(); Blam::Content::Fonts::Cleanup(); Blam::Cache::ClearCachedFiles(); BlamRendering::DirectX::Cleanup(); Blam::Logger::Queue::Flush(); DestroyWindow(main_hwnd); UnregisterClass(ver_conv, wc.hInstance); } HWND Blam::GetMainWindowHandle() { return main_hwnd; }