/// <summary> /// Add Horizontal Options to the content area. /// </summary> /// <param name="entries">The menu data.</param> /// <param name="c">The content area to add the entries to.</param> /// <param name="returnScreen">The screen to return to when the user hits cancel.</param> public static void AddModMenuContent( List <IMenuMod.MenuEntry> entries, ContentArea c, MenuScreen returnScreen ) { foreach (var entry in entries) { c.AddHorizontalOption( entry.Name, new HorizontalOptionConfig { ApplySetting = (_, i) => entry.Saver(i), RefreshSetting = (s, _) => s.optionList.SetOptionTo(entry.Loader()), CancelAction = _ => ((Patch.UIManager)UIManager.instance).GoToDynamicMenu(returnScreen), Description = string.IsNullOrEmpty(entry.Description) ? null : new DescriptionInfo { Text = entry.Description }, Label = entry.Name, Options = entry.Values, Style = HorizontalOptionStyle.VanillaStyle }, out var option ); option.menuSetting.RefreshValueFromGameSettings(); } }
/// <summary> /// Creates a text panel. /// </summary> /// <param name="content">The <c>ContentArea</c> to put the text panel in.</param> /// <param name="name">The name of the text panel game object.</param> /// <param name="size">The size of the text panel.</param> /// <param name="config">The configuration options for the text panel.</param> /// <param name="text">The <c>Text</c> component on the created text panel.</param> /// <returns></returns> public static ContentArea AddTextPanel( this ContentArea content, string name, RelVector2 size, TextPanelConfig config, out Text text ) { content.AddStaticPanel(name, size, out var go); text = go.AddComponent <Text>(); text.text = config.Text; text.fontSize = config.Size; text.font = config.Font switch { TextPanelConfig.TextFont.TrajanRegular => MenuResources.TrajanRegular, TextPanelConfig.TextFont.TrajanBold => MenuResources.TrajanBold, TextPanelConfig.TextFont.Perpetua => MenuResources.Perpetua, TextPanelConfig.TextFont.NotoSerifCJKSCRegular => MenuResources.NotoSerifCJKSCRegular, _ => MenuResources.TrajanRegular }; text.supportRichText = true; text.alignment = config.Anchor; return(content); }
/// <summary> /// Creates a single item wrapper. /// </summary> /// <remarks> /// This wrapper will have no size so all parent relative sizes will break. /// </remarks> /// <param name="content">The <c>ContentArea</c> to put the wrapper in.</param> /// <param name="name">The name of the wrapper game object.</param> /// <param name="action">The action that will get called to add the inner object.</param> /// <param name="wrapper">The newly created wrapper.</param> /// <returns></returns> public static ContentArea AddWrappedItem( this ContentArea content, string name, Action <ContentArea> action, out GameObject wrapper ) { // Wrapper wrapper = new GameObject(name); GameObject.DontDestroyOnLoad(wrapper); wrapper.transform.SetParent(content.ContentObject.transform, false); // RectTransform var wrapperRt = wrapper.AddComponent <RectTransform>(); wrapperRt.sizeDelta = new Vector2(0f, 0f); wrapperRt.pivot = new Vector2(0.5f, 0.5f); wrapperRt.anchorMin = new Vector2(0.5f, 0.5f); wrapperRt.anchorMax = new Vector2(0.5f, 0.5f); content.Layout.ModifyNext(wrapperRt); // CanvasRenderer wrapper.AddComponent <CanvasRenderer>(); action(new ContentArea(wrapper, new SingleContentLayout(new Vector2(0.5f, 0.5f)), content.NavGraph)); return(content); }
/// <summary> /// Creates a scrollable window.<br/> /// The scrolling content will be the same width as the parent. /// </summary> /// <param name="content">The <c>ContentArea</c> to put the scrollable window in.</param> /// <param name="config">The configuration options for the scrollbar.</param> /// <param name="contentHeight">The height of the scroll window.</param> /// <param name="layout">The layout to apply to the added content.</param> /// <param name="action">The action that will get called to add the content.</param> /// <returns></returns> public static ContentArea AddScrollPaneContent( this ContentArea content, ScrollbarConfig config, RelLength contentHeight, IContentLayout layout, Action <ContentArea> action ) => content.AddScrollPaneContent(config, contentHeight, layout, action, out _, out _);
/// <summary> /// Creates an image panel. /// </summary> /// <param name="content">The <c>ContentArea</c> to put the text panel in.</param> /// <param name="name">The name of the image panel game object.</param> /// <param name="size">The size of the image panel.</param> /// <param name="sprite">The image to render.</param> /// <param name="image">The <c>Image</c> component on the created image panel.</param> /// <returns></returns> public static ContentArea AddImagePanel( this ContentArea content, string name, RelVector2 size, Sprite sprite, out Image image ) { content.AddStaticPanel(name, size, out var go); image = go.AddComponent <Image>(); image.sprite = sprite; image.preserveAspect = true; return(content); }
/// <summary> /// Creates a sized static panel with no other properties. /// </summary> /// <param name="content">The <c>ContentArea</c> to put the panel in.</param> /// <param name="name">The name of the panel game object.</param> /// <param name="size">The size of the panel.</param> /// <param name="obj">The newly created panel.</param> /// <returns></returns> public static ContentArea AddStaticPanel( this ContentArea content, string name, RelVector2 size, out GameObject obj ) { var go = new GameObject(name); GameObject.DontDestroyOnLoad(go); go.transform.SetParent(content.ContentObject.transform, false); // RectTransform var rt = go.AddComponent <RectTransform>(); size.GetBaseTransformData().Apply(rt); content.Layout.ModifyNext(rt); // CanvasRenderer go.AddComponent <CanvasRenderer>(); obj = go; return(content); }
/// <summary> /// Creates a keybind menu item. /// </summary> /// <param name="content">The <c>ContentArea</c> to put the keybind item in.</param> /// <param name="name">The name of the keybind game object.</param> /// <param name="action">The <c>PlayerAction</c> to associate with this keybind.</param> /// <param name="config">The configuration options for the keybind item.</param> /// <param name="mappableKey">The <c>MappablKey</c> component on the created keybind item.</param> /// <returns></returns> public static ContentArea AddKeybind( this ContentArea content, string name, PlayerAction action, KeybindConfig config, out MappableKey mappableKey ) { var style = config.Style ?? KeybindStyle.VanillaStyle; // Keybind object var keybind = new GameObject($"{name}"); GameObject.DontDestroyOnLoad(keybind); keybind.transform.SetParent(content.ContentObject.transform, false); // CanvasRenderer keybind.AddComponent <CanvasRenderer>(); // RectTransform var keybindRt = keybind.AddComponent <RectTransform>(); new RelVector2(new Vector2(650f, 100f)).GetBaseTransformData().Apply(keybindRt); content.Layout.ModifyNext(keybindRt); // MappableKey var mapKey = (Patch.MappableKey)keybind.AddComponent <MappableKey>(); mapKey.InitCustomActions(action.Owner, action); var mkbutton = (Patch.MenuSelectable)(MenuSelectable) mapKey; mkbutton.cancelAction = (CancelAction)Patch.CancelAction.CustomCancelAction; mkbutton.customCancelAction = _ => { mapKey.AbortRebind(); config.CancelAction?.Invoke(mapKey); }; content.NavGraph.AddNavigationNode(mapKey); // Text object var text = new GameObject("Text"); GameObject.DontDestroyOnLoad(text); text.transform.SetParent(keybind.transform, false); // CanvasRenderer text.AddComponent <CanvasRenderer>(); // RectTransform var textRt = text.AddComponent <RectTransform>(); textRt.sizeDelta = new Vector2(0f, 0f); textRt.anchorMin = new Vector2(0f, 0f); textRt.anchorMax = new Vector2(1f, 1f); textRt.anchoredPosition = new Vector2(0f, 0f); textRt.pivot = new Vector2(0.5f, 0.5f); // Text var labelText = text.AddComponent <Text>(); labelText.font = MenuResources.TrajanBold; labelText.fontSize = style.LabelTextSize; labelText.resizeTextMaxSize = style.LabelTextSize; labelText.alignment = TextAnchor.MiddleLeft; labelText.text = config.Label; labelText.supportRichText = true; labelText.verticalOverflow = VerticalWrapMode.Overflow; labelText.horizontalOverflow = HorizontalWrapMode.Overflow; // FixVerticalAlign text.AddComponent <FixVerticalAlign>(); // LeftCursor object var cursorL = new GameObject("CursorLeft"); GameObject.DontDestroyOnLoad(cursorL); cursorL.transform.SetParent(keybind.transform, false); // CanvasRenderer cursorL.AddComponent <CanvasRenderer>(); // RectTransform var cursorLRt = cursorL.AddComponent <RectTransform>(); cursorLRt.sizeDelta = new Vector2(154f, 112f); cursorLRt.pivot = new Vector2(0.5f, 0.5f); cursorLRt.anchorMin = new Vector2(0f, 0.5f); cursorLRt.anchorMax = new Vector2(0f, 0.5f); cursorLRt.anchoredPosition = new Vector2(-52f, 0f); cursorLRt.localScale = new Vector3(0.4f, 0.4f, 0.4f); // Animator var cursorLAnimator = cursorL.AddComponent <Animator>(); cursorLAnimator.runtimeAnimatorController = MenuResources.MenuCursorAnimator; cursorLAnimator.updateMode = AnimatorUpdateMode.UnscaledTime; cursorLAnimator.applyRootMotion = false; // Image cursorL.AddComponent <Image>(); // Post Component Config mapKey.leftCursor = cursorLAnimator; // RightCursor object var cursorR = new GameObject("CursorRight"); GameObject.DontDestroyOnLoad(cursorR); cursorR.transform.SetParent(keybind.transform, false); // CanvasRenderer cursorR.AddComponent <CanvasRenderer>(); // RectTransform var cursorRRt = cursorR.AddComponent <RectTransform>(); cursorRRt.sizeDelta = new Vector2(154f, 112f); cursorRRt.pivot = new Vector2(0.5f, 0.5f); cursorRRt.anchorMin = new Vector2(1f, 0.5f); cursorRRt.anchorMax = new Vector2(1f, 0.5f); cursorRRt.anchoredPosition = new Vector2(52f, 0f); cursorRRt.localScale = new Vector3(-0.4f, 0.4f, 0.4f); // Animator var cursorRAnimator = cursorR.AddComponent <Animator>(); cursorRAnimator.runtimeAnimatorController = MenuResources.MenuCursorAnimator; cursorRAnimator.updateMode = AnimatorUpdateMode.UnscaledTime; cursorRAnimator.applyRootMotion = false; // Image cursorR.AddComponent <Image>(); // Post Component Config mapKey.rightCursor = cursorRAnimator; // Keymap object var keymap = new GameObject("Keymap"); GameObject.DontDestroyOnLoad(keymap); keymap.transform.SetParent(keybind.transform, false); // CanvasRenderer keymap.AddComponent <CanvasRenderer>(); // RectTransform var keymapRt = keymap.AddComponent <RectTransform>(); keymapRt.sizeDelta = new Vector2(145.8f, 82.4f); keymapRt.anchorMin = new Vector2(1f, 0.5f); keymapRt.anchorMax = new Vector2(1f, 0.5f); keymapRt.anchoredPosition = new Vector2(0f, 0f); keymapRt.pivot = new Vector2(1f, 0.5f); // Image var keymapImg = keymap.AddComponent <Image>(); keymapImg.preserveAspect = true; mapKey.keymapSprite = keymapImg; // Keymap Text object var keymapText = new GameObject("Text"); GameObject.DontDestroyOnLoad(keymapText); keymapText.transform.SetParent(keymap.transform, false); // CanvasRenderer keymapText.AddComponent <CanvasRenderer>(); // RectTransform var keymapTextRt = keymapText.AddComponent <RectTransform>(); keymapTextRt.sizeDelta = new Vector2(65f, 60f); keymapTextRt.anchorMin = new Vector2(0.5f, 0.5f); keymapTextRt.anchorMin = new Vector2(0.5f, 0.5f); keymapTextRt.anchoredPosition = new Vector2(32f, 0f); keymapTextRt.pivot = new Vector2(0.5f, 0.5f); // Text var keymapTextText = keymapText.AddComponent <Text>(); keymapTextText.font = MenuResources.Perpetua; mapKey.keymapText = keymapTextText; // FixVerticalAlign keymapText.AddComponent <FixVerticalAlign>().labelFixType = FixVerticalAlign.LabelFixType.KeyMap; mapKey.GetBinding(); mapKey.ShowCurrentBinding(); mappableKey = mapKey; return(content); }
/// <summary> /// Creates a keybind menu item. /// </summary> /// <param name="content">The <c>ContentArea</c> to put the keybind item in.</param> /// <param name="name">The name of the keybind game object.</param> /// <param name="action">The <c>PlayerAction</c> to associate with this keybind.</param> /// <param name="config">The configuration options for the keybind item.</param> /// <returns></returns> public static ContentArea AddKeybind( this ContentArea content, string name, PlayerAction action, KeybindConfig config ) => content.AddKeybind(name, action, config, out _);
/// <summary> /// Creates a text panel. /// </summary> /// <param name="content">The <c>ContentArea</c> to put the text panel in.</param> /// <param name="name">The name of the text panel game object.</param> /// <param name="size">The size of the text panel.</param> /// <param name="config">The configuration options for the text panel.</param> /// <returns></returns> public static ContentArea AddTextPanel( this ContentArea content, string name, RelVector2 size, TextPanelConfig config ) => content.AddTextPanel(name, size, config, out _);
/// <summary> /// Creates a single item wrapper. /// </summary> /// <remarks> /// This wrapper will have no size so all parent relative sizes will break. /// </remarks> /// <param name="content">The <c>ContentArea</c> to put the wrapper in.</param> /// <param name="name">The name of the wrapper game object.</param> /// <param name="action">The action that will get called to add the inner object.</param> /// <returns></returns> public static ContentArea AddWrappedItem( this ContentArea content, string name, Action <ContentArea> action ) => content.AddWrappedItem(name, action, out _);
/// <summary> /// Creates an image panel. /// </summary> /// <param name="content">The <c>ContentArea</c> to put the text panel in.</param> /// <param name="name">The name of the image panel game object.</param> /// <param name="size">The size of the image panel.</param> /// <param name="image">The image to render.</param> /// <returns></returns> public static ContentArea AddImagePanel( this ContentArea content, string name, RelVector2 size, Sprite image ) => content.AddImagePanel(name, size, image, out _);
/// <summary> /// Creates a menu button. /// </summary> /// <param name="content">The <c>ContentArea</c> to put the button in.</param> /// <param name="name">The name of the button game object.</param> /// <param name="config">The configuration options for the menu button.</param> /// <param name="button">The <c>MenuButton</c> component on the created menu button.</param> /// <returns></returns> public static ContentArea AddMenuButton( this ContentArea content, string name, MenuButtonConfig config, out MenuButton button ) { var style = config.Style ?? MenuButtonStyle.VanillaStyle; // Option object var option = new GameObject($"{name}"); GameObject.DontDestroyOnLoad(option); option.transform.SetParent(content.ContentObject.transform, false); // CanvasRenderer option.AddComponent <CanvasRenderer>(); // RectTransform var optionRt = option.AddComponent <RectTransform>(); new RelVector2(new RelLength(0f, 1f), style.Height) .GetBaseTransformData() .Apply(optionRt); content.Layout.ModifyNext(optionRt); // MenuButton var menuButton = (Patch.MenuButton)option.AddComponent <MenuButton>(); menuButton.buttonType = (MenuButton.MenuButtonType)Patch.MenuButton.MenuButtonType.CustomSubmit; menuButton.submitAction = config.SubmitAction; menuButton.cancelAction = (CancelAction)Patch.CancelAction.CustomCancelAction; menuButton.proceed = config.Proceed; ((Patch.MenuSelectable)(MenuSelectable) menuButton).customCancelAction = config.CancelAction; content.NavGraph.AddNavigationNode(menuButton); // Label object var label = new GameObject("Label"); GameObject.DontDestroyOnLoad(label); label.transform.SetParent(option.transform, false); // CanvasRenderer label.AddComponent <CanvasRenderer>(); // RectTransform var labelRt = label.AddComponent <RectTransform>(); labelRt.sizeDelta = new Vector2(0f, 0f); labelRt.pivot = new Vector2(0.5f, 0.5f); labelRt.anchorMin = new Vector2(0f, 0f); labelRt.anchorMax = new Vector2(1f, 1f); labelRt.anchoredPosition = new Vector2(0f, 0f); // Text var labelText = label.AddComponent <Text>(); labelText.font = MenuResources.TrajanBold; labelText.fontSize = style.TextSize; labelText.resizeTextMaxSize = style.TextSize; labelText.alignment = TextAnchor.MiddleCenter; labelText.text = config.Label; labelText.supportRichText = true; labelText.verticalOverflow = VerticalWrapMode.Overflow; labelText.horizontalOverflow = HorizontalWrapMode.Overflow; // FixVerticalAlign label.AddComponent <FixVerticalAlign>(); // ContentSizeFitter var labelCsf = label.AddComponent <ContentSizeFitter>(); labelCsf.horizontalFit = ContentSizeFitter.FitMode.PreferredSize; // LeftCursor object var cursorL = new GameObject("CursorLeft"); GameObject.DontDestroyOnLoad(cursorL); cursorL.transform.SetParent(label.transform, false); // CanvasRenderer cursorL.AddComponent <CanvasRenderer>(); // RectTransform var cursorLRt = cursorL.AddComponent <RectTransform>(); cursorLRt.sizeDelta = new Vector2(164f, 119f); cursorLRt.pivot = new Vector2(0.5f, 0.5f); cursorLRt.anchorMin = new Vector2(0f, 0.5f); cursorLRt.anchorMax = new Vector2(0f, 0.5f); cursorLRt.anchoredPosition = new Vector2(-65f, 0f); cursorLRt.localScale = new Vector3(0.4f, 0.4f, 0.4f); // Animator var cursorLAnimator = cursorL.AddComponent <Animator>(); cursorLAnimator.runtimeAnimatorController = MenuResources.MenuCursorAnimator; cursorLAnimator.updateMode = AnimatorUpdateMode.UnscaledTime; cursorLAnimator.applyRootMotion = false; // Image cursorL.AddComponent <Image>(); // Post Component Config menuButton.leftCursor = cursorLAnimator; // RightCursor object var cursorR = new GameObject("CursorRight"); GameObject.DontDestroyOnLoad(cursorR); cursorR.transform.SetParent(label.transform, false); // CanvasRenderer cursorR.AddComponent <CanvasRenderer>(); // RectTransform var cursorRRt = cursorR.AddComponent <RectTransform>(); cursorRRt.sizeDelta = new Vector2(164f, 119f); cursorRRt.pivot = new Vector2(0.5f, 0.5f); cursorRRt.anchorMin = new Vector2(1f, 0.5f); cursorRRt.anchorMax = new Vector2(1f, 0.5f); cursorRRt.anchoredPosition = new Vector2(65f, 0f); cursorRRt.localScale = new Vector3(-0.4f, 0.4f, 0.4f); // Animator var cursorRAnimator = cursorR.AddComponent <Animator>(); cursorRAnimator.runtimeAnimatorController = MenuResources.MenuCursorAnimator; cursorRAnimator.updateMode = AnimatorUpdateMode.UnscaledTime; cursorRAnimator.applyRootMotion = false; // Image cursorR.AddComponent <Image>(); // Post Component Config menuButton.rightCursor = cursorRAnimator; // FlashEffect object var flash = new GameObject("FlashEffect"); GameObject.DontDestroyOnLoad(flash); flash.transform.SetParent(label.transform, false); // CanvasRenderer flash.AddComponent <CanvasRenderer>(); // RectTransform var flashRt = flash.AddComponent <RectTransform>(); flashRt.sizeDelta = new Vector2(0f, 0f); flashRt.anchorMin = new Vector2(0f, 0f); flashRt.anchorMax = new Vector2(1f, 1f); flashRt.anchoredPosition = new Vector2(0f, 0f); flashRt.pivot = new Vector2(0.5f, 0.5f); // Image flash.AddComponent <Image>(); // Animator var flashAnimator = flash.AddComponent <Animator>(); flashAnimator.runtimeAnimatorController = MenuResources.MenuButtonFlashAnimator; flashAnimator.updateMode = AnimatorUpdateMode.UnscaledTime; flashAnimator.applyRootMotion = false; // Post Component Config menuButton.flashEffect = flashAnimator; // Description if (config.Description is DescriptionInfo descInfo) { var descStyle = descInfo.Style ?? DescriptionStyle.MenuButtonSingleLineVanillaStyle; var description = new GameObject("Description"); GameObject.DontDestroyOnLoad(description); description.transform.SetParent(option.transform, false); // CanvasRenderer description.AddComponent <CanvasRenderer>(); // RectTransform var rt = description.AddComponent <RectTransform>(); RectTransformData.FromSizeAndPos( descStyle.Size, new AnchoredPosition(new Vector2(0.5f, 0), new Vector2(0.5f, 1)) ).Apply(rt); // Animator var anim = description.AddComponent <Animator>(); anim.runtimeAnimatorController = MenuResources.TextHideShowAnimator; anim.updateMode = AnimatorUpdateMode.UnscaledTime; anim.applyRootMotion = false; // Text var descText = description.AddComponent <Text>(); descText.font = MenuResources.Perpetua; descText.fontSize = descStyle.TextSize; descText.resizeTextMaxSize = descStyle.TextSize; descText.alignment = descStyle.TextAnchor; descText.text = descInfo.Text; descText.supportRichText = true; descText.verticalOverflow = VerticalWrapMode.Overflow; descText.horizontalOverflow = HorizontalWrapMode.Wrap; // Post Component Config menuButton.descriptionText = anim; } button = menuButton; return(content); }
/// <summary> /// Creates a menu button. /// </summary> /// <param name="content">The <c>ContentArea</c> to put the button in.</param> /// <param name="name">The name of the button game object.</param> /// <param name="config">The configuration options for the menu button.</param> /// <returns></returns> public static ContentArea AddMenuButton( this ContentArea content, string name, MenuButtonConfig config ) => content.AddMenuButton(name, config, out _);
/// <summary> /// Creates a scrollable window.<br/> /// The scrolling content will be the same width as the parent. /// </summary> /// <param name="content">The <c>ContentArea</c> to put the scrollable window in.</param> /// <param name="config">The configuration options for the scrollbar.</param> /// <param name="contentHeight">The height of the scroll window.</param> /// <param name="layout">The layout to apply to the added content.</param> /// <param name="action">The action that will get called to add the content.</param> /// <param name="scrollContent">The created scrollable window game object.</param> /// <param name="scroll">The <c>Scrollbar</c> component on the created scrollbar.</param> /// <returns></returns> public static ContentArea AddScrollPaneContent( this ContentArea content, ScrollbarConfig config, RelLength contentHeight, IContentLayout layout, Action <ContentArea> action, out GameObject scrollContent, out Scrollbar scroll ) { // Scrollbar content.AddScrollbar(config, out scroll); // ScrollMask var scrollMask = new GameObject("ScrollMask"); GameObject.DontDestroyOnLoad(scrollMask); scrollMask.transform.SetParent(content.ContentObject.transform, false); // RectTransform var scrollMaskRt = scrollMask.AddComponent <RectTransform>(); scrollMaskRt.sizeDelta = new Vector2(0f, 0f); scrollMaskRt.pivot = new Vector2(0.5f, 0.5f); scrollMaskRt.anchorMin = new Vector2(0f, 0f); scrollMaskRt.anchorMax = new Vector2(1f, 1f); scrollMaskRt.anchoredPosition = new Vector2(0f, 0f); // CanvasRenderer scrollMask.AddComponent <CanvasRenderer>(); // Mask var mask = scrollMask.AddComponent <Mask>(); mask.showMaskGraphic = false; // Image var maskImage = scrollMask.AddComponent <Image>(); maskImage.raycastTarget = false; // Scrolling Pane var scrollPane = new GameObject("ScrollingPane"); GameObject.DontDestroyOnLoad(scrollPane); scrollPane.transform.SetParent(scrollMask.transform, false); // RectTransform var scrollPaneRt = scrollPane.AddComponent <RectTransform>(); RectTransformData.FromSizeAndPos( new RelVector2(new RelLength(0f, 1f), contentHeight), new AnchoredPosition(new Vector2(0.5f, 1f), new Vector2(0.5f, 1f)) ).Apply(scrollPaneRt); // CanvasRenderer scrollPane.AddComponent <CanvasRenderer>(); action(new ContentArea( scrollPane, layout, new ScrollMovingNavGraph { Inner = content.NavGraph, Scrollbar = scroll, ScrollPaneTransform = scrollPaneRt, SelectionPadding = config.SelectionPadding ?? (_ => (0, 0)) }
/// <summary> /// Creates a horizontal option. /// </summary> /// <param name="content">The <c>ContentArea</c> to put the option in.</param> /// <param name="name">The name of the option game object.</param> /// <param name="config">The configuration options for the horizontal option.</param> /// <param name="horizontalOption">The <c>MenuOptionHorizontal</c> component on the created horizontal option.</param> /// <returns></returns> public static ContentArea AddHorizontalOption( this ContentArea content, string name, HorizontalOptionConfig config, out MenuOptionHorizontal horizontalOption ) { var style = config.Style ?? HorizontalOptionStyle.VanillaStyle; // Option object var option = new GameObject($"{name}"); GameObject.DontDestroyOnLoad(option); option.transform.SetParent(content.ContentObject.transform, false); // CanvasRenderer option.AddComponent <CanvasRenderer>(); // RectTransform var optionRt = option.AddComponent <RectTransform>(); style.Size.GetBaseTransformData().Apply(optionRt); content.Layout.ModifyNext(optionRt); // MenuOptionHorizontal var menuOptionHorizontal = option.AddComponent <MenuOptionHorizontal>(); menuOptionHorizontal.optionList = config.Options; menuOptionHorizontal.applySettingOn = MenuOptionHorizontal.ApplyOnType.Scroll; menuOptionHorizontal.cancelAction = (CancelAction)Patch.CancelAction.CustomCancelAction; ((Patch.MenuSelectable)(MenuSelectable) menuOptionHorizontal).customCancelAction = config.CancelAction; content.NavGraph.AddNavigationNode(menuOptionHorizontal); // MenuSetting var menuSetting = (Patch.MenuSetting)option.AddComponent <MenuSetting>(); menuSetting.settingType = (MenuSetting.MenuSettingType)Patch.MenuSetting.MenuSettingType.CustomSetting; menuSetting.customApplySetting = config.ApplySetting; menuSetting.customRefreshSetting = config.RefreshSetting; menuSetting.optionList = menuOptionHorizontal; // Post Component Config menuOptionHorizontal.menuSetting = menuSetting; // Label object var label = new GameObject("Label"); GameObject.DontDestroyOnLoad(label); label.transform.SetParent(option.transform, false); // CanvasRenderer label.AddComponent <CanvasRenderer>(); // RectTransform var labelRt = label.AddComponent <RectTransform>(); // the RectTransform that TC uses is utter garbage and imo this make far more sense labelRt.sizeDelta = new Vector2(0f, 0f); // this makes sense if you think about it labelRt.pivot = new Vector2(0.5f, 0.5f); labelRt.anchorMin = new Vector2(0f, 0f); labelRt.anchorMax = new Vector2(1f, 1f); labelRt.anchoredPosition = new Vector2(0f, 0f); // Text var labelText = label.AddComponent <Text>(); labelText.font = MenuResources.TrajanBold; labelText.fontSize = style.LabelTextSize; labelText.resizeTextMaxSize = style.LabelTextSize; labelText.alignment = TextAnchor.MiddleLeft; labelText.text = config.Label; labelText.supportRichText = true; labelText.verticalOverflow = VerticalWrapMode.Overflow; labelText.horizontalOverflow = HorizontalWrapMode.Overflow; // FixVerticalAlign label.AddComponent <FixVerticalAlign>(); // Text object var optionText = new GameObject("Text"); GameObject.DontDestroyOnLoad(optionText); optionText.transform.SetParent(option.transform, false); // CanvasRenderer optionText.AddComponent <CanvasRenderer>(); // RectTransform var optionTextRt = optionText.AddComponent <RectTransform>(); optionTextRt.sizeDelta = new Vector2(0f, 0f); // this makes sense if you think about it optionTextRt.pivot = new Vector2(0.5f, 0.5f); optionTextRt.anchorMin = new Vector2(0f, 0f); optionTextRt.anchorMax = new Vector2(1f, 1f); optionTextRt.anchoredPosition = new Vector2(0f, 0f); // Text var optionTextText = optionText.AddComponent <Text>(); optionTextText.font = MenuResources.TrajanRegular; optionTextText.fontSize = style.ValueTextSize; optionTextText.resizeTextMaxSize = style.ValueTextSize; optionTextText.alignment = TextAnchor.MiddleRight; optionTextText.text = config.Label; optionTextText.supportRichText = true; optionTextText.verticalOverflow = VerticalWrapMode.Overflow; optionTextText.horizontalOverflow = HorizontalWrapMode.Overflow; // FixVerticalAlign optionText.AddComponent <FixVerticalAlign>(); // Post Component Config menuOptionHorizontal.optionText = optionTextText; // LeftCursor object var cursorL = new GameObject("CursorLeft"); GameObject.DontDestroyOnLoad(cursorL); cursorL.transform.SetParent(option.transform, false); // CanvasRenderer cursorL.AddComponent <CanvasRenderer>(); // RectTransform var cursorLRt = cursorL.AddComponent <RectTransform>(); cursorLRt.sizeDelta = new Vector2(164f, 119f); cursorLRt.pivot = new Vector2(0.5f, 0.5f); cursorLRt.anchorMin = new Vector2(0f, 0.5f); cursorLRt.anchorMax = new Vector2(0f, 0.5f); cursorLRt.anchoredPosition = new Vector2(-70f, 0f); cursorLRt.localScale = new Vector3(0.4f, 0.4f, 0.4f); // Animator var cursorLAnimator = cursorL.AddComponent <Animator>(); cursorLAnimator.runtimeAnimatorController = MenuResources.MenuCursorAnimator; cursorLAnimator.updateMode = AnimatorUpdateMode.UnscaledTime; cursorLAnimator.applyRootMotion = false; // Image cursorL.AddComponent <Image>(); // Post Component Config menuOptionHorizontal.leftCursor = cursorLAnimator; // RightCursor object var cursorR = new GameObject("CursorRight"); GameObject.DontDestroyOnLoad(cursorR); cursorR.transform.SetParent(option.transform, false); // CanvasRenderer cursorR.AddComponent <CanvasRenderer>(); // RectTransform var cursorRRt = cursorR.AddComponent <RectTransform>(); cursorRRt.sizeDelta = new Vector2(164f, 119f); cursorRRt.pivot = new Vector2(0.5f, 0.5f); cursorRRt.anchorMin = new Vector2(1f, 0.5f); cursorRRt.anchorMax = new Vector2(1f, 0.5f); cursorRRt.anchoredPosition = new Vector2(70f, 0f); cursorRRt.localScale = new Vector3(-0.4f, 0.4f, 0.4f); // Animator var cursorRAnimator = cursorR.AddComponent <Animator>(); cursorRAnimator.runtimeAnimatorController = MenuResources.MenuCursorAnimator; cursorRAnimator.updateMode = AnimatorUpdateMode.UnscaledTime; cursorRAnimator.applyRootMotion = false; // Image cursorR.AddComponent <Image>(); // Post Component Config menuOptionHorizontal.rightCursor = cursorRAnimator; // Description if (config.Description is DescriptionInfo descInfo) { var descStyle = descInfo.Style ?? DescriptionStyle.HorizOptionSingleLineVanillaStyle; var description = new GameObject("Description"); GameObject.DontDestroyOnLoad(description); description.transform.SetParent(option.transform, false); // CanvasRenderer description.AddComponent <CanvasRenderer>(); // RectTransform var rt = description.AddComponent <RectTransform>(); RectTransformData.FromSizeAndPos( descStyle.Size, new AnchoredPosition(new Vector2(0, 0), new Vector2(0, 1), new Vector2(60, 0)) ).Apply(rt); // Animator var anim = description.AddComponent <Animator>(); anim.runtimeAnimatorController = MenuResources.TextHideShowAnimator; anim.updateMode = AnimatorUpdateMode.UnscaledTime; anim.applyRootMotion = false; // Text var descText = description.AddComponent <Text>(); descText.font = MenuResources.Perpetua; descText.fontSize = descStyle.TextSize; descText.resizeTextMaxSize = descStyle.TextSize; descText.alignment = descStyle.TextAnchor; descText.text = descInfo.Text; descText.supportRichText = true; descText.verticalOverflow = VerticalWrapMode.Overflow; descText.horizontalOverflow = HorizontalWrapMode.Wrap; // Post Component Config menuOptionHorizontal.descriptionText = anim; } horizontalOption = menuOptionHorizontal; return(content); }
/// <summary> /// Creates a horizontal option. /// </summary> /// <param name="content">The <c>ContentArea</c> to put the option in.</param> /// <param name="name">The name of the option game object.</param> /// <param name="config">The configuration options for the horizontal option.</param> /// <returns></returns> public static ContentArea AddHorizontalOption( this ContentArea content, string name, HorizontalOptionConfig config ) => content.AddHorizontalOption(name, config, out _);