Will we be able to bind to arrays and Lists with custom elements?
If so, is there a time frame?
Will we be able to bind to arrays and Lists with custom elements?
If so, is there a time frame?
Hi!
This should already be possible. If you need this to be automatic, you can use property drawers for the targeted type. Otherwise you can define a BaseField, assign the bindingPath property and use them with a ListView.
Hope this helps!
Hi, this answer looks like what I’m also looking for but I’m not sure I know the basics well enough to act on it. Could you elaborate on how to use this, or point me in the direction of how to learn more about using BaseFields? Thanks in advance
Hey @maddogedge !
BaseField<T>
is a base class to create inspector-like controls. It implements INotifyValueChanged<T>
, which will make sure that the control has a value
property and it will handle sending the appropriate event when the value
changed… The base class also comes with a label
. BaseField<T>
also derives from BindableElement
, which makes the IBindable.bindingPath
available on it. More info on what the base class provides here.
When creating a custom editor/property drawer, you can use BaseField<T>
controls, such as IntegerField
, FloatField
, ColorField
, etc, to create the hierarchy you want. In some cases, the controls we offer will not be exactly what you want. When that happens, you can create a custom control. For example, if you have a color property and you want the users to only be able to choose between 3 different colors, you could create a custom control that derives from BaseField<Color>
. Since the BaseField<Color>
base class already has all the requirements for the editor binding system, it can then be used as a drop-in replacement for a ColorField
. You can find more info about creating a bindable custom control here.
Hope this helps!
Ok thanks!
So would BaseField<float[ ]> work ok?
I think I’ve managed to bind a float as a property field, but I’m struggling to get it working with Uxml****AttributeDescription calls in a custom BindableElement (as done for floats and a piechart here
)
If I just want to plot an array which is completely built in another cs script (hence no need for editable attributes) is there a simpler way to achieve this?
In general, is the approach of binding a float[ ] to an element and trying to plot it each update the recommended approach? I saw in another tutorial a stream may be a better approach perhaps?
This is my not-working code below, and it’s a bit of a cut-and-paste frankenstein from different tutorials. Can I salvage it?
Thanks for your help!
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class LineGraph2D : BindableElement, INotifyValueChanged<float[]>
{
public new class UxmlFactory : UxmlFactory<LineGraph2D, UxmlTraits> { }
public new class UxmlTraits : BindableElement.UxmlTraits
{
UxmlTypeAttributeDescription<float[]> m_Value = new UxmlTypeAttributeDescription<float[]> { name = "my-value" };
public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
{
base.Init(ve, bag, cc);
var line2D = ve as LineGraph2D;
// Unity Doesn't like this line below (can't assign a System.Type to float[])
//line2D.myValue = m_Value.GetValueFromBag(bag, cc);
}
}
VisualElement lineGraph;
float[] m_Value;
public float[] myValue { get; set; }
public float[] value { get; set; }
public void SetValueWithoutNotify(float[] newValue)
{
m_Value = newValue as float[];
lineGraph.MarkDirtyRepaint();
}
public LineGraph2D()
{
lineGraph = new VisualElement();
lineGraph.generateVisualContent += DrawArray;
Add(lineGraph);
}
void DrawArray(MeshGenerationContext ctx)
{
var painter = ctx.painter2D;
painter.strokeColor = Color.red;
painter.fillColor = Color.red;
painter.lineWidth = 1f;
painter.BeginPath();
for (int i = 0; i < m_Value.Length; i++)
// TODO change for array data (and scale etc)
painter.LineTo(new Vector2((float)i * 10f, 50f * m_Value[i]));
painter.Stroke();
}
}
From your code it looks like you’re trying to allow the user to set the plot data in UXML. At the moment I don’t believe there exist any array/list UXMLAttributeDescription types (UXMLTypeAttributeDescription
is for passing in type names, not arbitrary data types), so if you really want to allow this you would probably need to implement your own parsing solution to pull the data from a string.
If you just want other scripts to be able to pass in data to plot, though, you don’t need to mess around with the UXML stuff at all. In my own graph plotting project I just expose a public void SetData(IList<float> data, string name)
method. With the code you have above it looks like you could call SetValueWithoutNotify
from another script for the same effect.