public void DrawToolTips(SpriteBatch b)
        {
            //  Draw tooltips on the hovered item inside the bag
            if (HoveredSlot.HasValue)
            {
                Object HoveredItem = GetHoveredItem();
                if (HoveredItem != null)
                {
                    Rectangle Location;
                    if (IsNavigatingWithGamepad)
                    {
                        Location = HoveredSlot.Value; //new Rectangle(HoveredSlot.Value.Right, HoveredSlot.Value.Bottom, 1, 1);
                    }
                    else
                    {
                        Location = new Rectangle(Game1.getMouseX() - 8, Game1.getMouseY() + 36, 8 + 36, 1);
                    }
                    DrawHelpers.DrawToolTipInfo(b, Location, HoveredItem, true, true, true, true, true, true, Bag.MaxStackSize);
                }
            }

            //  Draw tooltips on the sidebar buttons
            if (IsRightSidebarVisible && HoveredContentsButton.HasValue)
            {
                string ButtonToolTip = "";
                if (HoveredContentsButton.Value == ContentsSidebarButton.SortingProperty)
                {
                    ButtonToolTip = ItemBagsMod.Translate(string.Format("RucksackSortProperty{0}ToolTip", Rucksack.SortProperty.ToString()));
                }
                else if (HoveredContentsButton.Value == ContentsSidebarButton.SortingOrder)
                {
                    if (Rucksack.SortOrder == SortingOrder.Ascending)
                    {
                        ButtonToolTip = ItemBagsMod.Translate("RucksackSortOrderAscendingToolTip");
                    }
                    else if (Rucksack.SortOrder == SortingOrder.Descending)
                    {
                        ButtonToolTip = ItemBagsMod.Translate("RucksackSortOrderDescendingToolTip");
                    }
                }

                if (!string.IsNullOrEmpty(ButtonToolTip))
                {
                    int     Margin      = 16;
                    Vector2 ToolTipSize = Game1.smallFont.MeasureString(ButtonToolTip);
                    DrawHelpers.DrawBox(b, HoveredContentsButtonBounds.Value.Left - (int)(ToolTipSize.X + Margin * 2), HoveredContentsButtonBounds.Value.Top, (int)(ToolTipSize.X + Margin * 2), (int)(ToolTipSize.Y + Margin * 2));
                    b.DrawString(Game1.smallFont, ButtonToolTip, new Vector2(HoveredContentsButtonBounds.Value.Left - Margin - ToolTipSize.X, HoveredContentsButtonBounds.Value.Top + Margin), Color.Black);
                }
            }
        }
Exemple #2
0
        public void Draw(SpriteBatch b)
        {
            Color     HighlightColor = Color.Yellow;
            Texture2D Highlight      = TextureHelpers.GetSolidColorTexture(Game1.graphics.GraphicsDevice, HighlightColor);

            DrawHelpers.DrawBox(b, Bounds);

            //  Draw preview image
            b.Draw(Game1.menuTexture, PreviewDestination, new Rectangle(128, 128, 64, 64), Color.White);
            ItemBag CurrentBag = HoveredSprite.HasValue ? PreviewBag : Bag;

            DrawHelpers.DrawItem(b, PreviewDestination, CurrentBag, false, false, 1f, 1f, Color.White, Color.White);

            //  Draw instructional text
            b.DrawString(InstructionFont, InstructionText, InstructionDestination, Color.Black, 0f, Vector2.Zero, InstructionScale, SpriteEffects.None, 1f);

            //  Draw spritesheet with all icons to choose from
            DrawHelpers.DrawBorder(b, new Rectangle(TextureDestination.Left - 2, TextureDestination.Top - 2, TextureDestination.Width + 4, TextureDestination.Height + 4), 2, Color.Black);
            b.Draw(Texture, TextureDestination, new Rectangle(0, 0, TextureWidth, TextureHeight), Color.White);
            if (HoveredSprite.HasValue)
            {
                Rectangle Destination = HoveredSprite.Value.GetOffseted(new Point(TextureDestination.X, TextureDestination.Y));
                b.Draw(Highlight, Destination, Color.White * 0.25f);
                int BorderThickness = Math.Max(2, HoveredSprite.Value.Width / SpriteSize);
                DrawHelpers.DrawBorder(b, Destination, BorderThickness, HighlightColor);
            }

            //  Draw buttons
            b.Draw(Game1.menuTexture, DefaultButtonDestination, new Rectangle(128, 128, 64, 64), Color.White);
            b.DrawString(ButtonFont, DefaultButtonText, DefaultButtonTextDestination, Color.Black, 0f, Vector2.Zero, ButtonFontScale, SpriteEffects.None, 1f);
            b.Draw(Game1.menuTexture, CloseButtonDestination, new Rectangle(128, 128, 64, 64), Color.White);
            b.DrawString(ButtonFont, CloseButtonText, CloseButtonTextDestination, Color.Black, 0f, Vector2.Zero, ButtonFontScale, SpriteEffects.None, 1f);
            if (HoveredButton.HasValue)
            {
                Rectangle Destination = HoveredButton.Value;
                b.Draw(Highlight, Destination, Color.White * 0.25f);
                int BorderThickness = Math.Max(2, HoveredButton.Value.Width / 16);
                DrawHelpers.DrawBorder(b, Destination, BorderThickness, HighlightColor);
            }
        }
