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
1 changed files with 62 additions and 45 deletions

View File

@ -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();
}