/// <summary> /// Renders custom objects as held objects for stardew valley machines. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public static void Render_RenderCustomObjectsHeldInMachines(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (TrackedMachines.ContainsKey(Game1.player.currentLocation)) { List <SObject> removalList = new List <SObject>(); foreach (SObject obj in TrackedMachines[Game1.player.currentLocation]) { if (obj.heldObject.Value == null) { removalList.Add(obj); } else { if (obj.heldObject.Value is CustomObject) { if (obj.MinutesUntilReady == 0) { float num = (float)(4.0 * Math.Round(Math.Sin(DateTime.UtcNow.TimeOfDay.TotalMilliseconds / 250.0), 2)); Vector2 pos = new Vector2(obj.TileLocation.X * Game1.tileSize, (obj.TileLocation.Y - 1) * Game1.tileSize - 32 + num); obj.heldObject.Value.draw(e.SpriteBatch, (int)pos.X, (int)pos.Y, 0.25f, 1f); } } } } foreach (SObject obj in removalList) { TrackedMachines[Game1.player.currentLocation].Remove(obj); } } }
private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (!Config.EnableMod) { return; } if (locationDict.TryGetValue(Game1.currentLocation.Name, out Dictionary <Point, List <ParticleEffectData> > dict)) { foreach (var kvp in dict) { foreach (var effect in kvp.Value) { ShowLocationParticleEffect(e.SpriteBatch, Game1.currentLocation, effect); } } } foreach (var key in effectDict.Keys) { var ped = effectDict[key]; switch (ped.type.ToLower()) { case "location": if (Game1.currentLocation.Name == ped.name) { ShowLocationParticleEffect(e.SpriteBatch, Game1.currentLocation, ped); } break; } } }
private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (FarmHouseStates.getState(StardewValley.Utility.getHomeOfFarmer(Game1.player)) != null) { //FarmHouseStates.drawRender(e.SpriteBatch); //e.SpriteBatch.Draw(Image.Renderer.testRender, Vector2.Zero, new Rectangle(0, 0, Image.Renderer.testRender.Width, Image.Renderer.testRender.Height), Color.White, 0.0f, Vector2.Zero, 4f, Microsoft.Xna.Framework.Graphics.SpriteEffects.None, 1); } }
private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { for (int i = animations.Count - 1; i >= 0; i--) { animations[i].draw(e.SpriteBatch, false, 0, 0, 1f); } if (sparklingText != null && lastUser != null) { sparklingText.draw(e.SpriteBatch, Game1.GlobalToLocal(Game1.viewport, lastUser.Position + new Vector2(-64f, -352f))); } }
public void drawExtraLayers(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (Pseudo3D.MapHandler.isPseudo3DLocation(Game1.currentLocation)) { Pseudo3D.MapHandler.drawOverlays(e.SpriteBatch, Game1.currentLocation); } ForegroundHandler.draw(e.SpriteBatch); //e.SpriteBatch.End(); //e.SpriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend); //ParticleHandler.draw(e.SpriteBatch); //Perspective.PerspectiveRenderer.draw(e.SpriteBatch); }
private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (!Context.IsWorldReady) { return; } foreach (var t in this._jumpingFish) { t.Draw(Game1.spriteBatch); } }
private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (!IsModEnabled()) { return; } if (Config.AsciiEnabled && asciifying) { int scale = 16; var lines = ConvertToAscii(ScaleScreen(scale, out int w, out int h), Game1.graphics.GraphicsDevice.PresentationParameters.BackBufferWidth / scale); if (lines.Count > 0) { e.SpriteBatch.Draw(blackTexture, new Rectangle(0, 0, Game1.viewport.Width, Game1.viewport.Height), Color.White); int height = Game1.viewport.Height / lines.Count; for (int i = 0; i < lines.Count; i++) { e.SpriteBatch.DrawString(font, lines[i], new Vector2(0, height * i), Color.White, 0, Vector2.Zero, 0.8f, SpriteEffects.None, 1); } } } else if (Config.PixelateEnabled && pixelating) { Color[] data = ScaleScreen(16, out int width, out int height); Texture2D pixelScreen = new Texture2D(Game1.graphics.GraphicsDevice, width, height); pixelScreen.SetData(data); e.SpriteBatch.Draw(pixelScreen, new Rectangle(0, 0, Game1.viewport.Width, Game1.viewport.Height), Color.White); } if (Config.RavenEnabled && (Game1.timeOfDay >= 2100 || Game1.timeOfDay <= 200)) { for (int i = 0; i < ravenText.Length; i++) { var y = Game1.viewport.Height - ravenTicks / 2 + i * 48; if (y < -48) { continue; } if (y > Game1.viewport.Height) { break; } e.SpriteBatch.DrawString(Game1.dialogueFont, ravenText[i], new Vector2(0, y), Color.DarkGray * 0.75f); e.SpriteBatch.DrawString(Game1.dialogueFont, ravenText[i], new Vector2(2, y + 2), Color.Black * 0.75f); } ravenTicks++; } else { ravenTicks = 0; } }
public void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (!Config.EnableMod || !placingTracks || Game1.activeClickableMenu != null) { return; } if (placingTracks) { float layerDepth = (Game1.currentCursorTile.Y * (16 * Game1.pixelZoom) + 16 * Game1.pixelZoom) / 10000f; e.SpriteBatch.Draw(trackTexture, Game1.GlobalToLocal(Game1.viewport, Game1.currentCursorTile * 64), new Rectangle(currentTrackIndex * 16, 0, 16, 16), Color.White, 0, Vector2.Zero, 4, SpriteEffects.None, layerDepth); } }
void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (Game1.paused) { return; } expAnimations.RemoveAll(anim => anim.Expired()); expAnimations.ForEach(anim => { anim.update(Game1.currentGameTime); anim.Draw(e.SpriteBatch); }); }
void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { foreach (Vector2 vec in CurrentPath) { e.SpriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, vec * 64f), new Rectangle(194 + 0 * 16, 388, 16, 16), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 0.999f); } foreach (Vector2 vec in NonPassables) { e.SpriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, vec * 64f), new Rectangle(194 + 1 * 16, 388, 16, 16), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 0.999f); } foreach (Vector2 vec in Passables) { e.SpriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, vec * 64f), new Rectangle(194 + 0 * 16, 388, 16, 16), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 0.999f); } }
/// <summary>Draws a hovering excalamation point above each entry in <see cref="ExclamationPointTiles"/> for the current player.</summary> private static void RenderedWorld_DrawExclamationPoints(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (!Context.IsPlayerFree) //if the plyer is NOT free (events, menus, etc) { return; //do nothing } foreach (ExclamationData point in ExclamationPointTiles.Value) //for each exclamation point to draw { if (!Game1.player.team.acceptedSpecialOrderTypes.Contains(point.OrderType)) //if the players do NOT already have an active order of this type { //draw the exclamation point (imitate code from Town.draw(SpriteBatch)) float yOffset = 4f * (float)Math.Round(Math.Sin(Game1.currentGameTime.TotalGameTime.TotalMilliseconds / 250.0), 2); e.SpriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, new Vector2(point.PixelPosition.X, point.PixelPosition.Y + yOffset)), SourceRectangle, Color.White, 0f, new Vector2(1f, 4f), 4f + Math.Max(0f, 0.25f - yOffset / 16f), SpriteEffects.None, 1f); } } }
private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (Config.EnableMod && framing && frameList.Count > 0) { var pos = Game1.getMousePosition(false) - Utility.Vector2ToPoint(new Vector2(frameList[currentFrame].texture.Width * 4 / Game1.options.zoomLevel, frameList[currentFrame].texture.Height * 4 / Game1.options.zoomLevel)); if (pos.X < 0) { pos.X = 0; } if (pos.Y < 0) { pos.Y = 0; } e.SpriteBatch.Draw(frameList[currentFrame].texture, Utility.PointToVector2(pos), null, Color.White, 0, Vector2.Zero, 4 / Game1.options.zoomLevel, SpriteEffects.None, 1); } }
private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (detachedMenus.Any()) { var back = Game1.options.showMenuBackground; Game1.options.showMenuBackground = true; foreach (var m in detachedMenus) { var f = AccessTools.Field(m.GetType(), "drawBG"); if (f != null) { f.SetValue(m, false); } m.draw(e.SpriteBatch); } Game1.options.showMenuBackground = back; } }
private void OnRenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (!(Context.IsPlayerFree && !Game1.eventUp && Game1.farmEvent == null && Config.harvestCropsRange > 0 && Config.harvestCrops)) { return; } if (Config.harvestCrops && Config.harvestCropsRange > 0 && Game1.player.ActiveObject != null && Game1.player.ActiveObject.bigCraftable.Value && Game1.player.ActiveObject.ParentSheetIndex == ItemIds.Autograbber) { // impl @ StardewValley::Object::drawPlacementBounds var placementTile = Game1.GetPlacementGrabTile(); var X = (int)placementTile.X; var Y = (int)placementTile.Y; if (Game1.IsPerformingMousePlacement()) { var range = Config.harvestCropsRange; for (int x = X - range; x <= X + range; x++) { for (int y = Y - range; y <= Y + range; y++) { if (Config.harvestCropsRangeMode == "Walk" && Math.Abs(X - x) + Math.Abs(Y - y) > range) { continue; } Game1.spriteBatch.Draw( Game1.mouseCursors, Game1.GlobalToLocal(new Vector2(x, y) * 64), new Rectangle(194, 388, 16, 16), Color.White, 0, Vector2.Zero, 4, SpriteEffects.None, 0.01f ); } } } } }
private static void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (Config.EnableMod && Config.PermaDeath && Game1.killScreen) { deathScreenTimer++; if (deathScreenTimer > Config.PermaDeathScreenTicks) { deathScreenTimer = 0; Game1.killScreen = false; SHelper.Events.Display.RenderedWorld -= Display_RenderedWorld; Game1.ExitToTitle(); } else { e.SpriteBatch.Draw(blackTexture, new Rectangle(0, 0, Game1.viewport.Width, Game1.viewport.Height), Color.White); e.SpriteBatch.DrawString(Game1.dialogueFont, "YOU DIED", new Vector2(Game1.viewport.Width / 2 - Game1.dialogueFont.MeasureString("YOU DIED").X * 4, Game1.viewport.Height / 2 - Game1.dialogueFont.MeasureString("YOU DIED").Y * 4), Color.Red * Math.Min(1, deathScreenTimer / (Config.PermaDeathScreenTicks / 2f)), 0, Vector2.Zero, 8, SpriteEffects.None, 1); } } }
private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (Game1.currentLocation == null) { return; } if (_showGrid) { TileInfoMenu.DrawGrid(e.SpriteBatch, colour: _gridColour, width: _gridWidth, opacity: 1f); } Point mouse = Game1.getMousePosition(); bool isChildHovered = Desktop.Taskbar.IsExpanded && Desktop.Children.Any(child => child.isWithinBounds(mouse.X, mouse.Y) || ((child.GetParentMenu() is WindowBar windowBar) && windowBar.isWithinBounds(mouse.X, mouse.Y))); if (_showTileHighlight && !isChildHovered) { TileInfoMenu.DrawTileHighlight(e.SpriteBatch, colour: _tileHighlightColour); } }
private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (Config.EnableMod && isBuilding) { if (Helper.Input.IsDown(Config.BuildKey) || Helper.Input.IsSuppressed(Config.BuildKey)) { buildingRect.Size = Utility.Vector2ToPoint(Game1.lastCursorTile - buildingRect.Location.ToVector2() + new Vector2(1, 1)); for (int x = buildingRect.X; x < buildingRect.X + buildingRect.Width; x++) { for (int y = buildingRect.Y; y < buildingRect.Y + buildingRect.Height; y++) { e.SpriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(new Vector2(x * 64, y * 64)), new Rectangle?(new Rectangle(194, 388, 16, 16)), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 1f); } } Helper.Input.Suppress(Config.BuildKey); } else { BuildBuilding(); isBuilding = false; buildingRect = new Rectangle(); } } else { isBuilding = false; buildingRect = new Rectangle(); } if (Game1.currentLocation.modData.TryGetValue($"{ModManifest.UniqueID}/index", out string indexString) && indexString.Length > 0) { string[] parts = indexString.Split('|'); foreach (var part in parts) { DrawBuilding(e.SpriteBatch, new ModularBuilding(Game1.currentLocation.modData[$"{ModManifest.UniqueID}/{part}"])); } } }
private static void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { Point mousePos = Game1.getMousePosition(); if (!phoneOpen) { appRunning = false; runningApp = null; if (Game1.activeClickableMenu is MobilePhoneMenu) { Game1.activeClickableMenu = null; } if ((Game1.displayHUD || Game1.eventUp) && Game1.currentBillboard == 0 && Game1.gameMode == 3 && !Game1.freezeControls && !Game1.panMode && !Game1.HostPaused && !Game1.game1.takingMapScreenshot) { if (clickingPhoneIcon) { if (SHelper.Input.IsDown(SButton.MouseLeft) && lastMousePosition != mousePos) { draggingPhoneIcon = true; Config.PhoneIconOffsetX += mousePos.X - lastMousePosition.X; Config.PhoneIconOffsetY += mousePos.Y - lastMousePosition.Y; phoneIconPosition = GetPhoneIconPosition(); lastMousePosition = mousePos; } } e.SpriteBatch.Draw(iconTexture, phoneIconPosition, Color.White); } return; } if (Game1.game1.takingMapScreenshot) { return; } if (!appRunning) { if (Game1.activeClickableMenu == null) { Game1.activeClickableMenu = new MobilePhoneMenu(); } } else { if (Game1.activeClickableMenu is MobilePhoneMenu) { Game1.activeClickableMenu = null; } } if (draggingPhone) { if (mousePos != lastMousePosition) { int x = mousePos.X - lastMousePosition.X; int y = mousePos.Y - lastMousePosition.Y; if (phoneRotated) { Config.PhoneRotatedOffsetX += x; Config.PhoneRotatedOffsetY += y; } else { Config.PhoneOffsetX += x; Config.PhoneOffsetY += y; } RefreshPhoneLayout(); lastMousePosition = mousePos; } } e.SpriteBatch.Draw(phoneRotated ? backgroundRotatedTexture : backgroundTexture, phonePosition, Color.White); e.SpriteBatch.Draw(phoneRotated ? phoneRotatedTexture : phoneTexture, phonePosition, Color.White); if (appRunning) { return; } List <string> keys = apps.Keys.ToList(); string appHover = null; bool hover = false; if (mousePos == lastPos) { hover = true; } else { ticksSinceMoved = 0; } for (int i = keys.Count - 1; i >= 0; i--) { if (!IsOnScreen(i, topRow)) { continue; } MobileApp app = apps[keys[i]]; if (app.icon == null) { context.Monitor.Log($"no icon for app {app.name}, removing from app list.", LogLevel.Error); apps.Remove(keys[i]); continue; } Vector2 appPos = context.GetAppPos(i); e.SpriteBatch.Draw(app.icon, appPos, Color.White); Rectangle rect = new Rectangle((int)appPos.X, (int)appPos.Y, Config.IconWidth, Config.IconHeight); if (hover && rect.Contains(mousePos)) { ticksSinceMoved++; if (ticksSinceMoved > Config.ToolTipDelayTicks) { appHover = app.name; } } } if (appHover != null) { Utility.drawTextWithShadow(e.SpriteBatch, appHover, Game1.dialogueFont, new Vector2(mousePos.X, mousePos.Y) - Game1.dialogueFont.MeasureString(appHover), Color.White, 1f, -1f, -1, -1, 1f, 3); } lastPos = mousePos; }
private static void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (ModEntry.callingNPC != null) { return; } if (!ModEntry.appRunning || !ModEntry.phoneOpen || ModEntry.runningApp != Helper.ModRegistry.ModID) { ModEntry.appRunning = false; ModEntry.phoneAppRunning = false; Helper.Events.Display.RenderedWorld -= Display_RenderedWorld; Helper.Events.Input.ButtonPressed -= Input_ButtonPressed; Helper.Events.Input.MouseWheelScrolled -= Input_MouseWheelScrolled; return; } Vector2 screenPos = PhoneUtils.GetScreenPosition(); Vector2 screenSize = PhoneUtils.GetScreenSize(); Rectangle headerRect = new Rectangle((int)screenPos.X, (int)screenPos.Y, (int)screenSize.X, Config.AppHeaderHeight); Point mousePos = Game1.getMousePosition(); if (Helper.Input.IsSuppressed(SButton.MouseLeft)) { int dy = mousePos.Y - lastMousePositionY; if (Math.Abs(dy) > 0 && ModEntry.screenRect.Contains(mousePos)) { dragging = true; } if (dragging) { AddYOffset(dy); } } if (clicked && !Helper.Input.IsSuppressed(SButton.MouseLeft)) { clicked = false; if (dragging) { Monitor.Log($"was dragging"); dragging = false; } else { if (headerRect.Contains(mousePos)) { if (new Rectangle((int)screenPos.X + (int)screenSize.X - Config.AppHeaderHeight, (int)screenPos.Y, Config.AppHeaderHeight, Config.AppHeaderHeight).Contains(mousePos)) { PhoneUtils.ToggleApp(false); } } else { for (int i = 0; i < callableList.Count; i++) { Vector2 pos = GetNPCPos(i); Rectangle r = new Rectangle((int)pos.X, (int)pos.Y, Config.ContactWidth, Config.ContactHeight); if (r.Contains(mousePos)) { Monitor.Log($"calling {callableList[i].npc.Name}"); //PhoneUtils.PlayRingTone(); CallNPC(callableList[i].npc); } } } } } lastMousePositionY = Game1.getMouseY(); int startListY = (int)screenPos.Y + Config.AppHeaderHeight; e.SpriteBatch.Draw(ModEntry.phoneBookTexture, screenPos, Color.White); if (yOffset < 0) { e.SpriteBatch.Draw(ModEntry.upArrowTexture, ModEntry.upArrowPosition, Color.White); } if (yOffset > PhoneUtils.GetScreenSize().Y - Config.AppHeaderHeight - listHeight) { e.SpriteBatch.Draw(ModEntry.downArrowTexture, ModEntry.downArrowPosition, Color.White); } int screenBottom = (int)(screenPos.Y + screenSize.Y); for (int i = 0; i < callableList.Count; i++) { Vector2 npcPos = GetNPCPos(i); Rectangle r = callableList[i].sourceRect; if (npcPos.Y < startListY - r.Height * 2 || npcPos.Y >= screenBottom) { continue; } Rectangle sourceRect = r; int cutTop = 0; int cutBottom = 0; if (npcPos.Y < startListY) { cutTop = (int)Math.Round((startListY - (int)npcPos.Y) / 2f); sourceRect = new Rectangle(r.X, r.Y + cutTop, r.Width, r.Height - cutTop); npcPos = new Vector2(npcPos.X, startListY); } else if (npcPos.Y > screenBottom - r.Height * 2) { cutBottom = (int)Math.Round((screenBottom - r.Height * 2 - (int)npcPos.Y) / 2f); sourceRect = new Rectangle(r.X, r.Y, r.Width, r.Height + cutBottom); } int alpha = callableList[i].npc.CurrentDialogue.Any() && !callableList[i].npc.isSleeping ? 255 : Config.UncallableNPCAlpha; e.SpriteBatch.Draw(callableList[i].portrait, npcPos + new Vector2((Config.ContactWidth - 32) / 2f, 0), sourceRect, new Color(255, 255, 255, alpha), 0, Vector2.Zero, 2, SpriteEffects.None, 0.86f); if (Config.ShowNamesInPhoneBook && npcPos.Y < screenBottom - Config.ContactHeight - callableList[i].nameSize.Y * 0.4f + 6) { e.SpriteBatch.DrawString(Game1.dialogueFont, callableList[i].name, GetNPCPos(i) + new Vector2(Config.ContactWidth / 2f - callableList[i].nameSize.X * 0.2f, Config.ContactHeight - 6), Color.Black, 0, Vector2.Zero, 0.4f, SpriteEffects.None, 0.86f); } } e.SpriteBatch.Draw(ModEntry.phoneBookHeaderTexture, headerRect, Color.White); string headerText = Helper.Translation.Get("phone-book"); Vector2 headerTextSize = Game1.dialogueFont.MeasureString(headerText) * Config.HeaderTextScale; e.SpriteBatch.DrawString(Game1.dialogueFont, headerText, screenPos + new Vector2(screenSize.X / 2f - headerTextSize.X / 2f, Config.AppHeaderHeight / 2f - headerTextSize.Y / 2f), Config.PhoneBookHeaderTextColor, 0, Vector2.Zero, Config.HeaderTextScale, SpriteEffects.None, 0.86f); e.SpriteBatch.DrawString(Game1.dialogueFont, "x", screenPos + new Vector2(screenSize.X - Config.AppHeaderHeight / 2f - Game1.dialogueFont.MeasureString("x").X *Config.HeaderTextScale / 2f, Config.AppHeaderHeight / 2f - headerTextSize.Y / 2f), Config.PhoneBookHeaderTextColor, 0, Vector2.Zero, Config.HeaderTextScale, SpriteEffects.None, 0.86f); }
private static void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (ModEntry.callingNPC != null) { return; } if (!ModEntry.appRunning || !ModEntry.phoneOpen || ModEntry.runningApp != Helper.ModRegistry.ModID) { ModEntry.appRunning = false; Helper.Events.Display.RenderedWorld -= Display_RenderedWorld; Helper.Events.Input.ButtonPressed -= Input_ButtonPressed; return; } Vector2 screenPos = PhoneUtils.GetScreenPosition(); Vector2 screenSize = PhoneUtils.GetScreenSize(); Rectangle headerRect = new Rectangle((int)screenPos.X, (int)screenPos.Y, (int)screenSize.X, Config.AppHeaderHeight); Rectangle footerRect = new Rectangle((int)screenPos.X, (int)screenPos.Y + (int)screenSize.Y - Config.AppHeaderHeight, (int)screenSize.X, Config.AppHeaderHeight); Point mousePos = Game1.getMousePosition(); if (Helper.Input.IsSuppressed(SButton.MouseLeft)) { int dy = mousePos.Y - lastMousePositionY; if (Math.Abs(dy) > 0 && ModEntry.screenRect.Contains(mousePos) && !headerRect.Contains(mousePos) && !footerRect.Contains(mousePos)) { dragging = true; } if (dragging) { float listHeight; if (whichTab == 0) { listHeight = skinListHeight; } else if (whichTab == 1) { listHeight = backListHeight; } else { listHeight = ringListHeight; } yOffset = (int)Math.Max(Math.Min(0, yOffset + dy), -1 * Math.Max(0, listHeight - screenSize.Y)); } } if (clicked && !Helper.Input.IsSuppressed(SButton.MouseLeft)) { clicked = false; Monitor.Log($"unclicked"); if (dragging) { Monitor.Log($"was dragging"); dragging = false; } else { if (headerRect.Contains(mousePos)) { if (new Rectangle((int)screenPos.X + (int)screenSize.X - Config.AppHeaderHeight, (int)screenPos.Y, Config.AppHeaderHeight, Config.AppHeaderHeight).Contains(mousePos)) { PhoneUtils.ToggleApp(false); } } else if (footerRect.Contains(mousePos)) { int newTab = (int)((mousePos.X - screenPos.X) / (screenSize.X / 3)); if (whichTab != newTab) { whichTab = newTab; yOffset = 0; int listcount = whichTab == 0 ? skinList.Count : (whichTab == 1 ? backgroundList.Count : ringList.Count); Monitor.Log($"switching to tab {whichTab}: {listcount} items"); } } else { if (whichTab == 0) { for (int i = 0; i < skinList.Count; i++) { Vector2 pos = GetItemPos(i); Rectangle r = new Rectangle((int)pos.X, (int)pos.Y, Config.ThemeItemWidth, Config.ThemeItemHeight); if (r.Contains(mousePos)) { Monitor.Log($"switching to {skinList[i]}"); SetSkin(skinList[i]); } } } else if (whichTab == 1) { for (int i = 0; i < backgroundList.Count; i++) { Vector2 pos = GetItemPos(i); Rectangle r = new Rectangle((int)pos.X, (int)pos.Y, Config.ThemeItemWidth, Config.ThemeItemHeight); if (r.Contains(mousePos)) { Monitor.Log($"switching to {backgroundList[i]}"); SetBackground(backgroundList[i]); } } } else if (whichTab == 2) { for (int i = 0; i < ringList.Count; i++) { Vector2 pos = GetItemPos(i); Rectangle r = new Rectangle((int)pos.X, (int)pos.Y, ModEntry.phoneWidth, Config.RingListItemHeight); if (r.Contains(mousePos)) { Monitor.Log($"switching to {ringList[i]}"); SetRing(ringList[i]); } } } } } } lastMousePositionY = Game1.getMouseY(); int startListY = (int)screenPos.Y + Config.AppHeaderHeight; if (whichTab == 2) { e.SpriteBatch.Draw(ModEntry.ringListBackgroundTexture, ModEntry.screenRect, Color.White); } else { e.SpriteBatch.Draw(ModEntry.backgroundTexture, ModEntry.phoneRect, Color.White); } if (yOffset < 0) { e.SpriteBatch.Draw(ModEntry.upArrowTexture, ModEntry.upArrowPosition, Color.White); } if (yOffset > PhoneUtils.GetScreenSize().Y - Config.AppHeaderHeight - skinListHeight) { e.SpriteBatch.Draw(ModEntry.downArrowTexture, ModEntry.downArrowPosition, Color.White); } int screenBottom = (int)(screenPos.Y + screenSize.Y); int count = whichTab == 0 ? skinList.Count : (whichTab == 1 ? backgroundList.Count : ringList.Count); for (int i = 0; i < count; i++) { Vector2 itemPos = GetItemPos(i); if (whichTab < 2) { Rectangle r = new Rectangle(0, 0, Config.PhoneWidth, Config.PhoneHeight); Rectangle sourceRect = r; Rectangle destRect; destRect = new Rectangle((int)itemPos.X, (int)itemPos.Y, Config.ThemeItemWidth, Config.ThemeItemHeight); float yScale = Config.ThemeItemHeight / (float)Config.PhoneHeight; if (itemPos.Y < startListY - r.Height * yScale || itemPos.Y >= screenBottom) { continue; } int cutTop = 0; int cutBottom = 0; if (itemPos.Y < startListY) { cutTop = (int)Math.Ceiling((startListY - itemPos.Y) / yScale); sourceRect = new Rectangle(r.X, (int)(r.Y + cutTop), r.Width, (int)(r.Height - cutTop)); destRect.Y = startListY; destRect.Height -= (int)(cutTop * yScale); itemPos = new Vector2(itemPos.X, startListY); } else if (itemPos.Y > screenBottom - r.Height * yScale - Config.AppHeaderHeight) { cutBottom = (int)Math.Ceiling((screenBottom - Config.AppHeaderHeight - r.Height * yScale - itemPos.Y) / yScale); destRect.Height += (int)(cutBottom * yScale); sourceRect = new Rectangle(r.X, r.Y, r.Width, r.Height + cutBottom); } Texture2D texture = whichTab == 0 ? skinDict[skinList[i]][0] : backgroundDict[backgroundList[i]][0]; //Monitor.Log($"drawing texture {i} {texture.Width}x{texture.Height} {destRect} {ModEntry.screenRect}"); e.SpriteBatch.Draw(texture, destRect, sourceRect, Color.White); } else { if (itemPos.Y < screenPos.Y || itemPos.Y >= screenBottom - Config.AppHeaderHeight) { continue; } if (ringList[i] == Config.PhoneRingTone) { e.SpriteBatch.Draw(ModEntry.ringListHighlightTexture, new Rectangle((int)(itemPos.X), (int)itemPos.Y, (int)(screenSize.X), Config.RingListItemHeight), Color.White); } string itemName = ringList[i]; if (itemName.Contains(":")) { itemName = itemName.Split(':')[1]; } e.SpriteBatch.DrawString(Game1.dialogueFont, itemName, itemPos, Config.RingListItemColor, 0, Vector2.Zero, Config.RingListItemScale, SpriteEffects.None, 0.86f); } } e.SpriteBatch.Draw(ModEntry.themesHeaderTexture, headerRect, Color.White); e.SpriteBatch.Draw(ModEntry.themesHeaderTexture, footerRect, Color.White); e.SpriteBatch.Draw(ModEntry.themesHighlightTexture, new Rectangle((int)(screenPos.X + (screenSize.X / 3f) * whichTab), screenBottom - Config.AppHeaderHeight, (int)(screenSize.X / 3f), Config.AppHeaderHeight), Color.White); string headerText = Helper.Translation.Get("themes"); string skinsText = Helper.Translation.Get("skins"); string backsText = Helper.Translation.Get("backs"); string ringsText = Helper.Translation.Get("rings"); Vector2 headerTextSize = Game1.dialogueFont.MeasureString(headerText) * Config.HeaderTextScale; Vector2 skinsTextSize = Game1.dialogueFont.MeasureString(skinsText) * Config.TabTextScale; Vector2 backsTextSize = Game1.dialogueFont.MeasureString(backsText) * Config.TabTextScale; Vector2 ringsTextSize = Game1.dialogueFont.MeasureString(ringsText) * Config.TabTextScale; e.SpriteBatch.DrawString(Game1.dialogueFont, headerText, screenPos + new Vector2(screenSize.X / 2f - headerTextSize.X / 2f, Config.AppHeaderHeight / 2f - headerTextSize.Y / 2f), Config.PhoneBookHeaderTextColor, 0, Vector2.Zero, Config.HeaderTextScale, SpriteEffects.None, 0.86f); e.SpriteBatch.DrawString(Game1.dialogueFont, "x", screenPos + new Vector2(screenSize.X - Config.AppHeaderHeight / 2f - Game1.dialogueFont.MeasureString("x").X *Config.HeaderTextScale / 2f, Config.AppHeaderHeight / 2f - headerTextSize.Y / 2f), Config.PhoneBookHeaderTextColor, 0, Vector2.Zero, Config.HeaderTextScale, SpriteEffects.None, 0.86f); e.SpriteBatch.DrawString(Game1.dialogueFont, skinsText, screenPos + new Vector2(screenSize.X / 6f - skinsTextSize.X / 2f, screenSize.Y - Config.AppHeaderHeight / 2f - headerTextSize.Y / 2f), whichTab == 0 ? Config.ThemesHeaderHighlightedTextColor : Config.ThemesHeaderTextColor, 0, Vector2.Zero, Config.TabTextScale, SpriteEffects.None, 0.86f); e.SpriteBatch.DrawString(Game1.dialogueFont, backsText, screenPos + new Vector2(screenSize.X / 2f - backsTextSize.X / 2f, screenSize.Y - Config.AppHeaderHeight / 2f - headerTextSize.Y / 2f), whichTab == 1 ? Config.ThemesHeaderHighlightedTextColor : Config.ThemesHeaderTextColor, 0, Vector2.Zero, Config.TabTextScale, SpriteEffects.None, 0.86f); e.SpriteBatch.DrawString(Game1.dialogueFont, ringsText, screenPos + new Vector2(screenSize.X * 5f / 6f - ringsTextSize.X / 2f, screenSize.Y - Config.AppHeaderHeight / 2f - headerTextSize.Y / 2f), whichTab == 2 ? Config.ThemesHeaderHighlightedTextColor : Config.ThemesHeaderTextColor, 0, Vector2.Zero, Config.TabTextScale, SpriteEffects.None, 0.86f); }
public static void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { Point mousePos = Game1.getMousePosition(); Point lastMousePos = ModEntry.lastMousePosition; ModEntry.lastMousePosition = mousePos; if (!ModEntry.phoneOpen) { ModEntry.appRunning = false; ModEntry.runningApp = null; if (Config.ShowPhoneIcon && Game1.displayHUD && !Game1.eventUp && Game1.currentBillboard == 0 && Game1.gameMode == 3 && !Game1.freezeControls && !Game1.panMode && !Game1.HostPaused && !Game1.game1.takingMapScreenshot) { if (ModEntry.clickingPhoneIcon) { if (Helper.Input.IsSuppressed(SButton.MouseLeft) && lastMousePos != mousePos) { ModEntry.draggingPhoneIcon = true; Config.PhoneIconOffsetX += mousePos.X - lastMousePos.X; Config.PhoneIconOffsetY += mousePos.Y - lastMousePos.Y; ModEntry.phoneIconPosition = PhoneUtils.GetPhoneIconPosition(); } else if (!Helper.Input.IsSuppressed(SButton.MouseLeft)) { if (!ModEntry.draggingPhoneIcon) { PhoneUtils.TogglePhone(true); } else { Helper.WriteConfig(Config); } ModEntry.clickingPhoneIcon = false; ModEntry.draggingPhoneIcon = false; } } e.SpriteBatch.Draw(ModEntry.iconTexture, ModEntry.phoneIconPosition, Color.White); } return; } else { ModEntry.clickingPhoneIcon = false; ModEntry.draggingPhoneIcon = false; } if (Game1.game1.takingMapScreenshot) { return; } if (ModEntry.draggingPhone) { if (Helper.Input.IsSuppressed(SButton.MouseLeft)) { if (mousePos != lastMousePos) { int x = mousePos.X - lastMousePos.X; int y = mousePos.Y - lastMousePos.Y; if (ModEntry.phoneRotated) { Config.PhoneRotatedOffsetX += x; Config.PhoneRotatedOffsetY += y; } else { Config.PhoneOffsetX += x; Config.PhoneOffsetY += y; } PhoneUtils.RefreshPhoneLayout(); } } else { ModEntry.context.Helper.WriteConfig(Config); ModEntry.draggingPhone = false; Monitor.Log($"released dragging phone"); } } else if (Helper.Input.IsSuppressed(SButton.MouseLeft) && !ModEntry.movingAppIcon) { int dy = mousePos.Y - lastMousePos.Y; if (Math.Abs(dy) > 0 && ModEntry.screenRect.Contains(mousePos)) { ModEntry.clickingApp = -1; ModEntry.draggingIcons = true; } if (ModEntry.draggingIcons) { ModEntry.yOffset = (int)Math.Max(Math.Min(0, ModEntry.yOffset + dy), -1 * Math.Max(0, ModEntry.listHeight - PhoneUtils.GetScreenSize().Y)); } } e.SpriteBatch.Draw(ModEntry.phoneRotated ? ModEntry.backgroundRotatedTexture : ModEntry.backgroundTexture, ModEntry.phoneRect, Color.White); e.SpriteBatch.Draw(ModEntry.phoneRotated ? ModEntry.phoneRotatedTexture : ModEntry.phoneTexture, ModEntry.phoneRect, Color.White); Vector2 screenPos = PhoneUtils.GetScreenPosition(); Vector2 screenSize = PhoneUtils.GetScreenSize(); if (ModEntry.callingNPC != null) { Rectangle destRect; Rectangle portraitSource = Game1.getSourceRectForStandardTileSheet(ModEntry.callingNPC.Portrait, 0, 64, 64); float scale; if ((float)portraitSource.Height * screenSize.X / (float)portraitSource.Width > screenSize.Y - Config.AppHeaderHeight) { scale = (screenSize.Y - Config.AppHeaderHeight) / (float)portraitSource.Height; destRect = new Rectangle((int)(screenPos.X + screenSize.X / 2f - portraitSource.Width * scale / 2f), (int)screenPos.Y, (int)(portraitSource.Width * scale), (int)screenSize.Y - Config.AppHeaderHeight); } else { scale = screenSize.X / (float)portraitSource.Width; //Monitor.Log($"{screenSize} {portraitSource.Width},{portraitSource.Height} {scale}"); destRect = new Rectangle((int)(screenPos.X), (int)(screenPos.Y + (screenSize.Y - Config.AppHeaderHeight) / 2f - portraitSource.Height * scale / 2f), (int)screenSize.X, (int)(portraitSource.Height * scale)); } e.SpriteBatch.Draw(ModEntry.callingNPC.Portrait, destRect, new Rectangle?(portraitSource), Color.White); SpriteText.drawStringHorizontallyCenteredAt(e.SpriteBatch, ModEntry.callingNPC.getName(), destRect.X + destRect.Width / 2, destRect.Bottom + 16, 999999, -1, 999999, 1f, 0.88f, false, -1, 99999); if (!ModEntry.inCall) { Rectangle answerRect = new Rectangle((int)(screenPos.X), ModEntry.screenRect.Bottom - Config.AppHeaderHeight, (int)(screenSize.X / 2f), Config.AppHeaderHeight); Rectangle declineRect = new Rectangle((int)(screenPos.X + screenSize.X / 2f), ModEntry.screenRect.Bottom - Config.AppHeaderHeight, (int)(screenSize.X / 2f), Config.AppHeaderHeight); e.SpriteBatch.Draw(ModEntry.answerTexture, answerRect, Color.White); e.SpriteBatch.Draw(ModEntry.declineTexture, declineRect, Color.White); float textScale = Config.CallTextScale; string ans = Helper.Translation.Get("answer"); Vector2 ansSize = Game1.dialogueFont.MeasureString(ans) * textScale; string dec = Helper.Translation.Get("decline"); Vector2 decSize = Game1.dialogueFont.MeasureString(dec) * textScale; e.SpriteBatch.DrawString(Game1.dialogueFont, ans, new Vector2(answerRect.X + answerRect.Width / 2f - ansSize.X / 2f, answerRect.Top + answerRect.Height / 2f - ansSize.Y / 2f), Config.CallTextColor, 0f, Vector2.Zero, textScale, SpriteEffects.None, 1f); e.SpriteBatch.DrawString(Game1.dialogueFont, dec, new Vector2(declineRect.X + declineRect.Width / 2f - decSize.X / 2f, declineRect.Top + declineRect.Height / 2f - decSize.Y / 2f), Config.CallTextColor, 0f, Vector2.Zero, textScale, SpriteEffects.None, 1f); if (ModEntry.clicking && !Helper.Input.IsSuppressed(SButton.MouseLeft)) { if (answerRect.Contains(mousePos)) { MobilePhoneApp.CallNPC(ModEntry.callingNPC); ModEntry.currentCallRings = 0; } else if (declineRect.Contains(mousePos)) { ModEntry.currentCallRings = 0; ModEntry.callingNPC = null; } } } else { Rectangle endRect = new Rectangle((int)(screenPos.X + screenSize.X / 4), ModEntry.screenRect.Bottom - Config.AppHeaderHeight, (int)(screenSize.X / 2), Config.AppHeaderHeight); e.SpriteBatch.Draw(ModEntry.declineTexture, endRect, Color.White); float textScale = Config.CallTextScale; string ends = Helper.Translation.Get("end-call"); Vector2 endsSize = Game1.dialogueFont.MeasureString(ends) * textScale; e.SpriteBatch.DrawString(Game1.dialogueFont, ends, new Vector2(endRect.X + endRect.Width / 2f - endsSize.X / 2f, endRect.Top + endRect.Height / 2f - endsSize.Y / 2f), Config.CallTextColor, 0f, Vector2.Zero, textScale, SpriteEffects.None, 1f); if (ModEntry.clicking && !Helper.Input.IsSuppressed(SButton.MouseLeft)) { if (endRect.Contains(mousePos)) { MobilePhoneCall.EndCall(); if (Game1.activeClickableMenu is DialogueBox) { Game1.activeClickableMenu = null; } } } } if ((ModEntry.clicking || ModEntry.clickingPhoneIcon) && !Helper.Input.IsSuppressed(SButton.MouseLeft)) { ModEntry.clickingApp = -1; ModEntry.switchingApp = -1; ModEntry.movingAppIconOffset = new Point(0, 0); ModEntry.clickingTicks = 0; ModEntry.clicking = false; ModEntry.movingAppIcon = false; ModEntry.clickingPhoneIcon = false; ModEntry.draggingPhone = false; ModEntry.draggingIcons = false; } return; } if (ModEntry.appRunning) { return; } if (ModEntry.runningApp == Helper.ModRegistry.ModID && Game1.activeClickableMenu == null) { MobilePhoneApp.OpenPhoneBook(); return; } List <string> keys = new List <string>(ModEntry.appOrder); if ((ModEntry.clicking || ModEntry.clickingPhoneIcon) && !Helper.Input.IsSuppressed(SButton.MouseLeft)) { Monitor.Log($"released click"); if (ModEntry.movingAppIcon && ModEntry.switchingApp != -1) { Monitor.Log($"switching app: {ModEntry.switchingApp} clicking app {ModEntry.clickingApp}"); Game1.playSound("stoneStep"); ModEntry.appOrder[ModEntry.clickingApp] = keys[ModEntry.switchingApp]; ModEntry.appOrder[ModEntry.switchingApp] = keys[ModEntry.clickingApp]; keys = new List <string>(ModEntry.appOrder); Config.AppList = keys.ToArray(); Helper.WriteConfig(Config); } else if (ModEntry.draggingIcons) { ModEntry.draggingIcons = false; } else if (!ModEntry.movingAppIcon) { for (int i = 0; i < keys.Count; i++) { Vector2 pos = PhoneUtils.GetAppPos(i); Rectangle r = new Rectangle((int)pos.X, (int)pos.Y, Config.IconWidth, Config.IconHeight); if (r.Contains(mousePos)) { if (ModEntry.apps[keys[i]].keyPress != null) { Monitor.Log($"pressing key {ModEntry.apps[keys[i]].keyPress}"); PhoneInput.PressKey(ModEntry.apps[keys[i]]); } else { Monitor.Log($"starting app {ModEntry.apps[keys[i]].name}"); ModEntry.apps[keys[i]].action.Invoke(); } } } } ModEntry.clickingApp = -1; ModEntry.switchingApp = -1; ModEntry.movingAppIconOffset = new Point(0, 0); ModEntry.clickingTicks = 0; ModEntry.clicking = false; ModEntry.movingAppIcon = false; ModEntry.clickingPhoneIcon = false; ModEntry.draggingPhone = false; ModEntry.draggingIcons = false; } else if (ModEntry.clicking && ModEntry.clickingApp != -1 && !ModEntry.movingAppIcon) { if (lastMousePos == mousePos) { if (ModEntry.clickingTicks > Config.TicksToMoveAppIcon) { Game1.playSound("pickUpItem"); ModEntry.movingAppIconOffset = new Point(5, 5); ModEntry.movingAppIcon = true; } else { ModEntry.clickingTicks++; } } else { ModEntry.clickingTicks = 0; ModEntry.clickingApp = -1; } } else if (ModEntry.movingAppIcon) { ModEntry.movingAppIconOffset = new Point(ModEntry.movingAppIconOffset.X + mousePos.X - lastMousePos.X, ModEntry.movingAppIconOffset.Y + mousePos.Y - lastMousePos.Y); Vector2 currentPos = PhoneUtils.GetAppPos(ModEntry.clickingApp); if (ModEntry.screenRect.Contains(Utility.Vector2ToPoint(currentPos))) { bool alreadySwitched = false; if (ModEntry.switchingApp != -1) { Vector2 pos = PhoneUtils.GetAppPos(ModEntry.switchingApp, true); if (Vector2.Distance(currentPos, pos) < (Config.IconWidth + Config.IconHeight) / 4f) { alreadySwitched = true; } } if (!alreadySwitched) { for (int i = 0; i < keys.Count; i++) { Vector2 pos = PhoneUtils.GetAppPos(i); if (i != ModEntry.clickingApp && Vector2.Distance(currentPos, pos) < (Config.IconWidth + Config.IconHeight) / 4f) { ModEntry.switchingApp = i; Monitor.Log($"new switching app: {ModEntry.switchingApp} clicking app {ModEntry.clickingApp}"); break; } else { ModEntry.switchingApp = -1; } } } } } string appHover = null; bool hover = false; if (mousePos == lastMousePos && !Helper.Input.IsSuppressed(SButton.MouseLeft)) { hover = true; } else { ModEntry.ticksSinceMoved = 0; } int screenBottom = (int)(screenPos.Y + screenSize.Y); for (int i = keys.Count - 1; i >= 0; i--) { MobileApp app = ModEntry.apps[keys[i]]; Vector2 appPos = PhoneUtils.GetAppPos(i); Rectangle r = new Rectangle(0, 0, Config.IconWidth, Config.IconHeight); Rectangle sourceRect = r; if (!ModEntry.movingAppIcon || i != ModEntry.clickingApp) { if (appPos.Y < screenPos.Y - r.Height * 2 || appPos.Y >= screenBottom) { continue; } if (appPos.Y < screenPos.Y) { int cutTop = (int)screenPos.Y - (int)appPos.Y; sourceRect = new Rectangle(r.X, r.Y + cutTop, r.Width, r.Height - cutTop); appPos = new Vector2(appPos.X, screenPos.Y); } else if (appPos.Y > screenBottom - r.Height) { int cutBottom = screenBottom - r.Height - (int)appPos.Y; sourceRect = new Rectangle(r.X, r.Y, r.Width, r.Height + cutBottom); } } e.SpriteBatch.Draw(app.icon, new Rectangle((int)appPos.X, (int)appPos.Y, sourceRect.Width, sourceRect.Height), sourceRect, Color.White, 0, Vector2.Zero, SpriteEffects.None, i == ModEntry.clickingApp && ModEntry.movingAppIcon ? 1f : 0.5f); Rectangle rect = new Rectangle((int)appPos.X, (int)appPos.Y, Config.IconWidth, sourceRect.Height); if (hover && !Helper.Input.IsSuppressed(SButton.MouseLeft) && rect.Contains(mousePos)) { ModEntry.ticksSinceMoved++; if (ModEntry.ticksSinceMoved > Config.ToolTipDelayTicks) { appHover = app.name; } } } if (appHover != null) { e.SpriteBatch.DrawString(Game1.dialogueFont, appHover, new Vector2(mousePos.X, mousePos.Y) - Game1.dialogueFont.MeasureString(appHover) + new Vector2(-2, 2), Color.Black); e.SpriteBatch.DrawString(Game1.dialogueFont, appHover, new Vector2(mousePos.X, mousePos.Y) - Game1.dialogueFont.MeasureString(appHover), Color.White); } }
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 void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e) { if (!Config.EnableMod || !ShowingGrid || Game1.activeClickableMenu != null) { return; } string location = Game1.player.currentLocation.NameOrUniqueName; if (!utilitySystemDict.ContainsKey(location)) { RemakeAllGroups(location); } Dictionary <Vector2, GridPipe> pipeDict = utilitySystemDict[location][CurrentGrid].pipes; List <PipeGroup> groupList = utilitySystemDict[location][CurrentGrid].groups; Dictionary <Vector2, UtilityObjectInstance> objectDict = utilitySystemDict[location][CurrentGrid].objects; Color color = CurrentGrid == GridType.electric ? Config.ElectricityColor : Config.WaterColor; foreach (var group in groupList) { Vector2 power = GetGroupPower(location, group, CurrentGrid); Vector2 storedPower = GetGroupStoragePower(location, group, CurrentGrid); float netPower = power.X + power.Y; bool powered = power.X > 0 && netPower + storedPower.X >= 0; foreach (var pipe in group.pipes) { if (Utility.isOnScreen(new Vector2(pipe.X * 64 + 32, pipe.Y * 64 + 32), 32)) { if (pipeDict[pipe].index == 4) { DrawTile(e.SpriteBatch, pipe, new GridPipe() { index = 1, rotation = 2 }, powered ? color : Config.UnpoweredGridColor); } else { DrawTile(e.SpriteBatch, pipe, pipeDict[pipe], powered ? color : Config.UnpoweredGridColor); } } } } foreach (var kvp in objectDict) { DrawAmount(e.SpriteBatch, kvp, kvp.Value.CurrentPowerVector.X + kvp.Value.CurrentPowerVector.Y, color); DrawCharge(e.SpriteBatch, kvp, color); } if (ShowingEdit) { if (CurrentTile == 4) { DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(-2, 2) / 64, new GridPipe() { index = 1, rotation = 2 }, Config.ShadowColor); DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(-2, -2) / 64, new GridPipe() { index = 1, rotation = 2 }, Config.ShadowColor); DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(2, -2) / 64, new GridPipe() { index = 1, rotation = 2 }, Config.ShadowColor); DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(2, 2) / 64, new GridPipe() { index = 1, rotation = 2 }, Config.ShadowColor); DrawTile(e.SpriteBatch, Game1.currentCursorTile, new GridPipe() { index = 1, rotation = 2 }, color); } else if (CurrentTile != 5) { DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(-2, 2) / 64, new GridPipe() { index = CurrentTile, rotation = CurrentRotation }, Config.ShadowColor); DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(-2, -2) / 64, new GridPipe() { index = CurrentTile, rotation = CurrentRotation }, Config.ShadowColor); DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(2, -2) / 64, new GridPipe() { index = CurrentTile, rotation = CurrentRotation }, Config.ShadowColor); DrawTile(e.SpriteBatch, Game1.currentCursorTile + new Vector2(2, 2) / 64, new GridPipe() { index = CurrentTile, rotation = CurrentRotation }, Config.ShadowColor); DrawTile(e.SpriteBatch, Game1.currentCursorTile, new GridPipe() { index = CurrentTile, rotation = CurrentRotation }, color); } if (Helper.Input.IsDown(Config.PlaceTile) || Helper.Input.IsSuppressed(Config.PlaceTile)) { if (lastCursorTile != Game1.lastCursorTile) { Helper.Input.Suppress(Config.PlaceTile); lastCursorTile = Game1.lastCursorTile; if (pipeDict.ContainsKey(Game1.lastCursorTile)) { if (!PayForPipe(true)) { return; } Monitor.Log($"Removing tile at {Game1.currentCursorTile}"); } else if (!PayForPipe(false)) { return; } Monitor.Log($"Placing tile {CurrentTile},{CurrentRotation} at {Game1.currentCursorTile}"); pipeDict[Game1.lastCursorTile] = new GridPipe() { index = CurrentTile, rotation = CurrentRotation }; if (Config.PipeSound?.Length > 0) { Game1.player.currentLocation.playSound(Config.PipeSound); } RemakeGroups(location, CurrentGrid); } } else { lastCursorTile = new Vector2(-1, -1); } } }