Exemple #3
0
        private void Display_RenderedWorld(object sender, RenderedWorldEventArgs e)
        {
            if (Game1.activeClickableMenu == null)
            {
                GameLocation CurrentLocation = Game1.player.currentLocation;

                bool IsHoveringPlacedObject = CurrentLocation.Objects.TryGetValue(HoveredTile, out SObject HoveredObject);
                if (IsHoveringPlacedObject)
                {
                    if (UserConfig.DrawToolTip)
                    {
                        //  Draw a tooltip that shows how many of the machine were combined, and its total combined processing power
                        //  Such as: "Quantity: 5\nPower: 465%"
                        if (HoveredObject.TryGetCombinedQuantity(out int CombinedQuantity))
                        {
                            float UIScaleFactor = Game1.options.zoomLevel / Game1.options.uiScale;

                            SpriteFont DefaultFont          = Game1.dialogueFont;
                            int        Padding              = 25;
                            int        MarginBetweenColumns = 10;
                            int        MarginBetweenRows    = 5;
                            float      LabelTextScale       = 0.75f;
                            float      ValueTextScale       = 1.0f;

                            List <string> RowHeaders = new List <string>()
                            {
                                Helper.Translation.Get("ToolTipQuantityLabel"), Helper.Translation.Get("ToolTipPowerLabel")
                            };
                            List <Vector2> RowHeaderSizes = RowHeaders.Select(x => DefaultFont.MeasureString(x) * LabelTextScale).ToList();

                            double        ProcessingPower          = UserConfig.ComputeProcessingPower(CombinedQuantity) * 100.0;
                            string        FormattedProcessingPower = string.Format("{0}%", ProcessingPower.ToString("#.#"));
                            List <string> RowValues = new List <string>()
                            {
                                CombinedQuantity.ToString(), FormattedProcessingPower
                            };
                            List <Vector2> RowValueSizes = RowValues.Select(x => DrawHelpers.MeasureStringWithSpecialNumbers(x, ValueTextScale, 0.0f)).ToList();

                            //  Measure the tooltip
                            List <int> RowHeights = new List <int>();
                            for (int i = 0; i < RowHeaders.Count; i++)
                            {
                                RowHeights.Add((int)Math.Max(RowHeaderSizes[i].Y, RowValueSizes[i].Y));
                            }

                            List <int> ColumnWidths = new List <int> {
                                (int)RowHeaderSizes.Max(x => x.X),
                                (int)RowValueSizes.Max(x => x.X)
                            };

                            int   ToolTipTopWidth = Padding + ColumnWidths.Sum() + (ColumnWidths.Count - 1) * MarginBetweenColumns + Padding;
                            int   ToolTipHeight   = Padding + RowHeights.Sum() + (RowHeights.Count - 1) * MarginBetweenRows + Padding;
                            Point ToolTipTopleft  = DrawHelpers.GetTopleftPosition(new Point(ToolTipTopWidth, ToolTipHeight),
                                                                                   new Point((int)((MouseScreenPosition.X + UserConfig.ToolTipOffset.X) / UIScaleFactor), (int)((MouseScreenPosition.Y + UserConfig.ToolTipOffset.Y) / UIScaleFactor)), 100);

                            //  Draw tooltip background
                            DrawHelpers.DrawBox(e.SpriteBatch, new Rectangle(ToolTipTopleft.X, ToolTipTopleft.Y, ToolTipTopWidth, ToolTipHeight));

                            //  Draw each row's header and value
                            int CurrentY = ToolTipTopleft.Y + Padding;
                            for (int i = 0; i < RowHeights.Count; i++)
                            {
                                int CurrentRowHeight = RowHeights[i];

                                //  Draw the row header
                                Vector2 RowHeaderPosition = new Vector2(
                                    ToolTipTopleft.X + Padding + ColumnWidths[0] - RowHeaderSizes[i].X,
                                    CurrentY + (RowHeights[i] - RowHeaderSizes[i].Y) / 2.0f
                                    );
                                e.SpriteBatch.DrawString(DefaultFont, RowHeaders[i], RowHeaderPosition, Color.Black, 0.0f, Vector2.Zero, LabelTextScale, SpriteEffects.None, 1.0f);

                                //  Draw the row value
                                Vector2 RowValuePosition = new Vector2(
                                    ToolTipTopleft.X + Padding + ColumnWidths[0] + MarginBetweenColumns,
                                    CurrentY + (RowHeights[i] - RowValueSizes[i].Y) / 2.0f
                                    );
                                DrawHelpers.DrawStringWithSpecialNumbers(e.SpriteBatch, RowValuePosition, RowValues[i], ValueTextScale, Color.White);

                                CurrentY += CurrentRowHeight + MarginBetweenRows;
                            }
                        }
                    }
                }
            }
        }
Exemple #4
0
        private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            if (Game1.activeClickableMenu == null && PlacedAugmentorsManager.Instance != null)
            {
                GameLocation CurrentLocation = Game1.player.currentLocation;

                bool IsHoveringPlacedObject = CurrentLocation.Objects.TryGetValue(HoveredTile, out Object HoveredObject);
                if (IsHoveringPlacedObject)
                {
                    Dictionary <AugmentorType, int> AttachedAugmentors = PlacedAugmentorsManager.Instance.GetAugmentorQuantities(CurrentLocation.NameOrUniqueName, HoveredTile);
                    bool HasAttachedAugmentors = AttachedAugmentors.Any(x => x.Value > 0);
                    if (MachineInfo.TryGetMachineInfo(HoveredObject, out MachineInfo MI))
                    {
                        SpriteFont DefaultFont = Game1.dialogueFont;

                        //  Draw a tooltip showing what effects the held item will have when attached to this machine
                        if (Game1.player.CurrentItem is Augmentor HeldAugmentor && HeldAugmentor.IsAugmentable(HoveredObject))
                        {
                            AttachedAugmentors.TryGetValue(HeldAugmentor.AugmentorType, out int CurrentAttachedQuantity);

                            double CurrentEffect = CurrentAttachedQuantity <= 0 ?
                                                   Augmentor.GetDefaultEffect(HeldAugmentor.AugmentorType) : Augmentor.ComputeEffect(HeldAugmentor.AugmentorType, CurrentAttachedQuantity, MI.RequiresInput);
                            double NewEffectSingle = Augmentor.ComputeEffect(HeldAugmentor.AugmentorType, CurrentAttachedQuantity + 1, MI.RequiresInput);
                            double NewEffectAll    = Augmentor.ComputeEffect(HeldAugmentor.AugmentorType, CurrentAttachedQuantity + HeldAugmentor.Stack, MI.RequiresInput);

                            //  Example of desired tooltip:
                            //        -------------------------------------------
                            //        |          [Icon] Time to process:        |
                            //        |-----------------------------------------|
                            //        |  Current Effect: 95.5%                  |
                            //        |      New Effect: 92.2% (1) / 81.1% (4)  |
                            //        -------------------------------------------

                            int   Padding         = 28;
                            int   MarginAfterIcon = 10;
                            float LabelTextScale  = 0.75f;
                            float ValueTextScale  = 1.0f;

                            //  Compute sizes of each row so we know how big the tooltip is, and can horizontally center the header and other rows

                            //  Compute size of header
                            int HeaderHorizontalPadding = 4;
                            Augmentor.TryGetIconDetails(HeldAugmentor.AugmentorType, out Texture2D IconTexture, out Rectangle IconSourcePosition, out float IconScale, out SpriteEffects IconEffects);
                            Vector2 IconSize        = new Vector2(IconSourcePosition.Width * IconScale, IconSourcePosition.Height * IconScale);
                            string  HeaderText      = string.Format("{0}:", HeldAugmentor.GetEffectDescription());
                            Vector2 HeaderTextSize  = DefaultFont.MeasureString(HeaderText) * LabelTextScale;
                            float   HeaderRowWidth  = IconSize.X + MarginAfterIcon + HeaderTextSize.X + HeaderHorizontalPadding * 2;
                            float   HeaderRowHeight = Math.Max(IconSize.Y, HeaderTextSize.Y);

                            //  Compute size of horizontal separator
                            int HorizontalSeparatorHeight = 6;
                            int HorizontalSeparatorMargin = 8;

                            //  Compute size of the labels before the effect values
                            int     MarginAfterLabel       = 8;
                            string  CurrentEffectLabel     = string.Format("{0}:", Translate("CurrentEffectLabel"));
                            Vector2 CurrentEffectLabelSize = DefaultFont.MeasureString(CurrentEffectLabel) * LabelTextScale;
                            string  NewEffectLabel         = string.Format("{0}:", Translate("NewEffectLabel"));
                            Vector2 NewEffectLabelSize     = DefaultFont.MeasureString(NewEffectLabel) * LabelTextScale;
                            float   EffectLabelWidth       = Math.Max(CurrentEffectLabelSize.X, NewEffectLabelSize.X);
                            Vector2 EffectLabelSize        = new Vector2(EffectLabelWidth, CurrentEffectLabelSize.Y + NewEffectLabelSize.Y);

                            //  Compute size of the effect values
                            string  CurrentEffectValue     = string.Format("{0}% ({1})", (CurrentEffect * 100.0).ToString("0.##"), CurrentAttachedQuantity);
                            Vector2 CurrentEffectValueSize = DrawHelpers.MeasureStringWithSpecialNumbers(CurrentEffectValue, ValueTextScale, 0.0f);
                            string  NewEffectValue;
                            if (HeldAugmentor.Stack > 1)
                            {
                                NewEffectValue = string.Format("{0}% ({1}) / {2}% ({3})",
                                                               (NewEffectSingle * 100.0).ToString("0.##"), (CurrentAttachedQuantity + 1), (NewEffectAll * 100.0).ToString("0.##"), (CurrentAttachedQuantity + HeldAugmentor.Stack));
                            }
                            else
                            {
                                NewEffectValue = string.Format("{0}% ({1})", (NewEffectSingle * 100.0).ToString("0.##"), (CurrentAttachedQuantity + 1));
                            }
                            Vector2 NewEffectValueSize = DrawHelpers.MeasureStringWithSpecialNumbers(NewEffectValue, ValueTextScale, 0.0f);

                            Vector2 EffectContentSize = new Vector2(EffectLabelWidth + MarginAfterLabel + Math.Max(CurrentEffectValueSize.X, NewEffectValueSize.X),
                                                                    Math.Max(CurrentEffectLabelSize.Y, CurrentEffectValueSize.Y) + Math.Max(NewEffectLabelSize.Y, NewEffectValueSize.Y));

                            //  Compute total size of tooltip, draw the background
                            Vector2 ToolTipSize    = new Vector2(Padding * 2 + Math.Max(HeaderRowWidth, EffectContentSize.X), Padding + HeaderRowHeight + HorizontalSeparatorMargin + HorizontalSeparatorHeight + HorizontalSeparatorMargin + EffectContentSize.Y + Padding);
                            Point   ToolTipTopleft = DrawHelpers.GetTopleftPosition(new Point((int)ToolTipSize.X, (int)ToolTipSize.Y), MouseScreenPosition, 100);
                            DrawHelpers.DrawBox(e.SpriteBatch, new Rectangle(ToolTipTopleft.X, ToolTipTopleft.Y, (int)ToolTipSize.X, (int)ToolTipSize.Y));
                            float CurrentY = ToolTipTopleft.Y + Padding;

                            //  Draw the header
                            float   HeaderStartX = ToolTipTopleft.X + (ToolTipSize.X - HeaderRowWidth) / 2.0f;
                            Vector2 IconPosition = new Vector2(HeaderStartX, CurrentY + (HeaderRowHeight - IconSize.Y) / 2.0f);
                            e.SpriteBatch.Draw(IconTexture, IconPosition, IconSourcePosition, Color.White, 0f, Vector2.Zero, IconScale, IconEffects, 1f);
                            Vector2 HeaderTextPosition = new Vector2(HeaderStartX + IconSize.X + MarginAfterIcon, CurrentY + (HeaderRowHeight - HeaderTextSize.Y) / 2.0f);
                            e.SpriteBatch.DrawString(DefaultFont, HeaderText, HeaderTextPosition, Color.Black, 0.0f, Vector2.Zero, LabelTextScale, SpriteEffects.None, 1.0f);
                            CurrentY += HeaderRowHeight + HorizontalSeparatorMargin;

                            //  Draw the horizontal separator
                            DrawHelpers.DrawHorizontalSeparator(e.SpriteBatch, ToolTipTopleft.X + Padding, (int)CurrentY, (int)(ToolTipSize.X - 2 * Padding), HorizontalSeparatorHeight);
                            CurrentY += HorizontalSeparatorHeight + HorizontalSeparatorMargin;

                            //  Draw the current effect
                            Vector2 CurrentEffectLabelPosition = new Vector2(ToolTipTopleft.X + Padding + (EffectLabelWidth - CurrentEffectLabelSize.X), CurrentY);
                            Vector2 CurrentEffectValuePosition = new Vector2(ToolTipTopleft.X + Padding + EffectLabelWidth + MarginAfterLabel, CurrentY);
                            e.SpriteBatch.DrawString(DefaultFont, CurrentEffectLabel, CurrentEffectLabelPosition, Color.Black, 0.0f, Vector2.Zero, LabelTextScale, SpriteEffects.None, 1.0f);
                            DrawHelpers.DrawStringWithSpecialNumbers(e.SpriteBatch, CurrentEffectValuePosition, CurrentEffectValue, ValueTextScale, Color.White);
                            CurrentY += Math.Max(CurrentEffectLabelSize.Y, CurrentEffectValueSize.Y);

                            //  Draw the new effect
                            Vector2 NewEffectLabelPosition = new Vector2(ToolTipTopleft.X + Padding + (EffectLabelWidth - NewEffectLabelSize.X), CurrentY);
                            Vector2 NewEffectValuePosition = new Vector2(ToolTipTopleft.X + Padding + EffectLabelWidth + MarginAfterLabel, CurrentY);
                            e.SpriteBatch.DrawString(DefaultFont, NewEffectLabel, NewEffectLabelPosition, Color.Black, 0.0f, Vector2.Zero, LabelTextScale, SpriteEffects.None, 1.0f);
                            DrawHelpers.DrawStringWithSpecialNumbers(e.SpriteBatch, NewEffectValuePosition, NewEffectValue, ValueTextScale, Color.White);
                        }
                        //  Draw a tooltip showing what effects are currently applied to this machine
                        else if (HasAttachedAugmentors)
                        {
                            int Padding         = 28;
                            int MarginAfterIcon = 10;

                            //  Compute the size of each icon
                            Dictionary <AugmentorType, Vector2> IconSizes = new Dictionary <AugmentorType, Vector2>();
                            foreach (KeyValuePair <AugmentorType, int> KVP in AttachedAugmentors.Where(x => x.Value > 0))
                            {
                                Augmentor.TryGetIconDetails(KVP.Key, out Texture2D IconTexture, out Rectangle IconSourcePosition, out float IconScale, out SpriteEffects IconEffects);
                                Vector2 IconSize = new Vector2(IconSourcePosition.Width * IconScale, IconSourcePosition.Height * IconScale);
                                IconSizes.Add(KVP.Key, IconSize);
                            }
                            float IconColumnWidth = IconSizes.Values.Max(x => x.Y);

                            //  Compute the size of each row (each row shows the effect of a type of augmentor that has been applied to this machine)
                            Dictionary <AugmentorType, Vector2> RowSizes = new Dictionary <AugmentorType, Vector2>();
                            foreach (KeyValuePair <AugmentorType, int> KVP in AttachedAugmentors.Where(x => x.Value > 0))
                            {
                                double  CurrentEffect = Augmentor.ComputeEffect(KVP.Key, KVP.Value, MI.RequiresInput);
                                string  Text          = string.Format("{0}% ({1})", (CurrentEffect * 100.0).ToString("0.#"), KVP.Value);
                                Vector2 TextSize      = DrawHelpers.MeasureStringWithSpecialNumbers(Text, 1.0f, 4.0f);

                                float RowWidth  = IconColumnWidth + MarginAfterIcon + TextSize.X;
                                float RowHeight = Math.Max(IconSizes[KVP.Key].Y, TextSize.Y);
                                RowSizes.Add(KVP.Key, new Vector2(RowWidth, RowHeight));
                            }

                            //  Compute total size of tooltip, draw the background
                            Vector2 ToolTipSize    = new Vector2(Padding * 2 + RowSizes.Values.Max(x => x.X), Padding * 2 + RowSizes.Values.Sum(x => x.Y));
                            Point   ToolTipTopleft = DrawHelpers.GetTopleftPosition(new Point((int)ToolTipSize.X, (int)ToolTipSize.Y), MouseScreenPosition, 100);
                            DrawHelpers.DrawBox(e.SpriteBatch, new Rectangle(ToolTipTopleft.X, ToolTipTopleft.Y, (int)ToolTipSize.X, (int)ToolTipSize.Y));
                            float CurrentY = ToolTipTopleft.Y + Padding;

                            //  Draw each row
                            float RowStartX = ToolTipTopleft.X + Padding;
                            foreach (KeyValuePair <AugmentorType, int> KVP in AttachedAugmentors.Where(x => x.Value > 0))
                            {
                                float CurrentX  = RowStartX;
                                float RowHeight = RowSizes[KVP.Key].Y;

                                //  Draw the icon
                                Augmentor.TryGetIconDetails(KVP.Key, out Texture2D IconTexture, out Rectangle IconSourcePosition, out float IconScale, out SpriteEffects IconEffects);
                                Vector2 IconSize     = IconSizes[KVP.Key];
                                Vector2 IconPosition = new Vector2(CurrentX + (IconColumnWidth - IconSize.X) / 2.0f, CurrentY + (RowHeight - IconSize.Y) / 2.0f);
                                e.SpriteBatch.Draw(IconTexture, IconPosition, IconSourcePosition, Color.White, 0f, Vector2.Zero, IconScale, IconEffects, 1f);
                                CurrentX += IconColumnWidth + MarginAfterIcon;

                                //  Draw the value
                                double  CurrentEffect = Augmentor.ComputeEffect(KVP.Key, KVP.Value, MI.RequiresInput);
                                string  Text          = string.Format("{0}% ({1})", (CurrentEffect * 100.0).ToString("0.#"), KVP.Value);
                                Vector2 TextSize      = DrawHelpers.MeasureStringWithSpecialNumbers(Text, 1.0f, 0.0f);
                                Vector2 TextPosition  = new Vector2(CurrentX, CurrentY + (RowHeight - TextSize.Y) / 2.0f);
                                DrawHelpers.DrawStringWithSpecialNumbers(e.SpriteBatch, TextPosition, Text, 1.0f, Color.White);

                                CurrentY += RowHeight;
                            }

                            //Maybe also show MinutesUntilReady if it's not ReadyForHarvest?
                        }
                    }
                }
            }
        public override void drawTooltip(SpriteBatch spriteBatch, ref int x, ref int y, SpriteFont font, float alpha, StringBuilder overrideText)
        {
            //  If viewing this bag from a Shop, draw a custom tooltip that displays icons for each item the bag is capable of storing
            if (Game1.activeClickableMenu is ShopMenu)
            {
                int SlotSize = 32; // May want to try 48. 64 is probably too big especially for bags that can store a large # of different items
                int NumItems = SizeInfo.Items.Count;
                int Columns  = Math.Min(12, NumItems);
                int Rows     = NumItems == 0 ? 0 : (NumItems - 1) / Columns + 1;

                int TitleWidth    = (int)(font.MeasureString(this.DisplayName).X * 1.5) + 24; // Not sure if this is the correct scale and margin that the game's default rendering of the title bar uses
                int TextWidth     = (int)font.MeasureString(overrideText).X + 32;             // Do not change this 32, it's the additional margin that the game uses around the description text
                int ItemsMargin   = 24;
                int ItemsWidth    = SlotSize * Columns + ItemsMargin * 2;
                int RequiredWidth = Math.Max(Math.Max(TextWidth, TitleWidth), ItemsWidth);

                int MarginAfterDescription = 24;
                int RequiredHeight         = (int)font.MeasureString(overrideText).Y + MarginAfterDescription + Rows * SlotSize - 8 + (int)font.MeasureString("999").Y + 32;

                DrawHelpers.DrawBox(spriteBatch, new Rectangle(x, y, RequiredWidth, RequiredHeight));

                //  Draw the description text
                if (overrideText != null && !string.IsNullOrEmpty(overrideText.ToString()) && overrideText.ToString() != " ")
                {
                    spriteBatch.DrawString(font, overrideText, new Vector2((float)(x + 16), (float)(y + 16 + 4)) + new Vector2(2f, 2f), Game1.textShadowColor * alpha);
                    spriteBatch.DrawString(font, overrideText, new Vector2((float)(x + 16), (float)(y + 16 + 4)) + new Vector2(0f, 2f), Game1.textShadowColor * alpha);
                    spriteBatch.DrawString(font, overrideText, new Vector2((float)(x + 16), (float)(y + 16 + 4)) + new Vector2(2f, 0f), Game1.textShadowColor * alpha);
                    spriteBatch.DrawString(font, overrideText, new Vector2((float)(x + 16), (float)(y + 16 + 4)), (Game1.textColor * 0.9f) * alpha);
                    y = y + (int)font.MeasureString(overrideText).Y;
                }

                //  Draw icons for each item that this bag is capable of storing
                y += MarginAfterDescription;
                int RowStartX    = x + (RequiredWidth - SlotSize * Columns) / 2;
                int CurrentX     = RowStartX;
                int CurrentIndex = 0;
                foreach (StoreableBagItem ItemInfo in SizeInfo.Items)
                {
                    if (CurrentIndex == Columns)
                    {
                        CurrentIndex = 0;
                        CurrentX     = RowStartX;
                        y           += SlotSize;
                    }

                    Object Item = ItemInfo.IsBigCraftable ?
                                  new Object(Vector2.Zero, ItemInfo.Id, false) :
                                  new Object(ItemInfo.Id, 0, false, -1, 0);

                    Rectangle Destination = new Rectangle(CurrentX, y, SlotSize, SlotSize);
                    spriteBatch.Draw(Game1.menuTexture, Destination, new Rectangle(128, 128, 64, 64), Color.White);
                    DrawHelpers.DrawItem(spriteBatch, Destination, Item, false, false, 1f, 1f, Color.White, Color.White);
                    CurrentX += SlotSize;
                    CurrentIndex++;
                }

                //  Finish filling in the current row with empty slots
                while (CurrentIndex < Columns)
                {
                    Rectangle Destination = new Rectangle(CurrentX, y, SlotSize, SlotSize);
                    spriteBatch.Draw(Game1.menuTexture, Destination, new Rectangle(64, 896, 64, 64), Color.White);
                    CurrentX += SlotSize;
                    CurrentIndex++;
                }

                y += SlotSize - 8;
            }
            else
            {
                base.drawTooltip(spriteBatch, ref x, ref y, font, alpha, overrideText);
            }
        }
        public void DrawToolTips(SpriteBatch b)
        {
            if (!IsJojaMember)
            {
                if (HoveredBundleItem != null)
                {
                    Object HoveredItem = GetHoveredItem();
                    if (HoveredItem != null)
                    {
                        Rectangle Location;
                        if (IsNavigatingWithGamepad)
                        {
                            Location = ItemSlotPositions[HoveredBundleItem].GetOffseted(TopLeftScreenPosition);
                        }
                        else
                        {
                            Location = new Rectangle(Game1.getMouseX() - 8, Game1.getMouseY() + 36, 8 + 36, 1);
                        }
                        DrawHelpers.DrawToolTipInfo(b, Location, HoveredItem, true, true, true, true, true, true,
                                                    HoveredBundleItem.Quantity, !HoveredBundleItem.IsCompleted, Color.White);
                    }
                }

                if (HoveredBundleTask != null)
                {
                    Rectangle ToolTipAnchorPoint = TaskHeaderPositions[HoveredBundleTask].GetOffseted(TopLeftScreenPosition);

                    int Padding        = 20;
                    int TaskImageSize  = 96;
                    int RewardIconSize = 48;
                    int RewardWidth    = RewardIconSize + 12 + RewardIconSize;

                    //  Compute header
                    SpriteFont HeaderFont  = Game1.dialogueFont;
                    float      HeaderScale = 1f;
                    string     HeaderText  = !string.IsNullOrEmpty(HoveredBundleTask.TranslatedName) ? HoveredBundleTask.TranslatedName : HoveredBundleTask.Name + " Bundle";
                    Vector2    HeaderSize  = HeaderFont.MeasureString(HeaderText) * HeaderScale;

                    //  Compute description
                    int ReadyToComplete = 0;
                    foreach (BundleItem BI in HoveredBundleTask.Items)
                    {
                        if (!BI.IsCompleted && ItemPlaceholders.TryGetValue(BI, out Object Placeholder) && Placeholder.Stack >= BI.Quantity)
                        {
                            ReadyToComplete++;
                        }
                    }
                    SpriteFont BodyFont  = Game1.smallFont;
                    float      BodyScale = 1.0f;
                    string     BodyText  = HoveredBundleTask.IsCompleted ? ItemBagsMod.Translate("BundleTaskCompletedToolTip") :
                                           ItemBagsMod.Translate("BundleTaskIncompleteToolTip", new Dictionary <string, string>()
                    {
                        { "CompletedCount", HoveredBundleTask.Items.Count(x => x.IsCompleted).ToString() },
                        { "TotalCount", HoveredBundleTask.Items.Count.ToString() },
                        { "ReadyToCompleteCount", ReadyToComplete.ToString() },
                        { "RequiredCount", HoveredBundleTask.RequiredItemCount.ToString() }
                    });
                    Vector2 BodySize = BodyFont.MeasureString(BodyText) * BodyScale;

                    int ToolTipWidth = (int)new List <float>()
                    {
                        TaskImageSize, HeaderSize.X, BodySize.X, RewardWidth
                    }.Max() + Padding * 2;
                    int ToolTipHeight = Padding + TaskImageSize + 16 + (int)HeaderSize.Y + 12 + (int)BodySize.Y + 12 + RewardIconSize + Padding;

                    //  Ensure tooltip is fully visible on screen
                    Rectangle Position = new Rectangle(ToolTipAnchorPoint.Right, ToolTipAnchorPoint.Top, ToolTipWidth, ToolTipHeight);
                    if (Position.Right > Game1.viewport.Size.Width)
                    {
                        Position = new Rectangle(ToolTipAnchorPoint.Left - ToolTipWidth, Position.Top, Position.Width, Position.Height);
                    }
                    if (Position.Bottom > Game1.viewport.Size.Height)
                    {
                        Position = new Rectangle(Position.X, ToolTipAnchorPoint.Bottom - ToolTipHeight, Position.Width, Position.Height);
                    }

                    DrawHelpers.DrawBox(b, Position);

                    int CurrentY = Position.Y + Padding;

                    //  Draw image associated with this task
                    Rectangle TaskImagePosition = new Rectangle(Position.X + (Position.Width - TaskImageSize) / 2, CurrentY, TaskImageSize, TaskImageSize);
                    DrawHelpers.DrawBorder(b, new Rectangle(TaskImagePosition.Left - 4, TaskImagePosition.Top - 4, TaskImagePosition.Width + 8, TaskImagePosition.Height + 8), 4, Color.Black);
                    b.Draw(HoveredBundleTask.ActualLargeIconTexture, TaskImagePosition, HoveredBundleTask.ActualLargeIconPosition, Color.White);
                    CurrentY += TaskImageSize + 16;

                    //  Draw header text (Task's name)
                    Vector2 HeaderPosition = new Vector2(Position.X + (Position.Width - HeaderSize.X) / 2, CurrentY);
                    b.DrawString(HeaderFont, HeaderText, HeaderPosition, Color.Black, 0f, Vector2.Zero, HeaderScale, SpriteEffects.None, 1f);
                    CurrentY += (int)(HeaderSize.Y + 12);

                    //  Draw description text
                    Vector2 BodyPosition = new Vector2(Position.X + (Position.Width - BodySize.X) / 2, CurrentY);
                    b.DrawString(BodyFont, BodyText, BodyPosition, Color.SlateGray, 0f, Vector2.Zero, BodyScale, SpriteEffects.None, 1f);
                    CurrentY += (int)(BodySize.Y + 12);

                    //  Draw reward item
                    Rectangle RewardPosition = new Rectangle(Position.X + (Position.Width - RewardWidth) / 2, CurrentY, RewardWidth, RewardIconSize);
                    b.Draw(TextureHelpers.JunimoNoteTexture, new Rectangle(RewardPosition.X, RewardPosition.Y, RewardIconSize, RewardIconSize), new Rectangle(548, 264, 18, 18), Color.White);
                    if (HoveredBundleTask.Reward != null)
                    {
                        DrawHelpers.DrawItem(b, new Rectangle(RewardPosition.Right - RewardIconSize, RewardPosition.Y, RewardIconSize, RewardIconSize), HoveredBundleTask.Reward.ToItem(), true, true, 1f, 1f, Color.White, Color.White);
                    }
                }
            }
        }
        public void Draw(SpriteBatch b)
        {
            if (IsJojaMember)
            {
                Rectangle BackgroundDestination = new Rectangle(Padding, Padding, RelativeBounds.Width - Padding * 2, RelativeBounds.Height - Padding * 2).GetOffseted(TopLeftScreenPosition);
                b.Draw(TextureHelpers.JojaCDForm, BackgroundDestination, new Rectangle(0, 0, TextureHelpers.JojaCDForm.Width, TextureHelpers.JojaCDForm.Height - 16), Color.White);

                string     Text     = "You Traitor!";
                SpriteFont Font     = Game1.smallFont;
                Vector2    TextSize = Font.MeasureString(Text) * 2;

                int JojaSuxDestinationSize = 128;

                int BoxPadding = 32;
                int BoxWidth   = Math.Max((int)TextSize.X, JojaSuxDestinationSize) + BoxPadding * 2;
                int BoxHeight  = (int)TextSize.Y + BoxPadding * 2 + JojaSuxDestinationSize - JojaSuxDestinationSize / 8;

                Rectangle BoxDestination = new Rectangle((RelativeBounds.Width - BoxWidth) / 2, (RelativeBounds.Height - BoxHeight) / 2,
                                                         BoxWidth, BoxHeight).GetOffseted(TopLeftScreenPosition);
                DrawHelpers.DrawBox(b, BoxDestination);

                Vector2 TextDestination = new Vector2(BoxDestination.X + (BoxDestination.Width - TextSize.X) / 2, BoxDestination.Y + BoxPadding);
                b.DrawString(Font, Text, TextDestination, Color.Black, 0f, Vector2.Zero, 2f, SpriteEffects.None, 1f);

                Rectangle JojaSuxSourcePosition = new Rectangle(258, 640, 32, 32);
                Rectangle JojaSuxDestination    = new Rectangle(BoxDestination.X + (BoxDestination.Width - JojaSuxDestinationSize) / 2, BoxDestination.Bottom - BoxPadding - JojaSuxDestinationSize, JojaSuxDestinationSize, JojaSuxDestinationSize);
                b.Draw(Game1.mouseCursors, JojaSuxDestination, JojaSuxSourcePosition, Color.White);
            }
            else
            {
                //  Draw room names
                foreach (KeyValuePair <BundleRoom, Rectangle> RoomHeader in RoomHeaderPositions)
                {
                    bool      IsCompleted = RoomHeader.Key.IsCompleted;
                    Rectangle Position    = RoomHeader.Value.GetOffseted(TopLeftScreenPosition);
                    DrawHelpers.DrawBox(b, Position);

                    string  Text = RoomHeader.Key.DisplayName;
                    Vector2 Size = RoomHeaderFont.MeasureString(Text) * RoomHeaderScale;
                    b.DrawString(RoomHeaderFont, Text, new Vector2(Position.X + (Position.Width - Size.X) / 2, Position.Y + (Position.Height - Size.Y) / 2),
                                 IsCompleted ? Color.Green : Color.Black, 0f, Vector2.Zero, RoomHeaderScale, SpriteEffects.None, 1f);

                    if (IsCompleted)
                    {
                        Rectangle CheckMarkDestination = new Rectangle(Position.Right - SlotSize / 6 - CheckMark.Width * CheckMarkScale, Position.Bottom - SlotSize / 6 - CheckMark.Height * CheckMarkScale,
                                                                       CheckMark.Width * CheckMarkScale, CheckMark.Height * CheckMarkScale);
                        b.Draw(TextureHelpers.PlayerStatusList, CheckMarkDestination, CheckMark, Color.White);
                    }
                }

                //  Draw the backgrounds of each slot
                foreach (Rectangle LockedSlot in LockedSlotPositions)
                {
                    b.Draw(Game1.menuTexture, LockedSlot.GetOffseted(TopLeftScreenPosition), new Rectangle(64, 896, 64, 64), Color.White);
                }
                foreach (KeyValuePair <BundleItem, Rectangle> ItemSlot in ItemSlotPositions)
                {
                    Rectangle TexturePosition;
                    if (ItemSlot.Key.IsCompleted)
                    {
                        TexturePosition = SlotDarkBackground;
                    }
                    else
                    {
                        Object Item = ItemPlaceholders[ItemSlot.Key];
                        if (Item.Stack == 0)
                        {
                            TexturePosition = SlotLightBackground;
                        }
                        else if (Item.Stack == ItemSlot.Key.Quantity)
                        {
                            TexturePosition = SlotDarkBackground;
                        }
                        else
                        {
                            TexturePosition = SlotMediumBackground;
                        }
                    }

                    b.Draw(TextureHelpers.JunimoNoteTexture, ItemSlot.Value.GetOffseted(TopLeftScreenPosition), TexturePosition, Color.White);
                }
                foreach (KeyValuePair <BundleTask, Rectangle> TaskHeader in TaskHeaderPositions)
                {
                    Rectangle TexturePosition = SlotMediumBackground;
                    if (TaskHeader.Key.IsCompleted)
                    {
                        TexturePosition = SlotDarkBackground;
                    }
                    b.Draw(TextureHelpers.JunimoNoteTexture, TaskHeader.Value.GetOffseted(TopLeftScreenPosition), TexturePosition, Color.White);
                }

                //  Draw the Task headers
                foreach (KeyValuePair <BundleTask, Rectangle> TaskHeader in TaskHeaderPositions)
                {
                    bool IsCompleted = TaskHeader.Key.IsCompleted;

                    //  Draw a thin yellow border if mouse is hovering this slot
                    bool IsHovered = TaskHeader.Key == HoveredBundleTask;
                    if (IsHovered)
                    {
                        Rectangle Destination = TaskHeader.Value.GetOffseted(TopLeftScreenPosition);

                        Color     HighlightColor = Color.Yellow;
                        Texture2D Highlight      = TextureHelpers.GetSolidColorTexture(Game1.graphics.GraphicsDevice, HighlightColor);
                        b.Draw(Highlight, Destination, Color.White * 0.25f);

                        int BorderThickness = Destination.Width / 16;
                        DrawHelpers.DrawBorder(b, Destination, BorderThickness, HighlightColor);
                    }

                    Rectangle Slot               = TaskHeader.Value;
                    Rectangle ScaledSlot         = new Rectangle(Slot.X + Slot.Width / 6, Slot.Y + Slot.Height / 6, Slot.Width - Slot.Width / 3, Slot.Height - Slot.Height / 3);
                    Rectangle SourceIconPosition = IsCompleted ? TaskHeader.Key.SpriteSmallIconOpenedPosition : TaskHeader.Key.SpriteSmallIconClosedPosition;
                    b.Draw(TextureHelpers.JunimoNoteTexture, ScaledSlot.GetOffseted(TopLeftScreenPosition), SourceIconPosition, Color.White);

                    if (IsCompleted)
                    {
                        Rectangle CheckMarkDestination = new Rectangle(Slot.Right - 1 - CheckMark.Width * CheckMarkScale, Slot.Bottom - 1 - CheckMark.Height * CheckMarkScale,
                                                                       CheckMark.Width * CheckMarkScale, CheckMark.Height * CheckMarkScale).GetOffseted(TopLeftScreenPosition);
                        b.Draw(TextureHelpers.PlayerStatusList, CheckMarkDestination, CheckMark, Color.White);
                    }
                }

                //  Draw the items of each slot
                foreach (KeyValuePair <BundleItem, Rectangle> ItemSlot in ItemSlotPositions)
                {
                    Rectangle Destination = ItemSlot.Value.GetOffseted(TopLeftScreenPosition);
                    Object    CurrentItem;
                    if (!ItemPlaceholders.TryGetValue(ItemSlot.Key, out CurrentItem))
                    {
                        CurrentItem = ItemSlot.Key.ToObject();
                    }

                    bool IsCompleted = ItemSlot.Key.IsCompleted;

                    //  Draw a thin yellow border if mouse is hovering this slot
                    bool IsHovered = ItemSlot.Key == HoveredBundleItem;
                    if (IsHovered)
                    {
                        Color     HighlightColor = Color.Yellow;
                        Texture2D Highlight      = TextureHelpers.GetSolidColorTexture(Game1.graphics.GraphicsDevice, HighlightColor);
                        b.Draw(Highlight, Destination, Color.White * 0.25f);

                        int BorderThickness = Destination.Width / 16;
                        DrawHelpers.DrawBorder(b, Destination, BorderThickness, HighlightColor);
                    }

                    float IconScale    = IsHovered ? 1.25f : 1.0f;
                    Color Overlay      = CurrentItem.Stack == 0 || IsCompleted ? Color.White * 0.30f : Color.White;
                    bool  DrawQuantity = CurrentItem.Stack > 0 && !IsCompleted && ItemSlot.Key.Quantity > 1;
                    DrawHelpers.DrawItem(b, Destination, CurrentItem, DrawQuantity, true, IconScale, 1.0f, Overlay,
                                         CurrentItem.Stack >= ItemSlot.Key.Quantity ? Color.Green : Color.White);

                    if (IsCompleted)
                    {
                        Rectangle CheckMarkDestination = new Rectangle(Destination.Right - 1 - CheckMark.Width * CheckMarkScale, Destination.Bottom - 1 - CheckMark.Height * CheckMarkScale,
                                                                       CheckMark.Width * CheckMarkScale, CheckMark.Height * CheckMarkScale);
                        b.Draw(TextureHelpers.PlayerStatusList, CheckMarkDestination, CheckMark, Color.White);
                    }
                }
            }
        }
