* Added a 'Default' button for config values to revert to the default value
* Added an internal config entry to save the window position between sessions
* Reordered the config settings in the menu so the important ones are at the top
* Adjusted the UI for config entries, should be a bit easier to read now.
* Adjusted the UI for Dictionaries, the keys and values now alternate background colors.
* A few other minor UI fixes and tweaks for 3.3.0
This commit is contained in:
Sinai 2021-03-31 01:42:32 +11:00
parent 456e15020f
commit f280b45ed3
21 changed files with 145 additions and 72 deletions

View File

@ -16,6 +16,8 @@ namespace UnityExplorer.Core.Config
public Action<T> OnValueChanged;
public Action OnValueChangedNotify { get; set; }
public object DefaultValue { get; }
public T Value
{
get => m_value;
@ -29,12 +31,13 @@ namespace UnityExplorer.Core.Config
set => SetValue((T)value);
}
public ConfigElement(string name, string description, T defaultValue, bool isInternal)
public ConfigElement(string name, string description, T defaultValue, bool isInternal = false)
{
Name = name;
Description = description;
m_value = defaultValue;
DefaultValue = defaultValue;
IsInternal = isInternal;
@ -52,6 +55,8 @@ namespace UnityExplorer.Core.Config
OnValueChanged?.Invoke(value);
OnValueChangedNotify?.Invoke();
ConfigManager.Handler.OnAnyConfigChanged();
}
object IConfigElement.GetLoaderConfigValue() => GetLoaderConfigValue();
@ -60,5 +65,10 @@ namespace UnityExplorer.Core.Config
{
return ConfigManager.Handler.GetConfigValue(this);
}
public void RevertToDefaultValue()
{
Value = (T)DefaultValue;
}
}
}

View File

