From 20a2a5f1e7569be92557c22840fd1aaf76b4b639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Wed, 24 Aug 2022 09:56:48 +0200 Subject: [PATCH] Make *OptionChoice components scrollable --- .../base/lib/gui/HOptionChoice.java | 61 +++++++++++++------ .../base/lib/gui/VOptionChoice.java | 61 +++++++++++++------ 2 files changed, 86 insertions(+), 36 deletions(-) diff --git a/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HOptionChoice.java b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HOptionChoice.java index 843788b0..27af12a0 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HOptionChoice.java +++ b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HOptionChoice.java @@ -2,35 +2,48 @@ package com.bartlomiejpluta.base.lib.gui; import com.bartlomiejpluta.base.api.context.Context; import com.bartlomiejpluta.base.api.event.Event; +import com.bartlomiejpluta.base.api.gui.Component; import com.bartlomiejpluta.base.api.gui.GUI; import com.bartlomiejpluta.base.api.input.Key; import com.bartlomiejpluta.base.api.input.KeyAction; import com.bartlomiejpluta.base.api.input.KeyEvent; +import com.bartlomiejpluta.base.api.screen.Screen; +import com.bartlomiejpluta.base.util.math.MathUtil; +import lombok.NonNull; import java.util.EnumSet; -public class HOptionChoice extends HScrollableLayout { +public class HOptionChoice extends HLayout { private static final EnumSet ACTIONS = EnumSet.of(KeyAction.PRESS, KeyAction.REPEAT); private int selected = 0; + private float scroll = 0; + private Component component = null; + private float scrollSpeed = 1f; public HOptionChoice(Context context, GUI gui) { super(context, gui); addEventListener(KeyEvent.TYPE, this::switchOption); } + public void setScrollSpeed(@NonNull Float scrollSpeed) { + this.scrollSpeed = MathUtil.clamp(scrollSpeed, 0f, 1f); + } + @Override public void focus() { super.focus(); if (!children.isEmpty()) { - children.get(selected).focus(); + component = children.get(selected); + component.focus(); } } @Override public void handleEvent(E event) { if (selected < children.size()) { - children.get(selected).handleEvent(event); + component = children.get(selected); + component.handleEvent(event); } if (!event.isConsumed()) { @@ -46,33 +59,45 @@ public class HOptionChoice extends HScrollableLayout { if (event.getKey() == Key.KEY_RIGHT && ACTIONS.contains(event.getAction())) { blurAll(); selected = (++selected) % children.size(); - children.get(selected).focus(); - scrollToSelected(); + component = children.get(selected); + component.focus(); event.consume(); } else if (event.getKey() == Key.KEY_LEFT && ACTIONS.contains(event.getAction())) { blurAll(); var size = children.size(); selected = (((--selected) % size) + size) % size; - children.get(selected).focus(); - scrollToSelected(); + component = children.get(selected); + component.focus(); event.consume(); } } - private void scrollToSelected() { - var childrenWidth = 0.0f; - - for (int i = 0; i < selected; ++i) { - var child = this.children.get(i); - childrenWidth += child.getMarginLeft() + child.getWidth() + child.getMarginRight(); - } - - scrollTo(childrenWidth / getWidth()); - } - private void blurAll() { for (var child : children) { child.blur(); } } + + @Override + public void update(float dt) { + super.update(dt); + if (component != null) { + if (component.getX() + component.getWidth() > getWidth() + getX()) { + scroll += (component.getWidth() + component.getX() - (getWidth() + getX())) * scrollSpeed; + } else if (component.getX() < getX()) { + scroll += (component.getX() - getX()) * scrollSpeed; + } + } + } + + @Override + public void draw(Screen screen, GUI gui) { + gui.clip(x, y, getWidth(), getHeight()); + + offsetX = -scroll; + + super.draw(screen, gui); + + gui.resetClip(); + } } diff --git a/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VOptionChoice.java b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VOptionChoice.java index 9bbd4f85..4a26eb68 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VOptionChoice.java +++ b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VOptionChoice.java @@ -2,35 +2,48 @@ package com.bartlomiejpluta.base.lib.gui; import com.bartlomiejpluta.base.api.context.Context; import com.bartlomiejpluta.base.api.event.Event; +import com.bartlomiejpluta.base.api.gui.Component; import com.bartlomiejpluta.base.api.gui.GUI; import com.bartlomiejpluta.base.api.input.Key; import com.bartlomiejpluta.base.api.input.KeyAction; import com.bartlomiejpluta.base.api.input.KeyEvent; +import com.bartlomiejpluta.base.api.screen.Screen; +import com.bartlomiejpluta.base.util.math.MathUtil; +import lombok.NonNull; import java.util.EnumSet; -public class VOptionChoice extends VScrollableLayout { +public class VOptionChoice extends VLayout { private static final EnumSet ACTIONS = EnumSet.of(KeyAction.PRESS, KeyAction.REPEAT); private int selected = 0; + private float scroll = 0; + private Component component = null; + private float scrollSpeed = 1f; public VOptionChoice(Context context, GUI gui) { super(context, gui); addEventListener(KeyEvent.TYPE, this::switchOption); } + public void setScrollSpeed(@NonNull Float scrollSpeed) { + this.scrollSpeed = MathUtil.clamp(scrollSpeed, 0f, 1f); + } + @Override public void focus() { super.focus(); if (!children.isEmpty()) { - children.get(selected).focus(); + component = children.get(selected); + component.focus(); } } @Override public void handleEvent(E event) { if (selected < children.size()) { - children.get(selected).handleEvent(event); + component = children.get(selected); + component.handleEvent(event); } if (!event.isConsumed()) { @@ -46,33 +59,45 @@ public class VOptionChoice extends VScrollableLayout { if (event.getKey() == Key.KEY_DOWN && ACTIONS.contains(event.getAction())) { blurAll(); selected = (++selected) % children.size(); - children.get(selected).focus(); - scrollToSelected(); + component = children.get(selected); + component.focus(); event.consume(); } else if (event.getKey() == Key.KEY_UP && ACTIONS.contains(event.getAction())) { blurAll(); var size = children.size(); selected = (((--selected) % size) + size) % size; - children.get(selected).focus(); - scrollToSelected(); + component = children.get(selected); + component.focus(); event.consume(); } } - private void scrollToSelected() { - var childrenHeight = 0.0f; - - for (int i = 0; i < selected; ++i) { - var child = children.get(i); - childrenHeight += child.getMarginTop() + child.getHeight() + child.getMarginBottom(); - } - - scrollTo(childrenHeight / getHeight()); - } - private void blurAll() { for (var child : children) { child.blur(); } } + + @Override + public void update(float dt) { + super.update(dt); + if (component != null) { + if (component.getY() + component.getHeight() > getHeight() + getY()) { + scroll += (component.getHeight() + component.getY() - (getHeight() + getY())) * scrollSpeed; + } else if (component.getY() < getY()) { + scroll += (component.getY() - getY()) * scrollSpeed; + } + } + } + + @Override + public void draw(Screen screen, GUI gui) { + gui.clip(x, y, getWidth(), getHeight()); + + offsetY = -scroll; + + super.draw(screen, gui); + + gui.resetClip(); + } }