Redesign the mod menu, settings and cosmetics screens #6
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ import org.saturnclient.ui.resources.Textures;
|
|||||||
import org.saturnclient.ui.screens.ClientSettings;
|
import org.saturnclient.ui.screens.ClientSettings;
|
||||||
import org.saturnclient.ui.screens.HudEditor;
|
import org.saturnclient.ui.screens.HudEditor;
|
||||||
import org.saturnclient.ui.screens.ModMenu;
|
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,
|
* 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 = {
|
private final Item[] items = {
|
||||||
new Item(Textures.ICON_MODS, () -> Providers.saturn.getClient().setScreen(new ModMenu())),
|
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_HUD_EDITOR, () -> Providers.saturn.getClient().setScreen(new HudEditor())),
|
||||||
new Item(Textures.ICON_SETTINGS, () -> Providers.saturn.getClient().setScreen(new ClientSettings())),
|
new Item(Textures.ICON_SETTINGS, () -> Providers.saturn.getClient().setScreen(new ClientSettings())),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,26 +1,68 @@
|
|||||||
package org.saturnclient.ui.components;
|
package org.saturnclient.ui.components;
|
||||||
|
|
||||||
|
import org.saturnclient.config.Theme;
|
||||||
import org.saturnclient.ui.Element;
|
import org.saturnclient.ui.Element;
|
||||||
import org.saturnclient.ui.ElementContext;
|
import org.saturnclient.ui.ElementContext;
|
||||||
import org.saturnclient.ui.RenderScope;
|
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 class SkinPreview extends Element {
|
||||||
public static EntityDrawer DRAWER;
|
public static EntityDrawer DRAWER;
|
||||||
private boolean negativeAngle = false;
|
|
||||||
private float angle = 0.0f;
|
|
||||||
|
|
||||||
public SkinPreview(float angle, boolean negativeAngle) {
|
/** Degrees turned per GUI pixel dragged */
|
||||||
this.angle = angle;
|
private static final float DRAG_SPEED = 1.2f;
|
||||||
this.negativeAngle = negativeAngle;
|
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
|
@Override
|
||||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
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 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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<List<String>> owned;
|
||||||
|
final Function<SaturnPlayer, String> equipped;
|
||||||
|
final Consumer<String> equip;
|
||||||
|
final Consumer<String> claim;
|
||||||
|
final Function<String, IdentifierRef> 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<List<String>> owned,
|
||||||
|
Function<SaturnPlayer, String> equipped, Consumer<String> equip, Consumer<String> claim,
|
||||||
|
Function<String, IdentifierRef> 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<String> ids() {
|
||||||
|
List<String> 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<String, String> 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<String> 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,6 @@ import org.saturnclient.ui.elements.Button;
|
|||||||
import org.saturnclient.ui.elements.ImageTexture;
|
import org.saturnclient.ui.elements.ImageTexture;
|
||||||
import org.saturnclient.ui.elements.TextureButton;
|
import org.saturnclient.ui.elements.TextureButton;
|
||||||
import org.saturnclient.ui.resources.Textures;
|
import org.saturnclient.ui.resources.Textures;
|
||||||
import org.saturnclient.ui.screens.cosmetics.CloakMenu;
|
|
||||||
|
|
||||||
public class ShiftMenu extends SaturnScreen {
|
public class ShiftMenu extends SaturnScreen {
|
||||||
public ShiftMenu() {
|
public ShiftMenu() {
|
||||||
@@ -51,7 +50,7 @@ public class ShiftMenu extends SaturnScreen {
|
|||||||
.animation(new Fade(AnimationConfig.shiftMenu)));
|
.animation(new Fade(AnimationConfig.shiftMenu)));
|
||||||
|
|
||||||
stagger.draw(new TextureButton(Textures.COSMETICS, () -> {
|
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)
|
}).dimensions(btnHeight, btnHeight).position(btnWidth + btnHeight + (spacing * 2), 0)
|
||||||
.animation(new Fade(AnimationConfig.shiftMenu)));
|
.animation(new Fade(AnimationConfig.shiftMenu)));
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import org.saturnclient.ui.elements.ImageTexture;
|
|||||||
import org.saturnclient.ui.elements.TextureButton;
|
import org.saturnclient.ui.elements.TextureButton;
|
||||||
import org.saturnclient.ui.resources.Fonts;
|
import org.saturnclient.ui.resources.Fonts;
|
||||||
import org.saturnclient.ui.resources.Textures;
|
import org.saturnclient.ui.resources.Textures;
|
||||||
import org.saturnclient.ui.screens.cosmetics.CloakMenu;
|
|
||||||
|
|
||||||
public class TitleMenu extends SaturnScreen {
|
public class TitleMenu extends SaturnScreen {
|
||||||
public TitleMenu() {
|
public TitleMenu() {
|
||||||
@@ -68,7 +67,7 @@ public class TitleMenu extends SaturnScreen {
|
|||||||
.animation(new SlideFade(AnimationConfig.mainMenu, s + 8)));
|
.animation(new SlideFade(AnimationConfig.mainMenu, s + 8)));
|
||||||
|
|
||||||
saturnStagger.draw(new TextureButton(Textures.CLOAK, () -> {
|
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)
|
}).dimensions(s, s).position((s + 2) * 2, 0)
|
||||||
.animation(new SlideFade(AnimationConfig.mainMenu, s + 8)));
|
.animation(new SlideFade(AnimationConfig.mainMenu, s + 8)));
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user