@ -24,6 +24,7 @@ namespace UnityExplorer.Core.Config
public static ConfigElement<bool> Hide_On_Startup;
public static ConfigElement<string> Last_Window_Anchors;
public static ConfigElement<string> Last_Window_Position;
public static ConfigElement<int> Last_Active_Tab;
public static ConfigElement<bool> Last_DebugConsole_State;
public static ConfigElement<bool> Last_SceneExplorer_State;
@ -41,6 +42,7 @@ namespace UnityExplorer.Core.Config
SceneExplorer.OnToggleShow += SceneExplorer_OnToggleShow;
PanelDragger.OnFinishResize += PanelDragger_OnFinishResize;
PanelDragger.OnFinishDrag += PanelDragger_OnFinishDrag;
MainMenu.OnActiveTabChanged += MainMenu_OnActiveTabChanged;
DebugConsole.OnToggleShow += DebugConsole_OnToggleShow;
}
@ -55,39 +57,40 @@ namespace UnityExplorer.Core.Config
{
Main_Menu_Toggle = new ConfigElement<KeyCode>("Main Menu Toggle",
"The UnityEngine.KeyCode to toggle the UnityExplorer Menu.",
KeyCode.F7,
false);
KeyCode.F7);
Force_Unlock_Mouse = new ConfigElement<bool>("Force Unlock Mouse",
"Force the Cursor to be unlocked (visible) when the UnityExplorer menu is open.",
true,
false);
Default_Page_Limit = new ConfigElement<int>("Default Page Limit",
"The default maximum number of elements per 'page' in UnityExplorer.",
25,
false);
Default_Output_Path = new ConfigElement<string>("Default Output Path",
"The default output path when exporting things from UnityExplorer.",
Path.Combine(ExplorerCore.Loader.ExplorerFolder, "Output"),
Hide_On_Startup = new ConfigElement<bool>("Hide On Startup",
"Should UnityExplorer be hidden on startup?",
false);
Log_Unity_Debug = new ConfigElement<bool>("Log Unity Debug",
"Should UnityEngine.Debug.Log messages be printed to UnityExplorer's log?",
false,
false);
Hide_On_Startup = new ConfigElement<bool>("Hide On Startup",
"Should UnityExplorer be hidden on startup?",
false,
false);
Force_Unlock_Mouse = new ConfigElement<bool>("Force Unlock Mouse",
"Force the Cursor to be unlocked (visible) when the UnityExplorer menu is open.",
true);
Default_Page_Limit = new ConfigElement<int>("Default Page Limit",
"The default maximum number of elements per 'page' in UnityExplorer.",
25);
Default_Output_Path = new ConfigElement<string>("Default Output Path",
"The default output path when exporting things from UnityExplorer.",
Path.Combine(ExplorerCore.Loader.ExplorerFolder, "Output"));
// Internal configs
Last_Window_Anchors = new ConfigElement<string>("Last_Window_Anchors",
"For internal use, the last anchors of the UnityExplorer window.",
DEFAULT_WINDOW_ANCHORS,
true);
Last_Window_Position = new ConfigElement<string>("Last_Window_Position",
"For internal use, the last position of the UnityExplorer window.",
DEFAULT_WINDOW_POSITION,
true);
Last_Active_Tab = new ConfigElement<int>("Last_Active_Tab",
"For internal use, the last active tab index.",
0,
@ -108,31 +111,33 @@ namespace UnityExplorer.Core.Config
private static void PanelDragger_OnFinishResize(RectTransform rect)
{
Last_Window_Anchors.Value = RectAnchorsToString(rect);
Handler.OnAnyConfigChanged();
Last_Window_Anchors.Value = rect.RectAnchorsToString();
}
private static void PanelDragger_OnFinishDrag(RectTransform rect)
{
Last_Window_Position.Value = rect.RectPositionToString();
}
private static void MainMenu_OnActiveTabChanged(int page)
{
Last_Active_Tab.Value = page;
Handler.OnAnyConfigChanged();
}
private static void DebugConsole_OnToggleShow(bool showing)
{
Last_DebugConsole_State.Value = showing;
Handler.OnAnyConfigChanged();
}
private static void SceneExplorer_OnToggleShow(bool showing)
{
Last_SceneExplorer_State.Value = showing;
Handler.OnAnyConfigChanged();
}
// Window Anchors helpers
private const string DEFAULT_WINDOW_ANCHORS = "0.25,0.10,0.78,0.95";
private const string DEFAULT_WINDOW_POSITION = "0,0";
internal static CultureInfo _enCulture = new CultureInfo("en-US");
@ -177,5 +182,33 @@ namespace UnityExplorer.Core.Config
panel.anchorMin = new Vector2(anchors.x, anchors.y);
panel.anchorMax = new Vector2(anchors.z, anchors.w);
}
internal static string RectPositionToString(this RectTransform rect)
{
return string.Format(_enCulture, "{0},{1}", new object[]
{
rect.localPosition.x, rect.localPosition.y
});
}
internal static void SetPositionFromString(this RectTransform rect, string stringPosition)
{
try
{
var split = stringPosition.Split(',');
if (split.Length != 2)
throw new Exception();
Vector3 vector = rect.localPosition;
vector.x = float.Parse(split[0], _enCulture);
vector.y = float.Parse(split[1], _enCulture);
rect.localPosition = vector;
}
catch //(Exception ex)
{
//ExplorerCore.LogWarning("Exception setting window position: " + ex);
}
}
}
}

View File

@ -11,9 +11,12 @@ namespace UnityExplorer.Core.Config
Type ElementType { get; }
object BoxedValue { get; set; }
object DefaultValue { get; }
object GetLoaderConfigValue();
void RevertToDefaultValue();
Action OnValueChangedNotify { get; set; }
}
}

View File

