Add support for editing path to the asset within AssetRefEditor
This commit is contained in:
@@ -77,11 +77,12 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
}
|
}
|
||||||
prop.Label(string.Format("Progress: {0}% ({1}/{2})", allKeys.Count > 0 ? (int)(((float)validCount / allKeys.Count * 100.0f)) : 0, validCount, allKeys.Count));
|
prop.Label(string.Format("Progress: {0}% ({1}/{2})", allKeys.Count > 0 ? (int)(((float)validCount / allKeys.Count * 100.0f)) : 0, validCount, allKeys.Count));
|
||||||
prop.Label("Tables:");
|
prop.Label("Tables:");
|
||||||
|
var projectFolder = Globals.ProjectFolder;
|
||||||
foreach (var table in e)
|
foreach (var table in e)
|
||||||
{
|
{
|
||||||
var namePath = table.Path;
|
var namePath = table.Path;
|
||||||
if (namePath.StartsWith(Globals.ProjectFolder))
|
if (namePath.StartsWith(projectFolder))
|
||||||
namePath = namePath.Substring(Globals.ProjectFolder.Length + 1);
|
namePath = namePath.Substring(projectFolder.Length + 1);
|
||||||
var tableLabel = prop.ClickableLabel(namePath).CustomControl;
|
var tableLabel = prop.ClickableLabel(namePath).CustomControl;
|
||||||
tableLabel.TextColorHighlighted = Color.Wheat;
|
tableLabel.TextColorHighlighted = Color.Wheat;
|
||||||
tableLabel.DoubleClick += delegate { Editor.Instance.Windows.ContentWin.Select(table); };
|
tableLabel.DoubleClick += delegate { Editor.Instance.Windows.ContentWin.Select(table); };
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FlaxEditor.Content;
|
using FlaxEditor.Content;
|
||||||
using FlaxEditor.CustomEditors.Elements;
|
|
||||||
using FlaxEditor.GUI;
|
using FlaxEditor.GUI;
|
||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
@@ -33,7 +32,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
[CustomEditor(typeof(Asset)), DefaultEditor]
|
[CustomEditor(typeof(Asset)), DefaultEditor]
|
||||||
public class AssetRefEditor : CustomEditor
|
public class AssetRefEditor : CustomEditor
|
||||||
{
|
{
|
||||||
private CustomElement<AssetPicker> _element;
|
private AssetPicker _picker;
|
||||||
private ScriptType _valueType;
|
private ScriptType _valueType;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -42,46 +41,59 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
{
|
{
|
||||||
if (!HasDifferentTypes)
|
if (HasDifferentTypes)
|
||||||
|
return;
|
||||||
|
_picker = layout.Custom<AssetPicker>().CustomControl;
|
||||||
|
|
||||||
|
_valueType = Values.Type.Type != typeof(object) || Values[0] == null ? Values.Type : TypeUtils.GetObjectType(Values[0]);
|
||||||
|
var assetType = _valueType;
|
||||||
|
if (assetType == typeof(string))
|
||||||
|
assetType = new ScriptType(typeof(Asset));
|
||||||
|
|
||||||
|
float height = 48;
|
||||||
|
var attributes = Values.GetAttributes();
|
||||||
|
var assetReference = (AssetReferenceAttribute)attributes?.FirstOrDefault(x => x is AssetReferenceAttribute);
|
||||||
|
if (assetReference != null)
|
||||||
{
|
{
|
||||||
_valueType = Values.Type.Type != typeof(object) || Values[0] == null ? Values.Type : TypeUtils.GetObjectType(Values[0]);
|
if (assetReference.UseSmallPicker)
|
||||||
var assetType = _valueType;
|
height = 32;
|
||||||
|
|
||||||
float height = 48;
|
if (string.IsNullOrEmpty(assetReference.TypeName))
|
||||||
var attributes = Values.GetAttributes();
|
|
||||||
var assetReference = (AssetReferenceAttribute)attributes?.FirstOrDefault(x => x is AssetReferenceAttribute);
|
|
||||||
if (assetReference != null)
|
|
||||||
{
|
{
|
||||||
if (assetReference.UseSmallPicker)
|
|
||||||
height = 32;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(assetReference.TypeName))
|
|
||||||
{
|
|
||||||
var customType = TypeUtils.GetType(assetReference.TypeName);
|
|
||||||
if (customType != ScriptType.Null)
|
|
||||||
assetType = customType;
|
|
||||||
else
|
|
||||||
Debug.LogWarning(string.Format("Unknown asset type '{0}' to use for asset picker filter.", assetReference.TypeName));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if (assetReference.TypeName.Length > 1 && assetReference.TypeName[0] == '.')
|
||||||
_element = layout.Custom<AssetPicker>();
|
{
|
||||||
_element.CustomControl.AssetType = assetType;
|
// Generic file picker
|
||||||
_element.CustomControl.Height = height;
|
assetType = ScriptType.Null;
|
||||||
_element.CustomControl.SelectedItemChanged += OnSelectedItemChanged;
|
_picker.FileExtension = assetReference.TypeName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var customType = TypeUtils.GetType(assetReference.TypeName);
|
||||||
|
if (customType != ScriptType.Null)
|
||||||
|
assetType = customType;
|
||||||
|
else
|
||||||
|
Debug.LogWarning(string.Format("Unknown asset type '{0}' to use for asset picker filter.", assetReference.TypeName));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_picker.AssetType = assetType;
|
||||||
|
_picker.Height = height;
|
||||||
|
_picker.SelectedItemChanged += OnSelectedItemChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSelectedItemChanged()
|
private void OnSelectedItemChanged()
|
||||||
{
|
{
|
||||||
if (typeof(AssetItem).IsAssignableFrom(_valueType.Type))
|
if (typeof(AssetItem).IsAssignableFrom(_valueType.Type))
|
||||||
SetValue(_element.CustomControl.SelectedItem);
|
SetValue(_picker.SelectedItem);
|
||||||
else if (_valueType.Type == typeof(Guid))
|
else if (_valueType.Type == typeof(Guid))
|
||||||
SetValue(_element.CustomControl.SelectedID);
|
SetValue(_picker.SelectedID);
|
||||||
else if (_valueType.Type == typeof(SceneReference))
|
else if (_valueType.Type == typeof(SceneReference))
|
||||||
SetValue(new SceneReference(_element.CustomControl.SelectedID));
|
SetValue(new SceneReference(_picker.SelectedID));
|
||||||
|
else if (_valueType.Type == typeof(string))
|
||||||
|
SetValue(_picker.SelectedPath);
|
||||||
else
|
else
|
||||||
SetValue(_element.CustomControl.SelectedAsset);
|
SetValue(_picker.SelectedAsset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -92,13 +104,15 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
if (!HasDifferentValues)
|
if (!HasDifferentValues)
|
||||||
{
|
{
|
||||||
if (Values[0] is AssetItem assetItem)
|
if (Values[0] is AssetItem assetItem)
|
||||||
_element.CustomControl.SelectedItem = assetItem;
|
_picker.SelectedItem = assetItem;
|
||||||
else if (Values[0] is Guid guid)
|
else if (Values[0] is Guid guid)
|
||||||
_element.CustomControl.SelectedID = guid;
|
_picker.SelectedID = guid;
|
||||||
else if (Values[0] is SceneReference sceneAsset)
|
else if (Values[0] is SceneReference sceneAsset)
|
||||||
_element.CustomControl.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;
|
||||||
else
|
else
|
||||||
_element.CustomControl.SelectedAsset = Values[0] as Asset;
|
_picker.SelectedAsset = Values[0] as Asset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -510,7 +510,7 @@ namespace FlaxEditor
|
|||||||
}
|
}
|
||||||
else if (!_autoSavePopup.Visible && !_autoSavePopup.UserClosed)
|
else if (!_autoSavePopup.Visible && !_autoSavePopup.UserClosed)
|
||||||
_autoSavePopup.ShowPopup();
|
_autoSavePopup.ShowPopup();
|
||||||
|
|
||||||
if (_autoSavePopup.Visible)
|
if (_autoSavePopup.Visible)
|
||||||
_autoSavePopup.UpdateTime(timeToNextSave);
|
_autoSavePopup.UpdateTime(timeToNextSave);
|
||||||
}
|
}
|
||||||
@@ -523,7 +523,7 @@ namespace FlaxEditor
|
|||||||
Scene.SaveScenes();
|
Scene.SaveScenes();
|
||||||
if (options.AutoSaveContent)
|
if (options.AutoSaveContent)
|
||||||
SaveContent();
|
SaveContent();
|
||||||
|
|
||||||
// Hide auto save popup and reset user closed
|
// Hide auto save popup and reset user closed
|
||||||
_autoSavePopup.HidePopup();
|
_autoSavePopup.HidePopup();
|
||||||
_autoSavePopup.UserClosed = false;
|
_autoSavePopup.UserClosed = false;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using FlaxEditor.Content;
|
using FlaxEditor.Content;
|
||||||
using FlaxEditor.GUI.Drag;
|
using FlaxEditor.GUI.Drag;
|
||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
@@ -22,22 +23,25 @@ namespace FlaxEditor.GUI
|
|||||||
private const float ButtonsSize = 12;
|
private const float ButtonsSize = 12;
|
||||||
|
|
||||||
private Asset _selected;
|
private Asset _selected;
|
||||||
private AssetItem _selectedItem;
|
private ContentItem _selectedItem;
|
||||||
private ScriptType _type;
|
private ScriptType _type;
|
||||||
|
private string _fileExtension;
|
||||||
|
|
||||||
private bool _isMouseDown;
|
private bool _isMouseDown;
|
||||||
private Float2 _mouseDownPos;
|
private Float2 _mouseDownPos;
|
||||||
private Float2 _mousePos;
|
private Float2 _mousePos;
|
||||||
private DragAssets _dragOverElement;
|
private DragItems _dragOverElement;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the selected item.
|
/// Gets or sets the selected item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public AssetItem SelectedItem
|
public ContentItem SelectedItem
|
||||||
{
|
{
|
||||||
get => _selectedItem;
|
get => _selectedItem;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
if (_selectedItem == value)
|
||||||
|
return;
|
||||||
if (value == null)
|
if (value == null)
|
||||||
{
|
{
|
||||||
if (_selected == null && _selectedItem is SceneItem)
|
if (_selected == null && _selectedItem is SceneItem)
|
||||||
@@ -46,13 +50,15 @@ namespace FlaxEditor.GUI
|
|||||||
_selectedItem.RemoveReference(this);
|
_selectedItem.RemoveReference(this);
|
||||||
_selectedItem = null;
|
_selectedItem = null;
|
||||||
_selected = null;
|
_selected = null;
|
||||||
TooltipText = string.Empty;
|
|
||||||
OnSelectedItemChanged();
|
OnSelectedItemChanged();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deselect
|
// Deselect
|
||||||
SelectedAsset = null;
|
_selectedItem?.RemoveReference(this);
|
||||||
|
_selectedItem = null;
|
||||||
|
_selected = null;
|
||||||
|
OnSelectedItemChanged();
|
||||||
}
|
}
|
||||||
else if (value is SceneItem item)
|
else if (value is SceneItem item)
|
||||||
{
|
{
|
||||||
@@ -66,15 +72,19 @@ namespace FlaxEditor.GUI
|
|||||||
_selectedItem = item;
|
_selectedItem = item;
|
||||||
_selected = null;
|
_selected = null;
|
||||||
_selectedItem?.AddReference(this);
|
_selectedItem?.AddReference(this);
|
||||||
|
|
||||||
// Update tooltip
|
|
||||||
TooltipText = _selectedItem?.NamePath;
|
|
||||||
|
|
||||||
OnSelectedItemChanged();
|
OnSelectedItemChanged();
|
||||||
}
|
}
|
||||||
|
else if (value is AssetItem assetItem)
|
||||||
|
{
|
||||||
|
SelectedAsset = FlaxEngine.Content.LoadAsync(assetItem.ID);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SelectedAsset = FlaxEngine.Content.LoadAsync(value.ID);
|
// Change value
|
||||||
|
_selectedItem?.RemoveReference(this);
|
||||||
|
_selectedItem = value;
|
||||||
|
_selected = null;
|
||||||
|
OnSelectedItemChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,13 +98,44 @@ namespace FlaxEditor.GUI
|
|||||||
{
|
{
|
||||||
if (_selected != null)
|
if (_selected != null)
|
||||||
return _selected.ID;
|
return _selected.ID;
|
||||||
if (_selectedItem != null)
|
if (_selectedItem is AssetItem assetItem)
|
||||||
return _selectedItem.ID;
|
return assetItem.ID;
|
||||||
return Guid.Empty;
|
return Guid.Empty;
|
||||||
}
|
}
|
||||||
set => SelectedItem = Editor.Instance.ContentDatabase.FindAsset(value);
|
set => SelectedItem = Editor.Instance.ContentDatabase.FindAsset(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the selected content item path.
|
||||||
|
/// </summary>
|
||||||
|
public string SelectedPath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string path = _selectedItem?.Path ?? _selected?.Path;
|
||||||
|
if (path != null)
|
||||||
|
{
|
||||||
|
// Convert into path relative to the project (cross-platform)
|
||||||
|
var projectFolder = Globals.ProjectFolder;
|
||||||
|
if (path.StartsWith(projectFolder))
|
||||||
|
path = path.Substring(projectFolder.Length + 1);
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
SelectedItem = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var path = StringUtils.IsRelative(value) ? Path.Combine(Globals.ProjectFolder, value) : value;
|
||||||
|
SelectedItem = Editor.Instance.ContentDatabase.Find(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the selected asset object.
|
/// Gets or sets the selected asset object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -117,16 +158,12 @@ namespace FlaxEditor.GUI
|
|||||||
_selectedItem = item;
|
_selectedItem = item;
|
||||||
_selected = value;
|
_selected = value;
|
||||||
_selectedItem?.AddReference(this);
|
_selectedItem?.AddReference(this);
|
||||||
|
|
||||||
// Update tooltip
|
|
||||||
TooltipText = _selectedItem?.NamePath;
|
|
||||||
|
|
||||||
OnSelectedItemChanged();
|
OnSelectedItemChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the assets types that this picker accepts (it supports types derived from the given type).
|
/// Gets or sets the assets types that this picker accepts (it supports types derived from the given type). Use <see cref="ScriptType.Null"/> for generic file picker.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ScriptType AssetType
|
public ScriptType AssetType
|
||||||
{
|
{
|
||||||
@@ -144,6 +181,25 @@ namespace FlaxEditor.GUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the content items extensions filter. Null if unused.
|
||||||
|
/// </summary>
|
||||||
|
public string FileExtension
|
||||||
|
{
|
||||||
|
get => _fileExtension;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_fileExtension != value)
|
||||||
|
{
|
||||||
|
_fileExtension = value;
|
||||||
|
|
||||||
|
// Auto deselect if the current value is invalid
|
||||||
|
if (_selectedItem != null && !IsValid(_selectedItem))
|
||||||
|
SelectedItem = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when selected item gets changed.
|
/// Occurs when selected item gets changed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -154,24 +210,32 @@ namespace FlaxEditor.GUI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CanEdit = true;
|
public bool CanEdit = true;
|
||||||
|
|
||||||
private bool IsValid(AssetItem item)
|
private bool IsValid(ContentItem item)
|
||||||
{
|
{
|
||||||
// Faster path for binary items (in-build)
|
if (_fileExtension != null && !item.Path.EndsWith(_fileExtension))
|
||||||
if (item is BinaryAssetItem binaryItem)
|
return false;
|
||||||
return _type.IsAssignableFrom(new ScriptType(binaryItem.Type));
|
if (_type == ScriptType.Null)
|
||||||
|
|
||||||
// Type filter
|
|
||||||
var type = TypeUtils.GetType(item.TypeName);
|
|
||||||
if (_type.IsAssignableFrom(type))
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Json assets can contain any type of the object defined by the C# type (data oriented design)
|
if (item is AssetItem assetItem)
|
||||||
if (item is JsonAssetItem && (_type.Type == typeof(JsonAsset) || _type.Type == typeof(Asset)))
|
{
|
||||||
return true;
|
// Faster path for binary items (in-built)
|
||||||
|
if (assetItem is BinaryAssetItem binaryItem)
|
||||||
|
return _type.IsAssignableFrom(new ScriptType(binaryItem.Type));
|
||||||
|
|
||||||
// Special case for scene asset references
|
// Type filter
|
||||||
if (_type.Type == typeof(SceneReference) && item is SceneItem)
|
var type = TypeUtils.GetType(assetItem.TypeName);
|
||||||
return true;
|
if (_type.IsAssignableFrom(type))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Json assets can contain any type of the object defined by the C# type (data oriented design)
|
||||||
|
if (assetItem is JsonAssetItem && (_type.Type == typeof(JsonAsset) || _type.Type == typeof(Asset)))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Special case for scene asset references
|
||||||
|
if (_type.Type == typeof(SceneReference) && assetItem is SceneItem)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -201,15 +265,26 @@ namespace FlaxEditor.GUI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void OnSelectedItemChanged()
|
protected virtual void OnSelectedItemChanged()
|
||||||
{
|
{
|
||||||
|
// Update tooltip
|
||||||
|
string tooltip;
|
||||||
|
if (_selectedItem is AssetItem assetItem)
|
||||||
|
tooltip = assetItem.NamePath;
|
||||||
|
else
|
||||||
|
tooltip = SelectedPath;
|
||||||
|
TooltipText = tooltip;
|
||||||
|
|
||||||
SelectedItemChanged?.Invoke();
|
SelectedItemChanged?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DoDrag()
|
private void DoDrag()
|
||||||
{
|
{
|
||||||
// Do the drag drop operation if has selected element
|
// Do the drag drop operation if has selected element
|
||||||
if (_selected != null && new Rectangle(Float2.Zero, Size).Contains(ref _mouseDownPos))
|
if (new Rectangle(Float2.Zero, Size).Contains(ref _mouseDownPos))
|
||||||
{
|
{
|
||||||
DoDragDrop(DragAssets.GetDragData(_selected));
|
if (_selected != null)
|
||||||
|
DoDragDrop(DragAssets.GetDragData(_selected));
|
||||||
|
else if (_selectedItem != null)
|
||||||
|
DoDragDrop(DragItems.GetDragData(_selectedItem));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,10 +414,7 @@ namespace FlaxEditor.GUI
|
|||||||
// Check if start drag drop
|
// Check if start drag drop
|
||||||
if (_isMouseDown)
|
if (_isMouseDown)
|
||||||
{
|
{
|
||||||
// Clear flag
|
|
||||||
_isMouseDown = false;
|
_isMouseDown = false;
|
||||||
|
|
||||||
// Do the drag
|
|
||||||
DoDrag();
|
DoDrag();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +438,6 @@ namespace FlaxEditor.GUI
|
|||||||
// Check if start drag drop
|
// Check if start drag drop
|
||||||
if (_isMouseDown && Float2.Distance(location, _mouseDownPos) > 10.0f && IconRect.Contains(_mouseDownPos))
|
if (_isMouseDown && Float2.Distance(location, _mouseDownPos) > 10.0f && IconRect.Contains(_mouseDownPos))
|
||||||
{
|
{
|
||||||
// Do the drag
|
|
||||||
_isMouseDown = false;
|
_isMouseDown = false;
|
||||||
DoDrag();
|
DoDrag();
|
||||||
}
|
}
|
||||||
@@ -392,14 +463,27 @@ namespace FlaxEditor.GUI
|
|||||||
}
|
}
|
||||||
else if (Button1Rect.Contains(location))
|
else if (Button1Rect.Contains(location))
|
||||||
{
|
{
|
||||||
// Show asset picker popup
|
|
||||||
Focus();
|
Focus();
|
||||||
AssetSearchPopup.Show(this, Button1Rect.BottomLeft, IsValid, assetItem =>
|
if (_type != ScriptType.Null)
|
||||||
{
|
{
|
||||||
SelectedItem = assetItem;
|
// Show asset picker popup
|
||||||
RootWindow.Focus();
|
AssetSearchPopup.Show(this, Button1Rect.BottomLeft, IsValid, item =>
|
||||||
Focus();
|
{
|
||||||
});
|
SelectedItem = item;
|
||||||
|
RootWindow.Focus();
|
||||||
|
Focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Show content item picker popup
|
||||||
|
ContentSearchPopup.Show(this, Button1Rect.BottomLeft, IsValid, item =>
|
||||||
|
{
|
||||||
|
SelectedItem = item;
|
||||||
|
RootWindow.Focus();
|
||||||
|
Focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (_selected != null || _selectedItem != null)
|
else if (_selected != null || _selectedItem != null)
|
||||||
{
|
{
|
||||||
@@ -437,10 +521,8 @@ namespace FlaxEditor.GUI
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
|
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
|
||||||
{
|
{
|
||||||
// Focus
|
|
||||||
Focus();
|
Focus();
|
||||||
|
|
||||||
// Check if has element selected
|
|
||||||
if (_selectedItem != null && IconRect.Contains(location))
|
if (_selectedItem != null && IconRect.Contains(location))
|
||||||
{
|
{
|
||||||
// Open it
|
// Open it
|
||||||
@@ -458,7 +540,7 @@ namespace FlaxEditor.GUI
|
|||||||
|
|
||||||
// Check if drop asset
|
// Check if drop asset
|
||||||
if (_dragOverElement == null)
|
if (_dragOverElement == null)
|
||||||
_dragOverElement = new DragAssets(IsValid);
|
_dragOverElement = new DragItems(IsValid);
|
||||||
if (CanEdit && _dragOverElement.OnDragEnter(data))
|
if (CanEdit && _dragOverElement.OnDragEnter(data))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,40 +8,38 @@ using FlaxEngine.GUI;
|
|||||||
namespace FlaxEditor.GUI
|
namespace FlaxEditor.GUI
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Popup that shows the list of assets to pick. Supports searching and basic items filtering.
|
/// Popup that shows the list of content items to pick. Supports searching and basic items filtering.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.GUI.ItemsListContextMenu" />
|
/// <seealso cref="FlaxEditor.GUI.ItemsListContextMenu" />
|
||||||
public class AssetSearchPopup : ItemsListContextMenu
|
public class ContentSearchPopup : ItemsListContextMenu
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The asset item.
|
/// The content item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.GUI.ItemsListContextMenu.Item" />
|
/// <seealso cref="FlaxEditor.GUI.ItemsListContextMenu.Item" />
|
||||||
public class AssetItemView : Item, IContentItemOwner
|
public class ContentItemView : Item, IContentItemOwner
|
||||||
{
|
{
|
||||||
private AssetItem _asset;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The icon size (in pixels).
|
/// The icon size (in pixels).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const float IconSize = 28;
|
public const float IconSize = 28;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the asset.
|
/// Gets the item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public AssetItem Asset => _asset;
|
public ContentItem ContentItem;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="AssetItemView"/> class.
|
/// Initializes a new instance of the <see cref="ContentItemView"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="asset">The asset.</param>
|
/// <param name="item">The item.</param>
|
||||||
public AssetItemView(AssetItem asset)
|
public ContentItemView(ContentItem item)
|
||||||
{
|
{
|
||||||
_asset = asset;
|
ContentItem = item;
|
||||||
_asset.AddReference(this);
|
ContentItem.AddReference(this);
|
||||||
|
|
||||||
Name = asset.ShortName;
|
Name = item.ShortName;
|
||||||
TooltipText = asset.Path;
|
TooltipText = item.Path;
|
||||||
|
|
||||||
Height = IconSize + 4;
|
Height = IconSize + 4;
|
||||||
}
|
}
|
||||||
@@ -60,16 +58,16 @@ namespace FlaxEditor.GUI
|
|||||||
|
|
||||||
// Draw icon
|
// Draw icon
|
||||||
var iconRect = new Rectangle(2, 2, IconSize, IconSize);
|
var iconRect = new Rectangle(2, 2, IconSize, IconSize);
|
||||||
_asset.DrawThumbnail(ref iconRect);
|
ContentItem.DrawThumbnail(ref iconRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnDestroy()
|
public override void OnDestroy()
|
||||||
{
|
{
|
||||||
if (_asset != null)
|
if (ContentItem != null)
|
||||||
{
|
{
|
||||||
_asset.RemoveReference(this);
|
ContentItem.RemoveReference(this);
|
||||||
_asset = null;
|
ContentItem = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
base.OnDestroy();
|
base.OnDestroy();
|
||||||
@@ -84,7 +82,7 @@ namespace FlaxEditor.GUI
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void OnItemRenamed(ContentItem item)
|
public void OnItemRenamed(ContentItem item)
|
||||||
{
|
{
|
||||||
Name = _asset.ShortName;
|
Name = ContentItem.ShortName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -99,12 +97,118 @@ namespace FlaxEditor.GUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validates if the given content item can be used to pick it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The item.</param>
|
||||||
|
/// <returns>True if is valid.</returns>
|
||||||
|
public delegate bool IsValidDelegate(ContentItem item);
|
||||||
|
|
||||||
|
private IsValidDelegate _isValid;
|
||||||
|
private Action<ContentItem> _selected;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected ContentSearchPopup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected ContentSearchPopup(IsValidDelegate isValid, Action<ContentItem> selected)
|
||||||
|
{
|
||||||
|
_isValid = isValid;
|
||||||
|
_selected = selected;
|
||||||
|
|
||||||
|
ItemClicked += OnItemClicked;
|
||||||
|
|
||||||
|
// TODO: use async thread to search workspace items
|
||||||
|
foreach (var project in Editor.Instance.ContentDatabase.Projects)
|
||||||
|
{
|
||||||
|
if (project.Content != null)
|
||||||
|
FindItems(project.Content.Folder);
|
||||||
|
}
|
||||||
|
SortItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnItemClicked(Item item)
|
||||||
|
{
|
||||||
|
_selected.Invoke(((ContentItemView)item).ContentItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FindItems(ContentFolder folder)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < folder.Children.Count; i++)
|
||||||
|
{
|
||||||
|
if (folder.Children[i] is ContentItem item && _isValid(item))
|
||||||
|
{
|
||||||
|
AddItem(new ContentItemView(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < folder.Children.Count; i++)
|
||||||
|
{
|
||||||
|
if (folder.Children[i] is ContentFolder child)
|
||||||
|
{
|
||||||
|
FindItems(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shows the popup.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="showTarget">The show target.</param>
|
||||||
|
/// <param name="showTargetLocation">The show target location.</param>
|
||||||
|
/// <param name="isValid">Event called to check if a given content item is valid to be used.</param>
|
||||||
|
/// <param name="selected">Event called on content item pick.</param>
|
||||||
|
/// <returns>The dialog.</returns>
|
||||||
|
public static ContentSearchPopup Show(Control showTarget, Float2 showTargetLocation, IsValidDelegate isValid, Action<ContentItem> selected)
|
||||||
|
{
|
||||||
|
var popup = new ContentSearchPopup(isValid, selected);
|
||||||
|
popup.Show(showTarget, showTargetLocation);
|
||||||
|
return popup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnDestroy()
|
||||||
|
{
|
||||||
|
_isValid = null;
|
||||||
|
_selected = null;
|
||||||
|
|
||||||
|
base.OnDestroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Popup that shows the list of assets to pick. Supports searching and basic items filtering.
|
||||||
|
/// </summary>
|
||||||
|
public class AssetSearchPopup : ContentSearchPopup
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The asset item.
|
||||||
|
/// </summary>
|
||||||
|
public class AssetItemView : ContentItemView
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the asset.
|
||||||
|
/// </summary>
|
||||||
|
public AssetItem AssetItem => (AssetItem)ContentItem;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AssetItemView"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="asset">The asset.</param>
|
||||||
|
public AssetItemView(AssetItem asset)
|
||||||
|
: base(asset)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Validates if the given asset item can be used to pick it.
|
/// Validates if the given asset item can be used to pick it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="asset">The asset.</param>
|
/// <param name="asset">The asset.</param>
|
||||||
/// <returns>True if is valid.</returns>
|
/// <returns>True if is valid.</returns>
|
||||||
public delegate bool IsValidDelegate(AssetItem asset);
|
public new delegate bool IsValidDelegate(AssetItem asset);
|
||||||
|
|
||||||
private IsValidDelegate _isValid;
|
private IsValidDelegate _isValid;
|
||||||
private Action<AssetItem> _selected;
|
private Action<AssetItem> _selected;
|
||||||
@@ -127,7 +231,7 @@ namespace FlaxEditor.GUI
|
|||||||
|
|
||||||
private void OnItemClicked(Item item)
|
private void OnItemClicked(Item item)
|
||||||
{
|
{
|
||||||
_selected(((AssetItemView)item).Asset);
|
_selected(((AssetItemView)item).AssetItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FindAssets(ContentFolder folder)
|
private void FindAssets(ContentFolder folder)
|
||||||
|
|||||||
@@ -1024,10 +1024,9 @@ namespace FlaxEditor.Utilities
|
|||||||
/// <returns>The processed name path.</returns>
|
/// <returns>The processed name path.</returns>
|
||||||
public static string GetAssetNamePath(string path)
|
public static string GetAssetNamePath(string path)
|
||||||
{
|
{
|
||||||
if (path.StartsWith(Globals.ProjectFolder))
|
var projectFolder = Globals.ProjectFolder;
|
||||||
{
|
if (path.StartsWith(projectFolder))
|
||||||
path = path.Substring(Globals.ProjectFolder.Length + 1);
|
path = path.Substring(projectFolder.Length + 1);
|
||||||
}
|
|
||||||
return StringUtils.GetPathWithoutExtension(path);
|
return StringUtils.GetPathWithoutExtension(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ namespace FlaxEditor.Windows
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
picker.SelectedID = AssetId;
|
picker.SelectedID = AssetId;
|
||||||
var assetItem = picker.SelectedItem;
|
var assetItem = picker.SelectedItem as AssetItem;
|
||||||
if (assetItem != null)
|
if (assetItem != null)
|
||||||
{
|
{
|
||||||
Title = assetItem.ShortName;
|
Title = assetItem.ShortName;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace FlaxEngine
|
|||||||
public class AssetReferenceAttribute : Attribute
|
public class AssetReferenceAttribute : Attribute
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The full name of the asset type to link. Use null or empty to skip it.
|
/// The full name of the asset type to link. Use null or empty to skip it. Can be used as file extension filter if starts with a dot and used over string property.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TypeName;
|
public string TypeName;
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ namespace FlaxEngine
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="AssetReferenceAttribute"/> class.
|
/// Initializes a new instance of the <see cref="AssetReferenceAttribute"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="typeName">The full name of the asset type to link. Use null or empty to skip it.</param>
|
/// <param name="typeName">The full name of the asset type to link. Use null or empty to skip it. Can be used as file extension filter if starts with a dot and used over string property.</param>
|
||||||
/// <param name="useSmallPicker">True if use asset picker with a smaller height (single line), otherwise will use with full icon.</param>
|
/// <param name="useSmallPicker">True if use asset picker with a smaller height (single line), otherwise will use with full icon.</param>
|
||||||
public AssetReferenceAttribute(string typeName = null, bool useSmallPicker = false)
|
public AssetReferenceAttribute(string typeName = null, bool useSmallPicker = false)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user