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() */
sq_setinstanceup(vm, 2, nullptr);
/* Register the AI to the base system */
info->GetScanner()->RegisterScript(info);
info->GetScanner()->RegisterScript(std::unique_ptr<AIInfo>{info});
return 0;
}
@ -136,22 +136,21 @@ bool AIInfo::CanLoadFromVersion(int version) const
/* static */ SQInteger AILibrary::Constructor(HSQUIRRELVM vm)
{
/* Create a new library */
AILibrary *library = new AILibrary();
auto library = std::make_unique<AILibrary>();
SQInteger res = ScriptInfo::Constructor(vm, *library);
if (res != 0) {
delete library;
return res;
}
/* Cache the category */
if (!library->CheckMethod("GetCategory") || !library->engine->CallStringMethod(library->SQ_instance, "GetCategory", &library->category, MAX_GET_OPS)) {
delete library;
return SQ_ERROR;
}
/* Register the Library to the base system */
library->GetScanner()->RegisterScript(library);
ScriptScanner *scanner = library->GetScanner();
scanner->RegisterScript(std::move(library));
return 0;
}

View File

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

View File

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

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() */
sq_setinstanceup(vm, 2, nullptr);
/* Register the Game to the base system */
info->GetScanner()->RegisterScript(info);
info->GetScanner()->RegisterScript(std::unique_ptr<GameInfo>{info});
return 0;
}
@ -106,22 +106,21 @@ bool GameInfo::CanLoadFromVersion(int version) const
/* static */ SQInteger GameLibrary::Constructor(HSQUIRRELVM vm)
{
/* Create a new library */
GameLibrary *library = new GameLibrary();
auto library = std::make_unique<GameLibrary>();
SQInteger res = ScriptInfo::Constructor(vm, *library);
if (res != 0) {
delete library;
return res;
}
/* Cache the category */
if (!library->CheckMethod("GetCategory") || !library->engine->CallStringMethod(library->SQ_instance, "GetCategory", &library->category, MAX_GET_OPS)) {
delete library;
return SQ_ERROR;
}
/* Register the Library to the base system */
library->GetScanner()->RegisterScript(library);
ScriptScanner *scanner = library->GetScanner();
scanner->RegisterScript(std::move(library));
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);
/* 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;
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;
}
ScriptScanner::ScriptScanner() :
engine(nullptr)
{
}
ScriptScanner::ScriptScanner() = default;
void ScriptScanner::ResetEngine()
{
@ -58,7 +55,7 @@ void ScriptScanner::ResetEngine()
void ScriptScanner::Initialize(std::string_view name)
{
this->engine = new Squirrel(name);
this->engine = std::make_unique<Squirrel>(name);
this->RescanDir();
@ -68,8 +65,6 @@ void ScriptScanner::Initialize(std::string_view name)
ScriptScanner::~ScriptScanner()
{
this->Reset();
delete this->engine;
}
void ScriptScanner::RescanDir()
@ -83,15 +78,12 @@ void ScriptScanner::RescanDir()
void ScriptScanner::Reset()
{
for (const auto &item : this->info_list) {
delete item.second;
}
this->info_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_name = fmt::format("{}.{}", script_original_name, info->GetVersion());
@ -99,7 +91,6 @@ void ScriptScanner::RegisterScript(ScriptInfo *info)
/* Check if GetShortName follows the rules */
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());
delete info;
return;
}
@ -111,7 +102,6 @@ void ScriptScanner::RegisterScript(ScriptInfo *info)
#else
if (it->second->GetMainScript() == info->GetMainScript()) {
#endif
delete info;
return;
}
@ -120,20 +110,20 @@ void ScriptScanner::RegisterScript(ScriptInfo *info)
Debug(script, 1, " 2: {}", info->GetMainScript());
Debug(script, 1, "The first is taking precedence.");
delete info;
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
* of the script is registered. */
auto it = this->info_single_list.find(script_original_name);
if (it == this->info_single_list.end()) {
this->info_single_list[script_original_name] = info;
} else if (it->second->GetVersion() < info->GetVersion()) {
it->second = info;
this->info_single_list[script_original_name] = script_info;
} else if (it->second->GetVersion() < script_info->GetVersion()) {
it->second = script_info;
}
}
}
@ -195,17 +185,17 @@ struct ScriptFileChecksumCreator : FileScanner {
* @param info The script to get the shortname and md5 sum from.
* @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;
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);
if (id != ci.unique_id) return false;
if (!md5sum) return true;
ScriptFileChecksumCreator checksum(dir);
const auto &tar_filename = info->GetTarFile();
const auto &tar_filename = info.GetTarFile();
TarList::iterator iter;
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
@ -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
* 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. */
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));
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)
{
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;
}
@ -243,7 +233,7 @@ bool ScriptScanner::HasScript(const ContentInfo &ci, bool md5sum)
std::optional<std::string_view> ScriptScanner::FindMainScript(const ContentInfo &ci, bool md5sum)
{
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;
}

View File

@ -13,7 +13,7 @@
#include "../fileio_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. */
class ScriptScanner : public FileScanner {
@ -26,7 +26,7 @@ public:
/**
* 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.
@ -51,7 +51,7 @@ public:
/**
* 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.
@ -84,11 +84,13 @@ public:
void RescanDir();
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 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.
/**

View File

@ -418,6 +418,7 @@ struct GameOptionsWindow : Window {
GameSettings *opt = nullptr;
bool reload = false;
int gui_scale = 0;
static inline int previous_gui_scale = 0; ///< Previous GUI scale.
static inline WidgetID active_tab = WID_GO_TAB_GENERAL;
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:
{
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);
if (AdjustGUIZoom(false))
ReInitAllWindows(true);
this->gui_scale = _gui_scale;
} else {
previous_gui_scale = _gui_scale; // Set the previous GUI scale value as the current one
_gui_scale_cfg = -1;
this->SetWidgetLoweredState(WID_GO_GUI_SCALE_AUTO, true);
if (AdjustGUIZoom(false)) ReInitAllWindows(true);

View File

@ -401,6 +401,40 @@ static void CancelIMEComposition(HWND hwnd)
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()
{
/* Only build if SDK is Windows 10 1803 or later. */