Skip to content

Commit

Permalink
Preview tooltip options
Browse files Browse the repository at this point in the history
  • Loading branch information
shedaniel committed Oct 27, 2023
1 parent 45c2597 commit 14052fb
Show file tree
Hide file tree
Showing 12 changed files with 197 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import me.shedaniel.rei.api.client.gui.widgets.Widgets;
import me.shedaniel.rei.impl.client.config.ConfigManagerImpl;
import me.shedaniel.rei.impl.client.config.ConfigObjectImpl;
import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl;
import me.shedaniel.rei.impl.client.gui.config.components.ConfigCategoriesListWidget;
import me.shedaniel.rei.impl.client.gui.config.components.ConfigEntriesListWidget;
import me.shedaniel.rei.impl.client.gui.config.options.AllREIConfigCategories;
Expand Down Expand Up @@ -94,19 +95,26 @@ public void init() {
}));
this.widgets.add(Widgets.createLabel(new Point(width / 2, 12), this.title));
int sideWidth = (int) (width / 3.8);
Widget[] list = {ConfigEntriesListWidget.create(new Rectangle(12 + sideWidth, 32, width - 20 - sideWidth, height - 32 - 32), activeCategory.getGroups())};
this.widgets.add(ConfigCategoriesListWidget.create(new Rectangle(8, 32, sideWidth, height - 32 - 32), categories, new IntValue() {
boolean singlePane = width - 20 - sideWidth <= 330;
int singleSideWidth = 32 + 6 + 4;
Widget[] list = {ConfigEntriesListWidget.create(new Rectangle(singlePane ? 8 + singleSideWidth : 12 + sideWidth, 32, singlePane ? width - 16 - singleSideWidth : width - 20 - sideWidth, height - 32 - 32), activeCategory.getGroups())};
IntValue selectedCategory = new IntValue() {
@Override
public void accept(int i) {
REIConfigScreen.this.activeCategory = categories.get(i);
list[0] = ConfigEntriesListWidget.create(new Rectangle(12 + sideWidth, 32, width - 20 - sideWidth, height - 32 - 32), activeCategory.getGroups());
list[0] = ConfigEntriesListWidget.create(new Rectangle(singlePane ? 8 + singleSideWidth : 12 + sideWidth, 32, singlePane ? width - 16 - singleSideWidth : width - 20 - sideWidth, height - 32 - 32), activeCategory.getGroups());
}

@Override
public int getAsInt() {
return categories.indexOf(activeCategory);
}
}));
};
if (!singlePane) {
this.widgets.add(ConfigCategoriesListWidget.create(new Rectangle(8, 32, sideWidth, height - 32 - 32), categories, selectedCategory));
} else {
this.widgets.add(ConfigCategoriesListWidget.createTiny(new Rectangle(8, 32, singleSideWidth - 4, height - 32 - 32), categories, selectedCategory));
}
this.widgets.add(Widgets.delegate(() -> list[0]));
}

