Working logic for select ui handler with skips and scroll

This commit is contained in:
Wlowscha 2025-01-06 12:53:49 +01:00
parent c78ea78be5
commit cedc020e11
No known key found for this signature in database
GPG Key ID: 3C8F1AD330565D04

View File

@ -44,12 +44,13 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
protected blockInput: boolean; protected blockInput: boolean;
protected scrollCursor: integer = 0; protected scrollCursor: integer = 0;
protected fullCursor: integer = 0;
protected scale: number = 0.1666666667; protected scale: number = 0.1666666667;
private cursorObj: Phaser.GameObjects.Image | null; private cursorObj: Phaser.GameObjects.Image | null;
protected unskippedIndices: number[]; protected unskippedIndices: number[] = [];
constructor(scene: BattleScene, mode: Mode | null) { 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()); 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? 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(); this.optionSelectBg.height = this.getWindowHeight();
@ -199,9 +203,6 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
let success = false; let success = false;
const options = this.getOptionsWithScroll();
const unskippedIndices = this.getUnskippedIndices(options);
let playSound = true; let playSound = true;
if (button === Button.ACTION || button === Button.CANCEL) { if (button === Button.ACTION || button === Button.CANCEL) {
@ -213,15 +214,14 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
success = true; success = true;
if (button === Button.CANCEL) { if (button === Button.CANCEL) {
if (this.config?.maxOptions && this.config.options.length > this.config.maxOptions) { if (this.config?.maxOptions && this.config.options.length > this.config.maxOptions) {
this.scrollCursor = (this.config.options.length - this.config.maxOptions) + 1; this.setCursor(this.unskippedIndices.length - 1);
this.cursor = unskippedIndices.length - 1;
} else if (!this.config?.noCancel) { } else if (!this.config?.noCancel) {
this.setCursor(unskippedIndices.length - 1); this.setCursor(this.unskippedIndices.length - 1);
} else { } else {
return false; 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?.handler()) {
if (!option.keepOpen) { if (!option.keepOpen) {
this.clear(); 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 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 // 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; 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?.handler()) {
if (!option.keepOpen) { if (!option.keepOpen) {
this.clear(); this.clear();
@ -246,15 +246,15 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
} else { } else {
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (this.cursor) { if (this.fullCursor === 0) {
success = this.setCursor(this.cursor - 1); success = this.setCursor(this.unskippedIndices.length - 1);
} else if (this.cursor === 0) { } else if (this.fullCursor) {
success = this.setCursor(unskippedIndices.length - 1); success = this.setCursor(this.fullCursor - 1);
} }
break; break;
case Button.DOWN: case Button.DOWN:
if (this.cursor < unskippedIndices.length - 1) { if (this.fullCursor < this.unskippedIndices.length - 1) {
success = this.setCursor(this.cursor + 1); success = this.setCursor(this.fullCursor + 1);
} else { } else {
success = this.setCursor(0); success = this.setCursor(0);
} }
@ -262,7 +262,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
} }
if (this.config?.supportHover) { if (this.config?.supportHover) {
// handle hover code if the element supports hover-handlers and the option has the optional hover-handler set. // 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) { if (optionStartIndex) {
options.unshift({ options.unshift({
label: scrollUpLabel, label: scrollUpLabel,
handler: () => true handler: () => true,
color: "#ffffff"
}); });
} }
if (optionEndIndex < optionsScrollTotal) { if (optionEndIndex < optionsScrollTotal) {
options.push({ options.push({
label: scrollDownLabel, label: scrollDownLabel,
handler: () => true handler: () => true,
color: "#ffffff"
}); });
} }
} }
@ -325,50 +327,64 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
return unskippedIndices; return unskippedIndices;
} }
setCursor(cursor: integer): boolean { setCursor(fullCursor: integer): boolean {
const changed = this.cursor !== cursor; 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 (changed && this.config?.maxOptions && this.config.options.length > this.config.maxOptions) {
if (Math.abs(cursor - this.cursor) === options.length - 1) {
// Wrap around the list // If the fullCursor is the last possible value, we go to the bottom
const optionsScrollTotal = this.config.options.length; if (fullCursor === this.unskippedIndices.length - 1) {
this.scrollCursor = cursor ? optionsScrollTotal - (this.config.maxOptions - 1) : 0; this.fullCursor = fullCursor;
this.setupOptions(); 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 { } else {
// Move the cursor up or down by 1 const isDown = fullCursor && fullCursor > this.fullCursor;
const isDown = cursor && cursor > this.cursor;
if (isDown) { if (isDown) {
if (options[Math.min(unskippedIndices[cursor], options.length)].label === scrollDownLabel) { // If there are skipped options under the next selection, we show them
isScroll = true; const jumpFromCurrent = this.unskippedIndices[fullCursor] - this.unskippedIndices[this.fullCursor];
this.scrollCursor += unskippedIndices[cursor] - unskippedIndices[this.cursor]; 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 { } else {
if (!cursor && this.scrollCursor) { const jumpFromPrevious = this.unskippedIndices[fullCursor] - this.unskippedIndices[fullCursor - 1];
isScroll = true;
this.scrollCursor--; 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 { } else {
this.cursor = cursor; this.fullCursor = fullCursor;
this.cursor = this.unskippedIndices[fullCursor];
} }
this.setupOptions();
if (!this.cursorObj) { if (!this.cursorObj) {
this.cursorObj = this.scene.add.image(0, 0, "cursor"); this.cursorObj = this.scene.add.image(0, 0, "cursor");
this.optionSelectContainer.add(this.cursorObj); this.optionSelectContainer.add(this.cursorObj);
} }
this.cursorObj.setScale(this.scale * 6); 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; return changed;
} }
@ -377,6 +393,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
super.clear(); super.clear();
this.config = null; this.config = null;
this.optionSelectContainer.setVisible(false); this.optionSelectContainer.setVisible(false);
this.fullCursor = 0;
this.scrollCursor = 0; this.scrollCursor = 0;
this.eraseCursor(); this.eraseCursor();
} }