Added gui classes and some textures from Create.
This commit is contained in:
@@ -0,0 +1,39 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.platform.InputConstants;
|
||||||
|
import net.minecraft.client.KeyMapping;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.client.event.RegisterKeyMappingsEvent;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
public class AllKeys {
|
||||||
|
|
||||||
|
public static boolean isKeyDown(int key) {
|
||||||
|
return InputConstants.isKeyDown(Minecraft.getInstance()
|
||||||
|
.getWindow()
|
||||||
|
.getWindow(), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isMouseButtonDown(int button) {
|
||||||
|
return GLFW.glfwGetMouseButton(Minecraft.getInstance()
|
||||||
|
.getWindow()
|
||||||
|
.getWindow(), button) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean ctrlDown() {
|
||||||
|
return Screen.hasControlDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean shiftDown() {
|
||||||
|
return Screen.hasShiftDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean altDown() {
|
||||||
|
return Screen.hasAltDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.platform.InputConstants;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.widget.AbstractSimiWidget;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Components;
|
||||||
|
import net.minecraft.client.gui.components.AbstractWidget;
|
||||||
|
import net.minecraft.client.gui.components.Widget;
|
||||||
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||||
|
import net.minecraft.client.gui.narration.NarratableEntry;
|
||||||
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public abstract class AbstractSimiScreen extends Screen {
|
||||||
|
|
||||||
|
protected int windowWidth, windowHeight;
|
||||||
|
protected int windowXOffset, windowYOffset;
|
||||||
|
protected int guiLeft, guiTop;
|
||||||
|
|
||||||
|
protected AbstractSimiScreen(Component title) {
|
||||||
|
super(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbstractSimiScreen() {
|
||||||
|
this(Components.immutableEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method must be called before {@code super.init()}!
|
||||||
|
*/
|
||||||
|
protected void setWindowSize(int width, int height) {
|
||||||
|
windowWidth = width;
|
||||||
|
windowHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method must be called before {@code super.init()}!
|
||||||
|
*/
|
||||||
|
protected void setWindowOffset(int xOffset, int yOffset) {
|
||||||
|
windowXOffset = xOffset;
|
||||||
|
windowYOffset = yOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
guiLeft = (width - windowWidth) / 2;
|
||||||
|
guiTop = (height - windowHeight) / 2;
|
||||||
|
guiLeft += windowXOffset;
|
||||||
|
guiTop += windowYOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
for (GuiEventListener listener : children()) {
|
||||||
|
if (listener instanceof TickableGuiEventListener tickable) {
|
||||||
|
tickable.tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPauseScreen() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected <W extends GuiEventListener & Widget & NarratableEntry> void addRenderableWidgets(W... widgets) {
|
||||||
|
for (W widget : widgets) {
|
||||||
|
addRenderableWidget(widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <W extends GuiEventListener & Widget & NarratableEntry> void addRenderableWidgets(Collection<W> widgets) {
|
||||||
|
for (W widget : widgets) {
|
||||||
|
addRenderableWidget(widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void removeWidgets(GuiEventListener... widgets) {
|
||||||
|
for (GuiEventListener widget : widgets) {
|
||||||
|
removeWidget(widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void removeWidgets(Collection<? extends GuiEventListener> widgets) {
|
||||||
|
for (GuiEventListener widget : widgets) {
|
||||||
|
removeWidget(widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
partialTicks = minecraft.getFrameTime();
|
||||||
|
|
||||||
|
ms.pushPose();
|
||||||
|
|
||||||
|
prepareFrame();
|
||||||
|
|
||||||
|
renderWindowBackground(ms, mouseX, mouseY, partialTicks);
|
||||||
|
renderWindow(ms, mouseX, mouseY, partialTicks);
|
||||||
|
super.render(ms, mouseX, mouseY, partialTicks);
|
||||||
|
renderWindowForeground(ms, mouseX, mouseY, partialTicks);
|
||||||
|
|
||||||
|
endFrame();
|
||||||
|
|
||||||
|
ms.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||||
|
boolean keyPressed = super.keyPressed(keyCode, scanCode, modifiers);
|
||||||
|
if (keyPressed || getFocused() != null)
|
||||||
|
return keyPressed;
|
||||||
|
|
||||||
|
InputConstants.Key mouseKey = InputConstants.getKey(keyCode, scanCode);
|
||||||
|
if (this.minecraft.options.keyInventory.isActiveAndMatches(mouseKey)) {
|
||||||
|
this.onClose();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void prepareFrame() {}
|
||||||
|
|
||||||
|
protected void renderWindowBackground(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
renderBackground(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks);
|
||||||
|
|
||||||
|
protected void renderWindowForeground(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
for (Widget widget : renderables) {
|
||||||
|
if (widget instanceof AbstractSimiWidget simiWidget && simiWidget.isHoveredOrFocused()
|
||||||
|
&& simiWidget.visible) {
|
||||||
|
List<Component> tooltip = simiWidget.getToolTip();
|
||||||
|
if (tooltip.isEmpty())
|
||||||
|
continue;
|
||||||
|
int ttx = simiWidget.lockedTooltipX == -1 ? mouseX : simiWidget.lockedTooltipX + simiWidget.x;
|
||||||
|
int tty = simiWidget.lockedTooltipY == -1 ? mouseY : simiWidget.lockedTooltipY + simiWidget.y;
|
||||||
|
renderComponentTooltip(ms, tooltip, ttx, tty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void endFrame() {}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
protected void debugWindowArea(PoseStack matrixStack) {
|
||||||
|
fill(matrixStack, guiLeft + windowWidth, guiTop + windowHeight, guiLeft, guiTop, 0xD3D3D3D3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GuiEventListener getFocused() {
|
||||||
|
GuiEventListener focused = super.getFocused();
|
||||||
|
if (focused instanceof AbstractWidget && !((AbstractWidget) focused).isFocused())
|
||||||
|
focused = null;
|
||||||
|
setFocused(focused);
|
||||||
|
return focused;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import nl.requios.effortlessbuilding.create.Create;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.element.ScreenElement;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Color;
|
||||||
|
import net.minecraft.client.gui.GuiComponent;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public enum AllGuiTextures implements ScreenElement {
|
||||||
|
|
||||||
|
// Widgets
|
||||||
|
BUTTON("widgets", 18, 18),
|
||||||
|
BUTTON_HOVER("widgets", 18, 0, 18, 18),
|
||||||
|
BUTTON_DOWN("widgets", 36, 0, 18, 18),
|
||||||
|
INDICATOR("widgets", 0, 18, 18, 6),
|
||||||
|
INDICATOR_WHITE("widgets", 18, 18, 18, 6),
|
||||||
|
INDICATOR_GREEN("widgets", 36, 18, 18, 6),
|
||||||
|
INDICATOR_YELLOW("widgets", 54, 18, 18, 6),
|
||||||
|
INDICATOR_RED("widgets", 72, 18, 18, 6),
|
||||||
|
|
||||||
|
HOTSLOT_ARROW("widgets", 24, 51, 20, 12),
|
||||||
|
HOTSLOT("widgets", 0, 68, 22, 22),
|
||||||
|
HOTSLOT_ACTIVE("widgets", 0, 46, 22, 22),
|
||||||
|
HOTSLOT_SUPER_ACTIVE("widgets", 27, 67, 24, 24),
|
||||||
|
|
||||||
|
SPEECH_TOOLTIP_BACKGROUND("widgets", 0, 24, 8, 8),
|
||||||
|
SPEECH_TOOLTIP_COLOR("widgets", 8, 24, 8, 8),
|
||||||
|
|
||||||
|
TRAIN_HUD_SPEED_BG("widgets", 0, 190, 182, 5),
|
||||||
|
TRAIN_HUD_SPEED("widgets", 0, 185, 182, 5),
|
||||||
|
TRAIN_HUD_THROTTLE("widgets", 0, 195, 182, 5),
|
||||||
|
TRAIN_HUD_THROTTLE_POINTER("widgets", 0, 209, 6, 9),
|
||||||
|
TRAIN_HUD_FRAME("widgets", 0, 200, 186, 7),
|
||||||
|
TRAIN_HUD_DIRECTION("widgets", 77, 165, 28, 20),
|
||||||
|
TRAIN_PROMPT_L("widgets", 8, 209, 3, 16),
|
||||||
|
TRAIN_PROMPT_R("widgets", 11, 209, 3, 16),
|
||||||
|
TRAIN_PROMPT("widgets", 0, 230, 256, 16),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
public static final int FONT_COLOR = 0x575F7A;
|
||||||
|
|
||||||
|
public final ResourceLocation location;
|
||||||
|
public int width, height;
|
||||||
|
public int startX, startY;
|
||||||
|
|
||||||
|
private AllGuiTextures(String location, int width, int height) {
|
||||||
|
this(location, 0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AllGuiTextures(int startX, int startY) {
|
||||||
|
this("icons", startX * 16, startY * 16, 16, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AllGuiTextures(String location, int startX, int startY, int width, int height) {
|
||||||
|
this(Create.ID, location, startX, startY, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AllGuiTextures(String namespace, String location, int startX, int startY, int width, int height) {
|
||||||
|
this.location = new ResourceLocation(namespace, "textures/gui/" + location + ".png");
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.startX = startX;
|
||||||
|
this.startY = startY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void bind() {
|
||||||
|
RenderSystem.setShaderTexture(0, location);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
@Override
|
||||||
|
public void render(PoseStack ms, int x, int y) {
|
||||||
|
bind();
|
||||||
|
GuiComponent.blit(ms, x, y, 0, startX, startY, width, height, 256, 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void render(PoseStack ms, int x, int y, GuiComponent component) {
|
||||||
|
bind();
|
||||||
|
component.blit(ms, x, y, startX, startY, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void render(PoseStack ms, int x, int y, Color c) {
|
||||||
|
bind();
|
||||||
|
UIRenderHelper.drawColoredTexture(ms, c, x, y, startX, startY, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
import com.mojang.math.Matrix4f;
|
||||||
|
import nl.requios.effortlessbuilding.create.Create;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.element.DelegatedStencilElement;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.element.ScreenElement;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Color;
|
||||||
|
import net.minecraft.client.gui.GuiComponent;
|
||||||
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public class AllIcons implements ScreenElement {
|
||||||
|
|
||||||
|
public static final ResourceLocation ICON_ATLAS = Create.asResource("textures/gui/icons.png");
|
||||||
|
public static final int ICON_ATLAS_SIZE = 256;
|
||||||
|
|
||||||
|
private static int x = 0, y = -1;
|
||||||
|
private int iconX;
|
||||||
|
private int iconY;
|
||||||
|
|
||||||
|
public static final AllIcons
|
||||||
|
I_ADD = newRow(),
|
||||||
|
I_TRASH = next(),
|
||||||
|
I_3x3 = next(),
|
||||||
|
I_TARGET = next(),
|
||||||
|
I_PRIORITY_VERY_LOW = next(),
|
||||||
|
I_PRIORITY_LOW = next(),
|
||||||
|
I_PRIORITY_HIGH = next(),
|
||||||
|
I_PRIORITY_VERY_HIGH = next(),
|
||||||
|
I_BLACKLIST = next(),
|
||||||
|
I_WHITELIST = next(),
|
||||||
|
I_WHITELIST_OR = next(),
|
||||||
|
I_WHITELIST_AND = next(),
|
||||||
|
I_WHITELIST_NOT = next(),
|
||||||
|
I_RESPECT_NBT = next(),
|
||||||
|
I_IGNORE_NBT = next();
|
||||||
|
|
||||||
|
public static final AllIcons
|
||||||
|
I_CONFIRM = newRow(),
|
||||||
|
I_NONE = next(),
|
||||||
|
I_OPEN_FOLDER = next(),
|
||||||
|
I_REFRESH = next(),
|
||||||
|
I_ACTIVE = next(),
|
||||||
|
I_PASSIVE = next(),
|
||||||
|
I_ROTATE_PLACE = next(),
|
||||||
|
I_ROTATE_PLACE_RETURNED = next(),
|
||||||
|
I_ROTATE_NEVER_PLACE = next(),
|
||||||
|
I_MOVE_PLACE = next(),
|
||||||
|
I_MOVE_PLACE_RETURNED = next(),
|
||||||
|
I_MOVE_NEVER_PLACE = next(),
|
||||||
|
I_CART_ROTATE = next(),
|
||||||
|
I_CART_ROTATE_PAUSED = next(),
|
||||||
|
I_CART_ROTATE_LOCKED = next();
|
||||||
|
|
||||||
|
public static final AllIcons
|
||||||
|
I_DONT_REPLACE = newRow(),
|
||||||
|
I_REPLACE_SOLID = next(),
|
||||||
|
I_REPLACE_ANY = next(),
|
||||||
|
I_REPLACE_EMPTY = next(),
|
||||||
|
I_CENTERED = next(),
|
||||||
|
I_ATTACHED = next(),
|
||||||
|
I_INSERTED = next(),
|
||||||
|
I_FILL = next(),
|
||||||
|
I_PLACE = next(),
|
||||||
|
I_REPLACE = next(),
|
||||||
|
I_CLEAR = next(),
|
||||||
|
I_OVERLAY = next(),
|
||||||
|
I_FLATTEN = next(),
|
||||||
|
I_LMB = next(),
|
||||||
|
I_SCROLL = next(),
|
||||||
|
I_RMB = next();
|
||||||
|
|
||||||
|
public static final AllIcons
|
||||||
|
I_TOOL_DEPLOY = newRow(),
|
||||||
|
I_SKIP_MISSING = next(),
|
||||||
|
I_SKIP_TILES = next(),
|
||||||
|
I_DICE = next(),
|
||||||
|
I_TUNNEL_SPLIT = next(),
|
||||||
|
I_TUNNEL_FORCED_SPLIT = next(),
|
||||||
|
I_TUNNEL_ROUND_ROBIN = next(),
|
||||||
|
I_TUNNEL_FORCED_ROUND_ROBIN = next(),
|
||||||
|
I_TUNNEL_PREFER_NEAREST = next(),
|
||||||
|
I_TUNNEL_RANDOMIZE = next(),
|
||||||
|
I_TUNNEL_SYNCHRONIZE = next(),
|
||||||
|
I_TOOLBOX = next(),
|
||||||
|
I_VIEW_SCHEDULE = next(),
|
||||||
|
|
||||||
|
I_TOOL_MOVE_XZ = newRow(),
|
||||||
|
I_TOOL_MOVE_Y = next(),
|
||||||
|
I_TOOL_ROTATE = next(),
|
||||||
|
I_TOOL_MIRROR = next(),
|
||||||
|
I_ARM_ROUND_ROBIN = next(),
|
||||||
|
I_ARM_FORCED_ROUND_ROBIN = next(),
|
||||||
|
I_ARM_PREFER_FIRST = next(),
|
||||||
|
|
||||||
|
I_ADD_INVERTED_ATTRIBUTE = next(),
|
||||||
|
I_FLIP = next(),
|
||||||
|
|
||||||
|
I_PLAY = newRow(),
|
||||||
|
I_PAUSE = next(),
|
||||||
|
I_STOP = next(),
|
||||||
|
I_PLACEMENT_SETTINGS = next(),
|
||||||
|
I_ROTATE_CCW = next(),
|
||||||
|
I_HOUR_HAND_FIRST = next(),
|
||||||
|
I_MINUTE_HAND_FIRST = next(),
|
||||||
|
I_HOUR_HAND_FIRST_24 = next(),
|
||||||
|
|
||||||
|
I_PATTERN_SOLID = newRow(),
|
||||||
|
I_PATTERN_CHECKERED = next(),
|
||||||
|
I_PATTERN_CHECKERED_INVERSED = next(),
|
||||||
|
I_PATTERN_CHANCE_25 = next(),
|
||||||
|
|
||||||
|
I_PATTERN_CHANCE_50 = newRow(),
|
||||||
|
I_PATTERN_CHANCE_75 = next(),
|
||||||
|
I_FOLLOW_DIAGONAL = next(),
|
||||||
|
I_FOLLOW_MATERIAL = next(),
|
||||||
|
|
||||||
|
I_SCHEMATIC = newRow(),
|
||||||
|
I_SEQ_REPEAT = next(),
|
||||||
|
|
||||||
|
I_MTD_LEFT = newRow(),
|
||||||
|
I_MTD_CLOSE = next(),
|
||||||
|
I_MTD_RIGHT = next(),
|
||||||
|
I_MTD_SCAN = next(),
|
||||||
|
I_MTD_REPLAY = next(),
|
||||||
|
I_MTD_USER_MODE = next(),
|
||||||
|
I_MTD_SLOW_MODE = next(),
|
||||||
|
|
||||||
|
I_CONFIG_UNLOCKED = newRow(),
|
||||||
|
I_CONFIG_LOCKED = next(),
|
||||||
|
I_CONFIG_DISCARD = next(),
|
||||||
|
I_CONFIG_SAVE = next(),
|
||||||
|
I_CONFIG_RESET = next(),
|
||||||
|
I_CONFIG_BACK = next(),
|
||||||
|
I_CONFIG_PREV = next(),
|
||||||
|
I_CONFIG_NEXT = next(),
|
||||||
|
I_DISABLE = next(),
|
||||||
|
I_CONFIG_OPEN = next(),
|
||||||
|
|
||||||
|
I_FX_SURFACE_OFF = newRow(),
|
||||||
|
I_FX_SURFACE_ON = next(),
|
||||||
|
I_FX_FIELD_OFF = next(),
|
||||||
|
I_FX_FIELD_ON = next(),
|
||||||
|
I_FX_BLEND = next(),
|
||||||
|
I_FX_BLEND_OFF = next();
|
||||||
|
;
|
||||||
|
|
||||||
|
public AllIcons(int x, int y) {
|
||||||
|
iconX = x * 16;
|
||||||
|
iconY = y * 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AllIcons next() {
|
||||||
|
return new AllIcons(++x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AllIcons newRow() {
|
||||||
|
return new AllIcons(x = 0, ++y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void bind() {
|
||||||
|
RenderSystem.setShaderTexture(0, ICON_ATLAS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
@Override
|
||||||
|
public void render(PoseStack matrixStack, int x, int y) {
|
||||||
|
bind();
|
||||||
|
GuiComponent.blit(matrixStack, x, y, 0, iconX, iconY, 16, 16, 256, 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void render(PoseStack matrixStack, int x, int y, GuiComponent component) {
|
||||||
|
bind();
|
||||||
|
component.blit(matrixStack, x, y, iconX, iconY, 16, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void render(PoseStack ms, MultiBufferSource buffer, int color) {
|
||||||
|
VertexConsumer builder = buffer.getBuffer(RenderType.textSeeThrough(ICON_ATLAS));
|
||||||
|
Matrix4f matrix = ms.last().pose();
|
||||||
|
Color rgb = new Color(color);
|
||||||
|
int light = LightTexture.FULL_BRIGHT;
|
||||||
|
|
||||||
|
Vec3 vec1 = new Vec3(0, 0, 0);
|
||||||
|
Vec3 vec2 = new Vec3(0, 1, 0);
|
||||||
|
Vec3 vec3 = new Vec3(1, 1, 0);
|
||||||
|
Vec3 vec4 = new Vec3(1, 0, 0);
|
||||||
|
|
||||||
|
float u1 = iconX * 1f / ICON_ATLAS_SIZE;
|
||||||
|
float u2 = (iconX + 16) * 1f / ICON_ATLAS_SIZE;
|
||||||
|
float v1 = iconY * 1f / ICON_ATLAS_SIZE;
|
||||||
|
float v2 = (iconY + 16) * 1f / ICON_ATLAS_SIZE;
|
||||||
|
|
||||||
|
vertex(builder, matrix, vec1, rgb, u1, v1, light);
|
||||||
|
vertex(builder, matrix, vec2, rgb, u1, v2, light);
|
||||||
|
vertex(builder, matrix, vec3, rgb, u2, v2, light);
|
||||||
|
vertex(builder, matrix, vec4, rgb, u2, v1, light);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
private void vertex(VertexConsumer builder, Matrix4f matrix, Vec3 vec, Color rgb, float u, float v, int light) {
|
||||||
|
builder.vertex(matrix, (float) vec.x, (float) vec.y, (float) vec.z)
|
||||||
|
.color(rgb.getRed(), rgb.getGreen(), rgb.getBlue(), 255)
|
||||||
|
.uv(u, v)
|
||||||
|
.uv2(light)
|
||||||
|
.endVertex();
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public DelegatedStencilElement asStencil() {
|
||||||
|
return new DelegatedStencilElement().withStencilRenderer((ms, w, h, alpha) -> this.render(ms, 0, 0)).withBounds(16, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.element.BoxElement;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.element.TextStencilElement;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.widget.BoxWidget;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
|
import net.minecraft.network.chat.FormattedText;
|
||||||
|
import net.minecraft.network.chat.Style;
|
||||||
|
import org.lwjgl.opengl.GL30;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class ConfirmationScreen extends AbstractSimiScreen {
|
||||||
|
|
||||||
|
private Screen source;
|
||||||
|
private Consumer<Response> action = _success -> {
|
||||||
|
};
|
||||||
|
private List<FormattedText> text = new ArrayList<>();
|
||||||
|
private boolean centered = false;
|
||||||
|
private int x;
|
||||||
|
private int y;
|
||||||
|
private int textWidth;
|
||||||
|
private int textHeight;
|
||||||
|
private boolean tristate;
|
||||||
|
|
||||||
|
private BoxWidget confirm;
|
||||||
|
private BoxWidget confirmDontSave;
|
||||||
|
private BoxWidget cancel;
|
||||||
|
private BoxElement textBackground;
|
||||||
|
|
||||||
|
public enum Response {
|
||||||
|
Confirm, ConfirmDontSave, Cancel
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Removes text lines from the back of the list
|
||||||
|
* */
|
||||||
|
public ConfirmationScreen removeTextLines(int amount) {
|
||||||
|
if (amount > text.size())
|
||||||
|
return clearText();
|
||||||
|
|
||||||
|
text.subList(text.size() - amount, text.size()).clear();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfirmationScreen clearText() {
|
||||||
|
this.text.clear();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfirmationScreen addText(FormattedText text) {
|
||||||
|
this.text.add(text);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfirmationScreen withText(FormattedText text) {
|
||||||
|
return clearText().addText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfirmationScreen at(int x, int y) {
|
||||||
|
this.x = Math.max(x, 0);
|
||||||
|
this.y = Math.max(y, 0);
|
||||||
|
this.centered = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfirmationScreen centered() {
|
||||||
|
this.centered = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfirmationScreen withAction(Consumer<Boolean> action) {
|
||||||
|
this.action = r -> action.accept(r == Response.Confirm);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfirmationScreen withThreeActions(Consumer<Response> action) {
|
||||||
|
this.action = action;
|
||||||
|
this.tristate = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open(@Nonnull Screen source) {
|
||||||
|
this.source = source;
|
||||||
|
Minecraft client = source.getMinecraft();
|
||||||
|
this.init(client, client.getWindow().getGuiScaledWidth(), client.getWindow().getGuiScaledHeight());
|
||||||
|
this.minecraft.screen = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
source.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
|
||||||
|
ArrayList<FormattedText> copy = new ArrayList<>(text);
|
||||||
|
text.clear();
|
||||||
|
copy.forEach(t -> text.addAll(font.getSplitter().splitLines(t, 300, Style.EMPTY)));
|
||||||
|
|
||||||
|
textHeight = text.size() * (font.lineHeight + 1) + 4;
|
||||||
|
textWidth = 300;
|
||||||
|
|
||||||
|
if (centered) {
|
||||||
|
x = width/2 - textWidth/2 - 2;
|
||||||
|
y = height/2 - textHeight/2 - 16;
|
||||||
|
} else {
|
||||||
|
x = Math.max(0, x - textWidth / 2);
|
||||||
|
y = Math.max(0, y -= textHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x + textWidth > width) {
|
||||||
|
x = width - textWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y + textHeight + 30 > height) {
|
||||||
|
y = height - textHeight - 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
int buttonX = x + textWidth / 2 - 6 - (int) (70 * (tristate ? 1.5f : 1));
|
||||||
|
|
||||||
|
TextStencilElement confirmText =
|
||||||
|
new TextStencilElement(font, tristate ? "Save" : "Confirm").centered(true, true);
|
||||||
|
confirm = new BoxWidget(buttonX, y + textHeight + 6, 70, 16).withCallback(() -> accept(Response.Confirm));
|
||||||
|
confirm.showingElement(confirmText.withElementRenderer(BoxWidget.gradientFactory.apply(confirm)));
|
||||||
|
addRenderableWidget(confirm);
|
||||||
|
|
||||||
|
buttonX += 12 + 70;
|
||||||
|
|
||||||
|
if (tristate) {
|
||||||
|
TextStencilElement confirmDontSaveText =
|
||||||
|
new TextStencilElement(font, "Don't Save").centered(true, true);
|
||||||
|
confirmDontSave =
|
||||||
|
new BoxWidget(buttonX, y + textHeight + 6, 70, 16).withCallback(() -> accept(Response.ConfirmDontSave));
|
||||||
|
confirmDontSave.showingElement(
|
||||||
|
confirmDontSaveText.withElementRenderer(BoxWidget.gradientFactory.apply(confirmDontSave)));
|
||||||
|
addRenderableWidget(confirmDontSave);
|
||||||
|
buttonX += 12 + 70;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextStencilElement cancelText = new TextStencilElement(font, "Cancel").centered(true, true);
|
||||||
|
cancel = new BoxWidget(buttonX, y + textHeight + 6, 70, 16)
|
||||||
|
.withCallback(() -> accept(Response.Cancel));
|
||||||
|
cancel.showingElement(cancelText.withElementRenderer(BoxWidget.gradientFactory.apply(cancel)));
|
||||||
|
addRenderableWidget(cancel);
|
||||||
|
|
||||||
|
textBackground = new BoxElement()
|
||||||
|
.gradientBorder(Theme.p(Theme.Key.BUTTON_DISABLE))
|
||||||
|
.withBounds(width + 10, textHeight + 35)
|
||||||
|
.at(-5, y - 5);
|
||||||
|
|
||||||
|
if (text.size() == 1)
|
||||||
|
x = (width - font.width(text.get(0))) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClose() {
|
||||||
|
accept(Response.Cancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void accept(Response success) {
|
||||||
|
minecraft.screen = source;
|
||||||
|
action.accept(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
textBackground.render(ms);
|
||||||
|
int offset = font.lineHeight + 1;
|
||||||
|
int lineY = y - offset;
|
||||||
|
|
||||||
|
ms.pushPose();
|
||||||
|
ms.translate(0, 0, 200);
|
||||||
|
|
||||||
|
for (FormattedText line : text) {
|
||||||
|
lineY += offset;
|
||||||
|
if (line == null)
|
||||||
|
continue;
|
||||||
|
font.draw(ms, line.getString(), x, lineY, 0xeaeaea);
|
||||||
|
}
|
||||||
|
|
||||||
|
ms.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderWindowBackground(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
endFrame();
|
||||||
|
|
||||||
|
source.render(ms, 0, 0, 10); // zero mouse coords to prevent further tooltips
|
||||||
|
|
||||||
|
prepareFrame();
|
||||||
|
|
||||||
|
this.fillGradient(ms, 0, 0, this.width, this.height, 0x70101010, 0x80101010);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void prepareFrame() {
|
||||||
|
UIRenderHelper.swapAndBlitColor(minecraft.getMainRenderTarget(), UIRenderHelper.framebuffer);
|
||||||
|
RenderSystem.clear(GL30.GL_STENCIL_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void endFrame() {
|
||||||
|
UIRenderHelper.swapAndBlitColor(UIRenderHelper.framebuffer, minecraft.getMainRenderTarget());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resize(@Nonnull Minecraft client, int width, int height) {
|
||||||
|
super.resize(client, width, height);
|
||||||
|
source.resize(client, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPauseScreen() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.math.Matrix4f;
|
||||||
|
import com.mojang.math.Vector3f;
|
||||||
|
|
||||||
|
public class CustomLightingSettings implements ILightingSettings {
|
||||||
|
|
||||||
|
private Vector3f light1;
|
||||||
|
private Vector3f light2;
|
||||||
|
private Matrix4f lightMatrix;
|
||||||
|
|
||||||
|
protected CustomLightingSettings(float yRot, float xRot) {
|
||||||
|
init(yRot, xRot, 0, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CustomLightingSettings(float yRot1, float xRot1, float yRot2, float xRot2) {
|
||||||
|
init(yRot1, xRot1, yRot2, xRot2, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void init(float yRot1, float xRot1, float yRot2, float xRot2, boolean doubleLight) {
|
||||||
|
light1 = Vector3f.ZP.copy();
|
||||||
|
light1.transform(Vector3f.YP.rotationDegrees(yRot1));
|
||||||
|
light1.transform(Vector3f.XN.rotationDegrees(xRot1));
|
||||||
|
|
||||||
|
if (doubleLight) {
|
||||||
|
light2 = Vector3f.ZP.copy();
|
||||||
|
light2.transform(Vector3f.YP.rotationDegrees(yRot2));
|
||||||
|
light2.transform(Vector3f.XN.rotationDegrees(xRot2));
|
||||||
|
} else {
|
||||||
|
light2 = Vector3f.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
lightMatrix = new Matrix4f();
|
||||||
|
lightMatrix.setIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyLighting() {
|
||||||
|
RenderSystem.setupLevelDiffuseLighting(light1, light2, lightMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
private float yRot1, xRot1;
|
||||||
|
private float yRot2, xRot2;
|
||||||
|
private boolean doubleLight;
|
||||||
|
|
||||||
|
public Builder firstLightRotation(float yRot, float xRot) {
|
||||||
|
yRot1 = yRot;
|
||||||
|
xRot1 = xRot;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder secondLightRotation(float yRot, float xRot) {
|
||||||
|
yRot2 = yRot;
|
||||||
|
xRot2 = xRot;
|
||||||
|
doubleLight = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder doubleLight() {
|
||||||
|
doubleLight = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomLightingSettings build() {
|
||||||
|
if (doubleLight) {
|
||||||
|
return new CustomLightingSettings(yRot1, xRot1, yRot2, xRot2);
|
||||||
|
} else {
|
||||||
|
return new CustomLightingSettings(yRot1, xRot1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.platform.Lighting;
|
||||||
|
|
||||||
|
public interface ILightingSettings {
|
||||||
|
|
||||||
|
void applyLighting();
|
||||||
|
|
||||||
|
static final ILightingSettings DEFAULT_3D = () -> Lighting.setupFor3DItems();
|
||||||
|
static final ILightingSettings DEFAULT_FLAT = () -> Lighting.setupForFlatItems();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.Tesselator;
|
||||||
|
import com.mojang.math.Matrix4f;
|
||||||
|
import net.minecraft.client.gui.Font;
|
||||||
|
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
|
import net.minecraft.network.chat.FormattedText;
|
||||||
|
import net.minecraft.network.chat.Style;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraftforge.client.ForgeHooksClient;
|
||||||
|
import net.minecraftforge.client.event.RenderTooltipEvent;
|
||||||
|
import net.minecraftforge.client.gui.ScreenUtils;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class RemovedGuiUtils {
|
||||||
|
@Nonnull
|
||||||
|
private static ItemStack cachedTooltipStack = ItemStack.EMPTY;
|
||||||
|
|
||||||
|
public static void preItemToolTip(@Nonnull ItemStack stack) {
|
||||||
|
cachedTooltipStack = stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void postItemToolTip() {
|
||||||
|
cachedTooltipStack = ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void drawHoveringText(PoseStack mStack, List<? extends FormattedText> textLines, int mouseX,
|
||||||
|
int mouseY, int screenWidth, int screenHeight, int maxTextWidth, Font font) {
|
||||||
|
drawHoveringText(mStack, textLines, mouseX, mouseY, screenWidth, screenHeight, maxTextWidth,
|
||||||
|
ScreenUtils.DEFAULT_BACKGROUND_COLOR, ScreenUtils.DEFAULT_BORDER_COLOR_START, ScreenUtils.DEFAULT_BORDER_COLOR_END,
|
||||||
|
font);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void drawHoveringText(PoseStack mStack, List<? extends FormattedText> textLines, int mouseX,
|
||||||
|
int mouseY, int screenWidth, int screenHeight, int maxTextWidth, int backgroundColor, int borderColorStart,
|
||||||
|
int borderColorEnd, Font font) {
|
||||||
|
drawHoveringText(cachedTooltipStack, mStack, textLines, mouseX, mouseY, screenWidth, screenHeight, maxTextWidth,
|
||||||
|
backgroundColor, borderColorStart, borderColorEnd, font);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void drawHoveringText(@Nonnull final ItemStack stack, PoseStack mStack,
|
||||||
|
List<? extends FormattedText> textLines, int mouseX, int mouseY, int screenWidth, int screenHeight,
|
||||||
|
int maxTextWidth, Font font) {
|
||||||
|
drawHoveringText(stack, mStack, textLines, mouseX, mouseY, screenWidth, screenHeight, maxTextWidth,
|
||||||
|
ScreenUtils.DEFAULT_BACKGROUND_COLOR, ScreenUtils.DEFAULT_BORDER_COLOR_START, ScreenUtils.DEFAULT_BORDER_COLOR_END,
|
||||||
|
font);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void drawHoveringText(@Nonnull final ItemStack stack, PoseStack pStack,
|
||||||
|
List<? extends FormattedText> textLines, int mouseX, int mouseY, int screenWidth, int screenHeight,
|
||||||
|
int maxTextWidth, int backgroundColor, int borderColorStart, int borderColorEnd, Font font) {
|
||||||
|
if (textLines.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
List<ClientTooltipComponent> list = ForgeHooksClient.gatherTooltipComponents(stack, textLines,
|
||||||
|
stack.getTooltipImage(), mouseX, screenWidth, screenHeight, font, font);
|
||||||
|
RenderTooltipEvent.Pre event =
|
||||||
|
new RenderTooltipEvent.Pre(stack, pStack, mouseX, mouseY, screenWidth, screenHeight, font, list);
|
||||||
|
if (MinecraftForge.EVENT_BUS.post(event))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mouseX = event.getX();
|
||||||
|
mouseY = event.getY();
|
||||||
|
screenWidth = event.getScreenWidth();
|
||||||
|
screenHeight = event.getScreenHeight();
|
||||||
|
font = event.getFont();
|
||||||
|
|
||||||
|
// RenderSystem.disableRescaleNormal();
|
||||||
|
RenderSystem.disableDepthTest();
|
||||||
|
int tooltipTextWidth = 0;
|
||||||
|
|
||||||
|
for (FormattedText textLine : textLines) {
|
||||||
|
int textLineWidth = font.width(textLine);
|
||||||
|
if (textLineWidth > tooltipTextWidth)
|
||||||
|
tooltipTextWidth = textLineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean needsWrap = false;
|
||||||
|
|
||||||
|
int titleLinesCount = 1;
|
||||||
|
int tooltipX = mouseX + 12;
|
||||||
|
if (tooltipX + tooltipTextWidth + 4 > screenWidth) {
|
||||||
|
tooltipX = mouseX - 16 - tooltipTextWidth;
|
||||||
|
if (tooltipX < 4) // if the tooltip doesn't fit on the screen
|
||||||
|
{
|
||||||
|
if (mouseX > screenWidth / 2)
|
||||||
|
tooltipTextWidth = mouseX - 12 - 8;
|
||||||
|
else
|
||||||
|
tooltipTextWidth = screenWidth - 16 - mouseX;
|
||||||
|
needsWrap = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxTextWidth > 0 && tooltipTextWidth > maxTextWidth) {
|
||||||
|
tooltipTextWidth = maxTextWidth;
|
||||||
|
needsWrap = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsWrap) {
|
||||||
|
int wrappedTooltipWidth = 0;
|
||||||
|
List<FormattedText> wrappedTextLines = new ArrayList<>();
|
||||||
|
for (int i = 0; i < textLines.size(); i++) {
|
||||||
|
FormattedText textLine = textLines.get(i);
|
||||||
|
List<FormattedText> wrappedLine = font.getSplitter()
|
||||||
|
.splitLines(textLine, tooltipTextWidth, Style.EMPTY);
|
||||||
|
if (i == 0)
|
||||||
|
titleLinesCount = wrappedLine.size();
|
||||||
|
|
||||||
|
for (FormattedText line : wrappedLine) {
|
||||||
|
int lineWidth = font.width(line);
|
||||||
|
if (lineWidth > wrappedTooltipWidth)
|
||||||
|
wrappedTooltipWidth = lineWidth;
|
||||||
|
wrappedTextLines.add(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tooltipTextWidth = wrappedTooltipWidth;
|
||||||
|
textLines = wrappedTextLines;
|
||||||
|
|
||||||
|
if (mouseX > screenWidth / 2)
|
||||||
|
tooltipX = mouseX - 16 - tooltipTextWidth;
|
||||||
|
else
|
||||||
|
tooltipX = mouseX + 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tooltipY = mouseY - 12;
|
||||||
|
int tooltipHeight = 8;
|
||||||
|
|
||||||
|
if (textLines.size() > 1) {
|
||||||
|
tooltipHeight += (textLines.size() - 1) * 10;
|
||||||
|
if (textLines.size() > titleLinesCount)
|
||||||
|
tooltipHeight += 2; // gap between title lines and next lines
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tooltipY < 4)
|
||||||
|
tooltipY = 4;
|
||||||
|
else if (tooltipY + tooltipHeight + 4 > screenHeight)
|
||||||
|
tooltipY = screenHeight - tooltipHeight - 4;
|
||||||
|
|
||||||
|
final int zLevel = 400;
|
||||||
|
RenderTooltipEvent.Color colorEvent = new RenderTooltipEvent.Color(stack, pStack, tooltipX, tooltipY,
|
||||||
|
font, backgroundColor, borderColorStart, borderColorEnd, list);
|
||||||
|
MinecraftForge.EVENT_BUS.post(colorEvent);
|
||||||
|
backgroundColor = colorEvent.getBackgroundStart();
|
||||||
|
borderColorStart = colorEvent.getBorderStart();
|
||||||
|
borderColorEnd = colorEvent.getBorderEnd();
|
||||||
|
|
||||||
|
pStack.pushPose();
|
||||||
|
Matrix4f mat = pStack.last()
|
||||||
|
.pose();
|
||||||
|
ScreenUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY - 4, tooltipX + tooltipTextWidth + 3,
|
||||||
|
tooltipY - 3, backgroundColor, backgroundColor);
|
||||||
|
ScreenUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY + tooltipHeight + 3,
|
||||||
|
tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 4, backgroundColor, backgroundColor);
|
||||||
|
ScreenUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3,
|
||||||
|
tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor);
|
||||||
|
ScreenUtils.drawGradientRect(mat, zLevel, tooltipX - 4, tooltipY - 3, tooltipX - 3, tooltipY + tooltipHeight + 3,
|
||||||
|
backgroundColor, backgroundColor);
|
||||||
|
ScreenUtils.drawGradientRect(mat, zLevel, tooltipX + tooltipTextWidth + 3, tooltipY - 3,
|
||||||
|
tooltipX + tooltipTextWidth + 4, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor);
|
||||||
|
ScreenUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY - 3 + 1, tooltipX - 3 + 1,
|
||||||
|
tooltipY + tooltipHeight + 3 - 1, borderColorStart, borderColorEnd);
|
||||||
|
ScreenUtils.drawGradientRect(mat, zLevel, tooltipX + tooltipTextWidth + 2, tooltipY - 3 + 1,
|
||||||
|
tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3 - 1, borderColorStart, borderColorEnd);
|
||||||
|
ScreenUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3,
|
||||||
|
tooltipY - 3 + 1, borderColorStart, borderColorStart);
|
||||||
|
ScreenUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY + tooltipHeight + 2,
|
||||||
|
tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, borderColorEnd, borderColorEnd);
|
||||||
|
|
||||||
|
MultiBufferSource.BufferSource renderType = MultiBufferSource.immediate(Tesselator.getInstance()
|
||||||
|
.getBuilder());
|
||||||
|
pStack.translate(0.0D, 0.0D, zLevel);
|
||||||
|
|
||||||
|
for (int lineNumber = 0; lineNumber < list.size(); ++lineNumber) {
|
||||||
|
ClientTooltipComponent line = list.get(lineNumber);
|
||||||
|
|
||||||
|
if (line != null)
|
||||||
|
line.renderText(font, tooltipX, tooltipY, mat, renderType);
|
||||||
|
|
||||||
|
if (lineNumber + 1 == titleLinesCount)
|
||||||
|
tooltipY += 2;
|
||||||
|
|
||||||
|
tooltipY += 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderType.endBatch();
|
||||||
|
pStack.popPose();
|
||||||
|
|
||||||
|
RenderSystem.enableDepthTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui;
|
||||||
|
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Color;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Couple;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class Theme {
|
||||||
|
|
||||||
|
private static final List<Theme> THEMES = new ArrayList<>();
|
||||||
|
public static final Theme BASE = addTheme(new Theme());
|
||||||
|
|
||||||
|
public static Theme addTheme(@Nonnull Theme theme) {
|
||||||
|
THEMES.add(theme);
|
||||||
|
THEMES.sort(Comparator.comparingInt(Theme::getPriority).reversed());
|
||||||
|
return theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeTheme(Theme theme) {
|
||||||
|
THEMES.remove(theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void reload() {
|
||||||
|
THEMES.forEach(Theme::init);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ColorHolder resolve(String key) {
|
||||||
|
return THEMES
|
||||||
|
.stream()
|
||||||
|
.map(theme -> theme.get(key))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.findFirst()
|
||||||
|
.map(holder -> holder.lookupKey == null ? holder : resolve(holder.lookupKey))
|
||||||
|
.orElse(ColorHolder.MISSING);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull public static Couple<Color> p(@Nonnull Key key) {return p(key.get());}
|
||||||
|
@Nonnull public static Couple<Color> p(String key) {return resolve(key).asPair();}
|
||||||
|
|
||||||
|
@Nonnull public static Color c(@Nonnull Key key, boolean first) {return c(key.get(), first);}
|
||||||
|
@Nonnull public static Color c(String key, boolean first) {return p(key).get(first);}
|
||||||
|
|
||||||
|
public static int i(@Nonnull Key key, boolean first) {return i(key.get(), first);}
|
||||||
|
public static int i(String key, boolean first) {return p(key).get(first).getRGB();}
|
||||||
|
|
||||||
|
@Nonnull public static Color c(@Nonnull Key key) {return c(key.get());}
|
||||||
|
@Nonnull public static Color c(String key) {return resolve(key).get();}
|
||||||
|
|
||||||
|
public static int i(@Nonnull Key key) {return i(key.get());}
|
||||||
|
public static int i(String key) {return resolve(key).get().getRGB();}
|
||||||
|
|
||||||
|
//-----------//
|
||||||
|
|
||||||
|
protected final Map<String, ColorHolder> colors;
|
||||||
|
private int priority = 0;
|
||||||
|
|
||||||
|
protected Theme() {
|
||||||
|
colors = new HashMap<>();
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Small note to addons: if you also want to make use of Theme,
|
||||||
|
* and add new Keys, please do not use mixins. Instead make a Theme
|
||||||
|
* subclass, override init and apply it via the static #addTheme
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
protected void init() {
|
||||||
|
put(Key.BUTTON_IDLE, new Color(0xdd_8ab6d6, true), new Color(0x90_8ab6d6, true));
|
||||||
|
put(Key.BUTTON_HOVER, new Color(0xff_9ABBD3, true), new Color(0xd0_9ABBD3, true));
|
||||||
|
put(Key.BUTTON_CLICK, new Color(0xff_ffffff), new Color(0xee_ffffff));
|
||||||
|
put(Key.BUTTON_DISABLE, new Color(0x80_909090, true), new Color(0x60_909090, true));
|
||||||
|
put(Key.BUTTON_SUCCESS, new Color(0xcc_88f788, true), new Color(0xcc_20cc20, true));
|
||||||
|
put(Key.BUTTON_FAIL, new Color(0xcc_f78888, true), new Color(0xcc_cc2020, true));
|
||||||
|
put(Key.TEXT, new Color(0xff_eeeeee), new Color(0xff_a3a3a3));
|
||||||
|
put(Key.TEXT_DARKER, new Color(0xff_a3a3a3), new Color(0xff_808080));
|
||||||
|
put(Key.TEXT_ACCENT_STRONG, new Color(0xff_8ab6d6), new Color(0xff_8ab6d6));
|
||||||
|
put(Key.TEXT_ACCENT_SLIGHT, new Color(0xff_ddeeff), new Color(0xff_a0b0c0));
|
||||||
|
put(Key.STREAK, new Color(0x101010, false));
|
||||||
|
put(Key.VANILLA_TOOLTIP_BORDER, new Color(0x50_5000ff, true), new Color(0x50_28007f, true));
|
||||||
|
put(Key.VANILLA_TOOLTIP_BACKGROUND, new Color(0xf0_100010, true));
|
||||||
|
|
||||||
|
put(Key.PONDER_BUTTON_IDLE, new Color(0x60_c0c0ff, true), new Color(0x30_c0c0ff, true));
|
||||||
|
put(Key.PONDER_BUTTON_HOVER, new Color(0xf0_c0c0ff, true), new Color(0xa0_c0c0ff, true));
|
||||||
|
put(Key.PONDER_BUTTON_CLICK, new Color(0xff_ffffff), new Color(0xdd_ffffff));
|
||||||
|
put(Key.PONDER_BUTTON_DISABLE, new Color(0x80_909090, true), new Color(0x20_909090, true));
|
||||||
|
put(Key.PONDER_BACKGROUND_TRANSPARENT, new Color(0xdd_000000, true));
|
||||||
|
put(Key.PONDER_BACKGROUND_FLAT, new Color(0xff_000000, false));
|
||||||
|
put(Key.PONDER_BACKGROUND_IMPORTANT, new Color(0xdd_0e0e20, true));
|
||||||
|
put(Key.PONDER_IDLE, new Color(0x40ffeedd, true), new Color(0x20ffeedd, true));
|
||||||
|
put(Key.PONDER_HOVER, new Color(0x70ffffff, true), new Color(0x30ffffff, true));
|
||||||
|
put(Key.PONDER_HIGHLIGHT, new Color(0xf0ffeedd, true), new Color(0x60ffeedd, true));
|
||||||
|
put(Key.TEXT_WINDOW_BORDER, new Color(0x607a6000, true), new Color(0x207a6000, true));
|
||||||
|
put(Key.PONDER_BACK_ARROW, new Color(0xf0aa9999, true), new Color(0x30aa9999, true));
|
||||||
|
put(Key.PONDER_PROGRESSBAR, new Color(0x80ffeedd, true), new Color(0x50ffeedd, true));
|
||||||
|
put(Key.PONDER_MISSING_CREATE, new Color(0x70_984500, true), new Color(0x70_692400, true));
|
||||||
|
//put(Key.PONDER_MISSING_VANILLA, new Color(0x50_5000ff, true), new Color(0x50_300077, true));
|
||||||
|
lookup(Key.PONDER_MISSING_VANILLA, Key.VANILLA_TOOLTIP_BORDER);
|
||||||
|
put(Key.CONFIG_TITLE_A, new Color(0xffc69fbc, true), new Color(0xfff6b8bb, true));
|
||||||
|
put(Key.CONFIG_TITLE_B, new Color(0xfff6b8bb, true), new Color(0xfffbf994, true));
|
||||||
|
//put(Key., new Color(0x, true), new Color(0x, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void put(String key, Color c) {
|
||||||
|
colors.put(key, ColorHolder.single(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void put(Key key, Color c) {
|
||||||
|
put(key.get(), c);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void put(String key, Color c1, Color c2) {
|
||||||
|
colors.put(key, ColorHolder.pair(c1, c2));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void put(Key key, Color c1, Color c2) {
|
||||||
|
put(key.get(), c1, c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void lookup(Key key, Key source) {
|
||||||
|
colors.put(key.get(), ColorHolder.lookup(source.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable protected ColorHolder get(String key) {
|
||||||
|
return colors.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPriority() {
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Theme setPriority(int priority) {
|
||||||
|
this.priority = priority;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Key {
|
||||||
|
|
||||||
|
public static final Key BUTTON_IDLE = new Key();
|
||||||
|
public static final Key BUTTON_HOVER = new Key();
|
||||||
|
public static final Key BUTTON_CLICK = new Key();
|
||||||
|
public static final Key BUTTON_DISABLE = new Key();
|
||||||
|
public static final Key BUTTON_SUCCESS = new Key();
|
||||||
|
public static final Key BUTTON_FAIL = new Key();
|
||||||
|
|
||||||
|
public static final Key TEXT = new Key();
|
||||||
|
public static final Key TEXT_DARKER = new Key();
|
||||||
|
public static final Key TEXT_ACCENT_STRONG = new Key();
|
||||||
|
public static final Key TEXT_ACCENT_SLIGHT = new Key();
|
||||||
|
|
||||||
|
public static final Key STREAK = new Key();
|
||||||
|
public static final Key VANILLA_TOOLTIP_BORDER = new Key();
|
||||||
|
public static final Key VANILLA_TOOLTIP_BACKGROUND = new Key();
|
||||||
|
|
||||||
|
public static final Key PONDER_BACKGROUND_TRANSPARENT = new Key();
|
||||||
|
public static final Key PONDER_BACKGROUND_FLAT = new Key();
|
||||||
|
public static final Key PONDER_BACKGROUND_IMPORTANT = new Key();
|
||||||
|
public static final Key PONDER_IDLE = new Key();
|
||||||
|
public static final Key PONDER_HOVER = new Key();
|
||||||
|
public static final Key PONDER_HIGHLIGHT = new Key();
|
||||||
|
public static final Key TEXT_WINDOW_BORDER = new Key();
|
||||||
|
public static final Key PONDER_BACK_ARROW = new Key();
|
||||||
|
public static final Key PONDER_PROGRESSBAR = new Key();
|
||||||
|
public static final Key PONDER_MISSING_CREATE = new Key();
|
||||||
|
public static final Key PONDER_MISSING_VANILLA = new Key();
|
||||||
|
|
||||||
|
public static final Key PONDER_BUTTON_IDLE = new Key();
|
||||||
|
public static final Key PONDER_BUTTON_HOVER = new Key();
|
||||||
|
public static final Key PONDER_BUTTON_CLICK = new Key();
|
||||||
|
public static final Key PONDER_BUTTON_DISABLE = new Key();
|
||||||
|
|
||||||
|
public static final Key CONFIG_TITLE_A = new Key();
|
||||||
|
public static final Key CONFIG_TITLE_B = new Key();
|
||||||
|
|
||||||
|
private static int index = 0;
|
||||||
|
|
||||||
|
private final String s;
|
||||||
|
|
||||||
|
protected Key() {
|
||||||
|
this.s = "_" + index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Key(String s) {
|
||||||
|
this.s = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get() {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ColorHolder {
|
||||||
|
|
||||||
|
private static final ColorHolder MISSING = ColorHolder.single(Color.BLACK);
|
||||||
|
|
||||||
|
private Couple<Color> colors;
|
||||||
|
private String lookupKey;
|
||||||
|
|
||||||
|
private static ColorHolder single(Color c) {
|
||||||
|
ColorHolder h = new ColorHolder();
|
||||||
|
h.colors = Couple.create(c.setImmutable(), c.setImmutable());
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ColorHolder pair(Color first, Color second) {
|
||||||
|
ColorHolder h = new ColorHolder();
|
||||||
|
h.colors = Couple.create(first.setImmutable(), second.setImmutable());
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ColorHolder lookup(String key) {
|
||||||
|
ColorHolder h = new ColorHolder();
|
||||||
|
h.lookupKey = key;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color get() {
|
||||||
|
return colors.getFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Couple<Color> asPair() {
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||||
|
|
||||||
|
public interface TickableGuiEventListener extends GuiEventListener {
|
||||||
|
void tick();
|
||||||
|
}
|
||||||
@@ -0,0 +1,316 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.pipeline.RenderTarget;
|
||||||
|
import com.mojang.blaze3d.platform.GlConst;
|
||||||
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
import com.mojang.blaze3d.platform.Window;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.*;
|
||||||
|
import com.mojang.math.Matrix4f;
|
||||||
|
import com.mojang.math.Vector3f;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Color;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Couple;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.GameRenderer;
|
||||||
|
import net.minecraftforge.client.gui.ScreenUtils;
|
||||||
|
import org.lwjgl.opengl.GL20;
|
||||||
|
import org.lwjgl.opengl.GL30;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
public class UIRenderHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An FBO that has a stencil buffer for use wherever stencil are necessary. Forcing the main FBO to have a stencil
|
||||||
|
* buffer will cause GL error spam when using fabulous graphics.
|
||||||
|
*/
|
||||||
|
public static CustomRenderTarget framebuffer;
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
RenderSystem.recordRenderCall(() -> {
|
||||||
|
Window mainWindow = Minecraft.getInstance().getWindow();
|
||||||
|
framebuffer = CustomRenderTarget.create(mainWindow);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateWindowSize(Window mainWindow) {
|
||||||
|
if (framebuffer != null)
|
||||||
|
framebuffer.resize(mainWindow.getWidth(), mainWindow.getHeight(), Minecraft.ON_OSX);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void drawFramebuffer(float alpha) {
|
||||||
|
framebuffer.renderWithAlpha(alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch from src to dst, after copying the contents of src to dst.
|
||||||
|
*/
|
||||||
|
public static void swapAndBlitColor(RenderTarget src, RenderTarget dst) {
|
||||||
|
GlStateManager._glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, src.frameBufferId);
|
||||||
|
GlStateManager._glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, dst.frameBufferId);
|
||||||
|
GlStateManager._glBlitFrameBuffer(0, 0, src.viewWidth, src.viewHeight, 0, 0, dst.viewWidth, dst.viewHeight, GL30.GL_COLOR_BUFFER_BIT, GL20.GL_LINEAR);
|
||||||
|
|
||||||
|
GlStateManager._glBindFramebuffer(GlConst.GL_FRAMEBUFFER, dst.frameBufferId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void streak(PoseStack ms, float angle, int x, int y, int breadth, int length) {
|
||||||
|
streak(ms, angle, x, y, breadth, length, Theme.i(Theme.Key.STREAK));
|
||||||
|
}
|
||||||
|
// angle in degrees; 0° -> fading to the right
|
||||||
|
// x and y specify the middle point of the starting edge
|
||||||
|
// breadth is the total width of the streak
|
||||||
|
|
||||||
|
public static void streak(PoseStack ms, float angle, int x, int y, int breadth, int length, int color) {
|
||||||
|
int a1 = 0xa0 << 24;
|
||||||
|
int a2 = 0x80 << 24;
|
||||||
|
int a3 = 0x10 << 24;
|
||||||
|
int a4 = 0x00 << 24;
|
||||||
|
|
||||||
|
color &= 0x00FFFFFF;
|
||||||
|
int c1 = a1 | color;
|
||||||
|
int c2 = a2 | color;
|
||||||
|
int c3 = a3 | color;
|
||||||
|
int c4 = a4 | color;
|
||||||
|
|
||||||
|
ms.pushPose();
|
||||||
|
ms.translate(x, y, 0);
|
||||||
|
ms.mulPose(Vector3f.ZP.rotationDegrees(angle - 90));
|
||||||
|
|
||||||
|
streak(ms, breadth / 2, length, c1, c2, c3, c4);
|
||||||
|
|
||||||
|
ms.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void streak(PoseStack ms, float angle, int x, int y, int breadth, int length, Color c) {
|
||||||
|
Color color = c.copy().setImmutable();
|
||||||
|
int c1 = color.scaleAlpha(0.625f).getRGB();
|
||||||
|
int c2 = color.scaleAlpha(0.5f).getRGB();
|
||||||
|
int c3 = color.scaleAlpha(0.0625f).getRGB();
|
||||||
|
int c4 = color.scaleAlpha(0f).getRGB();
|
||||||
|
|
||||||
|
ms.pushPose();
|
||||||
|
ms.translate(x, y, 0);
|
||||||
|
ms.mulPose(Vector3f.ZP.rotationDegrees(angle - 90));
|
||||||
|
|
||||||
|
streak(ms, breadth / 2, length, c1, c2, c3, c4);
|
||||||
|
|
||||||
|
ms.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void streak(PoseStack ms, int width, int height, int c1, int c2, int c3, int c4) {
|
||||||
|
double split1 = .5;
|
||||||
|
double split2 = .75;
|
||||||
|
Matrix4f model = ms.last().pose();
|
||||||
|
ScreenUtils.drawGradientRect(model, 0, -width, 0, width, (int) (split1 * height), c1, c2);
|
||||||
|
ScreenUtils.drawGradientRect(model, 0, -width, (int) (split1 * height), width, (int) (split2 * height), c2, c3);
|
||||||
|
ScreenUtils.drawGradientRect(model, 0, -width, (int) (split2 * height), width, height, c3, c4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #angledGradient(MatrixStack, float, int, int, int, int, int, Color, Color)
|
||||||
|
*/
|
||||||
|
public static void angledGradient(@Nonnull PoseStack ms, float angle, int x, int y, int breadth, int length, Couple<Color> c) {
|
||||||
|
angledGradient(ms, angle, x, y, 0, breadth, length, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #angledGradient(MatrixStack, float, int, int, int, int, int, Color, Color)
|
||||||
|
*/
|
||||||
|
public static void angledGradient(@Nonnull PoseStack ms, float angle, int x, int y, int z, int breadth, int length, Couple<Color> c) {
|
||||||
|
angledGradient(ms, angle, x, y, z, breadth, length, c.getFirst(), c.getSecond());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #angledGradient(MatrixStack, float, int, int, int, int, int, Color, Color)
|
||||||
|
*/
|
||||||
|
public static void angledGradient(@Nonnull PoseStack ms, float angle, int x, int y, int breadth, int length, Color color1, Color color2) {
|
||||||
|
angledGradient(ms, angle, x, y, 0, breadth, length, color1, color2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* x and y specify the middle point of the starting edge
|
||||||
|
*
|
||||||
|
* @param angle the angle of the gradient in degrees; 0° means from left to right
|
||||||
|
* @param color1 the color at the starting edge
|
||||||
|
* @param color2 the color at the ending edge
|
||||||
|
* @param breadth the total width of the gradient
|
||||||
|
*/
|
||||||
|
public static void angledGradient(@Nonnull PoseStack ms, float angle, int x, int y, int z, int breadth, int length, Color color1, Color color2) {
|
||||||
|
ms.pushPose();
|
||||||
|
ms.translate(x, y, z);
|
||||||
|
ms.mulPose(Vector3f.ZP.rotationDegrees(angle - 90));
|
||||||
|
|
||||||
|
Matrix4f model = ms.last().pose();
|
||||||
|
int w = breadth / 2;
|
||||||
|
ScreenUtils.drawGradientRect(model, 0, -w, 0, w, length, color1.getRGB(), color2.getRGB());
|
||||||
|
|
||||||
|
ms.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void breadcrumbArrow(PoseStack matrixStack, int x, int y, int z, int width, int height, int indent, Couple<Color> colors) {breadcrumbArrow(matrixStack, x, y, z, width, height, indent, colors.getFirst(), colors.getSecond());}
|
||||||
|
|
||||||
|
// draws a wide chevron-style breadcrumb arrow pointing left
|
||||||
|
public static void breadcrumbArrow(PoseStack matrixStack, int x, int y, int z, int width, int height, int indent, Color startColor, Color endColor) {
|
||||||
|
matrixStack.pushPose();
|
||||||
|
matrixStack.translate(x - indent, y, z);
|
||||||
|
|
||||||
|
breadcrumbArrow(matrixStack, width, height, indent, startColor, endColor);
|
||||||
|
|
||||||
|
matrixStack.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void breadcrumbArrow(PoseStack ms, int width, int height, int indent, Color c1, Color c2) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 0,0 x1,y1 ********************* x4,y4 ***** x7,y7
|
||||||
|
* **** ****
|
||||||
|
* **** ****
|
||||||
|
* x0,y0 x2,y2 x5,y5
|
||||||
|
* **** ****
|
||||||
|
* **** ****
|
||||||
|
* x3,y3 ********************* x6,y6 ***** x8,y8
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
float x0 = 0, y0 = height / 2f;
|
||||||
|
float x1 = indent, y1 = 0;
|
||||||
|
float x2 = indent, y2 = height / 2f;
|
||||||
|
float x3 = indent, y3 = height;
|
||||||
|
float x4 = width, y4 = 0;
|
||||||
|
float x5 = width, y5 = height / 2f;
|
||||||
|
float x6 = width, y6 = height;
|
||||||
|
float x7 = indent + width, y7 = 0;
|
||||||
|
float x8 = indent + width, y8 = height;
|
||||||
|
|
||||||
|
indent = Math.abs(indent);
|
||||||
|
width = Math.abs(width);
|
||||||
|
Color fc1 = Color.mixColors(c1, c2, 0);
|
||||||
|
Color fc2 = Color.mixColors(c1, c2, (indent) / (width + 2f * indent));
|
||||||
|
Color fc3 = Color.mixColors(c1, c2, (indent + width) / (width + 2f * indent));
|
||||||
|
Color fc4 = Color.mixColors(c1, c2, 1);
|
||||||
|
|
||||||
|
RenderSystem.disableTexture();
|
||||||
|
RenderSystem.enableBlend();
|
||||||
|
RenderSystem.disableCull();
|
||||||
|
RenderSystem.defaultBlendFunc();
|
||||||
|
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
||||||
|
|
||||||
|
Tesselator tessellator = Tesselator.getInstance();
|
||||||
|
BufferBuilder bufferbuilder = tessellator.getBuilder();
|
||||||
|
Matrix4f model = ms.last().pose();
|
||||||
|
bufferbuilder.begin(VertexFormat.Mode.TRIANGLES, DefaultVertexFormat.POSITION_COLOR);
|
||||||
|
|
||||||
|
bufferbuilder.vertex(model, x0, y0, 0).color(fc1.getRed(), fc1.getGreen(), fc1.getBlue(), fc1.getAlpha()).endVertex();
|
||||||
|
bufferbuilder.vertex(model, x1, y1, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex();
|
||||||
|
bufferbuilder.vertex(model, x2, y2, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex();
|
||||||
|
|
||||||
|
bufferbuilder.vertex(model, x0, y0, 0).color(fc1.getRed(), fc1.getGreen(), fc1.getBlue(), fc1.getAlpha()).endVertex();
|
||||||
|
bufferbuilder.vertex(model, x2, y2, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex();
|
||||||
|
bufferbuilder.vertex(model, x3, y3, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex();
|
||||||
|
|
||||||
|
bufferbuilder.vertex(model, x3, y3, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex();
|
||||||
|
bufferbuilder.vertex(model, x1, y1, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex();
|
||||||
|
bufferbuilder.vertex(model, x4, y4, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex();
|
||||||
|
|
||||||
|
bufferbuilder.vertex(model, x3, y3, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex();
|
||||||
|
bufferbuilder.vertex(model, x4, y4, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex();
|
||||||
|
bufferbuilder.vertex(model, x6, y6, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex();
|
||||||
|
|
||||||
|
bufferbuilder.vertex(model, x5, y5, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex();
|
||||||
|
bufferbuilder.vertex(model, x4, y4, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex();
|
||||||
|
bufferbuilder.vertex(model, x7, y7, 0).color(fc4.getRed(), fc4.getGreen(), fc4.getBlue(), fc4.getAlpha()).endVertex();
|
||||||
|
|
||||||
|
bufferbuilder.vertex(model, x6, y6, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex();
|
||||||
|
bufferbuilder.vertex(model, x5, y5, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex();
|
||||||
|
bufferbuilder.vertex(model, x8, y8, 0).color(fc4.getRed(), fc4.getGreen(), fc4.getBlue(), fc4.getAlpha()).endVertex();
|
||||||
|
|
||||||
|
tessellator.end();
|
||||||
|
RenderSystem.enableCull();
|
||||||
|
RenderSystem.disableBlend();
|
||||||
|
RenderSystem.enableTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
//just like AbstractGui#drawTexture, but with a color at every vertex
|
||||||
|
public static void drawColoredTexture(PoseStack ms, Color c, int x, int y, int tex_left, int tex_top, int width, int height) {
|
||||||
|
drawColoredTexture(ms, c, x, y, 0, (float) tex_left, (float) tex_top, width, height, 256, 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void drawColoredTexture(PoseStack ms, Color c, int x, int y, int z, float tex_left, float tex_top, int width, int height, int sheet_width, int sheet_height) {
|
||||||
|
drawColoredTexture(ms, c, x, x + width, y, y + height, z, width, height, tex_left, tex_top, sheet_width, sheet_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void drawStretched(PoseStack ms, int left, int top, int w, int h, int z, AllGuiTextures tex) {
|
||||||
|
tex.bind();
|
||||||
|
drawTexturedQuad(ms.last()
|
||||||
|
.pose(), Color.WHITE, left, left + w, top, top + h, z, tex.startX / 256f, (tex.startX + tex.width) / 256f,
|
||||||
|
tex.startY / 256f, (tex.startY + tex.height) / 256f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void drawColoredTexture(PoseStack ms, Color c, int left, int right, int top, int bot, int z, int tex_width, int tex_height, float tex_left, float tex_top, int sheet_width, int sheet_height) {
|
||||||
|
drawTexturedQuad(ms.last().pose(), c, left, right, top, bot, z, (tex_left + 0.0F) / (float) sheet_width, (tex_left + (float) tex_width) / (float) sheet_width, (tex_top + 0.0F) / (float) sheet_height, (tex_top + (float) tex_height) / (float) sheet_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void drawTexturedQuad(Matrix4f m, Color c, int left, int right, int top, int bot, int z, float u1, float u2, float v1, float v2) {
|
||||||
|
Tesselator tesselator = Tesselator.getInstance();
|
||||||
|
BufferBuilder bufferbuilder = tesselator.getBuilder();
|
||||||
|
RenderSystem.enableBlend();
|
||||||
|
RenderSystem.defaultBlendFunc();
|
||||||
|
RenderSystem.setShader(GameRenderer::getPositionColorTexShader);
|
||||||
|
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX);
|
||||||
|
bufferbuilder.vertex(m, (float) left , (float) bot, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u1, v2).endVertex();
|
||||||
|
bufferbuilder.vertex(m, (float) right, (float) bot, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u2, v2).endVertex();
|
||||||
|
bufferbuilder.vertex(m, (float) right, (float) top, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u2, v1).endVertex();
|
||||||
|
bufferbuilder.vertex(m, (float) left , (float) top, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u1, v1).endVertex();
|
||||||
|
tesselator.end();
|
||||||
|
RenderSystem.disableBlend();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void flipForGuiRender(PoseStack poseStack) {
|
||||||
|
poseStack.mulPoseMatrix(Matrix4f.createScaleMatrix(1, -1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CustomRenderTarget extends RenderTarget {
|
||||||
|
|
||||||
|
public CustomRenderTarget(boolean useDepth) {
|
||||||
|
super(useDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CustomRenderTarget create(Window mainWindow) {
|
||||||
|
CustomRenderTarget framebuffer = new CustomRenderTarget(true);
|
||||||
|
framebuffer.resize(mainWindow.getWidth(), mainWindow.getHeight(), Minecraft.ON_OSX);
|
||||||
|
framebuffer.setClearColor(0, 0, 0, 0);
|
||||||
|
framebuffer.enableStencil();
|
||||||
|
return framebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renderWithAlpha(float alpha) {
|
||||||
|
Window window = Minecraft.getInstance().getWindow();
|
||||||
|
|
||||||
|
float vx = (float) window.getGuiScaledWidth();
|
||||||
|
float vy = (float) window.getGuiScaledHeight();
|
||||||
|
float tx = (float) viewWidth / (float) width;
|
||||||
|
float ty = (float) viewHeight / (float) height;
|
||||||
|
|
||||||
|
RenderSystem.enableTexture();
|
||||||
|
RenderSystem.enableDepthTest();
|
||||||
|
RenderSystem.setShader(() -> Minecraft.getInstance().gameRenderer.blitShader);
|
||||||
|
RenderSystem.getShader().setSampler("DiffuseSampler", colorTextureId);
|
||||||
|
|
||||||
|
bindRead();
|
||||||
|
|
||||||
|
Tesselator tessellator = Tesselator.getInstance();
|
||||||
|
BufferBuilder bufferbuilder = tessellator.getBuilder();
|
||||||
|
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX);
|
||||||
|
|
||||||
|
bufferbuilder.vertex(0, vy, 0).color(1, 1, 1, alpha).uv(0, 0).endVertex();
|
||||||
|
bufferbuilder.vertex(vx, vy, 0).color(1, 1, 1, alpha).uv(tx, 0).endVertex();
|
||||||
|
bufferbuilder.vertex(vx, 0, 0).color(1, 1, 1, alpha).uv(tx, ty).endVertex();
|
||||||
|
bufferbuilder.vertex(0, 0, 0).color(1, 1, 1, alpha).uv(0, ty).endVertex();
|
||||||
|
|
||||||
|
tessellator.end();
|
||||||
|
unbindRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.container;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.platform.InputConstants;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.AllGuiTextures;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.TickableGuiEventListener;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.widget.AbstractSimiWidget;
|
||||||
|
import net.minecraft.client.gui.components.AbstractWidget;
|
||||||
|
import net.minecraft.client.gui.components.Widget;
|
||||||
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||||
|
import net.minecraft.client.gui.narration.NarratableEntry;
|
||||||
|
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||||
|
import net.minecraft.client.gui.screens.inventory.ContainerScreen;
|
||||||
|
import net.minecraft.client.renderer.Rect2i;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
|
public abstract class AbstractSimiContainerScreen<T extends AbstractContainerMenu> extends AbstractContainerScreen<T> {
|
||||||
|
|
||||||
|
protected int windowXOffset, windowYOffset;
|
||||||
|
|
||||||
|
public AbstractSimiContainerScreen(T container, Inventory inv, Component title) {
|
||||||
|
super(container, inv, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method must be called before {@code super.init()}!
|
||||||
|
*/
|
||||||
|
protected void setWindowSize(int width, int height) {
|
||||||
|
imageWidth = width;
|
||||||
|
imageHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method must be called before {@code super.init()}!
|
||||||
|
*/
|
||||||
|
protected void setWindowOffset(int xOffset, int yOffset) {
|
||||||
|
windowXOffset = xOffset;
|
||||||
|
windowYOffset = yOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
leftPos += windowXOffset;
|
||||||
|
topPos += windowYOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void containerTick() {
|
||||||
|
for (GuiEventListener listener : children()) {
|
||||||
|
if (listener instanceof TickableGuiEventListener tickable) {
|
||||||
|
tickable.tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected <W extends GuiEventListener & Widget & NarratableEntry> void addRenderableWidgets(W... widgets) {
|
||||||
|
for (W widget : widgets) {
|
||||||
|
addRenderableWidget(widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <W extends GuiEventListener & Widget & NarratableEntry> void addRenderableWidgets(Collection<W> widgets) {
|
||||||
|
for (W widget : widgets) {
|
||||||
|
addRenderableWidget(widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void removeWidgets(GuiEventListener... widgets) {
|
||||||
|
for (GuiEventListener widget : widgets) {
|
||||||
|
removeWidget(widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void removeWidgets(Collection<? extends GuiEventListener> widgets) {
|
||||||
|
for (GuiEventListener widget : widgets) {
|
||||||
|
removeWidget(widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
partialTicks = minecraft.getFrameTime();
|
||||||
|
|
||||||
|
renderBackground(matrixStack);
|
||||||
|
|
||||||
|
super.render(matrixStack, mouseX, mouseY, partialTicks);
|
||||||
|
|
||||||
|
renderForeground(matrixStack, mouseX, mouseY, partialTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderLabels(PoseStack poseStack, int mouseX, int mouseY) {
|
||||||
|
// no-op to prevent screen- and inventory-title from being rendered at incorrect
|
||||||
|
// location
|
||||||
|
// could also set this.titleX/Y and this.playerInventoryTitleX/Y to the proper
|
||||||
|
// values instead
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderForeground(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
renderTooltip(ms, mouseX, mouseY);
|
||||||
|
for (Widget widget : renderables) {
|
||||||
|
if (widget instanceof AbstractSimiWidget simiWidget && simiWidget.isHoveredOrFocused()) {
|
||||||
|
List<Component> tooltip = simiWidget.getToolTip();
|
||||||
|
if (tooltip.isEmpty())
|
||||||
|
continue;
|
||||||
|
int ttx = simiWidget.lockedTooltipX == -1 ? mouseX : simiWidget.lockedTooltipX + simiWidget.x;
|
||||||
|
int tty = simiWidget.lockedTooltipY == -1 ? mouseY : simiWidget.lockedTooltipY + simiWidget.y;
|
||||||
|
renderComponentTooltip(ms, tooltip, ttx, tty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLeftOfCentered(int textureWidth) {
|
||||||
|
return leftPos - windowXOffset + (imageWidth - textureWidth) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renderPlayerInventory(PoseStack ms, int x, int y) {
|
||||||
|
AllGuiTextures.PLAYER_INVENTORY.render(ms, x, y, this);
|
||||||
|
font.draw(ms, playerInventoryTitle, x + 8, y + 6, 0x404040);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) {
|
||||||
|
InputConstants.Key mouseKey = InputConstants.getKey(pKeyCode, pScanCode);
|
||||||
|
if (getFocused() != null && this.minecraft.options.keyInventory.isActiveAndMatches(mouseKey))
|
||||||
|
return false;
|
||||||
|
return super.keyPressed(pKeyCode, pScanCode, pModifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GuiEventListener getFocused() {
|
||||||
|
GuiEventListener focused = super.getFocused();
|
||||||
|
if (focused instanceof AbstractWidget && !((AbstractWidget) focused).isFocused())
|
||||||
|
focused = null;
|
||||||
|
setFocused(focused);
|
||||||
|
return focused;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for moving JEI out of the way of extra things like block renders.
|
||||||
|
*
|
||||||
|
* @return the space that the GUI takes up outside the normal rectangle defined
|
||||||
|
* by {@link ContainerScreen}.
|
||||||
|
*/
|
||||||
|
public List<Rect2i> getExtraAreas() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
protected void debugWindowArea(PoseStack matrixStack) {
|
||||||
|
fill(matrixStack, leftPos + imageWidth, topPos + imageHeight, leftPos, topPos, 0xD3D3D3D3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
protected void debugExtraAreas(PoseStack matrixStack) {
|
||||||
|
for (Rect2i area : getExtraAreas()) {
|
||||||
|
fill(matrixStack, area.getX() + area.getWidth(), area.getY() + area.getHeight(), area.getX(), area.getY(),
|
||||||
|
0xD3D3D3D3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.container;
|
||||||
|
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.networking.SimplePacketBase;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraftforge.network.NetworkEvent.Context;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class ClearContainerPacket extends SimplePacketBase {
|
||||||
|
|
||||||
|
public ClearContainerPacket() {}
|
||||||
|
|
||||||
|
public ClearContainerPacket(FriendlyByteBuf buffer) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(FriendlyByteBuf buffer) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(Supplier<Context> context) {
|
||||||
|
context.get()
|
||||||
|
.enqueueWork(() -> {
|
||||||
|
ServerPlayer player = context.get()
|
||||||
|
.getSender();
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
|
if (!(player.containerMenu instanceof IClearableContainer))
|
||||||
|
return;
|
||||||
|
((IClearableContainer) player.containerMenu).clearContents();
|
||||||
|
});
|
||||||
|
context.get()
|
||||||
|
.setPacketHandled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.container;
|
||||||
|
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.IInteractionChecker;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||||
|
import net.minecraft.world.inventory.MenuType;
|
||||||
|
import net.minecraft.world.inventory.Slot;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public abstract class ContainerBase<T> extends AbstractContainerMenu {
|
||||||
|
|
||||||
|
public Player player;
|
||||||
|
public Inventory playerInventory;
|
||||||
|
public T contentHolder;
|
||||||
|
|
||||||
|
protected ContainerBase(MenuType<?> type, int id, Inventory inv, FriendlyByteBuf extraData) {
|
||||||
|
super(type, id);
|
||||||
|
init(inv, createOnClient(extraData));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ContainerBase(MenuType<?> type, int id, Inventory inv, T contentHolder) {
|
||||||
|
super(type, id);
|
||||||
|
init(inv, contentHolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void init(Inventory inv, T contentHolderIn) {
|
||||||
|
player = inv.player;
|
||||||
|
playerInventory = inv;
|
||||||
|
contentHolder = contentHolderIn;
|
||||||
|
initAndReadInventory(contentHolder);
|
||||||
|
addSlots();
|
||||||
|
broadcastChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
protected abstract T createOnClient(FriendlyByteBuf extraData);
|
||||||
|
|
||||||
|
protected abstract void initAndReadInventory(T contentHolder);
|
||||||
|
|
||||||
|
protected abstract void addSlots();
|
||||||
|
|
||||||
|
protected abstract void saveData(T contentHolder);
|
||||||
|
|
||||||
|
protected void addPlayerSlots(int x, int y) {
|
||||||
|
for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot)
|
||||||
|
this.addSlot(new Slot(playerInventory, hotbarSlot, x + hotbarSlot * 18, y + 58));
|
||||||
|
for (int row = 0; row < 3; ++row)
|
||||||
|
for (int col = 0; col < 9; ++col)
|
||||||
|
this.addSlot(new Slot(playerInventory, col + row * 9 + 9, x + col * 18, y + row * 18));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removed(Player playerIn) {
|
||||||
|
super.removed(playerIn);
|
||||||
|
saveData(contentHolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stillValid(Player player) {
|
||||||
|
if (contentHolder == null)
|
||||||
|
return false;
|
||||||
|
if (contentHolder instanceof IInteractionChecker)
|
||||||
|
return ((IInteractionChecker) contentHolder).canPlayerUse(player);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.container;
|
||||||
|
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.inventory.ClickType;
|
||||||
|
import net.minecraft.world.inventory.MenuType;
|
||||||
|
import net.minecraft.world.inventory.Slot;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraftforge.items.ItemHandlerHelper;
|
||||||
|
import net.minecraftforge.items.ItemStackHandler;
|
||||||
|
|
||||||
|
public abstract class GhostItemContainer<T> extends ContainerBase<T> implements IClearableContainer {
|
||||||
|
|
||||||
|
public ItemStackHandler ghostInventory;
|
||||||
|
|
||||||
|
protected GhostItemContainer(MenuType<?> type, int id, Inventory inv, FriendlyByteBuf extraData) {
|
||||||
|
super(type, id, inv, extraData);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GhostItemContainer(MenuType<?> type, int id, Inventory inv, T contentHolder) {
|
||||||
|
super(type, id, inv, contentHolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ItemStackHandler createGhostInventory();
|
||||||
|
|
||||||
|
protected abstract boolean allowRepeats();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initAndReadInventory(T contentHolder) {
|
||||||
|
ghostInventory = createGhostInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearContents() {
|
||||||
|
for (int i = 0; i < ghostInventory.getSlots(); i++)
|
||||||
|
ghostInventory.setStackInSlot(i, ItemStack.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canTakeItemForPickAll(ItemStack stack, Slot slotIn) {
|
||||||
|
return slotIn.container == playerInventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canDragTo(Slot slotIn) {
|
||||||
|
if (allowRepeats())
|
||||||
|
return true;
|
||||||
|
return slotIn.container == playerInventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) {
|
||||||
|
if (slotId < 36) {
|
||||||
|
super.clicked(slotId, dragType, clickTypeIn, player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (clickTypeIn == ClickType.THROW)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ItemStack held = getCarried();
|
||||||
|
int slot = slotId - 36;
|
||||||
|
if (clickTypeIn == ClickType.CLONE) {
|
||||||
|
if (player.isCreative() && held.isEmpty()) {
|
||||||
|
ItemStack stackInSlot = ghostInventory.getStackInSlot(slot)
|
||||||
|
.copy();
|
||||||
|
stackInSlot.setCount(stackInSlot.getMaxStackSize());
|
||||||
|
setCarried(stackInSlot);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack insert;
|
||||||
|
if (held.isEmpty()) {
|
||||||
|
insert = ItemStack.EMPTY;
|
||||||
|
} else {
|
||||||
|
insert = held.copy();
|
||||||
|
insert.setCount(1);
|
||||||
|
}
|
||||||
|
ghostInventory.setStackInSlot(slot, insert);
|
||||||
|
getSlot(slotId).setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack quickMoveStack(Player playerIn, int index) {
|
||||||
|
if (index < 36) {
|
||||||
|
ItemStack stackToInsert = playerInventory.getItem(index);
|
||||||
|
for (int i = 0; i < ghostInventory.getSlots(); i++) {
|
||||||
|
ItemStack stack = ghostInventory.getStackInSlot(i);
|
||||||
|
if (!allowRepeats() && ItemHandlerHelper.canItemStacksStack(stack, stackToInsert))
|
||||||
|
break;
|
||||||
|
if (stack.isEmpty()) {
|
||||||
|
ItemStack copy = stackToInsert.copy();
|
||||||
|
copy.setCount(1);
|
||||||
|
ghostInventory.insertItem(i, copy, false);
|
||||||
|
getSlot(i + 36).setChanged();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ghostInventory.extractItem(index - 36, 1, false);
|
||||||
|
getSlot(index).setChanged();
|
||||||
|
}
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.container;
|
||||||
|
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.networking.SimplePacketBase;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraftforge.network.NetworkEvent.Context;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class GhostItemSubmitPacket extends SimplePacketBase {
|
||||||
|
|
||||||
|
private final ItemStack item;
|
||||||
|
private final int slot;
|
||||||
|
|
||||||
|
public GhostItemSubmitPacket(ItemStack item, int slot) {
|
||||||
|
this.item = item;
|
||||||
|
this.slot = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GhostItemSubmitPacket(FriendlyByteBuf buffer) {
|
||||||
|
item = buffer.readItem();
|
||||||
|
slot = buffer.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(FriendlyByteBuf buffer) {
|
||||||
|
buffer.writeItem(item);
|
||||||
|
buffer.writeInt(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(Supplier<Context> context) {
|
||||||
|
context.get()
|
||||||
|
.enqueueWork(() -> {
|
||||||
|
ServerPlayer player = context.get()
|
||||||
|
.getSender();
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (player.containerMenu instanceof GhostItemContainer) {
|
||||||
|
GhostItemContainer<?> c = (GhostItemContainer<?>) player.containerMenu;
|
||||||
|
c.ghostInventory.setStackInSlot(slot, item);
|
||||||
|
c.getSlot(36 + slot).setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
context.get()
|
||||||
|
.setPacketHandled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.container;
|
||||||
|
|
||||||
|
//import nl.requios.effortlessbuilding.create.foundation.networking.AllPackets;
|
||||||
|
|
||||||
|
public interface IClearableContainer {
|
||||||
|
|
||||||
|
default void sendClearPacket() {
|
||||||
|
// AllPackets.channel.sendToServer(new ClearContainerPacket());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated //warning: does not work
|
||||||
|
public void clearContents();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.element;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.*;
|
||||||
|
import com.mojang.math.Matrix4f;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Color;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Couple;
|
||||||
|
import net.minecraft.client.renderer.GameRenderer;
|
||||||
|
|
||||||
|
public class BoxElement extends RenderElement {
|
||||||
|
|
||||||
|
protected Color background = new Color(0xff000000, true);
|
||||||
|
protected Color borderTop = new Color(0x40ffeedd, true);
|
||||||
|
protected Color borderBot = new Color(0x20ffeedd, true);
|
||||||
|
protected int borderOffset = 2;
|
||||||
|
|
||||||
|
public <T extends BoxElement> T withBackground(Color color) {
|
||||||
|
this.background = color;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BoxElement> T withBackground(int color) {
|
||||||
|
return withBackground(new Color(color, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BoxElement> T flatBorder(Color color) {
|
||||||
|
this.borderTop = color;
|
||||||
|
this.borderBot = color;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BoxElement> T flatBorder(int color) {
|
||||||
|
return flatBorder(new Color(color, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BoxElement> T gradientBorder(Couple<Color> colors) {
|
||||||
|
this.borderTop = colors.getFirst();
|
||||||
|
this.borderBot = colors.getSecond();
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BoxElement> T gradientBorder(Color top, Color bot) {
|
||||||
|
this.borderTop = top;
|
||||||
|
this.borderBot = bot;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BoxElement> T gradientBorder(int top, int bot) {
|
||||||
|
return gradientBorder(new Color(top, true), new Color(bot, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BoxElement> T withBorderOffset(int offset) {
|
||||||
|
this.borderOffset = offset;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PoseStack ms) {
|
||||||
|
renderBox(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
//total box width = 1 * 2 (outer border) + 1 * 2 (inner color border) + 2 * borderOffset + width
|
||||||
|
//defaults to 2 + 2 + 4 + 16 = 24px
|
||||||
|
//batch everything together to save a bunch of gl calls over ScreenUtils
|
||||||
|
protected void renderBox(PoseStack ms) {
|
||||||
|
/*
|
||||||
|
* _____________
|
||||||
|
* _|_____________|_
|
||||||
|
* | | ___________ | |
|
||||||
|
* | | | | | | |
|
||||||
|
* | | | | | | |
|
||||||
|
* | | |--* | | | |
|
||||||
|
* | | | h | | |
|
||||||
|
* | | | --w-+ | | |
|
||||||
|
* | | | | | |
|
||||||
|
* | | |_________| | |
|
||||||
|
* |_|_____________|_|
|
||||||
|
* |_____________|
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
RenderSystem.disableTexture();
|
||||||
|
RenderSystem.enableBlend();
|
||||||
|
RenderSystem.defaultBlendFunc();
|
||||||
|
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
||||||
|
|
||||||
|
Matrix4f model = ms.last().pose();
|
||||||
|
int f = borderOffset;
|
||||||
|
Color c1 = background.copy().scaleAlpha(alpha);
|
||||||
|
Color c2 = borderTop.copy().scaleAlpha(alpha);
|
||||||
|
Color c3 = borderBot.copy().scaleAlpha(alpha);
|
||||||
|
Tesselator tessellator = Tesselator.getInstance();
|
||||||
|
BufferBuilder b = tessellator.getBuilder();
|
||||||
|
|
||||||
|
b.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||||
|
//outer top
|
||||||
|
b.vertex(model, x - f - 1 , y - f - 2 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x - f - 1 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 1 + width, y - f - 2 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
//outer left
|
||||||
|
b.vertex(model, x - f - 2 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x - f - 2 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x - f - 1 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
//outer bottom
|
||||||
|
b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x - f - 1 , y + f + 2 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 1 + width, y + f + 2 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
//outer right
|
||||||
|
b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 2 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 2 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
//inner background - also render behind the inner edges
|
||||||
|
b.vertex(model, x - f - 1 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
|
||||||
|
tessellator.end();
|
||||||
|
b.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||||
|
//inner top - includes corners
|
||||||
|
b.vertex(model, x - f - 1 , y - f - 1 , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x - f - 1 , y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 1 + width, y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
|
||||||
|
//inner left - excludes corners
|
||||||
|
b.vertex(model, x - f - 1 , y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x - f - 1 , y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x - f , y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x - f , y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
|
||||||
|
//inner bottom - includes corners
|
||||||
|
b.vertex(model, x - f - 1 , y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 1 + width, y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
|
||||||
|
//inner right - excludes corners
|
||||||
|
b.vertex(model, x + f + width, y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + width, y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 1 + width, y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
|
||||||
|
b.vertex(model, x + f + 1 + width, y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
|
||||||
|
|
||||||
|
tessellator.end();
|
||||||
|
|
||||||
|
RenderSystem.disableBlend();
|
||||||
|
RenderSystem.enableTexture();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.element;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
public class CombinedStencilElement extends StencilElement {
|
||||||
|
|
||||||
|
private StencilElement element1;
|
||||||
|
private StencilElement element2;
|
||||||
|
private ElementMode mode;
|
||||||
|
|
||||||
|
private CombinedStencilElement() {}
|
||||||
|
|
||||||
|
public static CombinedStencilElement of(@Nonnull StencilElement element1, @Nonnull StencilElement element2) {
|
||||||
|
return of(element1, element2, ElementMode.FIRST);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CombinedStencilElement of(@Nonnull StencilElement element1, @Nonnull StencilElement element2, ElementMode mode) {
|
||||||
|
CombinedStencilElement e = new CombinedStencilElement();
|
||||||
|
e.element1 = element1;
|
||||||
|
e.element2 = element2;
|
||||||
|
e.mode = mode;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends CombinedStencilElement> T withFirst(StencilElement element) {
|
||||||
|
this.element1 = element;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends CombinedStencilElement> T withSecond(StencilElement element) {
|
||||||
|
this.element2 = element;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends CombinedStencilElement> T withMode(ElementMode mode) {
|
||||||
|
this.mode = mode;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderStencil(PoseStack ms) {
|
||||||
|
ms.pushPose();
|
||||||
|
element1.transform(ms);
|
||||||
|
element1.withBounds(width, height);
|
||||||
|
element1.renderStencil(ms);
|
||||||
|
ms.popPose();
|
||||||
|
ms.pushPose();
|
||||||
|
element2.transform(ms);
|
||||||
|
element2.withBounds(width, height);
|
||||||
|
element2.renderStencil(ms);
|
||||||
|
ms.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderElement(PoseStack ms) {
|
||||||
|
if (mode.rendersFirst())
|
||||||
|
element1.<StencilElement>withBounds(width, height).renderElement(ms);
|
||||||
|
|
||||||
|
if (mode.rendersSecond())
|
||||||
|
element2.<StencilElement>withBounds(width, height).renderElement(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ElementMode {
|
||||||
|
FIRST, SECOND, BOTH;
|
||||||
|
|
||||||
|
boolean rendersFirst() {
|
||||||
|
return this == FIRST || this == BOTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean rendersSecond() {
|
||||||
|
return this == SECOND || this == BOTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.element;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.UIRenderHelper;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Color;
|
||||||
|
|
||||||
|
public class DelegatedStencilElement extends StencilElement {
|
||||||
|
|
||||||
|
protected static final ElementRenderer EMPTY_RENDERER = (ms, width, height, alpha) -> {};
|
||||||
|
protected static final ElementRenderer DEFAULT_ELEMENT = (ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, -3, 5, height+4, width+6, new Color(0xff_10dd10).scaleAlpha(alpha), new Color(0xff_1010dd).scaleAlpha(alpha));
|
||||||
|
|
||||||
|
protected ElementRenderer stencil;
|
||||||
|
protected ElementRenderer element;
|
||||||
|
|
||||||
|
public DelegatedStencilElement() {
|
||||||
|
stencil = EMPTY_RENDERER;
|
||||||
|
element = DEFAULT_ELEMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DelegatedStencilElement(ElementRenderer stencil, ElementRenderer element) {
|
||||||
|
this.stencil = stencil;
|
||||||
|
this.element = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends DelegatedStencilElement> T withStencilRenderer(ElementRenderer renderer) {
|
||||||
|
stencil = renderer;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends DelegatedStencilElement> T withElementRenderer(ElementRenderer renderer) {
|
||||||
|
element = renderer;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderStencil(PoseStack ms) {
|
||||||
|
stencil.render(ms, width, height, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderElement(PoseStack ms) {
|
||||||
|
element.render(ms, width, height, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ElementRenderer {
|
||||||
|
void render(PoseStack ms, int width, int height, float alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,297 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.element;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.core.PartialModel;
|
||||||
|
import com.jozufozu.flywheel.core.model.ModelUtil;
|
||||||
|
import com.mojang.blaze3d.platform.GlStateManager.DestFactor;
|
||||||
|
import com.mojang.blaze3d.platform.GlStateManager.SourceFactor;
|
||||||
|
import com.mojang.blaze3d.platform.Lighting;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.math.Vector3f;
|
||||||
|
//import nl.requios.effortlessbuilding.create.foundation.fluid.FluidRenderer;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.ILightingSettings;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.UIRenderHelper;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Color;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.VecHelper;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.Sheets;
|
||||||
|
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
|
||||||
|
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||||
|
import net.minecraft.client.renderer.entity.ItemRenderer;
|
||||||
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
|
import net.minecraft.world.inventory.InventoryMenu;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.level.ItemLike;
|
||||||
|
import net.minecraft.world.level.block.BaseFireBlock;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.LiquidBlock;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.material.Fluid;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraftforge.client.RenderTypeHelper;
|
||||||
|
import net.minecraftforge.fluids.FluidStack;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public class GuiGameElement {
|
||||||
|
|
||||||
|
public static GuiRenderBuilder of(ItemStack stack) {
|
||||||
|
return new GuiItemRenderBuilder(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GuiRenderBuilder of(ItemLike itemProvider) {
|
||||||
|
return new GuiItemRenderBuilder(itemProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GuiRenderBuilder of(BlockState state) {
|
||||||
|
return new GuiBlockStateRenderBuilder(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GuiRenderBuilder of(PartialModel partial) {
|
||||||
|
return new GuiBlockPartialRenderBuilder(partial);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GuiRenderBuilder of(Fluid fluid) {
|
||||||
|
return new GuiBlockStateRenderBuilder(fluid.defaultFluidState()
|
||||||
|
.createLegacyBlock()
|
||||||
|
.setValue(LiquidBlock.LEVEL, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class GuiRenderBuilder extends RenderElement {
|
||||||
|
protected double xLocal, yLocal, zLocal;
|
||||||
|
protected double xRot, yRot, zRot;
|
||||||
|
protected double scale = 1;
|
||||||
|
protected int color = 0xFFFFFF;
|
||||||
|
protected Vec3 rotationOffset = Vec3.ZERO;
|
||||||
|
protected ILightingSettings customLighting = null;
|
||||||
|
|
||||||
|
public GuiRenderBuilder atLocal(double x, double y, double z) {
|
||||||
|
this.xLocal = x;
|
||||||
|
this.yLocal = y;
|
||||||
|
this.zLocal = z;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GuiRenderBuilder rotate(double xRot, double yRot, double zRot) {
|
||||||
|
this.xRot = xRot;
|
||||||
|
this.yRot = yRot;
|
||||||
|
this.zRot = zRot;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GuiRenderBuilder rotateBlock(double xRot, double yRot, double zRot) {
|
||||||
|
return this.rotate(xRot, yRot, zRot)
|
||||||
|
.withRotationOffset(VecHelper.getCenterOf(BlockPos.ZERO));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GuiRenderBuilder scale(double scale) {
|
||||||
|
this.scale = scale;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GuiRenderBuilder color(int color) {
|
||||||
|
this.color = color;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GuiRenderBuilder withRotationOffset(Vec3 offset) {
|
||||||
|
this.rotationOffset = offset;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GuiRenderBuilder lighting(ILightingSettings lighting) {
|
||||||
|
customLighting = lighting;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void prepareMatrix(PoseStack matrixStack) {
|
||||||
|
matrixStack.pushPose();
|
||||||
|
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
RenderSystem.enableDepthTest();
|
||||||
|
RenderSystem.enableBlend();
|
||||||
|
RenderSystem.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||||
|
prepareLighting(matrixStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void transformMatrix(PoseStack matrixStack) {
|
||||||
|
matrixStack.translate(x, y, z);
|
||||||
|
matrixStack.scale((float) scale, (float) scale, (float) scale);
|
||||||
|
matrixStack.translate(xLocal, yLocal, zLocal);
|
||||||
|
UIRenderHelper.flipForGuiRender(matrixStack);
|
||||||
|
matrixStack.translate(rotationOffset.x, rotationOffset.y, rotationOffset.z);
|
||||||
|
matrixStack.mulPose(Vector3f.ZP.rotationDegrees((float) zRot));
|
||||||
|
matrixStack.mulPose(Vector3f.XP.rotationDegrees((float) xRot));
|
||||||
|
matrixStack.mulPose(Vector3f.YP.rotationDegrees((float) yRot));
|
||||||
|
matrixStack.translate(-rotationOffset.x, -rotationOffset.y, -rotationOffset.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void cleanUpMatrix(PoseStack matrixStack) {
|
||||||
|
matrixStack.popPose();
|
||||||
|
cleanUpLighting(matrixStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void prepareLighting(PoseStack matrixStack) {
|
||||||
|
if (customLighting != null) {
|
||||||
|
customLighting.applyLighting();
|
||||||
|
} else {
|
||||||
|
Lighting.setupFor3DItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void cleanUpLighting(PoseStack matrixStack) {
|
||||||
|
if (customLighting != null) {
|
||||||
|
Lighting.setupFor3DItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class GuiBlockModelRenderBuilder extends GuiRenderBuilder {
|
||||||
|
|
||||||
|
protected BakedModel blockModel;
|
||||||
|
protected BlockState blockState;
|
||||||
|
|
||||||
|
public GuiBlockModelRenderBuilder(BakedModel blockmodel, @Nullable BlockState blockState) {
|
||||||
|
this.blockState = blockState == null ? Blocks.AIR.defaultBlockState() : blockState;
|
||||||
|
this.blockModel = blockmodel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PoseStack matrixStack) {
|
||||||
|
prepareMatrix(matrixStack);
|
||||||
|
|
||||||
|
Minecraft mc = Minecraft.getInstance();
|
||||||
|
BlockRenderDispatcher blockRenderer = mc.getBlockRenderer();
|
||||||
|
MultiBufferSource.BufferSource buffer = mc.renderBuffers()
|
||||||
|
.bufferSource();
|
||||||
|
|
||||||
|
transformMatrix(matrixStack);
|
||||||
|
|
||||||
|
RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS);
|
||||||
|
renderModel(blockRenderer, buffer, matrixStack);
|
||||||
|
|
||||||
|
cleanUpMatrix(matrixStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renderModel(BlockRenderDispatcher blockRenderer, MultiBufferSource.BufferSource buffer,
|
||||||
|
PoseStack ms) {
|
||||||
|
if (blockState.getBlock() == Blocks.AIR) {
|
||||||
|
RenderType renderType = Sheets.translucentCullBlockSheet();
|
||||||
|
blockRenderer.getModelRenderer()
|
||||||
|
.renderModel(ms.last(), buffer.getBuffer(renderType), blockState, blockModel, 1, 1, 1,
|
||||||
|
LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, ModelUtil.VIRTUAL_DATA, null);
|
||||||
|
} else {
|
||||||
|
int color = Minecraft.getInstance()
|
||||||
|
.getBlockColors()
|
||||||
|
.getColor(blockState, null, null, 0);
|
||||||
|
Color rgb = new Color(color == -1 ? this.color : color);
|
||||||
|
|
||||||
|
for (RenderType chunkType : blockModel.getRenderTypes(blockState, RandomSource.create(42L), ModelUtil.VIRTUAL_DATA)) {
|
||||||
|
RenderType renderType = RenderTypeHelper.getEntityRenderType(chunkType, true);
|
||||||
|
blockRenderer.getModelRenderer()
|
||||||
|
.renderModel(ms.last(), buffer.getBuffer(renderType), blockState, blockModel,
|
||||||
|
rgb.getRedAsFloat(), rgb.getGreenAsFloat(), rgb.getBlueAsFloat(),
|
||||||
|
LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, ModelUtil.VIRTUAL_DATA, chunkType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.endBatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GuiBlockStateRenderBuilder extends GuiBlockModelRenderBuilder {
|
||||||
|
|
||||||
|
public GuiBlockStateRenderBuilder(BlockState blockstate) {
|
||||||
|
super(Minecraft.getInstance()
|
||||||
|
.getBlockRenderer()
|
||||||
|
.getBlockModel(blockstate), blockstate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderModel(BlockRenderDispatcher blockRenderer, MultiBufferSource.BufferSource buffer,
|
||||||
|
PoseStack ms) {
|
||||||
|
if (blockState.getBlock() instanceof BaseFireBlock) {
|
||||||
|
Lighting.setupForFlatItems();
|
||||||
|
super.renderModel(blockRenderer, buffer, ms);
|
||||||
|
Lighting.setupFor3DItems();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.renderModel(blockRenderer, buffer, ms);
|
||||||
|
|
||||||
|
if (blockState.getFluidState()
|
||||||
|
.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// FluidRenderer.renderFluidBox(new FluidStack(blockState.getFluidState()
|
||||||
|
// .getType(), 1000), 0, 0, 0, 1, 1, 1, buffer, ms, LightTexture.FULL_BRIGHT, false);
|
||||||
|
// buffer.endBatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GuiBlockPartialRenderBuilder extends GuiBlockModelRenderBuilder {
|
||||||
|
|
||||||
|
public GuiBlockPartialRenderBuilder(PartialModel partial) {
|
||||||
|
super(partial.get(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GuiItemRenderBuilder extends GuiRenderBuilder {
|
||||||
|
|
||||||
|
private final ItemStack stack;
|
||||||
|
|
||||||
|
public GuiItemRenderBuilder(ItemStack stack) {
|
||||||
|
this.stack = stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GuiItemRenderBuilder(ItemLike provider) {
|
||||||
|
this(new ItemStack(provider));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PoseStack matrixStack) {
|
||||||
|
prepareMatrix(matrixStack);
|
||||||
|
transformMatrix(matrixStack);
|
||||||
|
renderItemIntoGUI(matrixStack, stack, customLighting == null);
|
||||||
|
cleanUpMatrix(matrixStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void renderItemIntoGUI(PoseStack matrixStack, ItemStack stack, boolean useDefaultLighting) {
|
||||||
|
ItemRenderer renderer = Minecraft.getInstance().getItemRenderer();
|
||||||
|
BakedModel bakedModel = renderer.getModel(stack, null, null, 0);
|
||||||
|
|
||||||
|
renderer.textureManager.getTexture(InventoryMenu.BLOCK_ATLAS).setFilter(false, false);
|
||||||
|
RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS);
|
||||||
|
RenderSystem.enableBlend();
|
||||||
|
RenderSystem.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||||
|
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
matrixStack.pushPose();
|
||||||
|
matrixStack.translate(0, 0, 100.0F + renderer.blitOffset);
|
||||||
|
matrixStack.translate(8.0F, -8.0F, 0.0F);
|
||||||
|
matrixStack.scale(16.0F, 16.0F, 16.0F);
|
||||||
|
MultiBufferSource.BufferSource buffer = Minecraft.getInstance().renderBuffers().bufferSource();
|
||||||
|
boolean flatLighting = !bakedModel.usesBlockLight();
|
||||||
|
if (useDefaultLighting && flatLighting) {
|
||||||
|
Lighting.setupForFlatItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.render(stack, ItemTransforms.TransformType.GUI, false, matrixStack, buffer, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, bakedModel);
|
||||||
|
buffer.endBatch();
|
||||||
|
RenderSystem.enableDepthTest();
|
||||||
|
if (useDefaultLighting && flatLighting) {
|
||||||
|
Lighting.setupFor3DItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
matrixStack.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.element;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
|
||||||
|
public abstract class RenderElement implements ScreenElement {
|
||||||
|
|
||||||
|
public static final RenderElement EMPTY = new RenderElement() {
|
||||||
|
@Override
|
||||||
|
public void render(PoseStack ms) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static RenderElement of(ScreenElement renderable) {
|
||||||
|
return new SimpleRenderElement(renderable);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int width = 16, height = 16;
|
||||||
|
protected float x = 0, y = 0, z = 0;
|
||||||
|
protected float alpha = 1f;
|
||||||
|
|
||||||
|
public <T extends RenderElement> T at(float x, float y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends RenderElement> T at(float x, float y, float z) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends RenderElement> T withBounds(int width, int height) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends RenderElement> T withAlpha(float alpha) {
|
||||||
|
this.alpha = alpha;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void render(PoseStack ms);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PoseStack ms, int x, int y) {
|
||||||
|
this.at(x, y).render(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SimpleRenderElement extends RenderElement {
|
||||||
|
|
||||||
|
private ScreenElement renderable;
|
||||||
|
|
||||||
|
public SimpleRenderElement(ScreenElement renderable) {
|
||||||
|
this.renderable = renderable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PoseStack ms) {
|
||||||
|
renderable.render(ms, (int) x, (int) y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.element;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public interface ScreenElement {
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
void render(PoseStack ms, int x, int y);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.element;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
public abstract class StencilElement extends RenderElement {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PoseStack ms) {
|
||||||
|
ms.pushPose();
|
||||||
|
transform(ms);
|
||||||
|
prepareStencil(ms);
|
||||||
|
renderStencil(ms);
|
||||||
|
prepareElement(ms);
|
||||||
|
renderElement(ms);
|
||||||
|
cleanUp(ms);
|
||||||
|
ms.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void renderStencil(PoseStack ms);
|
||||||
|
|
||||||
|
protected abstract void renderElement(PoseStack ms);
|
||||||
|
|
||||||
|
protected void transform(PoseStack ms) {
|
||||||
|
ms.translate(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void prepareStencil(PoseStack ms) {
|
||||||
|
GL11.glDisable(GL11.GL_STENCIL_TEST);
|
||||||
|
RenderSystem.stencilMask(~0);
|
||||||
|
RenderSystem.clear(GL11.GL_STENCIL_BUFFER_BIT, Minecraft.ON_OSX);
|
||||||
|
GL11.glEnable(GL11.GL_STENCIL_TEST);
|
||||||
|
RenderSystem.stencilOp(GL11.GL_REPLACE, GL11.GL_KEEP, GL11.GL_KEEP);
|
||||||
|
RenderSystem.stencilMask(0xFF);
|
||||||
|
RenderSystem.stencilFunc(GL11.GL_NEVER, 1, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void prepareElement(PoseStack ms) {
|
||||||
|
GL11.glEnable(GL11.GL_STENCIL_TEST);
|
||||||
|
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
|
||||||
|
RenderSystem.stencilFunc(GL11.GL_EQUAL, 1, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void cleanUp(PoseStack ms) {
|
||||||
|
GL11.glDisable(GL11.GL_STENCIL_TEST);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.element;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Components;
|
||||||
|
import net.minecraft.client.gui.Font;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
|
||||||
|
public class TextStencilElement extends DelegatedStencilElement {
|
||||||
|
|
||||||
|
protected Font font;
|
||||||
|
protected MutableComponent component;
|
||||||
|
protected boolean centerVertically = false;
|
||||||
|
protected boolean centerHorizontally = false;
|
||||||
|
|
||||||
|
public TextStencilElement(Font font) {
|
||||||
|
super();
|
||||||
|
this.font = font;
|
||||||
|
height = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextStencilElement(Font font, String text) {
|
||||||
|
this(font);
|
||||||
|
component = Components.literal(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextStencilElement(Font font, MutableComponent component) {
|
||||||
|
this(font);
|
||||||
|
this.component = component;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextStencilElement withText(String text) {
|
||||||
|
component = Components.literal(text);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextStencilElement withText(MutableComponent component) {
|
||||||
|
this.component = component;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextStencilElement centered(boolean vertical, boolean horizontal) {
|
||||||
|
this.centerVertically = vertical;
|
||||||
|
this.centerHorizontally = horizontal;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderStencil(PoseStack ms) {
|
||||||
|
|
||||||
|
float x = 0, y = 0;
|
||||||
|
if (centerHorizontally)
|
||||||
|
x = width / 2f - font.width(component) / 2f;
|
||||||
|
|
||||||
|
if (centerVertically)
|
||||||
|
y = height / 2f - (font.lineHeight - 1) / 2f;
|
||||||
|
|
||||||
|
font.draw(ms, component, x, y, 0xff_000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderElement(PoseStack ms) {
|
||||||
|
float x = 0, y = 0;
|
||||||
|
if (centerHorizontally)
|
||||||
|
x = width / 2f - font.width(component) / 2f;
|
||||||
|
|
||||||
|
if (centerVertically)
|
||||||
|
y = height / 2f - (font.lineHeight - 1) / 2f;
|
||||||
|
|
||||||
|
ms.pushPose();
|
||||||
|
ms.translate(x, y, 0);
|
||||||
|
element.render(ms, font.width(component), font.lineHeight + 2, alpha);
|
||||||
|
ms.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableComponent getComponent() {
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.widget;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.TickableGuiEventListener;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Components;
|
||||||
|
import net.minecraft.client.gui.components.AbstractWidget;
|
||||||
|
import net.minecraft.client.gui.narration.NarrationElementOutput;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
public abstract class AbstractSimiWidget extends AbstractWidget implements TickableGuiEventListener {
|
||||||
|
|
||||||
|
public static final int HEADER_RGB = 0x5391E1;
|
||||||
|
|
||||||
|
protected float z;
|
||||||
|
protected boolean wasHovered = false;
|
||||||
|
protected List<Component> toolTip = new LinkedList<>();
|
||||||
|
protected BiConsumer<Integer, Integer> onClick = (_$, _$$) -> {};
|
||||||
|
|
||||||
|
public int lockedTooltipX = -1;
|
||||||
|
public int lockedTooltipY = -1;
|
||||||
|
|
||||||
|
protected AbstractSimiWidget(int x, int y) {
|
||||||
|
this(x, y, 16, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbstractSimiWidget(int x, int y, int width, int height) {
|
||||||
|
this(x, y, width, height, Components.immutableEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbstractSimiWidget(int x, int y, int width, int height, Component message) {
|
||||||
|
super(x, y, width, height, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends AbstractSimiWidget> T withCallback(BiConsumer<Integer, Integer> cb) {
|
||||||
|
this.onClick = cb;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends AbstractSimiWidget> T withCallback(Runnable cb) {
|
||||||
|
return withCallback((_$, _$$) -> cb.run());
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends AbstractSimiWidget> T atZLevel(float z) {
|
||||||
|
this.z = z;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Component> getToolTip() {
|
||||||
|
return toolTip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(@Nonnull PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
if (visible) {
|
||||||
|
isHovered = mouseX >= x && mouseY >= y && mouseX < x + width && mouseY < y + height;
|
||||||
|
beforeRender(ms, mouseX, mouseY, partialTicks);
|
||||||
|
renderButton(ms, mouseX, mouseY, partialTicks);
|
||||||
|
afterRender(ms, mouseX, mouseY, partialTicks);
|
||||||
|
wasHovered = isHoveredOrFocused();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void beforeRender(@Nonnull PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
ms.pushPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderButton(@Nonnull PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void afterRender(@Nonnull PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
ms.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runCallback(double mouseX, double mouseY) {
|
||||||
|
onClick.accept((int) mouseX, (int) mouseY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(double mouseX, double mouseY) {
|
||||||
|
runCallback(mouseX, mouseY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateNarration(NarrationElementOutput pNarrationElementOutput) {
|
||||||
|
defaultButtonNarrationText(pNarrationElementOutput);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.widget;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.Theme;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.Theme.Key;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.UIRenderHelper;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.element.BoxElement;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.element.DelegatedStencilElement;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Color;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Couple;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.animation.LerpedFloat;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class BoxWidget extends ElementWidget {
|
||||||
|
|
||||||
|
public static final Function<BoxWidget, DelegatedStencilElement.ElementRenderer> gradientFactory = (box) -> (ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, w/2, -2, w + 4, h + 4, box.gradientColor1, box.gradientColor2);
|
||||||
|
|
||||||
|
protected BoxElement box;
|
||||||
|
|
||||||
|
protected Color customBorderTop;
|
||||||
|
protected Color customBorderBot;
|
||||||
|
protected Color customBackground;
|
||||||
|
protected boolean animateColors = true;
|
||||||
|
protected LerpedFloat colorAnimation = LerpedFloat.linear();
|
||||||
|
|
||||||
|
protected Color gradientColor1, gradientColor2;
|
||||||
|
private Color previousColor1, previousColor2;
|
||||||
|
private Color colorTarget1 = Theme.c(getIdleTheme(), true).copy();
|
||||||
|
private Color colorTarget2 = Theme.c(getIdleTheme(), false).copy();
|
||||||
|
|
||||||
|
public BoxWidget() {
|
||||||
|
this(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoxWidget(int x, int y) {
|
||||||
|
this(x, y, 16, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoxWidget(int x, int y, int width, int height) {
|
||||||
|
super(x, y, width, height);
|
||||||
|
box = new BoxElement()
|
||||||
|
.at(x, y)
|
||||||
|
.withBounds(width, height);
|
||||||
|
gradientColor1 = colorTarget1;
|
||||||
|
gradientColor2 = colorTarget2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BoxWidget> T withBounds(int width, int height) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BoxWidget> T withBorderColors(Couple<Color> colors) {
|
||||||
|
this.customBorderTop = colors.getFirst();
|
||||||
|
this.customBorderBot = colors.getSecond();
|
||||||
|
updateColorsFromState();
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BoxWidget> T withBorderColors(Color top, Color bot) {
|
||||||
|
this.customBorderTop = top;
|
||||||
|
this.customBorderBot = bot;
|
||||||
|
updateColorsFromState();
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BoxWidget> T withCustomBackground(Color color) {
|
||||||
|
this.customBackground = color;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BoxWidget> T animateColors(boolean b) {
|
||||||
|
this.animateColors = b;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
colorAnimation.tickChaser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(double x, double y) {
|
||||||
|
super.onClick(x, y);
|
||||||
|
|
||||||
|
gradientColor1 = Theme.c(getClickTheme(), true);
|
||||||
|
gradientColor2 = Theme.c(getClickTheme(), false);
|
||||||
|
startGradientAnimation(getColorForState(true), getColorForState(false), true, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void beforeRender(@Nonnull PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
super.beforeRender(ms, mouseX, mouseY, partialTicks);
|
||||||
|
|
||||||
|
if (isHovered != wasHovered) {
|
||||||
|
startGradientAnimation(
|
||||||
|
getColorForState(true),
|
||||||
|
getColorForState(false),
|
||||||
|
isHovered
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colorAnimation.settled()) {
|
||||||
|
gradientColor1 = colorTarget1;
|
||||||
|
gradientColor2 = colorTarget2;
|
||||||
|
} else {
|
||||||
|
float animationValue = 1 - Math.abs(colorAnimation.getValue(partialTicks));
|
||||||
|
gradientColor1 = Color.mixColors(previousColor1, colorTarget1, animationValue);
|
||||||
|
gradientColor2 = Color.mixColors(previousColor2, colorTarget2, animationValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderButton(@Nonnull PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
float fadeValue = fade.getValue(partialTicks);
|
||||||
|
if (fadeValue < .1f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
box.withAlpha(fadeValue);
|
||||||
|
box.withBackground(customBackground != null ? customBackground : Theme.c(Theme.Key.PONDER_BACKGROUND_TRANSPARENT))
|
||||||
|
.gradientBorder(gradientColor1, gradientColor2)
|
||||||
|
.at(x, y, z)
|
||||||
|
.withBounds(width, height)
|
||||||
|
.render(ms);
|
||||||
|
|
||||||
|
super.renderButton(ms, mouseX, mouseY, partialTicks);
|
||||||
|
|
||||||
|
wasHovered = isHovered;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMouseOver(double mX, double mY) {
|
||||||
|
if (!active || !visible)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float padX = 2 + paddingX;
|
||||||
|
float padY = 2 + paddingY;
|
||||||
|
|
||||||
|
return x - padX <= mX && y - padY <= mY && mX < x + padX + width && mY < y + padY + height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean clicked(double pMouseX, double pMouseY) {
|
||||||
|
if (!active || !visible)
|
||||||
|
return false;
|
||||||
|
return isMouseOver(pMouseX, pMouseY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoxElement getBox() {
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateColorsFromState() {
|
||||||
|
colorTarget1 = getColorForState(true);
|
||||||
|
colorTarget2 = getColorForState(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void animateGradientFromState() {
|
||||||
|
startGradientAnimation(
|
||||||
|
getColorForState(true),
|
||||||
|
getColorForState(false),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startGradientAnimation(Color c1, Color c2, boolean positive, double expSpeed) {
|
||||||
|
if (!animateColors)
|
||||||
|
return;
|
||||||
|
|
||||||
|
colorAnimation.startWithValue(positive ? 1 : -1);
|
||||||
|
colorAnimation.chase(0, expSpeed, LerpedFloat.Chaser.EXP);
|
||||||
|
colorAnimation.tickChaser();
|
||||||
|
|
||||||
|
previousColor1 = gradientColor1;
|
||||||
|
previousColor2 = gradientColor2;
|
||||||
|
|
||||||
|
colorTarget1 = c1;
|
||||||
|
colorTarget2 = c2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startGradientAnimation(Color c1, Color c2, boolean positive) {
|
||||||
|
startGradientAnimation(c1, c2, positive, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color getColorForState(boolean first) {
|
||||||
|
if (!active)
|
||||||
|
return Theme.p(getDisabledTheme()).get(first);
|
||||||
|
|
||||||
|
if (isHovered) {
|
||||||
|
if (first)
|
||||||
|
return customBorderTop != null ? customBorderTop.darker() : Theme.c(getHoverTheme(), true);
|
||||||
|
else
|
||||||
|
return customBorderBot != null ? customBorderBot.darker() : Theme.c(getHoverTheme(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
return customBorderTop != null ? customBorderTop : Theme.c(getIdleTheme(), true);
|
||||||
|
else
|
||||||
|
return customBorderBot != null ? customBorderBot : Theme.c(getIdleTheme(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Key getDisabledTheme() {
|
||||||
|
return Theme.Key.BUTTON_DISABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Key getIdleTheme() {
|
||||||
|
return Theme.Key.BUTTON_IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Key getHoverTheme() {
|
||||||
|
return Theme.Key.BUTTON_HOVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Key getClickTheme() {
|
||||||
|
return Theme.Key.BUTTON_CLICK;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.widget;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.element.RenderElement;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.element.ScreenElement;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.animation.LerpedFloat;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
|
public class ElementWidget extends AbstractSimiWidget {
|
||||||
|
|
||||||
|
protected RenderElement element = RenderElement.EMPTY;
|
||||||
|
|
||||||
|
protected boolean usesFade = false;
|
||||||
|
protected int fadeModX;
|
||||||
|
protected int fadeModY;
|
||||||
|
protected LerpedFloat fade = LerpedFloat.linear().startWithValue(1);
|
||||||
|
|
||||||
|
protected boolean rescaleElement = false;
|
||||||
|
protected float rescaleSizeX;
|
||||||
|
protected float rescaleSizeY;
|
||||||
|
|
||||||
|
protected float paddingX = 0;
|
||||||
|
protected float paddingY = 0;
|
||||||
|
|
||||||
|
public ElementWidget(int x, int y) {
|
||||||
|
super(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ElementWidget(int x, int y, int width, int height) {
|
||||||
|
super(x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends ElementWidget> T showingElement(RenderElement element) {
|
||||||
|
this.element = element;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends ElementWidget> T showing(ScreenElement renderable) {
|
||||||
|
return this.showingElement(RenderElement.of(renderable));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends ElementWidget> T modifyElement(Consumer<RenderElement> consumer) {
|
||||||
|
if (element != null)
|
||||||
|
consumer.accept(element);
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends ElementWidget> T mapElement(UnaryOperator<RenderElement> function) {
|
||||||
|
if (element != null)
|
||||||
|
element = function.apply(element);
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends ElementWidget> T withPadding(float paddingX, float paddingY) {
|
||||||
|
this.paddingX = paddingX;
|
||||||
|
this.paddingY = paddingY;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends ElementWidget> T enableFade(int fadeModifierX, int fadeModifierY) {
|
||||||
|
this.fade.startWithValue(0);
|
||||||
|
this.usesFade = true;
|
||||||
|
this.fadeModX = fadeModifierX;
|
||||||
|
this.fadeModY = fadeModifierY;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends ElementWidget> T disableFade() {
|
||||||
|
this.fade.startWithValue(1);
|
||||||
|
this.usesFade = false;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LerpedFloat fade() {
|
||||||
|
return fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends ElementWidget> T fade(float target) {
|
||||||
|
fade.chase(target, 0.1, LerpedFloat.Chaser.EXP);
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rescaling and its effects aren't properly tested with most elements.
|
||||||
|
* Thought it should work fine when using a TextStencilElement.
|
||||||
|
* Check BaseConfigScreen's title for such an example.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public <T extends ElementWidget> T rescaleElement(float rescaleSizeX, float rescaleSizeY) {
|
||||||
|
this.rescaleElement = true;
|
||||||
|
this.rescaleSizeX = rescaleSizeX;
|
||||||
|
this.rescaleSizeY = rescaleSizeY;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends ElementWidget> T disableRescale() {
|
||||||
|
this.rescaleElement = false;
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
fade.tickChaser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void beforeRender(@Nonnull PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
super.beforeRender(ms, mouseX, mouseY, partialTicks);
|
||||||
|
isHovered = isMouseOver(mouseX, mouseY);
|
||||||
|
|
||||||
|
float fadeValue = fade.getValue(partialTicks);
|
||||||
|
element.withAlpha(fadeValue);
|
||||||
|
if (fadeValue < 1) {
|
||||||
|
ms.translate((1 - fadeValue) * fadeModX, (1 - fadeValue) * fadeModY, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderButton(@Nonnull PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
ms.pushPose();
|
||||||
|
ms.translate(x + paddingX, y + paddingY, z);
|
||||||
|
float innerWidth = width - 2 * paddingX;
|
||||||
|
float innerHeight = height - 2 * paddingY;
|
||||||
|
float eX = element.getX(), eY = element.getY();
|
||||||
|
if (rescaleElement) {
|
||||||
|
float xScale = innerWidth / rescaleSizeX;
|
||||||
|
float yScale = innerHeight / rescaleSizeY;
|
||||||
|
ms.scale(xScale, yScale, 1);
|
||||||
|
element.at(eX / xScale, eY / yScale);
|
||||||
|
innerWidth /= xScale;
|
||||||
|
innerHeight /= yScale;
|
||||||
|
}
|
||||||
|
element.withBounds((int) innerWidth, (int) innerHeight).render(ms);
|
||||||
|
ms.popPose();
|
||||||
|
if (rescaleElement) {
|
||||||
|
element.at(eX, eY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderElement getRenderElement() {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.widget;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.AllGuiTextures;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.element.ScreenElement;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
public class IconButton extends AbstractSimiWidget {
|
||||||
|
|
||||||
|
protected ScreenElement icon;
|
||||||
|
|
||||||
|
public IconButton(int x, int y, ScreenElement icon) {
|
||||||
|
this(x, y, 18, 18, icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IconButton(int x, int y, int w, int h, ScreenElement icon) {
|
||||||
|
super(x, y, w, h);
|
||||||
|
this.icon = icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderButton(@Nonnull PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
if (visible) {
|
||||||
|
isHovered = mouseX >= x && mouseY >= y && mouseX < x + width && mouseY < y + height;
|
||||||
|
|
||||||
|
AllGuiTextures button = !active ? AllGuiTextures.BUTTON_DOWN
|
||||||
|
: isHoveredOrFocused() ? AllGuiTextures.BUTTON_HOVER : AllGuiTextures.BUTTON;
|
||||||
|
|
||||||
|
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
drawBg(matrixStack, button);
|
||||||
|
icon.render(matrixStack, x + 1, y + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void drawBg(PoseStack matrixStack, AllGuiTextures button) {
|
||||||
|
AllGuiTextures.BUTTON.bind();
|
||||||
|
blit(matrixStack, x, y, button.startX, button.startY, button.width, button.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToolTip(Component text) {
|
||||||
|
toolTip.clear();
|
||||||
|
toolTip.add(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIcon(ScreenElement icon) {
|
||||||
|
this.icon = icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.widget;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.gui.AllGuiTextures;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
public class Indicator extends AbstractSimiWidget {
|
||||||
|
|
||||||
|
public State state;
|
||||||
|
|
||||||
|
public Indicator(int x, int y, Component tooltip) {
|
||||||
|
super(x, y, AllGuiTextures.INDICATOR.width, AllGuiTextures.INDICATOR.height);
|
||||||
|
this.toolTip = ImmutableList.of(tooltip);
|
||||||
|
this.state = State.OFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(@Nonnull PoseStack matrixStack, int mouseX, int mouseY, float partialTicks ) {
|
||||||
|
if (!visible)
|
||||||
|
return;
|
||||||
|
AllGuiTextures toDraw;
|
||||||
|
switch (state) {
|
||||||
|
case ON: toDraw = AllGuiTextures.INDICATOR_WHITE; break;
|
||||||
|
case OFF: toDraw = AllGuiTextures.INDICATOR; break;
|
||||||
|
case RED: toDraw = AllGuiTextures.INDICATOR_RED; break;
|
||||||
|
case YELLOW: toDraw = AllGuiTextures.INDICATOR_YELLOW; break;
|
||||||
|
case GREEN: toDraw = AllGuiTextures.INDICATOR_GREEN; break;
|
||||||
|
default: toDraw = AllGuiTextures.INDICATOR; break;
|
||||||
|
}
|
||||||
|
toDraw.render(matrixStack, x, y, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum State {
|
||||||
|
OFF, ON,
|
||||||
|
RED, YELLOW, GREEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.widget;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Components;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.Font;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
public class Label extends AbstractSimiWidget {
|
||||||
|
|
||||||
|
public Component text;
|
||||||
|
public String suffix;
|
||||||
|
protected boolean hasShadow;
|
||||||
|
protected int color;
|
||||||
|
protected Font font;
|
||||||
|
|
||||||
|
public Label(int x, int y, Component text) {
|
||||||
|
super(x, y, Minecraft.getInstance().font.width(text), 10);
|
||||||
|
font = Minecraft.getInstance().font;
|
||||||
|
this.text = Components.literal("Label");
|
||||||
|
color = 0xFFFFFF;
|
||||||
|
hasShadow = false;
|
||||||
|
suffix = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Label colored(int color) {
|
||||||
|
this.color = color;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Label withShadow() {
|
||||||
|
this.hasShadow = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Label withSuffix(String s) {
|
||||||
|
suffix = s;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTextAndTrim(Component newText, boolean trimFront, int maxWidthPx) {
|
||||||
|
Font fontRenderer = Minecraft.getInstance().font;
|
||||||
|
|
||||||
|
if (fontRenderer.width(newText) <= maxWidthPx) {
|
||||||
|
text = newText;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String trim = "...";
|
||||||
|
int trimWidth = fontRenderer.width(trim);
|
||||||
|
|
||||||
|
String raw = newText.getString();
|
||||||
|
StringBuilder builder = new StringBuilder(raw);
|
||||||
|
int startIndex = trimFront ? 0 : raw.length() - 1;
|
||||||
|
int endIndex = !trimFront ? 0 : raw.length() - 1;
|
||||||
|
int step = (int) Math.signum(endIndex - startIndex);
|
||||||
|
|
||||||
|
for (int i = startIndex; i != endIndex; i += step) {
|
||||||
|
String sub = builder.substring(trimFront ? i : startIndex, trimFront ? endIndex + 1 : i + 1);
|
||||||
|
if (fontRenderer.width(Components.literal(sub).setStyle(newText.getStyle())) + trimWidth <= maxWidthPx) {
|
||||||
|
text = Components.literal(trimFront ? trim + sub : sub + trim).setStyle(newText.getStyle());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderButton(@Nonnull PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
if (text == null || text.getString().isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
RenderSystem.setShaderColor(1, 1, 1, 1);
|
||||||
|
MutableComponent copy = text.plainCopy();
|
||||||
|
if (suffix != null && !suffix.isEmpty())
|
||||||
|
copy.append(suffix);
|
||||||
|
|
||||||
|
if (hasShadow)
|
||||||
|
font.drawShadow(matrixStack, copy, x, y, color);
|
||||||
|
else
|
||||||
|
font.draw(matrixStack, copy, x, y, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.widget;
|
||||||
|
|
||||||
|
import nl.requios.effortlessbuilding.create.AllKeys;
|
||||||
|
//import nl.requios.effortlessbuilding.create.AllSoundEvents;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Components;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Lang;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
//import net.minecraft.client.resources.sounds.SimpleSoundInstance;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class ScrollInput extends AbstractSimiWidget {
|
||||||
|
|
||||||
|
protected Consumer<Integer> onScroll;
|
||||||
|
protected int state;
|
||||||
|
protected Component title = Lang.translateDirect("gui.scrollInput.defaultTitle");
|
||||||
|
protected final Component scrollToModify = Lang.translateDirect("gui.scrollInput.scrollToModify");
|
||||||
|
protected final Component shiftScrollsFaster = Lang.translateDirect("gui.scrollInput.shiftScrollsFaster");
|
||||||
|
protected Label displayLabel;
|
||||||
|
protected boolean inverted;
|
||||||
|
protected Function<Integer, Component> formatter;
|
||||||
|
|
||||||
|
protected int min, max;
|
||||||
|
protected int shiftStep;
|
||||||
|
Function<StepContext, Integer> step;
|
||||||
|
|
||||||
|
public ScrollInput(int xIn, int yIn, int widthIn, int heightIn) {
|
||||||
|
super(xIn, yIn, widthIn, heightIn);
|
||||||
|
state = 0;
|
||||||
|
min = 0;
|
||||||
|
max = 1;
|
||||||
|
shiftStep = 5;
|
||||||
|
step = standardStep();
|
||||||
|
formatter = i -> Components.literal(String.valueOf(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Function<StepContext, Integer> standardStep() {
|
||||||
|
return c -> c.shift ? shiftStep : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScrollInput inverted() {
|
||||||
|
inverted = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScrollInput withRange(int min, int max) {
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScrollInput calling(Consumer<Integer> onScroll) {
|
||||||
|
this.onScroll = onScroll;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScrollInput format(Function<Integer, Component> formatter) {
|
||||||
|
this.formatter = formatter;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScrollInput removeCallback() {
|
||||||
|
this.onScroll = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScrollInput titled(MutableComponent title) {
|
||||||
|
this.title = title;
|
||||||
|
updateTooltip();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScrollInput withStepFunction(Function<StepContext, Integer> step) {
|
||||||
|
this.step = step;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScrollInput writingTo(Label label) {
|
||||||
|
this.displayLabel = label;
|
||||||
|
if (label != null)
|
||||||
|
writeToLabel();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScrollInput setState(int state) {
|
||||||
|
this.state = state;
|
||||||
|
clampState();
|
||||||
|
updateTooltip();
|
||||||
|
if (displayLabel != null)
|
||||||
|
writeToLabel();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScrollInput withShiftStep(int step) {
|
||||||
|
shiftStep = step;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
|
||||||
|
if (inverted)
|
||||||
|
delta *= -1;
|
||||||
|
|
||||||
|
StepContext context = new StepContext();
|
||||||
|
context.control = AllKeys.ctrlDown();
|
||||||
|
context.shift = AllKeys.shiftDown();
|
||||||
|
context.currentValue = state;
|
||||||
|
context.forward = delta > 0;
|
||||||
|
|
||||||
|
int priorState = state;
|
||||||
|
boolean shifted = AllKeys.shiftDown();
|
||||||
|
int step = (int) Math.signum(delta) * this.step.apply(context);
|
||||||
|
|
||||||
|
state += step;
|
||||||
|
if (shifted)
|
||||||
|
state -= state % shiftStep;
|
||||||
|
|
||||||
|
clampState();
|
||||||
|
|
||||||
|
if (priorState != state) {
|
||||||
|
// Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(AllSoundEvents.SCROLL_VALUE.getMainEvent(), 1.5f + 0.1f * (state-min)/(max-min)));
|
||||||
|
onChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
return priorState != state;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void clampState() {
|
||||||
|
if (state >= max)
|
||||||
|
state = max - 1;
|
||||||
|
if (state < min)
|
||||||
|
state = min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onChanged() {
|
||||||
|
if (displayLabel != null)
|
||||||
|
writeToLabel();
|
||||||
|
if (onScroll != null)
|
||||||
|
onScroll.accept(state);
|
||||||
|
updateTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeToLabel() {
|
||||||
|
displayLabel.text = formatter.apply(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateTooltip() {
|
||||||
|
toolTip.clear();
|
||||||
|
if (title == null)
|
||||||
|
return;
|
||||||
|
toolTip.add(title.plainCopy()
|
||||||
|
.withStyle(s -> s.withColor(HEADER_RGB)));
|
||||||
|
toolTip.add(scrollToModify.plainCopy()
|
||||||
|
.withStyle(ChatFormatting.ITALIC, ChatFormatting.DARK_GRAY));
|
||||||
|
toolTip.add(shiftScrollsFaster.plainCopy()
|
||||||
|
.withStyle(ChatFormatting.ITALIC, ChatFormatting.DARK_GRAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StepContext {
|
||||||
|
public int currentValue;
|
||||||
|
public boolean forward;
|
||||||
|
public boolean shift;
|
||||||
|
public boolean control;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.widget;
|
||||||
|
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Components;
|
||||||
|
import nl.requios.effortlessbuilding.create.foundation.utility.Lang;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SelectionScrollInput extends ScrollInput {
|
||||||
|
|
||||||
|
private final MutableComponent scrollToSelect = Lang.translateDirect("gui.scrollInput.scrollToSelect");
|
||||||
|
protected List<? extends Component> options;
|
||||||
|
|
||||||
|
public SelectionScrollInput(int xIn, int yIn, int widthIn, int heightIn) {
|
||||||
|
super(xIn, yIn, widthIn, heightIn);
|
||||||
|
options = new ArrayList<>();
|
||||||
|
inverted();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScrollInput forOptions(List<? extends Component> options) {
|
||||||
|
this.options = options;
|
||||||
|
this.max = options.size();
|
||||||
|
format(options::get);
|
||||||
|
updateTooltip();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateTooltip() {
|
||||||
|
toolTip.clear();
|
||||||
|
if (title == null)
|
||||||
|
return;
|
||||||
|
toolTip.add(title.plainCopy()
|
||||||
|
.withStyle(s -> s.withColor(HEADER_RGB)));
|
||||||
|
int min = Math.min(this.max - 16, state - 7);
|
||||||
|
int max = Math.max(this.min + 16, state + 8);
|
||||||
|
min = Math.max(min, this.min);
|
||||||
|
max = Math.min(max, this.max);
|
||||||
|
if (this.min + 1 == min)
|
||||||
|
min--;
|
||||||
|
if (min > this.min)
|
||||||
|
toolTip.add(Components.literal("> ...").withStyle(ChatFormatting.GRAY));
|
||||||
|
if (this.max - 1 == max)
|
||||||
|
max++;
|
||||||
|
for (int i = min; i < max; i++) {
|
||||||
|
if (i == state)
|
||||||
|
toolTip.add(Components.empty()
|
||||||
|
.append("-> ")
|
||||||
|
.append(options.get(i))
|
||||||
|
.withStyle(ChatFormatting.WHITE));
|
||||||
|
else
|
||||||
|
toolTip.add(Components.empty()
|
||||||
|
.append("> ")
|
||||||
|
.append(options.get(i))
|
||||||
|
.withStyle(ChatFormatting.GRAY));
|
||||||
|
}
|
||||||
|
if (max < this.max)
|
||||||
|
toolTip.add(Components.literal("> ...").withStyle(ChatFormatting.GRAY));
|
||||||
|
|
||||||
|
toolTip.add(scrollToSelect.plainCopy()
|
||||||
|
.withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package nl.requios.effortlessbuilding.create.foundation.gui.widget;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TooltipArea extends AbstractSimiWidget {
|
||||||
|
|
||||||
|
public TooltipArea(int x, int y, int width, int height) {
|
||||||
|
super(x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderButton(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
if (visible)
|
||||||
|
isHovered = mouseX >= x && mouseY >= y && mouseX < x + width && mouseY < y + height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TooltipArea withTooltip(List<Component> tooltip) {
|
||||||
|
this.toolTip = tooltip;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,12 @@
|
|||||||
|
display_link.png, icons.png and widgets.png within this folder fall under the MIT license.
|
||||||
|
|
||||||
|
The MIT License Copyright (c) <year> <copyright holders> 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.
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
Reference in New Issue
Block a user