Skip to content

Conversation

@MauriceButler
Copy link

@MauriceButler MauriceButler commented Sep 21, 2025

Introduces new functions get_changed_settings and check_changed_settings_in_group. This brings Project Settings to parity with the Editor Settings functionality.

This allows much more fine-grained responses to setting changes.

This approach is non-breaking.

func _enter_tree() -> void:
	ProjectSettings.settings_changed.connect(_on_project_settings_changed)
	
func _on_project_settings_changed() -> void:
	print("_on_project_settings_changed")
	
	if !ProjectSettings.check_changed_settings_in_group('my_settings'):
		return

	var changed_settings = ProjectSettings.get_changed_settings()

As part of this, the settings_changed is now only emitted when a settings value is set to a different value.

Fixes: #110747
Closes godotengine/godot-proposals#13244

@MauriceButler MauriceButler requested review from a team as code owners September 21, 2025 13:54
@rsubtil
Copy link
Member

rsubtil commented Sep 21, 2025

I'm not too keen with this solution of having two very similar signal names for the same concept. In my opinion it makes more sense to introduce the (name, old_value, new_value) args to the existing signal instead.

Thing is, I believe that would cause a breaking change for existing code, even though we are only adding arguments, since there would be a mismatch of argument count between the signal and existing connected functions. So I'm not sure how problematic this would be.

@MauriceButler
Copy link
Author

I agree, I originally changed the existing signal, but I was trying to avoid a breaking change.

I am happy to make the breaking change if that's the approach deemed correct.

I could fix the broken code in the engine, but any userland code would still be affected.

I'm not sure how widely used this signal is outside of addons, but anyone using this signal would benefit from the usability improvements, being able to filter on specific settings, and reducing processing, at the cost of a minor change to the signature.

@lawnjelly
Copy link
Member

Needs a proposal:
https://github.com/godotengine/godot-proposals

@AThousandShips
Copy link
Member

AThousandShips commented Sep 23, 2025

This will only emit for exactly one setting, which would be confusing IMO, it should at least be mentioned in the documentation that changing a second setting in the same frame will not trigger this specific signal

@MauriceButler
Copy link
Author

This will only emit for exactly one setting, which would be confusing IMO, it should at least be mentioned in the documentation that changing a second setting in the same frame will not trigger this specific signal

That was not the intended behavior, I must not have tested that as well as I thought.

My aim is that each setting change would trigger this signal.

I won't update this yet I'll wait on the proposal approval before spending more time on it.

@AThousandShips
Copy link
Member

Based on how I read the code it queues one change notification per frame, for the first changed case, after that it skips any changes of any setting, as it sets is_changed = true and then any call to _queue_changed is skipped

@MauriceButler MauriceButler force-pushed the project-setting-changed-signal branch from 053f96d to e7dd3f8 Compare September 23, 2025 12:23
signal.name = p_name;
signal.old_value = p_old_value;
signal.new_value = p_new_value;
pending_signals.push_back(signal);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks better, note though that this will fire for duplicates, but that would be desirable I'd say, though if you do change the setting twice in a frame it will call with the two changed values in order

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, multiple changes to the same settings for different values is correct to fire for each change.

Multiple changes to the same setting of the same value do not.

I can add an explicit test for that to make it clear.

@MauriceButler MauriceButler force-pushed the project-setting-changed-signal branch 2 times, most recently from b2d82e6 to b5582da Compare September 28, 2025 03:25
@MauriceButler
Copy link
Author

I have reworked this to mimic the way Editor Settings work.
No new signals, non-breaking and aligns Editor and Project settings fnctionality.

@MauriceButler MauriceButler changed the title Add signal for individual project setting change Added ability to get list of Project Settings changed, similar to Editor Settings functionality Sep 28, 2025
@MauriceButler MauriceButler force-pushed the project-setting-changed-signal branch from b5582da to 482864c Compare September 28, 2025 22:51
@AThousandShips AThousandShips changed the title Added ability to get list of Project Settings changed, similar to Editor Settings functionality Add ability to get list of Project Settings changed, similar to Editor Settings functionality Oct 7, 2025
Clears the whole configuration (not recommended, may break things).
</description>
</method>
<method name="clear_changed_settings">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this for?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover from a test method, cleanup and removed.

Returns the localized path (starting with [code]res://[/code]) corresponding to the absolute, native OS [param path]. See also [method globalize_path].
</description>
</method>
<method name="mark_setting_changed">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know EditorSettings also have this method, but I wonder why 🤔 Changing a setting will automatically mark it as modified.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly I dont know either.
I copied it to to match EditorSettings but I dont know how a setting could get in another way.
I have removed it.

// Capture old value before making changes
Variant old_value;
if (props.has(p_name)) {
old_value = props[p_name].variant;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are checking anyway whether the value changed, maybe the method could return early if it didn't change?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call I have added an early return check.

@MauriceButler MauriceButler force-pushed the project-setting-changed-signal branch from 482864c to 07b8725 Compare November 3, 2025 11:31
uint32_t _version = 1;

// Track changed settings for get_changed_settings functionality
HashSet<String> changed_settings;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method to queue changes uses StringName and in _set it checks for has, so I'd say that using StringName here would be best and then just casting it to String when you need a String. It's not expensive but it will improve the checking operations and the insertion as StringName already has its hash and the comparison is faster

You'd just need to change the const String &setting : changed_settings to const String setting : changed_settings

StringName has a tiny overhead in storage but I'd say that's not critical compared with the better performance when inserting and querying

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I can make that change.

Do you think I should I change EditorSettings while I am at it to keep them in sync?

Or do that as a seperate performance improvement PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say to keep that as is, or leave it in both cases

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the change for ProjectSettings

@MauriceButler MauriceButler force-pushed the project-setting-changed-signal branch from 07b8725 to e451640 Compare November 3, 2025 13:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

5 participants