Expand All @@ -125,6 +133,7 @@ public void render(PoseStack poses, int mouseX, int mouseY, float delta) {
for (Widget widget : widgets) {
widget.render(poses, mouseX, mouseY, delta);
}
ScreenOverlayImpl.getInstance().lateRender(poses, mouseX, mouseY, delta);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,14 @@ public static Widget create(Rectangle bounds, List<OptionCategory> categories, I
.build();
return ScrollableViewWidget.create(bounds, list.withPadding(0, 5), true);
}

public static Widget createTiny(Rectangle bounds, List<OptionCategory> categories, IntValue selected) {
WidgetWithBounds list = ListWidget.builderOf(RectangleUtils.inset(bounds, (bounds.width - 6 - 16) / 2, 9), categories,
(index, entry) -> ConfigCategoryEntryWidget.createTiny(entry))
.gap(7)
.isSelectable((index, entry) -> true)
.selected(selected)
.build();
return ScrollableViewWidget.create(bounds, list.withPadding(0, 9), true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,12 @@ public static WidgetWithBounds create(OptionCategory category) {
Widgets.createTexturedWidget(category.getIcon(), new Rectangle(3, 3, 16, 16), 0, 0, 1, 1, 1, 1)
);
}

public static WidgetWithBounds createTiny(OptionCategory category) {
Rectangle bounds = new Rectangle(0, 0, 16, 16);
return Widgets.withTooltip(
Widgets.withBounds(Widgets.createTexturedWidget(category.getIcon(), bounds, 0, 0, 1, 1, 1, 1), bounds),
category.getName()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds;
import me.shedaniel.rei.api.client.gui.widgets.Widgets;
import me.shedaniel.rei.api.client.util.MatrixUtils;
import me.shedaniel.rei.impl.client.gui.config.options.AllREIConfigGroups;
import me.shedaniel.rei.impl.client.gui.config.options.CompositeOption;
import me.shedaniel.rei.impl.client.gui.config.options.OptionGroup;
import me.shedaniel.rei.impl.client.gui.config.options.preview.TooltipPreview;
import net.minecraft.client.gui.GuiComponent;
import org.apache.commons.lang3.tuple.Triple;

Expand All @@ -42,6 +44,21 @@

public class ConfigGroupWidget {
public static WidgetWithBounds create(OptionGroup entry, int width) {
if (entry == AllREIConfigGroups.APPEARANCE_TOOLTIPS) {
int halfWidth = width * 6 / 10 - 2;
WidgetWithBounds left = _create(entry, halfWidth);
Widget background = Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> {
GuiComponent.fill(matrices, 0, 0, width - halfWidth - 4, left.getBounds().height, 0xFF333333);
GuiComponent.fill(matrices, 1, 1, width - halfWidth - 4 - 1, left.getBounds().height - 1, 0xFF000000);
});
Widget right = Widgets.withTranslate(TooltipPreview.create(() -> width - halfWidth - 4, () -> left.getBounds().height), halfWidth + 2, 0, 0);
return Widgets.concatWithBounds(() -> new Rectangle(0, 0, width, left.getBounds().height), left, background, right);
}

return _create(entry, width);
}

private static WidgetWithBounds _create(OptionGroup entry, int width) {
List<Triple<Widget, Supplier<Rectangle>, Matrix4f[]>> widgets = new ArrayList<>();
int[] height = {0};
WidgetWithBounds groupTitle = Widgets.createLabel(new Point(0, 3), entry.getGroupName().copy().withStyle(style -> style.withColor(0xFFC0C0C0).withUnderlined(true)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@
import me.shedaniel.rei.api.client.util.MatrixUtils;
import me.shedaniel.rei.impl.client.gui.config.REIConfigScreen;
import me.shedaniel.rei.impl.client.gui.config.options.CompositeOption;
import me.shedaniel.rei.impl.common.util.RectangleUtils;
import me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.util.FormattedCharSequence;
Expand All @@ -56,7 +55,7 @@ public static <T> WidgetWithBounds create(CompositeOption<T> option, int width)
int[] stableHeight = {12};
int[] height = {12};
widgets.add(Widgets.createLabel(new Point(0, 0), option.getName().copy().withStyle(style -> style.withColor(0xFFC0C0C0)))
.leftAligned());
.leftAligned());
WidgetWithBounds optionValue = ConfigOptionValueWidget.create(option);
widgets.add(Widgets.withTranslate(optionValue, () -> Matrix4f.createTranslateMatrix(width - optionValue.getBounds().width - optionValue.getBounds().x, 0, 0)));
widgets.add(new WidgetWithBounds() {
Expand Down Expand Up @@ -97,6 +96,7 @@ public Rectangle getBounds() {
@Override
public void render(PoseStack poses, int mouseX, int mouseY, float delta) {
this.previewHeight.update(delta);
if (ConfigUtils.isReducedMotion()) this.previewHeight.completeImmediately();
height[0] = stableHeight[0] + Math.round(this.previewHeight.value());

for (int i = 0; i < split.size(); i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import static me.shedaniel.rei.impl.client.gui.config.options.AllREIConfigOptions.*;
import static me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils.translatable;

interface AllREIConfigGroups {
public interface AllREIConfigGroups {
static <T> OptionGroup make(String id) {
return new OptionGroup(translatable("config.rei.options.groups." + id));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import static me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils.literal;
import static me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils.translatable;

interface AllREIConfigOptions {
public interface AllREIConfigOptions {
static <T> CompositeOption<T> make(String id, Function<ConfigObjectImpl, T> bind,
BiConsumer<ConfigObjectImpl, T> save) {
return new CompositeOption<>(translatable("config.rei.options." + id),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,22 @@

package me.shedaniel.rei.impl.client.gui.config.options;

import me.shedaniel.rei.api.client.config.ConfigObject;
import me.shedaniel.rei.impl.client.gui.config.REIConfigScreen;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;

public interface ConfigUtils {
static boolean isReducedMotion() {
if (Minecraft.getInstance().screen instanceof REIConfigScreen screen) {
return ((Boolean) screen.getOptions().get(AllREIConfigOptions.REDUCED_MOTION)).booleanValue();
} else {
return ConfigObject.getInstance().isReducedMotion();
}
}

static MutableComponent literal(String text) {
return new TextComponent(text);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public WidgetWithBounds preview(int width, Supplier<AppearanceTheme> value) {
.color(labelColor.value().getColor());
return Widgets.concatWithBounds(new Rectangle(0, 0, width, 56), List.of(base, label, Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> {
labelColor.update(delta);
if (ConfigUtils.isReducedMotion()) {
labelColor.completeImmediately();
}
label.color(labelColor.value().getColor());
})));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* This file is licensed under the MIT License, part of Roughly Enough Items.
* Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package me.shedaniel.rei.impl.client.gui.config.options.preview;

import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import com.mojang.math.Matrix4f;
import me.shedaniel.math.Rectangle;
import me.shedaniel.rei.api.client.config.ConfigObject;
import me.shedaniel.rei.api.client.gui.widgets.Tooltip;
import me.shedaniel.rei.api.client.gui.widgets.Widget;
import me.shedaniel.rei.api.client.gui.widgets.Widgets;
import me.shedaniel.rei.api.common.entry.EntryStack;
import me.shedaniel.rei.api.common.util.EntryStacks;
import me.shedaniel.rei.impl.client.gui.config.REIConfigScreen;
import me.shedaniel.rei.impl.client.gui.config.options.AllREIConfigOptions;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.resources.language.I18n;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.util.FormattedCharSequence;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;

import java.util.ArrayList;
import java.util.List;
import java.util.function.IntSupplier;
import java.util.stream.Stream;

public class TooltipPreview {
public static Widget create(IntSupplier width, IntSupplier height) {
return Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> {
EntryStack<ItemStack> stack = EntryStacks.of(Items.OAK_PLANKS);
boolean appendModNames = (Boolean) ((REIConfigScreen) Minecraft.getInstance().screen).getOptions().get(AllREIConfigOptions.APPEND_MOD_NAMES);
boolean appendFavorites = (Boolean) ((REIConfigScreen) Minecraft.getInstance().screen).getOptions().get(AllREIConfigOptions.APPEND_FAVORITES_HINT);
List<Tooltip.Entry> entries = new ArrayList<>();
entries.add(Tooltip.entry(new TranslatableComponent("block.minecraft.oak_planks")));
if (appendModNames) {
entries.add(Tooltip.entry(new TextComponent("Minecraft").withStyle(ChatFormatting.BLUE, ChatFormatting.ITALIC)));
}
if (appendFavorites) {
String name = ConfigObject.getInstance().getFavoriteKeyCode().getLocalizedName().getString();
entries.addAll(Stream.of(I18n.get("text.rei.favorites_tooltip", name).split("\n"))
.map(TextComponent::new).map(Tooltip::entry).toList());
}
List<FormattedCharSequence> components = entries.stream().flatMap(entry -> Minecraft.getInstance().font.split(entry.getAsText(), width.getAsInt() - 8 - 4).stream()).toList();
int minWidth = components.stream().mapToInt(component -> Minecraft.getInstance().font.width(component)).max().orElse(0) + 4;
int minHeight = components.stream().mapToInt(component -> components.get(0) == component ? 2 + 10 : 10).sum() + 4;

int tX = Math.max(4, (width.getAsInt() - minWidth) / 2), tWidth = Math.min(width.getAsInt() - 8, minWidth), tY = 24 + 4, tHeight = Math.min(minHeight, height.getAsInt() - tY - 4);
matrices.pushPose();
matrices.translate(0, Math.max(0, (height.getAsInt() - (tY + tHeight)) / 2), 400);
stack.getRenderer().render(stack, matrices, new Rectangle(width.getAsInt() / 2 - 12, 0, 24, 24), mouseX, mouseY, delta);

matrices.translate(0, 0, -400);
Tesselator tesselator = Tesselator.getInstance();
BufferBuilder bufferBuilder = tesselator.getBuilder();
RenderSystem.setShader(GameRenderer::getPositionColorShader);
bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
Matrix4f matrix4f = matrices.last().pose();
fillGradient(matrix4f, bufferBuilder, tX - 3, tY - 4, tX + tWidth + 3, tY - 3, 400, -267386864, -267386864);
fillGradient(matrix4f, bufferBuilder, tX - 3, tY + tHeight + 3, tX + tWidth + 3, tY + tHeight + 4, 400, -267386864, -267386864);
fillGradient(matrix4f, bufferBuilder, tX - 3, tY - 3, tX + tWidth + 3, tY + tHeight + 3, 400, -267386864, -267386864);
fillGradient(matrix4f, bufferBuilder, tX - 4, tY - 3, tX - 3, tY + tHeight + 3, 400, -267386864, -267386864);
fillGradient(matrix4f, bufferBuilder, tX + tWidth + 3, tY - 3, tX + tWidth + 4, tY + tHeight + 3, 400, -267386864, -267386864);
fillGradient(matrix4f, bufferBuilder, tX - 3, tY - 3 + 1, tX - 3 + 1, tY + tHeight + 3 - 1, 400, 1347420415, 1344798847);
fillGradient(matrix4f, bufferBuilder, tX + tWidth + 2, tY - 3 + 1, tX + tWidth + 3, tY + tHeight + 3 - 1, 400, 1347420415, 1344798847);
fillGradient(matrix4f, bufferBuilder, tX - 3, tY - 3, tX + tWidth + 3, tY - 3 + 1, 400, 1347420415, 1347420415);
fillGradient(matrix4f, bufferBuilder, tX - 3, tY + tHeight + 2, tX + tWidth + 3, tY + tHeight + 3, 400, 1344798847, 1344798847);
RenderSystem.enableDepthTest();
RenderSystem.disableTexture();
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
bufferBuilder.end();
BufferUploader.end(bufferBuilder);
RenderSystem.disableBlend();
RenderSystem.enableTexture();

matrices.translate(0, 0, 400);

for (int i = 0; i < components.size(); i++) {
Minecraft.getInstance().font.draw(matrices, components.get(i), tX + 2, tY + 2, -1);
tY += 10 + (i == 0 ? 2 : 0);
}

matrices.popPose();
});
}

private static void fillGradient(Matrix4f pose, BufferBuilder builder, int x1, int y1, int x2, int y2, int blitOffset, int color1, int color2) {
float f = (float) (color1 >> 24 & 0xFF) / 255.0F;
float g = (float) (color1 >> 16 & 0xFF) / 255.0F;
float h = (float) (color1 >> 8 & 0xFF) / 255.0F;
float i = (float) (color1 & 0xFF) / 255.0F;
float j = (float) (color2 >> 24 & 0xFF) / 255.0F;
float k = (float) (color2 >> 16 & 0xFF) / 255.0F;
float l = (float) (color2 >> 8 & 0xFF) / 255.0F;
float m = (float) (color2 & 0xFF) / 255.0F;
builder.vertex(pose, (float) x2, (float) y1, (float) blitOffset).color(g, h, i, f).endVertex();
builder.vertex(pose, (float) x1, (float) y1, (float) blitOffset).color(g, h, i, f).endVertex();
builder.vertex(pose, (float) x1, (float) y2, (float) blitOffset).color(k, l, m, j).endVertex();
builder.vertex(pose, (float) x2, (float) y2, (float) blitOffset).color(k, l, m, j).endVertex();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public int getMaxScrollHeight() {
}));
widgets.add(createScrollerWidget(bounds, scrollingRef[0]));

return Widgets.withBounds(Widgets.concat(widgets), bounds);
return Widgets.concatWithBounds(bounds, widgets);
}

private static Widget createScrollerWidget(Rectangle bounds, ScrollingContainer scrolling) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@
import me.shedaniel.clothconfig2.api.animator.ValueAnimator;
import me.shedaniel.math.Rectangle;
import me.shedaniel.rei.api.client.REIRuntime;
import me.shedaniel.rei.api.client.config.ConfigObject;
import me.shedaniel.rei.api.client.gui.config.DisplayScreenType;
import me.shedaniel.rei.api.client.gui.config.RecipeBorderType;
import me.shedaniel.rei.api.client.gui.widgets.Panel;
import me.shedaniel.rei.impl.client.gui.InternalTextures;
import me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.gui.components.events.GuiEventListener;
import org.jetbrains.annotations.ApiStatus;
Expand Down Expand Up @@ -117,6 +116,7 @@ public Rectangle getBounds() {
@Override
public void render(PoseStack matrices, int mouseX, int mouseY, float delta) {
this.darkBackgroundAlpha.update(delta);
if (ConfigUtils.isReducedMotion()) this.darkBackgroundAlpha.completeImmediately();
if (!getRendering().test(this))
return;
int x = bounds.x, y = bounds.y, width = bounds.width, height = bounds.height;
Expand Down

0 comments on commit 14052fb

Please sign in to comment.