From cedc020e11eb3ce09d12f63ad6a1411eb41527bf Mon Sep 17 00:00:00 2001 From: Wlowscha <54003515+Wlowscha@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:53:49 +0100 Subject: [PATCH] Working logic for select ui handler with skips and scroll --- src/ui/abstact-option-select-ui-handler.ts | 107 ++++++++++++--------- 1 file changed, 62 insertions(+), 45 deletions(-) diff --git a/src/ui/abstact-option-select-ui-handler.ts b/src/ui/abstact-option-select-ui-handler.ts index fa7a6d14ac0..b486dfaa2a5 100644 --- a/src/ui/abstact-option-select-ui-handler.ts +++ b/src/ui/abstact-option-select-ui-handler.ts @@ -44,12 +44,13 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { protected blockInput: boolean; protected scrollCursor: integer = 0; + protected fullCursor: integer = 0; protected scale: number = 0.1666666667; private cursorObj: Phaser.GameObjects.Image | null; - protected unskippedIndices: number[]; + protected unskippedIndices: number[] = []; constructor(scene: BattleScene, mode: Mode | null) { @@ -133,7 +134,10 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { this.optionSelectBg.width = Math.max(this.optionSelectText.displayWidth + 24, this.getWindowWidth()); if (this.config?.options && this.config?.options.length > (this.config?.maxOptions!)) { // TODO: is this bang correct? - this.optionSelectText.setText(this.getOptionsWithScroll().map(o => o.label).join("\n")); + this.optionSelectText.setText(this.getOptionsWithScroll().map(o => o.item + ? `[color=${o.color || "white"}] ${o.label}[/color]` + : `[color=${o.color || "white"}]${o.label}[/color]` + ).join("\n")); } this.optionSelectBg.height = this.getWindowHeight(); @@ -199,9 +203,6 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { let success = false; - const options = this.getOptionsWithScroll(); - const unskippedIndices = this.getUnskippedIndices(options); - let playSound = true; if (button === Button.ACTION || button === Button.CANCEL) { @@ -213,15 +214,14 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { success = true; if (button === Button.CANCEL) { if (this.config?.maxOptions && this.config.options.length > this.config.maxOptions) { - this.scrollCursor = (this.config.options.length - this.config.maxOptions) + 1; - this.cursor = unskippedIndices.length - 1; + this.setCursor(this.unskippedIndices.length - 1); } else if (!this.config?.noCancel) { - this.setCursor(unskippedIndices.length - 1); + this.setCursor(this.unskippedIndices.length - 1); } else { return false; } } - const option = this.config?.options[unskippedIndices[this.cursor] + (this.scrollCursor - (this.scrollCursor ? 1 : 0))]; + const option = this.config?.options[this.unskippedIndices[this.fullCursor]]; if (option?.handler()) { if (!option.keepOpen) { this.clear(); @@ -234,7 +234,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { // this is here to differentiate between a Button.SUBMIT vs Button.ACTION within the autocomplete handler // this is here because Button.ACTION is picked up as z on the keyboard, meaning if you're typing and hit z, it'll select the option you've chosen success = true; - const option = this.config?.options[unskippedIndices[this.cursor] + (this.scrollCursor - (this.scrollCursor ? 1 : 0))]; + const option = this.config?.options[this.unskippedIndices[this.fullCursor]]; if (option?.handler()) { if (!option.keepOpen) { this.clear(); @@ -246,15 +246,15 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { } else { switch (button) { case Button.UP: - if (this.cursor) { - success = this.setCursor(this.cursor - 1); - } else if (this.cursor === 0) { - success = this.setCursor(unskippedIndices.length - 1); + if (this.fullCursor === 0) { + success = this.setCursor(this.unskippedIndices.length - 1); + } else if (this.fullCursor) { + success = this.setCursor(this.fullCursor - 1); } break; case Button.DOWN: - if (this.cursor < unskippedIndices.length - 1) { - success = this.setCursor(this.cursor + 1); + if (this.fullCursor < this.unskippedIndices.length - 1) { + success = this.setCursor(this.fullCursor + 1); } else { success = this.setCursor(0); } @@ -262,7 +262,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { } if (this.config?.supportHover) { // handle hover code if the element supports hover-handlers and the option has the optional hover-handler set. - this.config?.options[unskippedIndices[this.cursor] + (this.scrollCursor - (this.scrollCursor ? 1 : 0))]?.onHover?.(); + this.config?.options[this.fullCursor]?.onHover?.(); } } @@ -304,13 +304,15 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { if (optionStartIndex) { options.unshift({ label: scrollUpLabel, - handler: () => true + handler: () => true, + color: "#ffffff" }); } if (optionEndIndex < optionsScrollTotal) { options.push({ label: scrollDownLabel, - handler: () => true + handler: () => true, + color: "#ffffff" }); } } @@ -325,50 +327,64 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { return unskippedIndices; } - setCursor(cursor: integer): boolean { - const changed = this.cursor !== cursor; + setCursor(fullCursor: integer): boolean { + const changed = this.fullCursor !== fullCursor; - let isScroll = false; - const options = this.getOptionsWithScroll(); - const unskippedIndices = this.getUnskippedIndices(options); if (changed && this.config?.maxOptions && this.config.options.length > this.config.maxOptions) { - if (Math.abs(cursor - this.cursor) === options.length - 1) { - // Wrap around the list - const optionsScrollTotal = this.config.options.length; - this.scrollCursor = cursor ? optionsScrollTotal - (this.config.maxOptions - 1) : 0; - this.setupOptions(); + + // If the fullCursor is the last possible value, we go to the bottom + if (fullCursor === this.unskippedIndices.length - 1) { + this.fullCursor = fullCursor; + this.cursor = this.config.maxOptions - (this.config.options.length - this.unskippedIndices[fullCursor]); + this.scrollCursor = this.config.options.length - this.config.maxOptions + 1; + // If the fullCursor is the first possible value, we go to the top + } else if (fullCursor === 0) { + this.fullCursor = fullCursor; + this.cursor = this.unskippedIndices[fullCursor]; + this.scrollCursor = 0; } else { - // Move the cursor up or down by 1 - const isDown = cursor && cursor > this.cursor; + const isDown = fullCursor && fullCursor > this.fullCursor; + if (isDown) { - if (options[Math.min(unskippedIndices[cursor], options.length)].label === scrollDownLabel) { - isScroll = true; - this.scrollCursor += unskippedIndices[cursor] - unskippedIndices[this.cursor]; + // If there are skipped options under the next selection, we show them + const jumpFromCurrent = this.unskippedIndices[fullCursor] - this.unskippedIndices[this.fullCursor]; + const skipsFromNext = this.unskippedIndices[fullCursor + 1] - this.unskippedIndices[fullCursor] - 1; + + if (this.cursor + jumpFromCurrent + skipsFromNext >= this.config.maxOptions - 1) { + this.fullCursor = fullCursor; + this.cursor = this.config.maxOptions - 2 - skipsFromNext; + this.scrollCursor = this.unskippedIndices[this.fullCursor] - this.cursor + 1; + } else { + this.fullCursor = fullCursor; + this.cursor = this.unskippedIndices[fullCursor] - this.scrollCursor + (this.scrollCursor ? 1 : 0); } } else { - if (!cursor && this.scrollCursor) { - isScroll = true; - this.scrollCursor--; + const jumpFromPrevious = this.unskippedIndices[fullCursor] - this.unskippedIndices[fullCursor - 1]; + + if (this.cursor - jumpFromPrevious < 1) { + this.fullCursor = fullCursor; + this.cursor = 1; + this.scrollCursor = this.unskippedIndices[this.fullCursor] - this.cursor + 1; + } else { + this.fullCursor = fullCursor; + this.cursor = this.unskippedIndices[fullCursor] - this.scrollCursor + (this.scrollCursor ? 1 : 0); } } - if (isScroll && this.scrollCursor === 1) { - this.scrollCursor += isDown ? 1 : -1; - } } - } - if (isScroll) { - this.setupOptions(); } else { - this.cursor = cursor; + this.fullCursor = fullCursor; + this.cursor = this.unskippedIndices[fullCursor]; } + this.setupOptions(); + if (!this.cursorObj) { this.cursorObj = this.scene.add.image(0, 0, "cursor"); this.optionSelectContainer.add(this.cursorObj); } this.cursorObj.setScale(this.scale * 6); - this.cursorObj.setPositionRelative(this.optionSelectBg, 12, 102 * this.scale + unskippedIndices[this.cursor] * (114 * this.scale - 3)); + this.cursorObj.setPositionRelative(this.optionSelectBg, 12, 102 * this.scale + this.cursor * (114 * this.scale - 3)); return changed; } @@ -377,6 +393,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { super.clear(); this.config = null; this.optionSelectContainer.setVisible(false); + this.fullCursor = 0; this.scrollCursor = 0; this.eraseCursor(); }