HorizontalGroupとLabelTextを組み合わせると、左側の文字の幅が無視されて見えなくなってしまう
なるときとならないときがある
下はLowとHighと書いてますが、High部分が消えている例です。
この不具合はおそらくUnityのPropertyFieldクラスの挙動に起因するものであり、ライブラリ側から修正することはやや難しいと思われます。
対処法として、#34 で追加されたLabelWidth属性を使用してラベルの横幅を上書きすることが可能です。こちらを使用して適切な横幅を設定してみてください。
3回スケジュールすることで対応できました。
[CustomGroupDrawer(typeof(HorizontalGroupAttribute))]
public sealed class HorizontalGroupDrawer : AlchemyGroupDrawer
{
public override VisualElement CreateRootElement(string label)
{
var root = new VisualElement()
{
style =
{
width = Length.Percent(100f),
flexDirection = FlexDirection.Row
}
};
static void AdjustLabel(PropertyField element, VisualElement inspector, int childCount)
{
if (element.childCount == 0) return;
if (element.Q<Foldout>() != null) return;
var field = element[0];
field.RemoveFromClassList("unity-base-field__aligned");
var labelElement = field.Q<Label>();
if (labelElement != null)
{
labelElement.style.minWidth = 0f;
labelElement.style.width = GUIHelper.CalculateLabelWidth(element, inspector) * 0.8f / childCount;
}
}
var count = 2;
root.schedule.Execute(() =>
{
count--;
if (root.childCount <= 1) return;
var visualTree = root.panel.visualTree;
foreach (var field in root.Query<PropertyField>().Build())
{
AdjustLabel(field, visualTree, root.childCount);
}
foreach (var field in root.Query<GenericField>().Children<PropertyField>().Build())
{
AdjustLabel(field, visualTree, root.childCount);
}
}).Until(() => count <= 0);
return root;
}
}
[CustomAttributeDrawer(typeof(LabelWidthAttribute))]
public sealed class LabelWidthDrawer : AlchemyAttributeDrawer
{
public override void OnCreateElement()
{
var width = ((LabelWidthAttribute)Attribute).Width;
if (Element is AlchemyPropertyField field && field.FieldElement is PropertyField)
{
var executed = false;
field.schedule.Execute(() =>
{
var label = field.Q<Label>();
if (label == null) return;
if(label.style.minWidth.value == width&& label.style.width.value == width)
{
executed = true;
return;
}
GUIHelper.SetMinAndCurrentWidth(label, width);
}).Until(() => executed);
return;
}
Debug.LogWarning("The LabelWidth attribute currently only supports PropertyField and is ignored for other visual elements.");
}
}
PropertyFieldはBind時に内部のコンポーネントを構築するため、scheduleによる複数回の遅延実行は対処として不確実です。また、HorizontalGroup内で独自のレイアウト処理をスケジュールすることはかなり強引な処理であり、将来的に他の問題を引き起こす可能性があります。(現在のLabelWidthDrawerも同様の問題を抱えているため、適用対象を特定のPropertyFieldに限定しています。)
LabelWidthを設定してもAdd/RemoveComponent時に同様の問題が発生するので、Until(() => false)のようにするしかないかもしれないですね、、
PropertyFieldからLabelを取り出してしまう方法でもうまくいきました。
//AlchemyPropertyFieldに以下を追加し、widthをいじるときはこれを用いる。
Label labelElement;
public Label OverridenLabel
{
get
{
if (labelElement != null) return labelElement;
var label = element.Q<Label>();
if (label == null)
{
return null;
}
labelElement = new Label(label.text);
var labelStyle = labelElement.style;
labelStyle.marginTop = 3f;
labelStyle.marginBottom = 3f;
labelStyle.marginLeft = 3f;
labelStyle.marginRight = 3f;
label.RemoveFromHierarchy();
style.flexDirection = FlexDirection.Row;
Insert(0, labelElement);
element.style.flexGrow = 1;
return labelElement;
}
}
Unfortunatly, (though I haven't checked) I think that'd break properties that use the label as a handle. I've managed to stabilize things with this.
public override VisualElement CreateRootElement(string label)
{
var root = new VisualElement();
root.styleSheets.Add(_styleSheet);
root.AddToClassList("horizontal-group__main-element");
static void AdjustLabel(PropertyField element, VisualElement inspector, int childCount)
{
if (element.childCount == 0) return;
if (element.Q<Foldout>() != null) return;
var field = element[0];
field.RemoveFromClassList("unity-base-field__aligned");
var labelElement = field.Q<Label>();
if (labelElement != null && !labelElement.ClassListContains("horizontal-group__property-field__label"))
{
labelElement.AddToClassList("horizontal-group__property-field__label");
labelElement.RegisterCallback<GeometryChangedEvent>(_ =>
{
//I'd like to use stylesheets here, but it seems values are set inline somewhere.
//Therefore we too must inline, aggressively.
labelElement.style.minWidth = new Length(50, LengthUnit.Percent);
labelElement.style.maxWidth = new Length(50, LengthUnit.Percent);
labelElement.style.width = GUIHelper.CalculateLabelWidth(element, inspector) * 0.8f / childCount;
});
}
}
root.RegisterCallback<GeometryChangedEvent>(_ =>
{
if (root.childCount <= 1) return;
var visualTree = root.panel.visualTree;
foreach (var field in root.Query<PropertyField>().Build())
{
AdjustLabel(field, visualTree, root.childCount);
}
foreach (var field in root.Query<GenericField>().Children<PropertyField>().Build())
{
AdjustLabel(field, visualTree, root.childCount);
}
});
return root;
}
Though its quite heavy handed. I'm gonna keep on trying.