Minimally (not) working widget redo

This commit is contained in:
DBotThePony 2021-12-28 19:50:37 +07:00
parent fcd460ee38
commit f6c80dcbd9
Signed by: DBot
GPG Key ID: DCC23B5715498507
54 changed files with 1874 additions and 2376 deletions

View File

@ -1,114 +0,0 @@
package ru.dbotthepony.mc.otm.client.render;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.resources.ResourceLocation;
import ru.dbotthepony.mc.otm.client.render.RenderHelper;
/**
* Represents a texture element on atlas
*/
public record SkinElement(ResourceLocation texture, float image_x, float image_y, float rect_w, float rect_h,
float defined_width, float defined_height) {
public void render(PoseStack stack, float x, float y, float width, float height) {
RenderSystem.setShaderTexture(0, texture);
RenderHelper.drawTexturedRectUV(
stack,
x,
y,
width,
height,
image_x / defined_width,
image_y / defined_height,
(image_x + rect_w) / defined_width,
(image_y + rect_h) / defined_height);
}
public void render(PoseStack stack) {
render(stack, 0, 0);
}
public void render(PoseStack stack, float x, float y) {
RenderSystem.setShaderTexture(0, texture);
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderHelper.drawTexturedRectUV(
stack,
x,
y,
rect_w,
rect_h,
image_x / defined_width,
image_y / defined_height,
(image_x + rect_w) / defined_width,
(image_y + rect_h) / defined_height);
}
public void renderW(PoseStack stack, float x, float y, float width) {
RenderSystem.setShaderTexture(0, texture);
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderHelper.drawTexturedRectUV(
stack,
x,
y,
width,
rect_h,
image_x / defined_width,
image_y / defined_height,
(image_x + rect_w) / defined_width,
(image_y + rect_h) / defined_height);
}
public void renderH(PoseStack stack, float x, float y, float height) {
RenderSystem.setShaderTexture(0, texture);
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderHelper.drawTexturedRectUV(
stack,
x,
y,
rect_w,
height,
image_x / defined_width,
image_y / defined_height,
(image_x + rect_w) / defined_width,
(image_y + rect_h) / defined_height);
}
public void renderRaw(PoseStack stack, float x, float y, float width, float height) {
// RenderSystem.setShader(GameRenderer::getPositionTexShader);
// RenderSystem.setShaderTexture(0, texture);
RenderHelper.drawTexturedRectUV(
stack,
x,
y,
width,
height,
image_x / defined_width,
image_y / defined_height,
(image_x + rect_w) / defined_width,
(image_y + rect_h) / defined_height);
}
public void renderRaw(PoseStack stack, float x, float y) {
// RenderSystem.setShader(GameRenderer::getPositionTexShader);
// RenderSystem.setShaderTexture(0, texture);
RenderHelper.drawTexturedRectUV(
stack,
x,
y,
rect_w,
rect_h,
image_x / defined_width,
image_y / defined_height,
(image_x + rect_w) / defined_width,
(image_y + rect_h) / defined_height);
}
}

View File

