I get that. But now how do I check for all the fields in a visual tree without repetition? For example, if I want to mark the scene dirty for any field having its value changed in a custom editor.
If you’re using DataBinding with SerializedObjects, the scene dirtying should be done automatically.
If you don`t use bindings, a workaround you can use now is to register to ChangeEvents at the root of your visual tree as the change events will bubble up the hierarchy after being handled at the target. While you unfortunately need to register to all known types of ChangeEvents, you only need to do it on one element.
// This will come in in the next 20.2 release, sent from PropertyFields
// evt.target refers to the original field that triggered the change.
rootElement.RegisterCallback<SerializedPropertyChangeEvent>((changeEvent) => DirtyStuff());
rootElement.RegisterCallback<ChangeEvent<int>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<bool>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<float>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<double>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<string>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<Color>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<UnityEngine.Object>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<Enum>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<Vector2>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<Vector3>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<Vector4>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<Rect>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<AnimationCurve>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<Bounds>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<Gradient>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<Quaternion>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<Vector2Int>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<Vector3Int>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<Vector3Int>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<RectInt>>((evt => DirtyStuff()));
rootElement.RegisterCallback<ChangeEvent<BoundsInt>>((evt => DirtyStuff()));
a less than ideal workaround but it should work. We’ll provide a better way to do this in the future
alternatively, ChangeEvent could be a simple catch-all using the same syntax
looking forward to SerializedPropertyChangeEvent, sounds like it’ll be super useful! though I think an AnyFieldChanged event would be much more useful.