[Bug,Enhancement] Fix and improve Starter selector UI (#3340)
* apply offset to all hybrid filter * make dropDownType to public for offsetHybridFilter function * refactoring defaultSettings to additional suport default cursor. * fix to remember last cursor on hover mode * remove unnecessary reset code * fix sort reset function * update resetFilter function * update requested changes * remove log msg * fix checking default on sort * refactoring hasDefaultValues function for readability * fix lastdir bug
This commit is contained in:
parent
97e362368c
commit
91b32132d0
|
@ -27,10 +27,10 @@ export class DropDownLabel {
|
|||
public text: string;
|
||||
public sprite?: Phaser.GameObjects.Sprite;
|
||||
|
||||
constructor(label: string, sprite?: Phaser.GameObjects.Sprite, state: DropDownState = DropDownState.ON) {
|
||||
constructor(label: string, sprite?: Phaser.GameObjects.Sprite, state: DropDownState = DropDownState.OFF) {
|
||||
this.text = label || "";
|
||||
this.sprite = sprite;
|
||||
this.state = state || DropDownState.ON;
|
||||
this.state = state;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,12 +262,13 @@ export class DropDown extends Phaser.GameObjects.Container {
|
|||
public options: DropDownOption[];
|
||||
private window: Phaser.GameObjects.NineSlice;
|
||||
private cursorObj: Phaser.GameObjects.Image;
|
||||
private dropDownType: DropDownType = DropDownType.MULTI;
|
||||
public dropDownType: DropDownType = DropDownType.MULTI;
|
||||
public cursor: number = 0;
|
||||
private lastCursor: number = -1;
|
||||
public defaultCursor: number = 0;
|
||||
private onChange: () => void;
|
||||
private lastDir: SortDirection = SortDirection.ASC;
|
||||
private defaultValues: any[];
|
||||
private defaultSettings: any[];
|
||||
|
||||
constructor(scene: BattleScene, x: number, y: number, options: DropDownOption[], onChange: () => void, type: DropDownType = DropDownType.MULTI, optionSpacing: number = 2) {
|
||||
const windowPadding = 5;
|
||||
|
@ -292,7 +293,7 @@ export class DropDown extends Phaser.GameObjects.Container {
|
|||
this.options.unshift(new DropDownOption(scene, "ALL", new DropDownLabel(i18next.t("filterBar:all"), undefined, this.checkForAllOn() ? DropDownState.ON : DropDownState.OFF)));
|
||||
}
|
||||
|
||||
this.defaultValues = this.getVals();
|
||||
this.defaultSettings = this.getSettings();
|
||||
|
||||
// Place ui elements in the correct spot
|
||||
options.forEach((option, index) => {
|
||||
|
@ -339,8 +340,8 @@ export class DropDown extends Phaser.GameObjects.Container {
|
|||
|
||||
resetCursor(): boolean {
|
||||
// If we are an hybrid dropdown in "hover" mode, don't move the cursor back to 0
|
||||
if (this.dropDownType === DropDownType.HYBRID && this.checkForAllOff() && this.cursor > 0) {
|
||||
return false;
|
||||
if (this.dropDownType === DropDownType.HYBRID && this.checkForAllOff()) {
|
||||
return this.setCursor(this.lastCursor);
|
||||
}
|
||||
return this.setCursor(this.defaultCursor);
|
||||
}
|
||||
|
@ -361,6 +362,7 @@ export class DropDown extends Phaser.GameObjects.Container {
|
|||
this.cursorObj.setVisible(true);
|
||||
// If hydrid type, we need to update the filters when going up/down in the list
|
||||
if (this.dropDownType === DropDownType.HYBRID) {
|
||||
this.lastCursor = cursor;
|
||||
this.onChange();
|
||||
}
|
||||
}
|
||||
|
@ -457,23 +459,43 @@ export class DropDown extends Phaser.GameObjects.Container {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current selected settings dictionary for each option
|
||||
* @returns an array of dictionaries with the current state of each option
|
||||
* - the settings dictionary is like this { val: any, state: DropDownState, cursor: boolean, dir: SortDirection }
|
||||
*/
|
||||
private getSettings(): any[] {
|
||||
const settings = [];
|
||||
for (let i = 0; i < this.options.length; i++) {
|
||||
settings.push({ val: this.options[i].val, state: this.options[i].state , cursor: (this.cursor === i), dir: this.options[i].dir });
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the values of all options are the same as the default ones
|
||||
* @returns true if they are the same, false otherwise
|
||||
*/
|
||||
public hasDefaultValues(): boolean {
|
||||
const currentValues = this.getVals();
|
||||
const currentValues = this.getSettings();
|
||||
|
||||
const compareValues = (keys: string[]): boolean => {
|
||||
return currentValues.length === this.defaultSettings.length &&
|
||||
currentValues.every((value, index) =>
|
||||
keys.every(key => value[key] === this.defaultSettings[index][key])
|
||||
);
|
||||
};
|
||||
|
||||
switch (this.dropDownType) {
|
||||
case DropDownType.MULTI:
|
||||
case DropDownType.HYBRID:
|
||||
return currentValues.length === this.defaultValues.length && currentValues.every((value, index) => value === this.defaultValues[index]);
|
||||
|
||||
case DropDownType.RADIAL:
|
||||
return currentValues.every((value, index) => value["val"] === this.defaultValues[index]["val"] && value["state"] === this.defaultValues[index]["state"]);
|
||||
return compareValues(["val", "state"]);
|
||||
|
||||
case DropDownType.HYBRID:
|
||||
return compareValues(["val", "state", "cursor"]);
|
||||
|
||||
case DropDownType.SINGLE:
|
||||
return currentValues[0]["dir"] === this.defaultValues[0]["dir"] && currentValues[0]["val"] === this.defaultValues[0]["val"];
|
||||
return compareValues(["val", "state", "dir"]);
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
@ -484,46 +506,29 @@ export class DropDown extends Phaser.GameObjects.Container {
|
|||
* Set all values to their default state
|
||||
*/
|
||||
public resetToDefault(): void {
|
||||
this.setCursor(this.defaultCursor);
|
||||
if (this.defaultSettings.length > 0) {
|
||||
this.setCursor(this.defaultCursor);
|
||||
this.lastDir = SortDirection.ASC;
|
||||
|
||||
for (let i = 0; i < this.options.length; i++) {
|
||||
const option = this.options[i];
|
||||
// reset values
|
||||
switch (this.dropDownType) {
|
||||
case DropDownType.HYBRID:
|
||||
case DropDownType.MULTI:
|
||||
if (this.defaultValues.includes(option.val)) {
|
||||
option.setOptionState(DropDownState.ON);
|
||||
for (let i = 0; i < this.options.length; i++) {
|
||||
// reset values with the defaultValues
|
||||
if (this.dropDownType === DropDownType.SINGLE) {
|
||||
if (this.defaultSettings[i].state === DropDownState.OFF) {
|
||||
this.options[i].setOptionState(DropDownState.OFF);
|
||||
this.options[i].setDirection(SortDirection.ASC);
|
||||
this.options[i].toggle.setVisible(false);
|
||||
} else {
|
||||
this.options[i].setOptionState(DropDownState.ON);
|
||||
this.options[i].setDirection(SortDirection.ASC);
|
||||
this.options[i].toggle.setVisible(true);
|
||||
}
|
||||
} else {
|
||||
option.setOptionState(DropDownState.OFF);
|
||||
}
|
||||
break;
|
||||
case DropDownType.RADIAL:
|
||||
const targetValue = this.defaultValues.find(value => value.val === option.val);
|
||||
option.setOptionState(targetValue.state);
|
||||
break;
|
||||
case DropDownType.SINGLE:
|
||||
if (option.val === this.defaultValues[0].val) {
|
||||
if (option.state !== DropDownState.ON) {
|
||||
this.toggleOptionState(i);
|
||||
}
|
||||
if (option.dir !== this.defaultValues[0].dir) {
|
||||
this.toggleOptionState(i);
|
||||
if (this.defaultSettings[i]) {
|
||||
this.options[i].setOptionState(this.defaultSettings[i]["state"]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Select or unselect "ALL" button if applicable
|
||||
if (this.dropDownType === DropDownType.MULTI || this.dropDownType === DropDownType.HYBRID) {
|
||||
if (this.checkForAllOn()) {
|
||||
this.options[0].setOptionState(DropDownState.ON);
|
||||
} else {
|
||||
this.options[0].setOptionState(DropDownState.OFF);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import BattleScene from "#app/battle-scene.js";
|
||||
import { DropDown } from "./dropdown";
|
||||
import { DropDown, DropDownType } from "./dropdown";
|
||||
import { StarterContainer } from "./starter-container";
|
||||
import { addTextObject, getTextColor, TextStyle } from "./text";
|
||||
import { UiTheme } from "#enums/ui-theme";
|
||||
|
@ -120,11 +120,13 @@ export class FilterBar extends Phaser.GameObjects.Container {
|
|||
/**
|
||||
* Move the leftmost dropdown to the left of the FilterBar instead of below it
|
||||
*/
|
||||
offsetFirstFilter(): void {
|
||||
if (this.dropDowns[0]) {
|
||||
this.dropDowns[0].autoSize();
|
||||
this.dropDowns[0].x -= this.dropDowns[0].getWidth();
|
||||
this.dropDowns[0].y = 0;
|
||||
offsetHybridFilters(): void {
|
||||
for (let i=0; i<this.dropDowns.length; i++) {
|
||||
if (this.dropDowns[i].dropDownType === DropDownType.HYBRID) {
|
||||
this.dropDowns[i].autoSize();
|
||||
this.dropDowns[i].x = - this.dropDowns[i].getWidth();
|
||||
this.dropDowns[i].y = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -450,11 +450,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
|
||||
// sort filter
|
||||
const sortOptions = [
|
||||
new DropDownOption(this.scene, 0, new DropDownLabel(i18next.t("filterBar:sortByNumber"))),
|
||||
new DropDownOption(this.scene, 1, new DropDownLabel(i18next.t("filterBar:sortByCost"), undefined, DropDownState.OFF)),
|
||||
new DropDownOption(this.scene, 2, new DropDownLabel(i18next.t("filterBar:sortByCandies"), undefined, DropDownState.OFF)),
|
||||
new DropDownOption(this.scene, 3, new DropDownLabel(i18next.t("filterBar:sortByIVs"), undefined, DropDownState.OFF)),
|
||||
new DropDownOption(this.scene, 4, new DropDownLabel(i18next.t("filterBar:sortByName"), undefined, DropDownState.OFF))
|
||||
new DropDownOption(this.scene, 0, new DropDownLabel(i18next.t("filterBar:sortByNumber"), undefined, DropDownState.ON)),
|
||||
new DropDownOption(this.scene, 1, new DropDownLabel(i18next.t("filterBar:sortByCost"))),
|
||||
new DropDownOption(this.scene, 2, new DropDownLabel(i18next.t("filterBar:sortByCandies"))),
|
||||
new DropDownOption(this.scene, 3, new DropDownLabel(i18next.t("filterBar:sortByIVs"))),
|
||||
new DropDownOption(this.scene, 4, new DropDownLabel(i18next.t("filterBar:sortByName")))
|
||||
];
|
||||
this.filterBar.addFilter(DropDownColumn.SORT, i18next.t("filterBar:sortFilter"), new DropDown(this.scene, 0, 0, sortOptions, this.updateStarters, DropDownType.SINGLE));
|
||||
this.filterBarContainer.add(this.filterBar);
|
||||
|
@ -462,7 +462,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
this.starterSelectContainer.add(this.filterBarContainer);
|
||||
|
||||
// Offset the generation filter dropdown to avoid covering the filtered pokemon
|
||||
this.filterBar.offsetFirstFilter();
|
||||
this.filterBar.offsetHybridFilters();
|
||||
|
||||
if (!this.scene.uiTheme) {
|
||||
starterContainerWindow.setVisible(false);
|
||||
|
@ -914,19 +914,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
*/
|
||||
resetFilters() : void {
|
||||
const genDropDown: DropDown = this.filterBar.getFilter(DropDownColumn.GEN);
|
||||
if (this.scene.gameMode.isChallenge) {
|
||||
// In challenge mode all gens are selected by default
|
||||
genDropDown.defaultCursor = 0;
|
||||
} else {
|
||||
// in other modes, gen 1 is selected by default, and all options disabled
|
||||
genDropDown.defaultCursor = 1;
|
||||
}
|
||||
|
||||
this.filterBar.setValsToDefault();
|
||||
|
||||
// for all modes except challenge, disable all gen options to enable hovering behavior
|
||||
if (!this.scene.gameMode.isChallenge) {
|
||||
genDropDown.unselectAllOptions();
|
||||
// if not in a challenge, in Gen hybrid filter hovering mode, set the cursor to the Gen1
|
||||
genDropDown.setCursor(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue