1
0
Fork 0

Compare commits

...

9 Commits

Author SHA1 Message Date
Oliver Bechstein-Rumble bd88948db3
Merge 71ac8d508b into 1d38cbafcb 2025-07-13 23:12:27 +00:00
Peter Nelson 1d38cbafcb Codechange: Use unique_ptr for ScriptInfo instances.
Replaces raw pointers, slightly.
2025-07-14 00:10:14 +01:00
Peter Nelson 992d58d799 Codechange: Pass ScriptInfo by reference to IsSameScript. 2025-07-14 00:10:14 +01:00
Peter Nelson 8f34b7a821 Codechange: Keep Squirrel engine in unique_ptr. 2025-07-14 00:10:14 +01:00
Peter Nelson bf6d0c4934
Codechange: Don't pre-fill font metrics when loading fonts. (#14436)
Each font cache implementation sets its own metrics based on the loaded font, so there is no need to pre-fill with (unscaled, invalid) default metrics.
2025-07-13 23:38:31 +01:00
Michael Lutz 3c4fb21a5e
Fix: [Win32] Link failure with newer Windows SDK version due to WinRT changes. (#14432) 2025-07-13 22:34:32 +01:00
OllieBechstein 71ac8d508b Fix coding style to better conform to the guidelines 2025-06-19 22:34:08 +02:00
OllieBechstein d6222cd5d7 Merge remote-tracking branch 'upstream/master' 2025-06-19 21:57:09 +02:00
OllieBechstein a87144d669 Added a variable in settings_gui that can remember the previous gui scale that was set. This means that toggling the auto scale on and then off will revert the scale to it's previous value. 2025-06-19 21:57:00 +02:00
10 changed files with 88 additions and 54 deletions

View File

@ -90,7 +90,7 @@ template <> SQInteger PushClassName<AIInfo, ScriptType::AI>(HSQUIRRELVM vm) { sq
/* Remove the link to the real instance, else it might get deleted by RegisterAI() */ /* Remove the link to the real instance, else it might get deleted by RegisterAI() */
sq_setinstanceup(vm, 2, nullptr); sq_setinstanceup(vm, 2, nullptr);
/* Register the AI to the base system */ /* Register the AI to the base system */
info->GetScanner()->RegisterScript(info); info->GetScanner()->RegisterScript(std::unique_ptr<AIInfo>{info});
return 0; return 0;
} }
@ -136,22 +136,21 @@ bool AIInfo::CanLoadFromVersion(int version) const
/* static */ SQInteger AILibrary::Constructor(HSQUIRRELVM vm) /* static */ SQInteger AILibrary::Constructor(HSQUIRRELVM vm)
{ {
/* Create a new library */ /* Create a new library */
AILibrary *library = new AILibrary(); auto library = std::make_unique<AILibrary>();
SQInteger res = ScriptInfo::Constructor(vm, *library); SQInteger res = ScriptInfo::Constructor(vm, *library);
if (res != 0) { if (res != 0) {
delete library;
return res; return res;
} }
/* Cache the category */ /* Cache the category */
if (!library->CheckMethod("GetCategory") || !library->engine->CallStringMethod(library->SQ_instance, "GetCategory", &library->category, MAX_GET_OPS)) { if (!library->CheckMethod("GetCategory") || !library->engine->CallStringMethod(library->SQ_instance, "GetCategory", &library->category, MAX_GET_OPS)) {
delete library;
return SQ_ERROR; return SQ_ERROR;
} }
/* Register the Library to the base system */ /* Register the Library to the base system */
library->GetScanner()->RegisterScript(library); ScriptScanner *scanner = library->GetScanner();
scanner->RegisterScript(std::move(library));
return 0; return 0;
} }

View File

@ -29,7 +29,7 @@ void AIScannerInfo::Initialize()
{ {
ScriptScanner::Initialize("AIScanner"); ScriptScanner::Initialize("AIScanner");
ScriptAllocatorScope alloc_scope(this->engine); ScriptAllocatorScope alloc_scope(this->engine.get());
/* Create the dummy AI */ /* Create the dummy AI */
this->main_script = "%_dummy"; this->main_script = "%_dummy";

View File

@ -22,9 +22,10 @@
#include "safeguards.h" #include "safeguards.h"
/** Default heights for the different sizes of fonts. */ /** Default unscaled heights for the different sizes of fonts. */
static const int _default_font_height[FS_END] = {10, 6, 18, 10}; /* static */ const int FontCache::DEFAULT_FONT_HEIGHT[FS_END] = {10, 6, 18, 10};
static const int _default_font_ascender[FS_END] = { 8, 5, 15, 8}; /** Default unscaled ascenders for the different sizes of fonts. */
/* static */ const int FontCache::DEFAULT_FONT_ASCENDER[FS_END] = {8, 5, 15, 8};
FontCacheSettings _fcsettings; FontCacheSettings _fcsettings;
@ -32,8 +33,7 @@ FontCacheSettings _fcsettings;
* Create a new font cache. * Create a new font cache.
* @param fs The size of the font. * @param fs The size of the font.
*/ */
FontCache::FontCache(FontSize fs) : parent(FontCache::Get(fs)), fs(fs), height(_default_font_height[fs]), FontCache::FontCache(FontSize fs) : parent(FontCache::Get(fs)), fs(fs)
ascender(_default_font_ascender[fs]), descender(_default_font_ascender[fs] - _default_font_height[fs])
{ {
assert(this->parent == nullptr || this->fs == this->parent->fs); assert(this->parent == nullptr || this->fs == this->parent->fs);
FontCache::caches[this->fs] = this; FontCache::caches[this->fs] = this;
@ -50,7 +50,7 @@ FontCache::~FontCache()
int FontCache::GetDefaultFontHeight(FontSize fs) int FontCache::GetDefaultFontHeight(FontSize fs)
{ {
return _default_font_height[fs]; return FontCache::DEFAULT_FONT_HEIGHT[fs];
} }
/** /**

View File

@ -23,9 +23,9 @@ protected:
static FontCache *caches[FS_END]; ///< All the font caches. static FontCache *caches[FS_END]; ///< All the font caches.
FontCache *parent; ///< The parent of this font cache. FontCache *parent; ///< The parent of this font cache.
const FontSize fs; ///< The size of the font. const FontSize fs; ///< The size of the font.
int height; ///< The height of the font. int height = 0; ///< The height of the font.
int ascender; ///< The ascender value of the font. int ascender = 0; ///< The ascender value of the font.
int descender; ///< The descender value of the font. int descender = 0; ///< The descender value of the font.
public: public:
FontCache(FontSize fs); FontCache(FontSize fs);
@ -33,6 +33,11 @@ public:
static void InitializeFontCaches(); static void InitializeFontCaches();
/** Default unscaled font heights. */
static const int DEFAULT_FONT_HEIGHT[FS_END];
/** Default unscaled font ascenders. */
static const int DEFAULT_FONT_ASCENDER[FS_END];
static int GetDefaultFontHeight(FontSize fs); static int GetDefaultFontHeight(FontSize fs);
/** /**

View File

@ -78,7 +78,7 @@ template <> SQInteger PushClassName<GameInfo, ScriptType::GS>(HSQUIRRELVM vm) {
/* Remove the link to the real instance, else it might get deleted by RegisterGame() */ /* Remove the link to the real instance, else it might get deleted by RegisterGame() */
sq_setinstanceup(vm, 2, nullptr); sq_setinstanceup(vm, 2, nullptr);
/* Register the Game to the base system */ /* Register the Game to the base system */
info->GetScanner()->RegisterScript(info); info->GetScanner()->RegisterScript(std::unique_ptr<GameInfo>{info});
return 0; return 0;
} }
@ -106,22 +106,21 @@ bool GameInfo::CanLoadFromVersion(int version) const
/* static */ SQInteger GameLibrary::Constructor(HSQUIRRELVM vm) /* static */ SQInteger GameLibrary::Constructor(HSQUIRRELVM vm)
{ {
/* Create a new library */ /* Create a new library */
GameLibrary *library = new GameLibrary(); auto library = std::make_unique<GameLibrary>();
SQInteger res = ScriptInfo::Constructor(vm, *library); SQInteger res = ScriptInfo::Constructor(vm, *library);
if (res != 0) { if (res != 0) {
delete library;
return res; return res;
} }
/* Cache the category */ /* Cache the category */
if (!library->CheckMethod("GetCategory") || !library->engine->CallStringMethod(library->SQ_instance, "GetCategory", &library->category, MAX_GET_OPS)) { if (!library->CheckMethod("GetCategory") || !library->engine->CallStringMethod(library->SQ_instance, "GetCategory", &library->category, MAX_GET_OPS)) {
delete library;
return SQ_ERROR; return SQ_ERROR;
} }
/* Register the Library to the base system */ /* Register the Library to the base system */
library->GetScanner()->RegisterScript(library); ScriptScanner *scanner = library->GetScanner();
scanner->RegisterScript(std::move(library));
return 0; return 0;
} }

View File

@ -92,8 +92,8 @@ GameLibrary *GameScannerLibrary::FindLibrary(const std::string &library, int ver
std::string library_name = fmt::format("{}.{}", library, version); std::string library_name = fmt::format("{}.{}", library, version);
/* Check if the library + version exists */ /* Check if the library + version exists */
ScriptInfoList::iterator it = this->info_list.find(library_name); auto it = this->info_list.find(library_name);
if (it == this->info_list.end()) return nullptr; if (it == this->info_list.end()) return nullptr;
return static_cast<GameLibrary *>((*it).second); return static_cast<GameLibrary *>(it->second);
} }

View File

@ -44,10 +44,7 @@ bool ScriptScanner::AddFile(const std::string &filename, size_t, const std::stri
return true; return true;
} }
ScriptScanner::ScriptScanner() : ScriptScanner::ScriptScanner() = default;
engine(nullptr)
{
}
void ScriptScanner::ResetEngine() void ScriptScanner::ResetEngine()
{ {
@ -58,7 +55,7 @@ void ScriptScanner::ResetEngine()
void ScriptScanner::Initialize(std::string_view name) void ScriptScanner::Initialize(std::string_view name)
{ {
this->engine = new Squirrel(name); this->engine = std::make_unique<Squirrel>(name);
this->RescanDir(); this->RescanDir();
@ -68,8 +65,6 @@ void ScriptScanner::Initialize(std::string_view name)
ScriptScanner::~ScriptScanner() ScriptScanner::~ScriptScanner()
{ {
this->Reset(); this->Reset();
delete this->engine;
} }
void ScriptScanner::RescanDir() void ScriptScanner::RescanDir()
@ -83,15 +78,12 @@ void ScriptScanner::RescanDir()
void ScriptScanner::Reset() void ScriptScanner::Reset()
{ {
for (const auto &item : this->info_list) {
delete item.second;
}
this->info_list.clear(); this->info_list.clear();
this->info_single_list.clear(); this->info_single_list.clear();
this->info_vector.clear();
} }
void ScriptScanner::RegisterScript(ScriptInfo *info) void ScriptScanner::RegisterScript(std::unique_ptr<ScriptInfo> &&info)
{ {
std::string script_original_name = this->GetScriptName(*info); std::string script_original_name = this->GetScriptName(*info);
std::string script_name = fmt::format("{}.{}", script_original_name, info->GetVersion()); std::string script_name = fmt::format("{}.{}", script_original_name, info->GetVersion());
@ -99,7 +91,6 @@ void ScriptScanner::RegisterScript(ScriptInfo *info)
/* Check if GetShortName follows the rules */ /* Check if GetShortName follows the rules */
if (info->GetShortName().size() != 4) { if (info->GetShortName().size() != 4) {
Debug(script, 0, "The script '{}' returned a string from GetShortName() which is not four characters. Unable to load the script.", info->GetName()); Debug(script, 0, "The script '{}' returned a string from GetShortName() which is not four characters. Unable to load the script.", info->GetName());
delete info;
return; return;
} }
@ -111,7 +102,6 @@ void ScriptScanner::RegisterScript(ScriptInfo *info)
#else #else
if (it->second->GetMainScript() == info->GetMainScript()) { if (it->second->GetMainScript() == info->GetMainScript()) {
#endif #endif
delete info;
return; return;
} }
@ -120,20 +110,20 @@ void ScriptScanner::RegisterScript(ScriptInfo *info)
Debug(script, 1, " 2: {}", info->GetMainScript()); Debug(script, 1, " 2: {}", info->GetMainScript());
Debug(script, 1, "The first is taking precedence."); Debug(script, 1, "The first is taking precedence.");
delete info;
return; return;
} }
this->info_list[script_name] = info; ScriptInfo *script_info = this->info_vector.emplace_back(std::move(info)).get();
this->info_list[script_name] = script_info;
if (!info->IsDeveloperOnly() || _settings_client.gui.ai_developer_tools) { if (!script_info->IsDeveloperOnly() || _settings_client.gui.ai_developer_tools) {
/* Add the script to the 'unique' script list, where only the highest version /* Add the script to the 'unique' script list, where only the highest version
* of the script is registered. */ * of the script is registered. */
auto it = this->info_single_list.find(script_original_name); auto it = this->info_single_list.find(script_original_name);
if (it == this->info_single_list.end()) { if (it == this->info_single_list.end()) {
this->info_single_list[script_original_name] = info; this->info_single_list[script_original_name] = script_info;
} else if (it->second->GetVersion() < info->GetVersion()) { } else if (it->second->GetVersion() < script_info->GetVersion()) {
it->second = info; it->second = script_info;
} }
} }
} }
@ -195,17 +185,17 @@ struct ScriptFileChecksumCreator : FileScanner {
* @param info The script to get the shortname and md5 sum from. * @param info The script to get the shortname and md5 sum from.
* @return True iff they're the same. * @return True iff they're the same.
*/ */
static bool IsSameScript(const ContentInfo &ci, bool md5sum, ScriptInfo *info, Subdirectory dir) static bool IsSameScript(const ContentInfo &ci, bool md5sum, const ScriptInfo &info, Subdirectory dir)
{ {
uint32_t id = 0; uint32_t id = 0;
auto str = std::string_view{info->GetShortName()}.substr(0, 4); auto str = std::string_view{info.GetShortName()}.substr(0, 4);
for (size_t j = 0; j < str.size(); j++) id |= static_cast<uint8_t>(str[j]) << (8 * j); for (size_t j = 0; j < str.size(); j++) id |= static_cast<uint8_t>(str[j]) << (8 * j);
if (id != ci.unique_id) return false; if (id != ci.unique_id) return false;
if (!md5sum) return true; if (!md5sum) return true;
ScriptFileChecksumCreator checksum(dir); ScriptFileChecksumCreator checksum(dir);
const auto &tar_filename = info->GetTarFile(); const auto &tar_filename = info.GetTarFile();
TarList::iterator iter; TarList::iterator iter;
if (!tar_filename.empty() && (iter = _tar_list[dir].find(tar_filename)) != _tar_list[dir].end()) { if (!tar_filename.empty() && (iter = _tar_list[dir].find(tar_filename)) != _tar_list[dir].end()) {
/* The main script is in a tar file, so find all files that /* The main script is in a tar file, so find all files that
@ -224,7 +214,7 @@ static bool IsSameScript(const ContentInfo &ci, bool md5sum, ScriptInfo *info, S
/* There'll always be at least 1 path separator character in a script /* There'll always be at least 1 path separator character in a script
* main script name as the search algorithm requires the main script to * main script name as the search algorithm requires the main script to
* be in a subdirectory of the script directory; so <dir>/<path>/main.nut. */ * be in a subdirectory of the script directory; so <dir>/<path>/main.nut. */
const std::string &main_script = info->GetMainScript(); const std::string &main_script = info.GetMainScript();
std::string path = main_script.substr(0, main_script.find_last_of(PATHSEPCHAR)); std::string path = main_script.substr(0, main_script.find_last_of(PATHSEPCHAR));
checksum.Scan(".nut", path); checksum.Scan(".nut", path);
} }
@ -235,7 +225,7 @@ static bool IsSameScript(const ContentInfo &ci, bool md5sum, ScriptInfo *info, S
bool ScriptScanner::HasScript(const ContentInfo &ci, bool md5sum) bool ScriptScanner::HasScript(const ContentInfo &ci, bool md5sum)
{ {
for (const auto &item : this->info_list) { for (const auto &item : this->info_list) {
if (IsSameScript(ci, md5sum, item.second, this->GetDirectory())) return true; if (IsSameScript(ci, md5sum, *item.second, this->GetDirectory())) return true;
} }
return false; return false;
} }
@ -243,7 +233,7 @@ bool ScriptScanner::HasScript(const ContentInfo &ci, bool md5sum)
std::optional<std::string_view> ScriptScanner::FindMainScript(const ContentInfo &ci, bool md5sum) std::optional<std::string_view> ScriptScanner::FindMainScript(const ContentInfo &ci, bool md5sum)
{ {
for (const auto &item : this->info_list) { for (const auto &item : this->info_list) {
if (IsSameScript(ci, md5sum, item.second, this->GetDirectory())) return item.second->GetMainScript(); if (IsSameScript(ci, md5sum, *item.second, this->GetDirectory())) return item.second->GetMainScript();
} }
return std::nullopt; return std::nullopt;
} }

View File

@ -13,7 +13,7 @@
#include "../fileio_func.h" #include "../fileio_func.h"
#include "../string_func.h" #include "../string_func.h"
typedef std::map<std::string, class ScriptInfo *, CaseInsensitiveComparator> ScriptInfoList; ///< Type for the list of scripts. using ScriptInfoList = std::map<std::string, class ScriptInfo *, CaseInsensitiveComparator>; ///< Type for the list of scripts.
/** Scanner to help finding scripts. */ /** Scanner to help finding scripts. */
class ScriptScanner : public FileScanner { class ScriptScanner : public FileScanner {
@ -26,7 +26,7 @@ public:
/** /**
* Get the engine of the main squirrel handler (it indexes all available scripts). * Get the engine of the main squirrel handler (it indexes all available scripts).
*/ */
class Squirrel *GetEngine() { return this->engine; } class Squirrel *GetEngine() { return this->engine.get(); }
/** /**
* Get the current main script the ScanDir is currently tracking. * Get the current main script the ScanDir is currently tracking.
@ -51,7 +51,7 @@ public:
/** /**
* Register a ScriptInfo to the scanner. * Register a ScriptInfo to the scanner.
*/ */
void RegisterScript(class ScriptInfo *info); void RegisterScript(std::unique_ptr<class ScriptInfo> &&info);
/** /**
* Get the list of registered scripts to print on the console. * Get the list of registered scripts to print on the console.
@ -84,11 +84,13 @@ public:
void RescanDir(); void RescanDir();
protected: protected:
class Squirrel *engine; ///< The engine we're scanning with. std::unique_ptr<class Squirrel> engine; ///< The engine we're scanning with.
std::string main_script; ///< The full path of the script. std::string main_script; ///< The full path of the script.
std::string tar_file; ///< If, which tar file the script was in. std::string tar_file; ///< If, which tar file the script was in.
ScriptInfoList info_list; ///< The list of all script. std::vector<std::unique_ptr<ScriptInfo>> info_vector;
ScriptInfoList info_list; ///< The list of all script.
ScriptInfoList info_single_list; ///< The list of all unique script. The best script (highest version) is shown. ScriptInfoList info_single_list; ///< The list of all unique script. The best script (highest version) is shown.
/** /**

View File

@ -418,6 +418,7 @@ struct GameOptionsWindow : Window {
GameSettings *opt = nullptr; GameSettings *opt = nullptr;
bool reload = false; bool reload = false;
int gui_scale = 0; int gui_scale = 0;
static inline int previous_gui_scale = 0; ///< Previous GUI scale.
static inline WidgetID active_tab = WID_GO_TAB_GENERAL; static inline WidgetID active_tab = WID_GO_TAB_GENERAL;
GameOptionsWindow(WindowDesc &desc) : Window(desc), filter_editbox(50), gui_scale(_gui_scale) GameOptionsWindow(WindowDesc &desc) : Window(desc), filter_editbox(50), gui_scale(_gui_scale)
@ -1066,9 +1067,13 @@ struct GameOptionsWindow : Window {
case WID_GO_GUI_SCALE_AUTO: case WID_GO_GUI_SCALE_AUTO:
{ {
if (_gui_scale_cfg == -1) { if (_gui_scale_cfg == -1) {
_gui_scale_cfg = _gui_scale; _gui_scale_cfg = previous_gui_scale; // Store the previous GUI scale value
this->SetWidgetLoweredState(WID_GO_GUI_SCALE_AUTO, false); this->SetWidgetLoweredState(WID_GO_GUI_SCALE_AUTO, false);
if (AdjustGUIZoom(false))
ReInitAllWindows(true);
this->gui_scale = _gui_scale;
} else { } else {
previous_gui_scale = _gui_scale; // Set the previous GUI scale value as the current one
_gui_scale_cfg = -1; _gui_scale_cfg = -1;
this->SetWidgetLoweredState(WID_GO_GUI_SCALE_AUTO, true); this->SetWidgetLoweredState(WID_GO_GUI_SCALE_AUTO, true);
if (AdjustGUIZoom(false)) ReInitAllWindows(true); if (AdjustGUIZoom(false)) ReInitAllWindows(true);

View File

@ -401,6 +401,40 @@ static void CancelIMEComposition(HWND hwnd)
HandleTextInput({}, true); HandleTextInput({}, true);
} }
#if defined(_MSC_VER) && defined(NTDDI_WIN10_RS4)
/* We only use WinRT functions on Windows 10 or later. Unfortunately, newer Windows SDKs are now
* linking the two functions below directly instead of using dynamic linking as previously.
* To avoid any runtime linking errors on Windows 7 or older, we stub in our own dynamic
* linking trampoline. */
static LibraryLoader _combase("combase.dll");
extern "C" int32_t __stdcall WINRT_IMPL_RoOriginateLanguageException(int32_t error, void *message, void *languageException) noexcept
{
typedef BOOL(WINAPI *PFNRoOriginateLanguageException)(int32_t, void *, void *);
static PFNRoOriginateLanguageException RoOriginateLanguageException = _combase.GetFunction("RoOriginateLanguageException");
if (RoOriginateLanguageException != nullptr) {
return RoOriginateLanguageException(error, message, languageException);
} else {
return TRUE;
}
}
extern "C" int32_t __stdcall WINRT_IMPL_RoGetActivationFactory(void *classId, winrt::guid const &iid, void **factory) noexcept
{
typedef BOOL(WINAPI *PFNRoGetActivationFactory)(void *, winrt::guid const &, void **);
static PFNRoGetActivationFactory RoGetActivationFactory = _combase.GetFunction("RoGetActivationFactory");
if (RoGetActivationFactory != nullptr) {
return RoGetActivationFactory(classId, iid, factory);
} else {
*factory = nullptr;
return winrt::impl::error_class_not_available;
}
}
#endif
static bool IsDarkModeEnabled() static bool IsDarkModeEnabled()
{ {
/* Only build if SDK is Windows 10 1803 or later. */ /* Only build if SDK is Windows 10 1803 or later. */