From 923d19bcc21312fd0d1e99aee012e2d9610997b3 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 20 Aug 2021 11:35:42 +0700 Subject: [PATCH] Panels test --- .../mc/otm/screen/MatteryScreen.java | 65 ++ .../mc/otm/screen/RenderHelper.java | 59 +- .../mc/otm/screen/panels/Dock.java | 10 + .../mc/otm/screen/panels/EditBoxPanel.java | 33 + .../mc/otm/screen/panels/EditablePanel.java | 759 ++++++++++++++++++ .../mc/otm/screen/panels/FramePanel.java | 86 ++ .../screen/panels/MinecraftWidgetPanel.java | 65 ++ 7 files changed, 1073 insertions(+), 4 deletions(-) create mode 100644 src/main/java/ru/dbotthepony/mc/otm/screen/panels/Dock.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditBoxPanel.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditablePanel.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/screen/panels/FramePanel.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/screen/panels/MinecraftWidgetPanel.java diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/MatteryScreen.java b/src/main/java/ru/dbotthepony/mc/otm/screen/MatteryScreen.java index 86c193c40..2f26b3aa4 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/screen/MatteryScreen.java +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/MatteryScreen.java @@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.screen; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.gui.Font; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.network.chat.Component; @@ -15,6 +16,9 @@ import ru.dbotthepony.mc.otm.menu.slot.MatterySlot; import ru.dbotthepony.mc.otm.menu.slot.MachineOutputSlot; import ru.dbotthepony.mc.otm.menu.slot.MatterContainerInputSlot; import ru.dbotthepony.mc.otm.menu.widget.AbstractWidget; +import ru.dbotthepony.mc.otm.screen.panels.EditablePanel; + +import java.util.ArrayList; public class MatteryScreen extends AbstractContainerScreen { protected static final ResourceLocation CONTAINER_BASE = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/generic_machine.png"); @@ -24,6 +28,8 @@ public class MatteryScreen extends AbstractContainerScree return CONTAINER_BASE; } + protected ArrayList panels = new ArrayList<>(); + public MatteryScreen(T p_97741_, Inventory p_97742_, Component p_97743_) { super(p_97741_, p_97742_, p_97743_); @@ -34,6 +40,61 @@ public class MatteryScreen extends AbstractContainerScree inventoryLabelY = imageHeight - 92; } + @Override + public boolean mouseClicked(double p_97748_, double p_97749_, int p_97750_) { + for (var panel : panels) { + if (panel.mouseClickedChecked(p_97748_, p_97749_, p_97750_)) { + return true; + } + } + + return super.mouseClicked(p_97748_, p_97749_, p_97750_); + } + + @Override + public boolean mouseDragged(double p_97752_, double p_97753_, int p_97754_, double p_97755_, double p_97756_) { + for (var panel : panels) { + if (panel.mouseDraggedChecked(p_97752_, p_97753_, p_97754_, p_97755_, p_97756_)) { + return true; + } + } + + return super.mouseDragged(p_97752_, p_97753_, p_97754_, p_97755_, p_97756_); + } + + @Override + public boolean mouseReleased(double p_97812_, double p_97813_, int p_97814_) { + for (var panel : panels) { + if (panel.mouseReleasedChecked(p_97812_, p_97813_, p_97814_)) { + return true; + } + } + + return super.mouseReleased(p_97812_, p_97813_, p_97814_); + } + + @Override + public boolean mouseScrolled(double p_94686_, double p_94687_, double p_94688_) { + for (var panel : panels) { + if (panel.mouseScrolledChecked(p_94686_, p_94687_, p_94688_)) { + return true; + } + } + + return super.mouseScrolled(p_94686_, p_94687_, p_94688_); + } + + @Override + public boolean keyPressed(int p_97765_, int p_97766_, int p_97767_) { + for (var panel : panels) { + if (panel.keyPressed(p_97765_, p_97766_, p_97767_)) { + return true; + } + } + + return super.keyPressed(p_97765_, p_97766_, p_97767_); + } + @Override protected void renderTooltip(PoseStack pose, int mouseX, int mouseY) { super.renderTooltip(pose, mouseX, mouseY); @@ -76,6 +137,10 @@ public class MatteryScreen extends AbstractContainerScree } + public Font getFont() { + return font; + } + @Override protected void renderBg(PoseStack pose, float p_97788_, int mouseX, int mouseY) { RenderSystem.setShader(GameRenderer::getPositionTexShader); diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/RenderHelper.java b/src/main/java/ru/dbotthepony/mc/otm/screen/RenderHelper.java index dc3eaccc3..5981036a3 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/screen/RenderHelper.java +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/RenderHelper.java @@ -19,6 +19,16 @@ public class RenderHelper { identity.setIdentity(); } + public static float depth_z = 0; + + public static void setUpcomingDepth(float depth) { + depth_z = depth; + } + + public static void clearUpcomingDepth() { + depth_z = 0; + } + // Regular functions /** @@ -50,10 +60,10 @@ public class RenderHelper { var builder = Tesselator.getInstance().getBuilder(); builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); - builder.vertex(matrix, x, y + height, 0).uv(u0, v1).endVertex(); - builder.vertex(matrix, x + width, y + height, 0).uv(u1, v1).endVertex(); - builder.vertex(matrix, x + width, y, 0).uv(u1, v0).endVertex(); - builder.vertex(matrix, x, y, 0).uv(u0, v0).endVertex(); + builder.vertex(matrix, x, y + height, depth_z).uv(u0, v1).endVertex(); + builder.vertex(matrix, x + width, y + height, depth_z).uv(u1, v1).endVertex(); + builder.vertex(matrix, x + width, y, depth_z).uv(u1, v0).endVertex(); + builder.vertex(matrix, x, y, depth_z).uv(u0, v0).endVertex(); builder.end(); BufferUploader.end(builder); } @@ -111,6 +121,31 @@ public class RenderHelper { drawTexturedRectUV(stack.last().pose(), x, y, width, height, u0, v0, u1, v1); } + /** + * @param stack stack to take transformation matrix from + * @param x position x on screen + * @param y position y on screen + * @param width drawn rectangle width + * @param height drawn rectangle height + * @param image_x absolute asset x, to compute U0 coordinate from + * @param image_y absolute asset y, to compute V0 coordinate from + * @param mapped_width absolute asset width, to compute U1 coordinate from + * @param mapped_height absolute asset height, to compute V1 coordinate from + */ + public static void drawTexturedRectAuto( + PoseStack stack, + float x, + float y, + float width, + float height, + float image_x, + float image_y, + float mapped_width, + float mapped_height + ) { + drawTexturedRectUV(stack.last().pose(), x, y, width, height, image_x / mapped_width, image_y / mapped_height, (image_x + width) / mapped_width, (image_y + height) / mapped_height); + } + /** * Draws a textured rectangle on screen * with matrix from pose @@ -255,6 +290,22 @@ public class RenderHelper { 256 ); + public static void drawRegularSlot( + PoseStack stack, + float x, + float y + ) { + drawTexturedRectAuto(stack, x, y, 18, 18, 0, 96, 256, 256); + } + + public static void drawBigSlot( + PoseStack stack, + float x, + float y + ) { + drawTexturedRectAuto(stack, x, y, 26, 26, 18, 96, 256, 256); + } + public static void drawWindowBackground( PoseStack stack, float x, diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/Dock.java b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/Dock.java new file mode 100644 index 000000000..1629c4156 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/Dock.java @@ -0,0 +1,10 @@ +package ru.dbotthepony.mc.otm.screen.panels; + +public enum Dock { + NONE, + LEFT, + RIGHT, + TOP, + BOTTOM, + FILL +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditBoxPanel.java b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditBoxPanel.java new file mode 100644 index 000000000..145de4e28 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditBoxPanel.java @@ -0,0 +1,33 @@ +package ru.dbotthepony.mc.otm.screen.panels; + +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import ru.dbotthepony.mc.otm.screen.MatteryScreen; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class EditBoxPanel extends MinecraftWidgetPanel { + public EditBoxPanel(@Nonnull MatteryScreen screen, @Nullable EditablePanel parent, float x, float y, float width, float height, Component component) { + super(screen, parent, x, y, width, height, (panel) -> { + return new EditBox(screen.getFont(), (int) panel.getRenderX(), (int) panel.getRenderY(), (int) panel.getWidth(), (int) panel.getHeight(), component); + }); + } + + @Override + protected void copyValues(EditBox new_widget, EditBox old_widget) { + new_widget.setValue(old_widget.getValue()); + } + + @Override + protected void onFocusChanged(boolean new_focused, boolean old_focused) { + widget.setFocus(new_focused); + } + + @Override + protected boolean mouseClickedInner(double mouse_x, double mouse_y, int flag) { + requestFocus(); + return widget.mouseClicked(mouse_x, mouse_y, flag); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditablePanel.java b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditablePanel.java new file mode 100644 index 000000000..ec327f813 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditablePanel.java @@ -0,0 +1,759 @@ +package ru.dbotthepony.mc.otm.screen.panels; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.gui.components.events.GuiEventListener; +import ru.dbotthepony.mc.otm.screen.MatteryScreen; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayList; + +/** + * Superclass of all panels + * This panel represent part of GMod's Panels API + * which allows much simpler GUI composition + */ +public class EditablePanel implements GuiEventListener { + public record ScreenPos(float x, float y) { + + } + + private EditablePanel parent; + public final MatteryScreen screen; + + protected boolean visible_internal = true; + private boolean visible = true; + + protected boolean focused = false; + private boolean focused_internal = false; + + // relative to parent + // updated inside performLayout of parent if docked + private float x; + private float y; + + // updated inside performLayout depending on dock + private float width; + private float height; + + // updated on each rendered frame + protected float parent_x; + protected float parent_y; + + private boolean needs_invalidation = false; + + private final ArrayList children = new ArrayList<>(); + + private Dock docking = Dock.NONE; + + public EditablePanel(@Nonnull MatteryScreen screen, @Nullable EditablePanel parent, float x, float y, float width, float height) { + this.parent = parent; + this.screen = screen; + this.x = x; + this.y = y; + this.width = width; + this.height = height; + + if (parent != null) + parent.onParent(this); + + invalidateLayout(); + } + + public float getRenderX() { + return parent_x; + } + + public float getRenderY() { + return parent_y; + } + + protected void innerRender(PoseStack stack, float mouse_x, float mouse_y, float flag) { + + } + + public void render(PoseStack stack, float mouse_x, float mouse_y, float flag) { + if (!getVisible()) { + return; + } + + if (needs_invalidation) { + needs_invalidation = false; + performLayout(); + } + + if (parent == null) { + parent_x = x; + parent_y = y; + } + + innerRender(stack, mouse_x, mouse_y, flag); + + for (var child : children) { + if (child.getVisible()) { + child.parent_x = parent_x + child.x; + child.parent_y = parent_y + child.y; + + child.render(stack, mouse_x, mouse_y, flag); + } + } + } + + public void setDocking(Dock docking) { + if (docking != this.docking) { + this.docking = docking; + + if (parent != null) + parent.invalidateLayout(); + } + } + + public static record DockProperty(float left, float top, float right, float bottom) { + public boolean equals(Object dock_margin) { + if (dock_margin instanceof DockProperty prop) { + return this == prop || left == prop.left && top == prop.top && right == prop.right && bottom == prop.bottom; + } + + return false; + } + } + + public DockProperty getDock_margin() { + return dock_margin; + } + + public DockProperty getDock_padding() { + return dock_padding; + } + + private DockProperty dock_margin = new DockProperty(0, 0, 0, 0); + private DockProperty dock_padding = new DockProperty(0, 0, 0, 0); + + public boolean setDockMargin(float left, float top, float right, float bottom) { + var dock = new DockProperty(left, top, right, bottom); + + if (!dock.equals(dock_margin)) { + dock_margin = dock; + + if (docking != Dock.NONE && parent != null) + parent.invalidateLayout(); + + return true; + } + + return false; + } + + public boolean setDockPadding(float left, float top, float right, float bottom) { + var dock = new DockProperty(left, top, right, bottom); + + if (!dock.equals(dock_padding)) { + dock_padding = dock; + invalidateLayout(); + return true; + } + + return false; + } + + public ScreenPos localToScreen(float x, float y) { + var get_parent = getParent(); + + while (get_parent != null) { + x += get_parent.getX(); + y += get_parent.getY(); + get_parent = get_parent.getParent(); + } + + return new ScreenPos(this.x + x, this.y + y); + } + + @Nullable + public EditablePanel getRootParent() { + if (getParent() == null) + return null; + + var get_parent = getParent(); + + while (true) { + var get_parent2 = get_parent.getParent(); + + if (get_parent2 != null) { + get_parent = get_parent2; + } else { + return get_parent; + } + } + } + + public EditablePanel getRootPanel() { + var get_parent = getRootParent(); + return get_parent != null ? get_parent : this; + } + + public ScreenPos localToScreen() { + return localToScreen(0, 0); + } + + public ScreenPos screenToLocal(float x, float y) { + var pos = localToScreen(); + return new ScreenPos(x - pos.x, y - pos.y); + } + + public ScreenPos screenToLocal(double x, double y) { + var pos = localToScreen(); + return new ScreenPos((float) (x - pos.x), (float) (y - pos.y)); + } + + public void invalidateLayout() { + needs_invalidation = true; + } + + public EditablePanel getParent() { + return parent; + } + + public boolean getVisible() { + return visible_internal && visible; + } + + public boolean getVisibleThis() { + return visible; + } + + protected void visibilityChanges(boolean new_visible, boolean old_visible) { + + } + + private void updateVisible() { + for (var child : children) { + var old_visible = child.getVisible(); + child.visible_internal = getVisible(); + var new_visible = child.getVisible(); + + if (old_visible != new_visible) { + child.visibilityChanges(new_visible, old_visible); + } + + child.updateVisible(); + } + } + + public void setVisible(boolean visible) { + if (this.visible != visible) { + var old_visible = getVisible(); + this.visible = visible; + var new_visible = getVisible(); + + if (old_visible != new_visible) { + visibilityChanges(new_visible, old_visible); + } + + updateVisible(); + } + } + + private boolean hasHierarchicalFocus() { + return getHierarchicalFocus() != null; + } + + @Nullable + private EditablePanel getHierarchicalFocus() { + if (focused) + return this; + + for (var child : children) { + if (child.focused) { + return child.getHierarchicalFocus(); + } + } + + return null; + } + + protected void onFocusChanged(boolean new_focused, boolean old_focused) { + + } + + private void updateFocused() { + var old_value = focused_internal; + focused_internal = hasHierarchicalFocus(); + + if (focused_internal != old_value) { + onFocusChanged(focused_internal, old_value); + } + + for (var child : children) { + child.updateFocused(); + } + } + + public boolean getFocused() { + return focused || focused_internal; + } + + public boolean getFocusedThis() { + return focused; + } + + public void setFocused(boolean focused) { + if (this.focused != focused) { + this.focused = focused; + getRootPanel().updateFocused(); + } + } + + /** + * Focuses this panel + */ + public void requestFocus() { + if (focused) + return; + + if (focused_internal) { + var child = getHierarchicalFocus(); + + while (child != null) { + child.setFocused(false); + child = getHierarchicalFocus(); + } + + setFocused(true); + } else { + setFocused(true); + } + } + + public void killFocus() { + if (this.focused_internal) { + var child = getHierarchicalFocus(); + + while (child != null) { + child.setFocused(false); + child = getHierarchicalFocus(); + } + + getRootPanel().updateFocused(); + } + } + + private void onParent(EditablePanel children) { + this.children.add(children); + updateVisible(); + invalidateLayout(); + } + + private void onUnparent(EditablePanel children) { + this.children.remove(children); + invalidateLayout(); + } + + public void setParent(@Nullable EditablePanel parent) { + if (this.parent != parent) { + invalidateLayout(); + + if (this.parent != null) + this.parent.onParent(this); + + this.parent = parent; + + if (parent != null) + parent.onParent(this); + } + } + + protected void xPosUpdated(float new_value, float old_value) {} + protected void yPosUpdated(float new_value, float old_value) {} + + protected void widthUpdated(float new_value, float old_value) {} + protected void heightUpdated(float new_value, float old_value) {} + + public void setPos(float x, float y) { + setX(x); + setY(y); + } + + public void setPos(double x, double y) { + setX((float) x); + setY((float) y); + } + + public void setSize(float w, float h) { + setWidth(w); + setHeight(h); + } + + public void setSize(double w, double h) { + setWidth((float) w); + setHeight((float) h); + } + + public void setDimensions(float x, float y, float w, float h) { + setPos(x, y); + setSize(w, h); + } + + public void setDimensions(double x, double y, double w, double h) { + setPos(x, y); + setSize(w, h); + } + + public float getX() { + return x; + } + + public void setX(float x) { + if (x != this.x) { + invalidateLayout(); + var old = this.x; + this.x = x; + xPosUpdated(x, old); + } + } + + public float getY() { + return y; + } + + public void setY(float y) { + if (y != this.y) { + invalidateLayout(); + var old = this.y; + this.y = y; + yPosUpdated(y, old); + } + } + + public float getWidth() { + return width; + } + + public void setWidth(float width) { + if (width != this.width) { + invalidateLayout(); + var old = this.width; + this.width = width; + widthUpdated(width, old); + } + } + + public float getHeight() { + return height; + } + + public void setHeight(float height) { + if (height != this.height) { + invalidateLayout(); + var old = this.height; + this.height = height; + heightUpdated(height, old); + } + } + + protected void performLayout() { + var dock_left = dock_padding.left; + var dock_right = dock_padding.right; + var dock_top = dock_padding.top; + var dock_bottom = dock_padding.bottom; + + // determine sizes + for (var child : children) { + switch (child.docking) { + case TOP -> dock_top += child.height + child.dock_margin.top; + case BOTTOM -> dock_bottom += child.height + child.dock_margin.bottom; + case LEFT -> dock_left += child.width + child.dock_margin.left; + case RIGHT -> dock_right += child.width + child.dock_margin.right; + } + } + + var dock_left2 = dock_padding.left; + var dock_right2 = dock_padding.right; + var dock_top2 = dock_padding.top; + var dock_bottom2 = dock_padding.bottom; + + // apply values + for (var child : children) { + switch (child.docking) { + case TOP -> { + child.setPos(dock_left + child.dock_margin.left, dock_top2 + child.dock_margin.top); + dock_top2 += child.height + child.dock_margin.top + child.dock_margin.bottom; + child.setWidth(Math.max(1, width - dock_left - dock_right - child.dock_margin.left - child.dock_margin.right)); + } + + case BOTTOM -> { + child.setPos(dock_left + child.dock_margin.left, height - dock_bottom2 - child.height - child.dock_margin.bottom); + dock_bottom2 += child.height + child.dock_margin.top + child.dock_margin.bottom; + child.setWidth(Math.max(1, width - dock_left - dock_right - child.dock_margin.left - child.dock_margin.right)); + } + + case LEFT -> { + child.setPos(dock_left2 + child.dock_margin.left, dock_top + child.dock_margin.top); + dock_left2 += child.width + child.dock_margin.left + child.dock_margin.right; + child.setHeight(Math.max(1, height - dock_top - dock_bottom - child.dock_margin.top - child.dock_margin.bottom)); + } + + case RIGHT -> { + child.setPos(width - dock_right2 - child.width - child.dock_margin.right, dock_top + child.dock_margin.top); + dock_right2 += child.width + child.dock_margin.left + child.dock_margin.right; + child.setHeight(Math.max(1, height - dock_top - dock_bottom - child.dock_margin.top - child.dock_margin.bottom)); + } + } + } + } + + private boolean accept_mouse_input = true; + private boolean accept_keyboard_input = true; + private boolean ignore_mouse_event_boundaries = false; + + public boolean getMouseInputEnabled() { + return accept_mouse_input; + } + + public void setMouseInputEnabled(boolean value) { + accept_mouse_input = value; + } + + public boolean getKeyboardInputEnabled() { + return accept_keyboard_input; + } + + public void setKeyboardInputEnabled(boolean value) { + accept_keyboard_input = value; + } + + public boolean getIgnoreMouseEventBoundaries() { + if (ignore_mouse_event_boundaries) { + return true; + } + + for (var child : children) { + if (child.getIgnoreMouseEventBoundaries()) { + return true; + } + } + + return false; + } + + // for use when this panel want to attain global focus + // such as when it is being dragged + public void setIgnoreMouseEventBoundaries(boolean value) { + ignore_mouse_event_boundaries = value; + } + + protected boolean auto_kill_focus = true; + + @Override + public void mouseMoved(double p_94758_, double p_94759_) { + + } + + protected boolean mouseClickedInner(double mouse_x, double mouse_y, int flag) { + return false; + } + + @Override + public boolean mouseClicked(double mouse_x, double mouse_y, int flag) { + if (!getVisible() || !getMouseInputEnabled()) + return false; + + if (ignore_mouse_event_boundaries) + return mouseClickedInner(mouse_x, mouse_y, flag); + + for (var child : children) { + var pos = child.localToScreen(); + + if (child.getIgnoreMouseEventBoundaries() || pos.x <= mouse_x && pos.x + child.width >= mouse_x && pos.y <= mouse_y && pos.y + child.height >= mouse_y) { + return child.mouseClicked(mouse_x, mouse_y, flag); + } else if (child.auto_kill_focus) { + child.killFocus(); + } + } + + return mouseClickedInner(mouse_x, mouse_y, flag); + } + + public boolean mouseClickedChecked(double mouse_x, double mouse_y, int flag) { + var pos = localToScreen(); + + if (getIgnoreMouseEventBoundaries() || pos.x <= mouse_x && pos.x + width >= mouse_x && pos.y <= mouse_y && pos.y + height >= mouse_y) { + return mouseClicked(mouse_x, mouse_y, flag); + } + + return false; + } + + protected boolean mouseReleasedInner(double mouse_x, double mouse_y, int flag) { + return false; + } + + @Override + public boolean mouseReleased(double mouse_x, double mouse_y, int flag) { + if (!getVisible() || !getMouseInputEnabled()) + return false; + + if (ignore_mouse_event_boundaries) + return mouseReleasedInner(mouse_x, mouse_y, flag); + + for (var child : children) { + var pos = child.localToScreen(); + + if (child.getIgnoreMouseEventBoundaries() || pos.x <= mouse_x && pos.x + child.width >= mouse_x && pos.y <= mouse_y && pos.y + child.height >= mouse_y) { + return child.mouseReleased(mouse_x, mouse_y, flag); + } + } + + return mouseReleasedInner(mouse_x, mouse_y, flag); + } + + public boolean mouseReleasedChecked(double mouse_x, double mouse_y, int flag) { + var pos = localToScreen(); + + if (getIgnoreMouseEventBoundaries() || pos.x <= mouse_x && pos.x + width >= mouse_x && pos.y <= mouse_y && pos.y + height >= mouse_y) { + return mouseReleased(mouse_x, mouse_y, flag); + } + + return false; + } + + protected boolean mouseDraggedInner(double mouse_x, double mouse_y, int flag, double drag_x, double drag_y) { + return false; + } + + @Override + public boolean mouseDragged(double mouse_x, double mouse_y, int flag, double drag_x, double drag_y) { + if (!getVisible() || !getMouseInputEnabled()) + return false; + + if (ignore_mouse_event_boundaries) + return mouseDraggedInner(mouse_x, mouse_y, flag, drag_x, drag_y); + + for (var child : children) { + var pos = child.localToScreen(); + + if (child.getIgnoreMouseEventBoundaries() || pos.x <= mouse_x && pos.x + child.width >= mouse_x && pos.y <= mouse_y && pos.y + child.height >= mouse_y) { + return child.mouseDragged(mouse_x, mouse_y, flag, drag_x, drag_y); + } + } + + return mouseDraggedInner(mouse_x, mouse_y, flag, drag_x, drag_y); + } + + public boolean mouseDraggedChecked(double mouse_x, double mouse_y, int flag, double drag_x, double drag_y) { + var pos = localToScreen(); + + if (getIgnoreMouseEventBoundaries() || pos.x <= mouse_x && pos.x + width >= mouse_x && pos.y <= mouse_y && pos.y + height >= mouse_y) { + return mouseDragged(mouse_x, mouse_y, flag, drag_x, drag_y); + } + + return false; + } + + @Override + public boolean mouseScrolled(double mouse_x, double mouse_y, double scroll) { + if (!getVisible() || !getMouseInputEnabled()) + return false; + + for (var child : children) { + var pos = child.localToScreen(); + + if (child.getIgnoreMouseEventBoundaries() || pos.x <= mouse_x && pos.x + child.width >= mouse_x && pos.y <= mouse_y && pos.y + child.height >= mouse_y) { + return child.mouseScrolled(mouse_x, mouse_y, scroll); + } + } + + return GuiEventListener.super.mouseScrolled(mouse_x, mouse_y, scroll); + } + + public boolean mouseScrolledChecked(double mouse_x, double mouse_y, double scroll) { + var pos = localToScreen(); + + if (getIgnoreMouseEventBoundaries() || pos.x <= mouse_x && pos.x + width >= mouse_x && pos.y <= mouse_y && pos.y + height >= mouse_y) { + return mouseScrolled(mouse_x, mouse_y, scroll); + } + + return false; + } + + protected boolean keyPressedInternal(int p_94745_, int p_94746_, int p_94747_) { + return false; + } + + @Override + public boolean keyPressed(int p_94745_, int p_94746_, int p_94747_) { + if (!getVisible() || !getKeyboardInputEnabled()) + return false; + + if (!focused_internal) + return false; + + if (focused) + return keyPressedInternal(p_94745_, p_94746_, p_94747_); + + for (var child : children) { + if (child.keyPressed(p_94745_, p_94746_, p_94747_)) { + return true; + } + } + + return false; + } + + protected boolean keyReleasedInternal(int p_94750_, int p_94751_, int p_94752_) { + return false; + } + + @Override + public boolean keyReleased(int p_94750_, int p_94751_, int p_94752_) { + if (!getVisible() || !getKeyboardInputEnabled()) + return false; + + if (!focused_internal) + return false; + + if (focused) + return keyReleasedInternal(p_94750_, p_94751_, p_94752_); + + for (var child : children) { + if (child.keyReleased(p_94750_, p_94751_, p_94752_)) { + return true; + } + } + + return false; + } + + @Override + public boolean charTyped(char p_94732_, int p_94733_) { + if (!getVisible() || !getKeyboardInputEnabled()) + return false; + + for (var child : children) { + if (child.charTyped(p_94732_, p_94733_)) { + return true; + } + } + + return true; + } + + @Override + public boolean changeFocus(boolean p_94756_) { + if (!getVisible()) + return false; + + return GuiEventListener.super.changeFocus(p_94756_); + } + + @Override + public boolean isMouseOver(double mouse_x, double mouse_y) { // called to check whenever we are hovering at this + if (!getVisible() || !getMouseInputEnabled()) + return false; + + if (getIgnoreMouseEventBoundaries()) + return true; + + var pos = localToScreen(); + return mouse_x >= pos.x && mouse_x <= pos.x + width && mouse_y >= pos.y && mouse_y + height <= pos.y; + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/FramePanel.java b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/FramePanel.java new file mode 100644 index 000000000..6d42a4153 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/FramePanel.java @@ -0,0 +1,86 @@ +package ru.dbotthepony.mc.otm.screen.panels; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.gui.narration.NarratableEntry; +import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.network.chat.Component; +import ru.dbotthepony.mc.otm.screen.MatteryScreen; +import ru.dbotthepony.mc.otm.screen.RenderHelper; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class FramePanel extends EditablePanel implements NarratableEntry { + protected Component title; + + public FramePanel(@Nonnull MatteryScreen screen, @Nullable EditablePanel parent, float x, float y, float width, float height, Component title) { + super(screen, parent, x, y, width, height); + this.title = title; + setDockPadding(4, screen.getFont().lineHeight + 2, 4, 4); + } + + protected boolean dragging = false; + protected double last_mouse_x = 0; + protected double last_mouse_y = 0; + + @Override + protected boolean mouseClickedInner(double mouse_x, double mouse_y, int flag) { + var pos = screenToLocal(mouse_x, mouse_y); + + if (getParent() == null && pos.y() >= 0 && pos.y() <= 12) { + setIgnoreMouseEventBoundaries(true); + last_mouse_x = mouse_x; + last_mouse_y = mouse_y; + dragging = true; + return true; + } + + return super.mouseClickedInner(mouse_x, mouse_y, flag); + } + + @Override + protected boolean mouseReleasedInner(double mouse_x, double mouse_y, int flag) { + if (dragging) { + setIgnoreMouseEventBoundaries(false); + + dragging = false; + return true; + } + + return super.mouseReleasedInner(mouse_x, mouse_y, flag); + } + + @Override + protected boolean mouseDraggedInner(double mouse_x, double mouse_y, int flag, double drag_x, double drag_y) { + if (dragging) { + var real_drag_x = mouse_x - last_mouse_x; + var real_drag_y = mouse_y - last_mouse_y; + + last_mouse_x = mouse_x; + last_mouse_y = mouse_y; + + setPos(getX() + real_drag_x, getY() + real_drag_y); + } + + return super.mouseDraggedInner(mouse_x, mouse_y, flag, drag_x, drag_y); + } + + @Override + protected void innerRender(PoseStack stack, float mouse_x, float mouse_y, float flag) { + // background + RenderHelper.drawWindowBackground(stack, parent_x, parent_y, getWidth(), getHeight()); + + // title + screen.getFont().draw(stack, title, parent_x + 4, parent_y + 5, 4210752); + } + + @Override + public NarrationPriority narrationPriority() { + return NarrationPriority.NONE; + } + + @Override + public void updateNarration(NarrationElementOutput narrationElementOutput) { + + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/MinecraftWidgetPanel.java b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/MinecraftWidgetPanel.java new file mode 100644 index 000000000..dd86ad3ee --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/MinecraftWidgetPanel.java @@ -0,0 +1,65 @@ +package ru.dbotthepony.mc.otm.screen.panels; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import ru.dbotthepony.mc.otm.screen.MatteryScreen; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class MinecraftWidgetPanel extends EditablePanel { + public interface WidgetFactory { + T create(MinecraftWidgetPanel panel); + } + + protected T widget; + private final WidgetFactory factory; + + public T getWidget() { + return widget; + } + + public MinecraftWidgetPanel(@Nonnull MatteryScreen screen, @Nullable EditablePanel parent, float x, float y, float width, float height, WidgetFactory factory) { + super(screen, parent, x, y, width, height); + this.widget = factory.create(this); + this.factory = factory; + } + + protected void copyValues(T new_widget, T old_widget) { + + } + + private void recreate() { + var new_widget = factory.create(this); + new_widget.visible = getVisible(); + new_widget.x = (int) parent_x; + new_widget.y = (int) parent_y; + copyValues(new_widget, widget); + widget = new_widget; + } + + @Override + protected void widthUpdated(float new_value, float old_value) { + recreate(); + } + + @Override + protected void heightUpdated(float new_value, float old_value) { + recreate(); + } + + @Override + protected void visibilityChanges(boolean new_visible, boolean old_visible) { + widget.visible = new_visible; + } + + @Override + protected void innerRender(PoseStack stack, float mouse_x, float mouse_y, float flag) { + widget.x = (int) parent_x; + widget.y = (int) parent_y; + + widget.render(stack, (int) mouse_x, (int) mouse_y, flag); + } +}