UnityExplorer/src/UI/Modules/SearchPage.cs
2020-12-14 19:26:59 +11:00

854 lines
31 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
//using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityExplorer.Helpers;
using UnityExplorer.Inspectors;
using UnityExplorer.UI.Shared;
using UnityExplorer.Unstrip;
using System.Reflection;
#if CPP
using UnhollowerRuntimeLib;
#endif
namespace UnityExplorer.UI.Modules
{
internal enum SearchContext
{
UnityObject,
GameObject,
Component,
Custom,
Singleton,
StaticClass
}
internal enum SceneFilter
{
Any,
Asset,
DontDestroyOnLoad,
Explicit,
}
internal enum ChildFilter
{
Any,
RootObject,
HasParent
}
public class SearchPage : MainMenu.Page
{
public override string Name => "Search";
public static SearchPage Instance;
internal SearchContext m_context;
private SceneFilter m_sceneFilter;
private ChildFilter m_childFilter;
internal bool m_isStaticClassSearching;
// ui elements
private Text m_resultCountText;
private InputField m_customTypeInput;
private InputField m_nameInput;
private Button m_selectedContextButton;
private readonly Dictionary<SearchContext, Button> m_contextButtons = new Dictionary<SearchContext, Button>();
private Dropdown m_sceneDropdown;
private int m_lastSceneCount = -1;
private GameObject m_extraFilterRow;
// Results
internal object[] m_results;
internal readonly List<object> m_resultShortList = new List<object>();
private int m_lastCount;
public PageHandler m_resultListPageHandler;
private GameObject m_resultListContent;
private readonly List<Text> m_resultListTexts = new List<Text>();
public SearchPage()
{
Instance = this;
}
public override void Init()
{
ConstructUI();
}
public void OnSceneChange()
{
m_results = new object[0];
RefreshResultList();
}
public override void Update()
{
if (HaveScenesChanged())
{
RefreshSceneDropdown();
}
if (m_customTypeInput.isFocused && m_context != SearchContext.Custom)
{
OnContextButtonClicked(SearchContext.Custom);
}
}
// Updating result list content
private void RefreshResultList()
{
m_resultListPageHandler.ListCount = m_results.Length;
int newCount = 0;
foreach (var itemIndex in m_resultListPageHandler)
{
newCount++;
// normalized index starting from 0
var i = itemIndex - m_resultListPageHandler.StartIndex;
if (itemIndex >= m_results.Length)
{
if (i > m_lastCount || i >= m_resultListTexts.Count)
break;
GameObject label = m_resultListTexts[i].transform.parent.parent.gameObject;
if (label.activeSelf)
label.SetActive(false);
}
else
{
var obj = m_results[itemIndex];
var unityObj = obj as UnityEngine.Object;
if (obj == null || (unityObj != null && !unityObj))
continue;
if (i >= m_resultShortList.Count)
{
m_resultShortList.Add(obj);
AddResultButton();
}
else
{
m_resultShortList[i] = obj;
}
var text = m_resultListTexts[i];
if (m_context != SearchContext.StaticClass)
{
var name = UISyntaxHighlight.ParseFullSyntax(obj.GetActualType(), true);
if (unityObj && m_context != SearchContext.Singleton && m_context != SearchContext.StaticClass)
{
if (unityObj && !string.IsNullOrEmpty(unityObj.name))
name += $": {unityObj.name}";
else
name += ": <i><color=grey>untitled</color></i>";
}
text.text = name;
}
else
{
var type = obj as Type;
text.text = UISyntaxHighlight.ParseFullSyntax(type, true);
}
var label = text.transform.parent.parent.gameObject;
if (!label.activeSelf)
label.SetActive(true);
}
}
m_lastCount = newCount;
}
// scene dropdown update
internal bool HaveScenesChanged()
{
if (m_lastSceneCount != SceneManager.sceneCount)
return true;
for (int i = 0; i < SceneManager.sceneCount; i++)
{
int dropdownIndex = i + 3;
if (dropdownIndex >= m_sceneDropdown.options.Count
|| m_sceneDropdown.options[dropdownIndex].text != SceneManager.GetSceneAt(i).name)
return true;
}
return false;
}
internal void RefreshSceneDropdown()
{
m_sceneDropdown.OnCancel(null);
m_sceneDropdown.options.Clear();
m_sceneDropdown.options.Add(new Dropdown.OptionData
{
text = "Any"
});
m_sceneDropdown.options.Add(new Dropdown.OptionData
{
text = "None (Asset / Resource)"
});
m_sceneDropdown.options.Add(new Dropdown.OptionData
{
text = "DontDestroyOnLoad"
});
m_lastSceneCount = 0;
for (int i = 0; i < SceneManager.sceneCount; i++)
{
m_lastSceneCount++;
var scene = SceneManager.GetSceneAt(i).name;
m_sceneDropdown.options.Add(new Dropdown.OptionData
{
text = scene
});
}
m_sceneDropdown.transform.Find("Label").GetComponent<Text>().text = "Any";
}
// ~~~~~ UI Callbacks ~~~~~
internal void OnSearchClicked()
{
m_resultListPageHandler.CurrentPage = 0;
if (m_context == SearchContext.StaticClass)
StaticClassSearch();
else if (m_context == SearchContext.Singleton)
SingletonSearch();
else
UnityObjectSearch();
RefreshResultList();
if (m_results.Length > 0)
m_resultCountText.text = $"{m_results.Length} Results";
else
m_resultCountText.text = "No results...";
}
internal void StaticClassSearch()
{
m_isStaticClassSearching = true;
var list = new List<Type>();
var nameFilter = "";
if (!string.IsNullOrEmpty(m_nameInput.text))
nameFilter = m_nameInput.text.ToLower();
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in asm.TryGetTypes().Where(it => it.IsSealed && it.IsAbstract))
{
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ToLower().Contains(nameFilter))
continue;
list.Add(type);
}
}
m_results = list.ToArray();
}
internal string[] s_instanceNames = new string[]
{
"m_instance",
"m_Instance",
"s_instance",
"s_Instance",
"_instance",
"_Instance",
"instance",
"Instance",
"<Instance>k__BackingField",
"<instance>k__BackingField",
};
private void SingletonSearch()
{
m_isStaticClassSearching = false;
var instances = new List<object>();
var nameFilter = "";
if (!string.IsNullOrEmpty(m_nameInput.text))
nameFilter = m_nameInput.text.ToLower();
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
// All non-static classes
foreach (var type in asm.TryGetTypes().Where(it => !it.IsSealed && !it.IsAbstract))
{
try
{
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ToLower().Contains(nameFilter))
continue;
#if CPP
// Only look for Properties in IL2CPP, not for Mono.
PropertyInfo pi;
foreach (var name in s_instanceNames)
{
pi = type.GetProperty(name, flags);
if (pi != null)
{
var instance = pi.GetValue(null, null);
if (instance != null)
{
instances.Add(instance);
continue;
}
}
}
#endif
// Look for a typical Instance backing field.
FieldInfo fi;
foreach (var name in s_instanceNames)
{
fi = type.GetField(name, flags);
if (fi != null)
{
var instance = fi.GetValue(null);
if (instance != null)
{
instances.Add(instance);
continue;
}
}
}
}
catch { }
}
}
m_results = instances.ToArray();
}
internal void UnityObjectSearch()
{
m_isStaticClassSearching = false;
Type searchType = null;
switch (m_context)
{
case SearchContext.GameObject:
searchType = typeof(GameObject); break;
case SearchContext.Component:
searchType = typeof(Component); break;
case SearchContext.Custom:
if (string.IsNullOrEmpty(m_customTypeInput.text))
{
ExplorerCore.LogWarning("Custom Type input must not be empty!");
return;
}
if (ReflectionHelpers.GetTypeByName(m_customTypeInput.text) is Type customType)
if (typeof(UnityEngine.Object).IsAssignableFrom(customType))
searchType = customType;
else
ExplorerCore.LogWarning($"Custom type '{customType.FullName}' is not assignable from UnityEngine.Object!");
else
ExplorerCore.LogWarning($"Could not find a type by the name '{m_customTypeInput.text}'!");
break;
default:
searchType = typeof(UnityEngine.Object); break;
}
if (searchType == null)
return;
var allObjects = ResourcesUnstrip.FindObjectsOfTypeAll(searchType);
var results = new List<object>();
// perform filter comparers
string nameFilter = null;
if (!string.IsNullOrEmpty(m_nameInput.text))
nameFilter = m_nameInput.text.ToLower();
bool canGetGameObject = (m_sceneFilter != SceneFilter.Any || m_childFilter != ChildFilter.Any)
&& (m_context == SearchContext.GameObject || typeof(Component).IsAssignableFrom(searchType));
string sceneFilter = null;
if (!canGetGameObject)
{
if (m_context != SearchContext.UnityObject && (m_sceneFilter != SceneFilter.Any || m_childFilter != ChildFilter.Any))
ExplorerCore.LogWarning($"Type '{searchType}' cannot have Scene or Child filters applied to it");
}
else
{
if (m_sceneFilter == SceneFilter.DontDestroyOnLoad)
sceneFilter = "DontDestroyOnLoad";
else if (m_sceneFilter == SceneFilter.Explicit)
sceneFilter = m_sceneDropdown.options[m_sceneDropdown.value].text;
}
foreach (var obj in allObjects)
{
// name check
if (!string.IsNullOrEmpty(nameFilter) && !obj.name.ToLower().Contains(nameFilter))
continue;
if (canGetGameObject)
{
#if MONO
var go = m_context == SearchContext.GameObject
? obj as GameObject
: (obj as Component).gameObject;
#else
var go = m_context == SearchContext.GameObject
? obj.TryCast<GameObject>()
: obj.TryCast<Component>().gameObject;
#endif
// scene check
if (m_sceneFilter != SceneFilter.Any)
{
if (!go)
continue;
switch (m_context)
{
case SearchContext.GameObject:
if (go.scene.name != sceneFilter)
continue;
break;
case SearchContext.Custom:
case SearchContext.Component:
if (go.scene.name != sceneFilter)
continue;
break;
}
}
if (m_childFilter != ChildFilter.Any)
{
if (!go)
continue;
// root object check (no parent)
if (m_childFilter == ChildFilter.HasParent && !go.transform.parent)
continue;
else if (m_childFilter == ChildFilter.RootObject && go.transform.parent)
continue;
}
}
results.Add(obj);
}
m_results = results.ToArray();
}
private void OnResultPageTurn()
{
RefreshResultList();
}
internal void OnResultClicked(int index)
{
if (m_context == SearchContext.StaticClass)
InspectorManager.Instance.Inspect((Type)m_resultShortList[index]);
else
InspectorManager.Instance.Inspect(m_resultShortList[index]);
}
internal void OnContextButtonClicked(SearchContext context)
{
if (m_selectedContextButton && m_context == context)
return;
if (m_selectedContextButton)
UIFactory.SetDefaultColorTransitionValues(m_selectedContextButton);
var button = m_contextButtons[context];
m_selectedContextButton = button;
var colors = m_selectedContextButton.colors;
colors.normalColor = new Color(0.35f, 0.7f, 0.35f);
colors.highlightedColor = colors.normalColor;
m_selectedContextButton.colors = colors;
m_context = context;
// if extra filters are valid
if (context == SearchContext.Component
|| context == SearchContext.GameObject
|| context == SearchContext.Custom)
{
m_extraFilterRow?.SetActive(true);
}
else
{
m_extraFilterRow?.SetActive(false);
}
}
#region UI CONSTRUCTION
internal void ConstructUI()
{
GameObject parent = MainMenu.Instance.PageViewport;
Content = UIFactory.CreateVerticalGroup(parent);
var mainGroup = Content.GetComponent<VerticalLayoutGroup>();
mainGroup.padding.left = 4;
mainGroup.padding.right = 4;
mainGroup.padding.top = 4;
mainGroup.padding.bottom = 4;
mainGroup.spacing = 5;
mainGroup.childForceExpandHeight = true;
mainGroup.childForceExpandWidth = true;
mainGroup.childControlHeight = true;
mainGroup.childControlWidth = true;
ConstructTopArea();
ConstructResultsArea();
}
internal void ConstructTopArea()
{
var topAreaObj = UIFactory.CreateVerticalGroup(Content, new Color(0.15f, 0.15f, 0.15f));
var topGroup = topAreaObj.GetComponent<VerticalLayoutGroup>();
topGroup.childForceExpandHeight = false;
topGroup.childControlHeight = true;
topGroup.childForceExpandWidth = true;
topGroup.childControlWidth = true;
topGroup.padding.top = 5;
topGroup.padding.left = 5;
topGroup.padding.right = 5;
topGroup.padding.bottom = 5;
topGroup.spacing = 5;
GameObject titleObj = UIFactory.CreateLabel(topAreaObj, TextAnchor.UpperLeft);
Text titleLabel = titleObj.GetComponent<Text>();
titleLabel.text = "Search";
titleLabel.fontSize = 20;
LayoutElement titleLayout = titleObj.AddComponent<LayoutElement>();
titleLayout.minHeight = 30;
titleLayout.flexibleHeight = 0;
// top area options
var optionsGroupObj = UIFactory.CreateVerticalGroup(topAreaObj, new Color(0.1f, 0.1f, 0.1f));
var optionsGroup = optionsGroupObj.GetComponent<VerticalLayoutGroup>();
optionsGroup.childForceExpandHeight = false;
optionsGroup.childControlHeight = true;
optionsGroup.childForceExpandWidth = true;
optionsGroup.childControlWidth = true;
optionsGroup.spacing = 10;
optionsGroup.padding.top = 4;
optionsGroup.padding.right = 4;
optionsGroup.padding.left = 4;
optionsGroup.padding.bottom = 4;
var optionsLayout = optionsGroupObj.AddComponent<LayoutElement>();
optionsLayout.minWidth = 500;
optionsLayout.minHeight = 70;
optionsLayout.flexibleHeight = 100;
// search context row
var contextRowObj = UIFactory.CreateHorizontalGroup(optionsGroupObj, new Color(1, 1, 1, 0));
var contextGroup = contextRowObj.GetComponent<HorizontalLayoutGroup>();
contextGroup.childForceExpandWidth = false;
contextGroup.childControlWidth = true;
contextGroup.childForceExpandHeight = false;
contextGroup.childControlHeight = true;
contextGroup.spacing = 3;
var contextLayout = contextRowObj.AddComponent<LayoutElement>();
contextLayout.minHeight = 25;
var contextLabelObj = UIFactory.CreateLabel(contextRowObj, TextAnchor.MiddleLeft);
var contextText = contextLabelObj.GetComponent<Text>();
contextText.text = "Searching for:";
var contextLabelLayout = contextLabelObj.AddComponent<LayoutElement>();
contextLabelLayout.minWidth = 125;
contextLabelLayout.minHeight = 25;
// context buttons
AddContextButton(contextRowObj, "UnityEngine.Object", SearchContext.UnityObject, 140);
AddContextButton(contextRowObj, "GameObject", SearchContext.GameObject);
AddContextButton(contextRowObj, "Component", SearchContext.Component);
AddContextButton(contextRowObj, "Custom...", SearchContext.Custom);
// custom type input
var customTypeObj = UIFactory.CreateInputField(contextRowObj);
var customTypeLayout = customTypeObj.AddComponent<LayoutElement>();
customTypeLayout.minWidth = 250;
customTypeLayout.flexibleWidth = 2000;
customTypeLayout.minHeight = 25;
customTypeLayout.flexibleHeight = 0;
m_customTypeInput = customTypeObj.GetComponent<InputField>();
m_customTypeInput.placeholder.gameObject.GetComponent<Text>().text = "eg. UnityEngine.Texture2D, etc...";
// static class and singleton buttons
var secondRow = UIFactory.CreateHorizontalGroup(optionsGroupObj, new Color(1, 1, 1, 0));
var secondGroup = secondRow.GetComponent<HorizontalLayoutGroup>();
secondGroup.childForceExpandWidth = false;
secondGroup.childForceExpandHeight = false;
secondGroup.spacing = 3;
var secondLayout = secondRow.AddComponent<LayoutElement>();
secondLayout.minHeight = 25;
var spacer = UIFactory.CreateUIObject("spacer", secondRow);
var spaceLayout = spacer.AddComponent<LayoutElement>();
spaceLayout.minWidth = 125;
spaceLayout.minHeight = 25;
AddContextButton(secondRow, "Static Class", SearchContext.StaticClass);
AddContextButton(secondRow, "Singleton", SearchContext.Singleton);
// search input
var nameRowObj = UIFactory.CreateHorizontalGroup(optionsGroupObj, new Color(1, 1, 1, 0));
var nameRowGroup = nameRowObj.GetComponent<HorizontalLayoutGroup>();
nameRowGroup.childForceExpandWidth = true;
nameRowGroup.childControlWidth = true;
nameRowGroup.childForceExpandHeight = false;
nameRowGroup.childControlHeight = true;
var nameRowLayout = nameRowObj.AddComponent<LayoutElement>();
nameRowLayout.minHeight = 25;
nameRowLayout.flexibleHeight = 0;
nameRowLayout.flexibleWidth = 5000;
var nameLabelObj = UIFactory.CreateLabel(nameRowObj, TextAnchor.MiddleLeft);
var nameLabelText = nameLabelObj.GetComponent<Text>();
nameLabelText.text = "Name contains:";
var nameLabelLayout = nameLabelObj.AddComponent<LayoutElement>();
nameLabelLayout.minWidth = 125;
nameLabelLayout.minHeight = 25;
var nameInputObj = UIFactory.CreateInputField(nameRowObj);
m_nameInput = nameInputObj.GetComponent<InputField>();
//m_nameInput.placeholder.gameObject.GetComponent<TextMeshProUGUI>().text = "";
var nameInputLayout = nameInputObj.AddComponent<LayoutElement>();
nameInputLayout.minWidth = 150;
nameInputLayout.flexibleWidth = 5000;
nameInputLayout.minHeight = 25;
// extra filter row
m_extraFilterRow = UIFactory.CreateHorizontalGroup(optionsGroupObj, new Color(1, 1, 1, 0));
m_extraFilterRow.SetActive(false);
var extraGroup = m_extraFilterRow.GetComponent<HorizontalLayoutGroup>();
extraGroup.childForceExpandHeight = true;
extraGroup.childControlHeight = true;
extraGroup.childForceExpandWidth = false;
extraGroup.childControlWidth = true;
var filterRowLayout = m_extraFilterRow.AddComponent<LayoutElement>();
filterRowLayout.minHeight = 25;
filterRowLayout.flexibleHeight = 0;
filterRowLayout.minWidth = 125;
filterRowLayout.flexibleWidth = 150;
// scene filter
var sceneLabelObj = UIFactory.CreateLabel(m_extraFilterRow, TextAnchor.MiddleLeft);
var sceneLabel = sceneLabelObj.GetComponent<Text>();
sceneLabel.text = "Scene Filter:";
var sceneLayout = sceneLabelObj.AddComponent<LayoutElement>();
sceneLayout.minWidth = 125;
sceneLayout.minHeight = 25;
var sceneDropObj = UIFactory.CreateDropdown(m_extraFilterRow, out m_sceneDropdown);
m_sceneDropdown.itemText.text = "Any";
m_sceneDropdown.itemText.fontSize = 12;
var sceneDropLayout = sceneDropObj.AddComponent<LayoutElement>();
sceneDropLayout.minWidth = 220;
sceneDropLayout.minHeight = 25;
m_sceneDropdown.onValueChanged.AddListener(OnSceneDropdownChanged);
void OnSceneDropdownChanged(int value)
{
if (value < 4)
m_sceneFilter = (SceneFilter)value;
else
m_sceneFilter = SceneFilter.Explicit;
}
// invisible space
var invis = UIFactory.CreateUIObject("spacer", m_extraFilterRow);
var invisLayout = invis.AddComponent<LayoutElement>();
invisLayout.minWidth = 25;
invisLayout.flexibleWidth = 0;
// children filter
var childLabelObj = UIFactory.CreateLabel(m_extraFilterRow, TextAnchor.MiddleLeft);
var childLabel = childLabelObj.GetComponent<Text>();
childLabel.text = "Child Filter:";
var childLayout = childLabelObj.AddComponent<LayoutElement>();
childLayout.minWidth = 100;
childLayout.minHeight = 25;
var childDropObj = UIFactory.CreateDropdown(m_extraFilterRow, out Dropdown childDrop);
childDrop.itemText.text = "Any";
childDrop.itemText.fontSize = 12;
var childDropLayout = childDropObj.AddComponent<LayoutElement>();
childDropLayout.minWidth = 180;
childDropLayout.minHeight = 25;
childDrop.options.Add(new Dropdown.OptionData { text = "Any" });
childDrop.options.Add(new Dropdown.OptionData { text = "Root Objects Only" });
childDrop.options.Add(new Dropdown.OptionData { text = "Children Only" });
childDrop.onValueChanged.AddListener(OnChildDropdownChanged);
void OnChildDropdownChanged(int value)
{
m_childFilter = (ChildFilter)value;
}
// search button
var searchBtnObj = UIFactory.CreateButton(topAreaObj);
var searchText = searchBtnObj.GetComponentInChildren<Text>();
searchText.text = "Search";
LayoutElement searchBtnLayout = searchBtnObj.AddComponent<LayoutElement>();
searchBtnLayout.minHeight = 30;
searchBtnLayout.flexibleHeight = 0;
var searchBtn = searchBtnObj.GetComponent<Button>();
searchBtn.onClick.AddListener(OnSearchClicked);
}
internal void AddContextButton(GameObject parent, string label, SearchContext context, float width = 110)
{
var btnObj = UIFactory.CreateButton(parent);
var btn = btnObj.GetComponent<Button>();
m_contextButtons.Add(context, btn);
btn.onClick.AddListener(() => { OnContextButtonClicked(context); });
var btnLayout = btnObj.AddComponent<LayoutElement>();
btnLayout.minHeight = 25;
btnLayout.minWidth = width;
var btnText = btnObj.GetComponentInChildren<Text>();
btnText.text = label;
// if first button
if (!m_selectedContextButton)
{
OnContextButtonClicked(context);
}
}
internal void ConstructResultsArea()
{
// Result group holder (NOT actual result list content)
var resultGroupObj = UIFactory.CreateVerticalGroup(Content, new Color(1,1,1,0));
var resultGroup = resultGroupObj.GetComponent<VerticalLayoutGroup>();
resultGroup.childForceExpandHeight = false;
resultGroup.childForceExpandWidth = true;
resultGroup.childControlHeight = true;
resultGroup.childControlWidth = true;
resultGroup.spacing = 5;
resultGroup.padding.top = 5;
resultGroup.padding.right = 5;
resultGroup.padding.left = 5;
resultGroup.padding.bottom = 5;
var resultCountObj = UIFactory.CreateLabel(resultGroupObj, TextAnchor.MiddleCenter);
m_resultCountText = resultCountObj.GetComponent<Text>();
m_resultCountText.text = "No results...";
GameObject scrollObj = UIFactory.CreateScrollView(resultGroupObj,
out m_resultListContent,
out SliderScrollbar scroller,
new Color(0.07f, 0.07f, 0.07f, 1));
m_resultListPageHandler = new PageHandler(scroller);
m_resultListPageHandler.ConstructUI(resultGroupObj);
m_resultListPageHandler.OnPageChanged += OnResultPageTurn;
// actual result list content
var contentGroup = m_resultListContent.GetComponent<VerticalLayoutGroup>();
contentGroup.spacing = 2;
contentGroup.childForceExpandHeight = false;
contentGroup.childControlHeight = true;
}
internal void AddResultButton()
{
int thisIndex = m_resultListTexts.Count();
GameObject btnGroupObj = UIFactory.CreateHorizontalGroup(m_resultListContent, new Color(0.1f, 0.1f, 0.1f));
HorizontalLayoutGroup btnGroup = btnGroupObj.GetComponent<HorizontalLayoutGroup>();
btnGroup.childForceExpandWidth = true;
btnGroup.childControlWidth = true;
btnGroup.childForceExpandHeight = false;
btnGroup.childControlHeight = true;
btnGroup.padding.top = 1;
btnGroup.padding.left = 1;
btnGroup.padding.right = 1;
btnGroup.padding.bottom = 1;
LayoutElement btnLayout = btnGroupObj.AddComponent<LayoutElement>();
btnLayout.flexibleWidth = 320;
btnLayout.minHeight = 25;
btnLayout.flexibleHeight = 0;
btnGroupObj.AddComponent<Mask>();
GameObject mainButtonObj = UIFactory.CreateButton(btnGroupObj);
LayoutElement mainBtnLayout = mainButtonObj.AddComponent<LayoutElement>();
mainBtnLayout.minHeight = 25;
mainBtnLayout.flexibleHeight = 0;
mainBtnLayout.minWidth = 230;
mainBtnLayout.flexibleWidth = 0;
Button mainBtn = mainButtonObj.GetComponent<Button>();
ColorBlock mainColors = mainBtn.colors;
mainColors.normalColor = new Color(0.1f, 0.1f, 0.1f);
mainColors.highlightedColor = new Color(0.2f, 0.2f, 0.2f, 1);
mainBtn.colors = mainColors;
mainBtn.onClick.AddListener(() => { OnResultClicked(thisIndex); });
Text mainText = mainButtonObj.GetComponentInChildren<Text>();
mainText.alignment = TextAnchor.MiddleLeft;
mainText.horizontalOverflow = HorizontalWrapMode.Overflow;
m_resultListTexts.Add(mainText);
}
#endregion
}
}