mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-01-17 22:40:59 +00:00
[Enhancement] Improvements to starter selection and filtering user experience (#3325)
* [filter-ui] Improvements to starter selection and filtering user experience Original messages of 14 squashed commits: * final cleanup and code comments * automatically go to the list of starters when closing filters * FilterBar cleanup. Associate each DropDown with an id and access them through it * reset all filters when creating a new game. Set different default gen filter for challenge mode * start of code cleanup plus some documentation * fix filter bar label coloring for legacy theme * change generation filter default values to be all generations selected * fix navigation between team and filtered Pokemon * add missing localisation keys * first pass at improving navigation between the UI elements * have each filter group handle its default values instead of the filter bar * revamp dropdown class. add possibility to display both a sprite and text label at the same time * groundwork to be able to move around starter ui elements more easily * add hybrid filtering type for Gen and Type filters, clean up implementation for radial type * [loc][ko][zh] localisation of starter ui filters for Chinese and Korean Co-authored-by: Enoch <enoch.jwsong@gmail.com> Co-authored-by: Yonmaru40 <47717431+40chyan@users.noreply.github.com> * [loc][de] German translations for the filters Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com> --------- Co-authored-by: Enoch <enoch.jwsong@gmail.com> Co-authored-by: Yonmaru40 <47717431+40chyan@users.noreply.github.com> Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>
This commit is contained in:
parent
22349da663
commit
0796a9fce8
@ -3,14 +3,17 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
|||||||
export const filterBar: SimpleTranslationEntries = {
|
export const filterBar: SimpleTranslationEntries = {
|
||||||
"genFilter": "Gen.",
|
"genFilter": "Gen.",
|
||||||
"typeFilter": "Typ",
|
"typeFilter": "Typ",
|
||||||
|
"dexFilter": "Dex.",
|
||||||
"unlocksFilter": "Freisch.",
|
"unlocksFilter": "Freisch.",
|
||||||
"winFilter": "Abschluss",
|
"miscFilter": "Sonst.",
|
||||||
"sortFilter": "Sort.",
|
"sortFilter": "Sort.",
|
||||||
"all": "Alle",
|
"all": "Alle",
|
||||||
"normal": "Normal",
|
"normal": "Normal",
|
||||||
"uncaught": "Nicht gefangen",
|
"uncaught": "Nicht gefangen",
|
||||||
|
"passive": "Passive",
|
||||||
"passiveUnlocked": "Passive freigeschaltet",
|
"passiveUnlocked": "Passive freigeschaltet",
|
||||||
"passiveLocked": "Passive gesperrt",
|
"passiveLocked": "Passive gesperrt",
|
||||||
|
"ribbon": "Band",
|
||||||
"hasWon": "Hat Klassik-Modus gewonnen",
|
"hasWon": "Hat Klassik-Modus gewonnen",
|
||||||
"hasNotWon": "Hat Klassik-Modus nicht gewonnen",
|
"hasNotWon": "Hat Klassik-Modus nicht gewonnen",
|
||||||
"sortByNumber": "Pokédex-Nummer",
|
"sortByNumber": "Pokédex-Nummer",
|
||||||
|
@ -3,16 +3,19 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
|||||||
export const filterBar: SimpleTranslationEntries = {
|
export const filterBar: SimpleTranslationEntries = {
|
||||||
"genFilter": "Gen",
|
"genFilter": "Gen",
|
||||||
"typeFilter": "Type",
|
"typeFilter": "Type",
|
||||||
|
"dexFilter": "Dex",
|
||||||
"unlocksFilter": "Unlocks",
|
"unlocksFilter": "Unlocks",
|
||||||
"winFilter": "Win",
|
"miscFilter": "Misc",
|
||||||
"sortFilter": "Sort",
|
"sortFilter": "Sort",
|
||||||
"all": "All",
|
"all": "All",
|
||||||
"normal": "Normal",
|
"normal": "Normal",
|
||||||
"uncaught": "Uncaught",
|
"uncaught": "Uncaught",
|
||||||
|
"passive": "Passive",
|
||||||
"passiveUnlocked": "Passive Unlocked",
|
"passiveUnlocked": "Passive Unlocked",
|
||||||
"passiveLocked": "Passive Locked",
|
"passiveLocked": "Passive Locked",
|
||||||
"hasWon": "Yes",
|
"ribbon": "Ribbon",
|
||||||
"hasNotWon": "No",
|
"hasWon": "Ribbon - Yes",
|
||||||
|
"hasNotWon": "Ribbon - No",
|
||||||
"sortByNumber": "No.",
|
"sortByNumber": "No.",
|
||||||
"sortByCost": "Cost",
|
"sortByCost": "Cost",
|
||||||
"sortByCandies": "Candy Count",
|
"sortByCandies": "Candy Count",
|
||||||
|
@ -3,14 +3,17 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
|||||||
export const filterBar: SimpleTranslationEntries = {
|
export const filterBar: SimpleTranslationEntries = {
|
||||||
"genFilter": "Gen.",
|
"genFilter": "Gen.",
|
||||||
"typeFilter": "Tipo",
|
"typeFilter": "Tipo",
|
||||||
|
"dexFilter": "Dex",
|
||||||
"unlocksFilter": "Otros",
|
"unlocksFilter": "Otros",
|
||||||
"winFilter": "Vic.",
|
"miscFilter": "Misc",
|
||||||
"sortFilter": "Orden",
|
"sortFilter": "Orden",
|
||||||
"all": "Todo",
|
"all": "Todo",
|
||||||
"normal": "Normal",
|
"normal": "Normal",
|
||||||
"uncaught": "No Capt.",
|
"uncaught": "No Capt.",
|
||||||
|
"passive": "Passive",
|
||||||
"passiveUnlocked": "Pasiva Desbloq.",
|
"passiveUnlocked": "Pasiva Desbloq.",
|
||||||
"passiveLocked": "Pasiva Bloq.",
|
"passiveLocked": "Pasiva Bloq.",
|
||||||
|
"ribbon": "Ribbon",
|
||||||
"hasWon": "Ya ha ganado",
|
"hasWon": "Ya ha ganado",
|
||||||
"hasNotWon": "Aún no ha ganado",
|
"hasNotWon": "Aún no ha ganado",
|
||||||
"sortByNumber": "Núm.",
|
"sortByNumber": "Núm.",
|
||||||
|
@ -3,16 +3,19 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
|||||||
export const filterBar: SimpleTranslationEntries = {
|
export const filterBar: SimpleTranslationEntries = {
|
||||||
"genFilter": "Gen",
|
"genFilter": "Gen",
|
||||||
"typeFilter": "Type",
|
"typeFilter": "Type",
|
||||||
"unlocksFilter": "Autres",
|
"dexFilter": "Dex",
|
||||||
"winFilter": "Victoires",
|
"unlocksFilter": "Débloq.",
|
||||||
|
"miscFilter": "Divers",
|
||||||
"sortFilter": "Tri",
|
"sortFilter": "Tri",
|
||||||
"all": "Tous",
|
"all": "Tous",
|
||||||
"normal": "Normal",
|
"normal": "Normal",
|
||||||
"uncaught": "Non-capturé",
|
"uncaught": "Non-capturé",
|
||||||
|
"passive": "Passif",
|
||||||
"passiveUnlocked": "Passif débloqué",
|
"passiveUnlocked": "Passif débloqué",
|
||||||
"passiveLocked": "Passif verrouillé",
|
"passiveLocked": "Passif verrouillé",
|
||||||
"hasWon": "Oui",
|
"ribbon": "Médaille",
|
||||||
"hasNotWon": "Aucune",
|
"hasWon": "Médaille - Oui",
|
||||||
|
"hasNotWon": "Médaille - Non",
|
||||||
"sortByNumber": "Par N°",
|
"sortByNumber": "Par N°",
|
||||||
"sortByCost": "Par cout",
|
"sortByCost": "Par cout",
|
||||||
"sortByCandies": "Par # bonbons",
|
"sortByCandies": "Par # bonbons",
|
||||||
|
@ -3,16 +3,19 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
|||||||
export const filterBar: SimpleTranslationEntries = {
|
export const filterBar: SimpleTranslationEntries = {
|
||||||
"genFilter": "Gen",
|
"genFilter": "Gen",
|
||||||
"typeFilter": "Tipo",
|
"typeFilter": "Tipo",
|
||||||
|
"dexFilter": "Dex",
|
||||||
"unlocksFilter": "Altro",
|
"unlocksFilter": "Altro",
|
||||||
"winFilter": "Vinto",
|
"miscFilter": "Misc",
|
||||||
"sortFilter": "Ordina",
|
"sortFilter": "Ordina",
|
||||||
"all": "Tutto",
|
"all": "Tutto",
|
||||||
"normal": "Normale",
|
"normal": "Normale",
|
||||||
"uncaught": "Mancante",
|
"uncaught": "Mancante",
|
||||||
|
"passive": "Passive",
|
||||||
"passiveUnlocked": "Passiva sbloccata",
|
"passiveUnlocked": "Passiva sbloccata",
|
||||||
"passiveLocked": "Passiva bloccata",
|
"passiveLocked": "Passiva bloccata",
|
||||||
"hasWon": "Si",
|
"ribbon": "Ribbon",
|
||||||
"hasNotWon": "No",
|
"hasWon": "Ribbon - Yes",
|
||||||
|
"hasNotWon": "Ribbon - No",
|
||||||
"sortByNumber": "Num. Dex",
|
"sortByNumber": "Num. Dex",
|
||||||
"sortByCost": "Costo",
|
"sortByCost": "Costo",
|
||||||
"sortByCandies": "Caramelle",
|
"sortByCandies": "Caramelle",
|
||||||
|
@ -3,16 +3,19 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
|||||||
export const filterBar: SimpleTranslationEntries = {
|
export const filterBar: SimpleTranslationEntries = {
|
||||||
"genFilter": "세대",
|
"genFilter": "세대",
|
||||||
"typeFilter": "타입",
|
"typeFilter": "타입",
|
||||||
"unlocksFilter": "등록",
|
"dexFilter": "도감",
|
||||||
"winFilter": "클리어",
|
"unlocksFilter": "해금",
|
||||||
|
"miscFilter": "기타",
|
||||||
"sortFilter": "정렬",
|
"sortFilter": "정렬",
|
||||||
"all": "전체",
|
"all": "전체",
|
||||||
"normal": "기본",
|
"normal": "기본",
|
||||||
"uncaught": "미포획",
|
"uncaught": "미포획",
|
||||||
|
"passive": "패시브",
|
||||||
"passiveUnlocked": "패시브 해금",
|
"passiveUnlocked": "패시브 해금",
|
||||||
"passiveLocked": "패시브 잠김",
|
"passiveLocked": "패시브 잠김",
|
||||||
"hasWon": "완료",
|
"ribbon": "클리어 여부",
|
||||||
"hasNotWon": "미완료",
|
"hasWon": "클리어 함",
|
||||||
|
"hasNotwon": "클리어 안함",
|
||||||
"sortByNumber": "도감번호",
|
"sortByNumber": "도감번호",
|
||||||
"sortByCost": "코스트",
|
"sortByCost": "코스트",
|
||||||
"sortByCandies": "사탕 수",
|
"sortByCandies": "사탕 수",
|
||||||
|
@ -3,16 +3,19 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
|||||||
export const filterBar: SimpleTranslationEntries = {
|
export const filterBar: SimpleTranslationEntries = {
|
||||||
"genFilter": "Ger.",
|
"genFilter": "Ger.",
|
||||||
"typeFilter": "Tipo",
|
"typeFilter": "Tipo",
|
||||||
|
"dexFilter": "Dex",
|
||||||
"unlocksFilter": "Outros",
|
"unlocksFilter": "Outros",
|
||||||
"winFilter": "Vit.",
|
"miscFilter": "Misc",
|
||||||
"sortFilter": "Ordem",
|
"sortFilter": "Ordem",
|
||||||
"all": "Tudo",
|
"all": "Tudo",
|
||||||
"normal": "Normal",
|
"normal": "Normal",
|
||||||
"uncaught": "Não Capturado",
|
"uncaught": "Não Capturado",
|
||||||
|
"passive": "Passive",
|
||||||
"passiveUnlocked": "Passiva Desbloq.",
|
"passiveUnlocked": "Passiva Desbloq.",
|
||||||
"passiveLocked": "Passiva Bloq.",
|
"passiveLocked": "Passiva Bloq.",
|
||||||
"hasWon": "Sim",
|
"ribbon": "Ribbon",
|
||||||
"hasNotWon": "Não",
|
"hasWon": "Ribbon - Yes",
|
||||||
|
"hasNotWon": "Ribbon - No",
|
||||||
"sortByNumber": "Núm.",
|
"sortByNumber": "Núm.",
|
||||||
"sortByCost": "Custo",
|
"sortByCost": "Custo",
|
||||||
"sortByCandies": "# Doces",
|
"sortByCandies": "# Doces",
|
||||||
|
@ -3,16 +3,19 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
|||||||
export const filterBar: SimpleTranslationEntries = {
|
export const filterBar: SimpleTranslationEntries = {
|
||||||
"genFilter": "世代",
|
"genFilter": "世代",
|
||||||
"typeFilter": "属性",
|
"typeFilter": "属性",
|
||||||
|
"dexFilter": "Dex",
|
||||||
"unlocksFilter": "解锁",
|
"unlocksFilter": "解锁",
|
||||||
"winFilter": "通关",
|
"miscFilter": "混合",
|
||||||
"sortFilter": "排序",
|
"sortFilter": "排序",
|
||||||
"all": "全部",
|
"all": "全部",
|
||||||
"normal": "无闪光",
|
"normal": "无闪光",
|
||||||
"uncaught": "未捕获",
|
"uncaught": "未捕获",
|
||||||
|
"passive": "被动",
|
||||||
"passiveUnlocked": "被动解锁",
|
"passiveUnlocked": "被动解锁",
|
||||||
"passiveLocked": "被动未解锁",
|
"passiveLocked": "被动未解锁",
|
||||||
"hasWon": "已通关",
|
"ribbon": "缎带",
|
||||||
"hasNotWon": "未通关",
|
"hasWon": "有缎带",
|
||||||
|
"hasNotWon": "无缎带",
|
||||||
"sortByNumber": "编号",
|
"sortByNumber": "编号",
|
||||||
"sortByCost": "费用",
|
"sortByCost": "费用",
|
||||||
"sortByCandies": "糖果",
|
"sortByCandies": "糖果",
|
||||||
|
@ -3,16 +3,19 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
|||||||
export const filterBar: SimpleTranslationEntries = {
|
export const filterBar: SimpleTranslationEntries = {
|
||||||
"genFilter": "世代",
|
"genFilter": "世代",
|
||||||
"typeFilter": "屬性",
|
"typeFilter": "屬性",
|
||||||
|
"dexFilter": "Dex",
|
||||||
"unlocksFilter": "解鎖",
|
"unlocksFilter": "解鎖",
|
||||||
"winFilter": "通關",
|
"miscFilter": "混合",
|
||||||
"sortFilter": "排序",
|
"sortFilter": "排序",
|
||||||
"all": "全部",
|
"all": "全部",
|
||||||
"normal": "通常",
|
"normal": "通常",
|
||||||
"uncaught": "未捕獲",
|
"uncaught": "未捕獲",
|
||||||
|
"passive": "被動",
|
||||||
"passiveUnlocked": "被動解鎖",
|
"passiveUnlocked": "被動解鎖",
|
||||||
"passiveLocked": "被動未解鎖",
|
"passiveLocked": "被動未解鎖",
|
||||||
"hasWon": "已通關",
|
"ribbon": "緞帶",
|
||||||
"hasNotWon": "未通關",
|
"hasWon": "有緞帶",
|
||||||
|
"hasNotWon": "無緞帶",
|
||||||
"sortByNumber": "編號",
|
"sortByNumber": "編號",
|
||||||
"sortByCost": "花費",
|
"sortByCost": "花費",
|
||||||
"sortByCandies": "糖果",
|
"sortByCandies": "糖果",
|
||||||
|
@ -7,14 +7,14 @@ import i18next from "i18next";
|
|||||||
export enum DropDownState {
|
export enum DropDownState {
|
||||||
ON = 0,
|
ON = 0,
|
||||||
OFF = 1,
|
OFF = 1,
|
||||||
INCLUDE = 2,
|
EXCLUDE = 2
|
||||||
EXCLUDE = 3,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DropDownType {
|
export enum DropDownType {
|
||||||
MULTI = 0,
|
SINGLE = 0,
|
||||||
SINGLE = 1,
|
MULTI = 1,
|
||||||
TRI = 2
|
HYBRID = 2,
|
||||||
|
RADIAL = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum SortDirection {
|
export enum SortDirection {
|
||||||
@ -22,130 +22,252 @@ export enum SortDirection {
|
|||||||
DESC = 1
|
DESC = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class DropDownLabel {
|
||||||
|
public state: DropDownState;
|
||||||
|
public text: string;
|
||||||
|
public sprite?: Phaser.GameObjects.Sprite;
|
||||||
|
|
||||||
|
constructor(label: string, sprite?: Phaser.GameObjects.Sprite, state: DropDownState = DropDownState.ON) {
|
||||||
|
this.text = label || "";
|
||||||
|
this.sprite = sprite;
|
||||||
|
this.state = state || DropDownState.ON;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export class DropDownOption extends Phaser.GameObjects.Container {
|
export class DropDownOption extends Phaser.GameObjects.Container {
|
||||||
public state: DropDownState = DropDownState.ON;
|
public state: DropDownState = DropDownState.ON;
|
||||||
public toggle: Phaser.GameObjects.Sprite;
|
public toggle: Phaser.GameObjects.Sprite;
|
||||||
public text: Phaser.GameObjects.Text;
|
public text: Phaser.GameObjects.Text;
|
||||||
public sprite?: Phaser.GameObjects.Sprite;
|
|
||||||
public val: any;
|
public val: any;
|
||||||
public dir: SortDirection = SortDirection.ASC;
|
public dir: SortDirection = SortDirection.ASC;
|
||||||
public offStateLabel: string; // label for OFF state in TRI dropdown
|
private currentLabelIndex: number;
|
||||||
public includeStateLabel: string; // label for INCLUDE state in TRI dropdown
|
private labels: DropDownLabel[];
|
||||||
public excludeStateLabel: string; // label for EXCLUDE state in TRI dropdown
|
private onColor = 0x33bbff;
|
||||||
private onColor = 0x55ff55;
|
|
||||||
private offColor = 0x272727;
|
private offColor = 0x272727;
|
||||||
private includeColor = 0x55ff55;
|
|
||||||
private excludeColor = 0xff5555;
|
private excludeColor = 0xff5555;
|
||||||
|
|
||||||
|
constructor(scene: SceneBase, val: any, labels: DropDownLabel | DropDownLabel[]) {
|
||||||
constructor(scene: SceneBase, val: any, text: string | string[], sprite?: Phaser.GameObjects.Sprite, state: DropDownState = DropDownState.ON) {
|
|
||||||
super(scene);
|
super(scene);
|
||||||
this.val = val;
|
this.val = val;
|
||||||
this.state = state;
|
|
||||||
if (text) {
|
|
||||||
if (Array.isArray(text)) {
|
|
||||||
this.offStateLabel = text[0];
|
|
||||||
this.includeStateLabel = text[1];
|
|
||||||
this.excludeStateLabel = text[2];
|
|
||||||
text = text[0];
|
|
||||||
} else {
|
|
||||||
this.offStateLabel = undefined;
|
|
||||||
this.includeStateLabel = undefined;
|
|
||||||
this.excludeStateLabel = undefined;
|
|
||||||
}
|
|
||||||
this.text = addTextObject(scene, 0, 0, text, TextStyle.TOOLTIP_CONTENT);
|
|
||||||
this.text.setOrigin(0, 0.5);
|
|
||||||
this.add(this.text);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sprite) {
|
if (Array.isArray(labels)) {
|
||||||
this.sprite = sprite.setOrigin(0, 0.5);
|
this.labels = labels;
|
||||||
this.add(this.sprite);
|
} else {
|
||||||
|
this.labels = labels? [ labels ] : [ new DropDownLabel("") ];
|
||||||
|
}
|
||||||
|
this.currentLabelIndex = 0;
|
||||||
|
const currentLabel = this.labels[this.currentLabelIndex];
|
||||||
|
|
||||||
|
this.state = currentLabel.state;
|
||||||
|
this.text = addTextObject(scene, 0, 0, currentLabel.text || "", TextStyle.TOOLTIP_CONTENT);
|
||||||
|
this.text.setOrigin(0, 0.5);
|
||||||
|
this.add(this.text);
|
||||||
|
|
||||||
|
// Add to container the sprite for each label if there is one
|
||||||
|
for (let i=0; i < this.labels.length; i++) {
|
||||||
|
const sprite = this.labels[i].sprite;
|
||||||
|
if (sprite) {
|
||||||
|
this.add(sprite);
|
||||||
|
sprite.setOrigin(0, 0.5);
|
||||||
|
if (i!== this.currentLabelIndex) {
|
||||||
|
sprite.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setupToggle(type: DropDownType): void {
|
/**
|
||||||
if (type === DropDownType.MULTI || type === DropDownType.TRI) {
|
* Initialize the toggle icon based on the provided DropDownType
|
||||||
this.toggle = this.scene.add.sprite(0, 0, "candy");
|
* For DropDownType.SINGLE: uses a cursor arrow icon
|
||||||
this.toggle.setScale(0.3);
|
* For other types: uses a candy icon
|
||||||
this.toggle.setOrigin(0, 0.5);
|
* @param type the DropDownType to use
|
||||||
} else {
|
* @param visible whether the icon should be visible or not
|
||||||
|
*/
|
||||||
|
setupToggleIcon(type: DropDownType, visible: boolean): void {
|
||||||
|
if (type === DropDownType.SINGLE) {
|
||||||
this.toggle = this.scene.add.sprite(0, 0, "cursor");
|
this.toggle = this.scene.add.sprite(0, 0, "cursor");
|
||||||
this.toggle.setScale(0.5);
|
this.toggle.setScale(0.5);
|
||||||
this.toggle.setOrigin(0, 0.5);
|
this.toggle.setOrigin(0, 0.5);
|
||||||
this.toggle.setRotation(Math.PI / 180 * -90);
|
this.toggle.setRotation(Math.PI / 180 * -90);
|
||||||
|
} else {
|
||||||
|
this.toggle = this.scene.add.sprite(0, 0, "candy");
|
||||||
|
this.toggle.setScale(0.3);
|
||||||
|
this.toggle.setOrigin(0, 0.5);
|
||||||
}
|
}
|
||||||
this.add(this.toggle);
|
this.add(this.toggle);
|
||||||
|
this.toggle.setVisible(visible);
|
||||||
|
this.updateToggleIconColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public setOptionState(type: DropDownType, state: DropDownState): DropDownState {
|
/**
|
||||||
this.state = state;
|
* Set the toggle icon color based on the current state
|
||||||
// if type is MULTI or SINGLE, set the color of the toggle based on the state
|
*/
|
||||||
if (type === DropDownType.MULTI || type === DropDownType.SINGLE) {
|
private updateToggleIconColor(): void {
|
||||||
if (this.state === DropDownState.OFF) {
|
switch (this.state) {
|
||||||
this.toggle.setTint(this.offColor);
|
case DropDownState.ON:
|
||||||
} else if (this.state === DropDownState.ON) {
|
this.toggle.setTint(this.onColor);
|
||||||
this.toggle.setTint(this.onColor);
|
break;
|
||||||
}
|
case DropDownState.OFF:
|
||||||
} else if (type === DropDownType.TRI) {
|
this.toggle.setTint(this.offColor);
|
||||||
if (this.state === DropDownState.OFF) {
|
break;
|
||||||
this.text.setText(this.offStateLabel);
|
case DropDownState.EXCLUDE:
|
||||||
this.toggle.setTint(this.offColor);
|
this.toggle.setTint(this.excludeColor);
|
||||||
} else if (this.state === DropDownState.INCLUDE) {
|
break;
|
||||||
this.text.setText(this.includeStateLabel);
|
|
||||||
this.toggle.setTint(this.includeColor);
|
|
||||||
} else if (this.state === DropDownState.EXCLUDE) {
|
|
||||||
this.text.setText(this.excludeStateLabel);
|
|
||||||
this.toggle.setTint(this.excludeColor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch the option to its next state and update visuals
|
||||||
|
* If only ON/OFF are possible, toggle between the two
|
||||||
|
* For radials, move to the next state in the list
|
||||||
|
* @returns the updated DropDownState
|
||||||
|
*/
|
||||||
|
public toggleOptionState(): DropDownState {
|
||||||
|
if (this.labels.length > 1) {
|
||||||
|
return this.setCurrentLabel((this.currentLabelIndex + 1) % this.labels.length);
|
||||||
|
}
|
||||||
|
const newState = this.state === DropDownState.ON ? DropDownState.OFF : DropDownState.ON;
|
||||||
|
return this.setOptionState(newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the option to the given state and update visuals
|
||||||
|
* @param newState the state to switch to
|
||||||
|
* @returns the new DropDownState
|
||||||
|
*/
|
||||||
|
public setOptionState(newState: DropDownState): DropDownState {
|
||||||
|
const newLabelIndex = this.labels.findIndex(label => label.state === newState);
|
||||||
|
if (newLabelIndex !== -1 && newLabelIndex !== this.currentLabelIndex) {
|
||||||
|
return this.setCurrentLabel(newLabelIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state = newState;
|
||||||
|
this.updateToggleIconColor();
|
||||||
|
return newState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the option state to the one at the given index and update visuals
|
||||||
|
* @param index index of the state to switch to
|
||||||
|
* @returns the new DropDownState
|
||||||
|
*/
|
||||||
|
private setCurrentLabel(index: number): DropDownState {
|
||||||
|
const currentLabel = this.labels[this.currentLabelIndex];
|
||||||
|
const newLabel = this.labels[index];
|
||||||
|
|
||||||
|
if (!newLabel) {
|
||||||
|
return this.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentLabelIndex = index;
|
||||||
|
|
||||||
|
// update state, sprite and text to fit the new label
|
||||||
|
this.state = newLabel.state;
|
||||||
|
this.updateToggleIconColor();
|
||||||
|
|
||||||
|
if (currentLabel.sprite) {
|
||||||
|
this.text.x -= currentLabel.sprite.displayWidth + 2;
|
||||||
|
currentLabel.sprite.setVisible(false);
|
||||||
|
}
|
||||||
|
if (newLabel.sprite) {
|
||||||
|
this.text.x += newLabel.sprite.displayWidth + 2;
|
||||||
|
newLabel.sprite.setVisible(true);
|
||||||
|
}
|
||||||
|
this.text.setText(newLabel.text);
|
||||||
|
|
||||||
return this.state;
|
return this.state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toggleOptionState(type: DropDownType): DropDownState {
|
/**
|
||||||
if (type === DropDownType.TRI) {
|
* Set the current SortDirection to the provided value and update icon accordingly
|
||||||
switch (this.state) {
|
* @param SortDirection the new SortDirection to use
|
||||||
case DropDownState.OFF:
|
*/
|
||||||
this.state = DropDownState.INCLUDE;
|
|
||||||
break;
|
|
||||||
case DropDownState.INCLUDE:
|
|
||||||
this.state = DropDownState.EXCLUDE;
|
|
||||||
break;
|
|
||||||
case DropDownState.EXCLUDE:
|
|
||||||
this.state = DropDownState.OFF;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (this.state) {
|
|
||||||
case DropDownState.ON:
|
|
||||||
this.state = DropDownState.OFF;
|
|
||||||
break;
|
|
||||||
case DropDownState.OFF:
|
|
||||||
this.state = DropDownState.ON;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this.setOptionState(type, this.state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public setDirection(dir: SortDirection): void {
|
public setDirection(dir: SortDirection): void {
|
||||||
this.dir = dir;
|
this.dir = dir;
|
||||||
this.toggle.flipX = this.dir === SortDirection.DESC;
|
this.toggle.flipX = this.dir === SortDirection.DESC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle the current SortDirection value
|
||||||
|
*/
|
||||||
public toggleDirection(): void {
|
public toggleDirection(): void {
|
||||||
this.setDirection(this.dir * -1);
|
this.setDirection(this.dir * -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Place the label elements (text and sprite if there is one) to the provided x and y position
|
||||||
|
* @param x the horizontal position
|
||||||
|
* @param y the vertical position
|
||||||
|
*/
|
||||||
|
setLabelPosition(x: number, y: number) {
|
||||||
|
let textX = x;
|
||||||
|
for (let i=0; i < this.labels.length; i++) {
|
||||||
|
const label = this.labels[i];
|
||||||
|
if (label.sprite) {
|
||||||
|
label.sprite.x = x;
|
||||||
|
label.sprite.y = y;
|
||||||
|
if (i === this.currentLabelIndex) {
|
||||||
|
textX += label.sprite.displayWidth + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.text) {
|
||||||
|
this.text.x = textX;
|
||||||
|
this.text.y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Place the toggle icon at the provided position
|
||||||
|
* @param x the horizontal position
|
||||||
|
* @param y the vertical position
|
||||||
|
*/
|
||||||
|
setTogglePosition(x: number, y: number) {
|
||||||
|
if (this.toggle) {
|
||||||
|
this.toggle.x = x;
|
||||||
|
this.toggle.y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the x position to use for the current label depending on if it has a sprite or not
|
||||||
|
*/
|
||||||
|
getCurrentLabelX(): number {
|
||||||
|
if (this.labels[this.currentLabelIndex].sprite) {
|
||||||
|
return this.labels[this.currentLabelIndex].sprite.x;
|
||||||
|
}
|
||||||
|
return this.text.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns max width needed to display all of the labels
|
||||||
|
*/
|
||||||
|
getWidth(): number {
|
||||||
|
let w = 0;
|
||||||
|
const currentText = this.text.text;
|
||||||
|
for (const label of this.labels) {
|
||||||
|
this.text.setText(label.text);
|
||||||
|
const spriteWidth = label.sprite? label.sprite.displayWidth + 2 : 0;
|
||||||
|
w = Math.max(w, this.text.displayWidth + spriteWidth);
|
||||||
|
}
|
||||||
|
this.text.setText(currentText);
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class DropDown extends Phaser.GameObjects.Container {
|
export class DropDown extends Phaser.GameObjects.Container {
|
||||||
public options: DropDownOption[];
|
public options: DropDownOption[];
|
||||||
private window: Phaser.GameObjects.NineSlice;
|
private window: Phaser.GameObjects.NineSlice;
|
||||||
private cursorObj: Phaser.GameObjects.Image;
|
private cursorObj: Phaser.GameObjects.Image;
|
||||||
private dropDownType: DropDownType = DropDownType.MULTI;
|
private dropDownType: DropDownType = DropDownType.MULTI;
|
||||||
public cursor: integer = 0;
|
public cursor: number = 0;
|
||||||
|
public defaultCursor: number = 0;
|
||||||
private onChange: () => void;
|
private onChange: () => void;
|
||||||
private lastDir: SortDirection = SortDirection.ASC;
|
private lastDir: SortDirection = SortDirection.ASC;
|
||||||
|
private defaultValues: any[];
|
||||||
|
|
||||||
constructor(scene: BattleScene, x: number, y: number, options: DropDownOption[], onChange: () => void, type: DropDownType = DropDownType.MULTI, optionSpacing: number = 2) {
|
constructor(scene: BattleScene, x: number, y: number, options: DropDownOption[], onChange: () => void, type: DropDownType = DropDownType.MULTI, optionSpacing: number = 2) {
|
||||||
const windowPadding = 5;
|
const windowPadding = 5;
|
||||||
@ -165,36 +287,31 @@ export class DropDown extends Phaser.GameObjects.Container {
|
|||||||
this.cursorObj.setOrigin(0, 0.5);
|
this.cursorObj.setOrigin(0, 0.5);
|
||||||
this.cursorObj.setVisible(false);
|
this.cursorObj.setVisible(false);
|
||||||
|
|
||||||
if (this.dropDownType === DropDownType.MULTI) {
|
// For MULTI and HYBRID filter, add an ALL option at the top
|
||||||
this.options.unshift(new DropDownOption(scene, "ALL", i18next.t("filterBar:all"), null, this.checkForAllOn() ? DropDownState.ON : DropDownState.OFF));
|
if (this.dropDownType === DropDownType.MULTI || this.dropDownType === DropDownType.HYBRID) {
|
||||||
|
this.options.unshift(new DropDownOption(scene, "ALL", new DropDownLabel(i18next.t("filterBar:all"), undefined, this.checkForAllOn() ? DropDownState.ON : DropDownState.OFF)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.defaultValues = this.getVals();
|
||||||
|
|
||||||
|
// Place ui elements in the correct spot
|
||||||
options.forEach((option, index) => {
|
options.forEach((option, index) => {
|
||||||
option.setupToggle(type);
|
const toggleVisibility = type !== DropDownType.SINGLE || option.state === DropDownState.ON;
|
||||||
if (type === DropDownType.SINGLE && option.state === DropDownState.OFF) {
|
option.setupToggleIcon(type, toggleVisibility);
|
||||||
option.toggle.setVisible(false);
|
|
||||||
}
|
|
||||||
option.setOptionState(type, option.state);
|
|
||||||
|
|
||||||
option.width = optionWidth;
|
option.width = optionWidth;
|
||||||
option.y = index * optionHeight + index * optionSpacing + optionPaddingY;
|
option.y = index * optionHeight + index * optionSpacing + optionPaddingY;
|
||||||
|
|
||||||
if (option.text) {
|
const baseX = cursorOffset + optionPaddingX + 3;
|
||||||
option.text.x = cursorOffset + optionPaddingX + 3 + 8;
|
const baseY = optionHeight / 2;
|
||||||
option.text.y = optionHeight / 2;
|
option.setLabelPosition(baseX + 8, baseY);
|
||||||
}
|
|
||||||
if (option.sprite) {
|
|
||||||
option.sprite.x = cursorOffset + optionPaddingX + 3 + 8;
|
|
||||||
option.sprite.y = optionHeight / 2;
|
|
||||||
}
|
|
||||||
if (type === DropDownType.SINGLE) {
|
if (type === DropDownType.SINGLE) {
|
||||||
option.toggle.x = cursorOffset + optionPaddingX + 3 + 3;
|
option.setTogglePosition(baseX + 3, baseY + 1);
|
||||||
option.toggle.y = optionHeight / 2 + 1;
|
|
||||||
} else {
|
} else {
|
||||||
option.toggle.x = cursorOffset + optionPaddingX + 3;
|
option.setTogglePosition(baseX, baseY);
|
||||||
option.toggle.y = optionHeight / 2;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.window = addWindow(scene, 0, 0, optionWidth, options[options.length - 1].y + optionHeight + optionPaddingY, false, false, null, null, WindowVariant.XTHIN);
|
this.window = addWindow(scene, 0, 0, optionWidth, options[options.length - 1].y + optionHeight + optionPaddingY, false, false, null, null, WindowVariant.XTHIN);
|
||||||
this.add(this.window);
|
this.add(this.window);
|
||||||
this.add(options);
|
this.add(options);
|
||||||
@ -202,10 +319,32 @@ export class DropDown extends Phaser.GameObjects.Container {
|
|||||||
this.setVisible(false);
|
this.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle(): void {
|
getWidth(): number {
|
||||||
|
return this.window? this.window.width : this.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleVisibility(): void {
|
||||||
this.setVisible(!this.visible);
|
this.setVisible(!this.visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setVisible(value: boolean): this {
|
||||||
|
super.setVisible(value);
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
this.autoSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return this.setCursor(this.defaultCursor);
|
||||||
|
}
|
||||||
|
|
||||||
setCursor(cursor: integer): boolean {
|
setCursor(cursor: integer): boolean {
|
||||||
this.cursor = cursor;
|
this.cursor = cursor;
|
||||||
if (cursor < 0) {
|
if (cursor < 0) {
|
||||||
@ -220,96 +359,213 @@ export class DropDown extends Phaser.GameObjects.Container {
|
|||||||
} else {
|
} else {
|
||||||
this.cursorObj.y = this.options[cursor].y + 3.5;
|
this.cursorObj.y = this.options[cursor].y + 3.5;
|
||||||
this.cursorObj.setVisible(true);
|
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.onChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleOptionState(): void {
|
/**
|
||||||
if (this.dropDownType === DropDownType.MULTI) {
|
* Switch the option at the provided index to its next state and update visuals
|
||||||
const newState = this.options[this.cursor].toggleOptionState(this.dropDownType);
|
* Update accordingly the other options if needed:
|
||||||
if (this.cursor === 0) {
|
* - if "all" is toggled, also update all other options
|
||||||
this.options.forEach((option, index) => {
|
* - for DropDownType.SINGLE, unselect the previously selected option if applicable
|
||||||
if (index !== this.cursor) {
|
* @param index the index of the option for which to update the state
|
||||||
option.setOptionState(this.dropDownType, newState);
|
*/
|
||||||
}
|
toggleOptionState(index: number = this.cursor): void {
|
||||||
});
|
const option: DropDownOption = this.options[index];
|
||||||
|
if (this.dropDownType === DropDownType.MULTI || this.dropDownType === DropDownType.HYBRID) {
|
||||||
|
const newState = option.toggleOptionState();
|
||||||
|
if (index === 0) {
|
||||||
|
// we are on the All option > put all other options to the newState
|
||||||
|
this.setAllOptions(newState);
|
||||||
} else {
|
} else {
|
||||||
if (this.checkForAllOff()) {
|
// select the "all" option if all others are selected, other unselect it
|
||||||
this.options[0].setOptionState(this.dropDownType, DropDownState.OFF);
|
if (newState === DropDownState.ON && this.checkForAllOn()) {
|
||||||
} else if (this.checkForAllOn()) {
|
this.options[0].setOptionState(DropDownState.ON);
|
||||||
this.options[0].setOptionState(this.dropDownType, DropDownState.ON);
|
|
||||||
} else {
|
} else {
|
||||||
this.options[0].setOptionState(this.dropDownType, DropDownState.OFF);
|
this.options[0].setOptionState(DropDownState.OFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (this.dropDownType === DropDownType.SINGLE) {
|
} else if (this.dropDownType === DropDownType.SINGLE) {
|
||||||
if (this.options[this.cursor].state === DropDownState.OFF) {
|
if (option.state === DropDownState.OFF) {
|
||||||
this.options.forEach((option) => {
|
this.options.forEach((option) => {
|
||||||
option.setOptionState(this.dropDownType, DropDownState.OFF);
|
option.setOptionState(DropDownState.OFF);
|
||||||
option.setDirection(SortDirection.ASC);
|
option.setDirection(SortDirection.ASC);
|
||||||
option.toggle.setVisible(false);
|
option.toggle.setVisible(false);
|
||||||
});
|
});
|
||||||
this.options[this.cursor].setOptionState(this.dropDownType, DropDownState.ON);
|
option.setOptionState(DropDownState.ON);
|
||||||
this.options[this.cursor].setDirection(this.lastDir);
|
option.setDirection(this.lastDir);
|
||||||
this.options[this.cursor].toggle.setVisible(true);
|
option.toggle.setVisible(true);
|
||||||
} else {
|
} else {
|
||||||
this.options[this.cursor].toggleDirection();
|
option.toggleDirection();
|
||||||
this.lastDir = this.options[this.cursor].dir;
|
this.lastDir = this.options[this.cursor].dir;
|
||||||
}
|
}
|
||||||
} else if (this.dropDownType === DropDownType.TRI) {
|
} else if (this.dropDownType === DropDownType.RADIAL) {
|
||||||
this.options[this.cursor].toggleOptionState(this.dropDownType);
|
option.toggleOptionState();
|
||||||
this.autoSize();
|
|
||||||
}
|
}
|
||||||
this.onChange();
|
this.onChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
setVisible(value: boolean): this {
|
/**
|
||||||
super.setVisible(value);
|
* Check whether all options except the "ALL" one are ON
|
||||||
|
* @returns true if all options are set to DropDownState.ON, false otherwise
|
||||||
if (value) {
|
*/
|
||||||
this.autoSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkForAllOn(): boolean {
|
checkForAllOn(): boolean {
|
||||||
return this.options.every((option, i) => i === 0 || option.state === DropDownState.ON);
|
return this.options.every((option, i) => i === 0 || option.state === DropDownState.ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether all options except the "ALL" one are OFF
|
||||||
|
* @returns true if all options are set to DropDownState.OFF, false otherwise
|
||||||
|
*/
|
||||||
checkForAllOff(): boolean {
|
checkForAllOff(): boolean {
|
||||||
return this.options.every((option, i) => i === 0 || option.state === DropDownState.OFF);
|
return this.options.every((option, i) => i === 0 || option.state === DropDownState.OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current selected values for each option
|
||||||
|
* @returns an array of values, depending on the DropDownType
|
||||||
|
* - if MULTI or HYBRID, an array of all the values of the options set to ON (except the ALL one)
|
||||||
|
* - if RADIAL, an array where the value for each option is of the form { val: any, state: DropDownState }
|
||||||
|
* - if SINGLE, a single object of the form { val: any, state: SortDirection }
|
||||||
|
*/
|
||||||
getVals(): any[] {
|
getVals(): any[] {
|
||||||
if (this.dropDownType === DropDownType.MULTI) {
|
if (this.dropDownType === DropDownType.MULTI) {
|
||||||
return this.options.filter((option, i) => i > 0 && option.state === DropDownState.ON).map((option) => option.val);
|
return this.options.filter((option, i) => i > 0 && option.state === DropDownState.ON).map((option) => option.val);
|
||||||
// in TRI dropdown, if state is ON, return the "ON" with the value, if state is OFF, return the "OFF" with the value, if state is TRI, return the "TRI" with the value
|
} else if (this.dropDownType === DropDownType.HYBRID) {
|
||||||
} else if (this.dropDownType === DropDownType.TRI) {
|
const selected = this.options.filter((option, i) => i > 0 && option.state === DropDownState.ON).map((option) => option.val);
|
||||||
return this.options.filter((option, i) => option.state === DropDownState.OFF || option.state === DropDownState.INCLUDE || option.state === DropDownState.EXCLUDE).map((option) => {
|
if (selected.length > 0) {
|
||||||
return {val: option.val, state: option.state};
|
return selected;
|
||||||
|
}
|
||||||
|
// if nothing is selected and the ALL option is hovered, return all elements
|
||||||
|
if (this.cursor === 0) {
|
||||||
|
return this.options.filter((_, i) => i > 0).map(option => option.val);
|
||||||
|
}
|
||||||
|
// if nothing is selected and a single option is hovered, return that one
|
||||||
|
return [this.options[this.cursor].val];
|
||||||
|
} else if (this.dropDownType === DropDownType.RADIAL) {
|
||||||
|
return this.options.map((option) => {
|
||||||
|
return { val: option.val, state: option.state };
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return this.options.filter((option, i) => option.state === DropDownState.ON).map((option) => {
|
return this.options.filter(option => option.state === DropDownState.ON).map((option) => {
|
||||||
return {val: option.val, dir: option.dir};
|
return { val: option.val, dir: option.dir };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
|
||||||
|
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"]);
|
||||||
|
|
||||||
|
case DropDownType.SINGLE:
|
||||||
|
return currentValues[0]["dir"] === this.defaultValues[0]["dir"] && currentValues[0]["val"] === this.defaultValues[0]["val"];
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set all values to their default state
|
||||||
|
*/
|
||||||
|
public resetToDefault(): void {
|
||||||
|
this.setCursor(this.defaultCursor);
|
||||||
|
|
||||||
|
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);
|
||||||
|
} 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set all options to a specific state
|
||||||
|
* @param state the DropDownState to assign to each option
|
||||||
|
*/
|
||||||
|
private setAllOptions(state: DropDownState) : void {
|
||||||
|
// For single type dropdown, setting all options is not relevant
|
||||||
|
if (this.dropDownType === DropDownType.SINGLE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const option of this.options) {
|
||||||
|
option.setOptionState(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set all options to their ON state
|
||||||
|
*/
|
||||||
|
public selectAllOptions() {
|
||||||
|
this.setAllOptions(DropDownState.ON);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set all options to their OFF state
|
||||||
|
*/
|
||||||
|
public unselectAllOptions() {
|
||||||
|
this.setAllOptions(DropDownState.OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically set the width and position based on the size of options
|
||||||
|
*/
|
||||||
autoSize(): void {
|
autoSize(): void {
|
||||||
let maxWidth = 0;
|
let maxWidth = 0;
|
||||||
let x = 0;
|
let x = 0;
|
||||||
for (let i = 0; i < this.options.length; i++) {
|
for (let i = 0; i < this.options.length; i++) {
|
||||||
if (this.options[i].sprite) {
|
const optionWidth = this.options[i].getWidth();
|
||||||
if (this.options[i].sprite.displayWidth > maxWidth) {
|
if (optionWidth > maxWidth) {
|
||||||
maxWidth = this.options[i].sprite.displayWidth;
|
maxWidth = optionWidth;
|
||||||
x = this.options[i].sprite.x;
|
x = this.options[i].getCurrentLabelX();
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.options[i].text.displayWidth > maxWidth) {
|
|
||||||
maxWidth = this.options[i].text.displayWidth;
|
|
||||||
x = this.options[i].text.x;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.window.width = maxWidth + x - this.window.x + 6;
|
this.window.width = maxWidth + x - this.window.x + 6;
|
||||||
@ -319,7 +575,4 @@ export class DropDown extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isActive(): boolean {
|
|
||||||
return this.options.some((option) => option.state === DropDownState.ON);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import BattleScene from "#app/battle-scene.js";
|
import BattleScene from "#app/battle-scene.js";
|
||||||
import { DropDown } from "./dropdown";
|
import { DropDown } from "./dropdown";
|
||||||
import { StarterContainer } from "./starter-container";
|
import { StarterContainer } from "./starter-container";
|
||||||
import { addTextObject, TextStyle } from "./text";
|
import { addTextObject, getTextColor, TextStyle } from "./text";
|
||||||
|
import { UiTheme } from "#enums/ui-theme";
|
||||||
import { addWindow, WindowVariant } from "./ui-theme";
|
import { addWindow, WindowVariant } from "./ui-theme";
|
||||||
|
|
||||||
export enum DropDownColumn {
|
export enum DropDownColumn {
|
||||||
GEN,
|
GEN,
|
||||||
TYPES,
|
TYPES,
|
||||||
SHINY,
|
DEX,
|
||||||
UNLOCKS,
|
UNLOCKS,
|
||||||
MISC,
|
MISC,
|
||||||
SORT
|
SORT
|
||||||
@ -15,18 +16,14 @@ export enum DropDownColumn {
|
|||||||
|
|
||||||
export class FilterBar extends Phaser.GameObjects.Container {
|
export class FilterBar extends Phaser.GameObjects.Container {
|
||||||
private window: Phaser.GameObjects.NineSlice;
|
private window: Phaser.GameObjects.NineSlice;
|
||||||
public labels: Phaser.GameObjects.Text[] = [];
|
private labels: Phaser.GameObjects.Text[] = [];
|
||||||
public dropDowns: DropDown[] = [];
|
private dropDowns: DropDown[] = [];
|
||||||
|
private columns: DropDownColumn[] = [];
|
||||||
public cursorObj: Phaser.GameObjects.Image;
|
public cursorObj: Phaser.GameObjects.Image;
|
||||||
public numFilters: number = 0;
|
public numFilters: number = 0;
|
||||||
public openDropDown: boolean = false;
|
public openDropDown: boolean = false;
|
||||||
private lastCursor: number = -1;
|
private lastCursor: number = -1;
|
||||||
public defaultGenVals: any[] = [];
|
private uiTheme: UiTheme;
|
||||||
public defaultTypeVals: any[] = [];
|
|
||||||
public defaultShinyVals: any[] = [];
|
|
||||||
public defaultUnlocksVals: any[] = [];
|
|
||||||
public defaultMiscVals: any[] = [];
|
|
||||||
public defaultSortVals: any[] = [];
|
|
||||||
|
|
||||||
constructor(scene: BattleScene, x: number, y: number, width: number, height: number) {
|
constructor(scene: BattleScene, x: number, y: number, width: number, height: number) {
|
||||||
super(scene, x, y);
|
super(scene, x, y);
|
||||||
@ -42,10 +39,26 @@ export class FilterBar extends Phaser.GameObjects.Container {
|
|||||||
this.cursorObj.setVisible(false);
|
this.cursorObj.setVisible(false);
|
||||||
this.cursorObj.setOrigin(0, 0);
|
this.cursorObj.setOrigin(0, 0);
|
||||||
this.add(this.cursorObj);
|
this.add(this.cursorObj);
|
||||||
|
|
||||||
|
this.uiTheme = scene.uiTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
addFilter(text: string, dropDown: DropDown): void {
|
/**
|
||||||
const filterTypesLabel = addTextObject(this.scene, 0, 3, text, TextStyle.TOOLTIP_CONTENT);
|
* Add a new filter to the FilterBar, as long that a unique DropDownColumn is provided
|
||||||
|
* @param column the DropDownColumn that will be used to access the filter values
|
||||||
|
* @param title the string that will get displayed in the filter bar
|
||||||
|
* @param dropDown the DropDown with all options for this filter
|
||||||
|
* @returns true if successful, false if the provided column was already in use for another filter
|
||||||
|
*/
|
||||||
|
addFilter(column: DropDownColumn, title: string, dropDown: DropDown): boolean {
|
||||||
|
// The column should be unique to each filter,
|
||||||
|
if (this.columns.includes(column)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.columns.push(column);
|
||||||
|
|
||||||
|
const filterTypesLabel = addTextObject(this.scene, 0, 3, title, TextStyle.TOOLTIP_CONTENT);
|
||||||
this.labels.push(filterTypesLabel);
|
this.labels.push(filterTypesLabel);
|
||||||
this.add(filterTypesLabel);
|
this.add(filterTypesLabel);
|
||||||
this.dropDowns.push(dropDown);
|
this.dropDowns.push(dropDown);
|
||||||
@ -53,69 +66,39 @@ export class FilterBar extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
this.calcFilterPositions();
|
this.calcFilterPositions();
|
||||||
this.numFilters++;
|
this.numFilters++;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the DropDown associated to a given filter
|
||||||
|
* @param col the DropDownColumn used to register the filter to retrieve
|
||||||
|
* @returns the associated DropDown if it exists, undefined otherwise
|
||||||
|
*/
|
||||||
|
getFilter(col: DropDownColumn) : DropDown {
|
||||||
|
return this.dropDowns[this.columns.indexOf(col)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlight the labels of the FilterBar if the filters are different from their default values
|
||||||
|
*/
|
||||||
updateFilterLabels(): void {
|
updateFilterLabels(): void {
|
||||||
const genVals = this.getVals(DropDownColumn.GEN);
|
for (let i = 0; i < this.numFilters; i++) {
|
||||||
const typeVals = this.getVals(DropDownColumn.TYPES);
|
if (this.dropDowns[i].hasDefaultValues()) {
|
||||||
const shinyVals = this.getVals(DropDownColumn.SHINY);
|
this.labels[i].setColor(getTextColor(TextStyle.TOOLTIP_CONTENT, false, this.uiTheme));
|
||||||
const unlocksVals = this.getVals(DropDownColumn.UNLOCKS);
|
} else {
|
||||||
const miscVals = this.getVals(DropDownColumn.MISC);
|
this.labels[i].setColor(getTextColor(TextStyle.STATS_LABEL, false, this.uiTheme));
|
||||||
const sortVals = this.getVals(DropDownColumn.SORT);
|
}
|
||||||
|
|
||||||
// onColor is Yellow, offColor is White
|
|
||||||
const onColor = 0xffef5c;
|
|
||||||
const offColor = 0xffffff;
|
|
||||||
|
|
||||||
// if genVals and defaultGenVals has same elements, set the label to offColor else set it to onColor
|
|
||||||
if (genVals.length === this.defaultGenVals.length && genVals.every((value, index) => value === this.defaultGenVals[index])) {
|
|
||||||
this.labels[DropDownColumn.GEN].setTint(offColor);
|
|
||||||
} else {
|
|
||||||
this.labels[DropDownColumn.GEN].setTint(onColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if typeVals and defaultTypeVals has same elements, set the label to offColor else set it to onColor
|
|
||||||
if (typeVals.length === this.defaultTypeVals.length && typeVals.every((value, index) => value === this.defaultTypeVals[index])) {
|
|
||||||
this.labels[DropDownColumn.TYPES].setTint(offColor);
|
|
||||||
} else {
|
|
||||||
this.labels[DropDownColumn.TYPES].setTint(onColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if shinyVals and defaultShinyVals has same elements, set the label to offColor else set it to onColor
|
|
||||||
if (shinyVals.length === this.defaultShinyVals.length && shinyVals.every((value, index) => value === this.defaultShinyVals[index])) {
|
|
||||||
this.labels[DropDownColumn.SHINY].setTint(offColor);
|
|
||||||
} else {
|
|
||||||
this.labels[DropDownColumn.SHINY].setTint(onColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if unlocksVals and defaultUnlocksVals has same elements, set the label to offColor else set it to onColor
|
|
||||||
if (unlocksVals.every((value, index) => value["val"] === this.defaultUnlocksVals[index]["val"] && value["state"] === this.defaultUnlocksVals[index]["state"])) {
|
|
||||||
this.labels[DropDownColumn.UNLOCKS].setTint(offColor);
|
|
||||||
} else {
|
|
||||||
this.labels[DropDownColumn.UNLOCKS].setTint(onColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if miscVals and defaultMiscVals has same elements, set the label to offColor else set it to onColor
|
|
||||||
if (miscVals.every((value, index) => value["val"] === this.defaultMiscVals[index]["val"] && value["state"] === this.defaultMiscVals[index]["state"])) {
|
|
||||||
this.labels[DropDownColumn.MISC].setTint(offColor);
|
|
||||||
} else {
|
|
||||||
this.labels[DropDownColumn.MISC].setTint(onColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if sortVals and defaultSortVals has same value and dir, set the label to offColor else set it to onColor
|
|
||||||
if (sortVals[0]["dir"] === this.defaultSortVals[0]["dir"] && sortVals[0]["val"] === this.defaultSortVals[0]["val"]) {
|
|
||||||
this.labels[DropDownColumn.SORT].setTint(offColor);
|
|
||||||
} else {
|
|
||||||
this.labels[DropDownColumn.SORT].setTint(onColor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
calcFilterPositions(): void {
|
/**
|
||||||
|
* Position the filter dropdowns evenly across the width of the container
|
||||||
|
*/
|
||||||
|
private calcFilterPositions(): void {
|
||||||
const paddingX = 6;
|
const paddingX = 6;
|
||||||
const cursorOffset = 8;
|
const cursorOffset = 8;
|
||||||
|
|
||||||
// position labels with even space across the width of the container
|
|
||||||
let totalWidth = paddingX * 2 + cursorOffset;
|
let totalWidth = paddingX * 2 + cursorOffset;
|
||||||
this.labels.forEach(label => {
|
this.labels.forEach(label => {
|
||||||
totalWidth += label.displayWidth + cursorOffset;
|
totalWidth += label.displayWidth + cursorOffset;
|
||||||
@ -134,12 +117,23 @@ 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setCursor(cursor: number): void {
|
setCursor(cursor: number): void {
|
||||||
if (this.lastCursor > -1) {
|
if (this.lastCursor > -1) {
|
||||||
if (this.dropDowns[this.lastCursor].visible) {
|
if (this.dropDowns[this.lastCursor].visible) {
|
||||||
this.dropDowns[this.lastCursor].setVisible(false);
|
this.dropDowns[this.lastCursor].setVisible(false);
|
||||||
this.dropDowns[cursor].setVisible(true);
|
this.dropDowns[cursor].setVisible(true);
|
||||||
this.dropDowns[cursor].setCursor(0);
|
this.dropDowns[cursor].resetCursor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,9 +143,9 @@ export class FilterBar extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toggleDropDown(index: number): void {
|
toggleDropDown(index: number): void {
|
||||||
this.dropDowns[index].toggle();
|
this.dropDowns[index].toggleVisibility();
|
||||||
this.openDropDown = this.dropDowns[index].visible;
|
this.openDropDown = this.dropDowns[index].visible;
|
||||||
this.dropDowns[index].setCursor(0);
|
this.dropDowns[index].resetCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
hideDropDowns(): void {
|
hideDropDowns(): void {
|
||||||
@ -182,11 +176,22 @@ export class FilterBar extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getVals(col: DropDownColumn): any[] {
|
getVals(col: DropDownColumn): any[] {
|
||||||
return this.dropDowns[col].getVals();
|
return this.getFilter(col).getVals();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setValsToDefault(): void {
|
||||||
|
for (const dropDown of this.dropDowns) {
|
||||||
|
dropDown.resetToDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the nearest filter to the provided container
|
||||||
|
* @param container the StarterContainer to compare position against
|
||||||
|
* @returns the index of the closest filter
|
||||||
|
*/
|
||||||
getNearestFilter(container: StarterContainer): number {
|
getNearestFilter(container: StarterContainer): number {
|
||||||
// find the nearest filter to the x position
|
|
||||||
const midx = container.x + container.icon.displayWidth / 2;
|
const midx = container.x + container.icon.displayWidth / 2;
|
||||||
let nearest = 0;
|
let nearest = 0;
|
||||||
let nearestDist = 1000;
|
let nearestDist = 1000;
|
||||||
@ -201,11 +206,4 @@ export class FilterBar extends Phaser.GameObjects.Container {
|
|||||||
return nearest;
|
return nearest;
|
||||||
}
|
}
|
||||||
|
|
||||||
getLastFilterX(): number {
|
|
||||||
return this.labels[this.lastCursor].x + this.labels[this.lastCursor].displayWidth / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
isFilterActive(index: number) {
|
|
||||||
return this.dropDowns[index].isActive();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ import { Species } from "#enums/species";
|
|||||||
import {Button} from "#enums/buttons";
|
import {Button} from "#enums/buttons";
|
||||||
import { EggSourceType } from "#app/enums/egg-source-types.js";
|
import { EggSourceType } from "#app/enums/egg-source-types.js";
|
||||||
import AwaitableUiHandler from "./awaitable-ui-handler";
|
import AwaitableUiHandler from "./awaitable-ui-handler";
|
||||||
import { DropDown, DropDownOption, DropDownState, DropDownType } from "./dropdown";
|
import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType } from "./dropdown";
|
||||||
import { StarterContainer } from "./starter-container";
|
import { StarterContainer } from "./starter-container";
|
||||||
import { DropDownColumn, FilterBar } from "./filter-bar";
|
import { DropDownColumn, FilterBar } from "./filter-bar";
|
||||||
import { ScrollBar } from "./scroll-bar";
|
import { ScrollBar } from "./scroll-bar";
|
||||||
@ -119,6 +119,14 @@ const starterCandyCosts: { passive: integer, costReduction: [integer, integer],
|
|||||||
{ passive: 10, costReduction: [3, 10], egg: 10 }, // 10
|
{ passive: 10, costReduction: [3, 10], egg: 10 }, // 10
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Position of UI elements
|
||||||
|
const filterBarHeight = 17;
|
||||||
|
const speciesContainerX = 109; // if team on the RIGHT: 109 / if on the LEFT: 143
|
||||||
|
const teamWindowX = 285; // if team on the RIGHT: 285 / if on the LEFT: 109
|
||||||
|
const teamWindowY = 18;
|
||||||
|
const teamWindowWidth = 34;
|
||||||
|
const teamWindowHeight = 132;
|
||||||
|
|
||||||
function getPassiveCandyCount(baseValue: integer): integer {
|
function getPassiveCandyCount(baseValue: integer): integer {
|
||||||
return starterCandyCosts[baseValue - 1].passive;
|
return starterCandyCosts[baseValue - 1].passive;
|
||||||
}
|
}
|
||||||
@ -145,6 +153,57 @@ function calcStarterPosition(index: number, scrollCursor:number = 0): {x: number
|
|||||||
return {x: x, y: y};
|
return {x: x, y: y};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the y position for the icon of stater pokemon selected for the team
|
||||||
|
* @param index index of the Pokemon in the team (0-5)
|
||||||
|
* @returns the y position to use for the icon
|
||||||
|
*/
|
||||||
|
function calcStarterIconY(index: number) {
|
||||||
|
const starterSpacing = teamWindowHeight / 7;
|
||||||
|
const firstStarterY = teamWindowY + starterSpacing / 2;
|
||||||
|
return Math.round(firstStarterY + starterSpacing * index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the index of the team Pokemon closest vertically to the given y position
|
||||||
|
* @param y the y position to find closest starter Pokemon
|
||||||
|
* @param teamSize how many Pokemon are in the team (0-6)
|
||||||
|
* @returns index of the closest Pokemon in the team container
|
||||||
|
*/
|
||||||
|
function findClosestStarterIndex(y: number, teamSize: number = 6): number {
|
||||||
|
let smallestDistance = teamWindowHeight;
|
||||||
|
let closestStarterIndex = 0;
|
||||||
|
for (let i = 0; i < teamSize; i++) {
|
||||||
|
const distance = Math.abs(y - (calcStarterIconY(i) - 13));
|
||||||
|
if (distance < smallestDistance) {
|
||||||
|
closestStarterIndex = i;
|
||||||
|
smallestDistance = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return closestStarterIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the row of the filtered Pokemon closest vertically to the given Pokemon in the team
|
||||||
|
* @param index index of the Pokemon in the team (0-5)
|
||||||
|
* @param numberOfRows the number of rows to check against
|
||||||
|
* @returns index of the row closest vertically to the given Pokemon
|
||||||
|
*/
|
||||||
|
function findClosestStarterRow(index: number, numberOfRows: number) {
|
||||||
|
const currentY = calcStarterIconY(index) - 13;
|
||||||
|
let smallestDistance = teamWindowHeight;
|
||||||
|
let closestRowIndex = 0;
|
||||||
|
for (let i=0; i < numberOfRows; i++) {
|
||||||
|
const distance = Math.abs(currentY - calcStarterPosition(i * 9).y);
|
||||||
|
if (distance < smallestDistance) {
|
||||||
|
closestRowIndex = i;
|
||||||
|
smallestDistance = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return closestRowIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export default class StarterSelectUiHandler extends MessageUiHandler {
|
export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
private starterSelectContainer: Phaser.GameObjects.Container;
|
private starterSelectContainer: Phaser.GameObjects.Container;
|
||||||
private starterSelectScrollBar: ScrollBar;
|
private starterSelectScrollBar: ScrollBar;
|
||||||
@ -297,40 +356,33 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.shinyOverlay.setVisible(false);
|
this.shinyOverlay.setVisible(false);
|
||||||
this.starterSelectContainer.add(this.shinyOverlay);
|
this.starterSelectContainer.add(this.shinyOverlay);
|
||||||
|
|
||||||
const starterContainerWindow = addWindow(this.scene, 109, 18, 175, 161);
|
const starterContainerWindow = addWindow(this.scene, speciesContainerX, filterBarHeight + 1, 175, 161);
|
||||||
const starterContainerBg = this.scene.add.image(110, 19, "starter_container_bg");
|
const starterContainerBg = this.scene.add.image(speciesContainerX+1, filterBarHeight + 2, "starter_container_bg");
|
||||||
starterContainerBg.setOrigin(0, 0);
|
starterContainerBg.setOrigin(0, 0);
|
||||||
this.starterSelectContainer.add(starterContainerBg);
|
this.starterSelectContainer.add(starterContainerBg);
|
||||||
|
|
||||||
this.starterSelectContainer.add(addWindow(this.scene, 285, 59, 34, 91));
|
this.starterSelectContainer.add(addWindow(this.scene, teamWindowX, teamWindowY, teamWindowWidth, teamWindowHeight));
|
||||||
this.starterSelectContainer.add(addWindow(this.scene, 285, 145, 34, 34, true));
|
this.starterSelectContainer.add(addWindow(this.scene, teamWindowX, teamWindowY + teamWindowHeight - 5, teamWindowWidth, teamWindowWidth, true));
|
||||||
this.starterSelectContainer.add(starterContainerWindow);
|
this.starterSelectContainer.add(starterContainerWindow);
|
||||||
|
|
||||||
|
// Create and initialise filter bar
|
||||||
this.filterBarContainer = this.scene.add.container(0, 0);
|
this.filterBarContainer = this.scene.add.container(0, 0);
|
||||||
|
this.filterBar = new FilterBar(this.scene, Math.min(speciesContainerX, teamWindowX), 1, 210, filterBarHeight);
|
||||||
// this.filterBar = new FilterBar(this.scene, 143, 1, 175, 17);
|
|
||||||
this.filterBar = new FilterBar(this.scene, 109, 1, 175, 17);
|
|
||||||
|
|
||||||
// gen filter
|
// gen filter
|
||||||
const genOptions: DropDownOption[] = [
|
const genOptions: DropDownOption[] = [
|
||||||
new DropDownOption(this.scene, 1, i18next.t("starterSelectUiHandler:gen1"), null, DropDownState.ON),
|
new DropDownOption(this.scene, 1, new DropDownLabel(i18next.t("starterSelectUiHandler:gen1"))),
|
||||||
new DropDownOption(this.scene, 2, i18next.t("starterSelectUiHandler:gen2"), null, DropDownState.ON),
|
new DropDownOption(this.scene, 2, new DropDownLabel(i18next.t("starterSelectUiHandler:gen2"))),
|
||||||
new DropDownOption(this.scene, 3, i18next.t("starterSelectUiHandler:gen3"), null, DropDownState.ON),
|
new DropDownOption(this.scene, 3, new DropDownLabel(i18next.t("starterSelectUiHandler:gen3"))),
|
||||||
new DropDownOption(this.scene, 4, i18next.t("starterSelectUiHandler:gen4"), null, DropDownState.ON),
|
new DropDownOption(this.scene, 4, new DropDownLabel(i18next.t("starterSelectUiHandler:gen4"))),
|
||||||
new DropDownOption(this.scene, 5, i18next.t("starterSelectUiHandler:gen5"), null, DropDownState.ON),
|
new DropDownOption(this.scene, 5, new DropDownLabel(i18next.t("starterSelectUiHandler:gen5"))),
|
||||||
new DropDownOption(this.scene, 6, i18next.t("starterSelectUiHandler:gen6"), null, DropDownState.ON),
|
new DropDownOption(this.scene, 6, new DropDownLabel(i18next.t("starterSelectUiHandler:gen6"))),
|
||||||
new DropDownOption(this.scene, 7, i18next.t("starterSelectUiHandler:gen7"), null, DropDownState.ON),
|
new DropDownOption(this.scene, 7, new DropDownLabel(i18next.t("starterSelectUiHandler:gen7"))),
|
||||||
new DropDownOption(this.scene, 8, i18next.t("starterSelectUiHandler:gen8"), null, DropDownState.ON),
|
new DropDownOption(this.scene, 8, new DropDownLabel(i18next.t("starterSelectUiHandler:gen8"))),
|
||||||
new DropDownOption(this.scene, 9, i18next.t("starterSelectUiHandler:gen9"), null, DropDownState.ON),
|
new DropDownOption(this.scene, 9, new DropDownLabel(i18next.t("starterSelectUiHandler:gen9"))),
|
||||||
];
|
];
|
||||||
this.filterBar.addFilter(i18next.t("filterBar:genFilter"), new DropDown(this.scene, 0, 0, genOptions, this.updateStarters, DropDownType.MULTI));
|
const genDropDown: DropDown = new DropDown(this.scene, 0, 0, genOptions, this.updateStarters, DropDownType.HYBRID);
|
||||||
this.filterBar.defaultGenVals = this.filterBar.getVals(DropDownColumn.GEN);
|
this.filterBar.addFilter(DropDownColumn.GEN, i18next.t("filterBar:genFilter"), genDropDown);
|
||||||
// set gen filter to all off except for the I GEN
|
|
||||||
for (const option of genOptions) {
|
|
||||||
if (option.val !== 1) {
|
|
||||||
option.setOptionState(DropDownType.MULTI ,DropDownState.OFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// type filter
|
// type filter
|
||||||
const typeKeys = Object.keys(Type).filter(v => isNaN(Number(v)));
|
const typeKeys = Object.keys(Type).filter(v => isNaN(Number(v)));
|
||||||
@ -342,10 +394,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
const typeSprite = this.scene.add.sprite(0, 0, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`);
|
const typeSprite = this.scene.add.sprite(0, 0, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`);
|
||||||
typeSprite.setScale(0.5);
|
typeSprite.setScale(0.5);
|
||||||
typeSprite.setFrame(type.toLowerCase());
|
typeSprite.setFrame(type.toLowerCase());
|
||||||
typeOptions.push(new DropDownOption(this.scene, index, null, typeSprite));
|
typeOptions.push(new DropDownOption(this.scene, index, new DropDownLabel("", typeSprite)));
|
||||||
});
|
});
|
||||||
this.filterBar.addFilter(i18next.t("filterBar:typeFilter"), new DropDown(this.scene, 0, 0, typeOptions, this.updateStarters, DropDownType.MULTI, 0.5));
|
this.filterBar.addFilter(DropDownColumn.TYPES, i18next.t("filterBar:typeFilter"), new DropDown(this.scene, 0, 0, typeOptions, this.updateStarters, DropDownType.HYBRID, 0.5));
|
||||||
this.filterBar.defaultTypeVals = this.filterBar.getVals(DropDownColumn.TYPES);
|
|
||||||
|
|
||||||
// shiny filter
|
// shiny filter
|
||||||
const shiny1Sprite = this.scene.add.sprite(0, 0, "shiny_icons");
|
const shiny1Sprite = this.scene.add.sprite(0, 0, "shiny_icons");
|
||||||
@ -365,45 +416,54 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
shiny3Sprite.setTint(getVariantTint(2));
|
shiny3Sprite.setTint(getVariantTint(2));
|
||||||
|
|
||||||
const shinyOptions = [
|
const shinyOptions = [
|
||||||
new DropDownOption(this.scene, "SHINY3", null, shiny3Sprite),
|
new DropDownOption(this.scene, "SHINY3", new DropDownLabel("", shiny3Sprite)),
|
||||||
new DropDownOption(this.scene, "SHINY2", null, shiny2Sprite),
|
new DropDownOption(this.scene, "SHINY2", new DropDownLabel("", shiny2Sprite)),
|
||||||
new DropDownOption(this.scene, "SHINY", null, shiny1Sprite),
|
new DropDownOption(this.scene, "SHINY", new DropDownLabel("", shiny1Sprite)),
|
||||||
new DropDownOption(this.scene, "NORMAL", i18next.t("filterBar:normal")),
|
new DropDownOption(this.scene, "NORMAL", new DropDownLabel(i18next.t("filterBar:normal"))),
|
||||||
new DropDownOption(this.scene, "UNCAUGHT", i18next.t("filterBar:uncaught")),
|
new DropDownOption(this.scene, "UNCAUGHT", new DropDownLabel(i18next.t("filterBar:uncaught")))
|
||||||
];
|
];
|
||||||
|
|
||||||
this.filterBar.addFilter("Owned", new DropDown(this.scene, 0, 0, shinyOptions, this.updateStarters, DropDownType.MULTI));
|
this.filterBar.addFilter(DropDownColumn.DEX, i18next.t("filterBar:dexFilter"), new DropDown(this.scene, 0, 0, shinyOptions, this.updateStarters, DropDownType.HYBRID));
|
||||||
this.filterBar.defaultShinyVals = this.filterBar.getVals(DropDownColumn.SHINY);
|
|
||||||
|
|
||||||
|
|
||||||
// unlocks filter
|
// unlocks filter
|
||||||
|
const passiveLabels = [
|
||||||
|
new DropDownLabel(i18next.t("filterBar:passive"), undefined, DropDownState.OFF),
|
||||||
|
new DropDownLabel(i18next.t("filterBar:passiveUnlocked"), undefined, DropDownState.ON),
|
||||||
|
new DropDownLabel(i18next.t("filterBar:passiveLocked"), undefined, DropDownState.EXCLUDE),
|
||||||
|
];
|
||||||
const unlocksOptions = [
|
const unlocksOptions = [
|
||||||
new DropDownOption(this.scene, "PASSIVE", ["Passive", i18next.t("filterBar:passiveUnlocked"), i18next.t("filterBar:passiveLocked")], null, DropDownState.OFF),
|
new DropDownOption(this.scene, "PASSIVE", passiveLabels),
|
||||||
];
|
];
|
||||||
|
|
||||||
this.filterBar.addFilter(i18next.t("filterBar:unlocksFilter"), new DropDown(this.scene, 0, 0, unlocksOptions, this.updateStarters, DropDownType.TRI));
|
this.filterBar.addFilter(DropDownColumn.UNLOCKS, i18next.t("filterBar:unlocksFilter"), new DropDown(this.scene, 0, 0, unlocksOptions, this.updateStarters, DropDownType.RADIAL));
|
||||||
this.filterBar.defaultUnlocksVals = this.filterBar.getVals(DropDownColumn.UNLOCKS);
|
|
||||||
|
|
||||||
// misc filter
|
// misc filter
|
||||||
const miscOptions = [
|
const winLabels = [
|
||||||
new DropDownOption(this.scene, "WIN", ["Win", "Win - Yes", "Win - No"], null, DropDownState.OFF),
|
new DropDownLabel(i18next.t("filterBar:ribbon"), undefined, DropDownState.OFF),
|
||||||
|
new DropDownLabel(i18next.t("filterBar:hasWon"), undefined, DropDownState.ON),
|
||||||
|
new DropDownLabel(i18next.t("filterBar:hasNotWon"), undefined, DropDownState.EXCLUDE),
|
||||||
];
|
];
|
||||||
this.filterBar.addFilter("Misc", new DropDown(this.scene, 0, 0, miscOptions, this.updateStarters, DropDownType.TRI));
|
const miscOptions = [
|
||||||
this.filterBar.defaultMiscVals = this.filterBar.getVals(DropDownColumn.MISC);
|
new DropDownOption(this.scene, "WIN", winLabels),
|
||||||
|
];
|
||||||
|
this.filterBar.addFilter(DropDownColumn.MISC, i18next.t("filterBar:miscFilter"), new DropDown(this.scene, 0, 0, miscOptions, this.updateStarters, DropDownType.RADIAL));
|
||||||
|
|
||||||
// sort filter
|
// sort filter
|
||||||
const sortOptions = [
|
const sortOptions = [
|
||||||
new DropDownOption(this.scene, 0, i18next.t("filterBar:sortByNumber")),
|
new DropDownOption(this.scene, 0, new DropDownLabel(i18next.t("filterBar:sortByNumber"))),
|
||||||
new DropDownOption(this.scene, 1, i18next.t("filterBar:sortByCost"), null, DropDownState.OFF),
|
new DropDownOption(this.scene, 1, new DropDownLabel(i18next.t("filterBar:sortByCost"), undefined, DropDownState.OFF)),
|
||||||
new DropDownOption(this.scene, 2, i18next.t("filterBar:sortByCandies"), null, DropDownState.OFF),
|
new DropDownOption(this.scene, 2, new DropDownLabel(i18next.t("filterBar:sortByCandies"), undefined, DropDownState.OFF)),
|
||||||
new DropDownOption(this.scene, 3, i18next.t("filterBar:sortByIVs"), null, DropDownState.OFF),
|
new DropDownOption(this.scene, 3, new DropDownLabel(i18next.t("filterBar:sortByIVs"), undefined, DropDownState.OFF)),
|
||||||
new DropDownOption(this.scene, 4, i18next.t("filterBar:sortByName"), null, DropDownState.OFF)];
|
new DropDownOption(this.scene, 4, new DropDownLabel(i18next.t("filterBar:sortByName"), undefined, DropDownState.OFF))
|
||||||
this.filterBar.addFilter(i18next.t("filterBar:sortFilter"), new DropDown(this.scene, 0, 0, sortOptions, this.updateStarters, DropDownType.SINGLE));
|
];
|
||||||
|
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);
|
this.filterBarContainer.add(this.filterBar);
|
||||||
this.filterBar.defaultSortVals = this.filterBar.getVals(DropDownColumn.SORT);
|
|
||||||
|
|
||||||
this.starterSelectContainer.add(this.filterBarContainer);
|
this.starterSelectContainer.add(this.filterBarContainer);
|
||||||
|
|
||||||
|
// Offset the generation filter dropdown to avoid covering the filtered pokemon
|
||||||
|
this.filterBar.offsetFirstFilter();
|
||||||
|
|
||||||
if (!this.scene.uiTheme) {
|
if (!this.scene.uiTheme) {
|
||||||
starterContainerWindow.setVisible(false);
|
starterContainerWindow.setVisible(false);
|
||||||
}
|
}
|
||||||
@ -479,22 +539,22 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.pokemonEggMoveBgs = [];
|
this.pokemonEggMoveBgs = [];
|
||||||
this.pokemonEggMoveLabels = [];
|
this.pokemonEggMoveLabels = [];
|
||||||
|
|
||||||
this.valueLimitLabel = addTextObject(this.scene, 302, 150, "0/10", TextStyle.TOOLTIP_CONTENT);
|
this.valueLimitLabel = addTextObject(this.scene, teamWindowX+17, 150, "0/10", TextStyle.TOOLTIP_CONTENT);
|
||||||
this.valueLimitLabel.setOrigin(0.5, 0);
|
this.valueLimitLabel.setOrigin(0.5, 0);
|
||||||
this.starterSelectContainer.add(this.valueLimitLabel);
|
this.starterSelectContainer.add(this.valueLimitLabel);
|
||||||
|
|
||||||
const startLabel = addTextObject(this.scene, 302, 162, i18next.t("common:start"), TextStyle.TOOLTIP_CONTENT);
|
const startLabel = addTextObject(this.scene, teamWindowX+17, 162, i18next.t("common:start"), TextStyle.TOOLTIP_CONTENT);
|
||||||
startLabel.setOrigin(0.5, 0);
|
startLabel.setOrigin(0.5, 0);
|
||||||
this.starterSelectContainer.add(startLabel);
|
this.starterSelectContainer.add(startLabel);
|
||||||
|
|
||||||
this.startCursorObj = this.scene.add.nineslice(289, 160, "select_cursor", null, 26, 15, 6, 6, 6, 6);
|
this.startCursorObj = this.scene.add.nineslice(teamWindowX+4, 160, "select_cursor", null, 26, 15, 6, 6, 6, 6);
|
||||||
this.startCursorObj.setVisible(false);
|
this.startCursorObj.setVisible(false);
|
||||||
this.startCursorObj.setOrigin(0, 0);
|
this.startCursorObj.setOrigin(0, 0);
|
||||||
this.starterSelectContainer.add(this.startCursorObj);
|
this.starterSelectContainer.add(this.startCursorObj);
|
||||||
|
|
||||||
const starterSpecies: Species[] = [];
|
const starterSpecies: Species[] = [];
|
||||||
|
|
||||||
const starterBoxContainer = this.scene.add.container(115, 9);
|
const starterBoxContainer = this.scene.add.container(speciesContainerX + 6, 9); //115
|
||||||
|
|
||||||
this.starterSelectScrollBar = new ScrollBar(this.scene, 161, 12, 0);
|
this.starterSelectScrollBar = new ScrollBar(this.scene, 161, 12, 0);
|
||||||
|
|
||||||
@ -544,7 +604,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.starterSelectContainer.add(starterBoxContainer);
|
this.starterSelectContainer.add(starterBoxContainer);
|
||||||
|
|
||||||
this.starterIcons = new Array(6).fill(null).map((_, i) => {
|
this.starterIcons = new Array(6).fill(null).map((_, i) => {
|
||||||
const icon = this.scene.add.sprite(292, 63 + 13 * i, "pokemon_icons_0");
|
const icon = this.scene.add.sprite(teamWindowX + 7, calcStarterIconY(i), "pokemon_icons_0");
|
||||||
icon.setScale(0.5);
|
icon.setScale(0.5);
|
||||||
icon.setOrigin(0, 0);
|
icon.setOrigin(0, 0);
|
||||||
icon.setFrame("unknown");
|
icon.setFrame("unknown");
|
||||||
@ -833,6 +893,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.setUpgradeAnimation(icon, species);
|
this.setUpgradeAnimation(icon, species);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.resetFilters();
|
||||||
this.updateStarters();
|
this.updateStarters();
|
||||||
|
|
||||||
this.setFilterMode(false);
|
this.setFilterMode(false);
|
||||||
@ -848,6 +909,27 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the selections for all filters to their default starting value
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer) {
|
showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer) {
|
||||||
super.showText(text, delay, callback, callbackDelay, prompt, promptDelay);
|
super.showText(text, delay, callback, callbackDelay, prompt, promptDelay);
|
||||||
|
|
||||||
@ -1035,11 +1117,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
const onScreenLastIndex = Math.min(this.filteredStarterContainers.length - 1, onScreenFirstIndex + maxRows * maxColumns - 1); // this is the last starter index on the screen
|
const onScreenLastIndex = Math.min(this.filteredStarterContainers.length - 1, onScreenFirstIndex + maxRows * maxColumns - 1); // this is the last starter index on the screen
|
||||||
const onScreenNumberOfStarters = onScreenLastIndex - onScreenFirstIndex + 1;
|
const onScreenNumberOfStarters = onScreenLastIndex - onScreenFirstIndex + 1;
|
||||||
const onScreenNumberOfRows = Math.ceil(onScreenNumberOfStarters / maxColumns);
|
const onScreenNumberOfRows = Math.ceil(onScreenNumberOfStarters / maxColumns);
|
||||||
// const onScreenFirstRow = Math.floor(onScreenFirstIndex / maxColumns);
|
|
||||||
const onScreenCurrentRow = Math.floor((this.cursor - onScreenFirstIndex) / maxColumns);
|
const onScreenCurrentRow = Math.floor((this.cursor - onScreenFirstIndex) / maxColumns);
|
||||||
|
|
||||||
// console.log("this.cursor: ", this.cursor, "this.scrollCursor" , this.scrollCursor, "numberOfStarters: ", numberOfStarters, "numOfRows: ", numOfRows, "currentRow: ", currentRow, "onScreenFirstIndex: ", onScreenFirstIndex, "onScreenLastIndex: ", onScreenLastIndex, "onScreenNumberOfStarters: ", onScreenNumberOfStarters, "onScreenNumberOfRow: ", onScreenNumberOfRows, "onScreenCurrentRow: ", onScreenCurrentRow);
|
|
||||||
|
|
||||||
const ui = this.getUi();
|
const ui = this.getUi();
|
||||||
|
|
||||||
let success = false;
|
let success = false;
|
||||||
@ -1053,8 +1132,18 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
}
|
}
|
||||||
} else if (button === Button.CANCEL) {
|
} else if (button === Button.CANCEL) {
|
||||||
if (this.filterMode && this.filterBar.openDropDown) {
|
if (this.filterMode && this.filterBar.openDropDown) {
|
||||||
|
// CANCEL with a filter menu open > close it
|
||||||
this.filterBar.toggleDropDown(this.filterBarCursor);
|
this.filterBar.toggleDropDown(this.filterBarCursor);
|
||||||
|
|
||||||
|
// if there are possible starters go the first one of the list
|
||||||
|
if (numberOfStarters > 0) {
|
||||||
|
this.setFilterMode(false);
|
||||||
|
this.scrollCursor = 0;
|
||||||
|
this.updateScroll();
|
||||||
|
this.setCursor(0);
|
||||||
|
}
|
||||||
success = true;
|
success = true;
|
||||||
|
|
||||||
} else if (this.statsMode) {
|
} else if (this.statsMode) {
|
||||||
this.toggleStatsMode(false);
|
this.toggleStatsMode(false);
|
||||||
success = true;
|
success = true;
|
||||||
@ -1081,6 +1170,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.starterIconsCursorIndex = this.starterSpecies.length - 1;
|
this.starterIconsCursorIndex = this.starterSpecies.length - 1;
|
||||||
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
|
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
|
||||||
} else {
|
} else {
|
||||||
|
// up from start button with no Pokemon in the team > go to filter
|
||||||
|
this.startCursorObj.setVisible(false);
|
||||||
|
this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1);
|
||||||
this.setFilterMode(true);
|
this.setFilterMode(true);
|
||||||
}
|
}
|
||||||
success = true;
|
success = true;
|
||||||
@ -1091,6 +1183,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.starterIconsCursorIndex = 0;
|
this.starterIconsCursorIndex = 0;
|
||||||
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
|
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
|
||||||
} else {
|
} else {
|
||||||
|
// down from start button with no Pokemon in the team > go to filter
|
||||||
|
this.startCursorObj.setVisible(false);
|
||||||
|
this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1);
|
||||||
this.setFilterMode(true);
|
this.setFilterMode(true);
|
||||||
}
|
}
|
||||||
success = true;
|
success = true;
|
||||||
@ -1129,27 +1224,31 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
success = this.filterBar.decDropDownCursor();
|
success = this.filterBar.decDropDownCursor();
|
||||||
// else if there is filtered starters
|
// else if there is filtered starters
|
||||||
} else if (numberOfStarters > 0) {
|
} else if (numberOfStarters > 0) {
|
||||||
|
// UP from filter bar to bottom of Pokemon list
|
||||||
this.setFilterMode(false);
|
this.setFilterMode(false);
|
||||||
this.scrollCursor = Math.max(0,numOfRows - 9);
|
this.scrollCursor = Math.max(0,numOfRows - 9);
|
||||||
this.updateScroll();
|
this.updateScroll();
|
||||||
const proportion = (this.filterBarCursor + 0.5) / this.filterBar.numFilters;
|
const proportion = (this.filterBarCursor + 0.5) / this.filterBar.numFilters;
|
||||||
const targetCol = Math.floor(proportion * 9);
|
const targetCol = Math.min(8, Math.floor(proportion * 11));
|
||||||
if (numberOfStarters % 9 > targetCol) {
|
if (numberOfStarters % 9 > targetCol) {
|
||||||
success = this.setCursor(numberOfStarters - (numberOfStarters) % 9 + targetCol);
|
this.setCursor(numberOfStarters - (numberOfStarters) % 9 + targetCol);
|
||||||
} else {
|
} else {
|
||||||
success = this.setCursor(Math.max(numberOfStarters - (numberOfStarters) % 9 + targetCol - 9,0));
|
this.setCursor(Math.max(numberOfStarters - (numberOfStarters) % 9 + targetCol - 9, 0));
|
||||||
}
|
}
|
||||||
|
success = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Button.DOWN:
|
case Button.DOWN:
|
||||||
if (this.filterBar.openDropDown) {
|
if (this.filterBar.openDropDown) {
|
||||||
success = this.filterBar.incDropDownCursor();
|
success = this.filterBar.incDropDownCursor();
|
||||||
} else if (numberOfStarters > 0) {
|
} else if (numberOfStarters > 0) {
|
||||||
|
// DOWN from filter bar to top of Pokemon list
|
||||||
this.setFilterMode(false);
|
this.setFilterMode(false);
|
||||||
this.scrollCursor = 0;
|
this.scrollCursor = 0;
|
||||||
this.updateScroll();
|
this.updateScroll();
|
||||||
const proportion = this.filterBarCursor / Math.max(1, this.filterBar.numFilters - 1);
|
const proportion = this.filterBarCursor / Math.max(1, this.filterBar.numFilters - 1);
|
||||||
this.setCursor(Math.round(proportion * (Math.min(9, numberOfStarters) - 1)));
|
const targetCol = Math.min(8, Math.floor(proportion * 11));
|
||||||
|
this.setCursor(Math.min(targetCol, numberOfStarters));
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1669,9 +1768,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.starterIconsCursorIndex === 0) {
|
if (this.starterIconsCursorIndex === 0) {
|
||||||
|
// Up from first Pokemon in the team > go to filter
|
||||||
this.starterIconsCursorObj.setVisible(false);
|
this.starterIconsCursorObj.setVisible(false);
|
||||||
this.setSpecies(null);
|
this.setSpecies(null);
|
||||||
this.startCursorObj.setVisible(true);
|
this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1);
|
||||||
|
this.setFilterMode(true);
|
||||||
} else {
|
} else {
|
||||||
this.starterIconsCursorIndex--;
|
this.starterIconsCursorIndex--;
|
||||||
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
|
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
|
||||||
@ -1687,7 +1788,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
}
|
}
|
||||||
success = this.setCursor(this.cursor + 9);
|
success = this.setCursor(this.cursor + 9);
|
||||||
this.updateScroll();
|
this.updateScroll();
|
||||||
} else { // last row
|
} else if (numOfRows > 1) {
|
||||||
|
// DOWN from last row of Pokemon > Wrap around to first row
|
||||||
|
this.scrollCursor = 0;
|
||||||
|
this.updateScroll();
|
||||||
|
success = this.setCursor(this.cursor % 9);
|
||||||
|
} else {
|
||||||
|
// DOWN from single row of Pokemon > Go to filters
|
||||||
|
this.filterBarCursor = this.filterBar.getNearestFilter(this.filteredStarterContainers[this.cursor]);
|
||||||
this.setFilterMode(true);
|
this.setFilterMode(true);
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
@ -1708,29 +1816,36 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
if (this.cursor % 9 !== 0) {
|
if (this.cursor % 9 !== 0) {
|
||||||
success = this.setCursor(this.cursor - 1);
|
success = this.setCursor(this.cursor - 1);
|
||||||
} else {
|
} else {
|
||||||
|
// LEFT from filtered Pokemon, on the left edge
|
||||||
|
|
||||||
if (this.starterSpecies.length === 0) {
|
if (this.starterSpecies.length === 0) {
|
||||||
// just wrap around to the last column
|
// no starter in team > wrap around to the last column
|
||||||
success = this.setCursor(this.cursor + Math.min(8, numberOfStarters - this.cursor));
|
success = this.setCursor(this.cursor + Math.min(8, numberOfStarters - this.cursor));
|
||||||
} else if (onScreenCurrentRow < 3) {
|
|
||||||
// always to the first starter
|
|
||||||
this.cursorObj.setVisible(false);
|
|
||||||
this.starterIconsCursorIndex = 0;
|
|
||||||
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
|
|
||||||
} else if (onScreenCurrentRow < 7) {
|
} else if (onScreenCurrentRow < 7) {
|
||||||
|
// at least one pokemon in team > for the first 7 rows, go to closest starter
|
||||||
this.cursorObj.setVisible(false);
|
this.cursorObj.setVisible(false);
|
||||||
this.starterIconsCursorIndex = Math.min(onScreenCurrentRow-2, this.starterSpecies.length - 1);
|
this.starterIconsCursorIndex = findClosestStarterIndex(this.cursorObj.y - 1, this.starterSpecies.length);
|
||||||
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
|
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// at least one pokemon in team > from the bottom 2 rows, go to start run button
|
||||||
this.cursorObj.setVisible(false);
|
this.cursorObj.setVisible(false);
|
||||||
this.setSpecies(null);
|
this.setSpecies(null);
|
||||||
this.startCursorObj.setVisible(true);
|
this.startCursorObj.setVisible(true);
|
||||||
}
|
}
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (numberOfStarters > 0) {
|
||||||
|
// LEFT from team > Go to closest filtered Pokemon
|
||||||
|
const closestRowIndex = findClosestStarterRow(this.starterIconsCursorIndex, onScreenNumberOfRows);
|
||||||
this.starterIconsCursorObj.setVisible(false);
|
this.starterIconsCursorObj.setVisible(false);
|
||||||
this.cursorObj.setVisible(true);
|
this.cursorObj.setVisible(true);
|
||||||
success = this.setCursor(Math.min(onScreenFirstIndex + (this.starterIconsCursorIndex + 2) * 9 + 8,onScreenLastIndex)); // set last column
|
this.setCursor(Math.min(onScreenFirstIndex + closestRowIndex * 9 + 8, onScreenLastIndex));
|
||||||
|
success = true;
|
||||||
|
} else {
|
||||||
|
// LEFT from team and no Pokemon in filter > do nothing
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Button.RIGHT:
|
case Button.RIGHT:
|
||||||
@ -1739,33 +1854,37 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
if (this.cursor % 9 < (currentRow < numOfRows - 1 ? 8 : (numberOfStarters - 1) % 9)) {
|
if (this.cursor % 9 < (currentRow < numOfRows - 1 ? 8 : (numberOfStarters - 1) % 9)) {
|
||||||
success = this.setCursor(this.cursor + 1);
|
success = this.setCursor(this.cursor + 1);
|
||||||
} else {
|
} else {
|
||||||
// in right edge
|
// RIGHT from filtered Pokemon, on the right edge
|
||||||
if (this.starterSpecies.length === 0) {
|
if (this.starterSpecies.length === 0) {
|
||||||
// just wrap around to the first column
|
// no selected starter in team > wrap around to the first column
|
||||||
success = this.setCursor(this.cursor - Math.min(8, this.cursor % 9));
|
success = this.setCursor(this.cursor - Math.min(8, this.cursor % 9));
|
||||||
} else if (onScreenCurrentRow < 3) {
|
|
||||||
// always to the first starter
|
|
||||||
this.cursorObj.setVisible(false);
|
|
||||||
this.starterIconsCursorIndex = 0;
|
|
||||||
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
|
|
||||||
} else if (onScreenCurrentRow < 7) {
|
} else if (onScreenCurrentRow < 7) {
|
||||||
|
// at least one pokemon in team > for the first 7 rows, go to closest starter
|
||||||
this.cursorObj.setVisible(false);
|
this.cursorObj.setVisible(false);
|
||||||
this.starterIconsCursorIndex = Math.min(onScreenCurrentRow-2, this.starterSpecies.length - 1);
|
this.starterIconsCursorIndex = findClosestStarterIndex(this.cursorObj.y - 1, this.starterSpecies.length);
|
||||||
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
|
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// at least one pokemon in team > from the bottom 2 rows, go to start run button
|
||||||
this.cursorObj.setVisible(false);
|
this.cursorObj.setVisible(false);
|
||||||
this.setSpecies(null);
|
this.setSpecies(null);
|
||||||
this.startCursorObj.setVisible(true);
|
this.startCursorObj.setVisible(true);
|
||||||
}
|
}
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
break;
|
} else if (numberOfStarters > 0) {
|
||||||
} else {
|
// RIGHT from team > Go to closest filtered Pokemon
|
||||||
|
const closestRowIndex = findClosestStarterRow(this.starterIconsCursorIndex, onScreenNumberOfRows);
|
||||||
this.starterIconsCursorObj.setVisible(false);
|
this.starterIconsCursorObj.setVisible(false);
|
||||||
this.cursorObj.setVisible(true);
|
this.cursorObj.setVisible(true);
|
||||||
success = this.setCursor(Math.min(onScreenFirstIndex + (this.starterIconsCursorIndex + 2) * 9, onScreenLastIndex - (onScreenLastIndex % 9))); // set first column
|
this.setCursor(Math.min(onScreenFirstIndex + closestRowIndex * 9, onScreenLastIndex - (onScreenLastIndex % 9)));
|
||||||
break;
|
success = true;
|
||||||
|
} else {
|
||||||
|
// RIGHT from team and no Pokemon in filter > do nothing
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1959,7 +2078,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
|
|
||||||
// pre filter for challenges
|
// pre filter for challenges
|
||||||
if (this.scene.gameMode.modeId === GameModes.CHALLENGE) {
|
if (this.scene.gameMode.modeId === GameModes.CHALLENGE) {
|
||||||
console.log("this.scene.gameMode.modeId", this.scene.gameMode.modeId);
|
|
||||||
this.starterContainers.forEach(container => {
|
this.starterContainers.forEach(container => {
|
||||||
const isValidForChallenge = new Utils.BooleanHolder(true);
|
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, container.species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(container.species, this.scene.gameData.getSpeciesDefaultDexAttr(container.species, false, true)), true);
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, container.species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(container.species, this.scene.gameData.getSpeciesDefaultDexAttr(container.species, false, true)), true);
|
||||||
@ -1997,7 +2115,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
|
|
||||||
const fitsType = this.filterBar.getVals(DropDownColumn.TYPES).some(type => container.species.isOfType((type as number) - 1));
|
const fitsType = this.filterBar.getVals(DropDownColumn.TYPES).some(type => container.species.isOfType((type as number) - 1));
|
||||||
|
|
||||||
const fitsShiny = this.filterBar.getVals(DropDownColumn.SHINY).some(variant => {
|
const fitsShiny = this.filterBar.getVals(DropDownColumn.DEX).some(variant => {
|
||||||
if (variant === "SHINY3") {
|
if (variant === "SHINY3") {
|
||||||
return isVariant3Caught;
|
return isVariant3Caught;
|
||||||
} else if (variant === "SHINY2") {
|
} else if (variant === "SHINY2") {
|
||||||
@ -2012,7 +2130,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const fitsPassive = this.filterBar.getVals(DropDownColumn.UNLOCKS).some(unlocks => {
|
const fitsPassive = this.filterBar.getVals(DropDownColumn.UNLOCKS).some(unlocks => {
|
||||||
if (unlocks.val === "PASSIVE" && unlocks.state === DropDownState.INCLUDE) {
|
if (unlocks.val === "PASSIVE" && unlocks.state === DropDownState.ON) {
|
||||||
return isPassiveUnlocked;
|
return isPassiveUnlocked;
|
||||||
} else if (unlocks.val === "PASSIVE" && unlocks.state === DropDownState.EXCLUDE) {
|
} else if (unlocks.val === "PASSIVE" && unlocks.state === DropDownState.EXCLUDE) {
|
||||||
return !isPassiveUnlocked;
|
return !isPassiveUnlocked;
|
||||||
@ -2024,7 +2142,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
const fitsWin = this.filterBar.getVals(DropDownColumn.MISC).some(misc => {
|
const fitsWin = this.filterBar.getVals(DropDownColumn.MISC).some(misc => {
|
||||||
if (container.species.speciesId < 10) {
|
if (container.species.speciesId < 10) {
|
||||||
}
|
}
|
||||||
if (misc.val === "WIN" && misc.state === DropDownState.INCLUDE) {
|
if (misc.val === "WIN" && misc.state === DropDownState.ON) {
|
||||||
return isWin;
|
return isWin;
|
||||||
} else if (misc.val === "WIN" && misc.state === DropDownState.EXCLUDE) {
|
} else if (misc.val === "WIN" && misc.state === DropDownState.EXCLUDE) {
|
||||||
return isNotWin || isUndefined;
|
return isNotWin || isUndefined;
|
||||||
@ -2749,8 +2867,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
if (this.starterSpecies.length > 0) {
|
if (this.starterSpecies.length > 0) {
|
||||||
this.starterIconsCursorIndex--;
|
this.starterIconsCursorIndex--;
|
||||||
} else {
|
} else {
|
||||||
|
// No more Pokemon selected, go back to filters
|
||||||
this.starterIconsCursorObj.setVisible(false);
|
this.starterIconsCursorObj.setVisible(false);
|
||||||
this.setSpecies(null);
|
this.setSpecies(null);
|
||||||
|
this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1);
|
||||||
this.setFilterMode(true);
|
this.setFilterMode(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user