MasatoMakino/pixijs-basic-button

View on GitHub
src/ButtonMaterialSet.ts

Summary

Maintainability
A
0 mins
Test Coverage
A
92%
import { Container, Text } from "pixi.js";
import { BasicButtonState, BasicClickButton } from "./index.js";

class ButtonOptionSet<T> {
  normal!: T;
  over?: T;
  down?: T;
  disable?: T;
  selectNormal?: T;
  selectOver?: T;
  selectDown?: T;

  /**
   * stateに対応するオプション値を取り出す
   * @param set
   * @param state
   */
  public static getMaterial<T>(
    set: ButtonOptionSet<T>,
    state: BasicButtonState,
  ): T {
    switch (state) {
      case "disable":
        return set.disable ?? set.normal;
      case "normal_over":
        return set.over ?? set.normal;
      case "normal_down":
        return set.down ?? set.normal;
      case "select":
        return set.selectNormal ?? set.normal;
      case "select_over":
        return set.selectOver ?? set.normal;
      case "select_down":
        return set.selectDown ?? set.normal;
      default:
        return set.normal;
    }
  }
}

/**
 * ボタンの状態に応じて表示されるDisplayObjectを格納するクラス。
 */
export class ButtonMaterialSet extends ButtonOptionSet<Container> {
  selectMarker?: Container;

  /**
   * ボタン上に状態パーツを配置する
   * @param {BasicClickButton} button
   * @param {ButtonMaterialSet} material
   */
  public static addChild(
    button: BasicClickButton,
    material: ButtonMaterialSet,
  ): void {
    this.remove(material);
    const materials = this.getMaterialArray(material);
    for (let mat of materials) {
      if (mat != null) button.addChild(mat);
    }
  }

  /**
   * この状態セットに含まれるパーツを表示ツリー上から削除する。
   * @param {ButtonMaterialSet} material
   */
  public static remove(material: ButtonMaterialSet): void {
    const materials = this.getMaterialArray(material);
    for (let mat of materials) {
      if (mat && mat.parent) mat.parent.removeChild(mat);
    }
  }

  /**
   * 全ての表示パーツを配列として取得する。
   * @param {ButtonMaterialSet} materials
   * @returns {DisplayObject[]}
   */
  private static getMaterialArray(
    materials: ButtonMaterialSet,
  ): (Container | undefined)[] {
    return [
      materials.normal,
      materials.over,
      materials.down,
      materials.disable,
      materials.selectNormal,
      materials.selectOver,
      materials.selectDown,
      materials.selectMarker,
    ];
  }

  /**
   * 可視状態をstateに合わせて更新する
   * @param {ButtonMaterialSet} material
   * @param {BasicButtonState} state
   */
  public static updateVisible(
    material: ButtonMaterialSet | undefined,
    state: BasicButtonState,
  ): void {
    if (material == null) return;

    this.invisibleAll(material);
    this.getMaterial(material, state).visible = true;

    if (material.selectMarker) {
      material.selectMarker.visible =
        state === "select" ||
        state === "select_over" ||
        state === "select_down";
    }
  }

  /**
   * 全てのパーツを不可視にする。
   * @param {ButtonMaterialSet} material
   */
  private static invisibleAll(material: ButtonMaterialSet): void {
    const materials = this.getMaterialArray(material);
    for (let mat of materials) {
      if (mat != null) mat.visible = false;
    }
  }
}

/**
 * テキストラベルの色についてのオプション。
 * 各ボタンのaddLabel関数でインスタンスに渡す。
 */
export class ButtonLabelColorSet extends ButtonOptionSet<number> {
  /**
   * ラベル文字色をボタン状態に応じて更新する。
   * @param {Text} field 更新対象ラベル
   * @param {ButtonLabelColorSet} colors 状態文字色セット
   * @param {BasicButtonState} state ボタン状態
   */
  public static update(
    field: Text,
    colors: ButtonLabelColorSet,
    state: BasicButtonState,
  ): void {
    if (field == null) return;
    field.style.fill = this.getMaterial(colors, state);
  }
}