3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Unity】App UIの入門としてDrag and Dropのサンプルコードを読む【App UI】

Posted at

自己紹介

とある事情で様々な方とお会いしてUnityモチベーションえぐい大学生。
これについても許可が出れば記事にします!

本記事の趣旨

App UIに入門するにあたって、サンプルコードを読もうと思ったので、ついでに記事を書く。
全体の概要を掴みつつ、少し機能に触れていこうと思う。

もととなるUI Toolkitに関しては触れないこととする。

App UIとは

突如として界隈でちょこっと有名になったUI Toolkitベースの公式UIフレームワーク。
ランタイム・エディター拡張ともに対応しており、テーマも複数あるなど今までのUnityとは思えない雰囲気。

Drag and Dropとは

App UIのサンプルプロジェクトの1つ
image.png
このような見た目でItem0を除いて全ての要素がドラッグアンドドロップできるUIを実現している。

サンプルコードを読む

始める前に少し言わせてほしい。なぜDragAndDropSampleScriptStartメソッドはコンストラクタではいけないのだ…

GridView

まず最初に、目につくのがGridViewというVisual Elementだろう。
これは「項目リスト」「表示項目の見た目を制御するメソッド」「実際の値を入れるメソッド」の3つを持つ。

今回のサンプルでは

今回のサンプルでは以下のような関数が使用されていた。

サンプルの「表示項目の見た目を制御するメソッド」
    static VisualElement MakeItem()
    {
        Debug.Log("Make");
        var item = new VisualElement();
        item.AddToClassList("dnd-item");
        var text = new Text();
        text.AddToClassList("dnd-item__label");
        item.Add(text);
        return item;
    }
サンプルの「実際の値を入れるメソッド」
    void BindSrcItem(VisualElement el, int idx)
    {
        Debug.Log("Bind");
        var item = (Text)el.ElementAt(0);
        item.text = (string)m_SrcList.itemsSource[idx];
    }

その他の機能

ドラッグの検知や複数個同時選択などの機能があるようだ。
ドラッグに関してはdragCanceledというイベントがあったがどうあがいても実行されなかった。

気になったところ

ドラッグアンドドロップするたびに全てのVisual Elementが再描画され上記2つのメソッドも呼び出されていた。
私もUI Toolkitがそこまで詳しくないためどこの仕様なのか分からないが、ちょっと気になった。

また、ドラッグアンドドロップで移動したのち選択が残るという挙動に違和感を覚えた。

DropZone

こちらはDropする挙動を設定できるVisualElementのようだ。
Dropされようなとき(dragStarted)Dropされたとき(dropped)Dropされた後処理(dragEnded)がある。

今回のサンプルでは

Dropされたときのイベント
    void OnDropped(IEnumerable<object> objects)
    {
        var selection = objects.Where(o => o is string).Cast<string>().ToList();
        
        if (selection.Count == 0)
            return;
        
        // Add dropped items to the destination list
        var dstItems = new List<string>(m_DstList.itemsSource?.Cast<string>() ?? Enumerable.Empty<string>());
        dstItems.AddRange(selection);
        m_DstList.itemsSource = dstItems;
        
        // Remove dropped items from the source list
        var srcItems = new List<string>(m_SrcList.itemsSource?.Cast<string>() ?? Enumerable.Empty<string>());
        foreach (var item in selection)
        {
            srcItems.Remove(item);
        }
        m_SrcList.itemsSource = srcItems;
        
        // Hide the dropzone if the destination list is not empty
        m_Dropzone.visibleIndicator = m_DstList.itemsSource != null || m_DstList.itemsSource.Count == 0;
    }
DropZoneの上に要素が来た時(=Dropされそうなとき)のイベント
    void OnEditorDragStarted()
    {
        // Accept every path from the editor
        m_Dropzone.visibleIndicator = true;
        m_Dropzone.state = DropZoneState.AcceptDrag;
    }
Dropされた後処理(このメソッドはイベント専用ではなくほかにも呼び出されてる)
    void Reset()
    {
        m_Dropzone.state = DropZoneState.Default;
        m_Dropzone.visibleIndicator = m_DstList.itemsSource == null || m_DstList.itemsSource.Count == 0;
        SetDraggedObjects(null);
    }

さいごに

App UIなんもわからんという状態からこの記事を書いているので全然深く掘れなかったのですが、なんでこんな書き方してるんだろうと思うとこともちらほらあったり。
もうちょっと洗練されたコードも書けそうな気がしたので、今後機会があればまた記事にしたいと思います。

今回はDropZoneがあるということが既に結構大きい発見でした。
App UIの開発はイベントを登録していく形でとてもWeb風だなと、流石UI Toolkitや!!

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?