diff --git a/src/main/java/org/saturnclient/ui/components/CosmeticPreview.java b/src/main/java/org/saturnclient/ui/components/CosmeticPreview.java deleted file mode 100644 index 81935ad..0000000 --- a/src/main/java/org/saturnclient/ui/components/CosmeticPreview.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.saturnclient.ui.components; - -import org.saturnclient.common.ref.asset.IdentifierRef; -import org.saturnclient.config.Theme; -import org.saturnclient.ui.Element; -import org.saturnclient.ui.ElementContext; -import org.saturnclient.ui.RenderScope; - -public class CosmeticPreview extends Element { - static int padding = 14; - - IdentifierRef sprite; - private Runnable onClick; - private boolean isSelected; - - public CosmeticPreview(boolean isSelected, IdentifierRef sprite, Runnable onClick) { - this.sprite = sprite; - this.onClick = onClick; - this.isSelected = isSelected; - - this.width = 50; - this.height = 111; - } - - @Override - public void render(RenderScope renderScope, ElementContext ctx) { - renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, - isSelected ? Theme.ACCENT.value : Theme.PRIMARY.value); - - int texWidth = width - padding; - int texHeight = height - padding; - - renderScope.drawTexture(sprite, padding / 2, padding / 2, 0, 0, texWidth, texHeight, - Theme.FOREGROUND.value); - } - - @Override - public void click(int mouseX, int mouseY) { - if (onClick != null) { - onClick.run(); - } - } -} diff --git a/src/main/java/org/saturnclient/ui/components/CosmeticTile.java b/src/main/java/org/saturnclient/ui/components/CosmeticTile.java new file mode 100644 index 0000000..2d25666 --- /dev/null +++ b/src/main/java/org/saturnclient/ui/components/CosmeticTile.java @@ -0,0 +1,125 @@ +package org.saturnclient.ui.components; + +import java.util.function.BooleanSupplier; + +import org.saturnclient.common.ref.asset.IdentifierRef; +import org.saturnclient.config.Theme; +import org.saturnclient.ui.Element; +import org.saturnclient.ui.ElementContext; +import org.saturnclient.ui.RenderScope; +import org.saturnclient.ui.resources.Fonts; +import org.saturnclient.ui.resources.Textures; + +/** + * One cosmetic in the cosmetics grid: its preview and name. It shows whether + * it's equipped, and cosmetics not owned yet are dimmed with a "Get" label. + */ +public class CosmeticTile extends Element { + public static final int HEIGHT = 168; + + private static final int INSET = 8; + private static final int IMAGE_AREA = 124; + private static final float NAME_SCALE = 0.62f; + private static final float BADGE_SCALE = 0.54f; + private static final int BADGE_HEIGHT = 20; + /** How long a claim may take before it can be tried again, in ms */ + private static final long CLAIM_TIMEOUT = 5000; + + private final String name; + private final IdentifierRef preview; + private final float previewAspect; + private final BooleanSupplier owned; + private final BooleanSupplier equipped; + private final Runnable onEquip; + private final Runnable onClaim; + + private long claimedAt = 0; + + /** + * @param previewAspect the preview texture's width divided by its height + */ + public CosmeticTile(String name, IdentifierRef preview, float previewAspect, int width, BooleanSupplier owned, + BooleanSupplier equipped, Runnable onEquip, Runnable onClaim) { + this.name = name; + this.preview = preview; + this.previewAspect = previewAspect; + this.owned = owned; + this.equipped = equipped; + this.onEquip = onEquip; + this.onClaim = onClaim; + this.width = width; + this.height = HEIGHT; + } + + @Override + public void render(RenderScope renderScope, ElementContext ctx) { + boolean isOwned = owned.getAsBoolean(); + boolean isEquipped = equipped.getAsBoolean(); + boolean hovered = ctx.isHovering(); + + int border = isEquipped ? Theme.ACCENT.value + : Theme.withAlpha(hovered ? 0.22f : 0.06f, Theme.FOREGROUND.value); + renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, isEquipped ? 2 : 1, + Theme.withAlpha(0.72f, Theme.PRIMARY.value), border); + + // Preview, fitted into its area + int areaWidth = width - INSET * 2; + renderScope.drawRoundedRectangle(INSET, INSET, areaWidth, IMAGE_AREA, Theme.WIDGET_RADIUS.value - 2, + Theme.withAlpha(0.05f, Theme.FOREGROUND.value)); + + int imageHeight = IMAGE_AREA - 12; + int imageWidth = (int) (imageHeight * previewAspect); + if (imageWidth > areaWidth - 12) { + imageWidth = areaWidth - 12; + imageHeight = (int) (imageWidth / previewAspect); + } + + renderScope.drawTexture(preview, INSET + (areaWidth - imageWidth) / 2, INSET + (IMAGE_AREA - imageHeight) / 2, + 0, 0, imageWidth, imageHeight, isOwned ? 0xFFFFFFFF : Theme.withAlpha(0.35f, 0xFFFFFFFF)); + + // Name + int nameY = INSET + IMAGE_AREA + (HEIGHT - INSET - IMAGE_AREA - (int) (Fonts.getHeight() * NAME_SCALE)) / 2; + renderScope.drawText(NAME_SCALE, Fonts.ellipsize(name, Theme.FONT.value, NAME_SCALE, width - 24), 12, nameY, + Theme.FONT.value, isOwned ? Theme.FOREGROUND.value : Theme.getMutedFg()); + + // Badge in the preview's corner + if (isEquipped) { + drawBadge(renderScope, "On", Theme.ACCENT.value, Theme.ACCENT_FG.value, true); + } else if (!isOwned) { + drawBadge(renderScope, isClaiming() ? "Claiming" : "Get", hovered ? Theme.ACCENT.value : Theme.PRIMARY.value, + hovered ? Theme.ACCENT_FG.value : Theme.PRIMARY_FG.value, false); + } + } + + private void drawBadge(RenderScope renderScope, String text, int background, int foreground, boolean check) { + int icon = check ? 10 : 0; + int badgeWidth = 14 + icon + (check ? 4 : 0) + (int) (Fonts.getWidth(text, Theme.FONT.value) * BADGE_SCALE); + int x = width - INSET - 6 - badgeWidth; + int y = INSET + 6; + + renderScope.drawRoundedRectangle(x, y, badgeWidth, BADGE_HEIGHT, 6, background); + + if (check) { + renderScope.drawTexture(Textures.CHECK, x + 7, y + (BADGE_HEIGHT - icon) / 2, 0, 0, icon, icon, foreground); + } + + int textY = y + (BADGE_HEIGHT - (int) (Fonts.getHeight() * BADGE_SCALE)) / 2; + renderScope.drawText(BADGE_SCALE, text, x + 7 + icon + (check ? 4 : 0), textY, Theme.FONT.value, foreground); + } + + @Override + public void click(int mouseX, int mouseY) { + if (owned.getAsBoolean()) { + if (!equipped.getAsBoolean()) { + onEquip.run(); + } + } else if (!isClaiming()) { + claimedAt = System.currentTimeMillis(); + onClaim.run(); + } + } + + private boolean isClaiming() { + return System.currentTimeMillis() - claimedAt < CLAIM_TIMEOUT; + } +} diff --git a/src/main/java/org/saturnclient/ui/components/Sidebar.java b/src/main/java/org/saturnclient/ui/components/Sidebar.java index 636ed9c..1aabfae 100644 --- a/src/main/java/org/saturnclient/ui/components/Sidebar.java +++ b/src/main/java/org/saturnclient/ui/components/Sidebar.java @@ -11,7 +11,7 @@ import org.saturnclient.ui.resources.Textures; import org.saturnclient.ui.screens.ClientSettings; import org.saturnclient.ui.screens.HudEditor; import org.saturnclient.ui.screens.ModMenu; -import org.saturnclient.ui.screens.cosmetics.CloakMenu; +import org.saturnclient.ui.screens.CosmeticsMenu; /** * The navigation rail beside Saturn's screens: the logo, one button per screen, @@ -37,7 +37,7 @@ public class Sidebar extends Element { private final Item[] items = { new Item(Textures.ICON_MODS, () -> Providers.saturn.getClient().setScreen(new ModMenu())), - new Item(Textures.ICON_COSMETICS, () -> Providers.saturn.getClient().setScreen(new CloakMenu())), + new Item(Textures.ICON_COSMETICS, () -> Providers.saturn.getClient().setScreen(new CosmeticsMenu())), new Item(Textures.ICON_HUD_EDITOR, () -> Providers.saturn.getClient().setScreen(new HudEditor())), new Item(Textures.ICON_SETTINGS, () -> Providers.saturn.getClient().setScreen(new ClientSettings())), }; diff --git a/src/main/java/org/saturnclient/ui/components/SkinPreview.java b/src/main/java/org/saturnclient/ui/components/SkinPreview.java index 1686c75..48a2b06 100644 --- a/src/main/java/org/saturnclient/ui/components/SkinPreview.java +++ b/src/main/java/org/saturnclient/ui/components/SkinPreview.java @@ -1,26 +1,68 @@ package org.saturnclient.ui.components; +import org.saturnclient.config.Theme; import org.saturnclient.ui.Element; import org.saturnclient.ui.ElementContext; import org.saturnclient.ui.RenderScope; +import org.saturnclient.ui.resources.Fonts; +/** + * The player, wearing their cosmetics, filling the element. Dragging it turns + * the player around. + */ public class SkinPreview extends Element { public static EntityDrawer DRAWER; - private boolean negativeAngle = false; - private float angle = 0.0f; - public SkinPreview(float angle, boolean negativeAngle) { - this.angle = angle; - this.negativeAngle = negativeAngle; + /** Degrees turned per GUI pixel dragged */ + private static final float DRAG_SPEED = 1.2f; + private static final float HINT_SCALE = 0.66f; + + private float yaw; + private boolean dragging = false; + + /** + * @param yaw degrees the player starts turned by: 0 faces the viewer, 180 + * shows their back + */ + public SkinPreview(float yaw) { + this.yaw = yaw; } @Override public void render(RenderScope renderScope, ElementContext ctx) { - DRAWER.render(renderScope, negativeAngle, angle, scale, ctx); + if (DRAWER != null && DRAWER.render(renderScope, width, height, yaw)) { + return; + } + + String hint = "Join a world to preview"; + int x = (width - (int) (Fonts.getWidth(hint, Theme.getBodyFont()) * HINT_SCALE)) / 2; + renderScope.drawText(HINT_SCALE, hint, x, height / 2, Theme.getBodyFont(), Theme.getMutedFg()); + } + + @Override + public void mouseClicked(double mouseX, double mouseY, int button) { + dragging = mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height; + } + + @Override + public void mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + if (dragging) { + yaw = (yaw - (float) deltaX * DRAG_SPEED) % 360; + } + } + + @Override + public void mouseReleased(double mouseX, double mouseY, int button) { + dragging = false; } public static interface EntityDrawer { - public void render(RenderScope renderScope, boolean negativeAngle, float angle, float scale, - ElementContext ctx); + /** + * Draws the client's player filling a {@code width} x {@code height} box, + * turned by {@code yaw} degrees (0 faces the viewer). + * + * @return false if there's no player to draw, such as on the title screen + */ + public boolean render(RenderScope renderScope, int width, int height, float yaw); } } diff --git a/src/main/java/org/saturnclient/ui/elements/TabMenu.java b/src/main/java/org/saturnclient/ui/elements/TabMenu.java deleted file mode 100644 index 6998d11..0000000 --- a/src/main/java/org/saturnclient/ui/elements/TabMenu.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.saturnclient.ui.elements; - -import org.saturnclient.common.ref.asset.IdentifierRef; -import org.saturnclient.config.Theme; -import org.saturnclient.ui.Element; -import org.saturnclient.ui.ElementContext; -import org.saturnclient.ui.RenderScope; -import org.saturnclient.ui.Utils; - -public class TabMenu extends Element { - public static class TabMenuComponent { - Runnable onClick; - IdentifierRef sprite; - - public TabMenuComponent(IdentifierRef sprite, Runnable onClick) { - this.onClick = onClick; - this.sprite = sprite; - } - } - - TabMenuComponent[] components; - public int selectedScreen = 0; - - public TabMenu(int active, TabMenuComponent... components) { - this.components = components; - width = 25 * components.length + 6; - height = 30; - this.selectedScreen = active; - } - - @Override - public void render(RenderScope renderScope, ElementContext ctx) { - renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, Theme.PRIMARY.value); - - int col = 0; - for (TabMenuComponent component : components) { - int x = 25 * col + 5; - - boolean hovering = ctx.isHovering(x, 5, 20, 20) || selectedScreen == col; - - if (hovering) { - renderScope.drawRoundedRectangle(x, 5, 20, 20, Theme.WIDGET_RADIUS.value, Theme.ACCENT.value); - } - - renderScope.drawTexture(component.sprite, x + 5, 10, 0, 0, 10, 10, - hovering ? Theme.ACCENT_FG.value : Theme.PRIMARY_FG.value); - - col++; - } - } - - @Override - public void click(int mouseX, int mouseY) { - int col = 0; - for (TabMenuComponent component : components) { - int x = 25 * col + 5; - if (Utils.isHovering(mouseX - x, mouseY - 5, 20, 20, 1.0f)) { - component.onClick.run(); - } - col++; - } - } -} diff --git a/src/main/java/org/saturnclient/ui/screens/CosmeticsMenu.java b/src/main/java/org/saturnclient/ui/screens/CosmeticsMenu.java new file mode 100644 index 0000000..738a3d3 --- /dev/null +++ b/src/main/java/org/saturnclient/ui/screens/CosmeticsMenu.java @@ -0,0 +1,233 @@ +package org.saturnclient.ui.screens; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.saturnclient.client.ServiceClient; +import org.saturnclient.client.player.SaturnPlayer; +import org.saturnclient.common.ref.asset.IdentifierRef; +import org.saturnclient.config.AnimationConfig; +import org.saturnclient.config.Theme; +import org.saturnclient.cosmetics.Cloaks; +import org.saturnclient.cosmetics.Hats; +import org.saturnclient.ui.Element; +import org.saturnclient.ui.ElementContext; +import org.saturnclient.ui.PanelScreen; +import org.saturnclient.ui.RenderScope; +import org.saturnclient.ui.anim.SlideFade; +import org.saturnclient.ui.components.CosmeticTile; +import org.saturnclient.ui.components.Sidebar; +import org.saturnclient.ui.components.SkinPreview; +import org.saturnclient.ui.elements.AnimationStagger; +import org.saturnclient.ui.elements.ChipGroup; +import org.saturnclient.ui.elements.Label; +import org.saturnclient.ui.elements.Scroll; +import org.saturnclient.ui.resources.Fonts; +import org.saturnclient.ui.resources.Textures; + +/** + * Cloaks and hats: the player on the left, turned by dragging, and a grid of + * every cosmetic on the right. Clicking an owned cosmetic equips it; clicking + * one not owned yet claims it, which is free. + */ +public class CosmeticsMenu extends PanelScreen { + private enum Kind { + CLOAKS("Cloaks", "Cloak", Cloaks.ALL_CLOAKS, () -> Cloaks.availableCloaks, player -> player.cloak, + Cloaks::setCloak, ServiceClient::buyCloak, Textures::getCloakPreview, 0.5f, 150f), + HATS("Hats", "Hat", Hats.ALL_HATS, () -> Hats.availableHats, player -> player.hat, + Hats::setHat, ServiceClient::buyHat, Textures::getHatPreview, 1f, -25f); + + final String title; + final String singular; + final String[] all; + final Supplier> owned; + final Function equipped; + final Consumer equip; + final Consumer claim; + final Function preview; + /** Width divided by height of the preview textures */ + final float previewAspect; + /** The angle the player starts at, showing off this kind of cosmetic */ + final float yaw; + + Kind(String title, String singular, String[] all, Supplier> owned, + Function equipped, Consumer equip, Consumer claim, + Function preview, float previewAspect, float yaw) { + this.title = title; + this.singular = singular; + this.all = all; + this.owned = owned; + this.equipped = equipped; + this.equip = equip; + this.claim = claim; + this.preview = preview; + this.previewAspect = previewAspect; + this.yaw = yaw; + } + + /** + * "" (nothing), then every cosmetic of this kind. + */ + List ids() { + List ids = new ArrayList<>(); + ids.add(""); + ids.addAll(List.of(all)); + return ids; + } + + String getEquipped() { + SaturnPlayer player = SaturnPlayer.get(); + return player == null ? "" : equipped.apply(player); + } + } + + /** Names that aren't just the id with each word capitalized */ + private static final Map NAMES = Map.of( + "", "None", + "amg", "AMG", + "amg_petronas", "AMG Petronas", + "bmw", "BMW", + "redbull", "Red Bull"); + + private static final int STAGE_WIDTH = 300; + private static final int STAGE_PADDING = 16; + private static final int STAGE_FOOTER = 70; + private static final int COLUMN_GAP = 20; + private static final int COLUMNS = 4; + private static final int TILE_GAP = 10; + private static final int GRID_Y = 58; + private static final int SCROLLBAR_SPACE = 14; + private static final float SMALL_SCALE = 0.6f; + + private Kind kind = Kind.CLOAKS; + + public CosmeticsMenu() { + super("Cosmetics", Sidebar.COSMETICS); + } + + @Override + protected void panel() { + drawStage(); + + int x = contentX + STAGE_WIDTH + COLUMN_GAP; + int width = contentX + contentWidth - x; + + // Header + draw(new Label(() -> "Cosmetics", 1.15f, () -> Theme.FONT.value, () -> Theme.FOREGROUND.value) + .position(x, contentY + 2)); + draw(new Label(this::getOwnedSummary, 0.66f, Theme::getBodyFont, Theme::getMutedFg) + .position(x, contentY + 28)); + + ChipGroup tabs = new ChipGroup(List.of(Kind.CLOAKS.title, Kind.HATS.title), kind.title, selected -> { + kind = selected.equals(Kind.HATS.title) ? Kind.HATS : Kind.CLOAKS; + init(); + }); + draw(tabs.position(x + width - tabs.width, contentY + 4)); + + // Grid + Scroll scroll = new Scroll(0).noBackground(); + int gridHeight = contentHeight - GRID_Y; + + if (SaturnPlayer.get() == null) { + String message = "Connect to Saturn to change your cosmetics"; + int messageX = (width - (int) (Fonts.getWidth(message, Theme.getBodyFont()) * 0.7f)) / 2; + scroll.draw(new Label(() -> message, 0.7f, Theme::getBodyFont, Theme::getMutedFg) + .position(messageX, 60)); + } else { + scroll.draw(createGrid(width)); + } + + draw(scroll.dimensions(width + SCROLLBAR_SPACE, gridHeight).position(x, contentY + GRID_Y)); + } + + /** + * The left column: the player, and what they have equipped. + */ + private void drawStage() { + draw(new Stage().dimensions(STAGE_WIDTH, contentHeight).position(contentX, contentY)); + + int previewY = contentY + STAGE_PADDING + 24; + int previewHeight = contentHeight - STAGE_PADDING - 24 - STAGE_FOOTER; + draw(new SkinPreview(kind.yaw).dimensions(STAGE_WIDTH, previewHeight).position(contentX, previewY)); + + int footerY = contentY + contentHeight - STAGE_FOOTER + 8; + draw(new Label(() -> getName(kind.getEquipped()), 1f, () -> Theme.FONT.value, () -> Theme.FOREGROUND.value) + .position(contentX + STAGE_PADDING + 4, footerY)); + draw(new Label(() -> kind.singular + " · Equipped", 0.64f, Theme::getBodyFont, Theme::getMutedFg) + .position(contentX + STAGE_PADDING + 4, footerY + 26)); + } + + private Element createGrid(int width) { + int tileWidth = (width - TILE_GAP * (COLUMNS - 1)) / COLUMNS; + AnimationStagger grid = new AnimationStagger(AnimationConfig.cosmeticsMenu); + List ids = kind.ids(); + + for (int i = 0; i < ids.size(); i++) { + String id = ids.get(i); + Kind k = kind; + + CosmeticTile tile = new CosmeticTile(getName(id), k.preview.apply(id), k.previewAspect, tileWidth, + () -> k.owned.get().contains(id), + () -> k.getEquipped().equals(id), + () -> k.equip.accept(id), + () -> k.claim.accept(id)); + + tile.position((i % COLUMNS) * (tileWidth + TILE_GAP), (i / COLUMNS) * (CosmeticTile.HEIGHT + TILE_GAP)); + tile.animation(new SlideFade(AnimationConfig.cosmeticsMenu, -12)); + grid.draw(tile); + } + + return grid; + } + + private String getOwnedSummary() { + // The owned list also holds "", for nothing equipped. + long owned = List.of(kind.all).stream().filter(kind.owned.get()::contains).count(); + return owned + " of " + kind.all.length + " " + kind.title.toLowerCase(Locale.ROOT) + + " owned · every cosmetic is free to claim"; + } + + private static String getName(String id) { + String name = NAMES.get(id); + if (name != null) { + return name; + } + + StringBuilder builder = new StringBuilder(); + for (String word : id.split("_")) { + if (!builder.isEmpty()) { + builder.append(' '); + } + builder.append(Character.toUpperCase(word.charAt(0))).append(word.substring(1)); + } + return builder.toString(); + } + + /** + * The darker card behind the player, with its heading and a hint that it + * can be turned. + */ + private static class Stage extends Element { + @Override + public void render(RenderScope renderScope, ElementContext ctx) { + renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value + 4, 1, + Theme.withAlpha(0.45f, 0xFF000000), Theme.withAlpha(0.05f, Theme.FOREGROUND.value)); + + renderScope.drawText(SMALL_SCALE, "PREVIEW", STAGE_PADDING, STAGE_PADDING, Theme.FONT.value, + Theme.getMutedFg()); + + String hint = "Drag to rotate"; + int hintWidth = (int) (Fonts.getWidth(hint, Theme.getBodyFont()) * SMALL_SCALE); + renderScope.drawText(SMALL_SCALE, hint, width - STAGE_PADDING - hintWidth, STAGE_PADDING, + Theme.getBodyFont(), Theme.getMutedFg()); + + renderScope.drawRectangle(STAGE_PADDING, height - STAGE_FOOTER, width - STAGE_PADDING * 2, 1, + Theme.getBorder()); + } + } +} diff --git a/src/main/java/org/saturnclient/ui/screens/ShiftMenu.java b/src/main/java/org/saturnclient/ui/screens/ShiftMenu.java index c727068..2915e68 100644 --- a/src/main/java/org/saturnclient/ui/screens/ShiftMenu.java +++ b/src/main/java/org/saturnclient/ui/screens/ShiftMenu.java @@ -11,7 +11,6 @@ import org.saturnclient.ui.elements.Button; import org.saturnclient.ui.elements.ImageTexture; import org.saturnclient.ui.elements.TextureButton; import org.saturnclient.ui.resources.Textures; -import org.saturnclient.ui.screens.cosmetics.CloakMenu; public class ShiftMenu extends SaturnScreen { public ShiftMenu() { @@ -51,7 +50,7 @@ public class ShiftMenu extends SaturnScreen { .animation(new Fade(AnimationConfig.shiftMenu))); stagger.draw(new TextureButton(Textures.COSMETICS, () -> { - Providers.saturn.getClient().setScreen(new CloakMenu()); + Providers.saturn.getClient().setScreen(new CosmeticsMenu()); }).dimensions(btnHeight, btnHeight).position(btnWidth + btnHeight + (spacing * 2), 0) .animation(new Fade(AnimationConfig.shiftMenu))); diff --git a/src/main/java/org/saturnclient/ui/screens/TitleMenu.java b/src/main/java/org/saturnclient/ui/screens/TitleMenu.java index a2bbace..bb61896 100644 --- a/src/main/java/org/saturnclient/ui/screens/TitleMenu.java +++ b/src/main/java/org/saturnclient/ui/screens/TitleMenu.java @@ -14,7 +14,6 @@ import org.saturnclient.ui.elements.ImageTexture; import org.saturnclient.ui.elements.TextureButton; import org.saturnclient.ui.resources.Fonts; import org.saturnclient.ui.resources.Textures; -import org.saturnclient.ui.screens.cosmetics.CloakMenu; public class TitleMenu extends SaturnScreen { public TitleMenu() { @@ -68,7 +67,7 @@ public class TitleMenu extends SaturnScreen { .animation(new SlideFade(AnimationConfig.mainMenu, s + 8))); saturnStagger.draw(new TextureButton(Textures.CLOAK, () -> { - Providers.saturn.getClient().setScreen(new CloakMenu()); + Providers.saturn.getClient().setScreen(new CosmeticsMenu()); }).dimensions(s, s).position((s + 2) * 2, 0) .animation(new SlideFade(AnimationConfig.mainMenu, s + 8))); diff --git a/src/main/java/org/saturnclient/ui/screens/cosmetics/CloakMenu.java b/src/main/java/org/saturnclient/ui/screens/cosmetics/CloakMenu.java deleted file mode 100644 index 79699d5..0000000 --- a/src/main/java/org/saturnclient/ui/screens/cosmetics/CloakMenu.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.saturnclient.ui.screens.cosmetics; - -import org.saturnclient.client.player.SaturnPlayer; -import org.saturnclient.common.provider.Providers; -import org.saturnclient.config.AnimationConfig; -import org.saturnclient.cosmetics.Cloaks; -import org.saturnclient.ui.SaturnScreen; -import org.saturnclient.ui.anim.Fade; -import org.saturnclient.ui.anim.SlideY; -import org.saturnclient.ui.components.CosmeticPreview; -import org.saturnclient.ui.components.Sidebar; -import org.saturnclient.ui.components.SkinPreview; -import org.saturnclient.ui.elements.AnimationStagger; -import org.saturnclient.ui.elements.Scroll; -import org.saturnclient.ui.elements.TabMenu; -import org.saturnclient.ui.elements.TabMenu.TabMenuComponent; -import org.saturnclient.ui.resources.Textures; - -public class CloakMenu extends SaturnScreen { - public CloakMenu() { - super("Cloaks Menu"); - } - - @Override - public void ui() { - int p = 10; - int g = 10; - - Scroll scroll = new Scroll(p); - - int row = 0; - int col = 0; - - SaturnPlayer player = SaturnPlayer.get(); - - AnimationStagger stagger = new AnimationStagger(AnimationConfig.cosmeticsMenu); - - if (player != null) { - for (String cloak : Cloaks.availableCloaks) { - - stagger.draw( - new CosmeticPreview( - cloak == player.cloak, - Textures.getCloakPreview(cloak), - () -> Cloaks.setCloak(cloak)) - .position((50 + g) * col, (111 + g) * row) - .animation(new SlideY(AnimationConfig.cosmeticsMenu, 14))); - - if (col == 5) { - col = 0; - row++; - } else { - col++; - } - } - } - - scroll.draw(stagger); - - int scrollWidth = 480 + 10 + (g * 2) + (p * 2); - - draw(scroll - .dimensions(scrollWidth, 350) - .center(width, height)); - - draw(new SkinPreview(-30.0f, false) - .scale(3.5f) - .position(scroll.x + (scrollWidth - 220), scroll.y + 40) - .animation(new Fade(500))); - - draw(new Sidebar(Sidebar.COSMETICS, this.provider::close) - .center(width, height, -(scrollWidth / 2 + 35), 0)); - - draw(new TabMenu(0, - new TabMenuComponent(Textures.CLOAK, () -> { - }), - new TabMenuComponent(Textures.HAT, () -> { - Providers.saturn.getClient().setScreen(new HatMenu()); - })) - .center(width, height, 0, -195)); - } -} diff --git a/src/main/java/org/saturnclient/ui/screens/cosmetics/HatMenu.java b/src/main/java/org/saturnclient/ui/screens/cosmetics/HatMenu.java deleted file mode 100644 index 1d2244d..0000000 --- a/src/main/java/org/saturnclient/ui/screens/cosmetics/HatMenu.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.saturnclient.ui.screens.cosmetics; - -import org.saturnclient.client.player.SaturnPlayer; -import org.saturnclient.common.provider.Providers; -import org.saturnclient.config.AnimationConfig; -import org.saturnclient.cosmetics.Hats; -import org.saturnclient.ui.SaturnScreen; -import org.saturnclient.ui.anim.Fade; -import org.saturnclient.ui.anim.SlideY; -import org.saturnclient.ui.components.CosmeticPreview; -import org.saturnclient.ui.components.Sidebar; -import org.saturnclient.ui.components.SkinPreview; -import org.saturnclient.ui.elements.AnimationStagger; -import org.saturnclient.ui.elements.Scroll; -import org.saturnclient.ui.elements.TabMenu; -import org.saturnclient.ui.elements.TabMenu.TabMenuComponent; -import org.saturnclient.ui.resources.Textures; - -public class HatMenu extends SaturnScreen { - public HatMenu() { - super("Hats Menu"); - } - - @Override - public void ui() { - int p = 10; - int g = 10; - - Scroll scroll = new Scroll(p); - - int row = 0; - int col = 0; - - SaturnPlayer player = SaturnPlayer.get(); - - AnimationStagger stagger = new AnimationStagger(AnimationConfig.cosmeticsMenu); - - if (player != null) { - for (String hat : Hats.availableHats) { - stagger.draw( - new CosmeticPreview( - hat == player.hat, - Textures.getHatPreview(hat), - () -> Hats.setHat(hat)) - .dimensions(50, 50) - .position((50 + g) * col, (50 + g) * row) - .animation(new SlideY(AnimationConfig.cosmeticsMenu, 14))); - - if (col == 5) { - col = 0; - row++; - } else { - col++; - } - } - } - - scroll.draw(stagger); - - int scrollWidth = 480 + 10 + (g * 2) + (p * 2); - - draw(scroll - .dimensions(scrollWidth, 350) - .center(width, height)); - - draw(new SkinPreview(170f, true) - .scale(3.5f) - .position(scroll.x + (scrollWidth - 220), scroll.y + 40) - .animation(new Fade(500))); - - draw(new Sidebar(Sidebar.COSMETICS, this.provider::close) - .center(width, height, -(scrollWidth / 2 + 35), 0)); - - draw(new TabMenu(1, - new TabMenuComponent(Textures.CLOAK, () -> { - Providers.saturn.getClient().setScreen(new CloakMenu()); - }), - new TabMenuComponent(Textures.HAT, () -> { - })) - .center(width, height, 0, -195)); - } -} diff --git a/src/main/java/org/saturnclient/ui/screens/store/CloakStore.java b/src/main/java/org/saturnclient/ui/screens/store/CloakStore.java deleted file mode 100644 index c6c2e7d..0000000 --- a/src/main/java/org/saturnclient/ui/screens/store/CloakStore.java +++ /dev/null @@ -1,142 +0,0 @@ -package org.saturnclient.ui.screens.store; - -// import org.saturnclient.cosmetics.cloak.Cloaks; -import org.saturnclient.client.ServiceClient; -import org.saturnclient.client.player.SaturnPlayer; -import org.saturnclient.common.provider.Providers; -import org.saturnclient.config.AnimationConfig; -import org.saturnclient.config.Theme; -import org.saturnclient.cosmetics.Cloaks; -import org.saturnclient.ui.SaturnScreen; -import org.saturnclient.ui.anim.Fade; -import org.saturnclient.ui.anim.SlideY; -import org.saturnclient.ui.components.CosmeticPreview; -import org.saturnclient.ui.components.Sidebar; -import org.saturnclient.ui.elements.AnimationStagger; -import org.saturnclient.ui.elements.ImageTexture; -import org.saturnclient.ui.elements.Scroll; -import org.saturnclient.ui.elements.TabMenu; -import org.saturnclient.ui.elements.Text; -import org.saturnclient.ui.elements.TabMenu.TabMenuComponent; -import org.saturnclient.ui.resources.Fonts; -import org.saturnclient.ui.resources.Textures; - -// import com.mojang.blaze3d.systems.RenderSystem; - -public class CloakStore extends SaturnScreen { - private long lastPurchaseTime = 0; - - public CloakStore() { - super("Cloak Store"); - } - - public CloakStore(long lastPurchaseTime) { - super("Cloak Store"); - this.lastPurchaseTime = lastPurchaseTime; - } - - @Override - public void ui() { - int p = 10; - int gx = 10; - int gy = 20; - - Scroll scroll = new Scroll(p); - - int row = 0; - int col = 0; - - SaturnPlayer player = SaturnPlayer.get(); - - AnimationStagger stagger = new AnimationStagger(AnimationConfig.cosmeticsMenu); - - if (player != null) { - for (String cloak : Cloaks.ALL_CLOAKS) { - if (!Cloaks.availableCloaks.contains(cloak)) { - - int x = (50 + gx) * col; - int y = (111 + gy) * row; - - stagger.draw( - new CosmeticPreview( - cloak == player.cloak, - Textures.getCloakPreview(cloak), - () -> handlePurchase(cloak)) - .position(x, y) - .animation(new SlideY(AnimationConfig.cosmeticsMenu, 16))); - - String t = "100"; - - stagger.draw( - new Text(t) - .position(x + Fonts.centerX(50, t, Theme.FONT.value), y + 113) - .scale(0.5f) - .animation(new Fade(400))); - - stagger.draw( - new ImageTexture(Textures.COINS) - .dimensions(16, 16) - .position(x + Fonts.getWidth(t, Theme.FONT.value) - 1, y + 112) - .scale(0.5f) - .animation(new Fade(400))); - - if (col == 8) { - col = 0; - row++; - } else { - col++; - } - } - } - } - - scroll.draw(stagger); - - int scrollWidth = 480 + 40 + (gx * 2) + (p * 2); - - draw(scroll - .dimensions(scrollWidth, 350) - .center(width, height, 15, 0)); - - draw(new Sidebar(Sidebar.COSMETICS, this.provider::close) - .center(width, height, -((scrollWidth - 30) / 2 + 35), 0)); - - draw(new TabMenu(0, - new TabMenuComponent(Textures.CLOAK, () -> { - }), - new TabMenuComponent(Textures.HAT, () -> { - Providers.saturn.getClient().setScreen(new HatStore()); - })) - .center(width, height, 0, -195)); - } - - private void handlePurchase(String cloak) { - long now = System.currentTimeMillis(); - - if (now - lastPurchaseTime >= 3000) { - // Utils.notify(NotificationKind.Info, "Purchase processing", "Please wait"); - - ServiceClient.buyCloak(cloak); - lastPurchaseTime = now; - - new Thread(() -> { - try { - Thread.sleep(5000); - } catch (InterruptedException ignored) { - } - - // RenderSystem.recordRenderCall(() -> { - // MinecraftProvider.PROVIDER.setScreen(new CloakStore(now)); - // // Utils.notify(NotificationKind.Success, - // // "Purchase complete", - // // "Congrats, enjoy your new cloak!"); - // }); - }).start(); - - } else { - // Utils.notify(NotificationKind.Error, - // "Timeout error", - // "Please wait 3 seconds"); - } - } -} diff --git a/src/main/java/org/saturnclient/ui/screens/store/HatStore.java b/src/main/java/org/saturnclient/ui/screens/store/HatStore.java deleted file mode 100644 index aec83e8..0000000 --- a/src/main/java/org/saturnclient/ui/screens/store/HatStore.java +++ /dev/null @@ -1,142 +0,0 @@ -package org.saturnclient.ui.screens.store; - -import org.saturnclient.client.ServiceClient; -import org.saturnclient.client.player.SaturnPlayer; -import org.saturnclient.common.provider.Providers; -import org.saturnclient.config.AnimationConfig; -import org.saturnclient.config.Theme; -import org.saturnclient.cosmetics.Hats; -import org.saturnclient.ui.SaturnScreen; -import org.saturnclient.ui.anim.Fade; -import org.saturnclient.ui.anim.SlideY; -import org.saturnclient.ui.components.CosmeticPreview; -import org.saturnclient.ui.components.Sidebar; -import org.saturnclient.ui.elements.AnimationStagger; -import org.saturnclient.ui.elements.ImageTexture; -import org.saturnclient.ui.elements.Scroll; -import org.saturnclient.ui.elements.TabMenu; -import org.saturnclient.ui.elements.Text; -import org.saturnclient.ui.elements.TabMenu.TabMenuComponent; -import org.saturnclient.ui.resources.Fonts; -import org.saturnclient.ui.resources.Textures; - -// import com.mojang.blaze3d.systems.RenderSystem; - -public class HatStore extends SaturnScreen { - private long lastPurchaseTime = 0; - - public HatStore() { - super("Hat Store"); - } - - public HatStore(long lastPurchaseTime) { - super("Hat Store"); - this.lastPurchaseTime = lastPurchaseTime; - } - - @Override - public void ui() { - int p = 10; - int gx = 10; - int gy = 20; - - Scroll scroll = new Scroll(p); - - int row = 0; - int col = 0; - - SaturnPlayer player = SaturnPlayer.get(); - - AnimationStagger stagger = new AnimationStagger(AnimationConfig.cosmeticsMenu); - - if (player != null) { - for (String hat : Hats.ALL_HATS) { - if (!Hats.availableHats.contains(hat)) { - - int x = (50 + gx) * col; - int y = (50 + gy) * row; - - stagger.draw( - new CosmeticPreview( - hat == player.hat, - Textures.getHatPreview(hat), - () -> handlePurchase(hat)) - .dimensions(50, 50) - .position(x, y) - .animation(new SlideY(AnimationConfig.cosmeticsMenu, 16))); - - String t = "50"; - - stagger.draw( - new Text(t) - .position(x + Fonts.centerX(50, t, Theme.FONT.value), y + 53) - .scale(0.5f) - .animation(new Fade(400))); - - stagger.draw( - new ImageTexture(Textures.COINS) - .dimensions(16, 16) - .position(x + Fonts.getWidth(t, Theme.FONT.value) + 4, y + 52) - .scale(0.5f) - .animation(new Fade(400))); - - if (col == 8) { - col = 0; - row++; - } else { - col++; - } - } - } - } - - scroll.draw(stagger); - - int scrollWidth = 480 + 40 + (gx * 2) + (p * 2); - - draw(scroll - .dimensions(scrollWidth, 350) - .center(width, height, 15, 0)); - - draw(new Sidebar(Sidebar.COSMETICS, this.provider::close) - .center(width, height, -((scrollWidth - 30) / 2 + 35), 0)); - - draw(new TabMenu(1, - new TabMenuComponent(Textures.CLOAK, () -> { - Providers.saturn.getClient().setScreen(new CloakStore()); - }), - new TabMenuComponent(Textures.HAT, () -> { - })) - .center(width, height, 0, -195)); - } - - private void handlePurchase(String hat) { - long now = System.currentTimeMillis(); - - if (now - lastPurchaseTime >= 3000) { - // Utils.notify(NotificationKind.Info, "Purchase processing", "Please wait"); - - ServiceClient.buyHat(hat); - lastPurchaseTime = now; - - new Thread(() -> { - try { - Thread.sleep(5000); - } catch (InterruptedException ignored) { - } - - // RenderSystem.recordRenderCall(() -> { - // MinecraftProvider.PROVIDER.setScreen(new HatStore(now)); - // // Utils.notify(NotificationKind.Success, - // // "Purchase complete", - // // "Congrats, enjoy your new hat!"); - // }); - }).start(); - - } else { - // Utils.notify(NotificationKind.Error, - // "Timeout error", - // "Please wait 3 seconds"); - } - } -}