Make build profile project detection also set build options

This commit is contained in:
Michael Alexsander 2025-03-06 15:42:10 -03:00
parent e45cc68092
commit 454e4f817c
No known key found for this signature in database
GPG Key ID: A9C91EE110F4EABA
28 changed files with 786 additions and 82 deletions

View File

@ -862,6 +862,19 @@ String GDExtensionResourceLoader::get_resource_type(const String &p_path) const
}
#ifdef TOOLS_ENABLED
void GDExtensionResourceLoader::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
Ref<GDExtension> gdext = ResourceLoader::load(p_path);
if (gdext.is_null()) {
return;
}
for (const StringName class_name : gdext->get_classes_used()) {
if (ClassDB::class_exists(class_name)) {
r_classes->insert(class_name);
}
}
}
bool GDExtension::has_library_changed() const {
return loader->has_library_changed();
}

View File

@ -184,6 +184,9 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
virtual bool handles_type(const String &p_type) const override;
virtual String get_resource_type(const String &p_path) const override;
#ifdef TOOLS_ENABLED
virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes) override;
#endif // TOOLS_ENABLED
};
#ifdef TOOLS_ENABLED

View File

@ -36,6 +36,7 @@
#include "core/io/missing_resource.h"
#include "core/object/script_language.h"
#include "core/version.h"
#include "scene/resources/packed_scene.h"
//#define print_bl(m_what) print_line(m_what)
#define print_bl(m_what) (void)(m_what)
@ -937,11 +938,10 @@ void ResourceLoaderBinary::get_classes_used(Ref<FileAccess> p_f, HashSet<StringN
return;
}
for (int i = 0; i < internal_resources.size(); i++) {
p_f->seek(internal_resources[i].offset);
for (const IntResource &res : internal_resources) {
p_f->seek(res.offset);
String t = get_unicode_string();
ERR_FAIL_COND(p_f->get_error() != OK);
if (t != String()) {
if (!p_f->get_error() && t != String() && ClassDB::class_exists(t)) {
p_classes->insert(t);
}
}
@ -1518,6 +1518,37 @@ void ResourceFormatLoaderBinary::get_classes_used(const String &p_path, HashSet<
loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
loader.res_path = loader.local_path;
loader.get_classes_used(f, r_classes);
// Fetch the nodes inside scene files.
if (loader.type == "PackedScene") {
ERR_FAIL_COND(loader.load() != OK);
Ref<SceneState> state = Ref<PackedScene>(loader.get_resource())->get_state();
for (int i = 0; i < state->get_node_count(); i++) {
const StringName node_name = state->get_node_type(i);
if (ClassDB::class_exists(node_name)) {
r_classes->insert(node_name);
}
// Fetch the values of properties in the node.
for (int j = 0; j < state->get_node_property_count(i); j++) {
const Variant var = state->get_node_property_value(i, j);
if (var.get_type() != Variant::OBJECT) {
continue;
}
const Object *obj = var.get_validated_object();
if (obj == nullptr) {
continue;
}
const StringName obj_name = obj->get_class_name();
if (ClassDB::class_exists(obj_name)) {
r_classes->insert(obj_name);
}
}
}
}
}
String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const {

View File

@ -434,6 +434,7 @@ Variant ResourceFormatImporter::get_resource_metadata(const String &p_path) cons
return pat.metadata;
}
void ResourceFormatImporter::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat, false);
@ -456,6 +457,18 @@ void ResourceFormatImporter::get_dependencies(const String &p_path, List<String>
ResourceLoader::get_dependencies(pat.path, p_dependencies, p_add_types);
}
void ResourceFormatImporter::get_build_dependencies(const String &p_path, HashSet<String> *r_dependencies) {
if (!exists(p_path)) {
return;
}
List<Ref<ResourceImporter>> valid_importers;
get_importers_for_file(p_path, &valid_importers);
for (Ref<ResourceImporter> importer : valid_importers) {
importer->get_build_dependencies(p_path, r_dependencies);
}
}
Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_name(const String &p_name) const {
for (int i = 0; i < importers.size(); i++) {
if (importers[i]->get_importer_name() == p_name) {
@ -555,9 +568,21 @@ ResourceFormatImporter::ResourceFormatImporter() {
//////////////
void ResourceImporter::get_build_dependencies(const String &p_path, HashSet<String> *r_dependencies) {
Vector<String> ret;
if (GDVIRTUAL_CALL(_get_build_dependencies, p_path, ret)) {
for (int i = 0; i < ret.size(); i++) {
r_dependencies->insert(ret[i]);
}
return;
}
}
void ResourceImporter::_bind_methods() {
BIND_ENUM_CONSTANT(IMPORT_ORDER_DEFAULT);
BIND_ENUM_CONSTANT(IMPORT_ORDER_SCENE);
GDVIRTUAL_BIND(_get_build_dependencies, "path");
}
/////

View File

@ -78,6 +78,8 @@ public:
virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes) override;
virtual bool exists(const String &p_path) const override;
void get_build_dependencies(const String &p_path, HashSet<String> *r_dependencies);
virtual int get_import_order(const String &p_path) const override;
Error get_import_order_threads_and_importer(const String &p_path, int &r_order, bool &r_can_threads, String &r_importer) const;
@ -106,6 +108,8 @@ class ResourceImporter : public RefCounted {
GDCLASS(ResourceImporter, RefCounted);
protected:
GDVIRTUAL1RC(Vector<String>, _get_build_dependencies, String)
static void _bind_methods();
public:
@ -155,6 +159,8 @@ public:
virtual Error import_group_file(const String &p_group_file, const HashMap<String, HashMap<StringName, Variant>> &p_source_file_options, const HashMap<String, String> &p_base_paths) { return ERR_UNAVAILABLE; }
virtual bool are_import_settings_valid(const String &p_path, const Dictionary &p_meta) const { return true; }
virtual String get_import_settings_string() const { return String(); }
virtual void get_build_dependencies(const String &p_path, HashSet<String> *r_build_dependencies);
};
VARIANT_ENUM_CAST(ResourceImporter::ImportOrder);

View File

@ -2152,6 +2152,30 @@ bool ClassDB::is_class_runtime(const StringName &p_class) {
return ti->is_runtime;
}
#ifdef TOOLS_ENABLED
void ClassDB::add_class_dependency(const StringName &p_class, const StringName &p_dependency) {
Locker::Lock lock(Locker::STATE_WRITE);
ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class));
if (classes[p_class].dependency_list.find(p_dependency)) {
ERR_FAIL();
}
classes[p_class].dependency_list.push_back(p_dependency);
}
void ClassDB::get_class_dependencies(const StringName &p_class, List<StringName> *r_rependencies) {
Locker::Lock lock(Locker::STATE_READ);
ClassInfo *ti = classes.getptr(p_class);
ERR_FAIL_NULL_MSG(ti, vformat("Cannot get class '%s'.", String(p_class)));
for (const StringName &dep : ti->dependency_list) {
r_rependencies->push_back(dep);
}
}
#endif // TOOLS_ENABLED
void ClassDB::add_resource_base_extension(const StringName &p_extension, const StringName &p_class) {
if (resource_base_extensions.has(p_extension)) {
return;

View File

@ -118,6 +118,7 @@ public:
HashMap<StringName, MethodInfo> signal_map;
List<PropertyInfo> property_list;
HashMap<StringName, PropertyInfo> property_map;
#ifdef DEBUG_ENABLED
List<StringName> constant_order;
List<StringName> method_order;
@ -127,6 +128,11 @@ public:
HashMap<StringName, Vector<Error>> method_error_values;
HashMap<StringName, List<StringName>> linked_properties;
#endif // DEBUG_ENABLED
#ifdef TOOLS_ENABLED
List<StringName> dependency_list;
#endif
HashMap<StringName, PropertySetGet> property_setget;
HashMap<StringName, Vector<uint32_t>> virtual_methods_compat;
@ -499,6 +505,11 @@ public:
static bool is_class_reloadable(const StringName &p_class);
static bool is_class_runtime(const StringName &p_class);
#ifdef TOOLS_ENABLED
static void add_class_dependency(const StringName &p_class, const StringName &p_dependency);
static void get_class_dependencies(const StringName &p_class, List<StringName> *r_rependencies);
#endif
static void add_resource_base_extension(const StringName &p_extension, const StringName &p_class);
static void get_resource_base_extensions(List<String> *p_extensions);
static void get_extensions_for_type(const StringName &p_class, List<String> *p_extensions);

View File

@ -147,6 +147,12 @@ enum PropertyUsageFlags {
#define ADD_SUBGROUP_INDENT(m_name, m_prefix, m_depth) ::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix, m_depth)
#define ADD_LINKED_PROPERTY(m_property, m_linked_property) ::ClassDB::add_linked_property(get_class_static(), m_property, m_linked_property)
#ifdef TOOLS_ENABLED
#define ADD_CLASS_DEPENDENCY(m_class) ::ClassDB::add_class_dependency(get_class_static(), m_class)
#else
#define ADD_CLASS_DEPENDENCY(m_class)
#endif
#define ADD_ARRAY_COUNT(m_label, m_count_property, m_count_property_setter, m_count_property_getter, m_prefix) ClassDB::add_property_array_count(get_class_static(), m_label, m_count_property, StringName(m_count_property_setter), StringName(m_count_property_getter), m_prefix)
#define ADD_ARRAY_COUNT_WITH_USAGE_FLAGS(m_label, m_count_property, m_count_property_setter, m_count_property_getter, m_prefix, m_property_usage_flags) ClassDB::add_property_array_count(get_class_static(), m_label, m_count_property, StringName(m_count_property_setter), StringName(m_count_property_getter), m_prefix, m_property_usage_flags)
#define ADD_ARRAY(m_array_path, m_prefix) ClassDB::add_property_array(get_class_static(), m_array_path, m_prefix)
@ -979,7 +985,6 @@ public:
bool editor_is_section_unfolded(const String &p_section);
const HashSet<String> &editor_get_section_folding() const { return editor_section_folding; }
void editor_clear_section_folding() { editor_section_folding.clear(); }
#endif
// Used by script languages to store binding data.

View File

@ -9,6 +9,25 @@
<tutorials>
<link title="Import plugins">$DOCS_URL/tutorials/plugins/editor/import_plugins.html</link>
</tutorials>
<methods>
<method name="_get_build_dependencies" qualifiers="virtual const">
<return type="PackedStringArray" />
<param index="0" name="path" type="String" />
<description>
Called when the engine compilation profile editor wants to check what build options an imported resource needs. For example, [ResourceImporterDynamicFont] has a property called [member ResourceImporterDynamicFont.multichannel_signed_distance_field], that depends on the engine to be build with the "msdfgen" module. If that resource happened to be a custom one, it would be handled like this:
[codeblock]
func _get_build_dependencies(path):
var resource = load(path)
var dependencies = PackedStringArray()
if resource.multichannel_signed_distance_field:
dependencies.push_back("module_msdfgen_enabled")
return dependencies
[/codeblock]
</description>
</method>
</methods>
<constants>
<constant name="IMPORT_ORDER_DEFAULT" value="0" enum="ImportOrder">
The default import order.

View File

@ -30,6 +30,7 @@
#include "editor_build_profile.h"
#include "core/config/project_settings.h"
#include "core/io/json.h"
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
@ -41,36 +42,60 @@
#include "scene/gui/line_edit.h"
#include "scene/gui/separator.h"
#include "modules/modules_enabled.gen.h" // For mono.
const char *EditorBuildProfile::build_option_identifiers[BUILD_OPTION_MAX] = {
// This maps to SCons build options.
"disable_3d",
"disable_2d_physics",
"disable_3d_physics",
"disable_navigation",
"disable_navigation_2d",
"disable_navigation_3d",
"disable_xr",
"rendering_device", // FIXME: there's no scons option to disable rendering device
"opengl3",
"module_openxr_enabled",
"wayland",
"x11",
"rendering_device", // FIXME: There's no scons option to disable rendering device.
"forward_plus_renderer",
"forward_mobile_renderer",
"vulkan",
"d3d12",
"metal",
"opengl3",
"disable_physics_2d",
"module_godot_physics_2d_enabled",
"disable_physics_3d",
"module_godot_physics_3d_enabled",
"module_jolt_physics_enabled",
"module_text_server_fb_enabled",
"module_text_server_adv_enabled",
"module_freetype_enabled",
"brotli",
"graphite",
"module_msdfgen_enabled"
"module_msdfgen_enabled",
};
const bool EditorBuildProfile::build_option_disabled_by_default[BUILD_OPTION_MAX] = {
// This maps to SCons build options.
false, // 3D
false, // PHYSICS_2D
false, // PHYSICS_3D
false, // NAVIGATION
false, // NAVIGATION_2D
false, // NAVIGATION_3D
false, // XR
false, // OPENXR
false, // WAYLAND
false, // X11
false, // RENDERING_DEVICE
false, // OPENGL
false, // FORWARD_RENDERER
false, // MOBILE_RENDERER
false, // VULKAN
false, // D3D12
false, // METAL
false, // OPENGL
false, // PHYSICS_2D
false, // PHYSICS_GODOT_2D
false, // PHYSICS_3D
false, // PHYSICS_GODOT_3D
false, // PHYSICS_JOLT
true, // TEXT_SERVER_FALLBACK
false, // TEXT_SERVER_COMPLEX
false, // TEXT_SERVER_ADVANCED
false, // DYNAMIC_FONTS
false, // WOFF2_FONTS
false, // GRAPHITE_FONTS
@ -80,38 +105,215 @@ const bool EditorBuildProfile::build_option_disabled_by_default[BUILD_OPTION_MAX
const bool EditorBuildProfile::build_option_disable_values[BUILD_OPTION_MAX] = {
// This maps to SCons build options.
true, // 3D
true, // PHYSICS_2D
true, // PHYSICS_3D
true, // NAVIGATION
true, // NAVIGATION_2D
true, // NAVIGATION_3D
true, // XR
false, // OPENXR
false, // WAYLAND
false, // X11
false, // RENDERING_DEVICE
false, // OPENGL
false, // FORWARD_RENDERER
false, // MOBILE_RENDERER
false, // VULKAN
false, // D3D12
false, // METAL
false, // OPENGL
true, // PHYSICS_2D
false, // PHYSICS_GODOT_2D
true, // PHYSICS_3D
false, // PHYSICS_GODOT_3D
false, // PHYSICS_JOLT
false, // TEXT_SERVER_FALLBACK
false, // TEXT_SERVER_COMPLEX
false, // TEXT_SERVER_ADVANCED
false, // DYNAMIC_FONTS
false, // WOFF2_FONTS
false, // GRAPHITE_FONTS
false, // MSDFGEN
};
// Options that require some resource explicitly asking for them when detecting from the project.
const bool EditorBuildProfile::build_option_explicit_use[BUILD_OPTION_MAX] = {
false, // 3D
false, // NAVIGATION_2D
false, // NAVIGATION_3D
false, // XR
false, // OPENXR
false, // WAYLAND
false, // X11
false, // RENDERING_DEVICE
false, // FORWARD_RENDERER
false, // MOBILE_RENDERER
false, // VULKAN
false, // D3D12
false, // METAL
false, // OPENGL
false, // PHYSICS_2D
false, // PHYSICS_GODOT_2D
false, // PHYSICS_3D
false, // PHYSICS_GODOT_3D
false, // PHYSICS_JOLT
false, // TEXT_SERVER_FALLBACK
false, // TEXT_SERVER_ADVANCED
false, // DYNAMIC_FONTS
false, // WOFF2_FONTS
false, // GRAPHITE_FONTS
true, // MSDFGEN
};
const EditorBuildProfile::BuildOptionCategory EditorBuildProfile::build_option_category[BUILD_OPTION_MAX] = {
BUILD_OPTION_CATEGORY_GENERAL, // 3D
BUILD_OPTION_CATEGORY_GENERAL, // PHYSICS_2D
BUILD_OPTION_CATEGORY_GENERAL, // PHYSICS_3D
BUILD_OPTION_CATEGORY_GENERAL, // NAVIGATION
BUILD_OPTION_CATEGORY_GENERAL, // NAVIGATION_2D
BUILD_OPTION_CATEGORY_GENERAL, // NAVIGATION_3D
BUILD_OPTION_CATEGORY_GENERAL, // XR
BUILD_OPTION_CATEGORY_GENERAL, // RENDERING_DEVICE
BUILD_OPTION_CATEGORY_GENERAL, // OPENGL
BUILD_OPTION_CATEGORY_GENERAL, // VULKAN
BUILD_OPTION_CATEGORY_GENERAL, // OPENXR
BUILD_OPTION_CATEGORY_GENERAL, // WAYLAND
BUILD_OPTION_CATEGORY_GENERAL, // X11
BUILD_OPTION_CATEGORY_GRAPHICS, // RENDERING_DEVICE
BUILD_OPTION_CATEGORY_GRAPHICS, // FORWARD_RENDERER
BUILD_OPTION_CATEGORY_GRAPHICS, // MOBILE_RENDERER
BUILD_OPTION_CATEGORY_GRAPHICS, // VULKAN
BUILD_OPTION_CATEGORY_GRAPHICS, // D3D12
BUILD_OPTION_CATEGORY_GRAPHICS, // METAL
BUILD_OPTION_CATEGORY_GRAPHICS, // OPENGL
BUILD_OPTION_CATEGORY_PHYSICS, // PHYSICS_2D
BUILD_OPTION_CATEGORY_PHYSICS, // PHYSICS_GODOT_2D
BUILD_OPTION_CATEGORY_PHYSICS, // PHYSICS_3D
BUILD_OPTION_CATEGORY_PHYSICS, // PHYSICS_GODOT_3D
BUILD_OPTION_CATEGORY_PHYSICS, // PHYSICS_JOLT
BUILD_OPTION_CATEGORY_TEXT_SERVER, // TEXT_SERVER_FALLBACK
BUILD_OPTION_CATEGORY_TEXT_SERVER, // TEXT_SERVER_COMPLEX
BUILD_OPTION_CATEGORY_TEXT_SERVER, // TEXT_SERVER_ADVANCED
BUILD_OPTION_CATEGORY_TEXT_SERVER, // DYNAMIC_FONTS
BUILD_OPTION_CATEGORY_TEXT_SERVER, // WOFF2_FONTS
BUILD_OPTION_CATEGORY_TEXT_SERVER, // GRAPHITE_FONTS
BUILD_OPTION_CATEGORY_TEXT_SERVER, // MSDFGEN
};
// Can't assign HashMaps to a HashMap at declaration, so do it in the class' constructor.
HashMap<EditorBuildProfile::BuildOption, HashMap<String, LocalVector<Variant>>> EditorBuildProfile::build_option_settings = {};
/* clang-format off */
const HashMap<EditorBuildProfile::BuildOption, LocalVector<EditorBuildProfile::BuildOption>> EditorBuildProfile::build_option_dependencies = {
{ BUILD_OPTION_OPENXR, {
BUILD_OPTION_XR,
} },
{ BUILD_OPTION_FORWARD_RENDERER, {
BUILD_OPTION_RENDERING_DEVICE,
} },
{ BUILD_OPTION_MOBILE_RENDERER, {
BUILD_OPTION_RENDERING_DEVICE,
} },
{ BUILD_OPTION_VULKAN, {
BUILD_OPTION_FORWARD_RENDERER,
BUILD_OPTION_MOBILE_RENDERER,
} },
{ BUILD_OPTION_D3D12, {
BUILD_OPTION_FORWARD_RENDERER,
BUILD_OPTION_MOBILE_RENDERER,
} },
{ BUILD_OPTION_METAL, {
BUILD_OPTION_FORWARD_RENDERER,
BUILD_OPTION_MOBILE_RENDERER,
} },
{ BUILD_OPTION_PHYSICS_GODOT_2D, {
BUILD_OPTION_PHYSICS_2D,
} },
{ BUILD_OPTION_PHYSICS_GODOT_3D, {
BUILD_OPTION_PHYSICS_3D,
} },
{ BUILD_OPTION_PHYSICS_JOLT, {
BUILD_OPTION_PHYSICS_3D,
} },
{ BUILD_OPTION_DYNAMIC_FONTS, {
BUILD_OPTION_TEXT_SERVER_ADVANCED,
} },
{ BUILD_OPTION_WOFF2_FONTS, {
BUILD_OPTION_TEXT_SERVER_ADVANCED,
} },
{ BUILD_OPTION_GRAPHITE_FONTS, {
BUILD_OPTION_TEXT_SERVER_ADVANCED,
} },
};
const HashMap<EditorBuildProfile::BuildOption, LocalVector<String>> EditorBuildProfile::build_option_classes = {
{ BUILD_OPTION_3D, {
"Node3D",
} },
{ BUILD_OPTION_NAVIGATION_2D, {
"NavigationAgent2D",
"NavigationLink2D",
"NavigationMeshSourceGeometryData2D",
"NavigationObstacle2D"
"NavigationPolygon",
"NavigationRegion2D",
} },
{ BUILD_OPTION_NAVIGATION_3D, {
"NavigationAgent3D",
"NavigationLink3D",
"NavigationMeshSourceGeometryData3D",
"NavigationObstacle3D",
"NavigationRegion3D",
} },
{ BUILD_OPTION_XR, {
"XRBodyModifier3D",
"XRBodyTracker",
"XRControllerTracker",
"XRFaceModifier3D",
"XRFaceTracker",
"XRHandModifier3D",
"XRHandTracker",
"XRInterface",
"XRInterfaceExtension",
"XRNode3D",
"XROrigin3D",
"XRPose",
"XRPositionalTracker",
"XRServer",
"XRTracker",
"XRVRS",
} },
{ BUILD_OPTION_RENDERING_DEVICE, {
"RenderingDevice",
} },
{ BUILD_OPTION_PHYSICS_2D, {
"CollisionObject2D",
"CollisionPolygon2D",
"CollisionShape2D",
"Joint2D",
"PhysicsServer2D",
"PhysicsServer2DManager",
"ShapeCast2D",
"RayCast2D",
"TouchScreenButton",
} },
{ BUILD_OPTION_PHYSICS_3D, {
"CollisionObject3D",
"CollisionPolygon3D",
"CollisionShape3D",
"CSGShape3D",
"GPUParticlesAttractor3D",
"GPUParticlesCollision3D",
"Joint3D",
"PhysicalBoneSimulator3D",
"PhysicsServer3D",
"PhysicsServer3DManager",
"PhysicsServer3DRenderingServerHandler",
"RayCast3D",
"SoftBody3D",
"SpringArm3D",
"SpringBoneCollision3D",
"SpringBoneSimulator3D",
"VehicleWheel3D",
} },
{ BUILD_OPTION_TEXT_SERVER_ADVANCED, {
"CanvasItem",
"Label3D",
"TextServerAdvanced",
} },
};
/* clang-format on */
void EditorBuildProfile::set_disable_class(const StringName &p_class, bool p_disabled) {
if (p_disabled) {
disabled_classes.insert(p_class);
@ -159,6 +361,17 @@ bool EditorBuildProfile::get_build_option_disable_value(BuildOption p_build_opti
return build_option_disable_values[p_build_option];
}
bool EditorBuildProfile::get_build_option_explicit_use(BuildOption p_build_option) {
ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, false);
return build_option_explicit_use[p_build_option];
}
void EditorBuildProfile::reset_build_options() {
for (int i = 0; i < EditorBuildProfile::BUILD_OPTION_MAX; i++) {
build_options_disabled[i] = build_option_disabled_by_default[i];
}
}
void EditorBuildProfile::set_force_detect_classes(const String &p_classes) {
force_detect_classes = p_classes;
}
@ -171,13 +384,24 @@ String EditorBuildProfile::get_build_option_name(BuildOption p_build_option) {
ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, String());
const char *build_option_names[BUILD_OPTION_MAX] = {
TTRC("3D Engine"),
TTRC("2D Physics"),
TTRC("3D Physics"),
TTRC("Navigation"),
TTRC("Navigation (2D)"),
TTRC("Navigation (3D)"),
TTRC("XR"),
TTRC("OpenXR"),
TTRC("Wayland"),
TTRC("X11"),
TTRC("RenderingDevice"),
TTRC("OpenGL"),
TTRC("Forward+ Renderer"),
TTRC("Mobile Renderer"),
TTRC("Vulkan"),
TTRC("D3D12"),
TTRC("Metal"),
TTRC("OpenGL"),
TTRC("Physics Server (2D)"),
TTRC("Godot Physics (2D)"),
TTRC("Physics Server (3D)"),
TTRC("Godot Physics (3D)"),
TTRC("Jolt Physics"),
TTRC("Text Server: Fallback"),
TTRC("Text Server: Advanced"),
TTRC("TTF, OTF, Type 1, WOFF1 Fonts"),
@ -193,13 +417,24 @@ String EditorBuildProfile::get_build_option_description(BuildOption p_build_opti
const char *build_option_descriptions[BUILD_OPTION_MAX] = {
TTRC("3D Nodes as well as RenderingServer access to 3D features."),
TTRC("2D Physics nodes and PhysicsServer2D."),
TTRC("3D Physics nodes and PhysicsServer3D."),
TTRC("Navigation, both 2D and 3D."),
TTRC("Navigation Server and capabilities for 2D."),
TTRC("Navigation Server and capabilities for 3D."),
TTRC("XR (AR and VR)."),
TTRC("RenderingDevice based rendering (if disabled, the OpenGL back-end is required)."),
TTRC("OpenGL back-end (if disabled, the RenderingDevice back-end is required)."),
TTRC("Vulkan back-end of RenderingDevice."),
TTRC("OpenXR standard implementation (requires XR to be enabled)."),
TTRC("Wayland display (Linux only)."),
TTRC("X11 display (Linux only)."),
TTRC("RenderingDevice based rendering (if disabled, the OpenGL backend is required)."),
TTRC("Forward+ renderer for advanced 3D graphics."),
TTRC("Mobile renderer for less advanced 3D graphics."),
TTRC("Vulkan backend of RenderingDevice."),
TTRC("Direct3D 12 backend of RenderingDevice."),
TTRC("Metal backend of RenderingDevice (Apple arm64 only)."),
TTRC("OpenGL backend (if disabled, the RenderingDevice backend is required)."),
TTRC("Physics Server and capabilities for 2D."),
TTRC("Godot Physics backend (2D)."),
TTRC("Physics Server and capabilities for 3D."),
TTRC("Godot Physics backend (3D)."),
TTRC("Jolt Physics backend (3D only)."),
TTRC("Fallback implementation of Text Server\nSupports basic text layouts."),
TTRC("Text Server implementation powered by ICU and HarfBuzz libraries.\nSupports complex text layouts, BiDi, and contextual OpenType font features."),
TTRC("TrueType, OpenType, Type 1, and WOFF1 font format support using FreeType library (if disabled, WOFF2 support is also disabled)."),
@ -211,16 +446,38 @@ String EditorBuildProfile::get_build_option_description(BuildOption p_build_opti
return TTRGET(build_option_descriptions[p_build_option]);
}
String EditorBuildProfile::get_build_option_identifier(BuildOption p_build_option) {
ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, String());
return build_option_identifiers[p_build_option];
}
EditorBuildProfile::BuildOptionCategory EditorBuildProfile::get_build_option_category(BuildOption p_build_option) {
ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, BUILD_OPTION_CATEGORY_GENERAL);
return build_option_category[p_build_option];
}
LocalVector<EditorBuildProfile::BuildOption> EditorBuildProfile::get_build_option_dependencies(BuildOption p_build_option) {
ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, LocalVector<EditorBuildProfile::BuildOption>());
return build_option_dependencies.has(p_build_option) ? build_option_dependencies[p_build_option] : LocalVector<EditorBuildProfile::BuildOption>();
}
HashMap<String, LocalVector<Variant>> EditorBuildProfile::get_build_option_settings(BuildOption p_build_option) {
ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, (HashMap<String, LocalVector<Variant>>()));
return build_option_settings.has(p_build_option) ? build_option_settings[p_build_option] : HashMap<String, LocalVector<Variant>>();
}
LocalVector<String> EditorBuildProfile::get_build_option_classes(BuildOption p_build_option) {
ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, LocalVector<String>());
return build_option_classes.has(p_build_option) ? build_option_classes[p_build_option] : LocalVector<String>();
}
String EditorBuildProfile::get_build_option_category_name(BuildOptionCategory p_build_option_category) {
ERR_FAIL_INDEX_V(p_build_option_category, BUILD_OPTION_CATEGORY_MAX, String());
const char *build_option_subcategories[BUILD_OPTION_CATEGORY_MAX]{
TTRC("General Features:"),
TTRC("Graphics and Rendering:"),
TTRC("Physics Systems:"),
TTRC("Text Rendering and Font Options:"),
};
@ -332,13 +589,24 @@ void EditorBuildProfile::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_from_file", "path"), &EditorBuildProfile::load_from_file);
BIND_ENUM_CONSTANT(BUILD_OPTION_3D);
BIND_ENUM_CONSTANT(BUILD_OPTION_PHYSICS_2D);
BIND_ENUM_CONSTANT(BUILD_OPTION_PHYSICS_3D);
BIND_ENUM_CONSTANT(BUILD_OPTION_NAVIGATION);
BIND_ENUM_CONSTANT(BUILD_OPTION_NAVIGATION_2D);
BIND_ENUM_CONSTANT(BUILD_OPTION_NAVIGATION_3D);
BIND_ENUM_CONSTANT(BUILD_OPTION_XR);
BIND_ENUM_CONSTANT(BUILD_OPTION_OPENXR);
BIND_ENUM_CONSTANT(BUILD_OPTION_WAYLAND);
BIND_ENUM_CONSTANT(BUILD_OPTION_X11);
BIND_ENUM_CONSTANT(BUILD_OPTION_RENDERING_DEVICE);
BIND_ENUM_CONSTANT(BUILD_OPTION_OPENGL);
BIND_ENUM_CONSTANT(BUILD_OPTION_FORWARD_RENDERER);
BIND_ENUM_CONSTANT(BUILD_OPTION_MOBILE_RENDERER);
BIND_ENUM_CONSTANT(BUILD_OPTION_VULKAN);
BIND_ENUM_CONSTANT(BUILD_OPTION_D3D12);
BIND_ENUM_CONSTANT(BUILD_OPTION_METAL);
BIND_ENUM_CONSTANT(BUILD_OPTION_OPENGL);
BIND_ENUM_CONSTANT(BUILD_OPTION_PHYSICS_2D);
BIND_ENUM_CONSTANT(BUILD_OPTION_PHYSICS_GODOT_2D);
BIND_ENUM_CONSTANT(BUILD_OPTION_PHYSICS_3D);
BIND_ENUM_CONSTANT(BUILD_OPTION_PHYSICS_GODOT_3D);
BIND_ENUM_CONSTANT(BUILD_OPTION_PHYSICS_JOLT);
BIND_ENUM_CONSTANT(BUILD_OPTION_TEXT_SERVER_FALLBACK);
BIND_ENUM_CONSTANT(BUILD_OPTION_TEXT_SERVER_ADVANCED);
BIND_ENUM_CONSTANT(BUILD_OPTION_DYNAMIC_FONTS);
@ -348,14 +616,78 @@ void EditorBuildProfile::_bind_methods() {
BIND_ENUM_CONSTANT(BUILD_OPTION_MAX);
BIND_ENUM_CONSTANT(BUILD_OPTION_CATEGORY_GENERAL);
BIND_ENUM_CONSTANT(BUILD_OPTION_CATEGORY_GRAPHICS);
BIND_ENUM_CONSTANT(BUILD_OPTION_CATEGORY_PHYSICS);
BIND_ENUM_CONSTANT(BUILD_OPTION_CATEGORY_TEXT_SERVER);
BIND_ENUM_CONSTANT(BUILD_OPTION_CATEGORY_MAX);
}
EditorBuildProfile::EditorBuildProfile() {
for (int i = 0; i < EditorBuildProfile::BUILD_OPTION_MAX; i++) {
build_options_disabled[i] = build_option_disabled_by_default[i];
}
reset_build_options();
HashMap<String, LocalVector<Variant>> settings_openxr = {
{ "xr/openxr/enabled", { true } },
};
build_option_settings.insert(BUILD_OPTION_OPENXR, settings_openxr);
HashMap<String, LocalVector<Variant>> settings_wayland = {
{ "display/display_server/driver.linuxbsd", { "default", "wayland" } },
};
build_option_settings.insert(BUILD_OPTION_OPENXR, settings_wayland);
HashMap<String, LocalVector<Variant>> settings_x11 = {
{ "display/display_server/driver.linuxbsd", { "default", "x11" } },
};
build_option_settings.insert(BUILD_OPTION_OPENXR, settings_x11);
HashMap<String, LocalVector<Variant>> settings_rd = {
{ "rendering/renderer/rendering_method", { "forward_plus", "mobile" } },
{ "rendering/renderer/rendering_method.mobile", { "forward_plus", "mobile" } },
{ "rendering/renderer/rendering_method.web", { "forward_plus", "mobile" } },
};
build_option_settings.insert(BUILD_OPTION_RENDERING_DEVICE, settings_rd);
HashMap<String, LocalVector<Variant>> settings_vulkan = {
{ "rendering/rendering_device/driver", { "vulkan" } },
{ "rendering/rendering_device/driver.windows", { "vulkan" } },
{ "rendering/rendering_device/driver.linuxbsd", { "vulkan" } },
{ "rendering/rendering_device/driver.android", { "vulkan" } },
{ "rendering/rendering_device/driver.ios", { "vulkan" } },
{ "rendering/rendering_device/driver.macos", { "vulkan" } },
{ "rendering/rendering_device/fallback_to_vulkan", { true } },
};
build_option_settings.insert(BUILD_OPTION_VULKAN, settings_vulkan);
HashMap<String, LocalVector<Variant>> settings_d3d12 = {
{ "rendering/rendering_device/driver", { "d3d12" } },
{ "rendering/rendering_device/driver.windows", { "d3d12" } },
{ "rendering/rendering_device/driver.linuxbsd", { "d3d12" } },
{ "rendering/rendering_device/driver.android", { "d3d12" } },
{ "rendering/rendering_device/driver.ios", { "d3d12" } },
{ "rendering/rendering_device/driver.macos", { "d3d12" } },
{ "rendering/rendering_device/fallback_to_d3d12", { true } },
};
build_option_settings.insert(BUILD_OPTION_VULKAN, settings_vulkan);
HashMap<String, LocalVector<Variant>> settings_metal = {
{ "rendering/rendering_device/driver", { "metal" } },
{ "rendering/rendering_device/driver.ios", { "metal" } },
{ "rendering/rendering_device/driver.macos", { "metal" } },
};
build_option_settings.insert(BUILD_OPTION_METAL, settings_metal);
HashMap<String, LocalVector<Variant>> settings_opengl = {
{ "rendering/renderer/rendering_method", { "gl_compatibility" } },
{ "rendering/renderer/rendering_method.mobile", { "gl_compatibility" } },
{ "rendering/renderer/rendering_method.web", { "gl_compatibility" } },
{ "rendering/rendering_device/fallback_to_opengl3", { true } },
};
build_option_settings.insert(BUILD_OPTION_OPENGL, settings_opengl);
HashMap<String, LocalVector<Variant>> settings_phy_godot_3d = {
{ "physics/3d/physics_engine", { "DEFAULT", "GodotPhysics3D" } },
};
build_option_settings.insert(BUILD_OPTION_PHYSICS_GODOT_3D, settings_phy_godot_3d);
HashMap<String, LocalVector<Variant>> settings_jolt = {
{ "physics/3d/physics_engine", { "Jolt Physics" } },
};
build_option_settings.insert(BUILD_OPTION_PHYSICS_JOLT, settings_jolt);
HashMap<String, LocalVector<Variant>> settings_msdfgen = {
{ "gui/theme/default_font_multichannel_signed_distance_field", { true } },
};
build_option_settings.insert(BUILD_OPTION_MSDFGEN, settings_msdfgen);
}
//////////////////////////
@ -406,7 +738,11 @@ void EditorBuildProfileManager::_profile_action(int p_action) {
confirm_dialog->popup_centered();
} break;
case ACTION_DETECT: {
confirm_dialog->set_text(TTR("This will scan all files in the current project to detect used classes."));
String text = TTR("This will scan all files in the current project to detect used classes.\nNote that the first scan may take a while, specially in larger projects.");
#ifdef MODULE_MONO_ENABLED
text += "\n\n" + TTR("Warning: Class detection for C# scripts is not currently available, and such files will be ignored.");
#endif // MODULE_MONO_ENABLED
confirm_dialog->set_text(text);
confirm_dialog->popup_centered();
} break;
case ACTION_MAX: {
@ -415,23 +751,35 @@ void EditorBuildProfileManager::_profile_action(int p_action) {
}
void EditorBuildProfileManager::_find_files(EditorFileSystemDirectory *p_dir, const HashMap<String, DetectedFile> &p_cache, HashMap<String, DetectedFile> &r_detected) {
if (p_dir == nullptr) {
if (p_dir == nullptr || p_dir->get_path().get_file().begins_with(".")) {
return;
}
for (int i = 0; i < p_dir->get_file_count(); i++) {
String p = p_dir->get_file_path(i);
if (EditorNode::get_singleton()->progress_task_step("detect_classes_from_project", p, 1)) {
project_scan_canceled = true;
return;
}
String p_check = p;
// Make so that the import file is the one checked if available,
// so the cache can be updated when it changes.
if (ResourceFormatImporter::get_singleton()->exists(p_check)) {
p_check += ".import";
}
uint64_t timestamp = 0;
String md5;
if (p_cache.has(p)) {
const DetectedFile &cache = p_cache[p];
// Check if timestamp and MD5 match.
timestamp = FileAccess::get_modified_time(p);
timestamp = FileAccess::get_modified_time(p_check);
bool cache_valid = true;
if (cache.timestamp != timestamp) {
md5 = FileAccess::get_md5(p);
md5 = FileAccess::get_md5(p_check);
if (md5 != cache.md5) {
cache_valid = false;
}
@ -449,14 +797,19 @@ void EditorBuildProfileManager::_find_files(EditorFileSystemDirectory *p_dir, co
HashSet<StringName> classes;
ResourceLoader::get_classes_used(p, &classes);
for (const StringName &E : classes) {
cache.classes.push_back(E);
}
HashSet<String> build_deps;
ResourceFormatImporter::get_singleton()->get_build_dependencies(p, &build_deps);
for (const String &E : build_deps) {
cache.build_deps.push_back(E);
}
if (md5.is_empty()) {
cache.timestamp = FileAccess::get_modified_time(p);
cache.md5 = FileAccess::get_md5(p);
cache.timestamp = FileAccess::get_modified_time(p_check);
cache.md5 = FileAccess::get_md5(p_check);
} else {
cache.timestamp = timestamp;
cache.md5 = md5;
@ -470,7 +823,9 @@ void EditorBuildProfileManager::_find_files(EditorFileSystemDirectory *p_dir, co
}
}
void EditorBuildProfileManager::_detect_classes() {
void EditorBuildProfileManager::_detect_from_project() {
EditorNode::get_singleton()->progress_add_task("detect_classes_from_project", TTRC("Scanning Project for Used Classes"), 3, true);
HashMap<String, DetectedFile> previous_file_cache;
Ref<FileAccess> f = FileAccess::open(EditorPaths::get_singleton()->get_project_settings_dir().path_join("used_class_cache"), FileAccess::READ);
@ -478,12 +833,13 @@ void EditorBuildProfileManager::_detect_classes() {
while (!f->eof_reached()) {
String l = f->get_line();
Vector<String> fields = l.split("::");
if (fields.size() == 4) {
if (fields.size() == 5) {
const String &path = fields[0];
DetectedFile df;
df.timestamp = fields[1].to_int();
df.md5 = fields[2];
df.classes = fields[3].split(",");
df.classes = fields[3].split(",", false);
df.build_deps = fields[4].split(",", false);
previous_file_cache.insert(path, df);
}
}
@ -494,7 +850,17 @@ void EditorBuildProfileManager::_detect_classes() {
_find_files(EditorFileSystem::get_singleton()->get_filesystem(), previous_file_cache, updated_file_cache);
if (project_scan_canceled) {
project_scan_canceled = false;
EditorNode::get_singleton()->progress_end_task("detect_classes_from_project");
return;
}
EditorNode::get_singleton()->progress_task_step("detect_classes_from_project", TTRC("Processing Classes Found"), 2);
HashSet<StringName> used_classes;
LocalVector<String> used_build_deps;
// Find classes and update the disk cache in the process.
f = FileAccess::open(EditorPaths::get_singleton()->get_project_settings_dir().path_join("used_class_cache"), FileAccess::WRITE);
@ -509,20 +875,41 @@ void EditorBuildProfileManager::_detect_classes() {
l += c;
used_classes.insert(c);
}
l += "::";
for (int i = 0; i < E.value.build_deps.size(); i++) {
String c = E.value.build_deps[i];
if (i > 0) {
l += ",";
}
l += c;
used_build_deps.push_back(c);
}
f->store_line(l);
}
f.unref();
// Add forced ones.
// Add classes that are either necessary for the engine to work properly, or there isn't a way to infer their use.
Vector<String> force_detect = edited->get_force_detect_classes().split(",");
for (int i = 0; i < force_detect.size(); i++) {
String c = force_detect[i].strip_edges();
if (c.is_empty()) {
continue;
const LocalVector<String> hardcoded_classes = { "InputEvent", "MainLoop", "StyleBox" };
for (const String &hc_class : hardcoded_classes) {
used_classes.insert(hc_class);
LocalVector<StringName> inheriters;
ClassDB::get_inheriters_from_class(hc_class, inheriters);
for (const StringName &inheriter : inheriters) {
used_classes.insert(inheriter);
}
}
// Add forced classes typed by the user.
const Vector<String> force_detect = edited->get_force_detect_classes().split(",");
for (const String &class_name : force_detect) {
const String class_stripped = class_name.strip_edges();
if (!class_stripped.is_empty()) {
used_classes.insert(class_stripped);
}
used_classes.insert(c);
}
// Filter all classes to discard inherited ones.
@ -532,13 +919,23 @@ void EditorBuildProfileManager::_detect_classes() {
for (const StringName &E : used_classes) {
StringName c = E;
if (!ClassDB::class_exists(c)) {
// Maybe this is an old class that got replaced? try getting compat class.
// Maybe this is an old class that got replaced? Try getting compat class.
c = ClassDB::get_compatibility_class(c);
if (!c) {
// No luck, skip.
continue;
}
}
List<StringName> dependencies;
ClassDB::get_class_dependencies(E, &dependencies);
for (const StringName &dep : dependencies) {
if (!all_used_classes.has(dep)) {
// Add classes which this class depends upon.
all_used_classes.insert(dep);
}
}
while (c) {
all_used_classes.insert(c);
c = ClassDB::get_parent_class(c);
@ -551,8 +948,8 @@ void EditorBuildProfileManager::_detect_classes() {
ClassDB::get_class_list(&all_classes);
for (const StringName &E : all_classes) {
if (all_used_classes.has(E)) {
// This class is valid, do nothing.
if (String(E).begins_with("Editor") || ClassDB::get_api_type(E) != ClassDB::API_CORE || all_used_classes.has(E)) {
// This class is valid or editor-only, do nothing.
continue;
}
@ -563,6 +960,88 @@ void EditorBuildProfileManager::_detect_classes() {
edited->set_disable_class(E, true);
}
}
edited->reset_build_options();
for (int i = 0; i < EditorBuildProfile::BUILD_OPTION_MAX; i++) {
// Check if the build option requires other options that are currently disabled.
LocalVector<EditorBuildProfile::BuildOption> dependencies = EditorBuildProfile::get_build_option_dependencies(EditorBuildProfile::BuildOption(i));
if (!dependencies.is_empty()) {
bool disable = true;
for (EditorBuildProfile::BuildOption dependency : dependencies) {
if (!edited->is_build_option_disabled(dependency)) {
disable = false;
break;
}
}
if (disable) {
edited->set_disable_build_option(EditorBuildProfile::BuildOption(i), true);
continue;
}
}
bool skip = false;
bool ignore = true;
// Check if the build option has enabled classes using it.
const LocalVector<String> classes = EditorBuildProfile::get_build_option_classes(EditorBuildProfile::BuildOption(i));
if (!classes.is_empty()) {
for (StringName class_name : classes) {
if (!edited->is_class_disabled(class_name)) {
skip = true;
break;
}
}
if (skip) {
continue;
}
ignore = false;
}
// Check if there's project settings requiring it.
const HashMap<String, LocalVector<Variant>> settings_list = EditorBuildProfile::get_build_option_settings(EditorBuildProfile::BuildOption(i));
if (!settings_list.is_empty()) {
for (KeyValue<String, LocalVector<Variant>> KV : settings_list) {
Variant proj_value = GLOBAL_GET(KV.key);
for (Variant value : KV.value) {
if (proj_value == value) {
skip = true;
break;
}
}
if (skip) {
break;
}
}
if (skip) {
continue;
}
ignore = false;
}
// Check if a resource setting depends on it.
if (used_build_deps.has(EditorBuildProfile::get_build_option_identifier(EditorBuildProfile::BuildOption(i)))) {
continue;
} else if (EditorBuildProfile::get_build_option_explicit_use(EditorBuildProfile::BuildOption(i))) {
ignore = false;
}
if (!skip && !ignore) {
edited->set_disable_build_option(EditorBuildProfile::BuildOption(i), true);
}
}
if (edited->is_build_option_disabled(EditorBuildProfile::BUILD_OPTION_TEXT_SERVER_ADVANCED)) {
edited->set_disable_build_option(EditorBuildProfile::BUILD_OPTION_TEXT_SERVER_FALLBACK, false);
}
EditorNode::get_singleton()->progress_end_task("detect_classes_from_project");
}
void EditorBuildProfileManager::_action_confirm() {
@ -583,7 +1062,7 @@ void EditorBuildProfileManager::_action_confirm() {
_update_edited_profile();
} break;
case ACTION_DETECT: {
_detect_classes();
_detect_from_project();
_update_edited_profile();
} break;
case ACTION_MAX: {
@ -869,7 +1348,7 @@ EditorBuildProfileManager::EditorBuildProfileManager() {
add_child(import_profile);
import_profile->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
import_profile->add_filter("*.gdbuild,*.build", TTR("Engine Compilation Profile"));
import_profile->connect("files_selected", callable_mp(this, &EditorBuildProfileManager::_import_profile));
import_profile->connect("file_selected", callable_mp(this, &EditorBuildProfileManager::_import_profile));
import_profile->set_title(TTR("Load Profile"));
import_profile->set_access(EditorFileDialog::ACCESS_FILESYSTEM);

View File

@ -41,13 +41,24 @@ class EditorBuildProfile : public RefCounted {
public:
enum BuildOption {
BUILD_OPTION_3D,
BUILD_OPTION_PHYSICS_2D,
BUILD_OPTION_PHYSICS_3D,
BUILD_OPTION_NAVIGATION,
BUILD_OPTION_NAVIGATION_2D,
BUILD_OPTION_NAVIGATION_3D,
BUILD_OPTION_XR,
BUILD_OPTION_OPENXR,
BUILD_OPTION_WAYLAND,
BUILD_OPTION_X11,
BUILD_OPTION_RENDERING_DEVICE,
BUILD_OPTION_OPENGL,
BUILD_OPTION_FORWARD_RENDERER,
BUILD_OPTION_MOBILE_RENDERER,
BUILD_OPTION_VULKAN,
BUILD_OPTION_D3D12,
BUILD_OPTION_METAL,
BUILD_OPTION_OPENGL,
BUILD_OPTION_PHYSICS_2D,
BUILD_OPTION_PHYSICS_GODOT_2D,
BUILD_OPTION_PHYSICS_3D,
BUILD_OPTION_PHYSICS_GODOT_3D,
BUILD_OPTION_PHYSICS_JOLT,
BUILD_OPTION_TEXT_SERVER_FALLBACK,
BUILD_OPTION_TEXT_SERVER_ADVANCED,
BUILD_OPTION_DYNAMIC_FONTS,
@ -59,6 +70,8 @@ public:
enum BuildOptionCategory {
BUILD_OPTION_CATEGORY_GENERAL,
BUILD_OPTION_CATEGORY_GRAPHICS,
BUILD_OPTION_CATEGORY_PHYSICS,
BUILD_OPTION_CATEGORY_TEXT_SERVER,
BUILD_OPTION_CATEGORY_MAX,
};
@ -74,7 +87,11 @@ private:
static const char *build_option_identifiers[BUILD_OPTION_MAX];
static const bool build_option_disabled_by_default[BUILD_OPTION_MAX];
static const bool build_option_disable_values[BUILD_OPTION_MAX];
static const bool build_option_explicit_use[BUILD_OPTION_MAX];
static const BuildOptionCategory build_option_category[BUILD_OPTION_MAX];
static const HashMap<BuildOption, LocalVector<BuildOption>> build_option_dependencies;
static HashMap<BuildOption, HashMap<String, LocalVector<Variant>>> build_option_settings;
static const HashMap<BuildOption, LocalVector<String>> build_option_classes;
String _get_build_option_name(BuildOption p_build_option) { return get_build_option_name(p_build_option); }
@ -91,6 +108,8 @@ public:
void set_disable_build_option(BuildOption p_build_option, bool p_disable);
bool is_build_option_disabled(BuildOption p_build_option) const;
void reset_build_options();
void set_force_detect_classes(const String &p_classes);
String get_force_detect_classes() const;
@ -101,8 +120,13 @@ public:
static String get_build_option_name(BuildOption p_build_option);
static String get_build_option_description(BuildOption p_build_option);
static String get_build_option_identifier(BuildOption p_build_option);
static bool get_build_option_disable_value(BuildOption p_build_option);
static bool get_build_option_explicit_use(BuildOption p_build_option);
static BuildOptionCategory get_build_option_category(BuildOption p_build_option);
static LocalVector<BuildOption> get_build_option_dependencies(BuildOption p_build_option);
static HashMap<String, LocalVector<Variant>> get_build_option_settings(BuildOption p_build_option);
static LocalVector<String> get_build_option_classes(BuildOption p_build_option);
static String get_build_option_category_name(BuildOptionCategory p_build_option_category);
@ -160,7 +184,10 @@ class EditorBuildProfileManager : public AcceptDialog {
void _class_list_item_selected();
void _class_list_item_edited();
void _class_list_item_collapsed(Object *p_item);
void _detect_classes();
bool project_scan_canceled = false;
void _detect_from_project();
void _force_detect_classes_changed(const String &p_text);
@ -168,6 +195,7 @@ class EditorBuildProfileManager : public AcceptDialog {
uint32_t timestamp = 0;
String md5;
Vector<String> classes;
Vector<String> build_deps;
};
void _find_files(EditorFileSystemDirectory *p_dir, const HashMap<String, DetectedFile> &p_cache, HashMap<String, DetectedFile> &r_detected);

View File

@ -65,6 +65,13 @@ String ResourceImporterDynamicFont::get_resource_type() const {
return "FontFile";
}
void ResourceImporterDynamicFont::get_build_dependencies(const String &p_path, HashSet<String> *r_dependencies) {
Ref<FontFile> font = ResourceLoader::load(p_path);
if (font.is_valid() && font->is_multichannel_signed_distance_field()) {
r_dependencies->insert("module_msdfgen_enabled");
}
}
bool ResourceImporterDynamicFont::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
if (p_option == "msdf_pixel_range" && !bool(p_options["multichannel_signed_distance_field"])) {
return false;

View File

@ -47,6 +47,7 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
virtual String get_save_extension() const override;
virtual String get_resource_type() const override;
virtual void get_build_dependencies(const String &p_path, HashSet<String> *r_build_dependencies) override;
virtual int get_preset_count() const override;
virtual String get_preset_name(int p_idx) const override;

View File

@ -2114,6 +2114,10 @@ void ColorPicker::_bind_methods() {
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, ColorPicker, mode_button_normal, "tab_unselected", "TabContainer");
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, ColorPicker, mode_button_pressed, "tab_selected", "TabContainer");
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, ColorPicker, mode_button_hover, "tab_selected", "TabContainer");
ADD_CLASS_DEPENDENCY("LineEdit");
ADD_CLASS_DEPENDENCY("MenuButton");
ADD_CLASS_DEPENDENCY("PopupMenu");
}
ColorPicker::ColorPicker() {

View File

@ -443,6 +443,8 @@ void AcceptDialog::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, AcceptDialog, buttons_separation);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, AcceptDialog, buttons_min_width);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, AcceptDialog, buttons_min_height);
ADD_CLASS_DEPENDENCY("Button");
}
void AcceptDialog::_validate_property(PropertyInfo &p_property) const {
@ -510,6 +512,8 @@ void ConfirmationDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cancel_button_text"), &ConfirmationDialog::get_cancel_button_text);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "cancel_button_text"), "set_cancel_button_text", "get_cancel_button_text");
ADD_CLASS_DEPENDENCY("Button");
}
Button *ConfirmationDialog::get_cancel_button() {

View File

@ -1900,6 +1900,12 @@ void FileDialog::_bind_methods() {
base_property_helper.register_property(PropertyInfo(Variant::PACKED_STRING_ARRAY, "values"), defaults.values, &FileDialog::set_option_values, &FileDialog::get_option_values);
base_property_helper.register_property(PropertyInfo(Variant::INT, "default"), defaults.default_idx, &FileDialog::set_option_default, &FileDialog::get_option_default);
PropertyListHelper::register_base_helper(&base_property_helper);
ADD_CLASS_DEPENDENCY("Button");
ADD_CLASS_DEPENDENCY("ConfirmationDialog");
ADD_CLASS_DEPENDENCY("LineEdit");
ADD_CLASS_DEPENDENCY("OptionButton");
ADD_CLASS_DEPENDENCY("Tree");
}
void FileDialog::set_show_hidden_files(bool p_show) {

View File

@ -3129,6 +3129,13 @@ void GraphEdit::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, GraphEdit, port_hotzone_inner_extent);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, GraphEdit, port_hotzone_outer_extent);
ADD_CLASS_DEPENDENCY("Button");
ADD_CLASS_DEPENDENCY("GraphFrame");
ADD_CLASS_DEPENDENCY("GraphNode");
ADD_CLASS_DEPENDENCY("HScrollBar");
ADD_CLASS_DEPENDENCY("SpinBox");
ADD_CLASS_DEPENDENCY("VScrollBar");
}
GraphEdit::GraphEdit() {

View File

@ -3305,6 +3305,8 @@ void LineEdit::_bind_methods() {
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, LineEdit, clear_icon, "clear");
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LineEdit, clear_button_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, LineEdit, clear_button_color_pressed);
ADD_CLASS_DEPENDENCY("PopupMenu");
}
LineEdit::LineEdit(const String &p_placeholder) {

View File

@ -763,6 +763,8 @@ void MenuBar::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, MenuBar, font_focus_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, MenuBar, h_separation);
ADD_CLASS_DEPENDENCY("PopupMenu");
}
void MenuBar::set_switch_on_hover(bool p_enabled) {

View File

@ -194,6 +194,8 @@ void MenuButton::_bind_methods() {
ADD_SIGNAL(MethodInfo("about_to_popup"));
ADD_CLASS_DEPENDENCY("PopupMenu");
PopupMenu::Item defaults(true);
base_property_helper.set_prefix("popup/item_");

View File

@ -625,6 +625,8 @@ void OptionButton::_bind_methods() {
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "disabled"), defaults.disabled, &OptionButton::_dummy_setter, &OptionButton::is_item_disabled);
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "separator"), defaults.separator, &OptionButton::_dummy_setter, &OptionButton::is_item_separator);
PropertyListHelper::register_base_helper(&base_property_helper);
ADD_CLASS_DEPENDENCY("PopupMenu");
}
void OptionButton::set_disable_shortcuts(bool p_disabled) {

View File

@ -7416,6 +7416,8 @@ void RichTextLabel::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, RichTextLabel, table_odd_row_bg);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, RichTextLabel, table_even_row_bg);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, RichTextLabel, table_border);
ADD_CLASS_DEPENDENCY("PopupMenu");
}
TextServer::VisibleCharactersBehavior RichTextLabel::get_visible_characters_behavior() const {

View File

@ -691,6 +691,8 @@ void SpinBox::_bind_methods() {
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, SpinBox, field_and_buttons_separator, "field_and_buttons_separator");
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, SpinBox, up_down_buttons_separator, "up_down_buttons_separator");
ADD_CLASS_DEPENDENCY("LineEdit");
}
SpinBox::SpinBox() {

View File

@ -1128,6 +1128,8 @@ void TabContainer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_tab_focus_mode", "get_tab_focus_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deselect_enabled"), "set_deselect_enabled", "get_deselect_enabled");
ADD_CLASS_DEPENDENCY("TabBar");
BIND_ENUM_CONSTANT(POSITION_TOP);
BIND_ENUM_CONSTANT(POSITION_BOTTOM);
BIND_ENUM_CONSTANT(POSITION_MAX);

View File

@ -7629,6 +7629,12 @@ void TextEdit::_bind_methods() {
/* Settings. */
GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "gui/timers/text_edit_idle_detect_sec", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 3);
GLOBAL_DEF(PropertyInfo(Variant::INT, "gui/common/text_edit_undo_stack_max_size", PROPERTY_HINT_RANGE, "0,10000,1,or_greater"), 1024);
/* Dependencies */
ADD_CLASS_DEPENDENCY("HScrollBar");
ADD_CLASS_DEPENDENCY("PopupMenu");
ADD_CLASS_DEPENDENCY("Timer");
ADD_CLASS_DEPENDENCY("VScrollBar");
}
/* Internal API for CodeEdit. */

View File

@ -6655,6 +6655,14 @@ void Tree::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, title_button_pressed);
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, title_button_hover);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, title_button_color);
ADD_CLASS_DEPENDENCY("HScrollBar");
ADD_CLASS_DEPENDENCY("HSlider");
ADD_CLASS_DEPENDENCY("LineEdit");
ADD_CLASS_DEPENDENCY("Popup");
ADD_CLASS_DEPENDENCY("TextEdit");
ADD_CLASS_DEPENDENCY("Timer");
ADD_CLASS_DEPENDENCY("VScrollBar");
}
Tree::Tree() {

View File

@ -177,18 +177,26 @@ World3D::World3D() {
World3D::~World3D() {
ERR_FAIL_NULL(RenderingServer::get_singleton());
#ifndef PHYSICS_3D_DISABLED
ERR_FAIL_NULL(PhysicsServer3D::get_singleton());
#endif // PHYSICS_3D_DISABLED
#ifndef NAVIGATION_3D_DISABLED
ERR_FAIL_NULL(NavigationServer3D::get_singleton());
#endif // NAVIGATION_3D_DISABLED
RenderingServer::get_singleton()->free(scenario);
#ifndef PHYSICS_3D_DISABLED
if (space.is_valid()) {
PhysicsServer3D::get_singleton()->free(space);
}
#endif // PHYSICS_3D_DISABLED
#ifndef NAVIGATION_3D_DISABLED
if (navigation_map.is_valid()) {
NavigationServer3D::get_singleton()->free(navigation_map);
}
#endif // NAVIGATION_3D_DISABLED
}

View File

@ -1223,15 +1223,10 @@ Error ResourceLoaderText::get_classes_used(HashSet<StringName> *r_classes) {
return error;
}
if (!next_tag.fields.has("type")) {
error = ERR_FILE_CORRUPT;
error_text = "Missing 'type' in external resource tag";
_printerr();
return error;
if (next_tag.fields.has("type")) {
r_classes->insert(next_tag.fields["type"]);
}
r_classes->insert(next_tag.fields["type"]);
while (true) {
String assign;
Variant value;
@ -1447,9 +1442,9 @@ bool ResourceFormatLoaderText::handles_type(const String &p_type) const {
}
void ResourceFormatLoaderText::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
String ext = p_path.get_extension().to_lower();
if (ext == "tscn") {
r_classes->insert("PackedScene");
const String type = get_resource_type(p_path);
if (!type.is_empty()) {
r_classes->insert(type);
}
// ...for anything else must test...