Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A Complete Builder Toggle API #3943

Merged
merged 11 commits into from
Feb 15, 2024
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using Terraria.Audio;
using Terraria.DataStructures;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;

namespace ExampleMod.Content
namespace ExampleMod.Content.BuilderToggles
{
// The examples in this file don't actually affect anything, they just show typical approaches for the BuilderToggle half of the effect.
// A full example would have code doing something, such as drawing an overlay, after checking ModContent.GetInstance<YourBuilderToggle>().Active and ModContent.GetInstance<YourBuilderToggle>().CurrentState.
Expand All @@ -14,17 +18,29 @@ public class ExampleBuilderToggle : BuilderToggle
public override bool Active() => Main.LocalPlayer.HeldItem.IsAir;

public override int NumberOfStates => 4;

public override string DisplayValue() {
string text = "Color: ";
string[] textMessages = new[] { "Red", "Blue", "Green", "Yellow" };

return text + textMessages[CurrentState];
}

public override Color DisplayColorTexture() {
public override bool Draw(SpriteBatch spriteBatch, ref BuilderToggleDrawParams drawParams) {
Color[] colors = new[] { Color.Red, Color.Blue, Color.Green, Color.Yellow };
drawParams.Color = colors[CurrentState];
return true;
}


// Right click to cycle through states backwards.
public override void OnRightClick() {
CurrentState -= 1;
if (CurrentState < 0) {
CurrentState = NumberOfStates - 1;
}

return colors[CurrentState];
SoundEngine.PlaySound(SoundID.Coins);
}
}

Expand All @@ -33,7 +49,7 @@ public class ExampleBuilderToggleDimmedLight : BuilderToggle
public static LocalizedText OnText { get; private set; }
public static LocalizedText OffText { get; private set; }

public override string Texture => "ExampleMod/Content/ExampleBuilderToggle";
public override string Texture => "ExampleMod/Content/BuilderToggles/ExampleBuilderToggle";
public override bool Active() => true;
public override int NumberOfStates => 2;

Expand All @@ -46,8 +62,9 @@ public override string DisplayValue() {
return CurrentState == 0 ? OnText.Value : OffText.Value;
}

public override Color DisplayColorTexture() {
return CurrentState == 0 ? Color.White : new Color(127, 127, 127);
public override bool Draw(SpriteBatch spriteBatch, ref BuilderToggleDrawParams drawParams) {
drawParams.Color = CurrentState == 0 ? Color.White : new Color(127, 127, 127);
return true;
}
}
}
78 changes: 78 additions & 0 deletions ExampleMod/Content/BuilderToggles/FreeBaitBuilderToggle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using Terraria;
using Terraria.Audio;
using Terraria.DataStructures;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;

namespace ExampleMod.Content.BuilderToggles;

// This example shows almost all BuilderToggle hooks.
// As it is just an example, it behaves more like a "button" than a "toggle".
// Left clicking allows you to select bait type and right clicking gives you 10 free bait of the selected type.
// Custom drawing is showcased in this example to handle frame changes.
public class FreeBaitBuilderToggle : BuilderToggle
{
public static LocalizedText NameText { get; private set; }

public override string HoverTexture => Texture;

public override bool Active() => !Main.LocalPlayer.HeldItem.IsAir && Main.LocalPlayer.HeldItem.fishingPole > 0;

public override int NumberOfStates => 4;

// Sorted after Torch God toggle because that would be cool.
public override Position OrderPosition => new After(TorchBiome);

public override bool OnLeftClick(ref SoundStyle? sound) {
// Change the click sound.
// If you don't want a sound to play, set sound to null.
sound = SoundID.DrumTomHigh;
return true;
}

public override void OnRightClick() {
// Give the player free baits when right clicked.
SoundEngine.PlaySound(Main.rand.NextBool() ? SoundID.DrumCymbal1 : SoundID.DrumCymbal2);
int itemType = CurrentState switch {
0 => ItemID.ApprenticeBait,
1 => ItemID.JourneymanBait,
2 => ItemID.MasterBait,
3 => ItemID.TruffleWorm,
_ => throw new ArgumentOutOfRangeException()
};

Main.LocalPlayer.QuickSpawnItem(new EntitySource_Gift(Main.LocalPlayer), itemType, 10);
}

// Use custom drawing to handle frame changes.
public override bool Draw(SpriteBatch spriteBatch, ref BuilderToggleDrawParams drawParams) {
drawParams.Frame = drawParams.Texture.Frame(4, 2, CurrentState % 4);
return true;
}

// Truffle Worm has a unique hover texture.
public override bool DrawHover(SpriteBatch spriteBatch, ref BuilderToggleDrawParams drawParams) {
int column = CurrentState == 3 ? 1 : 0; // The hover texture for TruffleWorm is unique
drawParams.Frame = drawParams.Texture.Frame(4, 2, column, 1);
return true;
}

public override void SetStaticDefaults() {
NameText = this.GetLocalization(nameof(NameText));
}

public override string DisplayValue() {
string itemName = CurrentState switch {
0 => Lang.GetItemNameValue(ItemID.ApprenticeBait),
1 => Lang.GetItemNameValue(ItemID.JourneymanBait),
2 => Lang.GetItemNameValue(ItemID.MasterBait),
3 => Lang.GetItemNameValue(ItemID.TruffleWorm),
_ => "Unknown (How did you get here?)"
};
return NameText.Format(itemName);
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions ExampleMod/Localization/TranslationsNeeded.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
en-US, 533/533, 100%, missing 0
ru-RU, 6/533, 1%, missing 527
zh-Hans, 1/533, 0%, missing 532
en-US, 534/534, 100%, missing 0
ru-RU, 7/534, 1%, missing 527
zh-Hans, 2/534, 0%, missing 532
2 changes: 2 additions & 0 deletions ExampleMod/Localization/en-US.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,8 @@ Mods: {
OnText: Example On
OffText: Example Off
}

FreeBaitBuilderToggle.NameText: Free Bait: {0}
}

# This is the command names for mod emotes
Expand Down
2 changes: 2 additions & 0 deletions ExampleMod/Localization/ru-RU.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,8 @@ Mods: {
// OnText: Example On
// OffText: Example Off
}

FreeBaitBuilderToggle.NameText: Бесплатная наживка: {0}
}

# This is the command names for mod emotes
Expand Down
2 changes: 2 additions & 0 deletions ExampleMod/Localization/zh-Hans.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,8 @@ Mods: {
// OnText: Example On
// OffText: Example Off
}

FreeBaitBuilderToggle.NameText: 免费鱼饵:{0}
}

# This is the command names for mod emotes
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Terraria.DataStructures;

/// <summary>
/// Holds data required for builder toggle drawing.
/// </summary>
public struct BuilderToggleDrawParams
{
/// <summary> The icon or icon hover texture </summary>
public Texture2D Texture = default;
/// <summary> The position </summary>
public Vector2 Position = default;
/// <summary> The frame rectangle (aka source rectangle) </summary>
public Rectangle Frame = default;
/// <summary> The color the icon or icon hover is drawn in. Defaults to White for icon, <see cref="Main.OurFavoriteColor"/> (yellow) for icon hover. </summary>
public Color Color = Color.White;
/// <summary> The scale of the icon or icon hover </summary>
public float Scale = 1f;
/// <summary> The spriteEffects </summary>
public SpriteEffects SpriteEffects = 0;

public BuilderToggleDrawParams() { }
}
73 changes: 47 additions & 26 deletions patches/tModLoader/Terraria/Main.TML.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ public static void BuilderTogglePageHandler(int startY, int activeToggles, out b
hover = true;

player[myPlayer].mouseInterface = true;
text = "Previous Page";
text = Language.GetTextValue("tModLoader.PreviousInfoAccPage");
mouseText = true;

if (mouseLeft && mouseLeftRelease) {
Expand All @@ -226,7 +226,7 @@ public static void BuilderTogglePageHandler(int startY, int activeToggles, out b
hover = true;

player[myPlayer].mouseInterface = true;
text = "Next Page";
text = Language.GetTextValue("tModLoader.NextInfoAccPage");
mouseText = true;

if (mouseLeft && mouseLeftRelease) {
Expand Down Expand Up @@ -266,7 +266,7 @@ private void DrawBuilderAccToggles_Inner(Vector2 start)

Texture2D texture = ModContent.Request<Texture2D>(builderToggle.Texture).Value;
Rectangle rectangle = new Rectangle(0, 0, texture.Width, texture.Height);
Color color = builderToggle.DisplayColorTexture();
Color color = builderToggle.DisplayColorTexture_Obsolete();

Vector2 position = startPosition + new Vector2(0, moveDownForButton ? 24 : 0) + new Vector2(0, (i % 12) * 24);
text = builderToggle.DisplayValue();
Expand All @@ -279,46 +279,67 @@ private void DrawBuilderAccToggles_Inner(Vector2 start)
*/

bool hover = Utils.CenteredRectangle(position, new Vector2(14f)).Contains(MouseScreen.ToPoint()) && !PlayerInput.IgnoreMouseInterface;
bool click = hover && mouseLeft && mouseLeftRelease;

if (toggleType == BuilderToggle.BlockSwap.Type || toggleType == BuilderToggle.TorchBiome.Type) {
if (toggleType == BuilderToggle.BlockSwap.Type)
rectangle = texture.Frame(3, 1, builderToggle.CurrentState != 0 ? 1 : 0);
else
rectangle = texture.Frame(4, 1, builderToggle.CurrentState == 0 ? 1 : 0);

position += new Vector2(1, 0);
}
else
rectangle = builderToggle.Type < 10 ? new Rectangle(builderToggle.Type * 16, 16, 14, 14) : rectangle;
bool leftClick = hover && mouseLeft && mouseLeftRelease;
bool rightClick = hover && mouseRight && mouseRightRelease;

/*
BuilderToggleLoader.ModifyDisplayColor(builderToggle, ref color);
BuilderToggleLoader.ModifyDisplayTexture(builderToggle, ref texture, ref rectangle);
*/

spriteBatch.Draw(texture, position, rectangle, color, 0f, rectangle.Size() / 2f, 1f, SpriteEffects.None, 0f);
// Save the original position for hover texture drawing so it won't be confusing
Vector2 hoverDrawPosition = position;
float scale = 1f;
SpriteEffects spriteEffects = SpriteEffects.None;

BuilderToggleDrawParams drawParams = new() {
Texture = texture,
Position = position,
Frame = rectangle,
Color = color,
Scale = scale,
SpriteEffects = spriteEffects
};
if (builderToggle.Draw(spriteBatch, ref drawParams)) {
spriteBatch.Draw(drawParams.Texture, drawParams.Position, drawParams.Frame, drawParams.Color, 0f, drawParams.Frame.Size() / 2f, drawParams.Scale, drawParams.SpriteEffects, 0f);
}

if (hover) {
player.mouseInterface = true;
mouseText = true;

if (toggleType != BuilderToggle.BlockSwap.Type && toggleType != BuilderToggle.TorchBiome.Type) {
Asset<Texture2D> iconHover = ModContent.Request<Texture2D>(builderToggle.HoverTexture);
spriteBatch.Draw(iconHover.Value, position, null, OurFavoriteColor, 0f, iconHover.Value.Size() / 2f, 1f, SpriteEffects.None, 0f);
Texture2D iconHover = ModContent.Request<Texture2D>(builderToggle.HoverTexture).Value;
Rectangle hoverRectangle = new Rectangle(0, 0, iconHover.Width, iconHover.Height);
Color hoverColor = OurFavoriteColor;
float hoverScale = 1f;
SpriteEffects hoverSpriteEffects = SpriteEffects.None;
drawParams = new() {
Texture = iconHover,
Position = hoverDrawPosition,
Frame = hoverRectangle,
Color = hoverColor,
Scale = hoverScale,
SpriteEffects = hoverSpriteEffects
};
if (builderToggle.DrawHover(spriteBatch, ref drawParams)) {
spriteBatch.Draw(drawParams.Texture, drawParams.Position, drawParams.Frame, drawParams.Color, 0f, drawParams.Frame.Size() / 2f, drawParams.Scale, drawParams.SpriteEffects, 0f);
}
else if (toggleType == BuilderToggle.BlockSwap.Type)
spriteBatch.Draw(texture, position, texture.Frame(3, 1, 2), OurFavoriteColor, 0f, rectangle.Size() / 2f, 0.9f, SpriteEffects.None, 0f);
else if (toggleType == BuilderToggle.TorchBiome.Type)
spriteBatch.Draw(texture, position, texture.Frame(4, 1, builderToggle.CurrentState == 0 ? 3 : 2), OurFavoriteColor, 0f, rectangle.Size() / 2f, 0.9f, SpriteEffects.None, 0f);
}

if (click) {
builderAccStatus[toggleType] = (builderAccStatus[toggleType] + 1) % numberOfStates;
SoundEngine.PlaySound((toggleType == BuilderToggle.BlockSwap.Type || toggleType == BuilderToggle.TorchBiome.Type) ? SoundID.Unlock : SoundID.MenuTick);
if (leftClick) {
SoundStyle? sound = SoundID.MenuTick;
if (builderToggle.OnLeftClick(ref sound)) {
builderAccStatus[toggleType] = (builderAccStatus[toggleType] + 1) % numberOfStates;
SoundEngine.PlaySound(sound);
}
mouseLeftRelease = false;
}

if (rightClick) {
builderToggle.OnRightClick();
mouseRightRelease = false;
}


UILinkPointNavigator.SetPosition(6000 + i % 12, position + rectangle.Size() * 0.15f);

Expand Down
Loading