@ -12,7 +12,7 @@ namespace UnityExplorer
public class ExplorerCore
{
public const string NAME = "UnityExplorer";
public const string VERSION = "3.3.0";
public const string VERSION = "3.3.1";
public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.unityexplorer";

View File

@ -35,7 +35,7 @@ namespace UnityExplorer.UI.CacheObject
{
IValue = InteractiveValue.Create(value, fallbackType);
IValue.Owner = this;
IValue.m_mainContentParent = m_rightGroup;
IValue.m_mainContentParent = m_mainGroup;
IValue.m_subContentParent = this.m_subContent;
}
@ -52,26 +52,28 @@ namespace UnityExplorer.UI.CacheObject
ConfigManager.Handler.OnAnyConfigChanged();
}
internal GameObject m_leftGroup;
internal GameObject m_rightGroup;
internal GameObject m_mainGroup;
//internal GameObject m_leftGroup;
//internal GameObject m_rightGroup;
//internal GameObject m_secondRow;
internal override void ConstructUI()
{
base.ConstructUI();
var vertGroup = UIFactory.CreateVerticalGroup(m_mainContent, "ConfigHolder", true, false, true, true, 5, new Vector4(2, 2, 2, 2));
m_mainGroup = UIFactory.CreateVerticalGroup(m_mainContent, "ConfigHolder", true, false, true, true, 5, new Vector4(2, 2, 2, 2));
var horiGroup = UIFactory.CreateHorizontalGroup(vertGroup, "ConfigEntryHolder", true, false, true, true);
var horiGroup = UIFactory.CreateHorizontalGroup(m_mainGroup, "ConfigEntryHolder", false, false, true, true, childAlignment: TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(horiGroup, minHeight: 30, flexibleHeight: 0);
// left group
//// left group
m_leftGroup = UIFactory.CreateHorizontalGroup(horiGroup, "ConfigTitleGroup", false, false, true, true, 4, default, new Color(1, 1, 1, 0));
UIFactory.SetLayoutElement(m_leftGroup, minHeight: 25, flexibleHeight: 0, minWidth: 125, flexibleWidth: 200);
//m_leftGroup = UIFactory.CreateHorizontalGroup(horiGroup, "ConfigTitleGroup", false, false, true, true, 4, default, new Color(1, 1, 1, 0));
//UIFactory.SetLayoutElement(m_leftGroup, minHeight: 25, flexibleHeight: 0, minWidth: 200, flexibleWidth: 0);
// config entry label
var configLabel = UIFactory.CreateLabel(m_leftGroup, "ConfigLabel", this.RefConfig.Name, TextAnchor.MiddleLeft);
var configLabel = UIFactory.CreateLabel(horiGroup, "ConfigLabel", this.RefConfig.Name, TextAnchor.MiddleLeft);
var leftRect = configLabel.GetComponent<RectTransform>();
leftRect.anchorMin = Vector2.zero;
leftRect.anchorMax = Vector2.one;
@ -80,23 +82,39 @@ namespace UnityExplorer.UI.CacheObject
leftRect.sizeDelta = Vector2.zero;
UIFactory.SetLayoutElement(configLabel.gameObject, minWidth: 250, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
// right group
// Default button
m_rightGroup = UIFactory.CreateVerticalGroup(horiGroup, "ConfigValueGroup", false, false, true, true, 2, new Vector4(4,2,0,0),
new Color(1, 1, 1, 0));
UIFactory.SetLayoutElement(m_rightGroup, minHeight: 25, minWidth: 150, flexibleHeight: 0, flexibleWidth: 5000);
var defaultButton = UIFactory.CreateButton(horiGroup,
"RevertDefaultButton",
"Default",
() => { RefConfig.RevertToDefaultValue(); },
new Color(0.3f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(defaultButton.gameObject, minWidth: 80, minHeight: 22, flexibleWidth: 0);
//// right group
//m_rightGroup = UIFactory.CreateVerticalGroup(horiGroup, "ConfigValueGroup", false, false, true, true, 4, default, new Color(1, 1, 1, 0));
//UIFactory.SetLayoutElement(m_rightGroup, minHeight: 25, minWidth: 150, flexibleHeight: 0, flexibleWidth: 5000);
// Description label
var desc = UIFactory.CreateLabel(m_mainGroup, "Description", $"<i>{RefConfig.Description}</i>", TextAnchor.MiddleLeft, Color.grey);
UIFactory.SetLayoutElement(desc.gameObject, minWidth: 250, minHeight: 20, flexibleWidth: 9999, flexibleHeight: 0);
//// Second row (IValue)
//m_secondRow = UIFactory.CreateHorizontalGroup(m_mainGroup, "DescriptionRow", false, false, true, true, 4, new Color(0.08f, 0.08f, 0.08f));
// IValue
if (IValue != null)
{
IValue.m_mainContentParent = m_rightGroup;
IValue.m_mainContentParent = m_mainGroup;
IValue.m_subContentParent = this.m_subContent;
}
// Config description label
UIFactory.CreateLabel(vertGroup, "Description", $"<i>{RefConfig.Description}</i>", TextAnchor.MiddleLeft, Color.grey);
m_subContent.transform.SetAsLastSibling();
// makes the subcontent look nicer
m_subContent.transform.SetParent(m_mainGroup.transform, false);
}
}
}

View File

@ -50,8 +50,12 @@ namespace UnityExplorer.UI.CacheObject
{
base.ConstructUI();
Color bgColor = this.PairType == PairTypes.Key
? new Color(0.07f, 0.07f, 0.07f)
: new Color(0.1f, 0.1f, 0.1f);
var rowObj = UIFactory.CreateHorizontalGroup(m_mainContent, "PairedGroup", false, false, true, true, 0, new Vector4(0,0,5,2),
new Color(1, 1, 1, 0));
bgColor);
var indexLabel = UIFactory.CreateLabel(rowObj, "IndexLabel", $"{this.PairType} {this.Index}:", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(indexLabel.gameObject, minWidth: 80, flexibleWidth: 30, minHeight: 25);

View File

@ -146,7 +146,7 @@ namespace UnityExplorer.UI.InteractiveValues
// dropdown
var dropdownObj = UIFactory.CreateDropdown(groupObj, out m_dropdown, "<notset>", 14, null);
var dropdownObj = UIFactory.CreateDropdown(groupObj, out m_dropdown, "", 14, null);
UIFactory.SetLayoutElement(dropdownObj, minWidth: 150, minHeight: 25, flexibleWidth: 120);
foreach (var kvp in m_values)

View File

@ -115,7 +115,7 @@ namespace UnityExplorer.UI.InteractiveValues
m_labelLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
m_readonlyInput = UIFactory.CreateLabel(m_valueContent, "ReadonlyLabel", "<notset>", TextAnchor.MiddleLeft);
m_readonlyInput = UIFactory.CreateLabel(m_valueContent, "ReadonlyLabel", "", TextAnchor.MiddleLeft);
m_readonlyInput.horizontalOverflow = HorizontalWrapMode.Overflow;
var testFitter = m_readonlyInput.gameObject.AddComponent<ContentSizeFitter>();
@ -128,7 +128,7 @@ namespace UnityExplorer.UI.InteractiveValues
{
base.ConstructSubcontent();
var groupObj = UIFactory.CreateVerticalGroup(m_subContentParent, "SubContent", true, false, true, true, 4, new Vector4(3,3,3,3),
var groupObj = UIFactory.CreateVerticalGroup(m_subContentParent, "SubContent", false, false, true, true, 4, new Vector4(3,3,3,3),
new Color(1, 1, 1, 0));
m_hiddenObj = UIFactory.CreateLabel(groupObj, "HiddenLabel", "", TextAnchor.MiddleLeft).gameObject;

View File

@ -338,7 +338,7 @@ namespace UnityExplorer.UI.InteractiveValues
// value label
m_baseLabel = UIFactory.CreateLabel(m_valueContent, "ValueLabel", "<not set>", TextAnchor.MiddleLeft);
m_baseLabel = UIFactory.CreateLabel(m_valueContent, "ValueLabel", "", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(m_baseLabel.gameObject, flexibleWidth: 9000, minHeight: 25);
m_subContentParent = subGroup;

View File

@ -200,15 +200,13 @@ namespace UnityExplorer.UI.Main.Home
UIFactory.CreateHorizontalGroup(topRowObj, "Toolbar", false, false, true, true, 10, new Vector4(2, 2, 2, 2), new Color(1,1,1,0));
// inspect under mouse button
AddMouseInspectButton(topRowObj, InspectUnderMouse.MouseInspectMode.UI);
AddMouseInspectButton(topRowObj, InspectUnderMouse.MouseInspectMode.World);
AddMouseInspectButton(topRowObj, "UI", InspectUnderMouse.MouseInspectMode.UI);
AddMouseInspectButton(topRowObj, "3D", InspectUnderMouse.MouseInspectMode.World);
}
private static void AddMouseInspectButton(GameObject topRowObj, InspectUnderMouse.MouseInspectMode mode)
private static void AddMouseInspectButton(GameObject topRowObj, string suffix, InspectUnderMouse.MouseInspectMode mode)
{
string lbl = "Mouse Inspect";
if (mode == InspectUnderMouse.MouseInspectMode.UI)
lbl += " (UI)";
string lbl = $"Mouse Inspect ({suffix})";
var inspectObj = UIFactory.CreateButton(topRowObj,
lbl,
@ -216,7 +214,7 @@ namespace UnityExplorer.UI.Main.Home
() => { InspectUnderMouse.StartInspect(mode); },
new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(inspectObj.gameObject, minWidth: 120, flexibleWidth: 0);
UIFactory.SetLayoutElement(inspectObj.gameObject, minWidth: 150, flexibleWidth: 0);
}
}
}

View File

@ -174,7 +174,7 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
var mainBtn = UIFactory.CreateButton(btnGroupObj,
"MainButton",
"<notset>",
"",
() => { OnChildListObjectClicked(thisIndex); },
mainColors);

View File

@ -181,7 +181,7 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
var mainBtn = UIFactory.CreateButton(groupObj,
"MainButton",
"<notset>",
"",
() => { OnCompListObjectClicked(thisIndex); },
mainColors);

View File

@ -380,7 +380,7 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
UIFactory.SetLayoutElement(valueTitle.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 25, flexibleWidth: 0);
// actual value label
var valueLabel = UIFactory.CreateLabel(rowObject, "ValueLabel", "<notset>", TextAnchor.MiddleLeft);
var valueLabel = UIFactory.CreateLabel(rowObject, "ValueLabel", "", TextAnchor.MiddleLeft);
editor.values[(int)vectorValue] = valueLabel;
UIFactory.SetLayoutElement(valueLabel.gameObject, minWidth: 85, flexibleWidth: 0, minHeight: 25);

View File

@ -321,7 +321,7 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
var layerLabel = UIFactory.CreateLabel(sceneLayerRow, "LayerLabel", "Layer:", TextAnchor.MiddleCenter, Color.grey, true, 14);
UIFactory.SetLayoutElement(layerLabel.gameObject, minWidth: 55, flexibleWidth: 0);
var layerDropdownObj = UIFactory.CreateDropdown(sceneLayerRow, out m_layerDropdown, "<notset>", 14, OnLayerSelected);
var layerDropdownObj = UIFactory.CreateDropdown(sceneLayerRow, out m_layerDropdown, "", 14, OnLayerSelected);
m_layerDropdown.options.Clear();
for (int i = 0; i < 32; i++)
{
@ -335,7 +335,7 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
var sceneLabel = UIFactory.CreateLabel(sceneLayerRow, "SceneLabel", "Scene:", TextAnchor.MiddleCenter, Color.grey, true, 14);
UIFactory.SetLayoutElement(sceneLabel.gameObject, minWidth: 55, flexibleWidth: 0);
m_sceneText = UIFactory.CreateLabel(sceneLayerRow, "SceneText", "<notset>", TextAnchor.MiddleLeft);
m_sceneText = UIFactory.CreateLabel(sceneLayerRow, "SceneText", "", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(m_sceneText.gameObject, minWidth: 120, flexibleWidth: 2000);
}

View File

@ -94,7 +94,7 @@ namespace UnityExplorer.UI.Main.Home.Inspectors
m_tabButton = UIFactory.CreateButton(tabGroupObj,
"TabButton",
"<notset>",
"",
() => { InspectorManager.Instance.SetInspectorTab(parent); });
UIFactory.SetLayoutElement(m_tabButton.gameObject, minWidth: 165, flexibleWidth: 0);

View File

@ -399,7 +399,7 @@ namespace UnityExplorer.UI.Main.Home
m_titleObj = UIFactory.CreateLabel(leftPane, "SceneExplorerTitle", "Scene Explorer", TextAnchor.UpperLeft, default, true, 20).gameObject;
UIFactory.SetLayoutElement(m_titleObj, minHeight: 30, flexibleHeight: 0);
m_sceneDropdownObj = UIFactory.CreateDropdown(leftPane, out m_sceneDropdown, "<notset>", 14, null);
m_sceneDropdownObj = UIFactory.CreateDropdown(leftPane, out m_sceneDropdown, "", 14, null);
UIFactory.SetLayoutElement(m_sceneDropdownObj, minHeight: 40, minWidth: 320, flexibleWidth: 0, flexibleHeight: 0);
m_sceneDropdownText = m_sceneDropdown.transform.Find("Label").GetComponent<Text>();

View File

@ -151,7 +151,8 @@ namespace UnityExplorer.UI.Main
private void ConstructMenu()
{
MainPanel = UIFactory.CreatePanel("MainMenu", out GameObject content, ConfigManager.Last_Window_Anchors.Value);
MainPanel = UIFactory.CreatePanel("MainMenu", out GameObject content,
ConfigManager.Last_Window_Anchors.Value, ConfigManager.Last_Window_Position.Value);
ConstructTitleBar(content);

View File

@ -35,14 +35,14 @@ namespace UnityExplorer.UI.Main.Options
{
GameObject parent = MainMenu.Instance.PageViewport;
Content = UIFactory.CreateVerticalGroup(parent, "OptionsPage", true, true, true, true, 5, new Vector4(4,4,4,4),
Content = UIFactory.CreateVerticalGroup(parent, "OptionsPage", false, true, true, true, 5, new Vector4(4,4,4,4),
new Color(0.15f, 0.15f, 0.15f));
UIFactory.SetLayoutElement(Content, minHeight: 340, flexibleHeight: 9999);
// ~~~~~ Title ~~~~~
var titleLabel = UIFactory.CreateLabel(Content, "Title", "Options", TextAnchor.UpperLeft, default, true, 25);
UIFactory.SetLayoutElement(titleLabel.gameObject, minHeight: 30, flexibleHeight: 0);
UIFactory.SetLayoutElement(titleLabel.gameObject, minHeight: 30, flexibleHeight: 0, flexibleWidth: 9999);
// Save button
@ -51,7 +51,7 @@ namespace UnityExplorer.UI.Main.Options
"Save Config File",
() => { ConfigManager.Handler.SaveConfig(); },
new Color(0.25f, 0.6f, 0.25f));
UIFactory.SetLayoutElement(btn.gameObject, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 0);
UIFactory.SetLayoutElement(btn.gameObject, minWidth: 200, flexibleWidth: 0, minHeight: 30, flexibleHeight: 0);
// ~~~~~ Actual options ~~~~~

View File

@ -18,6 +18,7 @@ namespace UnityExplorer.UI.Main
public RectTransform Panel { get; set; }
public static event Action<RectTransform> OnFinishResize;
public static event Action<RectTransform> OnFinishDrag;
public PanelDragger(RectTransform dragArea, RectTransform panelToDrag)
{
@ -115,6 +116,7 @@ namespace UnityExplorer.UI.Main
Vector3 diff = InputManager.MousePosition - m_lastDragPosition;
m_lastDragPosition = InputManager.MousePosition;
// update position while preserving the z value
Vector3 pos = Panel.localPosition;
float z = pos.z;
pos += diff;
@ -125,7 +127,8 @@ namespace UnityExplorer.UI.Main
public void OnEndDrag()
{
WasDragging = false;
//UpdateResizeCache();
OnFinishDrag?.Invoke(Panel);
}
#endregion

View File

@ -448,7 +448,7 @@ namespace UnityExplorer.UI.Main.Search
var mainButton = UIFactory.CreateButton(btnGroupObj,
"ResultButton",
"<not set>",
"",
() => { OnResultClicked(thisIndex); },
mainColors);

View File

@ -157,7 +157,7 @@ namespace UnityExplorer.UI
/// <summary>
/// Create a Panel on the UI Canvas.
/// </summary>
public static GameObject CreatePanel(string name, out GameObject contentHolder, string anchors = null)
public static GameObject CreatePanel(string name, out GameObject contentHolder, string anchors = null, string position = null)
{
var panelObj = CreateUIObject(name, UIManager.CanvasRoot);
var rect = panelObj.GetComponent<RectTransform>();
@ -169,6 +169,9 @@ namespace UnityExplorer.UI
if (anchors != null)
rect.SetAnchorsFromString(anchors);
if (position != null)
rect.SetPositionFromString(position);
var maskImg = panelObj.AddComponent<Image>();
maskImg.color = Color.white;
panelObj.AddComponent<Mask>().showMaskGraphic = false;