Skip to content

Commit 4750141

Browse files
committed
WIP Calculator
1 parent d9d53c6 commit 4750141

22 files changed

+631
-317
lines changed

api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ default boolean isLeftHandSidePanel() {
294294

295295
FavoriteAddWidgetMode getFavoriteAddWidgetMode();
296296

297+
@ApiStatus.Experimental
298+
boolean isCalculatorPanelEnabled();
299+
297300
ModifierKeyCode getFavoriteKeyCode();
298301

299302
ModifierKeyCode getRecipeKeybind();

runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,11 @@ public FavoriteAddWidgetMode getFavoriteAddWidgetMode() {
328328
return advanced.layout.favoriteAddWidgetMode;
329329
}
330330

331+
@Override
332+
public boolean isCalculatorPanelEnabled() {
333+
return advanced.layout.calculatorPanel;
334+
}
335+
331336
@Override
332337
public ModifierKeyCode getFavoriteKeyCode() {
333338
return basics.keyBindings.favoriteKeybind == null ? ModifierKeyCode.unknown() : basics.keyBindings.favoriteKeybind;
@@ -693,6 +698,7 @@ public static class Layout {
693698
@Comment("Merges displays with equal contents under 1 display.")
694699
public boolean mergeDisplayUnderOne = true;
695700
public FavoriteAddWidgetMode favoriteAddWidgetMode = FavoriteAddWidgetMode.ALWAYS_VISIBLE;
701+
public boolean calculatorPanel = true;
696702
}
697703

698704
public static class Accessibility {

runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
428428
if (REIRuntimeImpl.getSearchField().keyReleased(keyCode, scanCode, modifiers))
429429
return true;
430430
for (GuiEventListener listener : widgets)
431-
if (listener != REIRuntimeImpl.getSearchField() && listener == getFocused() && listener.keyPressed(keyCode, scanCode, modifiers))
431+
if (listener != REIRuntimeImpl.getSearchField() && listener == getFocused() && listener.keyReleased(keyCode, scanCode, modifiers))
432432
return true;
433433
}
434434
}

runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ static <T> OptionGroup make(String id) {
9090
.add(COLLAPSIBLE_ENTRIES);
9191
OptionGroup FAVORITES_FAVORITES = make("favorites.favorites")
9292
.add(FAVORITES_MODE)
93-
.add(NEW_FAVORITES_BUTTON_VISIBILITY);
93+
.add(NEW_FAVORITES_BUTTON_VISIBILITY)
94+
.add(CALCULATOR_MODE);
9495
OptionGroup FAVORITES_ADVANCED = make("favorites.advanced")
9596
.add(GAME_MODE_COMMAND)
9697
.add(TIME_COMMAND)

runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ static ComparableValue<Double>[] doubleRange(double start, double end, double st
222222
.enabledDisabled();
223223
CompositeOption<FavoriteAddWidgetMode> NEW_FAVORITES_BUTTON_VISIBILITY = make("favorites.new_favorites_button_visibility", i -> i.advanced.layout.favoriteAddWidgetMode, (i, v) -> i.advanced.layout.favoriteAddWidgetMode = v)
224224
.enumOptions();
225+
CompositeOption<Boolean> CALCULATOR_MODE = make("favorites.calculator_mode", i -> i.advanced.layout.calculatorPanel, (i, v) -> i.advanced.layout.calculatorPanel = v)
226+
.enabledDisabled();
225227
CompositeOption<String> GAME_MODE_COMMAND = make("favorites.game_mode_command", i -> i.advanced.commands.gamemodeCommand, (i, v) -> i.advanced.commands.gamemodeCommand = v)
226228
.string();
227229
CompositeOption<String> TIME_COMMAND = make("favorites.time_command", i -> i.advanced.commands.timeCommand, (i, v) -> i.advanced.commands.timeCommand = v)

runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/FavoritesListWidget.java

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@
5555
import me.shedaniel.rei.impl.client.gui.widget.favorites.history.DisplayHistoryWidget;
5656
import me.shedaniel.rei.impl.client.gui.widget.favorites.listeners.FavoritesRegionListener;
5757
import me.shedaniel.rei.impl.client.gui.widget.favorites.listeners.FavoritesSystemRegionListener;
58-
import me.shedaniel.rei.impl.client.gui.widget.favorites.panel.FavoritesPanel;
58+
import me.shedaniel.rei.impl.client.gui.widget.favorites.panel.CalculatorPanel;
59+
import me.shedaniel.rei.impl.client.gui.widget.favorites.panel.FavoritesAddPanel;
5960
import me.shedaniel.rei.impl.client.gui.widget.favorites.panel.FavoritesTogglePanelButton;
6061
import me.shedaniel.rei.impl.client.gui.widget.favorites.trash.TrashWidget;
6162
import me.shedaniel.rei.impl.client.gui.widget.region.EntryStacksRegionWidget;
@@ -64,7 +65,6 @@
6465
import me.shedaniel.rei.impl.common.util.RectangleUtils;
6566
import net.minecraft.client.gui.GuiGraphics;
6667
import net.minecraft.client.gui.screens.Screen;
67-
import net.minecraft.network.chat.Component;
6868
import org.apache.commons.lang3.mutable.MutableLong;
6969
import org.apache.commons.lang3.tuple.Triple;
7070
import org.jetbrains.annotations.ApiStatus;
@@ -85,20 +85,13 @@ public class FavoritesListWidget extends WidgetWithBounds implements DraggableCo
8585
private EntryStacksRegionWidget<FavoriteEntry> region = new EntryStacksRegionWidget<>(new FavoritesRegionListener(this));
8686
private List<FavoriteEntry> lastSystemEntries = new ArrayList<>();
8787

88-
public final FavoritesPanel favoritePanel = new FavoritesPanel(this);
88+
public final FavoritesAddPanel favoritePanel = new FavoritesAddPanel(this);
89+
public final CalculatorPanel calculatorPanel = new CalculatorPanel(this);
8990
public final TrashWidget trash = new TrashWidget(this);
9091
public final DisplayHistoryWidget displayHistory = new DisplayHistoryWidget(this);
91-
public final FavoritesTogglePanelButton togglePanelButton = new FavoritesTogglePanelButton(this, 0, Component.translatable("text.rei.add_favorite_widget"),
92-
favoritePanel.expendState, () -> {
93-
favoritePanel.expendState.setTo(!favoritePanel.expendState.target(), ConfigObject.getInstance().isReducedMotion() ? 0 : 1500);
94-
favoritePanel.resetRows();
95-
});
96-
public final FavoritesTogglePanelButton calculatorPanelButton = new FavoritesTogglePanelButton(this, 1, Component.translatable("text.rei.calculator_widget"),
97-
favoritePanel.expendState, () -> {
98-
favoritePanel.expendState.setTo(!favoritePanel.expendState.target(), ConfigObject.getInstance().isReducedMotion() ? 0 : 1500);
99-
favoritePanel.resetRows();
100-
});
101-
private final List<Widget> children = ImmutableList.of(favoritePanel, togglePanelButton, calculatorPanelButton, systemRegion, region);
92+
public final FavoritesTogglePanelButton togglePanelButton = new FavoritesTogglePanelButton.ToggleAdd(this);
93+
public final FavoritesTogglePanelButton calculatorPanelButton = new FavoritesTogglePanelButton.ToggleCalculator(this);
94+
private final List<Widget> children = ImmutableList.of(favoritePanel, calculatorPanel, togglePanelButton, calculatorPanelButton, systemRegion, region);
10295

10396
@Override
10497
public boolean mouseScrolled(double mouseX, double mouseY, double amountX, double amountY) {
@@ -213,12 +206,12 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
213206

214207
displayHistory.render(graphics, mouseX, mouseY, delta);
215208

216-
if (favoritePanel.getBounds().height > 20) {
217-
// Opened favorites panel
218-
region.getBounds().setBounds(this.favoritesBounds.x, this.favoritesBounds.y + topOffsetHeight, this.favoritesBounds.width, this.favoritesBounds.height - topOffsetHeight - (this.favoritesBounds.getMaxY() - this.favoritePanel.getBounds().y) - 4 - (Math.round(trashHeight) <= 0 ? 0 : trashHeight));
219-
} else {
220-
region.getBounds().setBounds(this.favoritesBounds.x, this.favoritesBounds.y + topOffsetHeight, this.favoritesBounds.width, this.favoritesBounds.height - topOffsetHeight - (Math.round(trashHeight) <= 0 ? 0 : trashHeight + 24));
221-
}
209+
int removeExtraHeight = 0;
210+
211+
if (favoritePanel.getBounds().height > 20) removeExtraHeight += this.favoritesBounds.getMaxY() - this.favoritePanel.getBounds().y + 4;
212+
if (calculatorPanel.getBounds().height > 20) removeExtraHeight += this.favoritesBounds.getMaxY() - this.calculatorPanel.getBounds().y + 4;
213+
214+
region.getBounds().setBounds(this.favoritesBounds.x, this.favoritesBounds.y + topOffsetHeight, this.favoritesBounds.width, this.favoritesBounds.height - topOffsetHeight - removeExtraHeight - (Math.round(trashHeight) <= 0 ? 0 : trashHeight));
222215

223216
systemRegion.render(graphics, mouseX, mouseY, delta);
224217
region.render(graphics, mouseX, mouseY, delta);
@@ -269,6 +262,7 @@ public void setSystemRegionEntries(@Nullable RealRegionEntry<FavoriteEntry> remo
269262

270263
private void renderAddFavorite(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
271264
this.favoritePanel.render(graphics, mouseX, mouseY, delta);
265+
this.calculatorPanel.render(graphics, mouseX, mouseY, delta);
272266
this.togglePanelButton.render(graphics, mouseX, mouseY, delta);
273267
this.calculatorPanelButton.render(graphics, mouseX, mouseY, delta);
274268
}
@@ -324,4 +318,15 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) {
324318
return true;
325319
return false;
326320
}
321+
322+
@Override
323+
public boolean charTyped(char character, int modifiers) {
324+
if (containsMouse(mouse()))
325+
for (Widget widget : children())
326+
if (widget.charTyped(character, modifiers))
327+
return true;
328+
if (displayHistory.charTyped(character, modifiers))
329+
return true;
330+
return false;
331+
}
327332
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package me.shedaniel.rei.impl.client.gui.widget.favorites.panel;
2+
3+
import me.shedaniel.clothconfig2.api.animator.NumberAnimator;
4+
import me.shedaniel.clothconfig2.api.animator.ProgressValueAnimator;
5+
import me.shedaniel.clothconfig2.api.animator.ValueAnimator;
6+
import me.shedaniel.math.Rectangle;
7+
import me.shedaniel.rei.api.client.config.ConfigObject;
8+
import me.shedaniel.rei.impl.client.gui.widget.favorites.FavoritesListWidget;
9+
import me.shedaniel.rei.impl.client.gui.widget.search.CalculatorDisplayUtils;
10+
import me.shedaniel.rei.impl.client.gui.widget.search.OverlaySearchField;
11+
import me.shedaniel.rei.impl.client.gui.widget.search.TextCalculator;
12+
import me.shedaniel.rei.impl.client.util.ColorUtils;
13+
import net.minecraft.client.Minecraft;
14+
import net.minecraft.client.gui.GuiGraphics;
15+
import net.minecraft.client.gui.components.events.GuiEventListener;
16+
import net.minecraft.network.chat.Component;
17+
18+
import java.util.ArrayList;
19+
import java.util.List;
20+
21+
public class CalculatorPanel extends FavoritesPanel {
22+
private final List<Row> rows = new ArrayList<>();
23+
private final OverlaySearchField textField = new OverlaySearchField(0, 0, 0, 0, null);
24+
private final NumberAnimator<Integer> previewHeight = ValueAnimator.ofDouble().asInt();
25+
private CalculatorDisplayUtils utils = new CalculatorDisplayUtils(7);
26+
private double eval;
27+
28+
public CalculatorPanel(FavoritesListWidget parent) {
29+
super(parent);
30+
this.textField.setHasBorder(false);
31+
this.textField.isMain = false;
32+
this.textField.setAutoPrefixEquals(true);
33+
this.textField.setSuggestion(Component.empty());
34+
this.textField.setResponder(text -> {
35+
if (!text.isBlank() && TextCalculator.isValid('=' + text)) {
36+
this.eval = new TextCalculator('=' + text).eval();
37+
this.previewHeight.setTo(Minecraft.getInstance().font.lineHeight + 1, ConfigObject.getInstance().isReducedMotion() ? 0 : 400);
38+
} else {
39+
this.previewHeight.setTo(0, ConfigObject.getInstance().isReducedMotion() ? 0 : 400);
40+
}
41+
});
42+
}
43+
44+
@Override
45+
public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
46+
this.previewHeight.update(delta);
47+
super.render(graphics, mouseX, mouseY, delta);
48+
this.innerBounds.setBounds(bounds.x + 4, bounds.y + 4, bounds.width - 8, bounds.height - 8);
49+
50+
int previewLength = Math.max(7, (this.innerBounds.width - 4) / font.width("="));
51+
if (previewLength != this.utils.maxLength()) this.utils = new CalculatorDisplayUtils(previewLength);
52+
53+
int buttonColor = 0xFFFFFF | (Math.round(0x34 * Math.min((float) expendState.progress() * 2, 1)) << 24);
54+
graphics.fillGradient(bounds.x, bounds.y, bounds.getMaxX(), bounds.getMaxY(), buttonColor, buttonColor);
55+
56+
if (expendState.progress() > 0.05f) {
57+
Rectangle availableFullBounds = parent.favoritesBounds.clone();
58+
availableFullBounds.height -= 20;
59+
Rectangle scissorBounds = new Rectangle(innerBounds.x - 1, innerBounds.y - 1, innerBounds.width + 2, innerBounds.height + 2).intersection(availableFullBounds);
60+
graphics.enableScissor(scissorBounds.x, scissorBounds.y, scissorBounds.getMaxX(), scissorBounds.getMaxY());
61+
graphics.pose().pushPose();
62+
63+
// Text Field Background
64+
Rectangle textFieldBorder = new Rectangle(innerBounds.x, innerBounds.getMaxY() - 9 - 5, innerBounds.width, 9 + 5);
65+
boolean textFieldFocused = textFieldBorder.contains(mouseX, mouseY) || this.textField.isFocused();
66+
int borderColor = ColorUtils.withAlpha(textFieldFocused ? 0x77FFFFFF : 0x77A0A0A0, expendState.progress());
67+
int backgroundColor = ColorUtils.withAlpha(textFieldFocused ? 0xFF000000 : 0xC0000000, expendState.progress());
68+
graphics.fillGradient(textFieldBorder.x - 1, textFieldBorder.y - 1, textFieldBorder.getMaxX() + 1, textFieldBorder.getMaxY() + 1, borderColor, borderColor);
69+
graphics.fillGradient(textFieldBorder.x, textFieldBorder.y, textFieldBorder.getMaxX(), textFieldBorder.getMaxY(), backgroundColor, backgroundColor);
70+
int leftPad = font.width("=");
71+
72+
// Equals
73+
graphics.pose().pushPose();
74+
graphics.pose().translate(-0.5, 0, 0);
75+
graphics.drawString(font, "=", innerBounds.x + 2, innerBounds.getMaxY() - 9 - 2, ColorUtils.withAlpha(0xFFAAAAAA, expendState.progress()));
76+
graphics.pose().popPose();
77+
78+
// Text Field
79+
this.textField.getBounds().setBounds(innerBounds.x + 2 + leftPad, innerBounds.getMaxY() - 9 - 2, innerBounds.width - 4 - leftPad, 9);
80+
this.textField.render(graphics, mouseX, mouseY, delta);
81+
82+
// Preview
83+
if (this.previewHeight.value() > 0) {
84+
int previewTop = textFieldBorder.y - 1 - this.previewHeight.value();
85+
graphics.enableScissor(textFieldBorder.x - 1, previewTop, textFieldBorder.getMaxX() + 1, textFieldBorder.y - 1);
86+
graphics.fillGradient(textFieldBorder.x - 1, previewTop, textFieldBorder.getMaxX() + 1, textFieldBorder.y - 1, borderColor, borderColor);
87+
graphics.drawString(font, this.utils.fmt(this.eval), textFieldBorder.x + 2, previewTop + 2, 0xFF000000, false);
88+
graphics.disableScissor();
89+
}
90+
91+
graphics.pose().popPose();
92+
graphics.disableScissor();
93+
} else {
94+
this.textField.getBounds().setBounds(0, 0, 0, 0);
95+
}
96+
}
97+
98+
@Override
99+
protected Rectangle getButtonArea() {
100+
return this.parent.calculatorPanelButton.getBounds();
101+
}
102+
103+
@Override
104+
protected Rectangle getTargetArea(Rectangle fullArea) {
105+
return new Rectangle(
106+
fullArea.x + 4,
107+
fullArea.getMaxY() - 4 - 16 - fullArea.height * 0.4f,
108+
fullArea.width - 8,
109+
fullArea.height * 0.4f
110+
);
111+
}
112+
113+
@Override
114+
public List<? extends GuiEventListener> children() {
115+
return List.of(this.textField);
116+
}
117+
118+
private record Row(String equation, double result, ProgressValueAnimator<Boolean> set) {
119+
public Row(String equation, double result) {
120+
this(equation, result, ValueAnimator.ofBoolean(false));
121+
this.set().setTo(true, ConfigObject.getInstance().isReducedMotion() ? 0 : 500);
122+
}
123+
}
124+
}

runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/panel/FadingFavoritesPanelButton.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@
2727
import me.shedaniel.clothconfig2.api.animator.ValueAnimator;
2828
import me.shedaniel.math.Rectangle;
2929
import me.shedaniel.rei.api.client.config.ConfigObject;
30+
import me.shedaniel.rei.api.client.gui.config.FavoriteAddWidgetMode;
3031
import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds;
3132
import me.shedaniel.rei.impl.client.gui.widget.favorites.FavoritesListWidget;
3233
import net.minecraft.client.gui.GuiGraphics;
3334
import net.minecraft.client.gui.components.events.GuiEventListener;
34-
import net.minecraft.client.renderer.MultiBufferSource;
3535

3636
import java.util.Collections;
3737
import java.util.List;
@@ -51,16 +51,17 @@ public FadingFavoritesPanelButton(FavoritesListWidget parent) {
5151
@Override
5252
public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
5353
this.bounds.setBounds(updateArea(parent.favoritesBounds));
54-
boolean hovered = containsMouse(mouseX, mouseY);
55-
switch (ConfigObject.getInstance().getFavoriteAddWidgetMode()) {
54+
boolean hovered = containsMouse(mouseX, mouseY) & isVisible();
55+
if (isOtherActive()) this.alpha.setTo(0, ConfigObject.getInstance().isReducedMotion() ? 0 : 750);
56+
else switch (getFavoriteAddWidgetMode()) {
5657
case ALWAYS_INVISIBLE:
5758
this.alpha.setAs(0);
5859
break;
5960
case AUTO_HIDE:
6061
this.alpha.setTo(hovered ? 1f : isAvailable(mouseX, mouseY) ? 0.5f : 0f, ConfigObject.getInstance().isReducedMotion() ? 0 : 260);
6162
break;
6263
case ALWAYS_VISIBLE:
63-
this.alpha.setAs(hovered ? 1f : 0.5f);
64+
this.alpha.setTo(hovered ? 1f : 0.5f, ConfigObject.getInstance().isReducedMotion() ? 0 : 750);
6465
break;
6566
}
6667
this.alpha.update(delta);
@@ -74,6 +75,10 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
7475
}
7576
}
7677

78+
protected abstract boolean isOtherActive();
79+
80+
protected abstract FavoriteAddWidgetMode getFavoriteAddWidgetMode();
81+
7782
protected abstract boolean isAvailable(int mouseX, int mouseY);
7883

7984
protected abstract void renderContents(GuiGraphics graphics);

0 commit comments

Comments
 (0)