Skip to content

Instantly share code, notes, and snippets.

@karljj1
Last active November 23, 2023 14:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save karljj1/8d57394a18b67bac62e7f359ab554503 to your computer and use it in GitHub Desktop.
Save karljj1/8d57394a18b67bac62e7f359ab554503 to your computer and use it in GitHub Desktop.
Example of a UI Toolkit custom binding for Addressables (2023.3)
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UIElements;
#if UNITY_EDITOR
public class AssetReferenceConverter<T> : UnityEditor.UIElements.UxmlAttributeConverter<AssetReferenceT<T>> where T : Object
{
public override AssetReferenceT<T> FromString(string value)
{
var split = value.Split('#');
return new AssetReferenceT<T>(split[0]){ SubObjectName = split[1] };
}
public override string ToString(AssetReferenceT<T> value)
{
return $"{value.AssetGUID}#{value.SubObjectName}";
}
}
#endif
// Our concrete class for Texture2D
[UxmlObject]
public partial class Texure2DAddressablesBinding : AddressablesBinding<Texture2D>
{ }
[UxmlObject]
public partial class SpriteAddressablesBinding : AddressablesBinding<Sprite>
{ }
// Our generic class for any Object. A concrete class is needed for each to be used in UXML.
[UxmlObject]
public partial class AddressablesBinding<T> : CustomBinding where T: Object
{
[UxmlAttribute]
public AssetReferenceT<T> AssetReference { get; set; }
[UxmlAttribute]
public bool Synchronous { get; set; }
public AddressablesBinding()
{
updateTrigger = BindingUpdateTrigger.WhenDirty;
}
protected override void OnDeactivated(in BindingActivationContext context)
{
if (AssetReference.OperationHandle.IsValid())
AssetReference.ReleaseAsset();
base.OnDeactivated(context);
}
protected override BindingResult Update(in BindingContext context)
{
if (!AssetReference.OperationHandle.IsValid())
{
AssetReference.LoadAssetAsync<T>();
if (!AssetReference.OperationHandle.IsDone && Synchronous)
AssetReference.OperationHandle.WaitForCompletion();
}
if (!AssetReference.OperationHandle.IsDone)
return new BindingResult(BindingStatus.Pending);
if (AssetReference.OperationHandle.Status == AsyncOperationStatus.Failed)
return new BindingResult(BindingStatus.Failure, AssetReference.OperationHandle.OperationException?.ToString());
var element = context.targetElement;
if (ConverterGroups.TrySetValueGlobal(ref element, context.bindingId, AssetReference.OperationHandle.Result as T, out var errorCode))
return new BindingResult(BindingStatus.Success);
else
return new BindingResult(BindingStatus.Failure, errorCode.ToString());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment