public override void drawInMenu(SpriteBatch spriteBatch, Vector2 location, float scaleSize, float transparency, float layerDepth, bool drawStackNumber) { Item.drawInMenu(spriteBatch, location, scaleSize, transparency, layerDepth, false); var _scale = 0.5f + scaleSize; Game1.drawWithBorder(getStackNumber().ToString(), Color.Black, Color.White, location + new Vector2(Game1.tileSize - Game1.tinyFont.MeasureString(getStackNumber().ToString()).X *_scale, Game1.tileSize - (float)((double)Game1.tinyFont.MeasureString(getStackNumber().ToString()).Y * 3.0f / 4.0f) * _scale), 0.0f, _scale, 1f, true); }
private void DrawAtCoordinates(int x, int y) { // draw box of height and width at location IClickableMenu.drawTextureBox(Game1.spriteBatch, x, y, boxwidth, boxheight, Color.White); //Calculate draw position for fish Vector2 drawPos; if (Config.ShowTreasure && BarHasTreasure && !BarTreasureCaught) { drawPos = new Vector2(x + (boxwidth / 2) - (spriteSize / 2) - (treasureSpacing / 2) + treasureOffset, y + margin); } else { drawPos = new Vector2(x + (boxwidth / 2) - (spriteSize / 2), y + margin); } if (showFish) // if showFish, draw fish in normal color { fishSprite.drawInMenu(Game1.spriteBatch, drawPos, 1.0f, 1.0f, 1.0f, StackDrawType.Hide); } else // else (if not showFish), draw fish in black color { fishSprite.drawInMenu(Game1.spriteBatch, drawPos, 1.0f, 1.0f, 1.0f, StackDrawType.Hide, Color.Black * 0.8f, true); } if (showText) // if showText, center the text x below the fish { Game1.spriteBatch.DrawString(Game1.dialogueFont, textValue, new Vector2(x + (boxwidth / 2) - ((int)textSize.X / 2), y + spriteSize + margin), Color.Black, 0f, Vector2.Zero, scale, SpriteEffects.None, 0f); } // if show treasure draw treasure with fish icon if (Config.ShowTreasure && BarHasTreasure && !BarTreasureCaught) { treasureSprite = new Object(693, 1); treasureSprite.drawInMenu(Game1.spriteBatch, new Vector2(x + (boxwidth / 2) - (spriteSize / 2) + (treasureSpacing / 2) + treasureOffset, y + margin), 1.0f, 1.0f, 1.0f, StackDrawType.Hide); } }
/// <summary>Draw the subject portrait (if available).</summary> /// <param name="spriteBatch">The sprite batch being drawn.</param> /// <param name="position">The position at which to draw.</param> /// <param name="size">The size of the portrait to draw.</param> /// <returns>Returns <c>true</c> if a portrait was drawn, else <c>false</c>.</returns> public override bool DrawPortrait(SpriteBatch spriteBatch, Vector2 position, Vector2 size) { Item item = this.DisplayItem; // draw stackable object if ((item as SObject)?.Stack > 1) { // remove stack number (doesn't play well with clipped content) SObject obj = (SObject)item; obj = new SObject(obj.ParentSheetIndex, 1, obj.IsRecipe, obj.Price, obj.Quality); obj.bigCraftable.Value = obj.bigCraftable.Value; obj.drawInMenu(spriteBatch, position, 1); return(true); } // draw generic item item.drawInMenu(spriteBatch, position, 1); return(true); }
private static void DrawProbBox(Dictionary <int, double> probs) { SpriteBatch b = Game1.spriteBatch; Size size = GetProbBoxSize(probs); IClickableMenu.drawTextureBox(Game1.spriteBatch, ProbBoxPos.X, ProbBoxPos.Y, size.Width, size.Height, Color.White); const int square = (int)(Game1.tileSize / 1.5); int x = ProbBoxPos.X + 8; int y = ProbBoxPos.Y + 16; SpriteFont font = Game1.smallFont; { StardewValley.Object tip = null; foreach (KeyValuePair <int, double> kv in probs) { string text = $"{kv.Value * 100:f1}%"; StardewValley.Object fish = new StardewValley.Object(kv.Key, 1); fish.drawInMenu(b, new Vector2(x + 8, y), 1.0f); Utility.drawTextWithShadow(b, text, font, new Vector2(x + 32 + square, y + 16), Color.Black); // Cookie : Check for tool tip Rectangle pic = new Rectangle(x + 8, y, fish.boundingBox.Width, fish.boundingBox.Height); if (pic.Contains(Game1.getMouseX(), Game1.getMouseY())) { tip = fish; } y += square + 16; } if (tip != null) { string name = tip.DisplayName; if (name.Length < 5) // make text width wide enough for price. { name = string.Format("{0,-5}", name); } IClickableMenu.drawHoverText(Game1.spriteBatch, name, font, 0, 0, tip.Price); } } }
private void DrawAtCoordinates(int x, int y) { // draw box of height and width at location IClickableMenu.drawTextureBox(Game1.spriteBatch, x, y, boxwidth, boxheight, Color.White); // if showFish, center the fish x if (showFish) { fishSprite.drawInMenu(Game1.spriteBatch, new Vector2(x + (boxwidth / 2) - (spriteSize / 2), y + margin), 1.0f, 1.0f, 1.0f, StackDrawType.Hide); // if showFish and showText, center the text x below the fish if (showText) { Game1.spriteBatch.DrawString(Game1.dialogueFont, textValue, new Vector2(x + (boxwidth / 2) - ((int)textSize.X / 2), y + spriteSize + margin), Color.Black, 0f, Vector2.Zero, scale, SpriteEffects.None, 0f); } } // else (if not showFish), center the text x&y else { Game1.spriteBatch.DrawString(Game1.dialogueFont, textValue, new Vector2(x + (boxwidth / 2) - ((int)textSize.X / 2), y + (boxheight / 2) - ((int)textSize.Y / 2)), Color.Black, 0f, Vector2.Zero, scale, SpriteEffects.None, 0f); } }
/********* ** Public methods *********/ public override void Draw(SpriteBatch batch, Rectangle region) { string page2 = Game1.parseText(ModEntry.SHelper.Translation.Get("Book_Page3"), Game1.smallFont, region.Width); string diffEasy = ModEntry.SHelper.Translation.Get("Difficulty_Easy"); float diffEasyHeight = Game1.smallFont.MeasureString(diffEasy).Y; float offset = Game1.smallFont.MeasureString(page2).Y + 20; Utility.drawTextWithShadow(batch, page2, Game1.smallFont, new Vector2(region.X, region.Y), Game1.textColor); const float boxscale = 3.1f; SObject item = new SObject(382, 1); Vector2 pos = new Vector2(region.X, region.Y + offset); batch.Draw(Game1.mouseCursors, pos, PaymentPage.ItemBox, Color.White, 0, Vector2.Zero, boxscale, SpriteEffects.None, 0); pos.X += 6; pos.Y += 6; item.drawInMenu(batch, pos, 1, 1, 0, false); Utility.drawTextWithShadow(batch, diffEasy, Game1.smallFont, new Vector2(region.X + PaymentPage.ItemBox.Width * boxscale + 4, region.Y + offset + (PaymentPage.ItemBox.Height * boxscale - diffEasyHeight) / 2), Game1.textColor); offset += PaymentPage.ItemBox.Height * boxscale + 4; item = new SObject(72, 1); pos = new Vector2(region.X, region.Y + offset); batch.Draw(Game1.mouseCursors, pos, PaymentPage.ItemBox, Color.White, 0, Vector2.Zero, boxscale, SpriteEffects.None, 0); pos.X += 6; pos.Y += 6; item.drawInMenu(batch, pos, 1, 1, 0, false); Utility.drawTextWithShadow(batch, ModEntry.SHelper.Translation.Get("Difficulty_Medium"), Game1.smallFont, new Vector2(region.X + PaymentPage.ItemBox.Width * boxscale + 4, region.Y + offset + (PaymentPage.ItemBox.Height * boxscale - diffEasyHeight) / 2), Game1.textColor); offset += PaymentPage.ItemBox.Height * boxscale + 4; item = new SObject(74, 1); pos = new Vector2(region.X, region.Y + offset); batch.Draw(Game1.mouseCursors, pos, PaymentPage.ItemBox, Color.White, 0, Vector2.Zero, boxscale, SpriteEffects.None, 0); pos.X += 6; pos.Y += 6; item.drawInMenu(batch, pos, 1, 1, 0, false); Utility.drawTextWithShadow(batch, ModEntry.SHelper.Translation.Get("Difficulty_Hard"), Game1.smallFont, new Vector2(region.X + PaymentPage.ItemBox.Width * boxscale + 4, region.Y + offset + (PaymentPage.ItemBox.Height * boxscale - diffEasyHeight) / 2), Game1.textColor); }
private static void DrawProbBox(Dictionary <int, double> probabilities) { SpriteBatch b = Game1.spriteBatch; Size size = GetProbBoxSize(probabilities); IClickableMenu.drawTextureBox(Game1.spriteBatch, InstanceHolder.Config.ProbBoxCoordinates.X, InstanceHolder.Config.ProbBoxCoordinates.Y, size.Width, size.Height, Color.White); const int square = (int)(Game1.tileSize / 1.5); int x = InstanceHolder.Config.ProbBoxCoordinates.X + 8; int y = InstanceHolder.Config.ProbBoxCoordinates.Y + 16; SpriteFont font = Game1.dialogueFont; { foreach (KeyValuePair <int, double> kv in probabilities) { string text = $"{kv.Value * 100:f1}%"; Object fish = new Object(kv.Key, 1); fish.drawInMenu(b, new Vector2(x + 8, y), 1.0f); Utility.drawTextWithShadow(b, text, font, new Vector2(x + 32 + square, y + 16), Color.Black); y += square + 16; } } }
private static void ShowCatchInfo() { if (!(Game1.activeClickableMenu is BobberBar bar)) { return; } SpriteBatch batch = Game1.spriteBatch; SpriteFont font = Game1.smallFont; IReflectionHelper reflection = ModMain.Reflection; ITranslationHelper translation = ModMain.Translation; int width = 0, height = 120; float scale = 1.0f; int whitchFish = reflection.GetField <int>(bar, "whichFish").GetValue(); int fishSize = reflection.GetField <int>(bar, "fishSize").GetValue(); int fishQuality = reflection.GetField <int>(bar, "fishQuality").GetValue(); bool treasure = reflection.GetField <bool>(bar, "treasure").GetValue(); bool treasureCaught = reflection.GetField <bool>(bar, "treasureCaught").GetValue(); float treasureAppearTimer = reflection.GetField <float>(bar, "treasureAppearTimer").GetValue() / 1000; StardewValley.Object fish = new StardewValley.Object(whitchFish, 1); // string speciesText = TryFormat(translation.Get("fishinfo.species").ToString(), fish.DisplayName); // string sizeText = TryFormat(translation.Get("fishinfo.size").ToString(), GetFinalSize(fishSize)); string speciesText = translation.Get("fishinfo.species").ToString() + fish.DisplayName; string sizeText = Game1.content.LoadString("Strings\\StringsFromCSFiles:FishingRod.cs.14082") + " " + FishSizeUnit(fishSize); string qualityText1 = translation.Get("fishinfo.quality").ToString(); string qualityText2 = translation.Get(GetKeyForQuality(fishQuality)).ToString(); string incomingText = TryFormat(translation.Get("fishinfo.treasure.incoming").ToString(), treasureAppearTimer); string appearedText = translation.Get("fishinfo.treasure.appear").ToString(); string caughtText = translation.Get("fishinfo.treasure.caught").ToString(); { Vector2 size = font.MeasureString(speciesText) * scale; if (size.X > width) { width = (int)size.X; } height += (int)size.Y; size = font.MeasureString(sizeText) * scale; if (size.X > width) { width = (int)size.X; } height += (int)size.Y; Vector2 temp = font.MeasureString(qualityText1); Vector2 temp2 = font.MeasureString(qualityText2); size = new Vector2(temp.X + temp2.X, Math.Max(temp.Y, temp2.Y)); if (size.X > width) { width = (int)size.X; } height += (int)size.Y; } if (treasure) { if (treasureAppearTimer > 0) { Vector2 size = font.MeasureString(incomingText) * scale; if (size.X > width) { width = (int)size.X; } height += (int)size.Y; } else { if (!treasureCaught) { Vector2 size = font.MeasureString(appearedText) * scale; if (size.X > width) { width = (int)size.X; } height += (int)size.Y; } else { Vector2 size = font.MeasureString(caughtText) * scale; if (size.X > width) { width = (int)size.X; } height += (int)size.Y; } } } width += 64; int x = bar.xPositionOnScreen + bar.width + 96; if (x + width > Game1.viewport.Width) { x = bar.xPositionOnScreen - width - 96; } int y = (int)Cap(bar.yPositionOnScreen, 0, Game1.viewport.Height - height); IClickableMenu.drawTextureBox(batch, Game1.menuTexture, new Rectangle(0, 256, 60, 60), x, y, width, height, Color.White); fish.drawInMenu(batch, new Vector2(x + width / 2 - 32, y + 16), 1.0f, 1.0f, 0.9f, false); Vector2 vec2 = new Vector2(x + 32, y + 96); DrawString(batch, font, ref vec2, speciesText, Color.Black, scale); DrawString(batch, font, ref vec2, sizeText, Color.Black, scale); DrawString(batch, font, ref vec2, qualityText1, Color.Black, scale, true); DrawString(batch, font, ref vec2, qualityText2, GetColorForQuality(fishQuality), scale); vec2.X = x + 32; if (treasure) { if (!treasureCaught) { if (treasureAppearTimer > 0f) { DrawString(batch, font, ref vec2, incomingText, Color.Red, scale); } else { DrawString(batch, font, ref vec2, appearedText, Color.LightGoldenrodYellow, scale); } } else { DrawString(batch, font, ref vec2, caughtText, Color.ForestGreen, scale); } } }
public static void RenderAlchemyBarToHUD() { int scale = 4; int alchemyBarWidth = DrawingUtil.alchemyBarSprite.Width * scale; int alchemyBarHeight = DrawingUtil.alchemyBarSprite.Height * scale; //special consideration for maps that are smaller than your display viewport (horizontally, this happens at the bus stop) int tileSizeWidth = Game1.player.currentLocation.Map.DisplayWidth; //apply special constraints in the event of small-ish maps here bool isPlayerOutdoors = Game1.player.currentLocation.IsOutdoors; //borders from the screen are viewport width / 2 - tileSizeWidth / 2 int viewportBorderWidth = Math.Max(0, Game1.viewport.Width / 2 - tileSizeWidth / 2); int alchemyBarPositionX = Game1.viewport.Width - (isPlayerOutdoors ? viewportBorderWidth : 0) - alchemyBarWidth - 120; int alchemyBarPositionY = Game1.viewport.Height - alchemyBarHeight - 16; Vector2 alchemyBarPosition = new Vector2(alchemyBarPositionX, alchemyBarPositionY); Game1.spriteBatch.Draw(DrawingUtil.alchemyBarSprite, alchemyBarPosition, new Rectangle(0, 0, DrawingUtil.alchemyBarSprite.Width, DrawingUtil.alchemyBarSprite.Height), Color.White, 0, new Vector2(), scale, SpriteEffects.None, 1); if (CurrentEnergy > 0) { Rectangle targetArea = new Rectangle(3, 13, 6, 41); float perc = CurrentEnergy / MaxEnergy; int h = (int)(targetArea.Height * perc); targetArea.Y += targetArea.Height - h; targetArea.Height = h; targetArea.X *= 4; targetArea.Y *= 4; targetArea.Width *= 4; targetArea.Height *= 4; targetArea.X += (int)alchemyBarPosition.X; targetArea.Y += (int)alchemyBarPosition.Y; Game1.spriteBatch.Draw(DrawingUtil.alchemyBarFillSprite, targetArea, new Rectangle(0, 0, 1, 1), Color.White); int alchemyBarMaxX = alchemyBarPositionX + alchemyBarWidth; int alchemyBarMaxY = alchemyBarPositionY + alchemyBarHeight; //perform hover over manually if (Game1.getMouseX() >= alchemyBarPositionX && Game1.getMouseX() <= alchemyBarMaxX && Game1.getMouseY() >= alchemyBarPositionY && Game1.getMouseY() <= alchemyBarMaxY) { string alkahestryEnergyString = $"{ ((int)Math.Floor(CurrentEnergy)).ToString()}/{ MaxEnergy.ToString()}"; float stringWidth = Game1.dialogueFont.MeasureString(alkahestryEnergyString).X; Vector2 alkahestryEnergyStringPosition = new Vector2(alchemyBarPosition.X - stringWidth - 32, alchemyBarPosition.Y + 64); Game1.spriteBatch.DrawString(Game1.dialogueFont, alkahestryEnergyString, alkahestryEnergyStringPosition, Color.White); } } // if the player is holding a transmutable item, let's show the current recipe, if it's available. //get the player's current item Item heldItem = Game1.player.CurrentItem; //player is holding item if (heldItem != null) { //get the item's ID int heldItemID = heldItem.parentSheetIndex; //abort any transmutation event for blacklisted items or items that for whatever reason can't exist in world. if (!GetTransmutationFormulas().HasItem(heldItemID)) { return; } // get a list of recipes, valid or not, for the item we're holding var recipes = GetTransmutationFormulas().GetRecipesForOutput(heldItemID); // get an initial sprite position for the recipe list origin (top left) point var startingRecipeSpritePosition = new Vector2(alchemyBarPositionX - (136), alchemyBarPositionY); // loop over recipes, for displaying them in sequence // we "throttle" the max number of recipes we can iterate over (this list is sorted by validity!) // to avoid drawing off screen. At most it can draw as many as fits "in the alchemy bar's height" for (int i = 0; i < Math.Min(recipes.Count, (int)Math.Floor(alchemyBarHeight / 62D)); i++) { // originally column index was intended to let recipes display two by two (or more) // it made a mess so I scrapped it. var columnIndex = 0; // row index is just the index of the recipe, this one is still used. var rowIndex = i; // get the draw position offsets for the first item var xOffset = (int)Math.Floor(columnIndex * -98D); var yOffset = (int)Math.Floor(rowIndex * 62D); // turn them into a vector var bestRecipeSpritePosition = new Vector2(startingRecipeSpritePosition.X + xOffset, startingRecipeSpritePosition.Y + yOffset); // fetch the recipe var bestRecipe = recipes[i]; // display the current recipe beside the alchemy bar // fetch the input item as an object representing the input and quantity desired by this recipe Item inputItem = new StardewValley.Object(bestRecipe.InputId, bestRecipe.GetInputCost(), false); // figure out if the player has the necessary inputs for this recipe var hasInputs = Game1.player.hasItemInInventory(inputItem.parentSheetIndex, inputItem.Stack + 1); // set the transparency of the renderer based on whether inputs are present, this is just visual flare. var transparencyBasedOnValidity = hasInputs ? 1.0F : 0.5F; // calls the vanilla menu item display code, it's perfect for this inputItem.drawInMenu(Game1.spriteBatch, bestRecipeSpritePosition, 0.92F, transparencyBasedOnValidity, 0.875F, true, Color.White, false); // create a font vector for the tiny arrow we draw pointing from left to right between the items. This is just visual flare. // this hard-coded vector offset puts the arrow directly to the right of the quantity of the input, pointing right toward the output # var fontVector = new Vector2(bestRecipeSpritePosition.X + 71, bestRecipeSpritePosition.Y + 44); // draw the arrow at 0.7 scale of a normal dialogue font, we want it about the same size as the numbers... for visual flare. Game1.spriteBatch.DrawString(Game1.dialogueFont, ">", fontVector, Color.White, 0F, new Vector2(0, 0), 0.70F, SpriteEffects.None, 0.89F); // now get the vector for the output item var outputRecipeSpritePosition = new Vector2(bestRecipeSpritePosition.X + 65, bestRecipeSpritePosition.Y); // fetch the output item as an object representing the output and quantity produced by this recipe Item outputItem = new StardewValley.Object(heldItemID, bestRecipe.GetOutputQuantity() + 1, false); // finally, draw the output item outputItem.drawInMenu(Game1.spriteBatch, outputRecipeSpritePosition, 0.92F, transparencyBasedOnValidity, 0.875F, true, Color.White, false); } } }
public static void DrawFishingInfoBox(SpriteBatch batch, BobberBar bar, SpriteFont font) { int width = 0, height = 120; float scale = 1.0f; int whichFish = Reflection.GetField <int>(bar, "whichFish").GetValue(); int fishSize = Reflection.GetField <int>(bar, "fishSize").GetValue(); int fishQuality = Reflection.GetField <int>(bar, "fishQuality").GetValue(); bool treasure = Reflection.GetField <bool>(bar, "treasure").GetValue(); bool treasureCaught = Reflection.GetField <bool>(bar, "treasureCaught").GetValue(); float treasureAppearTimer = Reflection.GetField <float>(bar, "treasureAppearTimer").GetValue() / 1000; bool perfect = Reflection.GetField <bool>(bar, "perfect").GetValue(); if (perfect) { if (fishQuality >= 2) { fishQuality = 4; } else if (fishQuality >= 1) { fishQuality = 3; } } Object fish = new Object(whichFish, 1, quality: fishQuality); int salePrice = fish.sellToStorePrice(); if (LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.en) { scale = 0.7f; } string speciesText = Util.TryFormat(Translation.Get("fishinfo.species").ToString(), fish.DisplayName); string sizeText = Util.TryFormat(Translation.Get("fishinfo.size").ToString(), GetFinalSize(fishSize)); string qualityText1 = Translation.Get("fishinfo.quality").ToString(); string qualityText2 = Translation.Get(GetKeyForQuality(fishQuality)).ToString(); string incomingText = Util.TryFormat(Translation.Get("fishinfo.treasure.incoming").ToString(), treasureAppearTimer); string appearedText = Translation.Get("fishinfo.treasure.appear").ToString(); string caughtText = Translation.Get("fishinfo.treasure.caught").ToString(); string priceText = Util.TryFormat(Translation.Get("fishinfo.price"), salePrice); { Vector2 size = font.MeasureString(speciesText) * scale; if (size.X > width) { width = (int)size.X; } height += (int)size.Y; size = font.MeasureString(sizeText) * scale; if (size.X > width) { width = (int)size.X; } height += (int)size.Y; Vector2 temp = font.MeasureString(qualityText1); Vector2 temp2 = font.MeasureString(qualityText2); size = new Vector2(temp.X + temp2.X, Math.Max(temp.Y, temp2.Y)); if (size.X > width) { width = (int)size.X; } height += (int)size.Y; size = font.MeasureString(priceText) * scale; if (size.X > width) { width = (int)size.X; } height += (int)size.Y; } if (treasure) { if (treasureAppearTimer > 0) { Vector2 size = font.MeasureString(incomingText) * scale; if (size.X > width) { width = (int)size.X; } height += (int)size.Y; } else { if (!treasureCaught) { Vector2 size = font.MeasureString(appearedText) * scale; if (size.X > width) { width = (int)size.X; } height += (int)size.Y; } else { Vector2 size = font.MeasureString(caughtText) * scale; if (size.X > width) { width = (int)size.X; } height += (int)size.Y; } } } width += 64; int x = bar.xPositionOnScreen + bar.width + 96; if (x + width > Game1.viewport.Width) { x = bar.xPositionOnScreen - width - 96; } int y = (int)Util.Cap(bar.yPositionOnScreen, 0, Game1.viewport.Height - height); Util.DrawWindow(x, y, width, height); fish.drawInMenu(batch, new Vector2(x + width / 2 - 32, y + 16), 1.0f, 1.0f, 0.9f, StackDrawType.Hide); Vector2 vec2 = new Vector2(x + 32, y + 96); Util.DrawString(batch, font, ref vec2, speciesText, Color.Black, scale); Util.DrawString(batch, font, ref vec2, sizeText, Color.Black, scale); Util.DrawString(batch, font, ref vec2, qualityText1, Color.Black, scale, true); Util.DrawString(batch, font, ref vec2, qualityText2, GetColorForQuality(fishQuality), scale); vec2.X = x + 32; Util.DrawString(batch, font, ref vec2, priceText, Color.Black, scale); if (treasure) { if (!treasureCaught) { if (treasureAppearTimer > 0f) { Util.DrawString(batch, font, ref vec2, incomingText, Color.Red, scale); } else { Util.DrawString(batch, font, ref vec2, appearedText, Color.LightGoldenrodYellow, scale); } } else { Util.DrawString(batch, font, ref vec2, caughtText, Color.ForestGreen, scale); } } }
/// <summary>Render the UI.</summary> /// <param name="spriteBatch">The sprite batch being drawn.</param> public override void draw(SpriteBatch spriteBatch) { this.Monitor.InterceptErrors("drawing the lookup info", () => { // calculate dimensions int x = this.xPositionOnScreen; int y = this.yPositionOnScreen; const int gutter = 15; float leftOffset = gutter; float topOffset = gutter; float contentWidth = this.width - gutter * 2; float contentHeight = this.height - gutter * 2; int tableBorderWidth = 1; // get font SpriteFont font = Game1.smallFont; float lineHeight = font.MeasureString("ABC").Y; float spaceWidth = DrawHelper.GetSpaceWidth(font); // draw background // (This uses a separate sprite batch because it needs to be drawn before the // foreground batch, and we can't use the foreground batch because the background is // outside the clipping area.) using (SpriteBatch backgroundBatch = new SpriteBatch(Game1.graphics.GraphicsDevice)) { backgroundBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, null); backgroundBatch.DrawSprite(Sprites.Letter.Sheet, Sprites.Letter.Sprite, x, y, scale: this.width / (float)Sprites.Letter.Sprite.Width); backgroundBatch.End(); } // draw foreground // (This uses a separate sprite batch to set a clipping area for scrolling.) using (SpriteBatch contentBatch = new SpriteBatch(Game1.graphics.GraphicsDevice)) { GraphicsDevice device = Game1.graphics.GraphicsDevice; Rectangle prevScissorRectangle = device.ScissorRectangle; try { // begin draw device.ScissorRectangle = new Rectangle(x + gutter, y + gutter, (int)contentWidth, (int)contentHeight); contentBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, new RasterizerState { ScissorTestEnable = true }); // scroll view this.CurrentScroll = Math.Max(0, this.CurrentScroll); // don't scroll past top this.CurrentScroll = Math.Min(this.MaxScroll, this.CurrentScroll); // don't scroll past bottom topOffset -= this.CurrentScroll; // scrolled down == move text up leftOffset += 36; float wrapWidth = this.width - leftOffset - gutter; float caughtTextSize = 0; topOffset += lineHeight; { Vector2 caughtLabelSize = contentBatch.DrawTextBlock(font, $"Caught : ", new Vector2(x + leftOffset, y + topOffset), wrapWidth); Vector2 caughtValueSize = contentBatch.DrawTextBlock(font, $"{this.Fishes.Count(fish => fish.Caught)}/{this.Fishes.Count()}", new Vector2(x + leftOffset + caughtLabelSize.X, y + topOffset), wrapWidth, bold: Game1.content.GetCurrentLanguage() != LocalizedContentManager.LanguageCode.zh); caughtTextSize = caughtLabelSize.X + caughtValueSize.X; } { int caught = 0, total = 0; foreach (var fish in this.Fishes) { if ((fish.Id == 159 || fish.Id == 160 || fish.Id == 163 || fish.Id == 775 || fish.Id == 682)) { if (fish.Caught) { caught++; } total++; } } Vector2 legendariesCaughtLabelSize = contentBatch.DrawTextBlock(font, $"Legendaries : ", new Vector2(x + leftOffset, y + topOffset + lineHeight), wrapWidth); Vector2 legendariesCaughtValueSize = contentBatch.DrawTextBlock(font, $"{caught}/{total}", new Vector2(x + leftOffset + legendariesCaughtLabelSize.X, y + topOffset + lineHeight), wrapWidth, bold: Game1.content.GetCurrentLanguage() != LocalizedContentManager.LanguageCode.zh); caughtTextSize = legendariesCaughtLabelSize.X + legendariesCaughtValueSize.X; topOffset += lineHeight; } { Vector2 catchableLabelSize = contentBatch.DrawTextBlock(font, $"Catchable now : ", new Vector2(x + leftOffset + caughtTextSize + leftOffset, y + topOffset - lineHeight), wrapWidth); float rowWidth = wrapWidth - catchableLabelSize.X - caughtTextSize - leftOffset; int fishPerRow = (int)(rowWidth / ((Game1.tileSize / 2) + 8)); float innerOffset = (Game1.tileSize / 2) + 8; float innerTopOffset = 0; int count = 0; foreach (var fish in GetFishesCurrentlyCatchable()) { int xPos = (int)(x + leftOffset + caughtTextSize + leftOffset + catchableLabelSize.X + (innerOffset * count)); int yPos = (int)(y + topOffset - lineHeight + innerTopOffset); ClickableTextureComponent textureComponent = new ClickableTextureComponent(fish.Name + "*" + fish.GetTod() + "*" + fish.GetLocation(), new Rectangle(xPos, yPos, Game1.tileSize / 2, Game1.tileSize / 2), (string)null, "", Game1.objectSpriteSheet, Game1.getSourceRectForStandardTileSheet(Game1.objectSpriteSheet, fish.Id, 16, 16), 2f, true); this.ClickableFishTextures.Add(textureComponent); textureComponent.draw(contentBatch, Color.White, 0.86f); count++; if (count == fishPerRow) { count = 0; innerTopOffset += (Game1.tileSize / 2) + 8; } } topOffset += innerTopOffset + (lineHeight * 2); } float column1RowHeight = 0, column2Offset = 0, rowOffset = topOffset; // draw fish info foreach (FishInfo fish in this.Fishes) { // draw sprite { Item item = new SObject(fish.Id, 1); item.drawInMenu(contentBatch, new Vector2(x + leftOffset + column2Offset, y + topOffset), 1f, 1f, 1f, StackDrawType.Hide, this.ShowAll || fish.Caught ? Color.White : Color.Black * 0.2f, false); topOffset += Game1.tileSize / 2 + spaceWidth; } // draw name { Vector2 nameSize = contentBatch.DrawTextBlock(font, $"{(this.ShowAll || fish.Caught ? fish.Name : "???")}", new Vector2(x + leftOffset + column2Offset + Game1.tileSize + spaceWidth, y + topOffset), wrapWidth, bold: Game1.content.GetCurrentLanguage() != LocalizedContentManager.LanguageCode.zh); // draw caught status for legendary fishes { if ((fish.Caught && (fish.Id == 159 || fish.Id == 160 || fish.Id == 163 || fish.Id == 682 || fish.Id == 775))) { contentBatch.DrawTextBlock(font, "(X)", new Vector2(x + leftOffset + column2Offset + Game1.tileSize + spaceWidth + nameSize.X + spaceWidth, y + topOffset), wrapWidth, bold: Game1.content.GetCurrentLanguage() != LocalizedContentManager.LanguageCode.zh); } } topOffset += Game1.tileSize / 2 + spaceWidth; } // draw table foreach (string key in fish.Data.Keys) { float cellPadding = 3; float labelWidth = fish.Data.Keys.Max(p => font.MeasureString(p).X); float valueWidth = wrapWidth / 2.2F - labelWidth - cellPadding * 4 - tableBorderWidth; // draw label & value Vector2 labelSize = contentBatch.DrawTextBlock(font, key, new Vector2(x + leftOffset + cellPadding + column2Offset, y + topOffset + cellPadding), wrapWidth); Vector2 valuePosition = new Vector2(x + leftOffset + labelWidth + cellPadding * 3 + column2Offset, y + topOffset + cellPadding); Vector2 valueSize = contentBatch.DrawTextBlock(font, this.ShowAll || fish.Caught ? fish.Data[key] : "???", valuePosition, valueWidth); Vector2 rowSize = new Vector2(labelWidth + valueWidth + cellPadding * 4, Math.Max(labelSize.Y, valueSize.Y)); // draw table row Color lineColor = Color.Gray; contentBatch.DrawLine(x + leftOffset + column2Offset, y + topOffset, new Vector2(rowSize.X, tableBorderWidth), lineColor); // top contentBatch.DrawLine(x + leftOffset + column2Offset, y + topOffset + rowSize.Y, new Vector2(rowSize.X, tableBorderWidth), lineColor); // bottom contentBatch.DrawLine(x + leftOffset + column2Offset, y + topOffset, new Vector2(tableBorderWidth, rowSize.Y), lineColor); // left contentBatch.DrawLine(x + leftOffset + column2Offset + labelWidth + cellPadding * 2, y + topOffset, new Vector2(tableBorderWidth, rowSize.Y), lineColor); // middle contentBatch.DrawLine(x + leftOffset + column2Offset + rowSize.X, y + topOffset, new Vector2(tableBorderWidth, rowSize.Y), lineColor); // right // update offset topOffset += Math.Max(labelSize.Y, valueSize.Y); } if (column2Offset == 0) { column2Offset += (wrapWidth / 2.2F - tableBorderWidth) + leftOffset / 2; column1RowHeight = topOffset + lineHeight; topOffset = rowOffset; // Reset topOffset } else { column2Offset = 0; // draw spacer topOffset += lineHeight; // Take max of column1 and column2 heights rowOffset = Math.Max(column1RowHeight, topOffset); // Move to next row topOffset = rowOffset; } } // update max scroll this.MaxScroll = Math.Max(0, (int)(topOffset - contentHeight + this.CurrentScroll)); // draw scroll icons if (this.MaxScroll > 0 && this.CurrentScroll > 0) { this.ScrollToTopButton.draw(spriteBatch); } if (this.MaxScroll > 0 && this.CurrentScroll < this.MaxScroll) { this.ScrollToBottomButton.draw(spriteBatch); } // end draw contentBatch.End(); } finally { device.ScissorRectangle = prevScissorRectangle; } } // draw cursor this.drawMouse(Game1.spriteBatch); if (!this.hoverText.Equals("")) { IClickableMenu.drawHoverText(spriteBatch, this.hoverText, Game1.smallFont, 0, 0, -1, (string)null, -1, (string[])null, (Item)null, 0, -1, -1, -1, -1, 1f, (CraftingRecipe)null); } }, this.OnDrawError); }
public override void draw(SpriteBatch b) { b.Draw(Game1.fadeToBlackRect, Game1.graphics.GraphicsDevice.Viewport.Bounds, Color.Black * 0.4f); draw(b); Game1.dayTimeMoneyBox.drawMoneyBox(b); b.Draw(_content.Load <Texture2D>("assets/bgpatch.png"), new Vector2(GeodeSpot.bounds.X, GeodeSpot.bounds.Y), new Rectangle(0, 0, 140, 78), Color.White, 0.0f, Vector2.Zero, 4f, SpriteEffects.None, 0.87f); if (GeodeSpot.item != null) { if (_geodeDestructionAnimation == null) { GeodeSpot.item.drawInMenu(b, new Vector2(GeodeSpot.bounds.X + 253 + (GeodeSpot.item.ParentSheetIndex == 275 ? -8 : 0), GeodeSpot.bounds.Y + 118 + (GeodeSpot.item.ParentSheetIndex == 275 ? 8 : 0)), 1f); } else { _geodeDestructionAnimation.draw(b, true); } foreach (var fluffSprite in _fluffSprites) { fluffSprite.draw(b, true); } if (_geodeTreasure != null && _delayBeforeShowArtifactTimer <= 0.0) { _geodeTreasure.drawInMenu(b, new Vector2(GeodeSpot.bounds.X + 253, GeodeSpot.bounds.Y + 118 + _yPositionOfGem), 1f); } _sparkle?.draw(b, true); } _clint.draw(b, new Vector2(GeodeSpot.bounds.X + 384, GeodeSpot.bounds.Y + 64), 0.877f); if (!hoverText.Equals("")) { drawHoverText(b, hoverText, Game1.smallFont); } heldItem?.drawInMenu(b, new Vector2(Game1.getOldMouseX() + 8, Game1.getOldMouseY() + 8), 1f); if (Game1.options.hardwareCursor) { return; } drawMouse(b); }
/// <summary>Patch to adjust fish pond UI for Aquarist increased max capacity.</summary> private static bool PondQueryMenuDrawPrefix(ref PondQueryMenu __instance, ref float ____age, ref Rectangle ____confirmationBoxRectangle, ref string ____confirmationText, ref SObject ____fishItem, ref FishPond ____pond, ref bool ___confirmingEmpty, ref string ___hoverText, SpriteBatch b) { try { var owner = Game1.getFarmer(____pond.owner.Value); if (!Utility.SpecificPlayerHasProfession("Aquarist", owner) || ____pond.lastUnlockedPopulationGate.Value < AwesomeProfessions.Reflection.GetField <FishPondData>(____pond, name: "_fishPondData").GetValue().PopulationGates.Keys.Max()) { return(true); // run original logic; } if (!Game1.globalFade) { b.Draw(Game1.fadeToBlackRect, Game1.graphics.GraphicsDevice.Viewport.Bounds, Color.Black * 0.75f); var hasUnresolvedNeeds = ____pond.neededItem.Value != null && ____pond.HasUnresolvedNeeds() && !____pond.hasCompletedRequest.Value; var pondNameText = Game1.content.LoadString("Strings\\UI:PondQuery_Name", ____fishItem.DisplayName); var textSize = Game1.smallFont.MeasureString(pondNameText); Game1.DrawBox((int)((Game1.uiViewport.Width / 2) - (textSize.X + 64f) * 0.5f), __instance.yPositionOnScreen - 4 + 128, (int)(textSize.X + 64f), 64); SUtility.drawTextWithShadow(b, pondNameText, Game1.smallFont, new Vector2((Game1.uiViewport.Width / 2) - textSize.X * 0.5f, __instance.yPositionOnScreen - 4 + 160f - textSize.Y * 0.5f), Color.Black); var displayedText = AwesomeProfessions.Reflection.GetMethod(__instance, name: "getDisplayedText").Invoke <string>(); var extraHeight = 0; if (hasUnresolvedNeeds) { extraHeight += 116; } var extraTextHeight = AwesomeProfessions.Reflection.GetMethod(__instance, name: "measureExtraTextHeight").Invoke <int>(displayedText); Game1.drawDialogueBox(__instance.xPositionOnScreen, __instance.yPositionOnScreen + 128, PondQueryMenu.width, PondQueryMenu.height - 128 + extraHeight + extraTextHeight, speaker: false, drawOnlyBox: true); var populationText = Game1.content.LoadString("Strings\\UI:PondQuery_Population", string.Concat(____pond.FishCount), ____pond.maxOccupants.Value); textSize = Game1.smallFont.MeasureString(populationText); SUtility.drawTextWithShadow(b, populationText, Game1.smallFont, new Vector2((__instance.xPositionOnScreen + PondQueryMenu.width / 2) - textSize.X * 0.5f, __instance.yPositionOnScreen + IClickableMenu.spaceToClearTopBorder + 16 + 128), Game1.textColor); var slotsToDraw = ____pond.maxOccupants.Value; var slotSpacing = 11f; var x = 0; var y = 0; for (var i = 0; i < slotsToDraw; ++i) { var yOffset = (float)Math.Sin(____age * 1f + x * 0.75f + y * 0.25f) * 2f; if (i < ____pond.FishCount) { ____fishItem.drawInMenu(b, new Vector2((__instance.xPositionOnScreen - 20 + PondQueryMenu.width / 2) - slotSpacing * Math.Min(slotsToDraw, 5) * 4f * 0.5f + slotSpacing * 4f * x - 12f, (__instance.yPositionOnScreen + (int)(yOffset * 4f)) + (y * 4) * slotSpacing + 275.2f), 0.75f, 1f, 0f, StackDrawType.Hide, Color.White, drawShadow: false); } else { ____fishItem.drawInMenu(b, new Vector2((__instance.xPositionOnScreen - 20 + PondQueryMenu.width / 2) - slotSpacing * Math.Min(slotsToDraw, 5) * 4f * 0.5f + slotSpacing * 4f * x - 12f, (__instance.yPositionOnScreen + (int)(yOffset * 4f)) + (y * 4) * slotSpacing + 275.2f), 0.75f, 0.35f, 0f, StackDrawType.Hide, Color.Black, drawShadow: false); } ++x; if (x != 6) { continue; } x = 0; ++y; } textSize = Game1.smallFont.MeasureString(displayedText); SUtility.drawTextWithShadow(b, displayedText, Game1.smallFont, new Vector2((__instance.xPositionOnScreen + PondQueryMenu.width / 2) - textSize.X * 0.5f, (__instance.yPositionOnScreen + PondQueryMenu.height + extraTextHeight - (hasUnresolvedNeeds ? 32 : 48)) - textSize.Y), Game1.textColor); if (hasUnresolvedNeeds) { AwesomeProfessions.Reflection.GetMethod(__instance, name: "drawHorizontalPartition").Invoke(b, (int)((__instance.yPositionOnScreen + PondQueryMenu.height + extraTextHeight) - 48f)); SUtility.drawWithShadow(b, Game1.mouseCursors, new Vector2((__instance.xPositionOnScreen + 60) + 8f * Game1.dialogueButtonScale / 10f, __instance.yPositionOnScreen + PondQueryMenu.height + extraTextHeight + 28), new Rectangle(412, 495, 5, 4), Color.White, (float)Math.PI / 2f, Vector2.Zero); var bringText = Game1.content.LoadString("Strings\\UI:PondQuery_StatusRequest_Bring"); textSize = Game1.smallFont.MeasureString(bringText); var leftX = __instance.xPositionOnScreen + 88; float textX = leftX; var iconX = textX + textSize.X + 4f; if (LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.ja || LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.ko || LocalizedContentManager.CurrentLanguageCode == LocalizedContentManager.LanguageCode.tr) { iconX = leftX - 8; textX = leftX + 76; } SUtility.drawTextWithShadow(b, bringText, Game1.smallFont, new Vector2(textX, __instance.yPositionOnScreen + PondQueryMenu.height + extraTextHeight + 24), Game1.textColor); b.Draw(Game1.objectSpriteSheet, new Vector2(iconX, __instance.yPositionOnScreen + PondQueryMenu.height + extraTextHeight + 4), Game1.getSourceRectForStandardTileSheet(Game1.objectSpriteSheet, ____pond.neededItem.Value.ParentSheetIndex, 16, 16), Color.Black * 0.4f, 0f, Vector2.Zero, 4f, SpriteEffects.None, 1f); b.Draw(Game1.objectSpriteSheet, new Vector2(iconX + 4f, __instance.yPositionOnScreen + PondQueryMenu.height + extraTextHeight), Game1.getSourceRectForStandardTileSheet(Game1.objectSpriteSheet, ____pond.neededItem.Value.ParentSheetIndex, 16, 16), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 1f); if (____pond.neededItemCount.Value > 1) { SUtility.drawTinyDigits(____pond.neededItemCount.Value, b, new Vector2(iconX + 48f, __instance.yPositionOnScreen + PondQueryMenu.height + extraTextHeight + 48), 3f, 1f, Color.White); } } __instance.okButton.draw(b); __instance.emptyButton.draw(b); __instance.changeNettingButton.draw(b); if (___confirmingEmpty) { b.Draw(Game1.fadeToBlackRect, Game1.graphics.GraphicsDevice.Viewport.Bounds, Color.Black * 0.75f); var padding = 16; ____confirmationBoxRectangle.Width += padding; ____confirmationBoxRectangle.Height += padding; ____confirmationBoxRectangle.X -= padding / 2; ____confirmationBoxRectangle.Y -= padding / 2; Game1.DrawBox(____confirmationBoxRectangle.X, ____confirmationBoxRectangle.Y, ____confirmationBoxRectangle.Width, ____confirmationBoxRectangle.Height); ____confirmationBoxRectangle.Width -= padding; ____confirmationBoxRectangle.Height -= padding; ____confirmationBoxRectangle.X += padding / 2; ____confirmationBoxRectangle.Y += padding / 2; b.DrawString(Game1.smallFont, ____confirmationText, new Vector2(____confirmationBoxRectangle.X, ____confirmationBoxRectangle.Y), Game1.textColor); __instance.yesButton.draw(b); __instance.noButton.draw(b); } else if (!string.IsNullOrEmpty(___hoverText)) { IClickableMenu.drawHoverText(b, ___hoverText, Game1.smallFont); } } __instance.drawMouse(b); return(false); // don't run original logic } catch (Exception ex) { Monitor.Log($"Failed in {nameof(PondQueryMenuDrawPrefix)}:\n{ex}"); return(true); // default to original logic } }
/// <summary>Render the UI.</summary> /// <param name="spriteBatch">The sprite batch being drawn.</param> public override void draw(SpriteBatch spriteBatch) { this.Monitor.InterceptErrors("drawing the lookup info", () => { // calculate dimensions int x = this.xPositionOnScreen; int y = this.yPositionOnScreen; const int gutter = 15; float leftOffset = gutter; float topOffset = gutter; float contentWidth = this.width - gutter * 2; float contentHeight = this.height - gutter * 2; int tableBorderWidth = 1; // get font SpriteFont font = Game1.smallFont; float lineHeight = font.MeasureString("ABC").Y; float spaceWidth = DrawHelper.GetSpaceWidth(font); // draw background // (This uses a separate sprite batch because it needs to be drawn before the // foreground batch, and we can't use the foreground batch because the background is // outside the clipping area.) using (SpriteBatch backgroundBatch = new SpriteBatch(Game1.graphics.GraphicsDevice)) { backgroundBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, null); backgroundBatch.DrawSprite(Sprites.Letter.Sheet, Sprites.Letter.Sprite, x, y, scale: this.width / (float)Sprites.Letter.Sprite.Width); backgroundBatch.End(); } // draw foreground // (This uses a separate sprite batch to set a clipping area for scrolling.) using (SpriteBatch contentBatch = new SpriteBatch(Game1.graphics.GraphicsDevice)) { GraphicsDevice device = Game1.graphics.GraphicsDevice; Rectangle prevScissorRectangle = device.ScissorRectangle; try { // begin draw device.ScissorRectangle = new Rectangle(x + gutter, y + gutter, (int)contentWidth, (int)contentHeight); contentBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, new RasterizerState { ScissorTestEnable = true }); // scroll view this.CurrentScroll = Math.Max(0, this.CurrentScroll); // don't scroll past top this.CurrentScroll = Math.Min(this.MaxScroll, this.CurrentScroll); // don't scroll past bottom topOffset -= this.CurrentScroll; // scrolled down == move text up leftOffset += 72; float wrapWidth = this.width - leftOffset - gutter; { int caught = 0; foreach (var fish in this.Fishes) { if (fish.Caught) { caught++; } } Vector2 caughtLabelSize = contentBatch.DrawTextBlock(font, $"Caught : ", new Vector2(x + leftOffset, y + topOffset), wrapWidth); Vector2 caughtValueSize = contentBatch.DrawTextBlock(font, $"{caught}/{this.Fishes.Count()}", new Vector2(x + leftOffset + caughtLabelSize.X, y + topOffset), wrapWidth, bold: Game1.content.GetCurrentLanguage() != LocalizedContentManager.LanguageCode.zh); topOffset += lineHeight * 4; } // draw fish info foreach (FishInfo fish in this.Fishes) { // draw sprite { Item item = new SObject(fish.Id, 1); item.drawInMenu(contentBatch, new Vector2(x + leftOffset, y + topOffset), 1f, 1f, 1f, false, fish.Caught ? Color.White : Color.Black * 0.2f, false); topOffset += Game1.tileSize / 2 + spaceWidth; } // draw name { Vector2 nameSize = contentBatch.DrawTextBlock(font, $"{(fish.Caught? fish.Name : "???")}", new Vector2(x + leftOffset + Game1.tileSize + spaceWidth, y + topOffset), wrapWidth, bold: Game1.content.GetCurrentLanguage() != LocalizedContentManager.LanguageCode.zh); topOffset += Game1.tileSize / 2 + spaceWidth; } // draw table foreach (string key in fish.Data.Keys) { float cellPadding = 3; float labelWidth = fish.Data.Keys.Max(p => font.MeasureString(p).X); float valueWidth = wrapWidth - labelWidth - cellPadding * 4 - tableBorderWidth; // draw label & value Vector2 labelSize = contentBatch.DrawTextBlock(font, key, new Vector2(x + leftOffset + cellPadding, y + topOffset + cellPadding), wrapWidth); Vector2 valuePosition = new Vector2(x + leftOffset + labelWidth + cellPadding * 3, y + topOffset + cellPadding); Vector2 valueSize = contentBatch.DrawTextBlock(font, fish.Caught? fish.Data[key] : "???", valuePosition, valueWidth); Vector2 rowSize = new Vector2(labelWidth + valueWidth + cellPadding * 4, Math.Max(labelSize.Y, valueSize.Y)); // draw table row Color lineColor = Color.Gray; contentBatch.DrawLine(x + leftOffset, y + topOffset, new Vector2(rowSize.X, tableBorderWidth), lineColor); // top contentBatch.DrawLine(x + leftOffset, y + topOffset + rowSize.Y, new Vector2(rowSize.X, tableBorderWidth), lineColor); // bottom contentBatch.DrawLine(x + leftOffset, y + topOffset, new Vector2(tableBorderWidth, rowSize.Y), lineColor); // left contentBatch.DrawLine(x + leftOffset + labelWidth + cellPadding * 2, y + topOffset, new Vector2(tableBorderWidth, rowSize.Y), lineColor); // middle contentBatch.DrawLine(x + leftOffset + rowSize.X, y + topOffset, new Vector2(tableBorderWidth, rowSize.Y), lineColor); // right // update offset topOffset += Math.Max(labelSize.Y, valueSize.Y); } // draw spacer topOffset += lineHeight; } // update max scroll this.MaxScroll = Math.Max(0, (int)(topOffset - contentHeight + this.CurrentScroll)); // draw scroll icons if (this.MaxScroll > 0 && this.CurrentScroll > 0) { this.ScrollUpButton.draw(contentBatch); } if (this.MaxScroll > 0 && this.CurrentScroll < this.MaxScroll) { this.ScrollDownButton.draw(spriteBatch); } // end draw contentBatch.End(); } finally { device.ScissorRectangle = prevScissorRectangle; } } // draw cursor this.drawMouse(Game1.spriteBatch); }, this.OnDrawError); }