Exemple #8
0
        public void DrawToolTips(SpriteBatch b)
        {
            if (IsEmptyMenu)
            {
                return;
            }

            //  Draw tooltip over hovered item
            if (HoveredSlot.HasValue)
            {
                //  Get the hovered Item Id and ColumnType
                int?       ItemId = null;
                ColumnType?Column = null;
                foreach (var KVP in SlotBounds)
                {
                    foreach (var KVP2 in KVP.Value)
                    {
                        if (KVP2.Value == HoveredSlot.Value)
                        {
                            ItemId = KVP.Key;
                            Column = KVP2.Key;
                            break;
                        }
                    }

                    if (ItemId.HasValue && Column.HasValue)
                    {
                        break;
                    }
                }

                if (ItemId.HasValue && Column.HasValue)
                {
                    if (Column == ColumnType.RowValue)
                    {
                        List <Object> Items            = Placeholders[ItemId.Value].Values.ToList();
                        List <int>    Quantities       = Items.Select(x => x.Stack).ToList();
                        List <int>    SingleValues     = Items.Select(x => ItemBag.GetSingleItemPrice(x)).ToList();
                        List <int>    MultipliedValues = Items.Select(x => x.Stack * ItemBag.GetSingleItemPrice(x)).ToList();

                        //  Compute how many digits each column needs so that we can align each number properly by making each number take up the maximum size of other numbers in the same column
                        int   SingleValueColumnDigits     = SingleValues.Max(x => DrawHelpers.GetNumDigits(x));
                        int   QuantityColumnDigits        = Quantities.Max(x => DrawHelpers.GetNumDigits(x));
                        int   MultipliedValueColumnDigits = MultipliedValues.Max(x => DrawHelpers.GetNumDigits(x));
                        float DigitScale                 = 3.0f;
                        float SingleValueColumnWidth     = SingleValueColumnDigits * DigitScale * DrawHelpers.TinyDigitBaseWidth;
                        float QuantityColumnWidth        = QuantityColumnDigits * DigitScale * DrawHelpers.TinyDigitBaseWidth;
                        float MultipliedValueColumnWidth = MultipliedValueColumnDigits * DigitScale * DrawHelpers.TinyDigitBaseWidth;

                        //  Compute how big the tooltip needs to be
                        int   Margin     = 32;
                        int   LineHeight = 28;
                        int   HorizontalSeparatorHeight = 6;
                        int   SeparatorMargin           = 4;
                        float PlusCharacterWidth        = Game1.tinyFont.MeasureString("+").X;
                        float MultiplyCharacterWidth    = Game1.tinyFont.MeasureString("*").X;
                        float EqualsCharacterWidth      = Game1.tinyFont.MeasureString("=").X;
                        float SpaceWidth  = 7f;
                        int   TotalWidth  = (int)(Margin + PlusCharacterWidth + SpaceWidth + SingleValueColumnWidth + SpaceWidth + MultiplyCharacterWidth + SpaceWidth + QuantityColumnWidth + SpaceWidth + EqualsCharacterWidth + SpaceWidth + MultipliedValueColumnWidth + Margin);
                        int   TotalHeight = (int)(Margin + Items.Count * LineHeight + SeparatorMargin + HorizontalSeparatorHeight + SeparatorMargin + LineHeight + Margin);

                        //  Ensure tooltip is fully visible on screen
                        Rectangle ToolTipLocation = new Rectangle(HoveredSlot.Value.Right, HoveredSlot.Value.Top, TotalWidth, TotalHeight);
                        if (ToolTipLocation.Right > Game1.viewport.Size.Width)
                        {
                            ToolTipLocation = new Rectangle(HoveredSlot.Value.Left - TotalWidth, HoveredSlot.Value.Top, TotalWidth, TotalHeight);
                        }

                        //  Draw background
                        DrawHelpers.DrawBox(b, ToolTipLocation);

                        //  Draw each row of values
                        int ShadowOffset     = 2;
                        int CurrentYPosition = ToolTipLocation.Y + Margin;
                        for (int i = 0; i < Items.Count; i++)
                        {
                            float CurrentXPosition = ToolTipLocation.X + Margin;
                            if (i != 0)
                            {
                                DrawHelpers.DrawStringWithShadow(b, Game1.tinyFont, "+", CurrentXPosition, CurrentYPosition, Color.White, Color.Black, ShadowOffset, ShadowOffset);
                            }
                            CurrentXPosition += PlusCharacterWidth + SpaceWidth;
                            Utility.drawTinyDigits(SingleValues[i], b, new Vector2(CurrentXPosition + SingleValueColumnWidth - DrawHelpers.MeasureNumber(SingleValues[i], DigitScale), CurrentYPosition), DigitScale, 1.0f, Color.White);
                            CurrentXPosition += SingleValueColumnWidth + SpaceWidth;
                            DrawHelpers.DrawStringWithShadow(b, Game1.tinyFont, "*", CurrentXPosition, CurrentYPosition + LineHeight / 4, Color.White, Color.Black, ShadowOffset, ShadowOffset);
                            CurrentXPosition += MultiplyCharacterWidth + SpaceWidth;
                            Utility.drawTinyDigits(Quantities[i], b, new Vector2(CurrentXPosition + QuantityColumnWidth - DrawHelpers.MeasureNumber(Quantities[i], DigitScale), CurrentYPosition), DigitScale, 1.0f, Color.White);
                            CurrentXPosition += QuantityColumnWidth + SpaceWidth;
                            DrawHelpers.DrawStringWithShadow(b, Game1.tinyFont, "=", CurrentXPosition, CurrentYPosition - LineHeight / 6, Color.White, Color.Black, ShadowOffset, ShadowOffset);
                            CurrentXPosition += EqualsCharacterWidth + SpaceWidth;
                            Utility.drawTinyDigits(MultipliedValues[i], b, new Vector2(CurrentXPosition + MultipliedValueColumnWidth - DrawHelpers.MeasureNumber(MultipliedValues[i], DigitScale), CurrentYPosition), DigitScale, 1.0f, Color.White);

                            CurrentYPosition += LineHeight;
                        }

                        //  Draw separator
                        CurrentYPosition += SeparatorMargin;
                        DrawHelpers.DrawHorizontalSeparator(b, ToolTipLocation.X + Margin, CurrentYPosition, TotalWidth - Margin * 2, HorizontalSeparatorHeight);
                        CurrentYPosition += HorizontalSeparatorHeight + SeparatorMargin;

                        //  Draw total value
                        int       SummedValue         = MultipliedValues.Sum();
                        float     SummedValueWidth    = DrawHelpers.MeasureNumber(SummedValue, DigitScale) + GoldIconSourceRect.Width * 2f + 8;
                        Vector2   SummedValuePosition = new Vector2(ToolTipLocation.X + ((ToolTipLocation.Width - SummedValueWidth) / 2), CurrentYPosition + 6);
                        Rectangle IconDestination     = new Rectangle((int)SummedValuePosition.X, (int)(SummedValuePosition.Y + (DrawHelpers.TinyDigitBaseHeight * DigitScale - GoldIconSourceRect.Height * 2) / 2), GoldIconSourceRect.Width * 2, GoldIconSourceRect.Height * 2);
                        b.Draw(GoldIconTexture, IconDestination, GoldIconSourceRect, Color.White);
                        Utility.drawTinyDigits(SummedValue, b, new Vector2(SummedValuePosition.X + GoldIconSourceRect.Width * 2f + 8, SummedValuePosition.Y), DigitScale, 1.0f, GetValueColor(SummedValue));
                    }
                    else
                    {
                        Object    HoveredItem = Placeholders[ItemId.Value][ConvertColumnTypeToObjectQuality(Column.Value)];
                        Rectangle Location;
                        if (IsNavigatingWithGamepad)
                        {
                            Location = HoveredSlot.Value; //new Rectangle(HoveredSlot.Value.Right, HoveredSlot.Value.Bottom, 1, 1);
                        }
                        else
                        {
                            Location = new Rectangle(Game1.getMouseX() - 8, Game1.getMouseY() + 36, 8 + 36, 1);
                        }
                        DrawHelpers.DrawToolTipInfo(b, Location, HoveredItem, true, true, true, true, true, true, Bag.MaxStackSize);
                    }
                }
            }
        }
        private void Display_RenderedWorld(object sender, RenderedWorldEventArgs e)
        {
            if (Game1.activeClickableMenu == null)
            {
                GameLocation CurrentLocation = Game1.player.currentLocation;

                bool IsHoveringPlacedObject = CurrentLocation.Objects.TryGetValue(HoveredTile, out SObject HoveredObject);
                if (IsHoveringPlacedObject)
                {
                    if (UserConfig.DrawToolTip)
                    {
                        //  Draw a tooltip that shows how many of the machine were combined, and its total combined processing power
                        //  Such as: "Quantity: 5\nPower: 465%"
                        if (HoveredObject.TryGetCombinedQuantity(out int CombinedQuantity))
                        {
                            Cask    Cask        = HoveredObject as Cask;
                            bool    IsCask      = Cask != null;
                            CrabPot CrabPot     = HoveredObject as CrabPot;
                            bool    IsCrabPot   = CrabPot != null;
                            bool    IsScarecrow = HoveredObject.IsScarecrow();

                            bool HasHeldObject = HoveredObject.heldObject?.Value != null;

                            float UIScaleFactor = Game1.options.zoomLevel / Game1.options.uiScale;

                            SpriteFont DefaultFont          = Game1.dialogueFont;
                            int        Padding              = 25;
                            int        MarginBetweenColumns = 10;
                            int        MarginBetweenRows    = 5;
                            float      LabelTextScale       = 0.75f;
                            float      ValueTextScale       = 1.0f;

                            bool ShowDurationInfo = UserConfig.ToolTipShowDuration && UserConfig.ShouldModifyProcessingSpeed(HoveredObject);
                            bool ShowQuantityInfo = UserConfig.ToolTipShowQuantity && UserConfig.ShouldModifyInputsAndOutputs(HoveredObject);

                            //  Compute row headers
                            List <string> RowHeaders = new List <string>()
                            {
                                Helper.Translation.Get("ToolTipQuantityLabel"), Helper.Translation.Get("ToolTipPowerLabel")
                            };
                            if (ShowDurationInfo)
                            {
                                if (IsCask)
                                {
                                    //RowHeaders.Add(Helper.Translation.Get("ToolTipCaskAgingRateLabel"));
                                    if (HasHeldObject)
                                    {
                                        RowHeaders.Add(Helper.Translation.Get("ToolTipCaskDaysUntilIridiumLabel"));
                                    }
                                }
                                else if (IsCrabPot)
                                {
                                    RowHeaders.Add(Helper.Translation.Get("ToolTipCrabPotProcessingIntervalLabel"));
                                }
                                else
                                {
                                    if (HasHeldObject)
                                    {
                                        RowHeaders.Add(Helper.Translation.Get("ToolTipMinutesRemainingLabel"));
                                    }
                                }
                            }
                            if (ShowQuantityInfo)
                            {
                                if (HasHeldObject && HoveredObject.HasModifiedOutput())
                                {
                                    RowHeaders.Add(Helper.Translation.Get("ToolTipProducedQuantityLabel"));
                                }
                            }
                            if (IsScarecrow)
                            {
                                RowHeaders.Add(Helper.Translation.Get("ToolTipScarecrowRadiusLabel"));
                            }
                            List <Vector2> RowHeaderSizes = RowHeaders.Select(x => DefaultFont.MeasureString(x) * LabelTextScale).ToList();

                            double ProcessingPower          = UserConfig.ComputeProcessingPower(CombinedQuantity) * 100.0;
                            string FormattedProcessingPower = string.Format("{0}%", ProcessingPower.ToString("0.#"));

                            //  Compute row values
                            List <string> RowValues = new List <string>()
                            {
                                CombinedQuantity.ToString(), FormattedProcessingPower
                            };
                            if (ShowDurationInfo)
                            {
                                if (IsCask)
                                {
                                    //RowValues.Add(Cask.agingRate.Value.ToString("0.##"));
                                    if (HasHeldObject)
                                    {
                                        RowValues.Add(Math.Ceiling(Cask.daysToMature.Value / Cask.agingRate.Value).ToString("0.##"));
                                    }
                                }
                                else if (IsCrabPot)
                                {
                                    CrabPot.TryGetProcessingInterval(out double Power, out double IntervalHours, out int IntervalMinutes);
                                    RowValues.Add(IntervalMinutes.ToString());
                                }
                                else
                                {
                                    if (HasHeldObject)
                                    {
                                        RowValues.Add(HoveredObject.MinutesUntilReady.ToString("0.##"));
                                    }
                                }
                            }
                            if (ShowQuantityInfo)
                            {
                                if (HasHeldObject && HoveredObject.HasModifiedOutput())
                                {
                                    RowValues.Add(HoveredObject.heldObject.Value.Stack.ToString());
                                }
                            }
                            if (IsScarecrow)
                            {
                                //  Subtract 1 because the game internally counts the scarecrow's occupied tile as part of its radius, but users usually would be confused by that
                                //  So a typical user expects radius=8 for a regular scarecrow, even though the game does its calculations with radius=9
                                int OriginalRadius = HoveredObject.GetScarecrowBaseRadius() - 1;
                                int AlteredRadius  = HoveredObject.GetScarecrowRadius() - 1;
                                //RowValues.Add(string.Format("{0}-->{1}", OriginalRadius, AlteredRadius));
                                RowValues.Add(AlteredRadius.ToString());
                            }
                            List <Vector2> RowValueSizes = RowValues.Select(x => DrawHelpers.MeasureStringWithSpecialNumbers(x, ValueTextScale, 0.0f)).ToList();

                            //  Measure the tooltip
                            List <int> RowHeights = new List <int>();
                            for (int i = 0; i < RowHeaders.Count; i++)
                            {
                                RowHeights.Add((int)Math.Max(RowHeaderSizes[i].Y, RowValueSizes[i].Y));
                            }

                            List <int> ColumnWidths = new List <int> {
                                (int)RowHeaderSizes.Max(x => x.X),
                                (int)RowValueSizes.Max(x => x.X)
                            };

                            int   ToolTipTopWidth = Padding + ColumnWidths.Sum() + (ColumnWidths.Count - 1) * MarginBetweenColumns + Padding;
                            int   ToolTipHeight   = Padding + RowHeights.Sum() + (RowHeights.Count - 1) * MarginBetweenRows + Padding;
                            Point ToolTipTopleft  = DrawHelpers.GetTopleftPosition(new Point(ToolTipTopWidth, ToolTipHeight),
                                                                                   new Point((int)((MouseScreenPosition.X + UserConfig.ToolTipOffset.X) / UIScaleFactor), (int)((MouseScreenPosition.Y + UserConfig.ToolTipOffset.Y) / UIScaleFactor)), 100);

                            //  Draw tooltip background
                            DrawHelpers.DrawBox(e.SpriteBatch, new Rectangle(ToolTipTopleft.X, ToolTipTopleft.Y, ToolTipTopWidth, ToolTipHeight));

                            //  Draw each row's header and value
                            int CurrentY = ToolTipTopleft.Y + Padding;
                            for (int i = 0; i < RowHeights.Count; i++)
                            {
                                int CurrentRowHeight = RowHeights[i];

                                //  Draw the row header
                                Vector2 RowHeaderPosition = new Vector2(
                                    ToolTipTopleft.X + Padding + ColumnWidths[0] - RowHeaderSizes[i].X,
                                    CurrentY + (RowHeights[i] - RowHeaderSizes[i].Y) / 2.0f
                                    );
                                e.SpriteBatch.DrawString(DefaultFont, RowHeaders[i], RowHeaderPosition, Color.Black, 0.0f, Vector2.Zero, LabelTextScale, SpriteEffects.None, 1.0f);

                                //  Draw the row value
                                Vector2 RowValuePosition = new Vector2(
                                    ToolTipTopleft.X + Padding + ColumnWidths[0] + MarginBetweenColumns,
                                    CurrentY + (RowHeights[i] - RowValueSizes[i].Y) / 2.0f
                                    );
                                DrawHelpers.DrawStringWithSpecialNumbers(e.SpriteBatch, RowValuePosition, RowValues[i], ValueTextScale, Color.White);

                                CurrentY += CurrentRowHeight + MarginBetweenRows;
                            }
                        }
                    }
                }
            }
        }