Skip to content

Commit

Permalink
Refactor ProjectSetting overrides
Browse files Browse the repository at this point in the history
* Overrides no longer happen for set/get.
* They must be checked with a new function: `ProjectSettings::get_setting_with_override()`.
* GLOBAL_DEF/GLOBAL_GET updated to use this

This change solves many problems:
* General confusion about getting the actual or overriden setting.
* Feature tags available after settings are loaded were being ignored, they are now considered.
* Hacks required for the Project Settings editor to work.

Fixes godotengine#64100. Fixes godotengine#64014. Fixes godotengine#61908.
  • Loading branch information
reduz committed Jan 13, 2023
1 parent 3c9bf4b commit 5a91a14
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 39 deletions.
53 changes: 32 additions & 21 deletions core/config/project_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,31 +291,26 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
return true;
}

if (!disable_feature_overrides) {
{ // Feature overrides.
int dot = p_name.operator String().find(".");
if (dot != -1) {
Vector<String> s = p_name.operator String().split(".");

bool override_valid = false;
for (int i = 1; i < s.size(); i++) {
String feature = s[i].strip_edges();
if (OS::get_singleton()->has_feature(feature) || custom_features.has(feature)) {
override_valid = true;
break;
Pair<StringName, StringName> fo(feature, p_name);

if (!feature_overrides.has(s[0])) {
feature_overrides[s[0]] = LocalVector<Pair<StringName, StringName>>();
}
}

if (override_valid) {
feature_overrides[s[0]] = p_name;
feature_overrides[s[0]].push_back(fo);
}
}
}

if (props.has(p_name)) {
if (!props[p_name].overridden) {
props[p_name].variant = p_value;
}

props[p_name].variant = p_value;
} else {
props[p_name] = VariantContainer(p_value, last_order++);
}
Expand All @@ -340,16 +335,35 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
bool ProjectSettings::_get(const StringName &p_name, Variant &r_ret) const {
_THREAD_SAFE_METHOD_

if (!props.has(p_name)) {
WARN_PRINT("Property not found: " + String(p_name));
return false;
}
r_ret = props[p_name].variant;
return true;
}

Variant ProjectSettings::get_setting_with_override(const StringName &p_name) const {
_THREAD_SAFE_METHOD_

StringName name = p_name;
if (!disable_feature_overrides && feature_overrides.has(name)) {
name = feature_overrides[name];
if (feature_overrides.has(name)) {
const LocalVector<Pair<StringName, StringName>> &overrides = feature_overrides[name];
for (uint32_t i = 0; i < overrides.size(); i++) {
if (OS::get_singleton()->has_feature(overrides[i].first)) { // Custom features are checked in OS.has_feature() already. No need to check twice.
if (props.has(overrides[i].second)) {
name = overrides[i].second;
break;
}
}
}
}

if (!props.has(name)) {
WARN_PRINT("Property not found: " + String(name));
return false;
return Variant();
}
r_ret = props[name].variant;
return true;
return props[name].variant;
}

struct _VCSort {
Expand Down Expand Up @@ -1101,10 +1115,6 @@ const HashMap<StringName, PropertyInfo> &ProjectSettings::get_custom_property_in
return custom_prop_info;
}

void ProjectSettings::set_disable_feature_overrides(bool p_disable) {
disable_feature_overrides = p_disable;
}

bool ProjectSettings::is_using_datapack() const {
return using_datapack;
}
Expand Down Expand Up @@ -1169,6 +1179,7 @@ void ProjectSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_setting", "name"), &ProjectSettings::has_setting);
ClassDB::bind_method(D_METHOD("set_setting", "name", "value"), &ProjectSettings::set_setting);
ClassDB::bind_method(D_METHOD("get_setting", "name", "default_value"), &ProjectSettings::get_setting, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("get_setting_with_override", "name"), &ProjectSettings::get_setting_with_override);
ClassDB::bind_method(D_METHOD("set_order", "name", "position"), &ProjectSettings::set_order);
ClassDB::bind_method(D_METHOD("get_order", "name"), &ProjectSettings::get_order);
ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &ProjectSettings::set_initial_value);
Expand Down
9 changes: 4 additions & 5 deletions core/config/project_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "core/object/class_db.h"
#include "core/os/thread_safe.h"
#include "core/templates/hash_map.h"
#include "core/templates/local_vector.h"
#include "core/templates/rb_set.h"

class ProjectSettings : public Object {
Expand Down Expand Up @@ -69,7 +70,6 @@ class ProjectSettings : public Object {
Variant variant;
Variant initial;
bool hide_from_editor = false;
bool overridden = false;
bool restart_if_changed = false;
#ifdef DEBUG_METHODS_ENABLED
bool ignore_value_in_docs = false;
Expand All @@ -91,12 +91,11 @@ class ProjectSettings : public Object {
RBMap<StringName, VariantContainer> props; // NOTE: Key order is used e.g. in the save_custom method.
String resource_path;
HashMap<StringName, PropertyInfo> custom_prop_info;
bool disable_feature_overrides = false;
bool using_datapack = false;
List<String> input_presets;

HashSet<String> custom_features;
HashMap<StringName, StringName> feature_overrides;
HashMap<StringName, LocalVector<Pair<StringName, StringName>>> feature_overrides;

HashMap<StringName, AutoloadInfo> autoloads;

Expand Down Expand Up @@ -181,7 +180,7 @@ class ProjectSettings : public Object {

List<String> get_input_presets() const { return input_presets; }

void set_disable_feature_overrides(bool p_disable);
Variant get_setting_with_override(const StringName &p_name) const;

bool is_using_datapack() const;

Expand All @@ -205,7 +204,7 @@ Variant _GLOBAL_DEF(const PropertyInfo &p_info, const Variant &p_default, bool p
#define GLOBAL_DEF_RST(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true)
#define GLOBAL_DEF_NOVAL(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, true)
#define GLOBAL_DEF_RST_NOVAL(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true, true)
#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get(m_var)
#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get_setting_with_override(m_var)

#define GLOBAL_DEF_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, false, true)
#define GLOBAL_DEF_RST_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true, false, true)
Expand Down
6 changes: 6 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@
[/codeblocks]
</description>
</method>
<method name="get_setting_with_override" qualifiers="const">
<return type="Variant" />
<param index="0" name="name" type="StringName" />
<description>
</description>
</method>
<method name="globalize_path" qualifiers="const">
<return type="String" />
<param index="0" name="path" type="String" />
Expand Down
1 change: 0 additions & 1 deletion main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1385,7 +1385,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
#ifdef TOOLS_ENABLED
if (editor) {
packed_data->set_disabled(true);
globals->set_disable_feature_overrides(true);
Engine::get_singleton()->set_editor_hint(true);
main_args.push_back("--editor");
if (!init_windowed) {
Expand Down
2 changes: 1 addition & 1 deletion modules/mono/csharp_script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ bool CSharpLanguage::is_assembly_reloading_needed() {
return false; // Already up to date
}
} else {
String assembly_name = ProjectSettings::get_singleton()->get_setting("dotnet/project/assembly_name");
String assembly_name = ProjectSettings::get_singleton()->get_setting_with_override("dotnet/project/assembly_name");

if (assembly_name.is_empty()) {
assembly_name = ProjectSettings::get_singleton()->get_safe_project_name();
Expand Down
4 changes: 2 additions & 2 deletions modules/mono/mono_gd/gd_mono.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime
}
#else
static String get_assembly_name() {
String assembly_name = ProjectSettings::get_singleton()->get_setting("dotnet/project/assembly_name");
String assembly_name = ProjectSettings::get_singleton()->get_setting_with_override("dotnet/project/assembly_name");

if (assembly_name.is_empty()) {
assembly_name = ProjectSettings::get_singleton()->get_safe_project_name();
Expand Down Expand Up @@ -466,7 +466,7 @@ void GDMono::_init_godot_api_hashes() {

#ifdef TOOLS_ENABLED
bool GDMono::_load_project_assembly() {
String assembly_name = ProjectSettings::get_singleton()->get_setting("dotnet/project/assembly_name");
String assembly_name = ProjectSettings::get_singleton()->get_setting_with_override("dotnet/project/assembly_name");

if (assembly_name.is_empty()) {
assembly_name = ProjectSettings::get_singleton()->get_safe_project_name();
Expand Down
2 changes: 1 addition & 1 deletion modules/text_server_adv/text_server_adv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

using namespace godot;

#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get(m_var)
#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get_setting_with_override(m_var)

#else
// Headers for building as built-in module.
Expand Down
2 changes: 1 addition & 1 deletion modules/text_server_fb/text_server_fb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

using namespace godot;

#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get(m_var)
#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get_setting_with_override(m_var)

#else
// Headers for building as built-in module.
Expand Down
6 changes: 1 addition & 5 deletions platform/android/export/export_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1558,11 +1558,7 @@ String EditorExportPlatformAndroid::load_splash_refs(Ref<Image> &splash_image, R
}

// Setup the splash bg color
bool bg_color_valid;
Color bg_color = ProjectSettings::get_singleton()->get("application/boot_splash/bg_color", &bg_color_valid);
if (!bg_color_valid) {
bg_color = boot_splash_bg_color;
}
Color bg_color = GLOBAL_GET("application/boot_splash/bg_color");

print_verbose("Creating splash background color image.");
splash_bg_color_image.instantiate();
Expand Down
4 changes: 2 additions & 2 deletions platform/web/export/export_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ void EditorExportPlatformWeb::_fix_html(Vector<uint8_t> &p_html, const Ref<Edito
const String custom_head_include = p_preset->get("html/head_include");
HashMap<String, String> replaces;
replaces["$GODOT_URL"] = p_name + ".js";
replaces["$GODOT_PROJECT_NAME"] = ProjectSettings::get_singleton()->get_setting("application/config/name");
replaces["$GODOT_PROJECT_NAME"] = ProjectSettings::get_singleton()->get_setting_with_override("application/config/name");
replaces["$GODOT_HEAD_INCLUDE"] = head_include + custom_head_include;
replaces["$GODOT_CONFIG"] = str_config;
_replace_strings(replaces, p_html);
Expand Down Expand Up @@ -193,7 +193,7 @@ Error EditorExportPlatformWeb::_add_manifest_icon(const String &p_path, const St
}

Error EditorExportPlatformWeb::_build_pwa(const Ref<EditorExportPreset> &p_preset, const String p_path, const Vector<SharedObject> &p_shared_objects) {
String proj_name = ProjectSettings::get_singleton()->get_setting("application/config/name");
String proj_name = ProjectSettings::get_singleton()->get_setting_with_override("application/config/name");
if (proj_name.is_empty()) {
proj_name = "Godot Game";
}
Expand Down

0 comments on commit 5a91a14

Please sign in to comment.