diff --git a/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs b/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs
index 17999d772..b83b44d59 100644
--- a/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs
@@ -33,7 +33,10 @@ namespace FlaxEditor.CustomEditors.Editors
[CustomEditor(typeof(Asset)), DefaultEditor]
public class AssetRefEditor : CustomEditor
{
- private AssetPicker _picker;
+ ///
+ /// The asset picker used to get a reference to an asset.
+ ///
+ public AssetPicker Picker;
private ScriptType _valueType;
///
@@ -44,7 +47,7 @@ namespace FlaxEditor.CustomEditors.Editors
{
if (HasDifferentTypes)
return;
- _picker = layout.Custom().CustomControl;
+ Picker = layout.Custom().CustomControl;
_valueType = Values.Type.Type != typeof(object) || Values[0] == null ? Values.Type : TypeUtils.GetObjectType(Values[0]);
var assetType = _valueType;
@@ -66,7 +69,7 @@ namespace FlaxEditor.CustomEditors.Editors
{
// Generic file picker
assetType = ScriptType.Null;
- _picker.FileExtension = assetReference.TypeName;
+ Picker.FileExtension = assetReference.TypeName;
}
else
{
@@ -78,23 +81,23 @@ namespace FlaxEditor.CustomEditors.Editors
}
}
- _picker.AssetType = assetType;
- _picker.Height = height;
- _picker.SelectedItemChanged += OnSelectedItemChanged;
+ Picker.AssetType = assetType;
+ Picker.Height = height;
+ Picker.SelectedItemChanged += OnSelectedItemChanged;
}
private void OnSelectedItemChanged()
{
if (typeof(AssetItem).IsAssignableFrom(_valueType.Type))
- SetValue(_picker.SelectedItem);
+ SetValue(Picker.SelectedItem);
else if (_valueType.Type == typeof(Guid))
- SetValue(_picker.SelectedID);
+ SetValue(Picker.SelectedID);
else if (_valueType.Type == typeof(SceneReference))
- SetValue(new SceneReference(_picker.SelectedID));
+ SetValue(new SceneReference(Picker.SelectedID));
else if (_valueType.Type == typeof(string))
- SetValue(_picker.SelectedPath);
+ SetValue(Picker.SelectedPath);
else
- SetValue(_picker.SelectedAsset);
+ SetValue(Picker.SelectedAsset);
}
///
@@ -105,15 +108,15 @@ namespace FlaxEditor.CustomEditors.Editors
if (!HasDifferentValues)
{
if (Values[0] is AssetItem assetItem)
- _picker.SelectedItem = assetItem;
+ Picker.SelectedItem = assetItem;
else if (Values[0] is Guid guid)
- _picker.SelectedID = guid;
+ Picker.SelectedID = guid;
else if (Values[0] is SceneReference sceneAsset)
- _picker.SelectedItem = Editor.Instance.ContentDatabase.FindAsset(sceneAsset.ID);
+ Picker.SelectedItem = Editor.Instance.ContentDatabase.FindAsset(sceneAsset.ID);
else if (Values[0] is string path)
- _picker.SelectedPath = path;
+ Picker.SelectedPath = path;
else
- _picker.SelectedAsset = Values[0] as Asset;
+ Picker.SelectedAsset = Values[0] as Asset;
}
}
}
diff --git a/Source/Editor/CustomEditors/Editors/ModelInstanceEntryEditor.cs b/Source/Editor/CustomEditors/Editors/ModelInstanceEntryEditor.cs
index a08a254d4..b7989cae3 100644
--- a/Source/Editor/CustomEditors/Editors/ModelInstanceEntryEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/ModelInstanceEntryEditor.cs
@@ -1,6 +1,8 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using FlaxEditor.CustomEditors.Elements;
+using FlaxEditor.CustomEditors.GUI;
+using FlaxEditor.Scripting;
using FlaxEngine;
namespace FlaxEditor.CustomEditors.Editors
@@ -13,6 +15,8 @@ namespace FlaxEditor.CustomEditors.Editors
{
private GroupElement _group;
private bool _updateName;
+ private MaterialBase _material;
+ private ModelInstanceEntry _entry;
///
public override void Initialize(LayoutElementsContainer layout)
@@ -20,10 +24,94 @@ namespace FlaxEditor.CustomEditors.Editors
_updateName = true;
var group = layout.Group("Entry");
_group = group;
+
+ _entry = (ModelInstanceEntry)Values[0];
+ var entryIndex = ParentEditor.ChildrenEditors.IndexOf(this);
+ var materiaLabel = new PropertyNameLabel("Material");
+ materiaLabel.TooltipText = "The mesh surface material used for the rendering.";
+ if (ParentEditor.ParentEditor.Values[0] is StaticModel staticModel)
+ {
+ // Ensure that entry with default material set is set back to null
+ if (_entry.Material == staticModel.Model.MaterialSlots[entryIndex].Material)
+ {
+ staticModel.SetMaterial(entryIndex, null);
+ }
+ _material = staticModel.GetMaterial(entryIndex);
+ var matContainer = new CustomValueContainer(new ScriptType(typeof(MaterialBase)), _material, (instance, index) => _material, (instance, index, value) => _material = value as MaterialBase);
+ var materialEditor = (_group.Property(materiaLabel, matContainer)) as AssetRefEditor;
+ materialEditor.Values.SetDefaultValue((staticModel.Model.MaterialSlots[entryIndex].Material) ? staticModel.Model.MaterialSlots[entryIndex].Material : GPUDevice.Instance.DefaultMaterial);
+ materialEditor.RefreshDefaultValue();
+ materialEditor.Picker.SelectedItemChanged += () =>
+ {
+ var material = materialEditor.Picker.SelectedAsset as MaterialBase;
+ if (!material)
+ {
+ staticModel.SetMaterial(entryIndex, GPUDevice.Instance.DefaultMaterial);
+ materialEditor.Picker.SelectedAsset = GPUDevice.Instance.DefaultMaterial;
+ }
+ else if (material == staticModel.Model.MaterialSlots[entryIndex].Material)
+ {
+ staticModel.SetMaterial(entryIndex, null);
+ }
+ else if (material == GPUDevice.Instance.DefaultMaterial && !staticModel.Model.MaterialSlots[entryIndex].Material)
+ {
+ staticModel.SetMaterial(entryIndex, null);
+ }
+ else
+ {
+ staticModel.SetMaterial(entryIndex, material);
+ }
+ };
+ }
+ else if (ParentEditor.ParentEditor.Values[0] is AnimatedModel animatedModel)
+ {
+ // Ensure that entry with default material set is set back to null
+ if (_entry.Material == animatedModel.SkinnedModel.MaterialSlots[entryIndex].Material)
+ {
+ animatedModel.SetMaterial(entryIndex, null);
+ }
+ _material = animatedModel.GetMaterial(entryIndex);
+
+ var matContainer = new CustomValueContainer(new ScriptType(typeof(MaterialBase)), _material, (instance, index) => _material, (instance, index, value) => _material = value as MaterialBase);
+ var materialEditor = (_group.Property(materiaLabel, matContainer)) as AssetRefEditor;
+ materialEditor.Values.SetDefaultValue((animatedModel.SkinnedModel.MaterialSlots[entryIndex].Material) ? animatedModel.SkinnedModel.MaterialSlots[entryIndex].Material : GPUDevice.Instance.DefaultMaterial);
+ materialEditor.RefreshDefaultValue();
+ materialEditor.Picker.SelectedItemChanged += () =>
+ {
+ var material = materialEditor.Picker.SelectedAsset as MaterialBase;
+ if (!material)
+ {
+ animatedModel.SetMaterial(entryIndex, GPUDevice.Instance.DefaultMaterial);
+ materialEditor.Picker.SelectedAsset = GPUDevice.Instance.DefaultMaterial;
+ }
+ else if (material == animatedModel.SkinnedModel.MaterialSlots[entryIndex].Material)
+ {
+ animatedModel.SetMaterial(entryIndex, null);
+ }
+ else if (material == GPUDevice.Instance.DefaultMaterial && !animatedModel.SkinnedModel.MaterialSlots[entryIndex].Material)
+ {
+ animatedModel.SetMaterial(entryIndex, null);
+ }
+ else
+ {
+ animatedModel.SetMaterial(entryIndex, material);
+ }
+ };
+ }
+
base.Initialize(group);
}
+ ///
+ protected override void SpawnProperty(LayoutElementsContainer itemLayout, ValueContainer itemValues, ItemInfo item)
+ {
+ // Skip material member as it is overridden
+ if (item.Info.Name == "Material")
+ return;
+ base.SpawnProperty(itemLayout, itemValues, item);
+ }
+
///
public override void Refresh()
{
diff --git a/Source/Engine/Graphics/GPUDevice.h b/Source/Engine/Graphics/GPUDevice.h
index 4dbcf6d06..422e554a0 100644
--- a/Source/Engine/Graphics/GPUDevice.h
+++ b/Source/Engine/Graphics/GPUDevice.h
@@ -238,7 +238,7 @@ public:
///
/// Gets the default material.
///
- MaterialBase* GetDefaultMaterial() const;
+ API_PROPERTY() MaterialBase* GetDefaultMaterial() const;
///
/// Gets the default material (Deformable domain).