diff --git a/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs b/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs index 88f916ae4..e89c80372 100644 --- a/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs +++ b/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs @@ -38,6 +38,7 @@ namespace FlaxEditor.CustomEditors.Editors /// public AssetPicker Picker; + private bool _isRefreshing; private ScriptType _valueType; /// @@ -89,6 +90,8 @@ namespace FlaxEditor.CustomEditors.Editors private void OnSelectedItemChanged() { + if (_isRefreshing) + return; if (typeof(AssetItem).IsAssignableFrom(_valueType.Type)) SetValue(Picker.SelectedItem); else if (_valueType.Type == typeof(Guid)) @@ -108,6 +111,7 @@ namespace FlaxEditor.CustomEditors.Editors if (!HasDifferentValues) { + _isRefreshing = true; if (Values[0] is AssetItem assetItem) Picker.SelectedItem = assetItem; else if (Values[0] is Guid guid) @@ -118,6 +122,7 @@ namespace FlaxEditor.CustomEditors.Editors Picker.SelectedPath = path; else Picker.SelectedAsset = Values[0] as Asset; + _isRefreshing = false; } } } diff --git a/Source/Editor/CustomEditors/Editors/ModelInstanceEntryEditor.cs b/Source/Editor/CustomEditors/Editors/ModelInstanceEntryEditor.cs index 1f04115de..277f9ecb0 100644 --- a/Source/Editor/CustomEditors/Editors/ModelInstanceEntryEditor.cs +++ b/Source/Editor/CustomEditors/Editors/ModelInstanceEntryEditor.cs @@ -15,7 +15,11 @@ namespace FlaxEditor.CustomEditors.Editors { private GroupElement _group; private bool _updateName; + private int _entryIndex; + private bool _isRefreshing; private MaterialBase _material; + private ModelInstanceActor _modelInstance; + private AssetRefEditor _materialEditor; /// public override void Initialize(LayoutElementsContainer layout) @@ -32,58 +36,75 @@ namespace FlaxEditor.CustomEditors.Editors materialLabel.TooltipText = "The mesh surface material used for the rendering."; if (ParentEditor.ParentEditor?.Values[0] is ModelInstanceActor modelInstance) { - // Ensure that entry with default material set is set back to null - var defaultValue = GPUDevice.Instance.DefaultMaterial; + _entryIndex = entryIndex; + _modelInstance = modelInstance; + var slots = modelInstance.MaterialSlots; + if (entry.Material == slots[entryIndex].Material) { - var slots = modelInstance.MaterialSlots; - if (entry.Material == slots[entryIndex].Material) - { - modelInstance.SetMaterial(entryIndex, null); - } - _material = modelInstance.GetMaterial(entryIndex); - if (slots[entryIndex].Material) - { - defaultValue = slots[entryIndex].Material; - } + // Ensure that entry with default material set is set back to null + modelInstance.SetMaterial(entryIndex, null); + } + _material = modelInstance.GetMaterial(entryIndex); + var defaultValue = GPUDevice.Instance.DefaultMaterial; + if (slots[entryIndex].Material) + { + // Use default value set on asset (eg. Model Asset) + defaultValue = slots[entryIndex].Material; } - var matContainer = new CustomValueContainer(new ScriptType(typeof(MaterialBase)), _material, (instance, index) => _material, (instance, index, value) => _material = value as MaterialBase); - var materialEditor = (AssetRefEditor)_group.Property(materialLabel, matContainer); + // Create material picker + var materialValue = new CustomValueContainer(new ScriptType(typeof(MaterialBase)), _material, (instance, index) => _material, (instance, index, value) => _material = value as MaterialBase); + var materialEditor = (AssetRefEditor)_group.Property(materialLabel, materialValue); materialEditor.Values.SetDefaultValue(defaultValue); materialEditor.RefreshDefaultValue(); - materialEditor.Picker.SelectedItemChanged += () => - { - var slots = modelInstance.MaterialSlots; - var material = materialEditor.Picker.SelectedAsset as MaterialBase; - var defaultMaterial = GPUDevice.Instance.DefaultMaterial; - if (!material) - { - modelInstance.SetMaterial(entryIndex, defaultMaterial); - materialEditor.Picker.SelectedAsset = defaultMaterial; - } - else if (material == slots[entryIndex].Material) - { - modelInstance.SetMaterial(entryIndex, null); - } - else if (material == defaultMaterial && !slots[entryIndex].Material) - { - modelInstance.SetMaterial(entryIndex, null); - } - else - { - modelInstance.SetMaterial(entryIndex, material); - } - }; + materialEditor.Picker.SelectedItemChanged += OnSelectedMaterialChanged; + _materialEditor = materialEditor; } base.Initialize(group); } + private void OnSelectedMaterialChanged() + { + if (_isRefreshing) + return; + _isRefreshing = true; + var slots = _modelInstance.MaterialSlots; + var material = _materialEditor.Picker.SelectedAsset as MaterialBase; + var defaultMaterial = GPUDevice.Instance.DefaultMaterial; + var value = (ModelInstanceEntry)Values[0]; + var prevMaterial = value.Material; + if (!material) + { + // Fallback to default material + _materialEditor.Picker.SelectedAsset = defaultMaterial; + value.Material = defaultMaterial; + } + else if (material == slots[_entryIndex].Material) + { + // Asset default material + value.Material = null; + } + else if (material == defaultMaterial && !slots[_entryIndex].Material) + { + // Default material while asset has no set as well + value.Material = null; + } + else + { + // Custom material + value.Material = material; + } + if (prevMaterial != value.Material) + SetValue(value); + _isRefreshing = false; + } + /// protected override void SpawnProperty(LayoutElementsContainer itemLayout, ValueContainer itemValues, ItemInfo item) { // Skip material member as it is overridden - if (item.Info.Name == "Material") + if (item.Info.Name == "Material" && _materialEditor != null) return; base.SpawnProperty(itemLayout, itemValues, item); } @@ -91,6 +112,7 @@ namespace FlaxEditor.CustomEditors.Editors /// public override void Refresh() { + // Update panel title to match material slot name if (_updateName && _group != null && ParentEditor?.ParentEditor != null && @@ -102,13 +124,26 @@ namespace FlaxEditor.CustomEditors.Editors var slots = modelInstance.MaterialSlots; if (slots != null && slots.Length > entryIndex) { - _group.Panel.HeaderText = "Entry " + slots[entryIndex].Name; _updateName = false; + _group.Panel.HeaderText = "Entry " + slots[entryIndex].Name; } } } + // Refresh currently selected material + _material = _modelInstance.GetMaterial(_entryIndex); + base.Refresh(); } + + /// + protected override void Deinitialize() + { + _material = null; + _modelInstance = null; + _materialEditor = null; + + base.Deinitialize(); + } } }