ゼニガネブログ

ゲーム開発のための小ネタなど。現在はUnityメインでやってます

【Unity】エディタ拡張のGUILayout.TextAreaにCtrl+Cによるコピー機能を無理やり実装する

f:id:zenigane138:20191112231232g:plain

何かしらの都合で、EditorGUILayout.TextAreaを使わずにGUILayout.TextAreaを使っている方への情報になります。

ソースコード

ポイント

Event.current.controlとEvent.current.keyCodeを使って複数キーの判定。
EventType.KeyDownは(Unity側に入力が持っていかれて?)if条件を満たさなくなるのでEventType.KeyUpを使ってごまかす。
GUIUtility.keyboardControlでキーボードのフォーカスが当たっているオブジェクトの制御IDを取得。
GUIUtility.GetStateObject()に制御IDとTypeを指定しオブジェクトにして取得。

おまけ

GetStateObject()とQueryStateObject()ってのがあるんだけどどっち使えばいいの?

GUIUtility-GetStateObject - Unity スクリプトリファレンス

GUIUtility-QueryStateObject - Unity スクリプトリファレンス

ドキュメントにある「state object」が何を指すのかがドキュメントを読んだ限りではわからなかったのですが、エディタ上ではとりあえずGetStateObject()で問題なさそうです。
GetStateObject()で「state object」なるものが生成され、以降はQueryStateObject()で取得するのがベストのようですが、毎回GetStateObject()で取得でもエディタ上では特に問題はなさそうでした。
「state object」が未生成の状態でQueryStateObject()を呼ぶとnullが返ってくる場合がありますが、nullの保証はなく例外が発生する場合もあるとの事です。

実機での検証が不十分で確実に安全かどうかはまだ把握出来ていないのでエディタ以外で使用する場合はご注意下さい。


実際に私の環境ではnullは返らず下記の例外がスローされました。
KeyNotFoundException: The given key was not present in the dictionary.
System.Collections.Generic.Dictionary`2[System.Int32,System.Object].get_Item (Int32 key) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:150)
UnityEngine.GUIStateObjects.QueryStateObject (System.Type t, Int32 controlID) (at C:/buildslave/unity/build/Runtime/Export/GUIStateObjects.cs:26)
UnityEngine.GUIUtility.QueryStateObject (System.Type t, Int32 controlID) (at C:/buildslave/unity/build/Runtime/IMGUI/Managed/GUIUtility.cs:102)