検索機能付きポップアップウィンドウ(Editor拡張)
以前作成したポップアップウィンドウ(ポップアップウィンドウの作成)に検索機能を追加しました。
Script
ポップアップウィンドウ
作成したScriptは以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
public class PopUpInfo { public static PopUpInfo instance = null; private int id; private int m_selected; public PopUpInfo(int control_id) { id = control_id; } public static int GetSelectedValue(int control_id, int selected) { if (instance == null) { return selected; } if (instance.id == control_id) { selected = instance.m_selected; } return selected; } public void SetSelectedValue(int selected) { m_selected = selected; } } public class EditorPopUpSearchWindow : PopupWindowContent { public static bool on_close = false; private string[] m_button_names; private bool[] m_hidden_flags; private int m_selected; private Rect m_rect_window; private PopUpInfo m_instance; private EditorWindow m_editorWindow; private GUIStyle m_style_label, m_style_search; private Texture2D tex_background; private Color m_color_backgraound = new Color(0.2f, 0.2f, 0.2f, 1.0f); private bool set_color = false; private string search_term; private Vector2 scroll_pos = Vector2.zero; //背景色変更なし public EditorPopUpSearchWindow(Rect rect_window, int selected, string[] button_names, GUIStyle style_popup_label, GUIStyle style_search_window, PopUpInfo instance, EditorWindow editorWindow) { m_button_names = button_names; m_selected = selected; m_rect_window = rect_window; m_instance = instance; m_style_label = style_popup_label; m_style_search = style_search_window; set_color = false; m_editorWindow = editorWindow; m_hidden_flags = new bool[m_button_names.Length]; for(int i = 0; i < m_hidden_flags.Length; i++) { m_hidden_flags[i] = false; } } //背景色変更あり public EditorPopUpSearchWindow(Rect rect_window, int selected, string[] button_names, GUIStyle style_popup_label, GUIStyle style_search_window, Color color_background, PopUpInfo instance, EditorWindow editorWindow) { m_button_names = button_names; m_selected = selected; m_rect_window = rect_window; m_instance = instance; m_style_label = style_popup_label; m_style_search = style_search_window; m_color_backgraound = color_background; set_color = true; m_editorWindow = editorWindow; m_hidden_flags = new bool[m_button_names.Length]; for (int i = 0; i < m_hidden_flags.Length; i++) { m_hidden_flags[i] = false; } } //背景色を変更する public static int Create(Vector2 window_size, string label, int selected, string[] button_names, GUIStyle style_label, GUIStyle style_button, GUIStyle style_popup, GUIStyle style_search_window, Color color_background, PopUpPosition popup_position, EditorWindow editorWindow) { selected = EditorPopUpSearchWindow.PopUp(window_size, label, selected, button_names, style_label, style_button, style_popup, style_search_window, color_background, popup_position, editorWindow); return selected; } //背景色を変更しない public static int Create(Vector2 window_size, string label, int selected, string[] button_names, GUIStyle style_label, GUIStyle style_button, GUIStyle style_popup, GUIStyle style_search_window, PopUpPosition popup_position, EditorWindow editorWindow) { selected = EditorPopUpSearchWindow.PopUp(window_size, label, selected, button_names, style_label, style_button, style_popup, style_search_window, Color.clear, popup_position, editorWindow); return selected; } static int PopUp(Vector2 window_size, string label, int selected, string[] button_names, GUIStyle style_label, GUIStyle style_button, GUIStyle style_popup, GUIStyle style_search_window, Color color_background, PopUpPosition popup_position, EditorWindow editorWindow) { int control_id = GUIUtility.GetControlID(FocusType.Passive); selected = PopUpInfo.GetSelectedValue(control_id, selected); Rect rect_control = GUILayoutUtility.GetRect(GUIContent.none, style_button); int margin = 3; int button_width = 85; int label_width = (int)rect_control.width - button_width - margin; Rect rect_label = new Rect(rect_control) { width = label_width }; Rect rect_button = new Rect(rect_control) { x = rect_control.x + label_width + margin, width = button_width }; Event event_current = Event.current; Vector2 mouse_pos = event_current.mousePosition; int label_id = GUIUtility.GetControlID(FocusType.Keyboard); int button_id = GUIUtility.GetControlID(FocusType.Passive); bool focus_button = false; bool on_button = false; bool on_click = false; if (event_current.button == 0) { switch (event_current.type) { case EventType.MouseDown: if (rect_label.Contains(mouse_pos)) { GUIUtility.keyboardControl = label_id; event_current.Use(); } else if (rect_button.Contains(mouse_pos)) { GUIUtility.keyboardControl = button_id; on_click = true; event_current.Use(); } break; } } //popupが閉じたとき if (EditorPopUpSearchWindow.on_close) { GUIUtility.keyboardControl = label_id; EditorPopUpSearchWindow.on_close = false; } if (GUIUtility.keyboardControl == label_id) focus_button = true; if (GUIUtility.keyboardControl == button_id) on_button = true; if (Event.current.type == EventType.Repaint) { style_label.Draw(rect_label, new GUIContent(label), false, false, false, focus_button || on_button); style_button.Draw(rect_button, new GUIContent(button_names[selected]), false, false, on_button, focus_button); } //ボタンがクリックされた時の処理 if (on_click) { GUIStyle style_radio = new GUIStyle(EditorStyles.radioButton); int size = button_names.Length; int window_width = (int)window_size.x; int window_height; int search_field_height = (int)style_search_window.fixedHeight; if (search_field_height <= 0) search_field_height = 18; search_field_height += style_search_window.margin.top + style_search_window.margin.bottom; int radio_button_height = (int)style_radio.fixedHeight; if (radio_button_height <= 0) radio_button_height = 19; radio_button_height *= size; radio_button_height += style_radio.margin.top + style_radio.margin.bottom * size; int bottom_margin = 2; //各要素の高さやmarginから計算した高さをwindowの高さとするとScrollBarが表示される。少し大きくすることで回避。 window_height = search_field_height + radio_button_height + bottom_margin; if (window_height > window_size.y) window_height = (int)window_size.y; //要素の高さより指定されたwindowの高さが大きい場合は、windowの高さを要素の高さに合わせる int window_x; int window_y = (int)rect_button.y + (int)rect_button.height - window_height; switch (popup_position) { case PopUpPosition.Left: window_x = (int)rect_button.x; break; case PopUpPosition.Center: window_x = (int)rect_button.x - (window_width - button_width) / 2; break; case PopUpPosition.Right: window_x = (int)rect_button.x - (window_width - button_width); break; default: window_x = (int)rect_button.x; break; } PopUpInfo.instance = new PopUpInfo(control_id); PopUpInfo.instance.SetSelectedValue(selected); Rect rect_window = new Rect(window_x, window_y, window_width, window_height); if (color_background != Color.clear) { var popup_content = new EditorPopUpSearchWindow(rect_window, selected, button_names, style_popup, style_search_window, color_background, PopUpInfo.instance, editorWindow); PopupWindow.Show(rect_window, popup_content); } else { var popup_content = new EditorPopUpSearchWindow(rect_window, selected, button_names, style_popup, style_search_window, PopUpInfo.instance, editorWindow); PopupWindow.Show(rect_window, popup_content); } } return selected; } public override Vector2 GetWindowSize() { return new Vector2(m_rect_window.width, m_rect_window.height); } public override void OnOpen() { if (set_color) { tex_background = new Texture2D(1, 1, TextureFormat.RGB24, false); tex_background.SetPixel(0, 0, m_color_backgraound); tex_background.Apply(); } } public override void OnGUI(Rect rect) { if (set_color) GUI.DrawTexture(new Rect(0, 0, m_rect_window.width, m_rect_window.height), tex_background, ScaleMode.StretchToFill); int name_length = m_button_names.Length; if (name_length == 0) return; EditorGUI.BeginChangeCheck(); search_term = EditorGUILayout.TextField(search_term, m_style_search); if (EditorGUI.EndChangeCheck()) { if(search_term != "") { for (int i = 0; i < name_length; i++) { m_hidden_flags[i] = true; //大文字小文字の区別をなくす string lower_name = m_button_names[i].ToLower(); int n = lower_name.IndexOf(search_term.ToLower()); //先頭から一致 //if (n == 0) //{ // m_hidden_flags[i] = false; //} //どこかしら一致 if (n != -1) { m_hidden_flags[i] = false; } } } else { for (int i = 0; i < name_length; i++) { m_hidden_flags[i] = false; } } } GUIStyle style_radio = new GUIStyle(EditorStyles.radioButton); scroll_pos = EditorGUILayout.BeginScrollView(scroll_pos); int selected = CustomEditorGUI.RadioButton(m_button_names, m_selected, m_hidden_flags, m_style_label, style_radio); EditorGUILayout.EndScrollView(); if (m_selected != selected) { m_editorWindow.Repaint(); m_selected = selected; } if (m_instance != null) { PopUpInfo.instance.SetSelectedValue(m_selected); } } public override void OnClose() { on_close = true; PopUpInfo.instance = null; m_editorWindow.Repaint(); } } |
検索を行うためのキーワードを入力するためのTextFieldを追加しています。EditorGUI.BeginChangeCheck()により、TextFieldの内容が変更された時のみ検索が実行されるようにしています。
1 2 3 |
EditorGUI.BeginChangeCheck(); search_term = EditorGUILayout.TextField(search_term, m_style_search); |
始めにEditorGUI.EndChangeCheck()により、TextFiledの内容が変更された時に実行されるようにしています。
1 2 3 4 |
if (EditorGUI.EndChangeCheck()) { ・・・ } |
次に、search_term != “”によりTextFieldに文字が入力されたか否かを判別します。文字列が入力されていない場合はm_hidden_flagsを全てfalseにすることで、ラジオボタンを全て表示するようにしています。
1 2 3 4 5 6 7 8 9 |
if(search_term != "") { ・・・ } else { for (int i = 0; i < name_length; i++) { m_hidden_flags[i] = false; } } |
文字が入力された場合の処理です。各ラジオボタンのラベル(m_button_names)と検索用キーワード(search_term)をそれぞれ、string.ToLower()により全て小文字にしています。これにより、大文字と小文字を区別することなく検索を行うことができます。
1 2 3 |
string lower_name = m_button_names[i].ToLower(); int n = lower_name.IndexOf(search_term.ToLower()); |
string.IndexOf()により、キーワードがラジオボタンのラベルに一致するか否かを判定します。string.IndexOf()は一致する部分がなければ-1を、一致する部分があればその位置を返します。よって、n != -1の場合にm_hidden_flags[i] = falseとし、ラジオボタンを表示するようにすれば、キーワードと一致したラジオボタンのみを表示できます。また、n == 0とすれば、キーワードがラベルの先頭から一致した場合のみ表示するようにできます。
1 2 3 4 5 6 7 8 9 10 11 |
//先頭から一致 //if (n == 0) //{ // m_hidden_flags[i] = false; //} //どこかしら一致 if (n != -1) { m_hidden_flags[i] = false; } |
ラジオボタン
以前作成したラジオボタンへ表示、非表示の機能を追加したラジオボタンのScriptです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
public class CustomEditorGUI { public static int RadioButton(string[] labels, int selected, bool[] hidden_flags, GUIStyle style_label, GUIStyle style_radio) { Event event_current = Event.current; Vector2 mouse_pos = event_current.mousePosition; int length = labels.Length; int margin = 3; int button_size = style_radio.normal.background.width; for (int i = 0; i < length; i++) { if (hidden_flags[i] == true) continue; int control_id = GUIUtility.GetControlID(FocusType.Keyboard); Rect rect_control = GUILayoutUtility.GetRect(GUIContent.none, style_radio); Rect rect_button = new Rect(rect_control) { width = button_size }; Rect rect_label = new Rect(rect_control) { x = rect_button.width + margin, width = rect_control.width - rect_button.width - margin }; EditorGUI.PrefixLabel(rect_label, control_id, new GUIContent(labels[i]), style_label); //radio button bool is_on = false; if (event_current.type == EventType.Repaint) { if (i == selected) { is_on = true; } style_radio.Draw(rect_button, GUIContent.none, control_id, is_on); } if (event_current.type == EventType.MouseDown) { if (rect_control.Contains(mouse_pos)) { selected = i; GUIUtility.keyboardControl = control_id; HandleUtility.Repaint(); } } } return selected; } } |
表示するか非表示にするかをhidden_flagsによって受け取ります。そして、非表示とすることを指定されていた場合(true)、continueによりfor文の処理を飛ばすことで非表示にしています。
1 |
if (hidden_flags[i] == true) continue; |
実行結果
以上のScriptを実行した結果は以下の通りです。キーワードによりラジオボタンの表示、非表示ができていることが分かります。
-
前の記事
MaterialのShaderプロパティーを表示 その2(Editor拡張) 2020.10.22
-
次の記事
ObjectFieldの作成(Editor拡張) 2020.11.23
コメントを書く