@ -13,9 +13,9 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.capability.android.AndroidCapabilityPlayer;
import ru.dbotthepony.mc.otm.client.render.RGBAColor;
import ru.dbotthepony.mc.otm.client.render.RenderHelper;
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel;
import ru.dbotthepony.mc.otm.menu.AndroidStationMenu;
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget;
import ru.dbotthepony.mc.otm.client.screen.panels.*;
import javax.annotation.Nullable;
@ -73,7 +73,7 @@ public class AndroidStationScreen extends MatteryScreen<AndroidStationMenu> impl
@Override
protected boolean innerRenderTooltips(PoseStack stack, float mouse_x, float mouse_y, float flag) {
if (is_hovered) {
if (isHovered()) {
var list = new ArrayList<>(node.getTooltip());
if (node.isResearched()) {
@ -87,7 +87,7 @@ public class AndroidStationScreen extends MatteryScreen<AndroidStationMenu> impl
renderComponentTooltip(stack, list, (int) mouse_x, (int) mouse_y);
}
return is_hovered;
return isHovered();
}
}
@ -100,8 +100,8 @@ public class AndroidStationScreen extends MatteryScreen<AndroidStationMenu> impl
}
@Override
public List<GaugeWidget> getGauges() {
return List.of(menu.battery_widget);
public List<EditablePanel> getGauges() {
return List.of(new PowerGaugePanel(this, null, menu.battery_widget));
}
@Override
@ -112,7 +112,7 @@ public class AndroidStationScreen extends MatteryScreen<AndroidStationMenu> impl
private final EditablePanel[] rows = new EditablePanel[100];
private final Set<AndroidResearchType<?>> seen = new HashSet<>();
private float next_x = 0;
private float[] rows_width = new float[100];
private final float[] rows_width = new float[100];
private final AndroidResearchButton[][] created_buttons = new AndroidResearchButton[100][1000];
private final int[] created_buttons_idx = new int[100];

View File

@ -2,8 +2,9 @@ package ru.dbotthepony.mc.otm.client.screen;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel;
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel;
import ru.dbotthepony.mc.otm.menu.BatteryBankMenu;
import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget;
import ru.dbotthepony.mc.otm.client.screen.panels.FlexGridPanel;
import ru.dbotthepony.mc.otm.client.screen.panels.SlotPanel;
@ -15,8 +16,8 @@ public class BatteryBankScreen extends MatteryScreen<BatteryBankMenu> implements
}
@Override
public List<GaugeWidget> getGauges() {
return List.of(menu.battery_widget);
public List<EditablePanel> getGauges() {
return List.of(new PowerGaugePanel(this, null, menu.battery_widget));
}
@Override

View File

@ -2,11 +2,12 @@ package ru.dbotthepony.mc.otm.client.screen;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel;
import ru.dbotthepony.mc.otm.client.screen.panels.FlexGridPanel;
import ru.dbotthepony.mc.otm.client.screen.panels.SlotPanel;
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel;
import ru.dbotthepony.mc.otm.menu.DriveRackMenu;
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget;
import java.util.List;
@ -16,8 +17,8 @@ public class DriveRackScreen extends MatteryScreen<DriveRackMenu> implements Mat
}
@Override
public List<GaugeWidget> getGauges() {
return List.of(menu.battery_widget);
public List<EditablePanel> getGauges() {
return List.of(new PowerGaugePanel(this, null, menu.battery_widget));
}
@Override

View File

@ -1,19 +1,15 @@
package ru.dbotthepony.mc.otm.client.screen;
import com.mojang.blaze3d.platform.InputConstants;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.ClickAction;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.item.ItemStack;
import ru.dbotthepony.mc.otm.client.screen.panels.*;
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel;
import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive;
import ru.dbotthepony.mc.otm.menu.DriveViewerMenu;
import ru.dbotthepony.mc.otm.menu.data.InteractPacket;
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget;
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
import ru.dbotthepony.mc.otm.client.screen.panels.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -32,8 +28,8 @@ public class DriveViewerScreen extends MatteryScreen<DriveViewerMenu> implements
}
@Override
public List<GaugeWidget> getGauges() {
return List.of(menu.battery_widget);
public List<EditablePanel> getGauges() {
return List.of(new PowerGaugePanel(this, null, menu.battery_widget));
}
@Override

View File

@ -1,24 +1,15 @@
package ru.dbotthepony.mc.otm.client.screen;
import com.mojang.blaze3d.platform.InputConstants;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.ClickAction;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.item.ItemStack;
import ru.dbotthepony.mc.otm.client.screen.panels.*;
import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive;
import ru.dbotthepony.mc.otm.menu.DriveViewerMenu;
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel;
import ru.dbotthepony.mc.otm.menu.ItemMonitorMenu;
import ru.dbotthepony.mc.otm.menu.data.InteractPacket;
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget;
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
public class ItemMonitorScreen extends MatteryScreen<ItemMonitorMenu> implements MatteryScreen.IMatteryScreenGaugeGetter, MatteryScreen.IMatteryScreenBatteryGetter {
@ -33,8 +24,8 @@ public class ItemMonitorScreen extends MatteryScreen<ItemMonitorMenu> implements
}
@Override
public List<GaugeWidget> getGauges() {
return List.of(menu.battery_widget);
public List<EditablePanel> getGauges() {
return List.of(new PowerGaugePanel(this, null, menu.battery_widget));
}
@Override

View File

@ -3,10 +3,12 @@ package ru.dbotthepony.mc.otm.client.screen;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.entity.player.Inventory;
import ru.dbotthepony.mc.otm.client.screen.panels.*;
import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel;
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel;
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel;
import ru.dbotthepony.mc.otm.menu.MatterBottlerMenu;
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget;
import ru.dbotthepony.mc.otm.client.screen.panels.*;
import javax.annotation.Nullable;
import java.util.List;
@ -17,8 +19,8 @@ public class MatterBottlerScreen extends MatteryScreen<MatterBottlerMenu> implem
}
@Override
public List<GaugeWidget> getGauges() {
return List.of(menu.battery_widget, menu.matter_widget);
public List<EditablePanel> getGauges() {
return List.of(new PowerGaugePanel(this, null, menu.battery_widget), new MatterGaugePanel(this, null, menu.matter_widget));
}
@Override
@ -31,7 +33,7 @@ public class MatterBottlerScreen extends MatteryScreen<MatterBottlerMenu> implem
new SlotPanel<>(this, grid, menu.work_slots[0]);
new SlotPanel<>(this, grid, menu.work_slots[1]);
new SlotPanel<>(this, grid, menu.work_slots[2]);
new MatteryWidgetPanel(this, grid, menu.progress).setDockMargin(2, 0, 2, 0);
new ProgressGaugePanel(this, grid, menu.progress).setDockMargin(2, 0, 2, 0);
new SlotPanel<>(this, grid, menu.work_slots[3]);
new SlotPanel<>(this, grid, menu.work_slots[4]);
new SlotPanel<>(this, grid, menu.work_slots[5]);

View File

@ -2,8 +2,8 @@ package ru.dbotthepony.mc.otm.client.screen;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel;
import ru.dbotthepony.mc.otm.menu.MatterCapacitorBankMenu;
import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget;
import ru.dbotthepony.mc.otm.client.screen.panels.*;
import java.util.List;
@ -14,8 +14,8 @@ public class MatterCapacitorBankScreen extends MatteryScreen<MatterCapacitorBank
}
@Override
public List<GaugeWidget> getGauges() {
return List.of(menu.matter_widget, menu.total_matter_widget);
public List<EditablePanel> getGauges() {
return List.of(new MatterGaugePanel(this, null, menu.matter_widget), new MatterGaugePanel(this, null, menu.total_matter_widget));
}
@Override

View File

@ -2,10 +2,14 @@ package ru.dbotthepony.mc.otm.client.screen;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel;
import ru.dbotthepony.mc.otm.client.screen.panels.FlexGridPanel;
import ru.dbotthepony.mc.otm.client.screen.panels.SlotPanel;
import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel;
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel;
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel;
import ru.dbotthepony.mc.otm.menu.MatterDecomposerMenu;
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget;
import ru.dbotthepony.mc.otm.client.screen.panels.*;
import java.util.List;
@ -15,8 +19,8 @@ public class MatterDecomposerScreen extends MatteryScreen<MatterDecomposerMenu>
}
@Override
public List<GaugeWidget> getGauges() {
return List.of(menu.battery_widget, menu.matter_widget);
public List<EditablePanel> getGauges() {
return List.of(new PowerGaugePanel(this, null, menu.battery_widget), new MatterGaugePanel(this, null, menu.matter_widget));
}
@Override
@ -27,7 +31,7 @@ public class MatterDecomposerScreen extends MatteryScreen<MatterDecomposerMenu>
@Override
public void createGridPanels(FlexGridPanel grid) {
new SlotPanel<>(this, grid, 0, 0, menu.input).setDockMargin(2, 0, 2, 0);
new MatteryWidgetPanel(this, grid, menu.progress).setDockMargin(2, 0, 2, 0);
new ProgressGaugePanel(this, grid, menu.progress).setDockMargin(2, 0, 2, 0);
new SlotPanel<>(this, grid, 0, 0, menu.output).setDockMargin(2, 0, 2, 0);
}
}

View File

@ -2,9 +2,11 @@ package ru.dbotthepony.mc.otm.client.screen;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel;
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel;
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel;
import ru.dbotthepony.mc.otm.menu.MatterReplicatorMenu;
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget;
import ru.dbotthepony.mc.otm.client.screen.panels.*;
import java.util.List;
@ -15,8 +17,8 @@ public class MatterReplicatorScreen extends MatteryScreen<MatterReplicatorMenu>
}
@Override
public List<GaugeWidget> getGauges() {
return List.of(menu.battery_widget, menu.matter_widget);
public List<EditablePanel> getGauges() {
return List.of(new PowerGaugePanel(this, null, menu.battery_widget), new MatterGaugePanel(this, null, menu.matter_widget));
}
@Override
@ -26,7 +28,7 @@ public class MatterReplicatorScreen extends MatteryScreen<MatterReplicatorMenu>
@Override
public void createGridPanels(FlexGridPanel grid) {
new MatteryWidgetPanel(this, grid, menu.progress).setDockMargin(2, 0, 2, 0);
new ProgressGaugePanel(this, grid, menu.progress).setDockMargin(2, 0, 2, 0);
for (var slot : menu.output_slots) {
new SlotPanel<>(this, grid, 0, 0, slot);

View File

@ -2,10 +2,13 @@ package ru.dbotthepony.mc.otm.client.screen;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel;
import ru.dbotthepony.mc.otm.client.screen.panels.FlexGridPanel;
import ru.dbotthepony.mc.otm.client.screen.panels.SlotPanel;
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel;
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel;
import ru.dbotthepony.mc.otm.menu.MatterScannerMenu;
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget;
import ru.dbotthepony.mc.otm.client.screen.panels.*;
import java.util.List;
@ -15,8 +18,8 @@ public class MatterScannerScreen extends MatteryScreen<MatterScannerMenu> implem
}
@Override
public List<GaugeWidget> getGauges() {
return List.of(menu.battery_widget);
public List<EditablePanel> getGauges() {
return List.of(new PowerGaugePanel(this, null, menu.battery_widget));
}
@Override
@ -27,6 +30,6 @@ public class MatterScannerScreen extends MatteryScreen<MatterScannerMenu> implem
@Override
public void createGridPanels(FlexGridPanel grid) {
new SlotPanel<>(this, grid, 0, 0, menu.input).setDockMargin(2, 0, 2, 0);
new MatteryWidgetPanel(this, grid, menu.progress).setDockMargin(2, 0, 2, 0);
new ProgressGaugePanel(this, grid, menu.progress).setDockMargin(2, 0, 2, 0);
}
}

View File

@ -8,6 +8,7 @@ import net.minecraft.ChatFormatting;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.renderer.entity.ItemRenderer;
@ -21,7 +22,6 @@ import net.minecraft.world.item.ItemStack;
import net.minecraftforge.client.event.ContainerScreenEvent;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget;
import ru.dbotthepony.mc.otm.client.screen.panels.*;
import javax.annotation.Nonnull;
@ -50,7 +50,7 @@ public abstract class MatteryScreen<T extends MatteryMenu> extends AbstractConta
public interface IMatteryScreenLeftPanel {}
public interface IMatteryScreenGaugeGetter extends IMatteryScreenLeftPanel {
List<GaugeWidget> getGauges();
List<EditablePanel> getGauges();
}
public interface IMatteryScreenBatteryGetter extends IMatteryScreenLeftPanel {
@ -178,8 +178,8 @@ public abstract class MatteryScreen<T extends MatteryMenu> extends AbstractConta
float height = 0;
for (var gauge : gauges.getGauges()) {
width += gauge.getImageWidth();
height = Math.max(height, gauge.getImageHeight());
width += gauge.getWidth();
height = Math.max(height, gauge.getHeight());
}
width += 2;
@ -192,7 +192,7 @@ public abstract class MatteryScreen<T extends MatteryMenu> extends AbstractConta
grid_gauges.setDock(Dock.TOP);
for (var gauge : gauges.getGauges()) {
new MatteryWidgetPanel(this, grid_gauges, gauge);
gauge.setParent(grid_gauges);
}
reserve.setWidth(Math.max(width, reserve.getWidth()));
@ -426,11 +426,6 @@ public abstract class MatteryScreen<T extends MatteryMenu> extends AbstractConta
if (main_frame != null) {
addPanel(main_frame);
for (var widget : menu.mattery_widgets) {
if (widget.auto_parent)
new MatteryWidgetPanel(this, main_frame, widget);
}
for (var slot : menu.main_slots) {
new SlotPanel<>(this, main_frame, slot);
}
@ -453,7 +448,7 @@ public abstract class MatteryScreen<T extends MatteryMenu> extends AbstractConta
var panel = panels.get(i);
if (hovered) {
panel.unsetHover();
panel.unsetHovered();
} else if (panel.tickHover(mouse_x, mouse_y)) {
hovered = true;
}
@ -470,7 +465,7 @@ public abstract class MatteryScreen<T extends MatteryMenu> extends AbstractConta
for (var panel : panels) {
RenderSystem.depthFunc(GL_ALWAYS);
panel.set3DDepth(depth);
panel.setAccumulatedDepth(depth);
RenderSystem.setShaderColor(1F, 1F, 1F, 1F);
depth = Math.max(depth, panel.render(pose, mouse_x, mouse_y, flag));
}

View File

@ -2,8 +2,8 @@ package ru.dbotthepony.mc.otm.client.screen;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import ru.dbotthepony.mc.otm.client.screen.widget.PatternGaugePanel;
import ru.dbotthepony.mc.otm.menu.PatternStorageMenu;
import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget;
import ru.dbotthepony.mc.otm.client.screen.panels.*;
import java.util.List;
@ -14,8 +14,8 @@ public class PatternStorageScreen extends MatteryScreen<PatternStorageMenu> impl
}
@Override
public List<GaugeWidget> getGauges() {
return List.of(menu.stored_this, menu.stored_grid);
public List<EditablePanel> getGauges() {
return List.of(new PatternGaugePanel(this, null, menu.stored_this), new PatternGaugePanel(this, null, menu.stored_grid));
}
@Override

View File

@ -7,7 +7,6 @@ import net.minecraft.client.gui.Font;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.client.gui.GuiUtils;
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen;
import ru.dbotthepony.mc.otm.client.render.RGBAColor;
import ru.dbotthepony.mc.otm.client.render.RenderHelper;
@ -52,7 +51,7 @@ public abstract class AbstractSlotPanel extends EditablePanel {
var system_stack = RenderSystem.getModelViewStack();
system_stack.pushPose();
system_stack.translate(parent_x + 1, parent_y + 1, 0);
system_stack.translate(getAbsoluteX() + 1, getAbsoluteY() + 1, 0);
RenderSystem.applyModelViewMatrix();
RenderSystem.depthFunc(GL_LESS);
@ -60,8 +59,8 @@ public abstract class AbstractSlotPanel extends EditablePanel {
// Thanks Mojang
// Very cool
// (for int x, int y, which are then cast into doubles anyway)
screen.getItemRenderer().blitOffset = accumulated_depth - 100; // force item to draw only 50 units "above" background
screen.getItemRenderer().renderAndDecorateItem(Minecraft.getInstance().player, itemstack, 0, 0, (int) (parent_x + parent_y * 1000) /* some kind of indexing ? */);
screen.getItemRenderer().blitOffset = getAccumulatedDepth() - 100; // force item to draw only 50 units "above" background
screen.getItemRenderer().renderAndDecorateItem(Minecraft.getInstance().player, itemstack, 0, 0, (int) (getAbsoluteX() + getAbsoluteY() * 1000) /* some kind of indexing ? */);
RenderSystem.depthFunc(GL_ALWAYS);
screen.getItemRenderer().renderGuiItemDecorations(screen.getFont(), itemstack, 0, 0, count_override);
@ -76,7 +75,7 @@ public abstract class AbstractSlotPanel extends EditablePanel {
RenderSystem.applyModelViewMatrix();
}
if (is_hovered) {
if (isHovered()) {
stack.pushPose();
stack.translate(0, 0, height);
RenderHelper.setDrawColor(SLOT_HIGHLIGHT);
@ -101,7 +100,7 @@ public abstract class AbstractSlotPanel extends EditablePanel {
@Override
protected boolean innerRenderTooltips(PoseStack stack, float mouse_x, float mouse_y, float flag) {
if (is_hovered) {
if (isHovered()) {
var itemstack = getItemStack();
if (!itemstack.isEmpty()) {

View File

@ -16,7 +16,7 @@ public class ButtonPanel extends MinecraftWidgetPanel<Button> {
return new Button(0, 0, (int) panel.getWidth(), Math.min(20, (int) panel.getHeight()), label, (btn) -> ((ButtonPanel) panel).onPress()) {
@Override
public boolean isHoveredOrFocused() {
return panel.is_hovered;
return panel.isHovered();
}
};
});

View File

@ -1,10 +0,0 @@
package ru.dbotthepony.mc.otm.client.screen.panels;
public enum Dock {
NONE,
LEFT,
RIGHT,
TOP,
BOTTOM,
FILL
}

View File

@ -14,7 +14,7 @@ public class EditBoxPanel extends MinecraftWidgetPanel<EditBox> {
return new EditBox(screen.getFont(), 0, 0, (int) panel.getWidth(), Math.min(20, (int) panel.getHeight()), component) {
@Override
public boolean isHoveredOrFocused() {
return panel.is_hovered;
return panel.isHovered();
}
};
});
@ -35,12 +35,11 @@ public class EditBoxPanel extends MinecraftWidgetPanel<EditBox> {
@Override
protected void factorize(EditBox widget, boolean recreation) {
widget.setFocus(focused);
widget.setFocus(isFocused());
}
@Override
protected void onFocusChanged(boolean new_focused, boolean old_focused) {
OverdriveThatMatters.LOGGER.info("Focus {}", new_focused);
getOrCreateWidget().setFocus(new_focused);
}

View File

@ -61,6 +61,10 @@ public class FlexGridPanel extends EditablePanel {
// "финальная" ширина этой панели
float this_width = getWidth() - getDockPadding().left() - getDockPadding().right();
if (this_width <= 0) {
return;
}
for (var child : children) {
min_width = Math.min(min_width, child.getWidth() + child.getDockMargin().left() + child.getDockMargin().right());
desired_width += child.getWidth() + child.getDockMargin().left() + child.getDockMargin().right();

View File

@ -34,7 +34,7 @@ public class GridPanel extends EditablePanel {
for (int row = 0; row < grid_height; row++) {
for (int column = 0; column < grid_width; column++) {
var child = childAtIndex(index);
var child = get(index);
if (child == null) {
break;
@ -55,7 +55,7 @@ public class GridPanel extends EditablePanel {
current_x = 0;
line_y = 0;
if (childAtIndex(index) == null) {
if (get(index) == null) {
break;
}
}

View File

@ -14,34 +14,34 @@ public class Label extends EditablePanel {
public Label(@Nonnull MatteryScreen<?> screen, @Nullable EditablePanel parent, float x, float y, float width, float height) {
super(screen, parent, x, y, width, height);
scissor = true;
setScissor(true);
}
public Label(@Nonnull MatteryScreen<?> screen, @Nullable EditablePanel parent) {
super(screen, parent);
scissor = true;
setScissor(true);
}
public Label(@Nonnull MatteryScreen<?> screen, @Nullable EditablePanel parent, float x, float y) {
super(screen, parent, x, y, 100, 12);
scissor = true;
setScissor(true);
}
public Label(@Nonnull MatteryScreen<?> screen, @Nullable EditablePanel parent, float x, float y, float width, float height, Component text) {
super(screen, parent, x, y, width, height);
scissor = true;
setScissor(true);
this.text = text;
}
public Label(@Nonnull MatteryScreen<?> screen, @Nullable EditablePanel parent, Component text) {
super(screen, parent);
scissor = true;
setScissor(true);
this.text = text;
}
public Label(@Nonnull MatteryScreen<?> screen, @Nullable EditablePanel parent, float x, float y, Component text) {
super(screen, parent, x, y, 100, 12);
scissor = true;
setScissor(true);
this.text = text;
}

View File

@ -1,45 +0,0 @@
package ru.dbotthepony.mc.otm.client.screen.panels;
import com.mojang.blaze3d.vertex.PoseStack;
import ru.dbotthepony.mc.otm.menu.widget.AbstractWidget;
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class MatteryWidgetPanel extends EditablePanel {
public final AbstractWidget widget;
public MatteryWidgetPanel(@Nonnull MatteryScreen screen, @Nullable EditablePanel parent, AbstractWidget widget) {
super(screen, parent, widget.x, widget.y, widget.getImageWidth(), widget.getImageHeight());
widget.x = 0;
widget.y = 0;
this.widget = widget;
}
public MatteryWidgetPanel(@Nonnull MatteryScreen screen, @Nullable EditablePanel parent, float x, float y, AbstractWidget widget) {
super(screen, parent, x, y, widget.getImageWidth(), widget.getImageHeight());
widget.x = 0;
widget.y = 0;
this.widget = widget;
}
@Override
protected void innerRender(PoseStack stack, float mouse_x, float mouse_y, float flag) {
widget.renderBackground(stack, 0, 0);
}
@Override
protected boolean innerRenderTooltips(PoseStack stack, float mouse_x, float mouse_y, float flag) {
if (is_hovered) {
var tooltips = widget.getTooltip();
if (tooltips != null) {
screen.renderComponentTooltip(stack, tooltips, (int) mouse_x, (int) mouse_y);
return true;
}
}
return false;
}
}

View File

@ -65,8 +65,8 @@ public class MinecraftWidgetPanel<T extends AbstractWidget> extends EditablePane
var new_widget = factory.create(this);
new_widget.visible = getVisible();
new_widget.x = (int) parent_x;
new_widget.y = (int) parent_y;
new_widget.x = (int) getAbsoluteX();
new_widget.y = (int) getAbsoluteY();
if (widget != null)
copyValues(new_widget, widget);

View File

@ -25,7 +25,7 @@ public class ScrollBarPanel extends EditablePanel {
protected void innerRender(PoseStack stack, float mouse_x, float mouse_y, float flag) {
if (is_scrolling) {
RenderHelper.scroll_bar_button_press.render(stack, 0, 0);
} else if (is_hovered) {
} else if (isHovered()) {
RenderHelper.scroll_bar_button_hover.render(stack, 0, 0);
} else {
RenderHelper.scroll_bar_button.render(stack, 0, 0);

View File

@ -93,7 +93,7 @@ public class SlotPanel<T extends MatterySlot> extends AbstractSlotPanel {
renderRegular(stack, itemstack, count_override);
if (is_hovered) {
if (isHovered()) {
screen.hoveredSlot = slot;
}
}

View File

@ -12,14 +12,14 @@ import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.menu.data.BigDecimalDataContainer;
import ru.dbotthepony.mc.otm.menu.slot.BatterySlot;
import ru.dbotthepony.mc.otm.menu.widget.BatteryLevelWidget;
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget;
import javax.annotation.Nullable;
public class BatteryBankMenu extends MatteryMenu {
protected BlockEntityBatteryBank tile;
public BatteryLevelWidget battery_widget;
public LevelGaugeWidget battery_widget;
public BatterySlot[] battery_slots = new BatterySlot[6 * 2];
public BatteryBankMenu(int p_38852_, Inventory inventory) {
@ -31,9 +31,9 @@ public class BatteryBankMenu extends MatteryMenu {
this.tile = tile;
if (tile == null || tile.getCapability(MatteryCapability.ENERGY).resolve().isEmpty()) {
battery_widget = new BatteryLevelWidget(this, 13, 24);
battery_widget = new LevelGaugeWidget(this);
} else {
battery_widget = new BatteryLevelWidget(this, 13, 24, tile.getCapability(MatteryCapability.ENERGY).resolve().get());
battery_widget = new LevelGaugeWidget(this, tile.getCapability(MatteryCapability.ENERGY).resolve().get());
}
for (int row = 0; row < 2; row++) {

View File

@ -9,7 +9,7 @@ import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterBottler;
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
import ru.dbotthepony.mc.otm.menu.widget.MatterLevelWidget;
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget;
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget;
import ru.dbotthepony.mc.otm.network.MatterBottlerSwitchPacket;
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
@ -44,7 +44,7 @@ public class MatterBottlerMenu extends PoweredMatteryMenu {
};
public ProgressGaugeWidget progress;
public MatterLevelWidget matter_widget;
public LevelGaugeWidget matter_widget;
public MatterySlot[] work_slots = new MatterySlot[6];
@ -54,21 +54,11 @@ public class MatterBottlerMenu extends PoweredMatteryMenu {
var container = tile != null ? tile.work_slots : new SimpleContainer(6);
if (tile == null) {
progress = new ProgressGaugeWidget(this) {
@Override
public UVWindingOrder getUVWindwing() {
if (work_flow.get(0) > 0) {
return UVWindingOrder.U0_V0_U1_V1;
}
return UVWindingOrder.U1_V0_U0_V1;
}
};
matter_widget = new MatterLevelWidget(this);
progress = new ProgressGaugeWidget(this);
matter_widget = new LevelGaugeWidget(this);
} else {
progress = new ProgressGaugeWidget(this, tile::getWorkProgress);
matter_widget = new MatterLevelWidget(this, tile.matter);
matter_widget = new LevelGaugeWidget(this, tile.matter);
}
for (int i = 0; i < container.getContainerSize(); i++) {

View File

@ -8,7 +8,7 @@ import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterCapacitorBank;
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.menu.slot.MatterContainerInputSlot;
import ru.dbotthepony.mc.otm.menu.widget.MatterLevelWidget;
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget;
import java.math.BigDecimal;
@ -17,8 +17,8 @@ public class MatterCapacitorBankMenu extends MatteryMenu {
this(p_38852_, inventory, null);
}
public MatterLevelWidget matter_widget;
public MatterLevelWidget total_matter_widget;
public LevelGaugeWidget matter_widget;
public LevelGaugeWidget total_matter_widget;
public MatterContainerInputSlot[] container_slots = new MatterContainerInputSlot[2 * 6];
@ -26,11 +26,11 @@ public class MatterCapacitorBankMenu extends MatteryMenu {
super(Registry.Menus.MATTER_CAPACITOR_BANK, p_38852_, inventory, tile);
if (tile == null) {
matter_widget = new MatterLevelWidget(this, 14, 20);
total_matter_widget = new MatterLevelWidget(this, 14, 20);
matter_widget = new LevelGaugeWidget(this);
total_matter_widget = new LevelGaugeWidget(this);
} else {
matter_widget = new MatterLevelWidget(this, 14, 20, tile.matter);
total_matter_widget = new MatterLevelWidget(this, 14, 20, () -> {
matter_widget = new LevelGaugeWidget(this, tile.matter);
total_matter_widget = new LevelGaugeWidget(this, () -> {
if (tile.getMatterGrid() != null) {
return tile.getMatterGrid().getStored();
}

View File

@ -10,7 +10,7 @@ import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterDecomposer;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
import ru.dbotthepony.mc.otm.menu.slot.MachineOutputSlot;
import ru.dbotthepony.mc.otm.menu.widget.MatterLevelWidget;
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget;
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget;
import javax.annotation.Nullable;
@ -23,7 +23,7 @@ public class MatterDecomposerMenu extends PoweredMatteryMenu {
public MatterySlot input;
public MachineOutputSlot output;
public ProgressGaugeWidget progress;
public MatterLevelWidget matter_widget;
public LevelGaugeWidget matter_widget;
public MatterDecomposerMenu(int containerID, Inventory inventory, @Nullable BlockEntityMatterDecomposer tile) {
super(Registry.Menus.MATTER_DECOMPOSER, containerID, inventory, tile);
@ -44,11 +44,11 @@ public class MatterDecomposerMenu extends PoweredMatteryMenu {
addSlot(output);
if (tile == null || tile.getCapability(MatteryCapability.MATTER).resolve().isEmpty()) {
matter_widget = new MatterLevelWidget(this, 22, 14);
progress = new ProgressGaugeWidget(this, 61 + 18 + 3, 36);
matter_widget = new LevelGaugeWidget(this);
progress = new ProgressGaugeWidget(this);
} else {
matter_widget = new MatterLevelWidget(this, 22, 14, tile.getCapability(MatteryCapability.MATTER).resolve().get());
progress = new ProgressGaugeWidget(this, 61 + 18 + 3, 36, () -> (float) tile.getWorkProgress(), tile::cantProcessJob);
matter_widget = new LevelGaugeWidget(this, tile.getCapability(MatteryCapability.MATTER).resolve().get());
progress = new ProgressGaugeWidget(this, () -> (float) tile.getWorkProgress(), tile::cantProcessJob);
}
addBatterySlot(14);

View File

@ -6,7 +6,7 @@ import net.minecraft.world.entity.player.Inventory;
import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterReplicator;
import ru.dbotthepony.mc.otm.menu.slot.MachineOutputSlot;
import ru.dbotthepony.mc.otm.menu.widget.MatterLevelWidget;
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget;
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget;
public class MatterReplicatorMenu extends PoweredMatteryMenu {
@ -14,7 +14,7 @@ public class MatterReplicatorMenu extends PoweredMatteryMenu {
this(p_38852_, inventory, null);
}
public MatterLevelWidget matter_widget;
public LevelGaugeWidget matter_widget;
public ProgressGaugeWidget progress;
public MachineOutputSlot[] output_slots = new MachineOutputSlot[3];
@ -29,11 +29,11 @@ public class MatterReplicatorMenu extends PoweredMatteryMenu {
}
if (tile != null) {
matter_widget = new MatterLevelWidget(this, 22, 14, tile.matter);
progress = new ProgressGaugeWidget(this, 38, 38, () -> (float) tile.getWorkProgress(), tile::cantProcessJob);
matter_widget = new LevelGaugeWidget(this, tile.matter);
progress = new ProgressGaugeWidget(this, () -> (float) tile.getWorkProgress(), tile::cantProcessJob);
} else {
matter_widget = new MatterLevelWidget(this, 22, 14);
progress = new ProgressGaugeWidget(this, 38, 38);
matter_widget = new LevelGaugeWidget(this);
progress = new ProgressGaugeWidget(this);
}
addBatterySlot(14);

View File

@ -33,9 +33,9 @@ public class MatterScannerMenu extends PoweredMatteryMenu {
addSlot(input);
if (tile != null) {
progress = new ProgressGaugeWidget(this, 88, 38, () -> (float) tile.getWorkProgress(), tile::cantProcessJob);
progress = new ProgressGaugeWidget(this, () -> (float) tile.getWorkProgress(), tile::cantProcessJob);
} else {
progress = new ProgressGaugeWidget(this, 88, 38);
progress = new ProgressGaugeWidget(this);
}
addBatterySlot();

View File

@ -1,320 +0,0 @@
package ru.dbotthepony.mc.otm.menu;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.*;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity;
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
import ru.dbotthepony.mc.otm.menu.widget.AbstractWidget;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
public abstract class MatteryMenu extends AbstractContainerMenu {
public final BlockEntity tile;
public final Inventory inventory;
public final Player ply;
public final ArrayList<AbstractWidget> mattery_widgets = new ArrayList<>();
public final ArrayList<MatterySlot> inventory_slots = new ArrayList<>();
public final ArrayList<MatterySlot> main_slots = new ArrayList<>();
protected final Set<Integer> locked_inventory_slots = new HashSet<>();
protected boolean isInventorySlotLocked(int index) {
return locked_inventory_slots.contains(index);
}
@Nullable
protected ContainerSynchronizer synchronizer;
@Override
public void setSynchronizer(ContainerSynchronizer p_150417_) {
synchronizer = p_150417_;
super.setSynchronizer(p_150417_);
}
protected MatteryMenu(@Nullable MenuType<?> p_38851_, int p_38852_, Inventory inventory) {
this(p_38851_, p_38852_, inventory, null);
}
protected MatteryMenu(@Nullable MenuType<?> p_38851_, int p_38852_, Inventory inventory, BlockEntity tile) {
super(p_38851_, p_38852_);
this.inventory = inventory;
this.ply = inventory.player;
this.tile = tile;
}
public void addWidget(AbstractWidget widget, Consumer<Consumer<ContainerData>> consumer) {
if (mattery_widgets.contains(widget))
return;
mattery_widgets.add(widget);
consumer.accept(this::addDataSlots);
}
public MatterySlot addMainSlot(MatterySlot slot) {
addSlot(slot);
main_slots.add(slot);
return slot;
}
protected void addInventorySlots() {
addInventorySlots(97);
}
protected int inventory_slot_index_start;
protected int inventory_slot_index_end;
protected void addInventorySlots(int offset) {
boolean first = true;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 9; ++j) {
var slot = new MatterySlot(inventory, j + i * 9 + 9, 8 + j * 18, 14 + i * 18) {
@Override
public boolean mayPlace(ItemStack p_40231_) {
return !isInventorySlotLocked(index);
}
@Override
public boolean mayPickup(Player p_40228_) {
return !isInventorySlotLocked(index);
}
};
inventory_slots.add(slot);
this.addSlot(slot);
if (first) {
first = false;
inventory_slot_index_start = slot.index;
}
}
}
MatterySlot last = null;
for (int k = 0; k < 9; ++k) {
last = new MatterySlot(inventory, k, 8 + k * 18, 14 + 58) {
@Override
public boolean mayPlace(ItemStack p_40231_) {
return !isInventorySlotLocked(index);
}
@Override
public boolean mayPickup(Player p_40228_) {
return !isInventorySlotLocked(index);
}
};
this.addSlot(last);
inventory_slots.add(last);
}
inventory_slot_index_end = last.index;
}
@Override
public void broadcastChanges() {
for (AbstractWidget widget : this.mattery_widgets) {
widget.updateServer();
}
super.broadcastChanges();
}
@Override
public void broadcastFullState() {
for (AbstractWidget widget : this.mattery_widgets) {
widget.updateServer();
}
super.broadcastFullState();
}
@Override
public boolean stillValid(Player player) {
if (tile == null)
return true;
if (player.level.getBlockEntity(tile.getBlockPos()) != tile) {
return false;
}
BlockPos pos = tile.getBlockPos();
return player.distanceToSqr((double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D) <= 64.0D;
}
abstract protected int getWorkingSlotStart();
abstract protected int getWorkingSlotEnd();
// This method receive Player interactor and slot_index where Shift + Right click occurred
// It shall return item stack that got moved
@Override
public ItemStack quickMoveStack(Player ply, int slot_index) {
// this.moveItemStackTo(ItemStack, int start_slot_index, int end_slot_index, boolean iteration_order)
// returns boolean, telling whenever ItemStack was modified (moved or sharnk)
// false means nothing happened
// Last boolean determine order of slot iteration, where:
// if TRUE, iteration order is end_slot_index -> start_slot_index
// if FALSE iteration order is start_slot_index -> end_slot_index
int start = getWorkingSlotStart();
int end = getWorkingSlotEnd();
if (start == end) {
return ItemStack.EMPTY;
}
ItemStack moved = ItemStack.EMPTY;
Slot get_slot = this.slots.get(slot_index);
if (get_slot.hasItem()) {
ItemStack slot_item = get_slot.getItem();
moved = slot_item.copy();
if (slot_index < inventory_slot_index_start) {
// Moving FROM machine TO inventory
if (!moveItemStackTo(slot_item, inventory_slot_index_start, inventory_slot_index_end + 1, false)) {
return ItemStack.EMPTY;
}
} else if (!moveItemStackTo(slot_item, start, end, false)) {
// Moving FROM inventory TO machine
return ItemStack.EMPTY;
}
if (slot_item.isEmpty()) {
get_slot.set(ItemStack.EMPTY);
} else {
get_slot.setChanged();
}
}
return moved;
}
public MoveResult quickMoveToInventory(ItemStack stack, boolean simulate) {
if (inventory_slot_index_start == 0 && inventory_slot_index_end == 0) {
return new MoveResult(false, stack, Set.of());
}
return customMoveItemStackTo(stack, inventory_slot_index_start, inventory_slot_index_end + 1, false, simulate);
}
@Override
protected boolean moveItemStackTo(ItemStack stack_to_move, int initial_slot, int final_slot, boolean reverse_direction) {
var move_result = customMoveItemStackTo(stack_to_move, initial_slot, final_slot, reverse_direction, false);
var remaining = move_result.remaining;
if (remaining.getCount() == stack_to_move.getCount())
return false;
stack_to_move.setCount(remaining.getCount());
return move_result.merge_occured;
}
public record MoveResult(boolean merge_occured, ItemStack remaining, Set<Slot> changed_slots) {
}
@Nonnull
protected MoveResult customMoveItemStackTo(@Nonnull ItemStack stack_to_move, int initial_slot, int final_slot, boolean reverse_direction, boolean simulate) {
boolean merge_occured = false;
int i = reverse_direction ? final_slot - 1 : initial_slot;
var changed = new HashSet<Slot>();
stack_to_move = stack_to_move.copy();
if (stack_to_move.isStackable()) {
while (!stack_to_move.isEmpty()) {
if (reverse_direction) {
if (i < initial_slot) {
break;
}
} else if (i >= final_slot) {
break;
}
var slot = this.slots.get(i);
var slot_stack = slot.getItem();
if (!slot_stack.isEmpty() && ItemStack.isSameItemSameTags(stack_to_move, slot_stack)) {
int j = slot_stack.getCount() + stack_to_move.getCount();
int maxSize = slot.getMaxStackSize(stack_to_move);
if (j <= maxSize) {
stack_to_move.setCount(0);
if (!simulate) {
slot_stack.setCount(j);
slot.setChanged();
}
merge_occured = true;
changed.add(slot);
} else if (slot_stack.getCount() < maxSize) {
stack_to_move.shrink(maxSize - slot_stack.getCount());
if (!simulate) {
slot_stack.setCount(maxSize);
slot.setChanged();
}
merge_occured = true;
changed.add(slot);
}
}
i += reverse_direction ? -1 : 1;
}
}
if (!stack_to_move.isEmpty()) {
i = reverse_direction ? final_slot - 1 : initial_slot;
while (true) {
if (reverse_direction) {
if (i < initial_slot) {
break;
}
} else if (i >= final_slot) {
break;
}
var slot = this.slots.get(i);
var slot_stack = slot.getItem();
if (slot_stack.isEmpty() && slot.mayPlace(stack_to_move)) {
if (!simulate) {
if (stack_to_move.getCount() > slot.getMaxStackSize()) {
slot.set(stack_to_move.split(slot.getMaxStackSize()));
} else {
slot.set(stack_to_move.split(stack_to_move.getCount()));
}
slot.setChanged();
}
merge_occured = true;
changed.add(slot);
break;
}
i += reverse_direction ? -1 : 1;
}
}
return new MoveResult(merge_occured, stack_to_move, changed);
}
}

View File

@ -5,8 +5,9 @@ import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Inventory;
import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.block.entity.BlockEntityPatternStorage;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.menu.slot.PatternSlot;
import ru.dbotthepony.mc.otm.menu.widget.PatternStorageWidget;
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget;
public class PatternStorageMenu extends MatteryMenu {
public PatternStorageMenu(int p_38852_, Inventory inventory) {
@ -15,29 +16,29 @@ public class PatternStorageMenu extends MatteryMenu {
public PatternSlot[] pattern_slots = new PatternSlot[2 * 4];
public PatternStorageWidget stored_this;
public PatternStorageWidget stored_grid;
public LevelGaugeWidget stored_this;
public LevelGaugeWidget stored_grid;
public PatternStorageMenu(int p_38852_, Inventory inventory, BlockEntityPatternStorage tile) {
super(Registry.Menus.PATTERN_STORAGE, p_38852_, inventory, tile);
if (tile == null) {
stored_this = new PatternStorageWidget(this);
stored_grid = new PatternStorageWidget(this);
stored_this = new LevelGaugeWidget(this);
stored_grid = new LevelGaugeWidget(this);
} else {
stored_this = new PatternStorageWidget(this, tile.getPatternStorage());
stored_grid = new PatternStorageWidget(this, () -> {
stored_this = new LevelGaugeWidget(this, tile.getPatternStorage());
stored_grid = new LevelGaugeWidget(this, () -> {
if (tile.getMatterGrid() != null) {
return tile.getMatterGrid().getStoredPatternCount();
return new Fraction(tile.getMatterGrid().getStoredPatternCount());
}
return 0L;
return Fraction.ZERO;
}, () -> {
if (tile.getMatterGrid() != null) {
return tile.getMatterGrid().getPatternCapacity();
return new Fraction(tile.getMatterGrid().getPatternCapacity());
}
return 0L;
return Fraction.ZERO;
});
}

View File

@ -7,14 +7,14 @@ import net.minecraft.world.inventory.MenuType;
import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatteryPowered;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.menu.slot.BatterySlot;
import ru.dbotthepony.mc.otm.menu.widget.BatteryLevelWidget;
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget;
import javax.annotation.Nullable;
abstract public class PoweredMatteryMenu extends MatteryMenu {
public final BlockEntityMatteryPowered tile;
public BatteryLevelWidget battery_widget;
public LevelGaugeWidget battery_widget;
public BatterySlot battery_slot;
protected PoweredMatteryMenu(
@ -27,9 +27,9 @@ abstract public class PoweredMatteryMenu extends MatteryMenu {
this.tile = tile;
if (tile == null || tile.getCapability(MatteryCapability.ENERGY).resolve().isEmpty()) {
battery_widget = new BatteryLevelWidget(this, 13, 14);
battery_widget = new LevelGaugeWidget(this);
} else {
battery_widget = new BatteryLevelWidget(this, 13, 14, tile.getCapability(MatteryCapability.ENERGY).resolve().get());
battery_widget = new LevelGaugeWidget(this, tile.getCapability(MatteryCapability.ENERGY).resolve().get());
}
}

View File

@ -1,74 +0,0 @@
package ru.dbotthepony.mc.otm.menu.widget;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.network.chat.Component;
import net.minecraft.world.inventory.ContainerData;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
import ru.dbotthepony.mc.otm.client.screen.UVWindingOrder;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.function.Consumer;
/**
* This widget class implement *shared* code
* meaning these widgets are created inside Menu, not inside Screen
* and these widgets are supposed to move data between server to client
*
* this is why this is different from Minecraft's clientside only widgets
*/
public abstract class AbstractWidget {
/**
* Unlike other flags such as GaugeDirection, this tells how to finally draw the texture.
*
* This allows mirroring or flipping or both of drawn texture.
*
* @return uv order to use
*/
public UVWindingOrder getUVWindwing() {
return UVWindingOrder.U0_V0_U1_V1;
}
public final MatteryMenu menu;
public int x;
public int y;
protected Consumer<ContainerData> register_data;
public boolean auto_parent = false;
public abstract int getImageWidth();
public abstract int getImageHeight();
public abstract int getImageX();
public abstract int getImageY();
public AbstractWidget(@Nonnull MatteryMenu menu, int x, int y) {
this.menu = menu;
this.x = x;
this.y = y;
menu.addWidget(this, (consumer) -> register_data = consumer);
}
public AbstractWidget(@Nonnull MatteryMenu menu) {
this(menu, 0, 0);
}
public AbstractWidget autoParent() {
auto_parent = true;
return this;
}
protected void addDataSlots(ContainerData slots) {
register_data.accept(slots);
}
abstract public void updateServer();
abstract public void renderBackground(PoseStack pose, float local_x, float local_y);
// true - rendered a tooltip, break the loop
// false - pass
@Nullable
abstract public List<Component> getTooltip();
}

View File

@ -1,64 +0,0 @@
package ru.dbotthepony.mc.otm.menu.widget;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.menu.FormattingHelper;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
import javax.annotation.Nullable;
import java.math.BigDecimal;
import java.util.List;
import java.util.function.Supplier;
public class BatteryLevelWidget extends StorageGaugeWidget {
public BatteryLevelWidget(MatteryMenu menu, int x, int y, IMatteryEnergyStorage capability) {
super(menu, x, y, capability::getBatteryLevel, capability::getMaxBatteryLevel);
}
public BatteryLevelWidget(MatteryMenu menu, IMatteryEnergyStorage capability) {
super(menu, 0, 0, capability::getBatteryLevel, capability::getMaxBatteryLevel);
}
public BatteryLevelWidget(MatteryMenu menu, int x, int y) {
super(menu, x, y);
}
public BatteryLevelWidget(MatteryMenu menu) {
super(menu, 0, 0);
}
public BatteryLevelWidget(MatteryMenu menu, int x, int y, Supplier<Fraction> value_supplier, Supplier<Fraction> max_value_supplier) {
super(menu, x, y, value_supplier, max_value_supplier);
}
@Override
public int getImageWidth() {
return 9;
}
@Override
public int getImageHeight() {
return 48;
}
@Override
public int getImageX() {
return 0;
}
@Override
public int getImageY() {
return 48;
}
@Nullable
@Override
public List<Component> getTooltip() {
return List.of(
new TranslatableComponent("otm.gui.power.percentage_level", String.format("%.2f", getLevel() * 100d)),
FormattingHelper.formatPowerLevel(value_container.getValue(), max_value_container.getValue())
);
}
}

View File

@ -1,125 +0,0 @@
package ru.dbotthepony.mc.otm.menu.widget;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.GameRenderer;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
import ru.dbotthepony.mc.otm.client.render.RenderHelper;
import ru.dbotthepony.mc.otm.client.screen.UVWindingOrder;
abstract public class GaugeWidget extends AbstractWidget {
public enum GaugeDirection {
TOP_TO_BOTTOM,
BOTTOM_TO_TOP,
LEFT_TO_RIGHT,
RIGHT_TO_LEFT
}
public GaugeWidget(MatteryMenu menu, int x, int y) {
super(menu, x, y);
}
public GaugeWidget(MatteryMenu menu) {
super(menu);
}
public GaugeDirection fill_order = GaugeDirection.BOTTOM_TO_TOP;
abstract public float getLevel();
protected void setupGaugeDrawing() {
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
RenderSystem.setShaderTexture(0, RenderHelper.WIDGETS);
}
@Override
public void renderBackground(PoseStack pose, float local_x, float local_y) {
setupGaugeDrawing();
var order = getUVWindwing();
RenderHelper.drawTexturedRectAuto(pose, local_x + x, local_y + y, getImageWidth(), getImageHeight(), getImageX(), getImageY(), order);
float level = getLevel();
if (level > 0.01f) {
if (fill_order == GaugeDirection.BOTTOM_TO_TOP) {
int intHeight = (int) Math.floor(level * (float) getImageHeight() + 0.5f);
RenderHelper.drawTexturedRectAuto(
pose,
local_x + x,
local_y + y + getImageHeight() - intHeight,
getImageWidth(),
intHeight,
getImageX() + getImageWidth(),
getImageY() + getImageHeight() - intHeight,
order);
} else if (fill_order == GaugeDirection.TOP_TO_BOTTOM) {
RenderHelper.drawTexturedRectAuto(
pose,
local_x + x,
local_y + y,
getImageWidth(),
(float) Math.floor(level * (float) getImageHeight() + 0.5f),
getImageX() + getImageWidth(),
getImageY(),
order);
} else if (fill_order == GaugeDirection.LEFT_TO_RIGHT) {
// forward order
if (order.u0 == UVWindingOrder.U0) {
RenderHelper.drawTexturedRectAuto(
pose,
local_x + x,
local_y + y,
(float) Math.floor(level * (float) getImageWidth() + 0.5f),
getImageHeight(),
getImageX() + getImageWidth(),
getImageY(),
order);
} else {
// backward order
var value = (float) Math.floor(level * (float) getImageWidth() + 0.5f);
RenderHelper.drawTexturedRectAuto(
pose,
local_x + x + getImageWidth() - value,
local_y + y,
value,
getImageHeight(),
getImageX() + getImageWidth(),
getImageY(),
order);
}
} else if (fill_order == GaugeDirection.RIGHT_TO_LEFT) {
// forward order
if (order.u0 == UVWindingOrder.U0) {
var value = (float) Math.floor(level * (float) getImageWidth() + 0.5f);
RenderHelper.drawTexturedRectAuto(
pose,
local_x + x + getImageWidth() - value,
local_y + y,
value,
getImageHeight(),
getImageX() + getImageWidth(),
getImageY(),
order);
} else {
// backward order
RenderHelper.drawTexturedRectAuto(
pose,
local_x + x,
local_y + y,
(float) Math.floor(level * (float) getImageWidth() + 0.5f),
getImageHeight(),
getImageX() + getImageWidth(),
getImageY(),
order);
}
}
}
}
}

View File

@ -1,64 +0,0 @@
package ru.dbotthepony.mc.otm.menu.widget;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.menu.FormattingHelper;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
import javax.annotation.Nullable;
import java.math.BigDecimal;
import java.util.List;
import java.util.function.Supplier;
public class MatterLevelWidget extends StorageGaugeWidget {
public MatterLevelWidget(MatteryMenu menu, int x, int y, IMatterHandler capability) {
super(menu, x, y, capability::getStoredMatter, capability::getMaxStoredMatter);
}
public MatterLevelWidget(MatteryMenu menu, int x, int y) {
super(menu, x, y);
}
public MatterLevelWidget(MatteryMenu menu) {
this(menu, 0, 0);
}
public MatterLevelWidget(MatteryMenu menu, IMatterHandler capability) {
this(menu, 0, 0, capability);
}
public MatterLevelWidget(MatteryMenu menu, int x, int y, Supplier<Fraction> value_supplier, Supplier<Fraction> max_value_supplier) {
super(menu, x, y, value_supplier, max_value_supplier);
}
@Override
public int getImageWidth() {
return 9;
}
@Override
public int getImageHeight() {
return 48;
}
@Override
public int getImageX() {
return 0;
}
@Override
public int getImageY() {
return 0;
}
@Nullable
@Override
public List<Component> getTooltip() {
return List.of(
new TranslatableComponent("otm.gui.matter.percentage_level", String.format("%.2f", getLevel() * 100d)),
FormattingHelper.formatMatterLevel(value_container.getValue(), max_value_container.getValue())
);
}
}

View File

@ -1,87 +0,0 @@
package ru.dbotthepony.mc.otm.menu.widget;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
import ru.dbotthepony.mc.otm.menu.data.LongDataContainer;
import javax.annotation.Nullable;
import java.util.List;
import java.util.function.Supplier;
public class PatternStorageWidget extends GaugeWidget {
public Supplier<Long> value_supplier;
public Supplier<Long> max_value_supplier;
protected final LongDataContainer value_container = new LongDataContainer();
protected final LongDataContainer max_value_container = new LongDataContainer();
public PatternStorageWidget(MatteryMenu menu, int x, int y, IPatternStorage capability) {
this(menu, x, y, () -> (long) capability.getStored(), () -> (long) capability.getCapacity());
}
public PatternStorageWidget(MatteryMenu menu, IPatternStorage capability) {
this(menu, 0, 0, () -> (long) capability.getStored(), () -> (long) capability.getCapacity());
}
public PatternStorageWidget(MatteryMenu menu) {
this(menu, 0, 0, null, null);
}
public PatternStorageWidget(MatteryMenu menu, int x, int y, Supplier<Long> value_supplier, Supplier<Long> max_value_supplier) {
super(menu, x, y);
this.value_supplier = value_supplier;
this.max_value_supplier = max_value_supplier;
addDataSlots(value_container);
addDataSlots(max_value_container);
}
public PatternStorageWidget(MatteryMenu menu, Supplier<Long> value_supplier, Supplier<Long> max_value_supplier) {
this(menu, 0, 0, value_supplier, max_value_supplier);
}
@Override
public void updateServer() {
if (value_supplier == null || max_value_supplier == null)
return;
value_container.setValue(value_supplier.get());
max_value_container.setValue(max_value_supplier.get());
}
@Override
public int getImageWidth() {
return 9;
}
@Override
public int getImageHeight() {
return 48;
}
@Override
public int getImageX() {
return 0;
}
@Override
public int getImageY() {
return 148;
}
@Nullable
@Override
public List<Component> getTooltip() {
return List.of(
new TranslatableComponent("otm.gui.pattern.percentage_level", String.format("%.2f", getLevel() * 100d)),
new TranslatableComponent("otm.gui.pattern.format", value_container.getValue(), max_value_container.getValue())
);
}
@Override
public float getLevel() {
return max_value_container.getValue() == 0 ? 0 : (float) ((double) value_container.getValue() / (double) max_value_container.getValue());
}
}

View File

@ -1,127 +0,0 @@
package ru.dbotthepony.mc.otm.menu.widget;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.inventory.ContainerData;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
import javax.annotation.Nullable;
import java.util.List;
import java.util.function.Supplier;
public class ProgressGaugeWidget extends GaugeWidget {
protected final Supplier<Float> progress_supplier;
protected final Supplier<Boolean> is_stuck_supplier;
protected final ContainerData progress_container = new ContainerData() {
private int progress;
private int is_stuck;
@Override
public int get(int i) {
return i == 0 ? progress : is_stuck;
}
@Override
public void set(int i, int i1) {
if (i == 0) {
progress = i1;
} else {
is_stuck = i1;
}
}
@Override
public int getCount() {
return 2;
}
};
public ProgressGaugeWidget(MatteryMenu menu, int x, int y, Supplier<Float> progress, Supplier<Boolean> is_stuck_supplier) {
super(menu, x, y);
fill_order = GaugeDirection.LEFT_TO_RIGHT;
addDataSlots(progress_container);
progress_supplier = progress;
this.is_stuck_supplier = is_stuck_supplier;
}
public ProgressGaugeWidget(MatteryMenu menu, int x, int y) {
this(menu, x, y, null, null);
}
public ProgressGaugeWidget(MatteryMenu menu) {
this(menu, 0, 0, null, null);
}
public ProgressGaugeWidget(MatteryMenu menu, Supplier<Float> progress) {
this(menu, 0, 0, progress, null);
}
public ProgressGaugeWidget(MatteryMenu menu, int x, int y, Supplier<Float> progress) {
this(menu, x, y, progress, null);
}
@Override
public int getImageWidth() {
return 22;
}
@Override
public int getImageHeight() {
return 16;
}
@Override
public int getImageX() {
return 0;
}
@Override
public int getImageY() {
return 132;
}
@Override
public void updateServer() {
if (progress_supplier != null)
progress_container.set(0, (int) (progress_supplier.get() * 10000f));
if (is_stuck_supplier != null)
progress_container.set(1, is_stuck_supplier.get() ? 1 : 0);
}
@Override
protected void setupGaugeDrawing() {
super.setupGaugeDrawing();
if (progress_container.get(1) != 0 && System.currentTimeMillis() % 1500L > 750L) {
RenderSystem.setShaderColor(0.8F, 0.4F, 0.4F, 1.0F);
}
}
@Nullable
@Override
public List<Component> getTooltip() {
List<Component> text;
if (progress_container.get(1) != 0) {
text = List.of(
new TranslatableComponent("otm.gui.progress_widget", String.format("%.2f", progress_container.get(0) / 100f)),
new TranslatableComponent("otm.gui.progress_widget_stuck").withStyle(ChatFormatting.DARK_RED)
);
} else {
text = List.of(
new TranslatableComponent("otm.gui.progress_widget", String.format("%.2f", progress_container.get(0) / 100f))
);
}
return text;
}
@Override
public float getLevel() {
return progress_container.get(0) / 10000f;
}
}

View File

@ -1,53 +0,0 @@
package ru.dbotthepony.mc.otm.menu.widget;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
import ru.dbotthepony.mc.otm.menu.data.BigDecimalDataContainer;
import ru.dbotthepony.mc.otm.menu.data.FractionDataContainer;
import java.math.BigDecimal;
import java.util.function.Supplier;
abstract public class StorageGaugeWidget extends GaugeWidget {
protected Supplier<Fraction> value_supplier;
protected Supplier<Fraction> max_value_supplier;
protected final FractionDataContainer value_container = new FractionDataContainer();
protected final FractionDataContainer max_value_container = new FractionDataContainer();
public StorageGaugeWidget(MatteryMenu menu, int x, int y) {
this(menu, x, y, null, null);
}
public StorageGaugeWidget(MatteryMenu menu) {
this(menu, 0, 0, null, null);
}
public StorageGaugeWidget(MatteryMenu menu, int x, int y, Supplier<Fraction> value_supplier, Supplier<Fraction> max_value_supplier) {
super(menu, x, y);
this.value_supplier = value_supplier;
this.max_value_supplier = max_value_supplier;
addDataSlots(value_container);
addDataSlots(max_value_container);
}
public StorageGaugeWidget(MatteryMenu menu, Supplier<Fraction> value_supplier, Supplier<Fraction> max_value_supplier) {
this(menu, 0, 0, value_supplier, max_value_supplier);
}
@Override
public void updateServer() {
if (value_supplier == null || max_value_supplier == null)
return;
value_container.setValue(value_supplier.get());
max_value_container.setValue(max_value_supplier.get());
}
@Override
public float getLevel() {
return max_value_container.getValue().compareTo(Fraction.ZERO) == 0 ? 0f : value_container.getValue().div(max_value_container.getValue()).toFloat();
}
}

View File

@ -235,6 +235,8 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti
check = false
}
if (power.isZero()) return
for (consumer in consumers) {
consumer.ifPresent {
if (it is IMatteryEnergyStorage) {

View File

@ -0,0 +1,84 @@
package ru.dbotthepony.mc.otm.client.render
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.resources.ResourceLocation
import ru.dbotthepony.mc.otm.client.screen.UVWindingOrder
@JvmRecord
data class SkinElement(
val texture: ResourceLocation = RenderHelper.WIDGETS,
val image_x: Float,
val image_y: Float,
val rect_w: Float,
val rect_h: Float,
val defined_width: Float = 256f,
val defined_height: Float = 256f
) {
@JvmOverloads
fun render(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = rect_w,
height: Float = rect_h,
winding: UVWindingOrder = UVWindingOrder.U0_V0_U1_V1
) {
RenderSystem.setShaderTexture(0, texture)
RenderSystem.enableBlend()
RenderSystem.defaultBlendFunc()
renderRaw(stack, x, y, width, height, winding)
}
@JvmOverloads
fun renderW(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = rect_w,
winding: UVWindingOrder = UVWindingOrder.U0_V0_U1_V1,
) {
render(stack, x, y, width = width, winding = winding)
}
@JvmOverloads
fun renderH(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
height: Float = rect_h,
winding: UVWindingOrder = UVWindingOrder.U0_V0_U1_V1,
) {
render(stack, x, y, height = height, winding = winding)
}
@JvmOverloads
fun renderRaw(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = rect_w,
height: Float = rect_h,
winding: UVWindingOrder = UVWindingOrder.U0_V0_U1_V1
) {
val u0 = image_x / defined_width
val v0 = image_y / defined_height
val u1 = (image_x + rect_w) / defined_width
val v1 = (image_y + rect_h) / defined_height
val winded = winding.translate(u0, v0, u1, v1)
RenderHelper.drawTexturedRectUV(
stack,
x,
y,
width,
height,
winded.u0,
winded.v0,
winded.u1,
winded.v1,
)
}
}

View File

@ -5,6 +5,8 @@ import net.minecraft.network.chat.TextComponent
import net.minecraft.network.chat.TranslatableComponent
import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
import ru.dbotthepony.mc.otm.menu.ChemicalGeneratorMenu
class ChemicalGeneratorScreen(menu: ChemicalGeneratorMenu, inventory: Inventory, title: Component) : MatteryScreen<ChemicalGeneratorMenu>(menu, inventory, title) {
@ -13,7 +15,7 @@ class ChemicalGeneratorScreen(menu: ChemicalGeneratorMenu, inventory: Inventory,
override fun makeMainFrame(): FramePanel? {
val frame = super.makeMainFrame()
val battery = MatteryWidgetPanel(this, frame, menu.energy)
val battery = PowerGaugePanel(this, frame, menu.energy)
battery.dock = Dock.LEFT
burn_time.parent = frame
burn_time.dock = Dock.TOP
@ -23,7 +25,7 @@ class ChemicalGeneratorScreen(menu: ChemicalGeneratorMenu, inventory: Inventory,
val grid = FlexGridPanel(this, frame)
SlotPanel(this, grid, menu.fuel_slot)
MatteryWidgetPanel(this, grid, menu.progress)
ProgressGaugePanel(this, grid, menu.progress)
grid.dock = Dock.FILL
grid.setDockMargin(0f, 2f, 0f, 0f)

View File

@ -1,51 +1,52 @@
package ru.dbotthepony.mc.otm.client.screen.panels;
package ru.dbotthepony.mc.otm.client.screen.panels
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen;
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
open class DraggableCanvasPanel @JvmOverloads constructor(
screen: MatteryScreen<*>,
parent: EditablePanel?,
x: Float = 0f,
y: Float = 0f,
width: Float = 10f,
height: Float = 10f
) : EditablePanel(
screen, parent, x, y, width, height
) {
protected var dragging = false
protected var lastMouseX = 0.0
protected var lastMouseY = 0.0
public class DraggableCanvasPanel extends EditablePanel {
public DraggableCanvasPanel(@Nonnull MatteryScreen<?> screen, @Nullable EditablePanel parent, float x, float y, float width, float height) {
super(screen, parent, x, y, width, height);
scissor = true;
override fun mouseClickedInner(mouse_x: Double, mouse_y: Double, flag: Int): Boolean {
dragging = true
lastMouseX = mouse_x
lastMouseY = mouse_y
ignoreMouseEventBoundaries = true
return true
}
public DraggableCanvasPanel(@Nonnull MatteryScreen<?> screen, @Nullable EditablePanel parent) {
super(screen, parent);
scissor = true;
override fun mouseReleasedInner(mouse_x: Double, mouse_y: Double, flag: Int): Boolean {
dragging = false
ignoreMouseEventBoundaries = false
return true
}
protected boolean dragging = false;
protected double last_mouse_x;
protected double last_mouse_y;
@Override
protected boolean mouseClickedInner(double mouse_x, double mouse_y, int flag) {
dragging = true;
last_mouse_x = mouse_x;
last_mouse_y = mouse_y;
setIgnoreMouseEventBoundaries(true);
return true;
}
@Override
protected boolean mouseReleasedInner(double mouse_x, double mouse_y, int flag) {
dragging = false;
setIgnoreMouseEventBoundaries(false);
return true;
}
@Override
protected boolean mouseDraggedInner(double mouse_x, double mouse_y, int flag, double drag_x, double drag_y) {
override fun mouseDraggedInner(
mouse_x: Double,
mouse_y: Double,
flag: Int,
drag_x: Double,
drag_y: Double
): Boolean {
if (dragging) {
x_offset -= last_mouse_x - mouse_x;
y_offset -= last_mouse_y - mouse_y;
last_mouse_x = mouse_x;
last_mouse_y = mouse_y;
xOffset -= (lastMouseX - mouse_x).toFloat()
yOffset -= (lastMouseY - mouse_y).toFloat()
lastMouseX = mouse_x
lastMouseY = mouse_y
}
return true;
return true
}
}
init {
scissor = true
}
}

View File

@ -0,0 +1,952 @@
package ru.dbotthepony.mc.otm.client.screen.panels
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.Font
import net.minecraft.client.gui.components.events.GuiEventListener
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.core.Logger
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.client.render.RenderHelper
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import kotlin.math.max
@JvmRecord
data class ScreenPos(val x: Float, val y: Float)
@JvmRecord
data class DockProperty @JvmOverloads constructor(val left: Float = 0f, val top: Float = 0f, val right: Float = 0f, val bottom: Float = 0f)
enum class Dock {
NONE, LEFT, RIGHT, TOP, BOTTOM, FILL
}
open class EditablePanel @JvmOverloads constructor(
@JvmField val screen: MatteryScreen<*>,
parent: EditablePanel?,
// относительно родителя
x: Float = 0f,
y: Float = 0f,
width: Float = 10f,
height: Float = 10f,
) : GuiEventListener {
var parent: EditablePanel? = null
set(value) {
if (field === value)
return
field?.onUnParent(this)
field = value
needsInvalidation = true
value?.onParent(this)
}
var x: Float = 0f
set(value) {
if (field == value) return
val old = field
field = value
needsInvalidation = true
xPosUpdated(value, old)
}
var y: Float = 0f
set(value) {
if (field == value) return
val old = field
field = value
needsInvalidation = true
yPosUpdated(value, old)
}
var width: Float = 10f
set(value) {
if (field == value) return
assert(value >= 0f) {"Invalid width $value"}
val old = field
field = value
needsInvalidation = true
widthUpdated(value, old)
}
var height: Float = 10f
set(value) {
if (field == value) return
assert(value >= 0f) {"Invalid height $value"}
val old = field
field = value
needsInvalidation = true
heightUpdated(value, old)
}
@JvmField
protected val children = ArrayList<EditablePanel>()
private var needsInvalidation = true
protected var visibleAsChildren: Boolean = true
private set
var visible: Boolean = true
set(value) {
if (field != value) {
val old = isVisible()
field = value
val new = isVisible()
if (old != new) {
visibilityChanges(new, old)
parent?.needsInvalidation = true
needsInvalidation = true
if (new) {
killFocus()
}
}
updateVisible()
}
}
// Позволяет смещать потомков на эту координату
var xOffset = 0f
var yOffset = 0f
// Обрезать отрисовку потомков?
var scissor = false
var dock = Dock.NONE
set(value) {
field = value
parent?.needsInvalidation = true
}
var dockMargin = DockProperty()
set(value) {
if (field != value) {
parent?.needsInvalidation = true
}
field = value
}
var dockPadding = DockProperty()
set(value) {
if (field != value) {
parent?.needsInvalidation = true
}
field = value
}
var acceptMouseInput = true
var acceptKeyboardInput = true
var ignoreMouseEventBoundaries = false
@JvmOverloads
fun setDockMargin(left: Float = 0f, top: Float = 0f, right: Float = 0f, bottom: Float = 0f) {
dockMargin = DockProperty(left, top, right, bottom)
}
@JvmOverloads
fun setDockPadding(left: Float = 0f, top: Float = 0f, right: Float = 0f, bottom: Float = 0f) {
dockPadding = DockProperty(left, top, right, bottom)
}
// абсолютное начало координат этой панели и потомков
// негативно если потомок выходит за границы
var boundingX = 0f
private set
var boundingY = 0f
private set
var boundingWidth = 0f
private set
var boundingHeight = 0f
private set
// Абсолютная координата, обновляется на отрисовке
var absoluteX = 0f
private set
var absoluteY = 0f
private set
var isHovered = false
private set
fun unsetHovered() {
isHovered = false
}
var isFocused = false
set(value) {
if (field != value) {
val old = field
field = value
onFocusChanged(old, value)
findAbsoluteRoot().updateFocus()
}
}
var autoKillFocus = false
protected set
private var focusedAsParent = false
var accumulatedDepth = 0f
fun accumulate3DHeight(value: Float) {
accumulatedDepth += value
}
fun font(): Font {
return screen.font
}
fun invalidateLayout() {
needsInvalidation = true
}
fun most3DHeight(): Float {
var depth = accumulatedDepth
for (child in children) {
depth = max(depth, child.most3DHeight())
}
return depth
}
init {
this.x = x
this.y = y
this.width = width
this.height = height
this.parent = parent
}
private fun onParent(child: EditablePanel) {
if (children.contains(child)) throw IllegalStateException("Already containing this child")
children.add(child)
needsInvalidation = true
updateVisible()
}
private fun onUnParent(child: EditablePanel) {
if (!children.contains(child)) throw IllegalStateException("Already not containing this child")
children.remove(child)
needsInvalidation = true
updateVisible()
}
protected open fun innerRender(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float) {}
protected open fun innerRenderTooltips(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float): Boolean {
return false
}
fun isVisible(): Boolean {
return visible && visibleAsChildren
}
fun render(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float): Float {
if (!isVisible()) {
return 0f
}
var depth = 0f
if (needsInvalidation) {
needsInvalidation = false
performLayout()
}
val parent = this.parent
if (parent == null) {
absoluteX = x
absoluteY = y
} else {
isHovered = parent.isHovered &&
mouse_x >= absoluteX &&
mouse_x <= absoluteX + width &&
mouse_y >= absoluteY &&
mouse_y <= absoluteY + height
}
val scissor = this.scissor
if (scissor) {
val scale = Minecraft.getInstance().window.guiScale
RenderHelper.pushScissorRect(
(absoluteX * scale).toInt(),
(absoluteY * scale).toInt(),
(width * scale).toInt(),
(height * scale).toInt(),
)
}
stack.pushPose()
stack.translate(absoluteX.toDouble(), absoluteY.toDouble(), accumulatedDepth.toDouble())
innerRender(stack, mouse_x, mouse_y, flag)
stack.popPose()
for (child in children) {
if (child.isVisible()) {
child.accumulatedDepth = accumulatedDepth + 1
child.absoluteX = absoluteX + child.x + xOffset
child.absoluteY = absoluteY + child.y + yOffset
RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
depth = max(depth, child.render(stack, mouse_x, mouse_y, flag))
}
}
if (scissor) {
RenderHelper.popScissorRect()
}
return depth
}
open fun tickHover(mouse_x: Float, mouse_y: Float): Boolean {
isHovered =
mouse_x >= absoluteX &&
mouse_x <= absoluteX + width &&
mouse_y >= absoluteY &&
mouse_y <= absoluteY + height
return isHovered
}
fun renderTooltips(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float): Boolean {
if (!isVisible()) {
return false
}
if (innerRenderTooltips(stack, mouse_x, mouse_y, flag)) {
return true
}
for (child in children) {
if (child.isVisible() && child.renderTooltips(stack, mouse_x, mouse_y, flag)) {
return true
}
}
return false
}
@JvmOverloads
fun localToScreen(_x: Float = 0f, _y: Float = 0f): ScreenPos {
var parent = this.parent
var x = _x
var y = _y
while (parent != null) {
x += parent.x + parent.xOffset
y += parent.y + parent.yOffset
parent = parent.parent
}
return ScreenPos(x, y)
}
fun screenToLocal(_x: Float = 0f, _y: Float = 0f): ScreenPos {
val pos = localToScreen()
return ScreenPos(_x - pos.x, _y - pos.y)
}
fun screenToLocal(_x: Double = 0.0, _y: Double = 0.0): ScreenPos {
val pos = localToScreen()
return ScreenPos((_x - pos.x).toFloat(), (_y - pos.y).toFloat())
}
fun findRoot(): EditablePanel? {
var parent = this.parent
if (parent == null) {
return null
}
while (true) {
val parent2 = parent!!.parent
if (parent2 != null) {
parent = parent2
} else {
return parent
}
}
}
fun findAbsoluteRoot(): EditablePanel {
return findRoot() ?: this
}
protected open fun performLayout() {
var left = dockPadding.left
var right = dockPadding.right
var top = dockPadding.top
var bottom = dockPadding.bottom
for (child in children) {
if (child.isVisible()) {
when (child.dock) {
Dock.NONE -> {}
Dock.FILL -> {}
Dock.LEFT -> {
child.setPos(left + child.dockMargin.left, top + child.dockMargin.top)
left += child.width + child.dockMargin.left + child.dockMargin.right
child.height = (
Math.max(
1f,
height - top - bottom - child.dockMargin.top - child.dockMargin.bottom
)
)
}
Dock.RIGHT -> {
child.setPos(
width - right - child.width - child.dockMargin.right,
top + child.dockMargin.top
)
right += child.width + child.dockMargin.left + child.dockMargin.right
child.height = (
Math.max(
1f,
height - top - bottom - child.dockMargin.top - child.dockMargin.bottom
)
)
}
Dock.TOP -> {
child.setPos(left + child.dockMargin.left, top + child.dockMargin.top)
top += child.height + child.dockMargin.top + child.dockMargin.bottom
child.width = (
Math.max(
1f,
width - left - right - child.dockMargin.left - child.dockMargin.right
)
)
}
Dock.BOTTOM -> {
child.setPos(
left + child.dockMargin.left,
height - bottom - child.height - child.dockMargin.bottom
)
bottom += child.height + child.dockMargin.top + child.dockMargin.bottom
child.width = (
Math.max(
1f,
width - left - right - child.dockMargin.left - child.dockMargin.right
)
)
}
}
}
}
for (child in children) {
if (child.isVisible() && child.dock == Dock.FILL) {
val w = width - child.dockMargin.left - child.dockMargin.right - right - left
val h = height - child.dockMargin.bottom - child.dockMargin.top - bottom - top
if (w < 1f || h < 1f) {
LOGGER.error("Unable to fit $child inside $this (FILL returned dimensions of $w $h)")
}
child.setDimensions(
left + child.dockMargin.left,
top + child.dockMargin.top,
Math.max(1f, w),
Math.max(1f, h)
)
}
}
boundingX = 0f
boundingY = 0f
boundingWidth = 0f
boundingHeight = 0f
for (child in children) {
if (child.isVisible()) {
boundingX = boundingX.coerceAtMost(child.x)
boundingY = boundingY.coerceAtMost(child.y)
boundingWidth = boundingWidth.coerceAtLeast(child.x + child.width)
boundingHeight = boundingHeight.coerceAtLeast(child.y + child.height)
}
}
}
companion object {
private val LOGGER = LogManager.getLogger()!!
}
protected open fun visibilityChanges(new: Boolean, old: Boolean) {
}
private fun updateVisible() {
for (child in children) {
val old = child.isVisible()
child.visibleAsChildren = isVisible()
val new = child.isVisible()
if (old != new) {
child.visibilityChanges(new, old)
}
child.updateVisible()
}
}
private fun killFocusInternal() {
for (child in children) {
child.killFocusInternal()
}
if (isFocused) {
isFocused = false
}
}
fun killFocus() {
if (isEverFocused()) {
killFocusInternal()
findAbsoluteRoot().updateFocus()
}
}
fun findHierarchicalFocus(): EditablePanel? {
if (isFocused) {
return this
}
for (child in children) {
val focus = child.findHierarchicalFocus()
if (focus != null) {
return focus
}
}
return null
}
fun hasHierarchicalFocus(): Boolean {
return findHierarchicalFocus() != null
}
protected open fun onHierarchicalFocusChanged(new: Boolean, old: Boolean) {
}
protected open fun onFocusChanged(new: Boolean, old: Boolean) {
}
private fun updateFocus() {
val old = focusedAsParent
focusedAsParent = hasHierarchicalFocus()
if (focusedAsParent != old) {
onHierarchicalFocusChanged(focusedAsParent, old)
}
for (child in children) {
child.updateFocus()
}
}
fun isEverFocused(): Boolean {
return isFocused || focusedAsParent
}
fun requestFocus() {
if (isFocused) {
return
}
if (focusedAsParent) {
var child = findHierarchicalFocus()
while (child != null) {
child.isFocused = false
child = findHierarchicalFocus()
}
}
isFocused = true
}
protected open fun xPosUpdated(new: Float, old: Float) {}
protected open fun yPosUpdated(new: Float, old: Float) {}
protected open fun widthUpdated(new: Float, old: Float) {}
protected open fun heightUpdated(new: Float, old: Float) {}
fun setPos(x: Float, y: Float) {
this.x = x
this.y = y
}
fun setPos(x: Double, y: Double) {
this.x = x.toFloat()
this.y = y.toFloat()
}
fun setSize(w: Float, h: Float) {
this.width = w
this.height = h
}
fun setSize(w: Double, h: Double) {
this.width = w.toFloat()
this.height = h.toFloat()
}
fun setDimensions(x: Float, y: Float, w: Float, h: Float) {
setPos(x, y)
setSize(w, h)
}
fun setDimensions(x: Double, y: Double, w: Double, h: Double) {
setPos(x, y)
setSize(w, h)
}
fun fetchChildren(): List<EditablePanel> {
return java.util.List.copyOf(children)
}
fun getUndockedChildren(): List<EditablePanel> {
var count = 0
for (child in children) {
if (child.dock == Dock.NONE) {
count++
}
}
val list = ArrayList<EditablePanel>(count)
for (child in children) {
if (child.dock == Dock.NONE) {
list.add(child)
}
}
return list
}
operator fun get(int: Int): EditablePanel? {
if (int < 0 || int >= children.size) return null
return children[int]
}
fun isIgnoringMouseEventBoundaries(): Boolean {
if (ignoreMouseEventBoundaries) {
return true
}
for (child in children) {
if (child.isIgnoringMouseEventBoundaries()) {
return true
}
}
return false
}
override fun mouseMoved(p_94758_: Double, p_94759_: Double) {
}
protected open fun mouseClickedInner(mouse_x: Double, mouse_y: Double, flag: Int): Boolean {
return true
}
fun withinBounds(mouse_x: Double, mouse_y: Double): Boolean {
val pos: ScreenPos = localToScreen()
return pos.x <= mouse_x && pos.x + width >= mouse_x && pos.y <= mouse_y && pos.y + height >= mouse_y
}
fun withinExtendedBounds(mouse_x: Double, mouse_y: Double): Boolean {
val pos: ScreenPos = localToScreen(boundingX, boundingY)
return pos.x <= mouse_x && pos.x + boundingWidth >= mouse_x && pos.y <= mouse_y && pos.y + boundingHeight >= mouse_y
}
final override fun mouseClicked(mouse_x: Double, mouse_y: Double, flag: Int): Boolean {
if (!isVisible() || !acceptMouseInput) return false
if (ignoreMouseEventBoundaries) return mouseClickedInner(mouse_x, mouse_y, flag)
for (child in children) {
if (child.mouseClickedChecked(mouse_x, mouse_y, flag)) {
return true
} else if (child.autoKillFocus) {
child.killFocus()
}
}
return mouseClickedInner(mouse_x, mouse_y, flag)
}
fun mouseClickedChecked(mouse_x: Double, mouse_y: Double, flag: Int): Boolean {
if (!isVisible() || !acceptMouseInput) return false
if (isIgnoringMouseEventBoundaries() || withinBounds(mouse_x, mouse_y)) {
if (acceptMouseInput && parent == null) screen.popup(this)
return mouseClicked(mouse_x, mouse_y, flag)
} else if (withinExtendedBounds(mouse_x, mouse_y)) {
for (child in children) {
if (child.mouseClickedChecked(mouse_x, mouse_y, flag)) {
return true
} else if (child.autoKillFocus) {
child.killFocus()
}
}
if (autoKillFocus) killFocus()
} else if (autoKillFocus) {
killFocus()
}
return false
}
protected open fun mouseReleasedInner(mouse_x: Double, mouse_y: Double, flag: Int): Boolean {
return true
}
final override fun mouseReleased(mouse_x: Double, mouse_y: Double, flag: Int): Boolean {
if (!isVisible() || !acceptMouseInput) return false
if (ignoreMouseEventBoundaries) return mouseReleasedInner(mouse_x, mouse_y, flag)
for (child in children) {
if (child.mouseReleasedChecked(mouse_x, mouse_y, flag)) {
return true
}
}
return mouseReleasedInner(mouse_x, mouse_y, flag)
}
fun mouseReleasedChecked(mouse_x: Double, mouse_y: Double, flag: Int): Boolean {
if (!isVisible() || !acceptMouseInput) return false
if (isIgnoringMouseEventBoundaries() || withinBounds(mouse_x, mouse_y)) {
return mouseReleased(mouse_x, mouse_y, flag)
} else if (withinExtendedBounds(mouse_x, mouse_y)) {
for (child in children) {
if (child.mouseReleasedChecked(mouse_x, mouse_y, flag)) {
return true
}
}
}
return false
}
protected open fun mouseDraggedInner(
mouse_x: Double,
mouse_y: Double,
flag: Int,
drag_x: Double,
drag_y: Double
): Boolean {
return true
}
final override fun mouseDragged(mouse_x: Double, mouse_y: Double, flag: Int, drag_x: Double, drag_y: Double): Boolean {
if (!isVisible() || !acceptMouseInput) return false
if (ignoreMouseEventBoundaries) return mouseDraggedInner(mouse_x, mouse_y, flag, drag_x, drag_y)
for (child in children) {
if (child.mouseDraggedChecked(mouse_x, mouse_y, flag, drag_x, drag_y)) {
return true
}
}
return mouseDraggedInner(mouse_x, mouse_y, flag, drag_x, drag_y)
}
fun mouseDraggedChecked(mouse_x: Double, mouse_y: Double, flag: Int, drag_x: Double, drag_y: Double): Boolean {
if (!isVisible() || !acceptMouseInput) return false
if (isIgnoringMouseEventBoundaries() || withinBounds(mouse_x, mouse_y)) {
return mouseDragged(mouse_x, mouse_y, flag, drag_x, drag_y)
} else if (withinExtendedBounds(mouse_x, mouse_y)) {
for (child in children) {
if (child.mouseDraggedChecked(mouse_x, mouse_y, flag, drag_x, drag_y)) {
return true
}
}
}
return false
}
protected open fun mouseScrolledInner(mouse_x: Double, mouse_y: Double, scroll: Double): Boolean {
return true
}
final override fun mouseScrolled(mouse_x: Double, mouse_y: Double, scroll: Double): Boolean {
if (!isVisible() || !acceptMouseInput) return false
if (ignoreMouseEventBoundaries) return mouseScrolledInner(mouse_x, mouse_y, scroll)
for (child in children) {
if (child.mouseScrolledChecked(mouse_x, mouse_y, scroll)) {
return true
}
}
return mouseScrolledInner(mouse_x, mouse_y, scroll)
}
fun mouseScrolledChecked(mouse_x: Double, mouse_y: Double, scroll: Double): Boolean {
if (!isVisible() || !acceptMouseInput) return false
if (isIgnoringMouseEventBoundaries() || withinBounds(mouse_x, mouse_y)) {
return mouseScrolled(mouse_x, mouse_y, scroll)
} else if (withinExtendedBounds(mouse_x, mouse_y)) {
for (child in children) {
if (child.mouseScrolledChecked(mouse_x, mouse_y, scroll)) {
return true
}
}
}
return false
}
protected open fun keyPressedInternal(p_94745_: Int, p_94746_: Int, p_94747_: Int): Boolean {
return false
}
final override fun keyPressed(p_94745_: Int, p_94746_: Int, p_94747_: Int): Boolean {
if (!isVisible() || !acceptKeyboardInput) return false
if (!focusedAsParent) return false
if (isFocused) return keyPressedInternal(p_94745_, p_94746_, p_94747_)
for (child in children) {
if (child.keyPressed(p_94745_, p_94746_, p_94747_)) {
return true
}
}
return false
}
protected open fun keyReleasedInternal(p_94750_: Int, p_94751_: Int, p_94752_: Int): Boolean {
return false
}
final override fun keyReleased(p_94750_: Int, p_94751_: Int, p_94752_: Int): Boolean {
if (!isVisible() || !acceptKeyboardInput) return false
if (!focusedAsParent) return false
if (isFocused) return keyReleasedInternal(p_94750_, p_94751_, p_94752_)
for (child in children) {
if (child.keyReleased(p_94750_, p_94751_, p_94752_)) {
return true
}
}
return false
}
protected open fun charTypedInternal(p_94732_: Char, p_94733_: Int): Boolean {
return false
}
final override fun charTyped(p_94732_: Char, p_94733_: Int): Boolean {
if (!isVisible() || !acceptKeyboardInput) return false
if (!focusedAsParent) return false
if (isFocused) return charTypedInternal(p_94732_, p_94733_)
for (child in children) {
if (child.charTyped(p_94732_, p_94733_)) {
return true
}
}
return true
}
override fun changeFocus(p_94756_: Boolean): Boolean {
return if (!isVisible()) false else super.changeFocus(p_94756_)
}
final override fun isMouseOver(
mouse_x: Double,
mouse_y: Double
): Boolean { // called to check whenever we are hovering at this
if (!isVisible() || !acceptMouseInput) return false
if (isIgnoringMouseEventBoundaries()) return true
val pos = localToScreen()
return mouse_x >= pos.x && mouse_x <= pos.x + width && mouse_y >= pos.y && mouse_y + height <= pos.y
}
open fun tick() {
for (child in children) {
child.tick()
}
}
var isRemoved = false
private set
protected open fun onRemoved() {}
fun remove() {
if (isRemoved) {
return
}
killFocus()
screen.removePanel(this)
for (child in children) {
child.remove()
}
onRemoved()
isRemoved = true
}
fun asGrid(): FlexGridPanel {
val grid = FlexGridPanel(screen, parent, x, y, width, height)
parent = grid
grid.dock = dock
dock = Dock.NONE
grid.dockPadding = dockPadding
grid.dockMargin = dockMargin
setDockPadding(0f, 0f, 0f, 0f)
setDockMargin(0f, 0f, 0f, 0f)
return grid
}
}

View File

@ -0,0 +1,175 @@
package ru.dbotthepony.mc.otm.client.screen.widget
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.TranslatableComponent
import ru.dbotthepony.mc.otm.client.render.RenderHelper
import ru.dbotthepony.mc.otm.client.render.SkinElement
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.menu.FormattingHelper
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
class PowerGaugePanel @JvmOverloads constructor(
screen: MatteryScreen<*>,
parent: EditablePanel? = null,
val widget: LevelGaugeWidget,
x: Float = 0f,
y: Float = 0f
): EditablePanel(screen, parent, x, y, width = GAUGE_BACKGROUND.rect_w + 1, height = GAUGE_BACKGROUND.rect_h + 1) {
init {
scissor = true
}
override fun innerRender(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float) {
GAUGE_BACKGROUND.render(stack, x, y)
GAUGE_FOREGROUND.render(stack, x, y)
}
override fun innerRenderTooltips(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float): Boolean {
if (isHovered) {
val tooltip = listOf(
TranslatableComponent("otm.gui.power.percentage_level", String.format("%.2f", widget.percentage() * 100.0)),
FormattingHelper.formatPowerLevel(widget.level(), widget.maxLevel())
)
screen.renderComponentTooltip(stack, tooltip, mouse_x.toInt(), mouse_y.toInt())
return true
}
return false
}
companion object {
val GAUGE_BACKGROUND = SkinElement(image_x = 0f, image_y = 48f, rect_w = 9f, rect_h = 48f)
val GAUGE_FOREGROUND = SkinElement(image_x = 9f, image_y = 48f, rect_w = 9f, rect_h = 48f)
}
}
class MatterGaugePanel @JvmOverloads constructor(
screen: MatteryScreen<*>,
parent: EditablePanel? = null,
val widget: LevelGaugeWidget,
x: Float = 0f,
y: Float = 0f
): EditablePanel(screen, parent, x, y, width = GAUGE_BACKGROUND.rect_w + 1, height = GAUGE_BACKGROUND.rect_h + 1) {
init {
scissor = true
}
override fun innerRender(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float) {
GAUGE_BACKGROUND.render(stack, x, y)
GAUGE_FOREGROUND.render(stack, x, y)
}
override fun innerRenderTooltips(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float): Boolean {
if (isHovered) {
val tooltip = listOf(
TranslatableComponent("otm.gui.matter.percentage_level", String.format("%.2f", widget.percentage() * 100.0)),
FormattingHelper.formatMatterLevel(widget.level(), widget.maxLevel())
)
screen.renderComponentTooltip(stack, tooltip, mouse_x.toInt(), mouse_y.toInt())
return true
}
return false
}
companion object {
val GAUGE_BACKGROUND = SkinElement(image_x = 0f, image_y = 48f, rect_w = 9f, rect_h = 48f)
val GAUGE_FOREGROUND = SkinElement(image_x = 9f, image_y = 48f, rect_w = 9f, rect_h = 48f)
}
}
class PatternGaugePanel @JvmOverloads constructor(
screen: MatteryScreen<*>,
parent: EditablePanel? = null,
val widget: LevelGaugeWidget,
x: Float = 0f,
y: Float = 0f
): EditablePanel(screen, parent, x, y, width = GAUGE_BACKGROUND.rect_w + 1, height = GAUGE_BACKGROUND.rect_h + 1) {
init {
scissor = true
}
override fun innerRender(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float) {
GAUGE_BACKGROUND.render(stack, x, y)
GAUGE_FOREGROUND.render(stack, x, y)
}
override fun innerRenderTooltips(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float): Boolean {
if (isHovered) {
val tooltip = listOf(
TranslatableComponent("otm.gui.pattern.percentage_level", String.format("%.2f", widget.percentage() * 100.0)),
TranslatableComponent("otm.gui.pattern.format", widget.level().decimalString(), widget.maxLevel().decimalString())
)
screen.renderComponentTooltip(stack, tooltip, mouse_x.toInt(), mouse_y.toInt())
return true
}
return false
}
companion object {
val GAUGE_BACKGROUND = SkinElement(image_x = 0f, image_y = 148f, rect_w = 9f, rect_h = 48f)
val GAUGE_FOREGROUND = SkinElement(image_x = 9f, image_y = 148f, rect_w = 9f, rect_h = 48f)
}
}
class ProgressGaugePanel @JvmOverloads constructor(
screen: MatteryScreen<*>,
parent: EditablePanel? = null,
val widget: ProgressGaugeWidget,
x: Float = 0f,
y: Float = 0f
): EditablePanel(screen, parent, x, y, width = GAUGE_BACKGROUND.rect_w + 1, height = GAUGE_BACKGROUND.rect_h + 1) {
init {
scissor = true
}
override fun innerRender(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float) {
GAUGE_BACKGROUND.render(stack, x, y)
GAUGE_FOREGROUND.render(stack, x, y)
}
override fun innerRenderTooltips(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float): Boolean {
if (isHovered) {
val tooltip: List<Component>
if (widget.isStuck()) {
tooltip = listOf(
TranslatableComponent(
"otm.gui.progress_widget",
String.format("%.2f", widget.percentage() * 100f)
),
TranslatableComponent("otm.gui.progress_widget_stuck").withStyle(ChatFormatting.DARK_RED)
)
} else {
tooltip = listOf(
TranslatableComponent(
"otm.gui.progress_widget",
String.format("%.2f", widget.percentage() * 100f)
)
)
}
screen.renderComponentTooltip(stack, tooltip, mouse_x.toInt(), mouse_y.toInt())
return true
}
return false
}
companion object {
val GAUGE_BACKGROUND = SkinElement(image_x = 0f, image_y = 132f, rect_w = 22f, rect_h = 16f)
val GAUGE_FOREGROUND = SkinElement(image_x = 22f, image_y = 132f, rect_w = 22f, rect_h = 16f)
}
}

View File

@ -501,10 +501,23 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @
return ZERO
}
// Позволяет получить процент от деления данного на divisor с точностью до 5 цифр
fun percentage(divisor: Fraction): Float {
val mul = (this * TEN_THOUSAND) / divisor
return mul.wholePart().toFloat() / 10_000f
}
companion object {
@JvmField
val ZERO = Fraction(BigInteger.ZERO)
@JvmField
val ONE_HUNDRED = Fraction(BigInteger.valueOf(100))
@JvmField
val TEN_THOUSAND = Fraction(BigInteger.valueOf(10_000))
@JvmField
val HALF = Fraction(BigInteger.ONE, BigInteger.TWO)

View File

@ -8,7 +8,7 @@ import ru.dbotthepony.mc.otm.Registry
import ru.dbotthepony.mc.otm.block.entity.BlockEntityChemicalGenerator
import ru.dbotthepony.mc.otm.menu.data.IntDataContainer
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot
import ru.dbotthepony.mc.otm.menu.widget.BatteryLevelWidget
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
class ChemicalGeneratorMenu @JvmOverloads constructor(id: Int, inv: Inventory, tile: BlockEntityChemicalGenerator? = null)
@ -22,7 +22,7 @@ class ChemicalGeneratorMenu @JvmOverloads constructor(id: Int, inv: Inventory, t
}
val progress = ProgressGaugeWidget(this) { 1f - tile!!.working_ticks.toFloat() / tile.working_ticks_total }
val energy = if (tile != null) BatteryLevelWidget(this, tile.energy) else BatteryLevelWidget(this)
val energy = LevelGaugeWidget(this, tile?.energy)
val burn_time = IntDataContainer()
init {

View File

@ -0,0 +1,308 @@
package ru.dbotthepony.mc.otm.menu
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.*
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.entity.BlockEntity
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot
import ru.dbotthepony.mc.otm.menu.widget.AbstractWidget
import java.util.function.Consumer
@JvmRecord
data class MoveResult(val merge_occured: Boolean, val remaining: ItemStack, val changed_slots: Set<Slot>)
abstract class MatteryMenu protected @JvmOverloads constructor(
p_38851_: MenuType<*>?,
p_38852_: Int,
@JvmField val inventory: Inventory,
tile: BlockEntity? = null
) : AbstractContainerMenu(p_38851_, p_38852_) {
@JvmField
val tile: BlockEntity?
@JvmField
val ply: Player = inventory.player
@JvmField
val mattery_widgets = ArrayList<AbstractWidget>()
@JvmField
val inventory_slots = ArrayList<MatterySlot>()
@JvmField
val main_slots = ArrayList<MatterySlot>()
@JvmField
protected val locked_inventory_slots: MutableSet<Int> = HashSet()
protected fun isInventorySlotLocked(index: Int): Boolean = locked_inventory_slots.contains(index)
@JvmField
protected var synchronizer: ContainerSynchronizer? = null
override fun setSynchronizer(p_150417_: ContainerSynchronizer) {
synchronizer = p_150417_
super.setSynchronizer(p_150417_)
}
fun addWidget(widget: AbstractWidget, consumer: Consumer<Consumer<ContainerData>>) {
if (!mattery_widgets.contains(widget)) {
mattery_widgets.add(widget)
consumer.accept(Consumer { p_38885_: ContainerData -> addDataSlots(p_38885_) })
}
}
fun addMainSlot(slot: MatterySlot): MatterySlot {
addSlot(slot)
main_slots.add(slot)
return slot
}
@JvmField
protected var inventory_slot_index_start = 0
@JvmField
protected var inventory_slot_index_end = 0
init {
this.tile = tile
}
@JvmOverloads
protected fun addInventorySlots(offset: Int = 97) {
var first = true
for (i in 0..2) {
for (j in 0..8) {
val slot: MatterySlot = object : MatterySlot(inventory, j + i * 9 + 9, 8 + j * 18, 14 + i * 18) {
override fun mayPlace(p_40231_: ItemStack): Boolean {
return !isInventorySlotLocked(index)
}
override fun mayPickup(p_40228_: Player): Boolean {
return !isInventorySlotLocked(index)
}
}
inventory_slots.add(slot)
addSlot(slot)
if (first) {
first = false
inventory_slot_index_start = slot.index
}
}
}
var last: MatterySlot? = null
for (k in 0..8) {
last = object : MatterySlot(inventory, k, 8 + k * 18, 14 + 58) {
override fun mayPlace(p_40231_: ItemStack): Boolean {
return !isInventorySlotLocked(index)
}
override fun mayPickup(p_40228_: Player): Boolean {
return !isInventorySlotLocked(index)
}
}
addSlot(last)
inventory_slots.add(last)
}
inventory_slot_index_end = last!!.index
}
override fun broadcastChanges() {
for (widget in mattery_widgets) {
widget.updateServer()
}
super.broadcastChanges()
}
override fun broadcastFullState() {
for (widget in mattery_widgets) {
widget.updateServer()
}
super.broadcastFullState()
}
override fun stillValid(player: Player): Boolean {
if (tile == null) return true
if (player.level.getBlockEntity(tile.blockPos) !== tile) {
return false
}
val pos = tile.blockPos
return player.distanceToSqr(pos.x.toDouble() + 0.5, pos.y.toDouble() + 0.5, pos.z.toDouble() + 0.5) <= 64.0
}
protected abstract fun getWorkingSlotStart(): Int
protected abstract fun getWorkingSlotEnd(): Int
// This method receive Player interactor and slot_index where Shift + Right click occurred
// It shall return item stack that got moved
override fun quickMoveStack(ply: Player, slot_index: Int): ItemStack {
// this.moveItemStackTo(ItemStack, int start_slot_index, int end_slot_index, boolean iteration_order)
// returns boolean, telling whenever ItemStack was modified (moved or sharnk)
// false means nothing happened
// Last boolean determine order of slot iteration, where:
// if TRUE, iteration order is end_slot_index -> start_slot_index
// if FALSE iteration order is start_slot_index -> end_slot_index
val start = getWorkingSlotStart()
val end = getWorkingSlotEnd()
if (start == end) {
return ItemStack.EMPTY
}
var moved = ItemStack.EMPTY
val get_slot = slots[slot_index]
if (get_slot.hasItem()) {
val slot_item = get_slot.item
moved = slot_item.copy()
if (slot_index < inventory_slot_index_start) {
// Moving FROM machine TO inventory
if (!moveItemStackTo(slot_item, inventory_slot_index_start, inventory_slot_index_end + 1, false)) {
return ItemStack.EMPTY
}
} else if (!moveItemStackTo(slot_item, start, end, false)) {
// Moving FROM inventory TO machine
return ItemStack.EMPTY
}
if (slot_item.isEmpty) {
get_slot.set(ItemStack.EMPTY)
} else {
get_slot.setChanged()
}
}
return moved
}
fun quickMoveToInventory(stack: ItemStack, simulate: Boolean): MoveResult {
return if (inventory_slot_index_start == 0 && inventory_slot_index_end == 0) {
MoveResult(false, stack, java.util.Set.of<Slot>())
} else customMoveItemStackTo(
stack,
inventory_slot_index_start,
inventory_slot_index_end + 1,
false,
simulate
)
}
override fun moveItemStackTo(
stack_to_move: ItemStack,
initial_slot: Int,
final_slot: Int,
reverse_direction: Boolean
): Boolean {
val move_result = customMoveItemStackTo(stack_to_move, initial_slot, final_slot, reverse_direction, false)
val remaining: ItemStack = move_result.remaining
if (remaining.count == stack_to_move.count) return false
stack_to_move.count = remaining.count
return move_result.merge_occured
}
protected fun customMoveItemStackTo(
_stack_to_move: ItemStack,
initial_slot: Int,
final_slot: Int,
reverse_direction: Boolean,
simulate: Boolean
): MoveResult {
var merge_occured = false
var i = if (reverse_direction) final_slot - 1 else initial_slot
val changed = HashSet<Slot>()
val stack_to_move = _stack_to_move.copy()
if (stack_to_move.isStackable) {
while (!stack_to_move.isEmpty) {
if (reverse_direction) {
if (i < initial_slot) {
break
}
} else if (i >= final_slot) {
break
}
val slot = slots[i]
val slot_stack = slot.item
if (!slot_stack.isEmpty && ItemStack.isSameItemSameTags(stack_to_move, slot_stack)) {
val j = slot_stack.count + stack_to_move.count
val maxSize = slot.getMaxStackSize(stack_to_move)
if (j <= maxSize) {
stack_to_move.count = 0
if (!simulate) {
slot_stack.count = j
slot.setChanged()
}
merge_occured = true
changed.add(slot)
} else if (slot_stack.count < maxSize) {
stack_to_move.shrink(maxSize - slot_stack.count)
if (!simulate) {
slot_stack.count = maxSize
slot.setChanged()
}
merge_occured = true
changed.add(slot)
}
}
i += if (reverse_direction) -1 else 1
}
}
if (!stack_to_move.isEmpty) {
i = if (reverse_direction) final_slot - 1 else initial_slot
while (true) {
if (reverse_direction) {
if (i < initial_slot) {
break
}
} else if (i >= final_slot) {
break
}
val slot = slots[i]
val slot_stack = slot.item
if (slot_stack.isEmpty && slot.mayPlace(stack_to_move)) {
if (!simulate) {
if (stack_to_move.count > slot.maxStackSize) {
slot.set(stack_to_move.split(slot.maxStackSize))
} else {
slot.set(stack_to_move.split(stack_to_move.count))
}
slot.setChanged()
}
merge_occured = true
changed.add(slot)
break
}
i += if (reverse_direction) -1 else 1
}
}
return MoveResult(merge_occured, stack_to_move, changed)
}
}

View File

@ -2,6 +2,26 @@ package ru.dbotthepony.mc.otm.menu.data
import net.minecraft.world.inventory.ContainerData
class BooleanDataContainer : ContainerData {
val buffer = intArrayOf(0)
var value: Boolean
get() = buffer[0] > 0
set(value) { buffer[0] = if (value) 1 else 0 }
override fun get(p_39284_: Int): Int {
return buffer[p_39284_]
}
override fun set(p_39285_: Int, p_39286_: Int) {
buffer[p_39285_] = p_39286_
}
override fun getCount(): Int {
return 1
}
}
class ShortDataContainer : ContainerData {
val buffer = intArrayOf(0)

View File

@ -0,0 +1,24 @@
package ru.dbotthepony.mc.otm.menu.widget
import net.minecraft.world.inventory.ContainerData
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import java.util.function.Consumer
abstract class AbstractWidget constructor(
@JvmField val menu: MatteryMenu,
) {
lateinit var data_registry: Consumer<ContainerData>
init {
menu.addWidget(this) {
data_registry = it
}
}
abstract fun updateServer()
protected fun addDataSlots(slots: ContainerData) {
data_registry.accept(slots)
}
}

View File

@ -0,0 +1,72 @@
package ru.dbotthepony.mc.otm.menu.widget
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.data.FractionDataContainer
import ru.dbotthepony.mc.otm.menu.data.IntDataContainer
import ru.dbotthepony.mc.otm.menu.data.ShortDataContainer
@Suppress("unused")
class LevelGaugeWidget(menu: MatteryMenu) : AbstractWidget(menu) {
@JvmField var level = {Fraction.ONE}
@JvmField var maxLevel = {Fraction.ONE}
@JvmField val levelContainer = FractionDataContainer()
@JvmField val maxLevelContainer = FractionDataContainer()
constructor(
menu: MatteryMenu,
power: IMatteryEnergyStorage?
) : this(menu) {
if (power == null) return
this.level = power::getBatteryLevel
this.maxLevel = power::getMaxBatteryLevel
}
constructor(
menu: MatteryMenu,
matter: IMatterHandler?
) : this(menu) {
if (matter == null) return
this.level = matter::getStoredMatter
this.maxLevel = matter::getMaxStoredMatter
}
constructor(
menu: MatteryMenu,
patterns: IPatternStorage?
) : this(menu) {
if (patterns == null) return
this.level = {Fraction(patterns.stored)}
this.maxLevel = {Fraction(patterns.capacity)}
}
constructor(
menu: MatteryMenu,
level: () -> Fraction,
maxLevel: () -> Fraction,
) : this(menu) {
this.level = level
this.maxLevel = maxLevel
}
init {
addDataSlots(levelContainer)
addDataSlots(maxLevelContainer)
}
override fun updateServer() {
levelContainer.value = level.invoke()
maxLevelContainer.value = maxLevel.invoke()
}
fun level(): Fraction = levelContainer.value
fun maxLevel(): Fraction = maxLevelContainer.value
fun percentage(): Float = levelContainer.value.percentage(maxLevelContainer.value)
}

View File

@ -0,0 +1,42 @@
package ru.dbotthepony.mc.otm.menu.widget
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.data.BooleanDataContainer
import ru.dbotthepony.mc.otm.menu.data.ShortDataContainer
@Suppress("unused")
class ProgressGaugeWidget(menu: MatteryMenu) : AbstractWidget(menu) {
@JvmField var progress = {0f}
@JvmField var stuck = {false}
@JvmField val progressContainer = ShortDataContainer()
@JvmField val stuckContainer = BooleanDataContainer()
init {
addDataSlots(progressContainer)
addDataSlots(stuckContainer)
}
constructor(
menu: MatteryMenu,
progress: () -> Float
) : this(menu) {
this.progress = progress
}
constructor(
menu: MatteryMenu,
progress: () -> Float,
stuck: () -> Boolean,
) : this(menu) {
this.progress = progress
this.stuck = stuck
}
override fun updateServer() {
progressContainer.value = (Math.max(Math.min(progress(), 1f), 0f) * 10_000f).toInt().toShort()
stuckContainer.value = stuck()
}
fun isStuck(): Boolean = stuckContainer.value
fun percentage(): Float = progressContainer.value / 10_000f
}