Skip to content
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

HorizontalGroupとLabelTextを組み合わせると、左側の文字の幅が無視されて見えなくなってしまう #11

Open
KurisuJuha opened this issue Dec 12, 2023 · 6 comments

Comments

@KurisuJuha
Copy link

なるときとならないときがある
下はLowとHighと書いてますが、High部分が消えている例です。
image

@AnnulusGames
Copy link
Owner

AnnulusGames commented Feb 17, 2024

この不具合はおそらくUnityのPropertyFieldクラスの挙動に起因するものであり、ライブラリ側から修正することはやや難しいと思われます。
対処法として、#34 で追加されたLabelWidth属性を使用してラベルの横幅を上書きすることが可能です。こちらを使用して適切な横幅を設定してみてください。

@Akeit0
Copy link
Contributor

Akeit0 commented Feb 17, 2024

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.");
    }
}

@AnnulusGames
Copy link
Owner

PropertyFieldはBind時に内部のコンポーネントを構築するため、scheduleによる複数回の遅延実行は対処として不確実です。また、HorizontalGroup内で独自のレイアウト処理をスケジュールすることはかなり強引な処理であり、将来的に他の問題を引き起こす可能性があります。(現在のLabelWidthDrawerも同様の問題を抱えているため、適用対象を特定のPropertyFieldに限定しています。)

@Akeit0
Copy link
Contributor

Akeit0 commented Feb 18, 2024

LabelWidthを設定してもAdd/RemoveComponent時に同様の問題が発生するので、Until(() => false)のようにするしかないかもしれないですね、、

@Akeit0
Copy link
Contributor

Akeit0 commented Feb 18, 2024

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;
    }
}

@Level6Rogue
Copy link

Level6Rogue commented Aug 14, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants