1#define ALICE_NO_ENTRY_POINT 1
3#include "common_types.cpp"
76#pragma comment(lib, "Ole32.lib")
77#pragma comment(lib, "Shell32.lib")
78#pragma comment(lib, "icu.lib")
90static float scaling_factor = 1.0f;
91static float dpi = 96.0f;
98static int32_t mouse_x = 0;
99static int32_t mouse_y = 0;
101static std::string ip_addr =
"127.0.0.1";
102static std::string password =
"";
103static std::string player_name =
"AnonAnon";
129 "Create a new scenario",
130 "for the selected mods",
145 "Senaryoyu yeniden oluştur",
147 "Seçilen modlar için yeni",
148 "bir senaryo oluşturun",
149 "Senaryo bulunamadı",
165 "Krijo një skenar të ri",
166 "për modalitetet e zgjedhura",
167 "Nuk u gjet asnjë skenar",
183 "Crea un nuevo escenario",
184 "para los mods seleccionados",
185 "No se encontro el escenario",
201 "Crea un nuovo esenario",
202 "per i mod selezionati",
203 "Scenario non trovato",
217 "Recrèer le scènario",
219 "Creer un nouveau scènario",
220 "pour les mods sèlectionnès",
221 "Scènario introuvable",
230 "Liste des modifications"
237 "Crie un novo cenário para",
238 "os mods selecionados",
239 "Cenário não encontrado",
248 "Lista de modificaçães"
252 "Szenario erstellen",
253 "Szenario neu erstellen",
255 "Neues Szenario für die",
256 "ausgewählten mods erstellen",
257 "Szenario nicht gefunden",
266 "Liste der Modifikationen"
271 "Återskapa scenario",
273 "Skepa ett nytt scenario",
275 "Scenario hittades inte",
284 "Lista åver åndriggar"
307 "إعادة إنشاء السيناريو",
309 "إنشاء سيناريو جديد",
311 "لم يتم العثور على المشهد",
320 "قائمة وزارة الدفاع",
325 "Gjenskape scenario",
327 "Lag et nytt scenario",
328 "for de valgte modsene",
329 "Ingen scenarioer funnet",
343 "Scenariu de recenzie",
345 "Creați un nou script",
346 "pentru moduri selectate",
347 "Nu a fost găsit niciun script",
361 "Воссоздать сценарий",
363 "Создать новый сценарий",
364 "Для выбранного мода",
379 "Odtwórz scenariusz",
381 "Utwórz nowy scenariusz",
382 "dla wybranych modów",
383 "Nie znaleziono scenariusza",
397 "Пресъздайте сценарий",
399 "Създайте нов сценарий",
400 "за избраните модове",
401 "Няма намерен сценарий",
417 "Creeu un nou escenari",
418 "per als mods seleccionats",
419 "No s'ha trobat cap escenari",
428 "Llista de modificacions",
433 "Znovu vytvořit scénář",
435 "Vytvořte nový scénář",
437 "Nebyl nalezen žádný scénář",
453 "Opret et nyt scenarie",
454 "for de valgte mods",
455 "Intet scenarie fundet",
468 "Δημιουργία σεναρίου",
469 "Αναδημιουργήστε το σενάριο",
471 "Δημιουργήστε ένα νέο σενάριο",
472 "για τα επιλεγμένα mods",
473 "Δεν βρέθηκε κανένα σενάριο",
478 "Λειτουργία για πολλούς παίκτες",
479 "Ξεκίνα το παιχνίδι",
487 "Luo skenaario uudelleen",
489 "Luo uusi skenaario",
490 "valituille modeille",
491 "Skenaariota ei löytynyt",
507 "צור תרחיש חדש עבור",
510 "כתובת פרוטוקול אינטרנט",
518 "רשימת השינויים במשחק"
522 "Forgatókönyv létrehozása",
523 "Forgatókönyv újbóli létrehozása",
525 "Hozzon létre egy új forgatókönyvet",
526 "a kiválasztott modokhoz",
527 "Nem található forgatókönyv",
541 "Scenario opnieuw maken",
543 "Maak een nieuw scenario",
544 "voor de geselecteerde mods",
545 "Geen scenario gevonden",
561 "Sukurkite naują pasirinktų",
562 "modifikacijų scenarijų",
563 "Scenarijus nerastas",
572 "Modifikacijų sąrašas"
576 "Izveidojiet scenāriju",
577 "Atkārtoti izveidojiet scenāriju",
579 "Izveidojiet jaunu scenāriju",
580 "atlasītajiem modiem",
581 "Nav atrasts neviens scenārijs",
586 "Vairāku spēlētāju spēle",
595 "Loo stsenaarium uuesti",
597 "Looge valitud modifikatsioonide",
598 "jaoks uus stsenaarium",
599 "Stsenaariumi ei leitud",
608 "Modifikatsioonide loend"
613 "परिदृश्य फिर से बनाएँ",
614 "कार्य कर रहा है...",
616 "एक नया परिदृश्य बनाएँ",
617 "कोई परिदृश्य नहीं मिला",
633 "Tạo một kịch bản mới cho",
635 "Không tìm thấy kịch bản",
649 "Վերստեղծեք սցենարը",
651 "Ստեղծեք նոր սցենար",
652 "ընտրված ռեժիմների համար",
653 "Ոչ մի սցենար չի գտնվել",
669 "Створіть новий сценарій",
671 "Не знайдено сценарію",
682static std::string_view* localised_strings = &en_localised_strings[0];
684static HWND m_hwnd =
nullptr;
716static int32_t obj_under_mouse = -1;
718static bool game_dir_not_found =
false;
776static std::vector<parsers::mod_file> mod_list;
783static std::vector<scenario_file> scenario_files;
785static uint32_t max_scenario_count = 0;
786static std::atomic<bool> file_is_ready =
true;
788static int32_t frame_in_list = 0;
790static HDC opengl_window_dc =
nullptr;
791static void* opengl_context =
nullptr;
794 PIXELFORMATDESCRIPTOR pfd;
795 ZeroMemory(&pfd,
sizeof(pfd));
796 pfd.nSize =
sizeof(pfd);
798 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
799 pfd.iPixelType = PFD_TYPE_RGBA;
802 pfd.cStencilBits = 8;
803 pfd.iLayerType = PFD_MAIN_PLANE;
805 HDC window_dc = opengl_window_dc;
807 int const pixel_format = ChoosePixelFormat(window_dc, &pfd);
808 SetPixelFormat(window_dc, pixel_format, &pfd);
810 auto handle_to_ogl_dc = wglCreateContext(window_dc);
811 wglMakeCurrent(window_dc, handle_to_ogl_dc);
813 if(glewInit() != 0) {
817 if(!wglewIsSupported(
"WGL_ARB_create_context")) {
822 static const int attribs_3_1[] = {
823 WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
824 WGL_CONTEXT_MINOR_VERSION_ARB, 1,
825 WGL_CONTEXT_FLAGS_ARB, 0,
826 WGL_CONTEXT_PROFILE_MASK_ARB,
827 WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
830 opengl_context = wglCreateContextAttribsARB(window_dc,
nullptr, attribs_3_1);
831 if(opengl_context ==
nullptr) {
835 wglMakeCurrent(window_dc, HGLRC(opengl_context));
836 wglDeleteContext(handle_to_ogl_dc);
838 if(wglewIsSupported(
"WGL_EXT_swap_control_tear") == 1) {
839 wglSwapIntervalEXT(-1);
840 }
else if(wglewIsSupported(
"WGL_EXT_swap_control") == 1) {
841 wglSwapIntervalEXT(1);
848 wglMakeCurrent(opengl_window_dc,
nullptr);
849 wglDeleteContext(HGLRC(opengl_context));
850 opengl_context =
nullptr;
858 if(obj_under_mouse != i) {
867 if(obj_under_mouse != -1) {
868 obj_under_mouse = -1;
876 for(int32_t i = 0; i < int32_t(mod_list.size()); ++i) {
877 if(mod_list[i].mod_selected) {
878 if(std::find(mod_list[i].dependent_mods.begin(), mod_list[i].dependent_mods.end(), mod.
name_) != mod_list[i].dependent_mods.end()) {
879 mod_list[i].mod_selected =
false;
887 for(int32_t i = 0; i < int32_t(mod_list.size()); ++i) {
888 if(!mod_list[i].mod_selected && mod_list[i].name_ == dep) {
889 mod_list[i].mod_selected =
true;
898 if(dep == modb.
name_)
901 for(int32_t i = 0; i < int32_t(mod_list.size()); ++i) {
902 if(seen_indices[i] ==
false && mod_list[i].name_ == dep) {
903 seen_indices[i] =
true;
913 std::vector<bool> seen_indices;
914 seen_indices.resize(mod_list.size());
921 if(a.mod_selected && b.mod_selected) {
922 return transitively_depends_on(b, a);
928 return a.name_ < b.name_;
942 if(n >= int32_t(mod_list.size()) - 1)
944 if(mod_list[n + 1].mod_selected ==
false)
956 for(int32_t i = 0; i < int32_t(mod_list.size()); ++i) {
957 if(mod_list[i].mod_selected ==
false)
960 mod_list[i].add_to_file_system(dummy);
968 auto len = std::min<size_t>(launcher::player_name.length(),
sizeof(p.
data));
969 std::memcpy(p.
data, launcher::player_name.c_str(), len);
979 ret += digits[v & 0x0F];
987 file_is_ready.store(
false, std::memory_order::memory_order_seq_cst);
989 std::thread file_maker([path]() {
993 auto root = get_root(fs_root);
994 auto common = open_directory(root,
NATIVE(
"common"));
996 if(
auto f = open_file(common,
NATIVE(
"bookmarks.txt")); f) {
1000 parsers::parse_bookmark_file(gen, err, bookmark_context);
1012 auto game_state = std::make_unique<sys::state>();
1014 game_state->load_scenario_data(err, bookmark_context.
bookmark_dates[date_index].date_);
1017 if(date_index == 0) {
1020 auto time_stamp =
uint64_t(std::time(0));
1021 auto base_name =
to_hex(time_stamp);
1025 ++max_scenario_count;
1026 selected_scenario_file = base_name +
NATIVE(
"-") + std::to_wstring(append) +
NATIVE(
".bin");
1029 auto content = view_contents(*of);
1031 if(desc.count != 0) {
1032 scenario_files.push_back(
scenario_file{ selected_scenario_file , desc });
1036 return a.ident.count > b.ident.count;
1038 scenario_key = game_state->scenario_checksum;
1043 game_state->scenario_checksum = scenario_key;
1049 auto assembled_file = std::string(
"You can still play the mod, but it might be unstable\r\nThe following problems were encountered while creating the scenario:\r\n\r\nErrors:\r\n") + err.
accumulated_errors +
"\r\n\r\nWarnings:\r\n" + err.
accumulated_warnings;
1065 file_is_ready.store(
true, std::memory_order::memory_order_release);
1066 InvalidateRect((
HWND)(m_hwnd),
nullptr, FALSE);
1069 file_maker.detach();
1073 if(!file_is_ready.load(std::memory_order::memory_order_acquire))
1076 file_is_ready.store(
false, std::memory_order::memory_order_seq_cst);
1077 selected_scenario_file =
NATIVE(
"");
1080 for(
auto& f : scenario_files) {
1081 if(f.ident.mod_path == mod_path) {
1082 selected_scenario_file = f.file_name;
1086 file_is_ready.store(
true, std::memory_order::memory_order_release);
1090 if(obj_under_mouse == -1)
1093 switch(obj_under_mouse) {
1095 PostMessageW(m_hwnd, WM_CLOSE, 0, 0);
1098 if(frame_in_list > 0) {
1100 InvalidateRect((
HWND)(m_hwnd),
nullptr, FALSE);
1104 if((frame_in_list + 1) *
ui_list_count < int32_t(mod_list.size())) {
1106 InvalidateRect((
HWND)(m_hwnd),
nullptr, FALSE);
1110 if(file_is_ready.load(std::memory_order::memory_order_acquire)) {
1112 InvalidateRect((
HWND)(m_hwnd),
nullptr, FALSE);
1116 if(file_is_ready.load(std::memory_order::memory_order_acquire) && !selected_scenario_file.empty()) {
1117 if(IsProcessorFeaturePresent(PF_AVX512F_INSTRUCTIONS_AVAILABLE)) {
1121 ZeroMemory(&si,
sizeof(si));
1123 PROCESS_INFORMATION pi;
1124 ZeroMemory(&pi,
sizeof(pi));
1128 const_cast<wchar_t*
>(temp_command_line.c_str()),
1138 CloseHandle(pi.hProcess);
1139 CloseHandle(pi.hThread);
1144 if(!IsProcessorFeaturePresent(PF_AVX2_INSTRUCTIONS_AVAILABLE)) {
1148 ZeroMemory(&si,
sizeof(si));
1150 PROCESS_INFORMATION pi;
1151 ZeroMemory(&pi,
sizeof(pi));
1155 const_cast<wchar_t*
>(temp_command_line.c_str()),
1165 CloseHandle(pi.hProcess);
1166 CloseHandle(pi.hThread);
1175 ZeroMemory(&si,
sizeof(si));
1177 PROCESS_INFORMATION pi;
1178 ZeroMemory(&pi,
sizeof(pi));
1182 const_cast<wchar_t*
>(temp_command_line.c_str()),
1192 CloseHandle(pi.hProcess);
1193 CloseHandle(pi.hThread);
1200 if(file_is_ready.load(std::memory_order::memory_order_acquire) && !selected_scenario_file.empty()) {
1203 temp_command_line +=
NATIVE(
" -host");
1204 temp_command_line +=
NATIVE(
" -name ");
1207 temp_command_line +=
NATIVE(
" -join");
1208 temp_command_line +=
NATIVE(
" ");
1210 temp_command_line +=
NATIVE(
" -name ");
1214 if(!ip_addr.empty() && ::strchr(ip_addr.c_str(),
':') !=
nullptr) {
1215 temp_command_line +=
NATIVE(
" -v6");
1219 if(!password.empty()) {
1220 temp_command_line +=
NATIVE(
" -password ");
1225 ZeroMemory(&si,
sizeof(si));
1227 PROCESS_INFORMATION pi;
1228 ZeroMemory(&pi,
sizeof(pi));
1232 const_cast<wchar_t*
>(temp_command_line.c_str()),
1242 CloseHandle(pi.hProcess);
1243 CloseHandle(pi.hThread);
1260 if(!file_is_ready.load(std::memory_order::memory_order_acquire))
1263 int32_t list_position = (obj_under_mouse -
ui_list_first) / 3;
1264 int32_t sub_obj = (obj_under_mouse -
ui_list_first) - list_position * 3;
1270 if(list_offset < int32_t(launcher::mod_list.size())) {
1271 launcher::mod_list[list_offset].mod_selected = !launcher::mod_list[list_offset].mod_selected;
1272 if(!launcher::mod_list[list_offset].mod_selected) {
1279 InvalidateRect((
HWND)(m_hwnd),
nullptr, FALSE);
1287 std::swap(launcher::mod_list[list_offset], launcher::mod_list[list_offset - 1]);
1289 InvalidateRect((
HWND)(m_hwnd),
nullptr, FALSE);
1297 std::swap(launcher::mod_list[list_offset], launcher::mod_list[list_offset + 1]);
1299 InvalidateRect((
HWND)(m_hwnd),
nullptr, FALSE);
1308GLint compile_shader(std::string_view source, GLenum type) {
1309 GLuint return_value = glCreateShader(type);
1311 if(return_value == 0) {
1312 MessageBoxW(m_hwnd, L
"shader creation failed", L
"OpenGL error", MB_OK);
1315 std::string s_source(source);
1316 GLchar
const* texts[] = {
1318 "#extension GL_ARB_explicit_uniform_location : enable\r\n",
1319 "#extension GL_ARB_explicit_attrib_location : enable\r\n",
1320 "#extension GL_ARB_shader_subroutine : enable\r\n",
1321 "#define M_PI 3.1415926535897932384626433832795\r\n",
1322 "#define PI 3.1415926535897932384626433832795\r\n",
1325 glShaderSource(return_value, 7, texts,
nullptr);
1326 glCompileShader(return_value);
1329 glGetShaderiv(return_value, GL_COMPILE_STATUS, &result);
1330 if(result == GL_FALSE) {
1331 GLint log_length = 0;
1332 glGetShaderiv(return_value, GL_INFO_LOG_LENGTH, &log_length);
1334 auto log = std::unique_ptr<char[]>(
new char[
static_cast<size_t>(log_length)]);
1335 GLsizei written = 0;
1336 glGetShaderInfoLog(return_value, log_length, &written, log.get());
1337 auto error = std::string(
"Shader failed to compile:\n") + log.get();
1338 MessageBoxA(m_hwnd, error.c_str(),
"OpenGL error", MB_OK);
1340 return return_value;
1343GLuint create_program(std::string_view vertex_shader, std::string_view fragment_shader) {
1344 GLuint return_value = glCreateProgram();
1345 if(return_value == 0) {
1346 MessageBoxW(m_hwnd, L
"program creation failed", L
"OpenGL error", MB_OK);
1349 auto v_shader = compile_shader(vertex_shader, GL_VERTEX_SHADER);
1350 auto f_shader = compile_shader(fragment_shader, GL_FRAGMENT_SHADER);
1352 glAttachShader(return_value, v_shader);
1353 glAttachShader(return_value, f_shader);
1354 glLinkProgram(return_value);
1357 glGetProgramiv(return_value, GL_LINK_STATUS, &result);
1358 if(result == GL_FALSE) {
1360 glGetProgramiv(return_value, GL_INFO_LOG_LENGTH, &logLen);
1362 char* log =
new char[
static_cast<size_t>(logLen)];
1364 glGetProgramInfoLog(return_value, logLen, &written, log);
1365 auto err = std::string(
"Program failed to link:\n") + log;
1366 MessageBoxA(m_hwnd, err.c_str(),
"OpenGL error", MB_OK);
1369 glDeleteShader(v_shader);
1370 glDeleteShader(f_shader);
1372 return return_value;
1375static GLfloat global_square_data[] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f };
1376static GLfloat global_square_right_data[] = { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f };
1377static GLfloat global_square_left_data[] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f };
1378static GLfloat global_square_flipped_data[] = { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f };
1379static GLfloat global_square_right_flipped_data[] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f };
1380static GLfloat global_square_left_flipped_data[] = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f };
1382static GLuint ui_shader_program = 0;
1384void load_shaders() {
1387 auto root = get_root(fs);
1389 std::string_view fx_str =
1390 "in vec2 tex_coord;\n"
1391 "out vec4 frag_color;\n"
1392 "uniform sampler2D texture_sampler;\n"
1393 "uniform vec4 d_rect;\n"
1394 "uniform float border_size;\n"
1395 "uniform vec3 inner_color;\n"
1396 "uniform vec4 subrect;\n"
1397 "uniform uvec2 subroutines_index;\n"
1398 "vec4 color_filter(vec2 tc) {\n"
1399 "\tvec4 color_in = texture(texture_sampler, tc);\n"
1400 "\tfloat sm_val = smoothstep(0.5 - border_size / 2.0, 0.5 + border_size / 2.0, color_in.r);\n"
1401 "\treturn vec4(inner_color, sm_val);\n"
1403 "vec4 no_filter(vec2 tc) {\n"
1404 "\treturn texture(texture_sampler, tc);\n"
1406 "vec4 disabled_color(vec4 color_in) {\n"
1407 "\tfloat amount = (color_in.r + color_in.g + color_in.b) / 4.0;\n"
1408 "\treturn vec4(amount, amount, amount, color_in.a);\n"
1410 "vec4 interactable_color(vec4 color_in) {\n"
1411 "\treturn vec4(color_in.r + 0.1, color_in.g + 0.1, color_in.b + 0.1, color_in.a);\n"
1413 "vec4 interactable_disabled_color(vec4 color_in) {\n"
1414 "\tfloat amount = (color_in.r + color_in.g + color_in.b) / 4.0;\n"
1415 "\treturn vec4(amount + 0.1, amount + 0.1, amount + 0.1, color_in.a);\n"
1417 "vec4 tint_color(vec4 color_in) {\n"
1418 "\treturn vec4(color_in.r * inner_color.r, color_in.g * inner_color.g, color_in.b * inner_color.b, color_in.a);\n"
1420 "vec4 enabled_color(vec4 color_in) {\n"
1421 "\treturn color_in;\n"
1423 "vec4 alt_tint_color(vec4 color_in) {\n"
1424 "\treturn vec4(color_in.r * subrect.r, color_in.g * subrect.g, color_in.b * subrect.b, color_in.a);\n"
1426 "vec4 font_function(vec2 tc) {\n"
1427 "\treturn int(subroutines_index.y) == 1 ? color_filter(tc) : no_filter(tc);\n"
1429 "vec4 coloring_function(vec4 tc) {\n"
1430 "\tswitch(int(subroutines_index.x)) {\n"
1431 "\tcase 3: return disabled_color(tc);\n"
1432 "\tcase 4: return enabled_color(tc);\n"
1433 "\tcase 12: return tint_color(tc);\n"
1434 "\tcase 13: return interactable_color(tc);\n"
1435 "\tcase 14: return interactable_disabled_color(tc);\n"
1436 "\tcase 16: return alt_tint_color(tc);\n"
1437 "\tdefault: break;\n"
1442 "\tfrag_color = coloring_function(font_function(tex_coord));\n"
1444 std::string_view vx_str =
1445 "layout (location = 0) in vec2 vertex_position;\n"
1446 "layout (location = 1) in vec2 v_tex_coord;\n"
1447 "out vec2 tex_coord;\n"
1448 "uniform float screen_width;\n"
1449 "uniform float screen_height;\n"
1450 "uniform vec4 d_rect;\n"
1452 "\tgl_Position = vec4(\n"
1453 "\t\t-1.0 + (2.0 * ((vertex_position.x * d_rect.z) + d_rect.x) / screen_width),\n"
1454 "\t\t 1.0 - (2.0 * ((vertex_position.y * d_rect.w) + d_rect.y) / screen_height),\n"
1456 "\ttex_coord = v_tex_coord;\n"
1459 ui_shader_program = create_program(vx_str, fx_str);
1462static GLuint global_square_vao = 0;
1463static GLuint global_square_buffer = 0;
1464static GLuint global_square_right_buffer = 0;
1465static GLuint global_square_left_buffer = 0;
1466static GLuint global_square_flipped_buffer = 0;
1467static GLuint global_square_right_flipped_buffer = 0;
1468static GLuint global_square_left_flipped_buffer = 0;
1470static GLuint sub_square_buffers[64] = { 0 };
1472void load_global_squares() {
1473 glGenBuffers(1, &global_square_buffer);
1476 glBindBuffer(GL_ARRAY_BUFFER, global_square_buffer);
1477 glBufferData(GL_ARRAY_BUFFER,
sizeof(GLfloat) * 16, global_square_data, GL_STATIC_DRAW);
1479 glGenVertexArrays(1, &global_square_vao);
1480 glBindVertexArray(global_square_vao);
1481 glEnableVertexAttribArray(0);
1482 glEnableVertexAttribArray(1);
1484 glBindVertexBuffer(0, global_square_buffer, 0,
sizeof(GLfloat) * 4);
1486 glVertexAttribFormat(0, 2, GL_FLOAT, GL_FALSE, 0);
1487 glVertexAttribFormat(1, 2, GL_FLOAT, GL_FALSE,
sizeof(GLfloat) * 2);
1488 glVertexAttribBinding(0, 0);
1489 glVertexAttribBinding(1, 0);
1491 glGenBuffers(1, &global_square_left_buffer);
1492 glBindBuffer(GL_ARRAY_BUFFER, global_square_left_buffer);
1493 glBufferData(GL_ARRAY_BUFFER,
sizeof(GLfloat) * 16, global_square_left_data, GL_STATIC_DRAW);
1495 glGenBuffers(1, &global_square_right_buffer);
1496 glBindBuffer(GL_ARRAY_BUFFER, global_square_right_buffer);
1497 glBufferData(GL_ARRAY_BUFFER,
sizeof(GLfloat) * 16, global_square_right_data, GL_STATIC_DRAW);
1499 glGenBuffers(1, &global_square_right_flipped_buffer);
1500 glBindBuffer(GL_ARRAY_BUFFER, global_square_right_flipped_buffer);
1501 glBufferData(GL_ARRAY_BUFFER,
sizeof(GLfloat) * 16, global_square_right_flipped_data, GL_STATIC_DRAW);
1503 glGenBuffers(1, &global_square_left_flipped_buffer);
1504 glBindBuffer(GL_ARRAY_BUFFER, global_square_left_flipped_buffer);
1505 glBufferData(GL_ARRAY_BUFFER,
sizeof(GLfloat) * 16, global_square_left_flipped_data, GL_STATIC_DRAW);
1507 glGenBuffers(1, &global_square_flipped_buffer);
1508 glBindBuffer(GL_ARRAY_BUFFER, global_square_flipped_buffer);
1509 glBufferData(GL_ARRAY_BUFFER,
sizeof(GLfloat) * 16, global_square_flipped_data, GL_STATIC_DRAW);
1511 glGenBuffers(64, sub_square_buffers);
1513 glBindBuffer(GL_ARRAY_BUFFER, sub_square_buffers[i]);
1515 float const cell_x =
static_cast<float>(i & 7) / 8.0f;
1516 float const cell_y =
static_cast<float>((i >> 3) & 7) / 8.0f;
1518 GLfloat global_sub_square_data[] = { 0.0f, 0.0f, cell_x, cell_y, 0.0f, 1.0f, cell_x, cell_y + 1.0f / 8.0f, 1.0f, 1.0f,
1519 cell_x + 1.0f / 8.0f, cell_y + 1.0f / 8.0f, 1.0f, 0.0f, cell_x + 1.0f / 8.0f, cell_y };
1521 glBufferData(GL_ARRAY_BUFFER,
sizeof(GLfloat) * 16, global_sub_square_data, GL_STATIC_DRAW);
1527namespace parameters {
1585 glBindVertexBuffer(0, global_square_buffer, 0,
sizeof(GLfloat) * 4);
1587 glBindVertexBuffer(0, global_square_flipped_buffer, 0,
sizeof(GLfloat) * 4);
1591 glBindVertexBuffer(0, global_square_left_buffer, 0,
sizeof(GLfloat) * 4);
1593 glBindVertexBuffer(0, global_square_left_flipped_buffer, 0,
sizeof(GLfloat) * 4);
1597 glBindVertexBuffer(0, global_square_right_buffer, 0,
sizeof(GLfloat) * 4);
1599 glBindVertexBuffer(0, global_square_right_flipped_buffer, 0,
sizeof(GLfloat) * 4);
1605 float x = float(ix);
1606 float y = float(iy);
1607 float width = float(iwidth);
1608 float height = float(iheight);
1610 glBindVertexArray(global_square_vao);
1614 glUniform4f(glGetUniformLocation(ui_shader_program,
"d_rect"), x, y, width, height);
1617 glActiveTexture(GL_TEXTURE0);
1618 glBindTexture(GL_TEXTURE_2D, texture_handle);
1621 glUniform2ui(glGetUniformLocation(ui_shader_program,
"subroutines_index"), subroutines[0], subroutines[1]);
1624 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1628 hb_buffer_clear_contents(f.
hb_buf);
1629 hb_buffer_add_utf8(f.
hb_buf, str.data(),
int(str.size()), 0,
int(str.size()));
1630 hb_buffer_guess_segment_properties(f.
hb_buf);
1632 unsigned int glyph_count = 0;
1633 hb_glyph_info_t* glyph_info = hb_buffer_get_glyph_infos(f.
hb_buf, &glyph_count);
1634 hb_glyph_position_t* glyph_pos = hb_buffer_get_glyph_positions(f.
hb_buf, &glyph_count);
1635 float x = baseline_x;
1636 for(
unsigned int i = 0; i < glyph_count; i++) {
1639 for(
unsigned int i = 0; i < glyph_count; i++) {
1640 hb_codepoint_t glyphid = glyph_info[i].codepoint;
1645 if(glyphid != FT_Get_Char_Index(f.
font_face,
' ')) {
1646 glBindVertexBuffer(0, sub_square_buffers[f.
glyph_positions[glyphid].texture_slot & 63], 0,
sizeof(GLfloat) * 4);
1647 glActiveTexture(GL_TEXTURE0);
1649 glUniform4f(glGetUniformLocation(ui_shader_program,
"d_rect"), x + x_offset * size / 64.f, baseline_y + y_offset * size / 64.f, size, size);
1650 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1652 x += x_advance * size / 64.f;
1657 glUniform3f(glGetUniformLocation(ui_shader_program,
"inner_color"), c.
r, c.
g, c.
b);
1658 glUniform1f(glGetUniformLocation(ui_shader_program,
"border_size"), 0.08f * 16.0f / size);
1661 glUniform2ui(glGetUniformLocation(ui_shader_program,
"subroutines_index"), subroutines[0], subroutines[1]);
1668static ::text::font_manager font_collection;
1669static ::text::font fonts[2];
1671static ::ogl::texture bg_tex;
1672static ::ogl::texture left_tex;
1673static ::ogl::texture right_tex;
1674static ::ogl::texture close_tex;
1675static ::ogl::texture big_button_tex;
1676static ::ogl::texture empty_check_tex;
1677static ::ogl::texture check_tex;
1678static ::ogl::texture up_tex;
1679static ::ogl::texture down_tex;
1680static ::ogl::texture line_bg_tex;
1681static ::ogl::texture big_l_button_tex;
1682static ::ogl::texture big_r_button_tex;
1683static ::ogl::texture warning_tex;
1686 hb_buffer_clear_contents(f.
hb_buf);
1687 hb_buffer_add_utf8(f.
hb_buf, codepoints,
int(count), 0,
int(count));
1688 hb_buffer_guess_segment_properties(f.
hb_buf);
1690 unsigned int glyph_count = 0;
1691 hb_glyph_info_t* glyph_info = hb_buffer_get_glyph_infos(f.
hb_buf, &glyph_count);
1692 hb_glyph_position_t* glyph_pos = hb_buffer_get_glyph_positions(f.
hb_buf, &glyph_count);
1694 for(
unsigned int i = 0; i < glyph_count; i++) {
1697 for(
unsigned int i = 0; i < glyph_count; i++) {
1698 hb_codepoint_t glyphid = glyph_info[i].codepoint;
1703 x += x_advance * size / 64.f;
1712 glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
1713 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1715 glUseProgram(ui_shader_program);
1716 glUniform1i(glGetUniformLocation(ui_shader_program,
"texture_sampler"), 0);
1717 glUniform1f(glGetUniformLocation(ui_shader_program,
"screen_width"),
float(
base_width));
1718 glUniform1f(glGetUniformLocation(ui_shader_program,
"screen_height"),
float(
base_height));
1720 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1723 glDepthRange(-1.0f, 1.0f);
1737 if(frame_in_list > 0) {
1753 if((frame_in_list + 1) *
ui_list_count < int32_t(mod_list.size())) {
1770 if(file_is_ready.load(std::memory_order::memory_order_acquire)) {
1777 if(game_dir_not_found) {
1786 if(selected_scenario_file.empty()) {
1802 if(game_dir_not_found) {
1825 if(file_is_ready.load(std::memory_order::memory_order_acquire) && !selected_scenario_file.empty()) {
1873 launcher::ogl::render_new_text(sv.data(),
launcher::ogl::color_modification::none,
ui_rects[
ui_obj_ip_addr].
x +
ui_rects[
ui_obj_ip_addr].
width -
base_text_extent(sv.data(),
uint32_t(sv.size()), 14, fonts[0]),
ui_rects[
ui_obj_ip_addr].
y - 21.f, 14.0f,
launcher::ogl::color3f{ 255.0f / 255.0f, 230.0f / 255.0f, 153.0f / 255.0f }, fonts[0]);
1882 launcher::ogl::render_new_text(sv.data(),
launcher::ogl::color_modification::none,
ui_rects[
ui_obj_password].
x +
ui_rects[
ui_obj_password].
width -
base_text_extent(sv.data(),
uint32_t(sv.size()), 14, fonts[0]),
ui_rects[
ui_obj_password].
y - 21.f, 14.0f,
launcher::ogl::color3f{ 255.0f / 255.0f, 230.0f / 255.0f, 153.0f / 255.0f }, fonts[0]);
1891 launcher::ogl::render_new_text(sv.data(),
launcher::ogl::color_modification::none,
ui_rects[
ui_obj_player_name].
x +
ui_rects[
ui_obj_player_name].
width -
base_text_extent(sv.data(),
uint32_t(sv.size()), 14, fonts[0]),
ui_rects[
ui_obj_player_name].
y - 21.f, 14.0f,
launcher::ogl::color3f{ 255.0f / 255.0f, 230.0f / 255.0f, 153.0f / 255.0f }, fonts[0]);
1900 launcher::ogl::render_new_text(sv.data(),
launcher::ogl::color_modification::none,
ui_rects[
ui_obj_play_game].
x +
ui_rects[
ui_obj_play_game].
width -
base_text_extent(sv.data(),
uint32_t(sv.size()), 22, fonts[1]),
ui_rects[
ui_obj_play_game].
y - 32.f, 22.0f,
launcher::ogl::color3f{ 255.0f / 255.0f, 230.0f / 255.0f, 153.0f / 255.0f }, fonts[1]);
1907 launcher::ogl::render_new_text(sv.data(),
launcher::ogl::color_modification::none,
ui_rects[
ui_obj_join_game].
x +
ui_rects[
ui_obj_join_game].
width -
base_text_extent(sv.data(),
uint32_t(sv.size()), 22, fonts[1]),
ui_rects[
ui_obj_host_game].
y - 32.f, 22.0f,
launcher::ogl::color3f{ 255.0f / 255.0f, 230.0f / 255.0f, 153.0f / 255.0f }, fonts[1]);
1931 for(int32_t i = 0; i <
ui_list_count && list_offset + i < int32_t(mod_list.size()); ++i) {
1932 auto& mod_ref = mod_list[list_offset + i];
1944 if(mod_ref.mod_selected) {
1996 SwapBuffers(opengl_window_dc);
2000 return char_code >= 0xDC00 && char_code <= 0xDFFF;
2003 return char_code >= 0xD800 && char_code <= 0xDBFF;
2012 WideCharToMultiByte(1250, 0, &c, 1, &char_out, 1,
nullptr,
nullptr);
2016LRESULT CALLBACK
WndProc(
HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
2017 if(message == WM_CREATE) {
2018 opengl_window_dc = GetDC(hwnd);
2020 create_opengl_context();
2022 glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
2023 glEnable(GL_LINE_SMOOTH);
2026 load_global_squares();
2030 auto root = get_root(fs);
2033 LANGID lang = GetUserDefaultUILanguage();
2035 switch(lang & 0xff) {
2041 localised_strings = &bg_localised_strings[0];
2045 localised_strings = &ca_localised_strings[0];
2048 localised_strings = &zh_localised_strings[0];
2052 localised_strings = &cs_localised_strings[0];
2055 localised_strings = &da_localised_strings[0];
2058 localised_strings = &de_localised_strings[0];
2061 localised_strings = &el_localised_strings[0];
2064 localised_strings = &en_localised_strings[0];
2067 localised_strings = &es_localised_strings[0];
2070 localised_strings = &fi_localised_strings[0];
2073 localised_strings = &fr_localised_strings[0];
2079 localised_strings = &hu_localised_strings[0];
2085 localised_strings = &it_localised_strings[0];
2094 localised_strings = &po_localised_strings[0];
2097 localised_strings = &nl_localised_strings[0];
2100 localised_strings = &no_localised_strings[0];
2103 localised_strings = &pl_localised_strings[0];
2106 localised_strings = &ro_localised_strings[0];
2109 localised_strings = &ru_localised_strings[0];
2113 localised_strings = &sq_localised_strings[0];
2116 localised_strings = &sv_localised_strings[0];
2119 localised_strings = &tr_localised_strings[0];
2122 localised_strings = &uk_localised_strings[0];
2126 localised_strings = &et_localised_strings[0];
2129 localised_strings = &lv_localised_strings[0];
2132 localised_strings = <_localised_strings[0];
2135 localised_strings = &vi_localised_strings[0];
2138 localised_strings = &hy_localised_strings[0];
2141 localised_strings = &hi_localised_strings[0];
2146 if(font_set_load == 0) {
2150 font_collection.
load_font(fonts[0], file_content.data, file_content.file_size);
2155 font_collection.
load_font(fonts[1], file_content.data, file_content.file_size);
2157 }
else if(font_set_load == 1) {
2161 font_collection.
load_font(fonts[0], file_content.data, file_content.file_size);
2166 font_collection.
load_font(fonts[1], file_content.data, file_content.file_size);
2168 }
else if(font_set_load == 2) {
2172 font_collection.
load_font(fonts[0], file_content.data, file_content.file_size);
2177 font_collection.
load_font(fonts[1], file_content.data, file_content.file_size);
2179 }
else if(font_set_load == 3) {
2183 font_collection.
load_font(fonts[0], file_content.data, file_content.file_size);
2188 font_collection.
load_font(fonts[1], file_content.data, file_content.file_size);
2206 game_dir_not_found =
false;
2212 game_dir_not_found =
true;
2221 for(
auto& f : mod_files) {
2224 auto content = view_contents(*of);
2232 for(
auto& f : s_files) {
2235 auto content = view_contents(*of);
2237 if(desc.count != 0) {
2238 max_scenario_count = std::max(desc.count, max_scenario_count);
2245 return a.ident.count > b.ident.count;
2255 dpi = float(HIWORD(wParam));
2256 auto lprcNewScale =
reinterpret_cast<RECT*
>(lParam);
2259 scaling_factor = float(lprcNewScale->right - lprcNewScale->left) /
base_width;
2261 SetWindowPos(hwnd,
nullptr, lprcNewScale->left, lprcNewScale->top,
2262 lprcNewScale->right - lprcNewScale->left, lprcNewScale->bottom - lprcNewScale->top,
2263 SWP_NOZORDER | SWP_NOACTIVATE);
2265 InvalidateRect((
HWND)(m_hwnd),
nullptr, FALSE);
2269 case WM_NCMOUSEMOVE:
2272 GetWindowRect(hwnd, &rcWindow);
2273 auto x = GET_X_LPARAM(lParam);
2274 auto y = GET_Y_LPARAM(lParam);
2276 POINTS adj{ SHORT(x - rcWindow.left), SHORT(y - rcWindow.top) };
2277 memcpy(&lParam, &adj,
sizeof(LPARAM));
2279 mouse_x = int32_t(
float(GET_X_LPARAM(lParam)) / scaling_factor);
2280 mouse_y = int32_t(
float(GET_Y_LPARAM(lParam)) / scaling_factor);
2282 InvalidateRect((
HWND)(m_hwnd),
nullptr, FALSE);
2288 mouse_x = int32_t(
float(GET_X_LPARAM(lParam)) / scaling_factor);
2289 mouse_y = int32_t(
float(GET_Y_LPARAM(lParam)) / scaling_factor);
2291 InvalidateRect((
HWND)(m_hwnd),
nullptr, FALSE);
2295 case WM_LBUTTONDOWN:
2306 POINT ptMouse = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
2308 GetWindowRect(hwnd, &rcWindow);
2310 if(ptMouse.x <= int32_t(rcWindow.left +
caption_width * scaling_factor)
2311 && ptMouse.y <= int32_t(rcWindow.top +
caption_height * scaling_factor)) {
2319 case WM_DISPLAYCHANGE:
2322 BeginPaint(hwnd, &ps);
2326 EndPaint(hwnd, &ps);
2333 if(GetKeyState(VK_CONTROL) & 0x8000) {
2334 if(wParam == L
'v' || wParam == L
'V') {
2335 if(!IsClipboardFormatAvailable(CF_TEXT))
2337 if(!OpenClipboard(m_hwnd))
2340 auto hglb = GetClipboardData(CF_TEXT);
2341 if(hglb !=
nullptr) {
2342 auto lptstr = GlobalLock(hglb);
2343 if(lptstr !=
nullptr) {
2344 std::string cb_data((
char*)lptstr);
2345 while(cb_data.length() > 0 && isspace(cb_data.back())) {
2358 if(GetKeyState(VK_CONTROL) & 0x8000) {
2364 if(turned_into ==
'\b') {
2365 if(!ip_addr.empty())
2367 }
else if(turned_into >= 32 && turned_into !=
'\t' && turned_into !=
' ' && ip_addr.size() < 46) {
2368 ip_addr.push_back(turned_into);
2371 if(turned_into ==
'\b') {
2372 if(!player_name.empty()) {
2373 player_name.pop_back();
2376 }
else if(turned_into >= 32 && turned_into !=
'\t' && turned_into !=
' ' && player_name.size() < 24) {
2377 player_name.push_back(turned_into);
2381 if(turned_into ==
'\b') {
2382 if(!password.empty())
2383 password.pop_back();
2384 }
else if(turned_into >= 32 && turned_into !=
'\t' && turned_into !=
' ' && password.size() < 16) {
2385 password.push_back(turned_into);
2390 InvalidateRect((
HWND)(m_hwnd),
nullptr, FALSE);
2397 return DefWindowProc(hwnd, message, wParam, lParam);
2403static CRITICAL_SECTION guard_abort_handler;
2406 static bool run_once =
false;
2408 EnterCriticalSection(&guard_abort_handler);
2409 if(run_once ==
false) {
2413 ZeroMemory(&si,
sizeof(si));
2415 PROCESS_INFORMATION pi;
2416 ZeroMemory(&pi,
sizeof(pi));
2431 LeaveCriticalSection(&guard_abort_handler);
2436 WaitForSingleObject(pi.hProcess, INFINITE);
2438 CloseHandle(pi.hProcess);
2439 CloseHandle(pi.hThread);
2441 LeaveCriticalSection(&guard_abort_handler);
2444LONG WINAPI
uef_wrapper(
struct _EXCEPTION_POINTERS* lpTopLevelExceptionFilter) {
2446 return EXCEPTION_CONTINUE_SEARCH;
2453 const wchar_t* expression,
2454 const wchar_t* function,
2455 const wchar_t* file,
2463 typedef BOOL(WINAPI* tGetPolicy)(LPDWORD lpFlags);
2464 typedef BOOL(WINAPI* tSetPolicy)(DWORD dwFlags);
2465 const DWORD EXCEPTION_SWALLOWING = 0x1;
2467 HMODULE kernel32 = LoadLibraryA(
"kernel32.dll");
2468 tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32,
"GetProcessUserModeExceptionPolicy");
2469 tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32,
"SetProcessUserModeExceptionPolicy");
2470 if(pGetPolicy && pSetPolicy) {
2472 if(pGetPolicy(&dwFlags)) {
2474 pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING);
2477 BOOL insanity = FALSE;
2478 SetUserObjectInformationA(GetCurrentProcess(), UOI_TIMERPROC_EXCEPTION_SUPPRESSION, &insanity,
sizeof(insanity));
2488 HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
2491 InitializeCriticalSection(&guard_abort_handler);
2493 if(!IsDebuggerPresent()) {
2497 _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
2502 SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
2504 if(!SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)))
2507 WNDCLASSEX wcex = { };
2508 wcex.cbSize = UINT(
sizeof(WNDCLASSEX));
2509 wcex.style = CS_OWNDC;
2511 wcex.cbClsExtra = 0;
2512 wcex.cbWndExtra =
sizeof(LONG_PTR);
2513 wcex.hInstance = GetModuleHandle(
nullptr);
2514 wcex.hIcon = (HICON)LoadImage(GetModuleHandleW(
nullptr), MAKEINTRESOURCE(
IDI_ICON1), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0);
2515 wcex.hbrBackground = NULL;
2516 wcex.lpszMenuName = NULL;
2517 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
2518 wcex.lpszClassName =
NATIVE(
"alice_launcher_class");
2520 if(RegisterClassEx(&wcex) == 0) {
2525 char username[256 + 1];
2526 DWORD username_len = 256 + 1;
2527 GetComputerNameA(username, &username_len);
2534 if(contents.file_size >=
sizeof(*p)) {
2535 launcher::player_name = std::string(p->
data);
2539 launcher::player_name = std::to_string(int32_t(rand()));
2542 launcher::m_hwnd = CreateWindowEx(
2544 L
"alice_launcher_class",
2545 L
"Launch Project Alice",
2546 WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_BORDER,
2553 GetModuleHandle(
nullptr),
2557 if(launcher::m_hwnd) {
2559 launcher::dpi = float(GetDpiForWindow((
HWND)(launcher::m_hwnd)));
2561 auto monitor_handle = MonitorFromWindow((
HWND)(launcher::m_hwnd), MONITOR_DEFAULTTOPRIMARY);
2563 mi.cbSize =
sizeof(mi);
2564 GetMonitorInfo(monitor_handle, &mi);
2566 auto vert_space = mi.rcWork.bottom - mi.rcWork.top;
2567 float rough_scale = float(vert_space) / 1080.0f;
2568 if(rough_scale >= 1.0f) {
2569 launcher::scaling_factor = std::round(rough_scale);
2571 launcher::scaling_factor = std::round(rough_scale * 4.0f) / 4.0f;
2575 (
HWND)(launcher::m_hwnd),
2581 SWP_NOMOVE | SWP_FRAMECHANGED);
2584 ShowWindow((
HWND)(launcher::m_hwnd), SW_SHOWNORMAL);
2585 UpdateWindow((
HWND)(launcher::m_hwnd));
2589 while(GetMessage(&msg, NULL, 0, 0)) {
2590 TranslateMessage(&msg);
2591 DispatchMessage(&msg);
GLuint get_texture_handle() const
std::string accumulated_errors
std::string accumulated_warnings
void load_font(font &fnt, char const *file_data, uint32_t file_size)
ankerl::unordered_dense::map< char32_t, glyph_sub_offset > glyph_positions
void make_glyph(char32_t ch_in)
std::vector< uint32_t > textures
#define assert(condition)
native_string produce_mod_path()
void enforce_list_order()
bool transitively_depends_on(parsers::mod_file const &moda, parsers::mod_file const &modb)
void find_scenario_file()
native_string to_hex(uint64_t v)
void EnableCrashingOnCrashes()
void signal_abort_handler(int)
LONG WINAPI uef_wrapper(struct _EXCEPTION_POINTERS *lpTopLevelExceptionFilter)
void invalid_parameter_wrapper(const wchar_t *expression, const wchar_t *function, const wchar_t *file, unsigned int line, uintptr_t pReserved)
int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
constexpr GLuint atlas_index
void render_new_text(std::string_view sv, color_modification enabled, float x, float y, float size, color3f const &c, ::text::font &f)
void render_textured_rect(color_modification enabled, int32_t ix, int32_t iy, int32_t iwidth, int32_t iheight, GLuint texture_handle, ui::rotation r, bool flipped)
constexpr float base_height
constexpr int32_t ui_obj_list_right
constexpr int32_t ui_list_move_down
constexpr int32_t ui_list_first
constexpr float caption_height
constexpr int32_t ui_obj_password
constexpr float list_text_right_align
constexpr int32_t ui_list_move_up
constexpr int32_t ui_obj_ip_addr
constexpr int32_t ui_row_height
constexpr int32_t ui_obj_close
bool transitively_depends_on(parsers::mod_file const &moda, parsers::mod_file const &modb)
void recursively_remove_from_list(parsers::mod_file &mod)
void recursively_add_to_list(parsers::mod_file &mod)
char process_utf16_to_win1250(wchar_t c)
constexpr int32_t ui_list_checkbox
constexpr int32_t ui_list_count
constexpr float caption_width
bool nth_item_can_move_up(int32_t n)
bool nth_item_can_move_down(int32_t n)
bool is_high_surrogate(uint16_t char_code) noexcept
bool update_under_mouse()
float base_text_extent(char const *codepoints, uint32_t count, int32_t size, text::font &f)
void enforce_list_order()
bool is_low_surrogate(uint16_t char_code) noexcept
constexpr ui_active_rect ui_rects[]
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
constexpr int32_t ui_obj_host_game
constexpr int32_t ui_obj_create_scenario
constexpr int32_t ui_obj_list_left
bool transitively_depends_on_internal(parsers::mod_file const &moda, parsers::mod_file const &modb, std::vector< bool > &seen_indices)
constexpr int32_t ui_obj_player_name
void create_opengl_context()
constexpr int32_t ui_list_end
constexpr float base_width
constexpr int32_t ui_obj_play_game
constexpr int32_t ui_obj_join_game
constexpr GLuint piechart
constexpr GLuint interactable
constexpr GLuint frame_stretch
constexpr GLuint no_filter
constexpr GLuint progress_bar
constexpr GLuint use_mask
constexpr GLuint screen_width
constexpr GLuint subsprite_b
constexpr GLuint barchart
constexpr GLuint inner_color
constexpr GLuint disabled
constexpr GLuint screen_height
constexpr GLuint drawing_rectangle
constexpr GLuint border_size
constexpr GLuint linegraph
constexpr GLuint interactable_disabled
constexpr GLuint border_filter
constexpr GLuint sub_sprite
void internal_text_render(sys::state &state, text::stored_glyphs const &txt, float x, float baseline_y, float size, text::font &f)
void render_new_text(sys::state &state, text::stored_glyphs const &txt, color_modification enabled, float x, float y, float size, color3f const &c, text::font &f)
auto map_color_modification_to_index(color_modification e)
void bind_vertices_by_rotation(sys::state const &state, ui::rotation r, bool flipped, bool rtl)
GLuint load_file_and_return_handle(native_string const &native_name, simple_fs::file_system const &fs, texture &asset_texture, bool keep_data)
void render_textured_rect(sys::state const &state, color_modification enabled, float x, float y, float width, float height, GLuint texture_handle, ui::rotation r, bool flipped, bool rtl)
std::vector< unopened_file > list_files(directory const &dir, native_char const *extension)
void add_root(file_system &fs, native_string_view root_path)
directory open_directory(directory const &dir, native_string_view directory_name)
native_string utf8_to_native(std::string_view data_in)
native_string extract_state(file_system const &fs)
void restore_state(file_system &fs, native_string_view data)
void write_file(directory const &dir, native_string_view file_name, char const *file_data, uint32_t file_size)
directory get_or_create_settings_directory()
native_string get_full_name(directory const &f)
std::optional< file > open_file(directory const &dir, native_string_view file_name)
std::optional< unopened_file > peek_file(directory const &dir, native_string_view file_name)
file_contents view_contents(file const &f)
native_string get_file_name(unopened_file const &f)
directory get_or_create_scenario_directory()
mod_identifier extract_mod_information(uint8_t const *ptr_in, uint64_t file_size)
void write_scenario_file(sys::state &state, native_string_view name, uint32_t count)
void write_save_file(sys::state &state, save_type type, std::string const &name)
constexpr int magnification_factor
void emit_error_message(std::string const &content, bool fatal)
std::string native_string
sys::mod_identifier ident
std::vector< bookmark_definition > bookmark_dates
std::vector< std::string > dependent_mods