Skip to content

Commit

Permalink
Merge pull request #31171 from aaronfranke/feature-system
Browse files Browse the repository at this point in the history
  • Loading branch information
akien-mga authored Nov 24, 2021
2 parents 3e33006 + e81c689 commit e49b127
Show file tree
Hide file tree
Showing 4 changed files with 252 additions and 52 deletions.
78 changes: 78 additions & 0 deletions core/config/project_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
#include "core/version.h"

#include "modules/modules_enabled.gen.h" // For mono.

const String ProjectSettings::PROJECT_DATA_DIR_NAME_SUFFIX = "godot";

Expand All @@ -66,6 +69,69 @@ String ProjectSettings::get_imported_files_path() const {
return get_project_data_path().plus_file("imported");
}

// Returns the features that a project must have when opened with this build of Godot.
// This is used by the project manager to provide the initial_settings for config/features.
const PackedStringArray ProjectSettings::get_required_features() {
PackedStringArray features = PackedStringArray();
features.append(VERSION_BRANCH);
#ifdef REAL_T_IS_DOUBLE
features.append("Double Precision");
#endif
return features;
}

// Returns the features supported by this build of Godot. Includes all required features.
const PackedStringArray ProjectSettings::_get_supported_features() {
PackedStringArray features = get_required_features();
#ifdef MODULE_MONO_ENABLED
features.append("C#");
#endif
// Allow pinning to a specific patch number or build type by marking
// them as supported. They're only used if the user adds them manually.
features.append(VERSION_BRANCH "." _MKSTR(VERSION_PATCH));
features.append(VERSION_FULL_CONFIG);
features.append(VERSION_FULL_BUILD);
// For now, assume Vulkan is always supported.
// This should be removed if it's possible to build the editor without Vulkan.
features.append("Vulkan Clustered");
features.append("Vulkan Mobile");
return features;
}

// Returns the features that this project needs but this build of Godot lacks.
const PackedStringArray ProjectSettings::get_unsupported_features(const PackedStringArray &p_project_features) {
PackedStringArray unsupported_features = PackedStringArray();
PackedStringArray supported_features = singleton->_get_supported_features();
for (int i = 0; i < p_project_features.size(); i++) {
if (!supported_features.has(p_project_features[i])) {
unsupported_features.append(p_project_features[i]);
}
}
unsupported_features.sort();
return unsupported_features;
}

// Returns the features that both this project has and this build of Godot has, ensuring required features exist.
const PackedStringArray ProjectSettings::_trim_to_supported_features(const PackedStringArray &p_project_features) {
// Remove unsupported features if present.
PackedStringArray features = PackedStringArray(p_project_features);
PackedStringArray supported_features = _get_supported_features();
for (int i = p_project_features.size() - 1; i > -1; i--) {
if (!supported_features.has(p_project_features[i])) {
features.remove_at(i);
}
}
// Add required features if not present.
PackedStringArray required_features = get_required_features();
for (int i = 0; i < required_features.size(); i++) {
if (!features.has(required_features[i])) {
features.append(required_features[i]);
}
}
features.sort();
return features;
}

String ProjectSettings::localize_path(const String &p_path) const {
if (resource_path.is_empty() || p_path.begins_with("res://") || p_path.begins_with("user://") ||
(p_path.is_absolute_path() && !p_path.begins_with(resource_path))) {
Expand Down Expand Up @@ -635,6 +701,11 @@ Error ProjectSettings::_load_settings_text(const String &p_path) {
} else {
if (section == String()) {
set(assign, value);
} else if (section == "application" && assign == "config/features") {
const PackedStringArray project_features_untrimmed = value;
const PackedStringArray project_features = _trim_to_supported_features(project_features_untrimmed);
set("application/config/features", project_features);
save();
} else {
set(section + "/" + assign, value);
}
Expand Down Expand Up @@ -666,6 +737,13 @@ Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path,
return err;
}

Error ProjectSettings::load_custom(const String &p_path) {
if (p_path.ends_with(".binary")) {
return _load_settings_binary(p_path);
}
return _load_settings_text(p_path);
}

int ProjectSettings::get_order(const String &p_name) const {
ERR_FAIL_COND_V_MSG(!props.has(p_name), -1, "Request for nonexistent project setting: " + p_name + ".");
return props[p_name].order;
Expand Down
8 changes: 7 additions & 1 deletion core/config/project_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class ProjectSettings : public Object {
//properties that are not for built in values begin from this value, so builtin ones are displayed first
NO_BUILTIN_ORDER_BASE = 1 << 16
};
const static PackedStringArray get_required_features();
const static PackedStringArray get_unsupported_features(const PackedStringArray &p_project_features);

struct AutoloadInfo {
StringName name;
Expand Down Expand Up @@ -111,6 +113,9 @@ class ProjectSettings : public Object {

Error _save_custom_bnd(const String &p_file);

const static PackedStringArray _get_supported_features();
const static PackedStringArray _trim_to_supported_features(const PackedStringArray &p_project_features);

void _convert_to_last_version(int p_from_version);

bool _load_resource_pack(const String &p_pack, bool p_replace_files = true, int p_offset = 0);
Expand All @@ -125,7 +130,7 @@ class ProjectSettings : public Object {
static void _bind_methods();

public:
static const int CONFIG_VERSION = 4;
static const int CONFIG_VERSION = 5;

void set_setting(const String &p_setting, const Variant &p_value);
Variant get_setting(const String &p_setting) const;
Expand Down Expand Up @@ -158,6 +163,7 @@ class ProjectSettings : public Object {

Error setup(const String &p_path, const String &p_main_pack, bool p_upwards = false, bool p_ignore_override = false);

Error load_custom(const String &p_path);
Error save_custom(const String &p_path = "", const CustomMap &p_custom = CustomMap(), const Vector<String> &p_custom_features = Vector<String>(), bool p_merge_with_current = true);
Error save();
void set_custom_property_info(const String &p_prop, const PropertyInfo &p_info);
Expand Down
4 changes: 3 additions & 1 deletion core/io/config_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ Error ConfigFile::_internal_save(FileAccess *file) {
if (E != values.front()) {
file->store_string("\n");
}
file->store_string("[" + E.key() + "]\n\n");
if (E.key() != "") {
file->store_string("[" + E.key() + "]\n\n");
}

for (OrderedHashMap<String, Variant>::Element F = E.get().front(); F; F = F.next()) {
String vstr;
Expand Down
Loading

0 comments on commit e49b127

Please sign in to comment.