mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-15 19:13:07 +01:00
Move more platform functions (#16416)
* Upgrade platform_get_locale_measurement_format()
* Upgrade platform_get_locale_date_format()
* Upgrade platform_get_locale_temperature_format()
* Move platform_directory_delete() to Path
* Upgrade platform_process_is_elevated()
* Move platform_update_palette() to Drawing.cpp
* Upgrade platform_get_steam_dir()
* Upgrade platform_get_font_path()
* Remove now-empty platform files
* Fix formatting
* Upgrade platform_get_default_scale()
* Move remaining stuff in Android.cpp
* Use return {} instead of return ""
This commit is contained in:
@@ -430,7 +430,7 @@ namespace OpenRCT2
|
||||
}
|
||||
#endif
|
||||
|
||||
if (platform_process_is_elevated())
|
||||
if (Platform::ProcessIsElevated())
|
||||
{
|
||||
std::string elevationWarning = _localisationService->GetString(STR_ADMIN_NOT_RECOMMENDED);
|
||||
if (gOpenRCT2Headless)
|
||||
|
||||
@@ -167,7 +167,7 @@ void update_palette_effects()
|
||||
paletteOffset[(i * 4) + 1] = -((0xFF - g1->offset[(i * 3) + 1]) / 2) - 1;
|
||||
paletteOffset[(i * 4) + 2] = -((0xFF - g1->offset[(i * 3) + 2]) / 2) - 1;
|
||||
}
|
||||
platform_update_palette(gGamePalette, PALETTE_OFFSET_DYNAMIC, PALETTE_LENGTH_DYNAMIC);
|
||||
UpdatePalette(gGamePalette, PALETTE_OFFSET_DYNAMIC, PALETTE_LENGTH_DYNAMIC);
|
||||
}
|
||||
gClimateLightningFlash++;
|
||||
}
|
||||
@@ -286,10 +286,10 @@ void update_palette_effects()
|
||||
}
|
||||
}
|
||||
|
||||
platform_update_palette(gGamePalette, PALETTE_OFFSET_ANIMATED, PALETTE_LENGTH_ANIMATED);
|
||||
UpdatePalette(gGamePalette, PALETTE_OFFSET_ANIMATED, PALETTE_LENGTH_ANIMATED);
|
||||
if (gClimateLightningFlash == 2)
|
||||
{
|
||||
platform_update_palette(gGamePalette, PALETTE_OFFSET_DYNAMIC, PALETTE_LENGTH_DYNAMIC);
|
||||
UpdatePalette(gGamePalette, PALETTE_OFFSET_DYNAMIC, PALETTE_LENGTH_DYNAMIC);
|
||||
gClimateLightningFlash = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,13 +166,13 @@ namespace Config
|
||||
model->landscape_smoothing = reader->GetBoolean("landscape_smoothing", true);
|
||||
model->language = reader->GetEnum<int32_t>("language", Platform::GetLocaleLanguage(), Enum_LanguageEnum);
|
||||
model->measurement_format = reader->GetEnum<MeasurementFormat>(
|
||||
"measurement_format", platform_get_locale_measurement_format(), Enum_MeasurementFormat);
|
||||
"measurement_format", Platform::GetLocaleMeasurementFormat(), Enum_MeasurementFormat);
|
||||
model->play_intro = reader->GetBoolean("play_intro", false);
|
||||
model->save_plugin_data = reader->GetBoolean("save_plugin_data", true);
|
||||
model->debugging_tools = reader->GetBoolean("debugging_tools", false);
|
||||
model->show_height_as_units = reader->GetBoolean("show_height_as_units", false);
|
||||
model->temperature_format = reader->GetEnum<TemperatureUnit>(
|
||||
"temperature_format", platform_get_locale_temperature_format(), Enum_Temperature);
|
||||
"temperature_format", Platform::GetLocaleTemperatureFormat(), Enum_Temperature);
|
||||
model->window_height = reader->GetInt32("window_height", -1);
|
||||
model->window_snap_proximity = reader->GetInt32("window_snap_proximity", 5);
|
||||
model->window_width = reader->GetInt32("window_width", -1);
|
||||
@@ -183,7 +183,7 @@ namespace Config
|
||||
model->use_vsync = reader->GetBoolean("use_vsync", true);
|
||||
model->virtual_floor_style = reader->GetEnum<VirtualFloorStyles>(
|
||||
"virtual_floor_style", VirtualFloorStyles::Glassy, Enum_VirtualFloorStyle);
|
||||
model->date_format = reader->GetEnum<int32_t>("date_format", platform_get_locale_date_format(), Enum_DateFormat);
|
||||
model->date_format = reader->GetEnum<int32_t>("date_format", Platform::GetLocaleDateFormat(), Enum_DateFormat);
|
||||
model->auto_staff_placement = reader->GetBoolean("auto_staff", true);
|
||||
model->handymen_mow_default = reader->GetBoolean("handymen_mow_default", false);
|
||||
model->default_inspection_interval = reader->GetInt32("default_inspection_interval", 2);
|
||||
@@ -202,7 +202,7 @@ namespace Config
|
||||
model->disable_lightning_effect = reader->GetBoolean("disable_lightning_effect", false);
|
||||
model->allow_loading_with_incorrect_checksum = reader->GetBoolean("allow_loading_with_incorrect_checksum", true);
|
||||
model->steam_overlay_pause = reader->GetBoolean("steam_overlay_pause", true);
|
||||
model->window_scale = reader->GetFloat("window_scale", platform_get_default_scale());
|
||||
model->window_scale = reader->GetFloat("window_scale", Platform::GetDefaultScale());
|
||||
model->scale_quality = reader->GetEnum<ScaleQuality>(
|
||||
"scale_quality", ScaleQuality::SmoothNearestNeighbour, Enum_ScaleQuality);
|
||||
model->show_fps = reader->GetBoolean("show_fps", false);
|
||||
@@ -652,8 +652,8 @@ namespace Config
|
||||
}
|
||||
}
|
||||
|
||||
utf8 steamPath[2048] = { 0 };
|
||||
if (platform_get_steam_path(steamPath, sizeof(steamPath)))
|
||||
auto steamPath = Platform::GetSteamPath();
|
||||
if (!steamPath.empty())
|
||||
{
|
||||
std::string location = Path::Combine(steamPath, platform_get_rct1_steam_dir());
|
||||
if (RCT1DataPresentAtLocation(location.c_str()))
|
||||
@@ -701,8 +701,8 @@ namespace Config
|
||||
}
|
||||
}
|
||||
|
||||
utf8 steamPath[2048] = { 0 };
|
||||
if (platform_get_steam_path(steamPath, sizeof(steamPath)))
|
||||
auto steamPath = Platform::GetSteamPath();
|
||||
if (!steamPath.empty())
|
||||
{
|
||||
std::string location = Path::Combine(steamPath, platform_get_rct2_steam_dir());
|
||||
if (Platform::OriginalGameDataExists(location))
|
||||
|
||||
@@ -104,4 +104,9 @@ namespace Path
|
||||
{
|
||||
return Platform::ResolveCasing(path, File::Exists(path));
|
||||
}
|
||||
|
||||
bool DeleteDirectory(std::string_view path)
|
||||
{
|
||||
return fs::remove_all(u8path(path)) > 0;
|
||||
}
|
||||
} // namespace Path
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace Path
|
||||
std::string GetDirectory(std::string_view path);
|
||||
void CreateDirectory(std::string_view path);
|
||||
bool DirectoryExists(std::string_view path);
|
||||
bool DeleteDirectory(std::string_view path);
|
||||
std::string GetFileName(std::string_view origPath);
|
||||
std::string GetFileNameWithoutExtension(std::string_view path);
|
||||
std::string GetExtension(std::string_view path);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
# include "../platform/Platform2.h"
|
||||
# include "../platform/platform.h"
|
||||
# include "IStream.hpp"
|
||||
# include "MemoryStream.h"
|
||||
@@ -30,7 +31,7 @@ public:
|
||||
// retrieve the JNI environment.
|
||||
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||
|
||||
jclass jniClass = platform_android_find_class(env, "io/openrct2/ZipArchive");
|
||||
jclass jniClass = Platform::AndroidFindClass(env, "io/openrct2/ZipArchive");
|
||||
jmethodID constructor = env->GetMethodID(jniClass, "<init>", "(Ljava/lang/String;)V");
|
||||
|
||||
jstring jniPath = env->NewStringUTF(path.data());
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Drawing.h"
|
||||
|
||||
#include "../Context.h"
|
||||
#include "../Game.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../common.h"
|
||||
#include "../core/Guard.hpp"
|
||||
@@ -17,8 +18,10 @@
|
||||
#include "../platform/platform.h"
|
||||
#include "../sprites.h"
|
||||
#include "../util/Util.h"
|
||||
#include "../world/Climate.h"
|
||||
#include "../world/Location.hpp"
|
||||
#include "../world/Water.h"
|
||||
#include "LightFX.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
@@ -600,7 +603,7 @@ void gfx_transpose_palette(int32_t pal, uint8_t product)
|
||||
source_pointer += 3;
|
||||
dest_pointer += 4;
|
||||
}
|
||||
platform_update_palette(gGamePalette, 10, 236);
|
||||
UpdatePalette(gGamePalette, 10, 236);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -641,7 +644,7 @@ void load_palette()
|
||||
dst += 4;
|
||||
}
|
||||
}
|
||||
platform_update_palette(gGamePalette, 10, 236);
|
||||
UpdatePalette(gGamePalette, 10, 236);
|
||||
gfx_invalidate_screen();
|
||||
}
|
||||
|
||||
@@ -787,3 +790,49 @@ FilterPaletteID GetGlassPaletteId(colour_t c)
|
||||
{
|
||||
return GlassPaletteIds[c];
|
||||
}
|
||||
|
||||
void UpdatePalette(const uint8_t* colours, int32_t start_index, int32_t num_colours)
|
||||
{
|
||||
colours += start_index * 4;
|
||||
|
||||
for (int32_t i = start_index; i < num_colours + start_index; i++)
|
||||
{
|
||||
uint8_t r = colours[2];
|
||||
uint8_t g = colours[1];
|
||||
uint8_t b = colours[0];
|
||||
|
||||
#ifdef __ENABLE_LIGHTFX__
|
||||
if (lightfx_is_available())
|
||||
{
|
||||
lightfx_apply_palette_filter(i, &r, &g, &b);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
float night = gDayNightCycle;
|
||||
if (night >= 0 && gClimateLightningFlash == 0)
|
||||
{
|
||||
r = lerp(r, soft_light(r, 8), night);
|
||||
g = lerp(g, soft_light(g, 8), night);
|
||||
b = lerp(b, soft_light(b, 128), night);
|
||||
}
|
||||
}
|
||||
|
||||
gPalette[i].Red = r;
|
||||
gPalette[i].Green = g;
|
||||
gPalette[i].Blue = b;
|
||||
gPalette[i].Alpha = 0;
|
||||
colours += 4;
|
||||
}
|
||||
|
||||
// Fix #1749 and #6535: rainbow path, donut shop and pause button contain black spots that should be white.
|
||||
gPalette[255].Alpha = 0;
|
||||
gPalette[255].Red = 255;
|
||||
gPalette[255].Green = 255;
|
||||
gPalette[255].Blue = 255;
|
||||
|
||||
if (!gOpenRCT2Headless)
|
||||
{
|
||||
drawing_engine_set_palette(gPalette);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -599,5 +599,6 @@ extern void (*mask_fn)(
|
||||
|
||||
std::optional<uint32_t> GetPaletteG1Index(colour_t paletteId);
|
||||
std::optional<PaletteMap> GetPaletteMapForColour(colour_t paletteId);
|
||||
void UpdatePalette(const uint8_t* colours, int32_t start_index, int32_t num_colours);
|
||||
|
||||
#include "NewDrawing.h"
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
# include "../core/String.hpp"
|
||||
# include "../localisation/Localisation.h"
|
||||
# include "../localisation/LocalisationService.h"
|
||||
# include "../platform/Platform2.h"
|
||||
# include "../platform/platform.h"
|
||||
# include "TTF.h"
|
||||
|
||||
@@ -125,17 +126,17 @@ bool ttf_initialise()
|
||||
{
|
||||
TTFFontDescriptor* fontDesc = &(gCurrentTTFFontSet->size[i]);
|
||||
|
||||
utf8 fontPath[MAX_PATH];
|
||||
if (!platform_get_font_path(fontDesc, fontPath, sizeof(fontPath)))
|
||||
auto fontPath = Platform::GetFontPath(*fontDesc);
|
||||
if (fontPath.empty())
|
||||
{
|
||||
log_verbose("Unable to load font '%s'", fontDesc->font_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
fontDesc->font = ttf_open_font(fontPath, fontDesc->ptSize);
|
||||
fontDesc->font = ttf_open_font(fontPath.c_str(), fontDesc->ptSize);
|
||||
if (fontDesc->font == nullptr)
|
||||
{
|
||||
log_verbose("Unable to load '%s'", fontPath);
|
||||
log_verbose("Unable to load '%s'", fontPath.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,9 +783,7 @@
|
||||
<ClCompile Include="peep\PeepData.cpp" />
|
||||
<ClCompile Include="peep\RideUseSystem.cpp" />
|
||||
<ClCompile Include="PlatformEnvironment.cpp" />
|
||||
<ClCompile Include="platform\Android.cpp" />
|
||||
<ClCompile Include="platform\Crash.cpp" />
|
||||
<ClCompile Include="platform\Linux.cpp" />
|
||||
<ClCompile Include="platform\Platform.Android.cpp" />
|
||||
<ClCompile Include="platform\Platform.Linux.cpp" />
|
||||
<ClCompile Include="platform\Platform.Posix.cpp" />
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2020 OpenRCT2 developers
|
||||
*
|
||||
* For a complete list of all authors, please refer to contributors.md
|
||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
# include "../config/Config.h"
|
||||
# include "../localisation/Language.h"
|
||||
# include "../util/Util.h"
|
||||
# include "platform.h"
|
||||
|
||||
# include <SDL.h>
|
||||
# include <jni.h>
|
||||
# include <wchar.h>
|
||||
|
||||
# ifndef NO_TTF
|
||||
bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size)
|
||||
{
|
||||
STUB();
|
||||
return false;
|
||||
}
|
||||
# endif
|
||||
|
||||
MeasurementFormat platform_get_locale_measurement_format()
|
||||
{
|
||||
return MeasurementFormat::Metric;
|
||||
}
|
||||
|
||||
float platform_get_default_scale()
|
||||
{
|
||||
JNIEnv* env = static_cast<JNIEnv*>(SDL_AndroidGetJNIEnv());
|
||||
|
||||
jobject activity = static_cast<jobject>(SDL_AndroidGetActivity());
|
||||
jclass activityClass = env->GetObjectClass(activity);
|
||||
jmethodID getDefaultScale = env->GetMethodID(activityClass, "getDefaultScale", "()F");
|
||||
|
||||
jfloat displayScale = env->CallFloatMethod(activity, getDefaultScale);
|
||||
|
||||
env->DeleteLocalRef(activity);
|
||||
env->DeleteLocalRef(activityClass);
|
||||
|
||||
return displayScale;
|
||||
}
|
||||
|
||||
bool platform_get_steam_path(utf8* outPath, size_t outSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AndroidClassLoader::AndroidClassLoader()
|
||||
{
|
||||
log_info("Obtaining JNI class loader");
|
||||
|
||||
// This is a workaround to be able to call JNI's ClassLoader from non-main
|
||||
// thread, based on https://stackoverflow.com/a/16302771
|
||||
|
||||
// Apparently it's OK to use it from across different thread, but JNI
|
||||
// only looks for ClassLoader in the _current_ thread and fails to find
|
||||
// it when searched for from a native library's non-main thread.
|
||||
|
||||
// The solution below works by obtaining a ClassLoader reference in main
|
||||
// thread and caching it for future use from any thread, instead of using
|
||||
// it via env->FindClass(). ClassLoader itself is abstract, so we cannot
|
||||
// create it directly; instead we take an arbitrary class and call
|
||||
// getClassLoader() on it to create a reference that way.
|
||||
|
||||
// If we're here, SDL's JNI_OnLoad has already been called and set env
|
||||
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||
|
||||
// Take an arbitrary class. While the class does not really matter, it
|
||||
// makes sense to use one that's most likely already loaded and is unlikely
|
||||
// to be removed from code.
|
||||
auto randomClass = env->FindClass("io/openrct2/MainActivity");
|
||||
jclass classClass = env->GetObjectClass(randomClass);
|
||||
|
||||
// Get its class loader
|
||||
auto classLoaderClass = env->FindClass("java/lang/ClassLoader");
|
||||
auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
|
||||
|
||||
// Store the class loader and its findClass method for future use
|
||||
_classLoader = env->NewGlobalRef(env->CallObjectMethod(randomClass, getClassLoaderMethod));
|
||||
_findClassMethod = env->GetMethodID(classLoaderClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
}
|
||||
|
||||
AndroidClassLoader::~AndroidClassLoader()
|
||||
{
|
||||
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||
env->DeleteGlobalRef(_classLoader);
|
||||
}
|
||||
|
||||
jobject AndroidClassLoader::_classLoader;
|
||||
jmethodID AndroidClassLoader::_findClassMethod;
|
||||
|
||||
static std::shared_ptr<AndroidClassLoader> acl;
|
||||
|
||||
void platform_android_init_class_loader()
|
||||
{
|
||||
acl = std::make_shared<AndroidClassLoader>();
|
||||
}
|
||||
|
||||
jclass platform_android_find_class(JNIEnv* env, const char* name)
|
||||
{
|
||||
return static_cast<jclass>(
|
||||
env->CallObjectMethod(AndroidClassLoader::_classLoader, AndroidClassLoader::_findClassMethod, env->NewStringUTF(name)));
|
||||
}
|
||||
#endif
|
||||
@@ -1,168 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2020 OpenRCT2 developers
|
||||
*
|
||||
* For a complete list of all authors, please refer to contributors.md
|
||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
// Despite the name, this file contains support for more OSs besides Linux, provided the necessary ifdefs remain small.
|
||||
// Otherwise, they should be spun off into their own files.
|
||||
#if defined(__unix__) && !defined(__ANDROID__) && !defined(__APPLE__)
|
||||
|
||||
# ifdef __FreeBSD__
|
||||
# include <sys/sysctl.h>
|
||||
# endif
|
||||
|
||||
# include <cstring>
|
||||
# include <ctype.h>
|
||||
# include <dlfcn.h>
|
||||
# include <errno.h>
|
||||
# ifndef NO_TTF
|
||||
# include <fontconfig/fontconfig.h>
|
||||
# endif // NO_TTF
|
||||
# include "../config/Config.h"
|
||||
# include "../core/File.h"
|
||||
# include "../core/Path.hpp"
|
||||
# include "../localisation/Language.h"
|
||||
# include "../localisation/StringIds.h"
|
||||
# include "../util/Util.h"
|
||||
# include "platform.h"
|
||||
|
||||
# include <fnmatch.h>
|
||||
# include <locale.h>
|
||||
# include <pwd.h>
|
||||
|
||||
MeasurementFormat platform_get_locale_measurement_format()
|
||||
{
|
||||
// LC_MEASUREMENT is GNU specific.
|
||||
# ifdef LC_MEASUREMENT
|
||||
const char* langstring = setlocale(LC_MEASUREMENT, "");
|
||||
# else
|
||||
const char* langstring = setlocale(LC_ALL, "");
|
||||
# endif
|
||||
|
||||
if (langstring != nullptr)
|
||||
{
|
||||
// using https://en.wikipedia.org/wiki/Metrication#Chronology_and_status_of_conversion_by_country as reference
|
||||
if (!fnmatch("*_US*", langstring, 0) || !fnmatch("*_MM*", langstring, 0) || !fnmatch("*_LR*", langstring, 0))
|
||||
{
|
||||
return MeasurementFormat::Imperial;
|
||||
}
|
||||
}
|
||||
return MeasurementFormat::Metric;
|
||||
}
|
||||
|
||||
bool platform_get_steam_path(utf8* outPath, size_t outSize)
|
||||
{
|
||||
const char* steamRoot = getenv("STEAMROOT");
|
||||
if (steamRoot != nullptr)
|
||||
{
|
||||
safe_strcpy(outPath, steamRoot, outSize);
|
||||
safe_strcat_path(outPath, "ubuntu12_32/steamapps/content", outSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
char steamPath[1024] = { 0 };
|
||||
const char* localSharePath = getenv("XDG_DATA_HOME");
|
||||
if (localSharePath != nullptr)
|
||||
{
|
||||
safe_strcpy(steamPath, localSharePath, sizeof(steamPath));
|
||||
safe_strcat_path(steamPath, "Steam/ubuntu12_32/steamapps/content", sizeof(steamPath));
|
||||
if (Path::DirectoryExists(steamPath))
|
||||
{
|
||||
safe_strcpy(outPath, steamPath, outSize);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const char* homeDir = getpwuid(getuid())->pw_dir;
|
||||
if (homeDir != nullptr)
|
||||
{
|
||||
safe_strcpy(steamPath, homeDir, sizeof(steamPath));
|
||||
safe_strcat_path(steamPath, ".local/share/Steam/ubuntu12_32/steamapps/content", sizeof(steamPath));
|
||||
if (Path::DirectoryExists(steamPath))
|
||||
{
|
||||
safe_strcpy(outPath, steamPath, outSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::fill_n(steamPath, sizeof(steamPath), 0x00);
|
||||
safe_strcpy(steamPath, homeDir, sizeof(steamPath));
|
||||
safe_strcat_path(steamPath, ".steam/steam/ubuntu12_32/steamapps/content", sizeof(steamPath));
|
||||
if (Path::DirectoryExists(steamPath))
|
||||
{
|
||||
safe_strcpy(outPath, steamPath, outSize);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
# ifndef NO_TTF
|
||||
bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size)
|
||||
{
|
||||
assert(buffer != nullptr);
|
||||
assert(font != nullptr);
|
||||
|
||||
log_verbose("Looking for font %s with FontConfig.", font->font_name);
|
||||
FcConfig* config = FcInitLoadConfigAndFonts();
|
||||
if (!config)
|
||||
{
|
||||
log_error("Failed to initialize FontConfig library");
|
||||
FcFini();
|
||||
return false;
|
||||
}
|
||||
|
||||
FcPattern* pat = FcNameParse(reinterpret_cast<const FcChar8*>(font->font_name));
|
||||
|
||||
FcConfigSubstitute(config, pat, FcMatchPattern);
|
||||
FcDefaultSubstitute(pat);
|
||||
|
||||
bool found = false;
|
||||
FcResult result = FcResultNoMatch;
|
||||
FcPattern* match = FcFontMatch(config, pat, &result);
|
||||
|
||||
if (match)
|
||||
{
|
||||
bool is_substitute = false;
|
||||
|
||||
// FontConfig implicitly falls back to any default font it is configured to handle.
|
||||
// In our implementation, this cannot account for supported character sets, leading
|
||||
// to unrendered characters (tofu) when trying to render e.g. CJK characters using a
|
||||
// Western (sans-)serif font. We therefore ignore substitutions FontConfig provides,
|
||||
// and instead rely on exact matches on the fonts predefined for each font family.
|
||||
FcChar8* matched_font_face = nullptr;
|
||||
if (FcPatternGetString(match, FC_FULLNAME, 0, &matched_font_face) == FcResultMatch
|
||||
&& strcmp(font->font_name, reinterpret_cast<const char*>(matched_font_face)) != 0)
|
||||
{
|
||||
log_verbose("FontConfig provided substitute font %s -- disregarding.", matched_font_face);
|
||||
is_substitute = true;
|
||||
}
|
||||
|
||||
FcChar8* filename = nullptr;
|
||||
if (!is_substitute && FcPatternGetString(match, FC_FILE, 0, &filename) == FcResultMatch)
|
||||
{
|
||||
found = true;
|
||||
safe_strcpy(buffer, reinterpret_cast<utf8*>(filename), size);
|
||||
log_verbose("FontConfig provided font %s", filename);
|
||||
}
|
||||
|
||||
FcPatternDestroy(match);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_warning("Failed to find required font.");
|
||||
}
|
||||
|
||||
FcPatternDestroy(pat);
|
||||
FcConfigDestroy(config);
|
||||
FcFini();
|
||||
return found;
|
||||
}
|
||||
# endif // NO_TTF
|
||||
|
||||
#endif
|
||||
@@ -13,6 +13,20 @@
|
||||
# include "../localisation/Language.h"
|
||||
# include "Platform2.h"
|
||||
|
||||
# include <SDL.h>
|
||||
# include <jni.h>
|
||||
|
||||
AndroidClassLoader::~AndroidClassLoader()
|
||||
{
|
||||
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||
env->DeleteGlobalRef(_classLoader);
|
||||
}
|
||||
|
||||
jobject AndroidClassLoader::_classLoader;
|
||||
jmethodID AndroidClassLoader::_findClassMethod;
|
||||
|
||||
static std::shared_ptr<AndroidClassLoader> acl;
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
std::string GetFolderPath(SPECIAL_FOLDER folder)
|
||||
@@ -65,6 +79,87 @@ namespace Platform
|
||||
{
|
||||
return Platform::GetCurrencyValue(NULL);
|
||||
}
|
||||
|
||||
MeasurementFormat GetLocaleMeasurementFormat()
|
||||
{
|
||||
return MeasurementFormat::Metric;
|
||||
}
|
||||
|
||||
std::string GetSteamPath()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
# ifndef NO_TTF
|
||||
std::string GetFontPath(const TTFFontDescriptor& font)
|
||||
{
|
||||
STUB();
|
||||
return {};
|
||||
}
|
||||
# endif
|
||||
|
||||
float GetDefaultScale()
|
||||
{
|
||||
JNIEnv* env = static_cast<JNIEnv*>(SDL_AndroidGetJNIEnv());
|
||||
|
||||
jobject activity = static_cast<jobject>(SDL_AndroidGetActivity());
|
||||
jclass activityClass = env->GetObjectClass(activity);
|
||||
jmethodID getDefaultScale = env->GetMethodID(activityClass, "getDefaultScale", "()F");
|
||||
|
||||
jfloat displayScale = env->CallFloatMethod(activity, getDefaultScale);
|
||||
|
||||
env->DeleteLocalRef(activity);
|
||||
env->DeleteLocalRef(activityClass);
|
||||
|
||||
return displayScale;
|
||||
}
|
||||
|
||||
void AndroidInitClassLoader()
|
||||
{
|
||||
acl = std::make_shared<AndroidClassLoader>();
|
||||
}
|
||||
|
||||
jclass AndroidFindClass(JNIEnv* env, std::string_view name)
|
||||
{
|
||||
return static_cast<jclass>(env->CallObjectMethod(
|
||||
AndroidClassLoader::_classLoader, AndroidClassLoader::_findClassMethod,
|
||||
env->NewStringUTF(std::string(name).c_str())));
|
||||
}
|
||||
} // namespace Platform
|
||||
|
||||
AndroidClassLoader::AndroidClassLoader()
|
||||
{
|
||||
log_info("Obtaining JNI class loader");
|
||||
|
||||
// This is a workaround to be able to call JNI's ClassLoader from non-main
|
||||
// thread, based on https://stackoverflow.com/a/16302771
|
||||
|
||||
// Apparently it's OK to use it from across different thread, but JNI
|
||||
// only looks for ClassLoader in the _current_ thread and fails to find
|
||||
// it when searched for from a native library's non-main thread.
|
||||
|
||||
// The solution below works by obtaining a ClassLoader reference in main
|
||||
// thread and caching it for future use from any thread, instead of using
|
||||
// it via env->FindClass(). ClassLoader itself is abstract, so we cannot
|
||||
// create it directly; instead we take an arbitrary class and call
|
||||
// getClassLoader() on it to create a reference that way.
|
||||
|
||||
// If we're here, SDL's JNI_OnLoad has already been called and set env
|
||||
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||
|
||||
// Take an arbitrary class. While the class does not really matter, it
|
||||
// makes sense to use one that's most likely already loaded and is unlikely
|
||||
// to be removed from code.
|
||||
auto randomClass = env->FindClass("io/openrct2/MainActivity");
|
||||
jclass classClass = env->GetObjectClass(randomClass);
|
||||
|
||||
// Get its class loader
|
||||
auto classLoaderClass = env->FindClass("java/lang/ClassLoader");
|
||||
auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
|
||||
|
||||
// Store the class loader and its findClass method for future use
|
||||
_classLoader = env->NewGlobalRef(env->CallObjectMethod(randomClass, getClassLoaderMethod));
|
||||
_findClassMethod = env->GetMethodID(classLoaderClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
# include <cstring>
|
||||
# include <fnmatch.h>
|
||||
# include <limits.h>
|
||||
# include <locale.h>
|
||||
# include <pwd.h>
|
||||
# include <vector>
|
||||
# if defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
@@ -23,6 +24,10 @@
|
||||
// for PATH_MAX
|
||||
# include <linux/limits.h>
|
||||
# endif // __linux__
|
||||
# ifndef NO_TTF
|
||||
# include <fontconfig/fontconfig.h>
|
||||
# endif // NO_TTF
|
||||
|
||||
# include "../OpenRCT2.h"
|
||||
# include "../core/Path.hpp"
|
||||
# include "../localisation/Language.h"
|
||||
@@ -250,6 +255,122 @@ namespace Platform
|
||||
|
||||
return Platform::GetCurrencyValue(lc->int_curr_symbol);
|
||||
}
|
||||
|
||||
MeasurementFormat GetLocaleMeasurementFormat()
|
||||
{
|
||||
// LC_MEASUREMENT is GNU specific.
|
||||
# ifdef LC_MEASUREMENT
|
||||
const char* langstring = setlocale(LC_MEASUREMENT, "");
|
||||
# else
|
||||
const char* langstring = setlocale(LC_ALL, "");
|
||||
# endif
|
||||
|
||||
if (langstring != nullptr)
|
||||
{
|
||||
// using https://en.wikipedia.org/wiki/Metrication#Chronology_and_status_of_conversion_by_country as reference
|
||||
if (!fnmatch("*_US*", langstring, 0) || !fnmatch("*_MM*", langstring, 0) || !fnmatch("*_LR*", langstring, 0))
|
||||
{
|
||||
return MeasurementFormat::Imperial;
|
||||
}
|
||||
}
|
||||
return MeasurementFormat::Metric;
|
||||
}
|
||||
|
||||
std::string GetSteamPath()
|
||||
{
|
||||
const char* steamRoot = getenv("STEAMROOT");
|
||||
if (steamRoot != nullptr)
|
||||
{
|
||||
return Path::Combine(steamRoot, "ubuntu12_32/steamapps/content");
|
||||
}
|
||||
|
||||
const char* localSharePath = getenv("XDG_DATA_HOME");
|
||||
if (localSharePath != nullptr)
|
||||
{
|
||||
auto steamPath = Path::Combine(localSharePath, "Steam/ubuntu12_32/steamapps/content");
|
||||
if (Path::DirectoryExists(steamPath))
|
||||
{
|
||||
return steamPath;
|
||||
}
|
||||
}
|
||||
|
||||
const char* homeDir = getpwuid(getuid())->pw_dir;
|
||||
if (homeDir == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto steamPath = Path::Combine(homeDir, ".local/share/Steam/ubuntu12_32/steamapps/content");
|
||||
if (Path::DirectoryExists(steamPath))
|
||||
{
|
||||
return steamPath;
|
||||
}
|
||||
|
||||
steamPath = Path::Combine(homeDir, ".steam/steam/ubuntu12_32/steamapps/content");
|
||||
if (Path::DirectoryExists(steamPath))
|
||||
{
|
||||
return steamPath;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string GetFontPath(const TTFFontDescriptor& font)
|
||||
{
|
||||
log_verbose("Looking for font %s with FontConfig.", font.font_name);
|
||||
FcConfig* config = FcInitLoadConfigAndFonts();
|
||||
if (!config)
|
||||
{
|
||||
log_error("Failed to initialize FontConfig library");
|
||||
FcFini();
|
||||
return {};
|
||||
}
|
||||
|
||||
FcPattern* pat = FcNameParse(reinterpret_cast<const FcChar8*>(font.font_name));
|
||||
|
||||
FcConfigSubstitute(config, pat, FcMatchPattern);
|
||||
FcDefaultSubstitute(pat);
|
||||
|
||||
std::string path = "";
|
||||
FcResult result = FcResultNoMatch;
|
||||
FcPattern* match = FcFontMatch(config, pat, &result);
|
||||
|
||||
if (match)
|
||||
{
|
||||
bool is_substitute = false;
|
||||
|
||||
// FontConfig implicitly falls back to any default font it is configured to handle.
|
||||
// In our implementation, this cannot account for supported character sets, leading
|
||||
// to unrendered characters (tofu) when trying to render e.g. CJK characters using a
|
||||
// Western (sans-)serif font. We therefore ignore substitutions FontConfig provides,
|
||||
// and instead rely on exact matches on the fonts predefined for each font family.
|
||||
FcChar8* matched_font_face = nullptr;
|
||||
if (FcPatternGetString(match, FC_FULLNAME, 0, &matched_font_face) == FcResultMatch
|
||||
&& strcmp(font.font_name, reinterpret_cast<const char*>(matched_font_face)) != 0)
|
||||
{
|
||||
log_verbose("FontConfig provided substitute font %s -- disregarding.", matched_font_face);
|
||||
is_substitute = true;
|
||||
}
|
||||
|
||||
FcChar8* filename = nullptr;
|
||||
if (!is_substitute && FcPatternGetString(match, FC_FILE, 0, &filename) == FcResultMatch)
|
||||
{
|
||||
path = reinterpret_cast<utf8*>(filename);
|
||||
log_verbose("FontConfig provided font %s", filename);
|
||||
}
|
||||
|
||||
FcPatternDestroy(match);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_warning("Failed to find required font.");
|
||||
}
|
||||
|
||||
FcPatternDestroy(pat);
|
||||
FcConfigDestroy(config);
|
||||
FcFini();
|
||||
return path;
|
||||
}
|
||||
} // namespace Platform
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
# include "../core/Memory.hpp"
|
||||
# include "../core/Path.hpp"
|
||||
# include "../core/String.hpp"
|
||||
# include "../localisation/Date.h"
|
||||
# include "Platform2.h"
|
||||
|
||||
# include <cerrno>
|
||||
@@ -22,6 +23,8 @@
|
||||
# include <cstring>
|
||||
# include <ctime>
|
||||
# include <dirent.h>
|
||||
# include <fnmatch.h>
|
||||
# include <locale>
|
||||
# include <pwd.h>
|
||||
# include <sys/stat.h>
|
||||
|
||||
@@ -267,6 +270,55 @@ namespace Platform
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t GetLocaleDateFormat()
|
||||
{
|
||||
const std::time_base::dateorder dateorder = std::use_facet<std::time_get<char>>(std::locale()).date_order();
|
||||
|
||||
switch (dateorder)
|
||||
{
|
||||
case std::time_base::mdy:
|
||||
return DATE_FORMAT_MONTH_DAY_YEAR;
|
||||
|
||||
case std::time_base::ymd:
|
||||
return DATE_FORMAT_YEAR_MONTH_DAY;
|
||||
|
||||
case std::time_base::ydm:
|
||||
return DATE_FORMAT_YEAR_DAY_MONTH;
|
||||
|
||||
default:
|
||||
return DATE_FORMAT_DAY_MONTH_YEAR;
|
||||
}
|
||||
}
|
||||
|
||||
TemperatureUnit GetLocaleTemperatureFormat()
|
||||
{
|
||||
// LC_MEASUREMENT is GNU specific.
|
||||
# ifdef LC_MEASUREMENT
|
||||
const char* langstring = setlocale(LC_MEASUREMENT, "");
|
||||
# else
|
||||
const char* langstring = setlocale(LC_ALL, "");
|
||||
# endif
|
||||
|
||||
if (langstring != nullptr)
|
||||
{
|
||||
if (!fnmatch("*_US*", langstring, 0) || !fnmatch("*_BS*", langstring, 0) || !fnmatch("*_BZ*", langstring, 0)
|
||||
|| !fnmatch("*_PW*", langstring, 0))
|
||||
{
|
||||
return TemperatureUnit::Fahrenheit;
|
||||
}
|
||||
}
|
||||
return TemperatureUnit::Celsius;
|
||||
}
|
||||
|
||||
bool ProcessIsElevated()
|
||||
{
|
||||
# ifndef __EMSCRIPTEN__
|
||||
return (geteuid() == 0);
|
||||
# else
|
||||
return false;
|
||||
# endif // __EMSCRIPTEN__
|
||||
}
|
||||
} // namespace Platform
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,11 +34,13 @@
|
||||
# include "../common.h"
|
||||
# include "../core/Path.hpp"
|
||||
# include "../core/String.hpp"
|
||||
# include "../localisation/Date.h"
|
||||
# include "../localisation/Language.h"
|
||||
# include "Platform2.h"
|
||||
# include "platform.h"
|
||||
|
||||
# include <iterator>
|
||||
# include <locale>
|
||||
|
||||
# if _WIN32_WINNT < 0x600
|
||||
# define swprintf_s(a, b, c, d, ...) swprintf(a, b, c, ##__VA_ARGS__)
|
||||
@@ -707,6 +709,169 @@ namespace Platform
|
||||
|
||||
return Platform::GetCurrencyValue(currCode);
|
||||
}
|
||||
|
||||
MeasurementFormat GetLocaleMeasurementFormat()
|
||||
{
|
||||
UINT measurement_system;
|
||||
if (GetLocaleInfo(
|
||||
LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER, reinterpret_cast<LPSTR>(&measurement_system),
|
||||
sizeof(measurement_system))
|
||||
== 0)
|
||||
{
|
||||
return MeasurementFormat::Metric;
|
||||
}
|
||||
|
||||
switch (measurement_system)
|
||||
{
|
||||
case 1:
|
||||
return MeasurementFormat::Imperial;
|
||||
case 0:
|
||||
default:
|
||||
return MeasurementFormat::Metric;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t GetLocaleDateFormat()
|
||||
{
|
||||
# if _WIN32_WINNT >= 0x0600
|
||||
// Retrieve short date format, eg "MM/dd/yyyy"
|
||||
wchar_t dateFormat[20];
|
||||
if (GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SSHORTDATE, dateFormat, static_cast<int>(std::size(dateFormat)))
|
||||
== 0)
|
||||
{
|
||||
return DATE_FORMAT_DAY_MONTH_YEAR;
|
||||
}
|
||||
|
||||
// The only valid characters for format types are: dgyM
|
||||
// We try to find 3 strings of format types, ignore any characters in between.
|
||||
// We also ignore 'g', as it represents 'era' and we don't have that concept
|
||||
// in our date formats.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd317787(v=vs.85).aspx
|
||||
//
|
||||
wchar_t first[sizeof(dateFormat)];
|
||||
wchar_t second[sizeof(dateFormat)];
|
||||
if (swscanf_s(
|
||||
dateFormat, L"%l[dyM]%*l[^dyM]%l[dyM]%*l[^dyM]%*l[dyM]", first, static_cast<uint32_t>(std::size(first)), second,
|
||||
static_cast<uint32_t>(std::size(second)))
|
||||
!= 2)
|
||||
{
|
||||
return DATE_FORMAT_DAY_MONTH_YEAR;
|
||||
}
|
||||
|
||||
if (wcsncmp(L"d", first, 1) == 0)
|
||||
{
|
||||
return DATE_FORMAT_DAY_MONTH_YEAR;
|
||||
}
|
||||
if (wcsncmp(L"M", first, 1) == 0)
|
||||
{
|
||||
return DATE_FORMAT_MONTH_DAY_YEAR;
|
||||
}
|
||||
if (wcsncmp(L"y", first, 1) == 0)
|
||||
{
|
||||
if (wcsncmp(L"d", second, 1) == 0)
|
||||
{
|
||||
return DATE_FORMAT_YEAR_DAY_MONTH;
|
||||
}
|
||||
|
||||
// Closest possible option
|
||||
return DATE_FORMAT_YEAR_MONTH_DAY;
|
||||
}
|
||||
# endif
|
||||
|
||||
// Default fallback
|
||||
return DATE_FORMAT_DAY_MONTH_YEAR;
|
||||
}
|
||||
|
||||
TemperatureUnit GetLocaleTemperatureFormat()
|
||||
{
|
||||
UINT fahrenheit;
|
||||
|
||||
// GetLocaleInfo will set fahrenheit to 1 if the locale on this computer
|
||||
// uses the United States measurement system or 0 otherwise.
|
||||
if (GetLocaleInfo(
|
||||
LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER, reinterpret_cast<LPSTR>(&fahrenheit),
|
||||
sizeof(fahrenheit))
|
||||
== 0)
|
||||
{
|
||||
// Assume celsius by default if function call fails
|
||||
return TemperatureUnit::Celsius;
|
||||
}
|
||||
|
||||
if (fahrenheit)
|
||||
return TemperatureUnit::Fahrenheit;
|
||||
|
||||
return TemperatureUnit::Celsius;
|
||||
}
|
||||
|
||||
bool ProcessIsElevated()
|
||||
{
|
||||
BOOL isElevated = FALSE;
|
||||
HANDLE hToken = nullptr;
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
|
||||
{
|
||||
TOKEN_ELEVATION Elevation;
|
||||
DWORD tokenSize = sizeof(TOKEN_ELEVATION);
|
||||
if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &tokenSize))
|
||||
{
|
||||
isElevated = Elevation.TokenIsElevated;
|
||||
}
|
||||
}
|
||||
if (hToken)
|
||||
{
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
return isElevated;
|
||||
}
|
||||
|
||||
std::string GetSteamPath()
|
||||
{
|
||||
wchar_t* wSteamPath;
|
||||
HKEY hKey;
|
||||
DWORD type, size;
|
||||
LRESULT result;
|
||||
|
||||
if (RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", &hKey) != ERROR_SUCCESS)
|
||||
return {};
|
||||
|
||||
// Get the size of the path first
|
||||
if (RegQueryValueExW(hKey, L"SteamPath", nullptr, &type, nullptr, &size) != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hKey);
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string outPath = "";
|
||||
wSteamPath = reinterpret_cast<wchar_t*>(malloc(size));
|
||||
result = RegQueryValueExW(hKey, L"SteamPath", nullptr, &type, reinterpret_cast<LPBYTE>(wSteamPath), &size);
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
auto utf8SteamPath = String::ToUtf8(wSteamPath);
|
||||
outPath = Path::Combine(utf8SteamPath, "steamapps", "common");
|
||||
}
|
||||
free(wSteamPath);
|
||||
RegCloseKey(hKey);
|
||||
return outPath;
|
||||
}
|
||||
|
||||
std::string GetFontPath(const TTFFontDescriptor& font)
|
||||
{
|
||||
# if !defined(__MINGW32__) && ((NTDDI_VERSION >= NTDDI_VISTA) && !defined(_USING_V110_SDK71_) && !defined(_ATL_XP_TARGETING))
|
||||
wchar_t* fontFolder;
|
||||
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Fonts, 0, nullptr, &fontFolder)))
|
||||
{
|
||||
// Convert wchar to utf8, then copy the font folder path to the buffer.
|
||||
auto outPathTemp = String::ToUtf8(fontFolder);
|
||||
CoTaskMemFree(fontFolder);
|
||||
|
||||
return Path::Combine(outPathTemp, font.filename);
|
||||
}
|
||||
|
||||
return {};
|
||||
# else
|
||||
log_warning("Compatibility hack: falling back to C:\\Windows\\Fonts");
|
||||
return Path::Combine("C:\\Windows\\Fonts\\", font.filename);
|
||||
# endif
|
||||
}
|
||||
} // namespace Platform
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,8 +19,10 @@
|
||||
# undef interface
|
||||
# undef abstract
|
||||
|
||||
# include <CoreText/CoreText.h>
|
||||
# include <Foundation/Foundation.h>
|
||||
# include <mach-o/dyld.h>
|
||||
# include <pwd.h>
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
@@ -216,6 +218,58 @@ namespace Platform
|
||||
return Platform::GetCurrencyValue(currencyCode.UTF8String);
|
||||
}
|
||||
}
|
||||
|
||||
MeasurementFormat GetLocaleMeasurementFormat()
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
NSNumber* metricSystem = [[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem];
|
||||
|
||||
if (metricSystem.boolValue)
|
||||
{
|
||||
return MeasurementFormat::Metric;
|
||||
}
|
||||
|
||||
return MeasurementFormat::Imperial;
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetSteamPath()
|
||||
{
|
||||
const char* homeDir = getpwuid(getuid())->pw_dir;
|
||||
if (homeDir == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto steamPath = Path::Combine(
|
||||
homeDir, "Library/Application Support/Steam/Steam.AppBundle/Steam/Contents/MacOS/steamapps");
|
||||
if (Path::DirectoryExists(steamPath))
|
||||
{
|
||||
return steamPath;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string GetFontPath(const TTFFontDescriptor& font)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
CTFontDescriptorRef fontRef = CTFontDescriptorCreateWithNameAndSize(
|
||||
static_cast<CFStringRef>([NSString stringWithUTF8String:font.font_name]), 0.0);
|
||||
CFURLRef url = static_cast<CFURLRef>(CTFontDescriptorCopyAttribute(fontRef, kCTFontURLAttribute));
|
||||
if (url)
|
||||
{
|
||||
NSString* fontPath = [NSString stringWithString:[static_cast<NSURL*>(CFBridgingRelease(url)) path]];
|
||||
return fontPath.UTF8String;
|
||||
}
|
||||
else
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -45,20 +45,29 @@ namespace Platform
|
||||
uint16_t GetLocaleLanguage();
|
||||
CurrencyType GetLocaleCurrency();
|
||||
CurrencyType GetCurrencyValue(const char* currCode);
|
||||
MeasurementFormat GetLocaleMeasurementFormat();
|
||||
uint8_t GetLocaleDateFormat();
|
||||
TemperatureUnit GetLocaleTemperatureFormat();
|
||||
rct2_time GetTimeLocal();
|
||||
rct2_date GetDateLocal();
|
||||
|
||||
bool FindApp(std::string_view app, std::string* output);
|
||||
int32_t Execute(std::string_view command, std::string* output = nullptr);
|
||||
bool ProcessIsElevated();
|
||||
float GetDefaultScale();
|
||||
|
||||
bool OriginalGameDataExists(std::string_view path);
|
||||
|
||||
std::string GetUsername();
|
||||
|
||||
std::string GetSteamPath();
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__)
|
||||
std::string GetEnvironmentPath(const char* name);
|
||||
std::string GetHomePath();
|
||||
#endif
|
||||
#ifndef NO_TTF
|
||||
std::string GetFontPath(const TTFFontDescriptor& font);
|
||||
#endif // NO_TTF
|
||||
|
||||
std::string FormatShortDate(std::time_t timestamp);
|
||||
std::string FormatTime(std::time_t timestamp);
|
||||
@@ -71,6 +80,10 @@ namespace Platform
|
||||
const uint32_t iconIndex);
|
||||
void RemoveFileAssociations();
|
||||
#endif
|
||||
#ifdef __ANDROID__
|
||||
void AndroidInitClassLoader();
|
||||
jclass AndroidFindClass(JNIEnv* env, std::string_view name);
|
||||
#endif
|
||||
|
||||
bool IsRunningInWine();
|
||||
bool IsColourTerminalSupported();
|
||||
@@ -78,3 +91,15 @@ namespace Platform
|
||||
utf8* StrDecompToPrecomp(utf8* input);
|
||||
bool RequireNewWindow(bool openGL);
|
||||
} // namespace Platform
|
||||
|
||||
#ifdef __ANDROID__
|
||||
class AndroidClassLoader
|
||||
{
|
||||
public:
|
||||
AndroidClassLoader();
|
||||
~AndroidClassLoader();
|
||||
static jobject _classLoader;
|
||||
static jmethodID _findClassMethod;
|
||||
};
|
||||
|
||||
#endif // __ANDROID__
|
||||
|
||||
@@ -89,11 +89,6 @@ bool platform_ensure_directory_exists(const utf8* path)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool platform_directory_delete(const utf8* path)
|
||||
{
|
||||
return fs::remove_all(u8path(path)) > 0;
|
||||
}
|
||||
|
||||
std::string platform_get_absolute_path(const utf8* relative_path, const utf8* base_path)
|
||||
{
|
||||
std::string result;
|
||||
@@ -174,46 +169,6 @@ time_t platform_file_get_modified_time(const utf8* path)
|
||||
return 100;
|
||||
}
|
||||
|
||||
TemperatureUnit platform_get_locale_temperature_format()
|
||||
{
|
||||
// LC_MEASUREMENT is GNU specific.
|
||||
# ifdef LC_MEASUREMENT
|
||||
const char* langstring = setlocale(LC_MEASUREMENT, "");
|
||||
# else
|
||||
const char* langstring = setlocale(LC_ALL, "");
|
||||
# endif
|
||||
|
||||
if (langstring != nullptr)
|
||||
{
|
||||
if (!fnmatch("*_US*", langstring, 0) || !fnmatch("*_BS*", langstring, 0) || !fnmatch("*_BZ*", langstring, 0)
|
||||
|| !fnmatch("*_PW*", langstring, 0))
|
||||
{
|
||||
return TemperatureUnit::Fahrenheit;
|
||||
}
|
||||
}
|
||||
return TemperatureUnit::Celsius;
|
||||
}
|
||||
|
||||
uint8_t platform_get_locale_date_format()
|
||||
{
|
||||
const std::time_base::dateorder dateorder = std::use_facet<std::time_get<char>>(std::locale()).date_order();
|
||||
|
||||
switch (dateorder)
|
||||
{
|
||||
case std::time_base::mdy:
|
||||
return DATE_FORMAT_MONTH_DAY_YEAR;
|
||||
|
||||
case std::time_base::ymd:
|
||||
return DATE_FORMAT_YEAR_MONTH_DAY;
|
||||
|
||||
case std::time_base::ydm:
|
||||
return DATE_FORMAT_YEAR_DAY_MONTH;
|
||||
|
||||
default:
|
||||
return DATE_FORMAT_DAY_MONTH_YEAR;
|
||||
}
|
||||
}
|
||||
|
||||
datetime64 platform_get_datetime_now_utc()
|
||||
{
|
||||
const datetime64 epochAsTicks = 621355968000000000;
|
||||
@@ -228,15 +183,6 @@ datetime64 platform_get_datetime_now_utc()
|
||||
return utcNow;
|
||||
}
|
||||
|
||||
bool platform_process_is_elevated()
|
||||
{
|
||||
# ifndef __EMSCRIPTEN__
|
||||
return (geteuid() == 0);
|
||||
# else
|
||||
return false;
|
||||
# endif // __EMSCRIPTEN__
|
||||
}
|
||||
|
||||
std::string platform_get_rct1_steam_dir()
|
||||
{
|
||||
return "app_285310" PATH_SEPARATOR "depot_285311";
|
||||
|
||||
@@ -137,56 +137,17 @@ namespace Platform
|
||||
sanitised = String::Trim(sanitised);
|
||||
return sanitised;
|
||||
}
|
||||
|
||||
#ifndef __ANDROID__
|
||||
float GetDefaultScale()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
} // namespace Platform
|
||||
|
||||
GamePalette gPalette;
|
||||
|
||||
void platform_update_palette(const uint8_t* colours, int32_t start_index, int32_t num_colours)
|
||||
{
|
||||
colours += start_index * 4;
|
||||
|
||||
for (int32_t i = start_index; i < num_colours + start_index; i++)
|
||||
{
|
||||
uint8_t r = colours[2];
|
||||
uint8_t g = colours[1];
|
||||
uint8_t b = colours[0];
|
||||
|
||||
#ifdef __ENABLE_LIGHTFX__
|
||||
if (lightfx_is_available())
|
||||
{
|
||||
lightfx_apply_palette_filter(i, &r, &g, &b);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
float night = gDayNightCycle;
|
||||
if (night >= 0 && gClimateLightningFlash == 0)
|
||||
{
|
||||
r = lerp(r, soft_light(r, 8), night);
|
||||
g = lerp(g, soft_light(g, 8), night);
|
||||
b = lerp(b, soft_light(b, 128), night);
|
||||
}
|
||||
}
|
||||
|
||||
gPalette[i].Red = r;
|
||||
gPalette[i].Green = g;
|
||||
gPalette[i].Blue = b;
|
||||
gPalette[i].Alpha = 0;
|
||||
colours += 4;
|
||||
}
|
||||
|
||||
// Fix #1749 and #6535: rainbow path, donut shop and pause button contain black spots that should be white.
|
||||
gPalette[255].Alpha = 0;
|
||||
gPalette[255].Red = 255;
|
||||
gPalette[255].Green = 255;
|
||||
gPalette[255].Blue = 255;
|
||||
|
||||
if (!gOpenRCT2Headless)
|
||||
{
|
||||
drawing_engine_set_palette(gPalette);
|
||||
}
|
||||
}
|
||||
|
||||
void platform_toggle_windowed_mode()
|
||||
{
|
||||
int32_t targetMode = gConfigGeneral.fullscreen_mode == 0 ? 2 : 0;
|
||||
@@ -254,13 +215,6 @@ void platform_sleep(uint32_t ms)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef __ANDROID__
|
||||
float platform_get_default_scale()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void core_init()
|
||||
{
|
||||
static bool initialised = false;
|
||||
@@ -269,7 +223,7 @@ void core_init()
|
||||
initialised = true;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
platform_android_init_class_loader();
|
||||
Platform::AndroidInitClassLoader();
|
||||
#endif // __ANDROID__
|
||||
|
||||
platform_ticks_init();
|
||||
|
||||
@@ -70,26 +70,6 @@ bool platform_ensure_directory_exists(const utf8* path)
|
||||
return success != FALSE;
|
||||
}
|
||||
|
||||
bool platform_directory_delete(const utf8* path)
|
||||
{
|
||||
// Needs to be double-null terminated as pFrom is a null terminated array of strings
|
||||
auto wPath = String::ToWideChar(path) + L"\0";
|
||||
|
||||
SHFILEOPSTRUCTW fileop;
|
||||
fileop.hwnd = nullptr; // no status display
|
||||
fileop.wFunc = FO_DELETE; // delete operation
|
||||
fileop.pFrom = wPath.c_str(); // source file name as double null terminated string
|
||||
fileop.pTo = nullptr; // no destination needed
|
||||
fileop.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; // do not prompt the user
|
||||
|
||||
fileop.fAnyOperationsAborted = FALSE;
|
||||
fileop.lpszProgressTitle = nullptr;
|
||||
fileop.hNameMappings = nullptr;
|
||||
|
||||
int32_t ret = SHFileOperationW(&fileop);
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
bool platform_lock_single_instance()
|
||||
{
|
||||
HANDLE mutex, status;
|
||||
@@ -116,36 +96,6 @@ int32_t platform_get_drives()
|
||||
return GetLogicalDrives();
|
||||
}
|
||||
|
||||
bool platform_get_steam_path(utf8* outPath, size_t outSize)
|
||||
{
|
||||
wchar_t* wSteamPath;
|
||||
HKEY hKey;
|
||||
DWORD type, size;
|
||||
LRESULT result;
|
||||
|
||||
if (RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", &hKey) != ERROR_SUCCESS)
|
||||
return false;
|
||||
|
||||
// Get the size of the path first
|
||||
if (RegQueryValueExW(hKey, L"SteamPath", nullptr, &type, nullptr, &size) != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
wSteamPath = reinterpret_cast<wchar_t*>(malloc(size));
|
||||
result = RegQueryValueExW(hKey, L"SteamPath", nullptr, &type, reinterpret_cast<LPBYTE>(wSteamPath), &size);
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
auto utf8SteamPath = String::ToUtf8(wSteamPath);
|
||||
safe_strcpy(outPath, utf8SteamPath.c_str(), outSize);
|
||||
safe_strcat_path(outPath, "steamapps\\common", outSize);
|
||||
}
|
||||
free(wSteamPath);
|
||||
RegCloseKey(hKey);
|
||||
return result == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
std::string platform_get_rct1_steam_dir()
|
||||
{
|
||||
return "Rollercoaster Tycoon Deluxe";
|
||||
@@ -176,127 +126,6 @@ time_t platform_file_get_modified_time(const utf8* path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
MeasurementFormat platform_get_locale_measurement_format()
|
||||
{
|
||||
UINT measurement_system;
|
||||
if (GetLocaleInfo(
|
||||
LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER, reinterpret_cast<LPSTR>(&measurement_system),
|
||||
sizeof(measurement_system))
|
||||
== 0)
|
||||
{
|
||||
return MeasurementFormat::Metric;
|
||||
}
|
||||
|
||||
switch (measurement_system)
|
||||
{
|
||||
case 1:
|
||||
return MeasurementFormat::Imperial;
|
||||
case 0:
|
||||
default:
|
||||
return MeasurementFormat::Metric;
|
||||
}
|
||||
}
|
||||
|
||||
TemperatureUnit platform_get_locale_temperature_format()
|
||||
{
|
||||
UINT fahrenheit;
|
||||
|
||||
// GetLocaleInfo will set fahrenheit to 1 if the locale on this computer
|
||||
// uses the United States measurement system or 0 otherwise.
|
||||
if (GetLocaleInfo(
|
||||
LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER, reinterpret_cast<LPSTR>(&fahrenheit),
|
||||
sizeof(fahrenheit))
|
||||
== 0)
|
||||
{
|
||||
// Assume celsius by default if function call fails
|
||||
return TemperatureUnit::Celsius;
|
||||
}
|
||||
|
||||
if (fahrenheit)
|
||||
return TemperatureUnit::Fahrenheit;
|
||||
|
||||
return TemperatureUnit::Celsius;
|
||||
}
|
||||
|
||||
uint8_t platform_get_locale_date_format()
|
||||
{
|
||||
# if _WIN32_WINNT >= 0x0600
|
||||
// Retrieve short date format, eg "MM/dd/yyyy"
|
||||
wchar_t dateFormat[20];
|
||||
if (GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SSHORTDATE, dateFormat, static_cast<int>(std::size(dateFormat))) == 0)
|
||||
{
|
||||
return DATE_FORMAT_DAY_MONTH_YEAR;
|
||||
}
|
||||
|
||||
// The only valid characters for format types are: dgyM
|
||||
// We try to find 3 strings of format types, ignore any characters in between.
|
||||
// We also ignore 'g', as it represents 'era' and we don't have that concept
|
||||
// in our date formats.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd317787(v=vs.85).aspx
|
||||
//
|
||||
wchar_t first[sizeof(dateFormat)];
|
||||
wchar_t second[sizeof(dateFormat)];
|
||||
if (swscanf_s(
|
||||
dateFormat, L"%l[dyM]%*l[^dyM]%l[dyM]%*l[^dyM]%*l[dyM]", first, static_cast<uint32_t>(std::size(first)), second,
|
||||
static_cast<uint32_t>(std::size(second)))
|
||||
!= 2)
|
||||
{
|
||||
return DATE_FORMAT_DAY_MONTH_YEAR;
|
||||
}
|
||||
|
||||
if (wcsncmp(L"d", first, 1) == 0)
|
||||
{
|
||||
return DATE_FORMAT_DAY_MONTH_YEAR;
|
||||
}
|
||||
if (wcsncmp(L"M", first, 1) == 0)
|
||||
{
|
||||
return DATE_FORMAT_MONTH_DAY_YEAR;
|
||||
}
|
||||
if (wcsncmp(L"y", first, 1) == 0)
|
||||
{
|
||||
if (wcsncmp(L"d", second, 1) == 0)
|
||||
{
|
||||
return DATE_FORMAT_YEAR_DAY_MONTH;
|
||||
}
|
||||
|
||||
// Closest possible option
|
||||
return DATE_FORMAT_YEAR_MONTH_DAY;
|
||||
}
|
||||
# endif
|
||||
|
||||
// Default fallback
|
||||
return DATE_FORMAT_DAY_MONTH_YEAR;
|
||||
}
|
||||
|
||||
# ifndef NO_TTF
|
||||
bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size)
|
||||
{
|
||||
# if !defined(__MINGW32__) \
|
||||
&& ((NTDDI_VERSION >= NTDDI_VISTA) && !defined(_USING_V110_SDK71_) && !defined(_ATL_XP_TARGETING))
|
||||
wchar_t* fontFolder;
|
||||
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Fonts, 0, nullptr, &fontFolder)))
|
||||
{
|
||||
// Convert wchar to utf8, then copy the font folder path to the buffer.
|
||||
auto outPathTemp = String::ToUtf8(fontFolder);
|
||||
safe_strcpy(buffer, outPathTemp.c_str(), size);
|
||||
|
||||
CoTaskMemFree(fontFolder);
|
||||
|
||||
// Append the requested font's file name.
|
||||
safe_strcat_path(buffer, font->filename, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
# else
|
||||
log_warning("Compatibility hack: falling back to C:\\Windows\\Fonts");
|
||||
safe_strcpy(buffer, "C:\\Windows\\Fonts\\", size);
|
||||
safe_strcat_path(buffer, font->filename, size);
|
||||
return true;
|
||||
# endif
|
||||
}
|
||||
# endif // NO_TTF
|
||||
|
||||
std::string platform_get_absolute_path(const utf8* relativePath, const utf8* basePath)
|
||||
{
|
||||
std::string result;
|
||||
@@ -338,26 +167,6 @@ datetime64 platform_get_datetime_now_utc()
|
||||
return utcNow;
|
||||
}
|
||||
|
||||
bool platform_process_is_elevated()
|
||||
{
|
||||
BOOL isElevated = FALSE;
|
||||
HANDLE hToken = nullptr;
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
|
||||
{
|
||||
TOKEN_ELEVATION Elevation;
|
||||
DWORD tokenSize = sizeof(TOKEN_ELEVATION);
|
||||
if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &tokenSize))
|
||||
{
|
||||
isElevated = Elevation.TokenIsElevated;
|
||||
}
|
||||
}
|
||||
if (hToken)
|
||||
{
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
return isElevated;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// URI protocol association setup
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2020 OpenRCT2 developers
|
||||
*
|
||||
* For a complete list of all authors, please refer to contributors.md
|
||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
|
||||
# include "../config/Config.h"
|
||||
# include "../core/Path.hpp"
|
||||
# include "../localisation/Language.h"
|
||||
# include "../util/Util.h"
|
||||
# include "platform.h"
|
||||
|
||||
// undefine `interface` and `abstract`, because it's causing conflicts with Objective-C's keywords
|
||||
# undef interface
|
||||
# undef abstract
|
||||
|
||||
# import <AppKit/AppKit.h>
|
||||
# import <Foundation/Foundation.h>
|
||||
# include <mach-o/dyld.h>
|
||||
# include <pwd.h>
|
||||
|
||||
# ifndef NO_TTF
|
||||
bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
CTFontDescriptorRef fontRef = CTFontDescriptorCreateWithNameAndSize(
|
||||
static_cast<CFStringRef>([NSString stringWithUTF8String:font->font_name]), 0.0);
|
||||
CFURLRef url = static_cast<CFURLRef>(CTFontDescriptorCopyAttribute(fontRef, kCTFontURLAttribute));
|
||||
if (url)
|
||||
{
|
||||
NSString* fontPath = [NSString stringWithString:[static_cast<NSURL*>(CFBridgingRelease(url)) path]];
|
||||
safe_strcpy(buffer, fontPath.UTF8String, size);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif // NO_TTF
|
||||
|
||||
MeasurementFormat platform_get_locale_measurement_format()
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
NSNumber* metricSystem = [[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem];
|
||||
|
||||
if (metricSystem.boolValue)
|
||||
{
|
||||
return MeasurementFormat::Metric;
|
||||
}
|
||||
|
||||
return MeasurementFormat::Imperial;
|
||||
}
|
||||
}
|
||||
|
||||
bool platform_get_steam_path(utf8* outPath, size_t outSize)
|
||||
{
|
||||
char steamPath[1024] = { 0 };
|
||||
const char* homeDir = getpwuid(getuid())->pw_dir;
|
||||
if (homeDir != NULL)
|
||||
{
|
||||
safe_strcpy(steamPath, homeDir, sizeof(steamPath));
|
||||
safe_strcat_path(
|
||||
steamPath, "Library/Application Support/Steam/Steam.AppBundle/Steam/Contents/MacOS/steamapps", sizeof(steamPath));
|
||||
if (Path::DirectoryExists(steamPath))
|
||||
{
|
||||
safe_strcpy(outPath, steamPath, outSize);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -82,14 +82,12 @@ struct file_dialog_desc
|
||||
};
|
||||
|
||||
// Platform shared definitions
|
||||
void platform_update_palette(const uint8_t* colours, int32_t start_index, int32_t num_colours);
|
||||
void platform_toggle_windowed_mode();
|
||||
void platform_refresh_video(bool recreate_window);
|
||||
|
||||
// Platform specific definitions
|
||||
time_t platform_file_get_modified_time(const utf8* path);
|
||||
bool platform_ensure_directory_exists(const utf8* path);
|
||||
bool platform_directory_delete(const utf8* path);
|
||||
std::string platform_get_absolute_path(const utf8* relative_path, const utf8* base_path);
|
||||
bool platform_lock_single_instance();
|
||||
|
||||
@@ -100,22 +98,11 @@ void platform_sleep(uint32_t ms);
|
||||
void platform_get_user_directory(utf8* outPath, const utf8* subDirectory, size_t outSize);
|
||||
bool platform_open_common_file_dialog(utf8* outFilename, file_dialog_desc* desc, size_t outSize);
|
||||
utf8* platform_open_directory_browser(const utf8* title);
|
||||
MeasurementFormat platform_get_locale_measurement_format();
|
||||
TemperatureUnit platform_get_locale_temperature_format();
|
||||
uint8_t platform_get_locale_date_format();
|
||||
bool platform_process_is_elevated();
|
||||
bool platform_get_steam_path(utf8* outPath, size_t outSize);
|
||||
std::string platform_get_rct1_steam_dir();
|
||||
std::string platform_get_rct2_steam_dir();
|
||||
|
||||
#ifndef NO_TTF
|
||||
bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size);
|
||||
#endif // NO_TTF
|
||||
|
||||
datetime64 platform_get_datetime_now_utc();
|
||||
|
||||
float platform_get_default_scale();
|
||||
|
||||
// Called very early in the program before parsing commandline arguments.
|
||||
void core_init();
|
||||
|
||||
@@ -137,17 +124,3 @@ bool platform_setup_uri_protocol();
|
||||
// as it requires external linkage, which 'static' prevents
|
||||
__declspec(dllexport) int32_t StartOpenRCT2(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int32_t nCmdShow);
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef __ANDROID__
|
||||
class AndroidClassLoader
|
||||
{
|
||||
public:
|
||||
AndroidClassLoader();
|
||||
~AndroidClassLoader();
|
||||
static jobject _classLoader;
|
||||
static jmethodID _findClassMethod;
|
||||
};
|
||||
|
||||
void platform_android_init_class_loader();
|
||||
jclass platform_android_find_class(JNIEnv* env, const char* name);
|
||||
#endif // __ANDROID__
|
||||
|
||||
@@ -389,7 +389,7 @@ static void scenario_update_daynight_cycle()
|
||||
// Only update palette if day / night cycle has changed
|
||||
if (gDayNightCycle != currentDayNightCycle)
|
||||
{
|
||||
platform_update_palette(gGamePalette, 10, 236);
|
||||
UpdatePalette(gGamePalette, 10, 236);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace TitleSequenceManager
|
||||
}
|
||||
else
|
||||
{
|
||||
platform_directory_delete(path);
|
||||
Path::DeleteDirectory(path);
|
||||
}
|
||||
_items.erase(_items.begin() + i);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user