aboutsummaryrefslogtreecommitdiff
path: root/runtime/src/main
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2022-06-26 03:33:14 +0800
committershedaniel <daniel@shedaniel.me>2022-06-26 03:33:14 +0800
commit81b82416abb2a94c12638fdbb08df2ac0f83254f (patch)
tree31379d04269c77a764d127685621a7cc6ac7136f /runtime/src/main
parent685dde03d71bbf18442564575e11a8247f401c0d (diff)
downloadRoughlyEnoughItems-81b82416abb2a94c12638fdbb08df2ac0f83254f.tar.gz
RoughlyEnoughItems-81b82416abb2a94c12638fdbb08df2ac0f83254f.tar.bz2
RoughlyEnoughItems-81b82416abb2a94c12638fdbb08df2ac0f83254f.zip
WIP on Tag Category, add Overflow Widget
Diffstat (limited to 'runtime/src/main')
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java15
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/AbstractDisplayViewingScreen.java52
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DelegateWidgetWithTranslate.java44
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/InternalWidgets.java5
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/NoOpWidget.java23
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/OverflowWidget.java148
-rwxr-xr-xruntime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json3
7 files changed, 263 insertions, 27 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java
index af0407f3d..a546bb033 100644
--- a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java
+++ b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java
@@ -38,6 +38,7 @@ import me.shedaniel.rei.api.client.config.ConfigObject;
import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer;
import me.shedaniel.rei.api.client.favorites.FavoriteEntry;
import me.shedaniel.rei.api.client.favorites.FavoriteEntryType;
+import me.shedaniel.rei.api.client.gui.screen.DisplayScreen;
import me.shedaniel.rei.api.client.gui.widgets.Tooltip;
import me.shedaniel.rei.api.client.gui.widgets.TooltipContext;
import me.shedaniel.rei.api.client.overlay.ScreenOverlay;
@@ -365,7 +366,7 @@ public class RoughlyEnoughItemsCoreClient {
});
ClientScreenInputEvent.MOUSE_CLICKED_PRE.register((minecraftClient, screen, mouseX, mouseY, button) -> {
isLeftMousePressed = true;
- if (shouldReturn(screen))
+ if (shouldReturn(screen) || screen instanceof DisplayScreen)
return EventResult.pass();
resetFocused(screen);
if (getOverlay().mouseClicked(mouseX, mouseY, button)) {
@@ -379,7 +380,7 @@ public class RoughlyEnoughItemsCoreClient {
});
ClientScreenInputEvent.MOUSE_RELEASED_PRE.register((minecraftClient, screen, mouseX, mouseY, button) -> {
isLeftMousePressed = false;
- if (shouldReturn(screen))
+ if (shouldReturn(screen) || screen instanceof DisplayScreen)
return EventResult.pass();
resetFocused(screen);
if (REIRuntime.getInstance().isOverlayVisible() && getOverlay().mouseReleased(mouseX, mouseY, button)
@@ -389,7 +390,7 @@ public class RoughlyEnoughItemsCoreClient {
return EventResult.pass();
});
ClientScreenInputEvent.MOUSE_SCROLLED_PRE.register((minecraftClient, screen, mouseX, mouseY, amount) -> {
- if (shouldReturn(screen))
+ if (shouldReturn(screen) || screen instanceof DisplayScreen)
return EventResult.pass();
resetFocused(screen);
if (REIRuntime.getInstance().isOverlayVisible() && getOverlay().mouseScrolled(mouseX, mouseY, amount)
@@ -398,7 +399,7 @@ public class RoughlyEnoughItemsCoreClient {
return EventResult.pass();
});
ClientScreenInputEvent.CHAR_TYPED_PRE.register((minecraftClient, screen, character, keyCode) -> {
- if (shouldReturn(screen))
+ if (shouldReturn(screen) || screen instanceof DisplayScreen)
return EventResult.pass();
if (screen.getFocused() != null && screen.getFocused() instanceof EditBox || (screen.getFocused() instanceof RecipeBookComponent && ((RecipeBookComponent) screen.getFocused()).searchBox != null && ((RecipeBookComponent) screen.getFocused()).searchBox.isFocused()))
if (!REIRuntimeImpl.getSearchField().isFocused())
@@ -418,7 +419,7 @@ public class RoughlyEnoughItemsCoreClient {
resetFocused(screen);
});
ClientScreenInputEvent.MOUSE_DRAGGED_PRE.register((minecraftClient, screen, mouseX1, mouseY1, button, mouseX2, mouseY2) -> {
- if (shouldReturn(screen))
+ if (shouldReturn(screen) || screen instanceof DisplayScreen)
return EventResult.pass();
resetFocused(screen);
if (getOverlay().mouseDragged(mouseX1, mouseY1, button, mouseX2, mouseY2)
@@ -427,7 +428,7 @@ public class RoughlyEnoughItemsCoreClient {
return EventResult.pass();
});
ClientScreenInputEvent.KEY_PRESSED_PRE.register((minecraftClient, screen, i, i1, i2) -> {
- if (shouldReturn(screen))
+ if (shouldReturn(screen) || screen instanceof DisplayScreen)
return EventResult.pass();
if (screen instanceof AbstractContainerScreen && ConfigObject.getInstance().doesDisableRecipeBook() && ConfigObject.getInstance().doesFixTabCloseContainer()) {
if (i == 258 && minecraftClient.options.keyInventory.matches(i, i1)) {
@@ -445,7 +446,7 @@ public class RoughlyEnoughItemsCoreClient {
return EventResult.pass();
});
ClientScreenInputEvent.KEY_RELEASED_PRE.register((minecraftClient, screen, i, i1, i2) -> {
- if (shouldReturn(screen))
+ if (shouldReturn(screen) || screen instanceof DisplayScreen)
return EventResult.pass();
if (screen.getFocused() != null && screen.getFocused() instanceof EditBox || (screen.getFocused() instanceof RecipeBookComponent && ((RecipeBookComponent) screen.getFocused()).searchBox != null && ((RecipeBookComponent) screen.getFocused()).searchBox.isFocused()))
if (!REIRuntimeImpl.getSearchField().isFocused())
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/AbstractDisplayViewingScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/AbstractDisplayViewingScreen.java
index 1ae89bdf1..7c6a0eeda 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/AbstractDisplayViewingScreen.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/AbstractDisplayViewingScreen.java
@@ -30,11 +30,13 @@ import com.mojang.datafixers.util.Pair;
import com.mojang.math.Matrix4f;
import dev.architectury.fluid.FluidStack;
import me.shedaniel.math.Rectangle;
+import me.shedaniel.rei.api.client.REIRuntime;
import me.shedaniel.rei.api.client.gui.screen.DisplayScreen;
import me.shedaniel.rei.api.client.gui.widgets.Slot;
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.client.overlay.ScreenOverlay;
import me.shedaniel.rei.api.client.registry.category.CategoryRegistry;
import me.shedaniel.rei.api.client.registry.display.DisplayCategory;
import me.shedaniel.rei.api.client.registry.display.DisplayCategoryView;
@@ -324,4 +326,54 @@ public abstract class AbstractDisplayViewingScreen extends Screen implements Dis
widget.tooltipProcessor(new TooltipProcessor());
}
+
+ private static ScreenOverlay getOverlay() {
+ return REIRuntime.getInstance().getOverlay().orElseThrow(() -> new IllegalStateException("Overlay not initialized!"));
+ }
+
+ private boolean handleFocuses(int button) {
+ if (button == 0) {
+ setDragging(true);
+ }
+ handleFocuses();
+ return true;
+ }
+
+ private boolean handleFocuses() {
+ if (getFocused() instanceof ScreenOverlay || getFocused() == this) {
+ setFocused(null);
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ return super.mouseClicked(mouseX, mouseY, button) || (getOverlay().mouseClicked(mouseX, mouseY, button) && handleFocuses());
+ }
+
+ @Override
+ public boolean mouseReleased(double mouseX, double mouseY, int button) {
+ return super.mouseReleased(mouseX, mouseY, button) || (getOverlay().mouseReleased(mouseX, mouseY, button) && handleFocuses());
+ }
+
+ @Override
+ public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
+ return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY) || (getOverlay().mouseDragged(mouseX, mouseY, button, deltaX, deltaY) && handleFocuses());
+ }
+
+ @Override
+ public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
+ return super.mouseScrolled(mouseX, mouseY, amount) || (getOverlay().mouseScrolled(mouseX, mouseY, amount) && handleFocuses());
+ }
+
+ @Override
+ public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
+ return super.keyReleased(keyCode, scanCode, modifiers) || (getOverlay().keyReleased(keyCode, scanCode, modifiers) && handleFocuses());
+ }
+
+ @Override
+ public boolean charTyped(char character, int modifiers) {
+ return super.charTyped(character, modifiers) || (getOverlay().charTyped(character, modifiers) && handleFocuses());
+ }
}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DelegateWidgetWithTranslate.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DelegateWidgetWithTranslate.java
index c03cd3fb3..c3e2090cd 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DelegateWidgetWithTranslate.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DelegateWidgetWithTranslate.java
@@ -40,18 +40,22 @@ public class DelegateWidgetWithTranslate extends DelegateWidget {
this.translate = translate;
}
+ protected Matrix4f translate() {
+ return translate.get();
+ }
+
@Override
- public void render(PoseStack poseStack, int i, int j, float f) {
+ public void render(PoseStack poseStack, int mouseX, int mouseY, float delta) {
poseStack.pushPose();
- poseStack.last().pose().multiply(translate.get());
- Vector4f mouse = transformMouse(i, j);
- super.render(poseStack, (int) mouse.x(), (int) mouse.y(), f);
+ poseStack.last().pose().multiply(translate());
+ Vector4f mouse = transformMouse(mouseX, mouseY);
+ super.render(poseStack, (int) mouse.x(), (int) mouse.y(), delta);
poseStack.popPose();
}
private Vector4f transformMouse(double mouseX, double mouseY) {
Vector4f mouse = new Vector4f((float) mouseX, (float) mouseY, 0, 1);
- mouse.transform(translate.get());
+ mouse.transform(translate());
return mouse;
}
@@ -62,33 +66,33 @@ public class DelegateWidgetWithTranslate extends DelegateWidget {
}
@Override
- public boolean mouseClicked(double d, double e, int i) {
- Vector4f mouse = transformMouse(d, e);
- return super.mouseClicked(mouse.x(), mouse.y(), i);
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ Vector4f mouse = transformMouse(mouseX, mouseY);
+ return super.mouseClicked(mouse.x(), mouse.y(), button);
}
@Override
- public boolean mouseReleased(double d, double e, int i) {
- Vector4f mouse = transformMouse(d, e);
- return super.mouseReleased(mouse.x(), mouse.y(), i);
+ public boolean mouseReleased(double mouseX, double mouseY, int button) {
+ Vector4f mouse = transformMouse(mouseX, mouseY);
+ return super.mouseReleased(mouse.x(), mouse.y(), button);
}
@Override
- public boolean mouseDragged(double d, double e, int i, double f, double g) {
- Vector4f mouse = transformMouse(d, e);
- return super.mouseDragged(mouse.x(), mouse.y(), i, f, g);
+ public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
+ Vector4f mouse = transformMouse(mouseX, mouseY);
+ return super.mouseDragged(mouse.x(), mouse.y(), button, deltaX, deltaY);
}
@Override
- public boolean mouseScrolled(double d, double e, double f) {
- Vector4f mouse = transformMouse(d, e);
- return super.mouseScrolled(mouse.x(), mouse.y(), f);
+ public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
+ Vector4f mouse = transformMouse(mouseX, mouseY);
+ return super.mouseScrolled(mouse.x(), mouse.y(), amount);
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
try {
- Widget.translateMouse(translate.get());
+ Widget.translateMouse(translate());
return super.keyPressed(keyCode, scanCode, modifiers);
} finally {
Widget.popMouse();
@@ -98,7 +102,7 @@ public class DelegateWidgetWithTranslate extends DelegateWidget {
@Override
public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
try {
- Widget.translateMouse(translate.get());
+ Widget.translateMouse(translate());
return super.keyReleased(keyCode, scanCode, modifiers);
} finally {
Widget.popMouse();
@@ -108,7 +112,7 @@ public class DelegateWidgetWithTranslate extends DelegateWidget {
@Override
public boolean charTyped(char character, int modifiers) {
try {
- Widget.translateMouse(translate.get());
+ Widget.translateMouse(translate());
return super.charTyped(character, modifiers);
} finally {
Widget.popMouse();
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/InternalWidgets.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/InternalWidgets.java
index a4dafd5bd..92004f529 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/InternalWidgets.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/InternalWidgets.java
@@ -273,5 +273,10 @@ public final class InternalWidgets {
public Widget noOp() {
return NoOpWidget.INSTANCE;
}
+
+ @Override
+ public Widget wrapOverflow(Rectangle bounds, WidgetWithBounds widget) {
+ return new OverflowWidget(bounds, widget);
+ }
}
}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/NoOpWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/NoOpWidget.java
index a682b83e5..a9cfd79ce 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/NoOpWidget.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/NoOpWidget.java
@@ -1,3 +1,26 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022 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.widget;
import com.mojang.blaze3d.vertex.PoseStack;
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/OverflowWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/OverflowWidget.java
new file mode 100644
index 000000000..12cdfcfc9
--- /dev/null
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/OverflowWidget.java
@@ -0,0 +1,148 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022 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.widget;
+
+import com.mojang.blaze3d.vertex.PoseStack;
+import com.mojang.math.Matrix4f;
+import me.shedaniel.clothconfig2.api.ScissorsHandler;
+import me.shedaniel.clothconfig2.api.animator.NumberAnimator;
+import me.shedaniel.clothconfig2.api.animator.ValueAnimator;
+import me.shedaniel.clothconfig2.api.scroll.ScrollingContainer;
+import me.shedaniel.math.FloatingPoint;
+import me.shedaniel.math.Rectangle;
+import me.shedaniel.rei.RoughlyEnoughItemsCoreClient;
+import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds;
+
+@SuppressWarnings("UnstableApiUsage")
+public class OverflowWidget extends DelegateWidgetWithTranslate {
+ private final Rectangle bounds;
+ private final NumberAnimator<Float> scale;
+ private final ValueAnimator<FloatingPoint> translate;
+ private final ValueAnimator<FloatingPoint> velocity;
+ private boolean dragging;
+
+ public OverflowWidget(Rectangle bounds, WidgetWithBounds widget) {
+ super(widget, Matrix4f::new);
+ this.bounds = bounds;
+ this.scale = ValueAnimator.ofFloat()
+ .setAs(1f);
+ this.translate = ValueAnimator.ofFloatingPoint()
+ .setAs(new FloatingPoint(-widget.getBounds().width / 2f, -widget.getBounds().height / 2f));
+ this.velocity = ValueAnimator.ofFloatingPoint()
+ .setAs(new FloatingPoint(0f, 0f));
+ }
+
+ @Override
+ protected Matrix4f translate() {
+ FloatingPoint translate = this.translate.value();
+ float scale = 1 / Math.max(this.scale.floatValue(), 0.001f);
+ Matrix4f matrix = Matrix4f.createTranslateMatrix(bounds.getCenterX() + (float) translate.x * scale, bounds.getCenterY() + (float) translate.y * scale, 0);
+ matrix.multiply(Matrix4f.createScaleMatrix(scale, scale, 1));
+ return matrix;
+ }
+
+ @Override
+ public void render(PoseStack poseStack, int mouseX, int mouseY, float delta) {
+ Rectangle widgetBounds = ((WidgetWithBounds) widget).getBounds();
+ this.scale.update(delta);
+ this.scale.setTarget(ScrollingContainer.handleBounceBack(this.scale.target() - 1,
+ Math.min(widgetBounds.width * 1.0F / getBounds().width, widgetBounds.height * 1.0F / getBounds().height) - 1, delta, .001) + 1);
+ this.translate.update(delta);
+ this.translate.setAs(new FloatingPoint(
+ ScrollingContainer.handleBounceBack(this.translate.target().x + widgetBounds.width - getBounds().width / 2 * scale.value(),
+ widgetBounds.width - getBounds().width * scale.value(), delta, .001) - (widgetBounds.width - getBounds().width / 2 * scale.value()),
+ ScrollingContainer.handleBounceBack(this.translate.target().y + widgetBounds.height - getBounds().height / 2 * scale.value(),
+ widgetBounds.height - getBounds().height * scale.value(), delta, .001) - (widgetBounds.height - getBounds().height / 2 * scale.value())
+ ));
+ if (!RoughlyEnoughItemsCoreClient.isLeftMousePressed) {
+ this.translate.setAs(new FloatingPoint(this.translate.value().x + this.velocity.value().x, this.translate.value().y + this.velocity.value().y));
+ }
+ this.velocity.update(delta);
+ this.velocity.setTo(new FloatingPoint(
+ ScrollingContainer.handleBounceBack(this.velocity.target().x, 0, delta, .0001),
+ ScrollingContainer.handleBounceBack(this.velocity.target().y, 0, delta, .0001)
+ ), 20);
+
+ ScissorsHandler.INSTANCE.scissor(this.bounds);
+ super.render(poseStack, mouseX, mouseY, delta);
+ ScissorsHandler.INSTANCE.removeLastScissor();
+ }
+
+ @Override
+ public Rectangle getBounds() {
+ return bounds;
+ }
+
+ @Override
+ public boolean containsMouse(double mouseX, double mouseY) {
+ return getBounds().contains(mouseX, mouseY);
+ }
+
+ @Override
+ public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
+ if (containsMouse(mouseX, mouseY)) {
+ this.scale.setTo(this.scale.target() + amount * -0.2f, 300);
+ return true;
+ }
+
+ return super.mouseScrolled(mouseX, mouseY, amount);
+ }
+
+ @Override
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ if (super.mouseClicked(mouseX, mouseY, button)) return true;
+ if (containsMouse(mouseX, mouseY) && button == 0) {
+ dragging = true;
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean mouseReleased(double mouseX, double mouseY, int button) {
+ if (dragging && button == 0) {
+ dragging = false;
+ return true;
+ }
+
+ return super.mouseReleased(mouseX, mouseY, button);
+ }
+
+ @Override
+ public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
+ if (dragging && button == 0) {
+ double newXTranslate = translate.target().x;
+ double newYTranslate = translate.target().y;
+ newXTranslate += deltaX * scale.doubleValue();
+ newYTranslate += deltaY * scale.doubleValue();
+
+ translate.setAs(new FloatingPoint(newXTranslate, newYTranslate));
+ velocity.setAs(new FloatingPoint(deltaX * scale.doubleValue(), deltaY * scale.doubleValue()));
+ return true;
+ }
+
+ return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
+ }
+}
diff --git a/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json b/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json
index e5b6b8f0c..acbb8e558 100755
--- a/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json
+++ b/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json
@@ -60,6 +60,7 @@
"category.rei.wax_scraping": "Wax Scraping",
"category.rei.oxidizing": "Oxidizing",
"category.rei.oxidation_scraping": "Oxidation Scraping",
+ "category.rei.tag": "Tag",
"category.rei.information": "Information",
"text.rei.composting.chance": "§e%d%% Chance",
"text.rei.composting.page": "Page %d",
@@ -82,6 +83,8 @@
"text.auto_craft.move_items": "Move Items",
"text.auto_craft.move_items.tooltip": "Ctrl-Click to Quick Craft",
"text.auto_craft.move_items.yog": "Generate NullPointerException!!",
+ "text.rei.expand.view": "Open Expanded View",
+ "text.rei.tag.copy.clipboard": "Save Tag Tree to clipboard",
"error.rei.transfer.too_small": "Unable to move items to a %dx%d grid.",
"error.rei.not.on.server": "REI is not on the server.",
"error.rei.not.enough.materials": "Not enough materials.",