ProjectSettings add dirty flag and project_settings_changed signal
Most frames there will be no change in project settings, and it makes no sense to read settings every frame in case of changes, as a large number of string compares are involved. This PR adds a signal to ProjectSettings that can be subscribed to in order to keep local settings up to date with ProjectSettings. In addition a function `ProjectSettings::has_changes()` is provided for objects outside the signal system (e.g. Rasterizers).
This commit is contained in:
parent
4ed2c8ee08
commit
f0af29346b
8 changed files with 132 additions and 36 deletions
|
@ -165,9 +165,26 @@ String ProjectSettings::globalize_path(const String &p_path) const {
|
|||
return p_path;
|
||||
}
|
||||
|
||||
void ProjectSettings::update() {
|
||||
if (_dirty_this_frame) {
|
||||
// A signal is sent a single time at the end of the frame when project settings
|
||||
// are changed. This allows objects to respond.
|
||||
// Alternatively objects outside the signal system can query ProjectSettings::has_changes()
|
||||
if (_dirty_this_frame == 2) {
|
||||
emit_signal("project_settings_changed");
|
||||
}
|
||||
|
||||
_dirty_this_frame--;
|
||||
}
|
||||
}
|
||||
|
||||
bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
// marking the project settings as dirty allows them only to be
|
||||
// checked when dirty.
|
||||
_dirty_this_frame = 2;
|
||||
|
||||
if (p_value.get_type() == Variant::NIL) {
|
||||
props.erase(p_name);
|
||||
} else {
|
||||
|
@ -1022,6 +1039,8 @@ void ProjectSettings::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &ProjectSettings::property_get_revert);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("save_custom", "file"), &ProjectSettings::_save_custom_bnd);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("project_settings_changed"));
|
||||
}
|
||||
|
||||
ProjectSettings::ProjectSettings() {
|
||||
|
|
|
@ -35,10 +35,37 @@
|
|||
#include "core/os/thread_safe.h"
|
||||
#include "core/set.h"
|
||||
|
||||
// Querying ProjectSettings is usually done at startup.
|
||||
// Additionally, in order to keep track of changes to ProjectSettings,
|
||||
// instead of Querying all the strings every frame just in case of changes,
|
||||
// there is a signal "project_settings_changed" which objects can subscribe to.
|
||||
|
||||
// E.g. (from another Godot object)
|
||||
// // Call your user written object function to Query the project settings once at creation,
|
||||
// perhaps in an ENTER_TREE notification:
|
||||
// _project_settings_changed()
|
||||
// // Then connect your function to the signal so it is called every time something changes in future:
|
||||
// ProjectSettings::get_singleton()->connect("project_settings_changed", this, "_project_settings_changed");
|
||||
|
||||
// Where for example your function may take the form:
|
||||
// void _project_settings_changed() {
|
||||
// _shadowmap_size = GLOBAL_GET("rendering/quality/shadow_atlas/size");
|
||||
// }
|
||||
|
||||
// You may want to also disconnect from the signal in EXIT_TREE notification, if your object may be deleted
|
||||
// before ProjectSettings:
|
||||
// ProjectSettings::get_singleton()->disconnect("project_settings_changed", this, "_project_settings_changed");
|
||||
|
||||
// Additionally, for objects that are not regular Godot objects capable of subscribing to signals (e.g. Rasterizers),
|
||||
// you can also query the function "has_changes()" each frame,
|
||||
// and update your local settings whenever this is set.
|
||||
|
||||
class ProjectSettings : public Object {
|
||||
GDCLASS(ProjectSettings, Object);
|
||||
_THREAD_SAFE_CLASS_
|
||||
|
||||
int _dirty_this_frame = 2;
|
||||
|
||||
public:
|
||||
typedef Map<String, Variant> CustomMap;
|
||||
static const String PROJECT_DATA_DIR_NAME_SUFFIX;
|
||||
|
@ -168,6 +195,14 @@ public:
|
|||
|
||||
bool has_custom_feature(const String &p_feature) const;
|
||||
|
||||
// Either use the signal `project_settings_changed` or query this function.
|
||||
// N.B. _dirty_this_frame is set initially to 2.
|
||||
// This is to cope with the situation where a project setting is changed in the iteration AFTER it is read.
|
||||
// There is therefore the potential for a change to be missed. Persisting the counter
|
||||
// for two frames avoids this, at the cost of a frame delay.
|
||||
bool has_changes() const { return _dirty_this_frame == 1; }
|
||||
void update();
|
||||
|
||||
ProjectSettings();
|
||||
~ProjectSettings();
|
||||
};
|
||||
|
|
|
@ -1569,6 +1569,13 @@
|
|||
Cell size used for the 2D hash grid that [VisibilityNotifier2D] uses (in pixels).
|
||||
</member>
|
||||
</members>
|
||||
<signals>
|
||||
<signal name="project_settings_changed">
|
||||
<description>
|
||||
Objects can use this signal to restrict reading of settings only to situations where a change has been made.
|
||||
</description>
|
||||
</signal>
|
||||
</signals>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
|
@ -99,8 +99,8 @@ void ImportDefaultsEditor::_save() {
|
|||
} else {
|
||||
ProjectSettings::get_singleton()->set("importer_defaults/" + settings->importer->get_importer_name(), Variant());
|
||||
}
|
||||
|
||||
emit_signal("project_settings_changed");
|
||||
// Calling ProjectSettings::set() causes the signal "project_settings_changed" to be sent to ProjectSettings.
|
||||
// ProjectSettingsEditor subscribes to this and can reads the settings updated here.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2462,6 +2462,49 @@ void SpatialEditorPlugin::edited_scene_changed() {
|
|||
}
|
||||
}
|
||||
|
||||
void SpatialEditorViewport::_project_settings_changed() {
|
||||
if (viewport) {
|
||||
_project_settings_change_pending = false;
|
||||
|
||||
//update shadow atlas if changed
|
||||
int shadowmap_size = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/size");
|
||||
int atlas_q0 = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/quadrant_0_subdiv");
|
||||
int atlas_q1 = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/quadrant_1_subdiv");
|
||||
int atlas_q2 = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/quadrant_2_subdiv");
|
||||
int atlas_q3 = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/quadrant_3_subdiv");
|
||||
|
||||
viewport->set_shadow_atlas_size(shadowmap_size);
|
||||
viewport->set_shadow_atlas_quadrant_subdiv(0, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q0));
|
||||
viewport->set_shadow_atlas_quadrant_subdiv(1, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q1));
|
||||
viewport->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2));
|
||||
viewport->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3));
|
||||
|
||||
// Update MSAA, FXAA, debanding and HDR if changed.
|
||||
int msaa_mode = ProjectSettings::get_singleton()->get("rendering/quality/filters/msaa");
|
||||
viewport->set_msaa(Viewport::MSAA(msaa_mode));
|
||||
|
||||
bool use_fxaa = ProjectSettings::get_singleton()->get("rendering/quality/filters/use_fxaa");
|
||||
viewport->set_use_fxaa(use_fxaa);
|
||||
|
||||
bool use_debanding = ProjectSettings::get_singleton()->get("rendering/quality/filters/use_debanding");
|
||||
viewport->set_use_debanding(use_debanding);
|
||||
|
||||
float sharpen_intensity = ProjectSettings::get_singleton()->get("rendering/quality/filters/sharpen_intensity");
|
||||
viewport->set_sharpen_intensity(sharpen_intensity);
|
||||
|
||||
bool hdr = ProjectSettings::get_singleton()->get("rendering/quality/depth/hdr");
|
||||
viewport->set_hdr(hdr);
|
||||
|
||||
const bool use_32_bpc_depth = ProjectSettings::get_singleton()->get("rendering/quality/depth/use_32_bpc_depth");
|
||||
viewport->set_use_32_bpc_depth(use_32_bpc_depth);
|
||||
|
||||
} else {
|
||||
// Could not update immediately, set a pending update.
|
||||
// This may never happen, but is included for safety
|
||||
_project_settings_change_pending = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SpatialEditorViewport::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
|
||||
bool visible = is_visible_in_tree();
|
||||
|
@ -2583,19 +2626,9 @@ void SpatialEditorViewport::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
|
||||
//update shadow atlas if changed
|
||||
|
||||
int shadowmap_size = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/size");
|
||||
int atlas_q0 = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/quadrant_0_subdiv");
|
||||
int atlas_q1 = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/quadrant_1_subdiv");
|
||||
int atlas_q2 = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/quadrant_2_subdiv");
|
||||
int atlas_q3 = ProjectSettings::get_singleton()->get("rendering/quality/shadow_atlas/quadrant_3_subdiv");
|
||||
|
||||
viewport->set_shadow_atlas_size(shadowmap_size);
|
||||
viewport->set_shadow_atlas_quadrant_subdiv(0, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q0));
|
||||
viewport->set_shadow_atlas_quadrant_subdiv(1, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q1));
|
||||
viewport->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2));
|
||||
viewport->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3));
|
||||
if (_project_settings_change_pending) {
|
||||
_project_settings_changed();
|
||||
}
|
||||
|
||||
bool shrink = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_HALF_RESOLUTION));
|
||||
|
||||
|
@ -2603,26 +2636,6 @@ void SpatialEditorViewport::_notification(int p_what) {
|
|||
viewport_container->set_stretch_shrink(shrink ? 2 : 1);
|
||||
}
|
||||
|
||||
// Update MSAA, FXAA, debanding and HDR if changed.
|
||||
|
||||
int msaa_mode = ProjectSettings::get_singleton()->get("rendering/quality/filters/msaa");
|
||||
viewport->set_msaa(Viewport::MSAA(msaa_mode));
|
||||
|
||||
bool use_fxaa = ProjectSettings::get_singleton()->get("rendering/quality/filters/use_fxaa");
|
||||
viewport->set_use_fxaa(use_fxaa);
|
||||
|
||||
bool use_debanding = ProjectSettings::get_singleton()->get("rendering/quality/filters/use_debanding");
|
||||
viewport->set_use_debanding(use_debanding);
|
||||
|
||||
float sharpen_intensity = ProjectSettings::get_singleton()->get("rendering/quality/filters/sharpen_intensity");
|
||||
viewport->set_sharpen_intensity(sharpen_intensity);
|
||||
|
||||
const bool hdr = ProjectSettings::get_singleton()->get("rendering/quality/depth/hdr");
|
||||
viewport->set_hdr(hdr);
|
||||
|
||||
const bool use_32_bpc_depth = ProjectSettings::get_singleton()->get("rendering/quality/depth/use_32_bpc_depth");
|
||||
viewport->set_use_32_bpc_depth(use_32_bpc_depth);
|
||||
|
||||
bool show_info = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION));
|
||||
info_label->set_visible(show_info);
|
||||
|
||||
|
@ -2689,10 +2702,17 @@ void SpatialEditorViewport::_notification(int p_what) {
|
|||
surface->connect("focus_entered", this, "_surface_focus_enter");
|
||||
surface->connect("focus_exited", this, "_surface_focus_exit");
|
||||
|
||||
// Ensure we are up to date with project settings
|
||||
_project_settings_changed();
|
||||
|
||||
// Any further changes to project settings get a signal
|
||||
ProjectSettings::get_singleton()->connect("project_settings_changed", this, "_project_settings_changed");
|
||||
|
||||
_init_gizmo_instance(index);
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_EXIT_TREE) {
|
||||
ProjectSettings::get_singleton()->disconnect("project_settings_changed", this, "_project_settings_changed");
|
||||
_finish_gizmo_instances();
|
||||
}
|
||||
|
||||
|
@ -3582,6 +3602,7 @@ void SpatialEditorViewport::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &SpatialEditorViewport::_selection_menu_hide);
|
||||
ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &SpatialEditorViewport::can_drop_data_fw);
|
||||
ClassDB::bind_method(D_METHOD("drop_data_fw"), &SpatialEditorViewport::drop_data_fw);
|
||||
ClassDB::bind_method(D_METHOD("_project_settings_changed"), &SpatialEditorViewport::_project_settings_changed);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("toggle_maximize_view", PropertyInfo(Variant::OBJECT, "viewport")));
|
||||
ADD_SIGNAL(MethodInfo("clicked", PropertyInfo(Variant::OBJECT, "viewport")));
|
||||
|
@ -4104,6 +4125,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
|
|||
gizmo_scale = 1.0;
|
||||
|
||||
preview_node = nullptr;
|
||||
_project_settings_change_pending = false;
|
||||
|
||||
info_label = memnew(Label);
|
||||
info_label->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -90 * EDSCALE);
|
||||
|
|
|
@ -243,6 +243,7 @@ public:
|
|||
|
||||
private:
|
||||
int index;
|
||||
bool _project_settings_change_pending;
|
||||
ViewType view_type;
|
||||
void _menu_option(int p_option);
|
||||
void _set_auto_orthogonal();
|
||||
|
@ -458,6 +459,8 @@ private:
|
|||
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
|
||||
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
|
||||
|
||||
void _project_settings_changed();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
|
|
@ -143,7 +143,16 @@ void ProjectSettingsEditor::_notification(int p_what) {
|
|||
restart_icon->set_texture(get_icon("StatusWarning", "EditorIcons"));
|
||||
restart_label->add_color_override("font_color", get_color("warning_color", "Editor"));
|
||||
|
||||
// The ImportDefaultsEditor changes settings which must be read by this object when changed
|
||||
ProjectSettings::get_singleton()->connect("project_settings_changed", this, "_settings_changed");
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
if (ProjectSettings::get_singleton()) {
|
||||
ProjectSettings::get_singleton()->disconnect("project_settings_changed", this, "_settings_changed");
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_POPUP_HIDE: {
|
||||
EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "project_settings", get_rect());
|
||||
set_process_unhandled_input(false);
|
||||
|
@ -2141,7 +2150,6 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
|
|||
import_defaults_editor = memnew(ImportDefaultsEditor);
|
||||
import_defaults_editor->set_name(TTR("Import Defaults"));
|
||||
tab_container->add_child(import_defaults_editor);
|
||||
import_defaults_editor->connect("project_settings_changed", this, "_settings_changed");
|
||||
|
||||
timer = memnew(Timer);
|
||||
timer->set_wait_time(1.5);
|
||||
|
|
|
@ -589,6 +589,8 @@ bool SceneTree::idle(float p_time) {
|
|||
|
||||
_call_idle_callbacks();
|
||||
|
||||
ProjectSettings::get_singleton()->update();
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
|
|
Loading…
Reference in a new issue