// Pixi-текстуры из пиксель-матриц сада: кэш модульного уровня — текстуры
// статичны, переживают перемонтаж компонента, поэтому при app.destroy
// не уничтожаются (texture: false). Модуль импортирует pixi и попадает
// в async-чанк рендерера (GardenRenderer импортируется динамически).
import { CanvasSource, Rectangle, Texture } from 'pixi.js'
import { drawMatrix } from './pixelart'
import type { Matrix, Palette } from './pixelart'
import {
DECOR,
GRASS_A,
GRASS_B,
GRASS_SUPER,
GRASS_TUFT,
HEDGE,
HOUSE,
PAL,
PLANT_BUILDERS,
RING_EPIC,
RING_RARE,
SELECT_OUTLINE,
SHADOW,
WILD,
plantFlower,
} from './sprites'
const cache = new Map<string, Texture>()
/** Текстура из матрицы; кэшируется по ключу (повторный вызов матрицу не читает). */
export function textureFor(key: string, rows: Matrix, palette: Palette): Texture {
const hit = cache.get(key)
if (hit) return hit
const cv = drawMatrix(rows, palette, 1)
// CanvasSource (не сырой TextureSource): только он знает uploadMethodId 'image'
// для загрузки canvas в GPU; TextureSource без адаптера молча не рисуется.
const source = new CanvasSource({
resource: cv,
scaleMode: 'nearest',
antialias: false,
})
const tex = new Texture({ source, frame: new Rectangle(0, 0, cv.width, cv.height) })
cache.set(key, tex)
return tex
}
/** Текстура тайла по имени. */
export function tileTexture(
name: 'grass-a' | 'grass-b' | 'grass-super' | 'grass-tuft' | 'wild' | 'hedge',
): Texture {
switch (name) {
case 'grass-a':
return textureFor('tile:grass-a', GRASS_A, PAL)
case 'grass-b':
return textureFor('tile:grass-b', GRASS_B, PAL)
case 'grass-super':
return textureFor('tile:grass-super', GRASS_SUPER, PAL)
case 'grass-tuft':
return textureFor('tile:grass-tuft', GRASS_TUFT, PAL)
case 'wild':
return textureFor('tile:wild', WILD, PAL)
case 'hedge':
return textureFor('tile:hedge', HEDGE, PAL)
}
}
/** Текстура домика. */
export function houseTexture(): Texture {
return textureFor('house', HOUSE, PAL)
}
/** Текстура растения (вид × стадия). */
export function plantTexture(species: string, stage: number): Texture {
const build = PLANT_BUILDERS[species] ?? plantFlower
const rows: Matrix = build(stage)
return textureFor(`plant:${species}:${stage}`, rows, PAL)
}
/** Текстура декорации по item_key. */
export function decorTexture(key: string): Texture {
return textureFor(`decor:${key}`, DECOR[key] ?? DECOR.flowerbed!, PAL)
}
/** Кольцо редкости. */
export function ringTexture(rarity: string): Texture {
return textureFor(`ring:${rarity}`, rarity === 'epic' ? RING_EPIC : RING_RARE, PAL)
}
/** Блёстка (эпик-растения). */
export function sparkleTexture(): Texture {
return textureFor('sparkle', ['.q.', 'qqq', '.q.'], PAL)
}
/** Рамка выделенной/целевой клетки. */
export function selectOutlineTexture(): Texture {
return textureFor('select-outline', SELECT_OUTLINE, PAL)
}
/** Овальная тень под объектом (ширина матрицы 24, высота 10). */
export function shadowTexture(): Texture {
return textureFor('shadow', SHADOW, PAL)
}