Ill try to be concise.
I am trying to create custom property drawers that show images of the Item data I provide.
I am having trouble with the item data and item combination data clearing its self.
The Image data also seems to be overwriting the other item data scriptable objects.
I need helping solving this
I Have 2 Data Classes that do not inherit from MonoBehaviour
and are not ScriptableObject
s.
ItemData:
using System;
using UnityEngine;
[Serializable]
public class ItemData
{
[SerializeField] private Sprite _itemImage;
[SerializeField] private string _itemName;
[SerializeField] private int _itemID;
public Sprite ItemImage { get => _itemImage; set => _itemImage = value; }
public string ItemName { get => _itemName; set => _itemName = value; }
public int ItemID { get => _itemID; set => _itemID = value; }
}
ItemCombinationData:
using System;
using UnityEngine;
[Serializable]
public class ItemCombinationData
{
[SerializeField] private ItemData _itemA;
[SerializeField] private ItemData _itemB;
[SerializeField] private ItemData _result;
public ItemData ItemA { get => _itemA; set => _itemA = value; }
public ItemData ItemB { get => _itemB; set => _itemB = value; }
public ItemData Result { get => _result; set => _result = value; }
}
I Have 2 Scriptable Object
Classes For this Data.
ItemDataScriptableObject:
using UnityEngine;
[CreateAssetMenu (fileName = "Item", menuName = "ScriptableObjects/Item", order = 1)]
public class ItemDataScriptableObject : ScriptableObject
{
[SerializeField] private ItemData _itemData;
public ItemData ItemData { get => _itemData; set => _itemData = value; }
}
ItemCombinationScriptableObject:
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu (fileName = "ItemCombinationList", menuName = "ScriptableObjects/ItemCombinationTable", order = 1)]
public class ItemCombinationScriptableObject : ScriptableObject
{
[SerializeField] private List<ItemCombinationData> _itemCombinations;
public List<ItemCombinationData> ItemCombinations { get => _itemCombinations; set => _itemCombinations = value; }
}
I Used UI Builder to Design the Visual Element
s and used code to bind the data.
ItemVisualElement:
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
public class ItemVisualElement : VisualElement
{
public new class UxmlFactory : UxmlFactory<ItemVisualElement> { }
public ItemVisualElement(){}
public VisualElement ImagePreview => this.Q<VisualElement>("ImagePreview");
public ObjectField ItemImageAsset => this.Q<ObjectField>("SpriteAsset");
public TextField ItemName => this.Q<TextField>("ItemName");
public IntegerField ItemID => this.Q<IntegerField>("ItemID");
public ItemVisualElement(VisualTreeAsset uxml, SerializedProperty spriteAssetProperty, SerializedProperty itemNameProperty, SerializedProperty itemIDProperty)
{
InitializeVisualElement(uxml, spriteAssetProperty, itemNameProperty, itemIDProperty);
}
public void InitializeVisualElement(VisualTreeAsset uxml, SerializedProperty spriteAssetProperty, SerializedProperty itemNameProperty, SerializedProperty itemIDProperty)
{
VisualTreeAsset asset = uxml;
asset.CloneTree(this);
ItemName.BindProperty(itemNameProperty);
ItemID.BindProperty(itemIDProperty);
ItemImageAsset.BindProperty(spriteAssetProperty);
ItemImageAsset.objectType = typeof(Sprite);
ItemImageAsset.RegisterValueChangedCallback((evt) =>
{
var itemImage = ItemImageAsset.value != null ? ((Sprite)ItemImageAsset.value) : null;
ImagePreview.style.backgroundImage = new StyleBackground(itemImage);
});
}
}
ItemCombinationVisualElement:
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
public class ItemCombinationVisualElement : VisualElement
{
public new class UxmlFactory : UxmlFactory<ItemCombinationVisualElement> { }
public ItemCombinationVisualElement() { }
public VisualElement ItemAPreview => this.Q<VisualElement>("ItemAPreview");
public VisualElement ItemBPreview => this.Q<VisualElement>("ItemBPreview");
public VisualElement ResultItemPreview => this.Q<VisualElement>("ResultItemPreview");
public ObjectField ItemAAsset => this.Q<ObjectField>("ItemA");
public ObjectField ItemBAsset => this.Q<ObjectField>("ItemB");
public ObjectField ItemCAsset => this.Q<ObjectField>("Result");
public ItemCombinationVisualElement(VisualTreeAsset uxml, SerializedProperty ItemAAssetProperty, SerializedProperty ItemBAssetProperty, SerializedProperty ItemCAssetProperty)
{
InitializeVisualElement(uxml, ItemAAssetProperty, ItemBAssetProperty, ItemCAssetProperty);
}
public void InitializeVisualElement(VisualTreeAsset uxml, SerializedProperty ItemAAssetProperty, SerializedProperty ItemBAssetProperty, SerializedProperty ItemCAssetProperty)
{
VisualTreeAsset asset = uxml;
asset.CloneTree(this);
ItemAAsset.BindProperty(ItemAAssetProperty);
ItemBAsset.BindProperty(ItemBAssetProperty);
ItemCAsset.BindProperty(ItemCAssetProperty);
ItemAAsset.objectType = typeof(ItemDataScriptableObject);
ItemBAsset.objectType = typeof(ItemDataScriptableObject);
ItemCAsset.objectType = typeof(ItemDataScriptableObject);
ItemAAsset.RegisterValueChangedCallback((evt) =>
{
var itemAImage = ItemAAsset.value != null ? ((ItemDataScriptableObject)ItemAAsset.value).ItemData.ItemImage : null;
ItemAPreview.style.backgroundImage = new StyleBackground(itemAImage);
});
ItemBAsset.RegisterValueChangedCallback((evt) =>
{
var itemBImage = ItemBAsset.value != null ? ((ItemDataScriptableObject)ItemBAsset.value).ItemData.ItemImage : null;
ItemBPreview.style.backgroundImage = new StyleBackground(itemBImage);
});
ItemCAsset.RegisterValueChangedCallback((evt) =>
{
var itemCImage = ItemCAsset.value != null ? ((ItemDataScriptableObject)ItemCAsset.value).ItemData.ItemImage : null;
ResultItemPreview.style.backgroundImage = new StyleBackground(itemCImage);
});
}
}
Images are attached as well…
The Image for all Items changes when I assign any item Scriptable Object
an Image.
The Item Combination List in the Item Combination Scriptable Object is also Removing all Images whenever I add a new Combination item to the List.
Here is the Code for The Custom Property Drawers:
Item Drawer:
using UnityEditor;
using UnityEngine.UIElements;
// ItemDrawerUIE
[CustomPropertyDrawer(typeof(ItemData))]
public class ItemDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
VisualTreeAsset uxml = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/GeneGame/Editor/Item/ItemLayout.uxml");
// Create property container element.
var container = new ItemVisualElement();
// Create property fields.
var itemImage = property.FindPropertyRelative("_itemImage");
var itemName = property.FindPropertyRelative("_itemName");
var itemID = property.FindPropertyRelative("_itemID");
container.InitializeVisualElement(uxml, itemImage, itemName, itemID);
return container;
}
}
Item Combination Drawer:
using UnityEditor;
using UnityEngine.UIElements;
// ItemCombinationDrawerUIE
[CustomPropertyDrawer(typeof(ItemCombinationData))]
public class ItemCombinationDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
VisualTreeAsset uxml = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/GeneGame/Editor/ItemCombination/ItemCombinationLayout.uxml");
// Create property container element.
var container = new ItemCombinationVisualElement();
// Create property fields.
var itemAField = property.FindPropertyRelative("_itemA");
var itemBField = property.FindPropertyRelative("_itemB");
var resultItemField = property.FindPropertyRelative("_result");
container.InitializeVisualElement(uxml, itemAField, itemBField, resultItemField);
return container;
}
}
I tried to keep this very simple.
I seem to be having trouble.
Any help would be appreciated.
UI toolkit seems cool but some of this is a bit frustrating.
The asset data changes for the scriptable objects I am viewing.