Skip to content

Vfx/fix/1289612 filter texture by dimension #5715

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Oct 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions com.unity.visualeffectgraph/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Eye dropper in the color fields kept updating after pressing the Esc key
- Automatically offset contexts when a new node is inserted to avoid overlapping
- Compilation error while using not exposed texture in ShaderGraph [Case 1367167](https://issuetracker.unity3d.com/product/unity/issues/guid/1367167/)
- Texture picker lists only textures with expected dimensions (2D, 3D, Cubemap)

## [12.0.0] - 2021-01-11
### Added
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Reflection;

using UnityEditor.Search;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Search;

using Object = UnityEngine.Object;

namespace UnityEditor.VFX.UI
{
static class CustomObjectPicker
{
internal static void Pick(Type type, TextureDimension textureDimension, Action<Object, bool> selectHandler)
{
var view = typeof(Texture).IsAssignableFrom(type)
? GetTexturePickerView(type, textureDimension, selectHandler)
: GetGenericView(type, selectHandler);

// Until the "viewState" API is made public (should be in 2022.1) we use reflection to remove the inspector button
var quickSearchType = typeof(Search.SearchService).Assembly.GetType("UnityEditor.Search.QuickSearch");
var viewStateInfo = quickSearchType?.GetProperty("viewState", BindingFlags.Instance | BindingFlags.NonPublic);
var state = viewStateInfo?.GetValue(view);
if (state != null)
{
var flagsInfo = state.GetType().GetField("flags", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
flagsInfo?.SetValue(state, SearchViewFlags.DisableInspectorPreview);
}
}

static ISearchView GetGenericView(Type type, Action<Object, bool> selectHandler)
{
return Search.SearchService.ShowObjectPicker(
selectHandler,
null,
null,
type.Name,
type);
}

static ISearchView GetTexturePickerView(Type type, TextureDimension textureDimension, Action<Object, bool> selectHandler)
{
var view = Search.SearchService.ShowPicker(
Search.SearchService.CreateContext(CreateTextureProvider(type, textureDimension)),
(x, y) => selectHandler(x?.ToObject(), y),
null,
null,
null,
type.Name,
5f);
view.itemIconSize = 5f;

return view;
}

static SearchProvider CreateTextureProvider(Type type, TextureDimension textureDimension)
{
return new SearchProvider("tex", "Texture", (context, _) => FetchTextures(type, textureDimension, context));
}

static IEnumerable<SearchItem> FetchTextures(Type type, TextureDimension textureDimension, SearchContext context)
{
// This piece of code is meant to put RenderTextures in a separate tab
// But the display is right now buggy, so keep it for later use when display issue is fixed
//var createGroupProviderMethod = typeof(Search.SearchUtils).GetMethod("CreateGroupProvider", BindingFlags.NonPublic|BindingFlags.Static);
//SearchProvider textureGroupProvider = null;
//SearchProvider renderTextureGroupProvider = null;
//if (createGroupProviderMethod != null)
//{
// textureGroupProvider = createGroupProviderMethod.Invoke(null, new object[] { adbProvider, type.Name, 0, true }) as SearchProvider;
// renderTextureGroupProvider = createGroupProviderMethod.Invoke(null, new object[] { adbProvider, "Render Textures", 1, true }) as SearchProvider;;
//}

var userQuery = context.searchQuery;
var providers = new[] { Search.SearchService.GetProvider("adb") };

using (var query = Search.SearchService.CreateContext(providers, $"t:{type.Name} {userQuery}", context.options))
using (var request = Search.SearchService.Request(query))
{
foreach (var r in request)
{
//r.provider = textureGroupProvider;
yield return r;
}
}

if (type != typeof(RenderTexture))
{
using (var query = Search.SearchService.CreateContext(providers, $"t:{nameof(RenderTexture)} {userQuery}", context.options))
using (var request = Search.SearchService.Request(query))
{
foreach (var r in request)
{
if (r == null) continue;
var rt = r.ToObject<RenderTexture>();
if (rt.dimension == textureDimension)
{
//r.provider = renderTextureGroupProvider;
yield return r;
}
}
}
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,121 +1,139 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
using UnityEditor.VFX;
using UnityEditor.VFX.UIElements;
using UnityObject = UnityEngine.Object;
using Type = System.Type;

using ObjectField = UnityEditor.VFX.UI.VFXLabeledField<UnityEditor.UIElements.ObjectField, UnityEngine.Object>;
using UnityObject = UnityEngine.Object;

namespace UnityEditor.VFX.UI
{
class ObjectPropertyRM : PropertyRM<UnityObject>
{
public ObjectPropertyRM(IPropertyRMProvider controller, float labelWidth) : base(controller, labelWidth)
static readonly Dictionary<Type, TextureDimension> s_TypeToDimensionMap = new()
{
m_ObjectField = new ObjectField(m_Label);
if (controller.portType == typeof(Texture2D) || controller.portType == typeof(Texture3D) || controller.portType == typeof(Cubemap))
m_ObjectField.control.objectType = typeof(Texture);
else
m_ObjectField.control.objectType = controller.portType;

m_ObjectField.RegisterCallback<ChangeEvent<UnityObject>>(OnValueChanged);
m_ObjectField.control.allowSceneObjects = false;
m_ObjectField.style.flexGrow = 1f;
m_ObjectField.style.flexShrink = 1f;
RegisterCallback<KeyDownEvent>(StopKeyPropagation);
Add(m_ObjectField);
}
{ typeof(Texture2D), TextureDimension.Tex2D },
{ typeof(Texture3D), TextureDimension.Tex3D },
{ typeof(Cubemap), TextureDimension.Cube },
};

public override float GetPreferredControlWidth()
{
return 120;
}
readonly TextField m_TextField;
readonly Image m_ValueIcon;
readonly TextureDimension m_textureDimension;

void StopKeyPropagation(KeyDownEvent e)
public ObjectPropertyRM(IPropertyRMProvider controller, float labelWidth) : base(controller, labelWidth)
{
e.StopPropagation();
}
styleSheets.Add(VFXView.LoadStyleSheet("ObjectPropertyRM"));

public void OnValueChanged(ChangeEvent<UnityObject> onObjectChanged)
{
UnityObject newValue = m_ObjectField.value;
if (typeof(Texture).IsAssignableFrom(m_Provider.portType))
{
Texture tex = newValue as Texture;
m_TextField = new TextField { name = "PickLabel", isReadOnly = true };
var button = new Button { name = "PickButton" };
var icon = new VisualElement { name = "PickIcon" };
m_ValueIcon = new Image { name = "TextureIcon" };

if (tex != null)
{
if (m_Provider.portType == typeof(Texture2D))
{
if (tex.dimension != TextureDimension.Tex2D)
{
Debug.LogError("Wrong Texture Dimension");

newValue = null;
}
}
else if (m_Provider.portType == typeof(Texture3D))
{
if (tex.dimension != TextureDimension.Tex3D)
{
Debug.LogError("Wrong Texture Dimension");

newValue = null;
}
}
else if (m_Provider.portType == typeof(Cubemap))
{
if (tex.dimension != TextureDimension.Cube)
{
Debug.LogError("Wrong Texture Dimension");

newValue = null;
}
}
}
}
m_Value = newValue;
NotifyValueChanged();
}
button.clicked += OnPickObject;
button.Add(icon);
m_TextField.Add(m_ValueIcon);
m_TextField.Add(button);
Add(m_TextField);

ObjectField m_ObjectField;
m_TextField.RegisterCallback<ClickEvent>(OnClickToShow);
RegisterCallback<DragUpdatedEvent>(OnDragUpdate);
RegisterCallback<DragEnterEvent>(OnDragEnter);
RegisterCallback<DragPerformEvent>(OnDragPerformed);

protected override void UpdateEnabled()
{
m_ObjectField.SetEnabled(propertyEnabled);
if (!s_TypeToDimensionMap.TryGetValue(m_Provider.portType, out m_textureDimension))
{
m_textureDimension = TextureDimension.Unknown;
}
}

protected override void UpdateIndeterminate()
{
m_ObjectField.visible = !indeterminate;
}
public override float GetPreferredControlWidth() => 120;

public override void UpdateGUI(bool force)
{
if (force)
m_ObjectField.SetValueWithoutNotify(null);
m_ObjectField.SetValueWithoutNotify(m_Value);
{
NotifyValueChanged();
}
}

public override void SetValue(object obj) // object setvalue should accept null
{
try
{
m_Value = (UnityObject)obj;
m_ValueIcon.image = obj != null
? AssetPreview.GetMiniTypeThumbnail(m_Value)
: AssetPreview.GetMiniTypeThumbnail(m_Provider.portType);
m_TextField.value = m_Value?.name ?? $"None ({m_Provider.portType.Name})";
}
catch (System.Exception)
catch (Exception)
{
Debug.Log("Error Trying to convert" + (obj != null ? obj.GetType().Name : "null") + " to " + typeof(UnityObject).Name);
Debug.Log($"Error Trying to convert {obj?.GetType().Name ?? "null"} to Object");
}

UpdateGUI(!object.ReferenceEquals(m_Value, obj));
UpdateGUI(!ReferenceEquals(m_Value, obj));
}

public override bool showsEverything { get { return true; } }
public override bool showsEverything => true;

protected override void UpdateEnabled() => SetEnabled(propertyEnabled);

protected override void UpdateIndeterminate() => visible = !indeterminate;

void OnPickObject() => CustomObjectPicker.Pick(m_Provider.portType, m_textureDimension, SelectHandler);

void SelectHandler(UnityObject obj, bool isCanceled)
{
if (!isCanceled)
{
SetValue(obj);
NotifyValueChanged();
}
}

void OnClickToShow(ClickEvent evt)
{
EditorGUI.PingObjectOrShowPreviewOnClick(m_Value, Rect.zero);
}

bool CanDrag()
{
if (DragAndDrop.objectReferences.Length == 1)
{
var type = DragAndDrop.objectReferences[0].GetType();
if (m_Provider.portType.IsAssignableFrom(type))
{
return true;
}

if (m_textureDimension != TextureDimension.Unknown && DragAndDrop.objectReferences[0] is Texture texture)
{
return texture.dimension == m_textureDimension;
}
}

return false;
}

void OnDragEnter(DragEnterEvent evt)
{
DragAndDrop.visualMode = CanDrag() ? DragAndDropVisualMode.Link : DragAndDropVisualMode.Rejected;
evt.StopPropagation();
}

void OnDragUpdate(DragUpdatedEvent evt)
{
DragAndDrop.visualMode = CanDrag() ? DragAndDropVisualMode.Link : DragAndDropVisualMode.Rejected;
evt.StopPropagation();
}

void OnDragPerformed(DragPerformEvent evt)
{
var dragObject = DragAndDrop.objectReferences.First();
SelectHandler(dragObject, false);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
using System;
using System.Collections.Generic;
using UnityEngine;

using UnityObject = UnityEngine.Object;
using UnityEngine.Rendering;

namespace UnityEditor.VFX
{
[VFXInfo(type = typeof(Texture2D))]
class VFXSlotTexture2D : VFXSlotObject
{
protected override void GenerateErrors(VFXInvalidateErrorReporter manager)
{
if (value is Texture texture && texture.dimension != TextureDimension.Tex2D)
manager.RegisterError("Slot_Value_Incorrect_Texture2D", VFXErrorType.Error, "This slot expects a Texture2D");

base.GenerateErrors(manager);
}

public override VFXValue DefaultExpression(VFXValue.Mode mode)
{
return new VFXTexture2DValue(0, mode);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using UnityEngine;
using UnityEngine.VFX;
using UnityEngine.Rendering;


Expand All @@ -9,6 +7,14 @@ namespace UnityEditor.VFX
[VFXInfo(type = typeof(Texture3D))]
class VFXSlotTexture3D : VFXSlotObject
{
protected override void GenerateErrors(VFXInvalidateErrorReporter manager)
{
if (value is Texture texture && texture.dimension != TextureDimension.Tex3D)
manager.RegisterError("Slot_Value_Incorrect_Texture3D", VFXErrorType.Error, "This slot expects a Texture3D");

base.GenerateErrors(manager);
}

public override VFXValue DefaultExpression(VFXValue.Mode mode)
{
return new VFXTexture3DValue(0, mode);
Expand Down
Loading