| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- import { type MapScene } from './mapRenderer'
- import { type ControlPointStyleEntry, type CourseLegStyleEntry, type ScoreBandStyleEntry } from '../../game/presentation/courseStyleConfig'
- export type RgbaColor = [number, number, number, number]
- export interface ResolvedControlStyle {
- entry: ControlPointStyleEntry
- color: RgbaColor
- }
- export interface ResolvedLegStyle {
- entry: CourseLegStyleEntry
- color: RgbaColor
- }
- export function hexToRgbaColor(hex: string, alphaOverride?: number): RgbaColor {
- const fallback: RgbaColor = [1, 1, 1, alphaOverride !== undefined ? alphaOverride : 1]
- if (typeof hex !== 'string' || !hex || hex.charAt(0) !== '#') {
- return fallback
- }
- const normalized = hex.slice(1)
- if (normalized.length !== 6 && normalized.length !== 8) {
- return fallback
- }
- const red = parseInt(normalized.slice(0, 2), 16)
- const green = parseInt(normalized.slice(2, 4), 16)
- const blue = parseInt(normalized.slice(4, 6), 16)
- const alpha = normalized.length === 8 ? parseInt(normalized.slice(6, 8), 16) : 255
- if (!Number.isFinite(red) || !Number.isFinite(green) || !Number.isFinite(blue) || !Number.isFinite(alpha)) {
- return fallback
- }
- return [
- red / 255,
- green / 255,
- blue / 255,
- alphaOverride !== undefined ? alphaOverride : alpha / 255,
- ]
- }
- function resolveScoreBandStyle(scene: MapScene, sequence: number): ScoreBandStyleEntry | null {
- const score = scene.controlScoresBySequence[sequence]
- if (score === undefined) {
- return null
- }
- const bands = scene.courseStyleConfig.scoreO.controls.scoreBands
- for (let index = 0; index < bands.length; index += 1) {
- const band = bands[index]
- if (score >= band.min && score <= band.max) {
- return band
- }
- }
- return null
- }
- export function resolveControlStyle(scene: MapScene, kind: 'start' | 'control' | 'finish', sequence: number | null, index?: number): ResolvedControlStyle {
- if (kind === 'start') {
- if (index !== undefined && scene.startStyleOverrides[index]) {
- const entry = scene.startStyleOverrides[index]
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- const entry = scene.gameMode === 'score-o'
- ? scene.courseStyleConfig.scoreO.controls.start
- : scene.courseStyleConfig.sequential.controls.start
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- if (kind === 'finish') {
- if (index !== undefined && scene.finishStyleOverrides[index]) {
- const entry = scene.finishStyleOverrides[index]
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- const entry = scene.gameMode === 'score-o'
- ? scene.courseStyleConfig.scoreO.controls.finish
- : scene.courseStyleConfig.sequential.controls.finish
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- if (sequence === null) {
- const entry = scene.courseStyleConfig.sequential.controls.default
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- if (scene.controlStyleOverridesBySequence[sequence]) {
- const entry = scene.controlStyleOverridesBySequence[sequence]
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- if (scene.gameMode === 'score-o') {
- if (scene.completedControlSequences.includes(sequence)) {
- const entry = scene.courseStyleConfig.scoreO.controls.collected
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- if (scene.focusedControlSequences.includes(sequence)) {
- const entry = scene.courseStyleConfig.scoreO.controls.focused
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- const bandEntry = resolveScoreBandStyle(scene, sequence)
- const entry = bandEntry || scene.courseStyleConfig.scoreO.controls.default
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- if (scene.readyControlSequences.includes(sequence) || scene.activeControlSequences.includes(sequence)) {
- const entry = scene.courseStyleConfig.sequential.controls.current
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- if (scene.completedControlSequences.includes(sequence)) {
- const entry = scene.courseStyleConfig.sequential.controls.completed
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- if (scene.skippedControlSequences.includes(sequence)) {
- const entry = scene.courseStyleConfig.sequential.controls.skipped
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- const entry = scene.courseStyleConfig.sequential.controls.default
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- export function resolveLegStyle(scene: MapScene, index: number): ResolvedLegStyle {
- if (scene.legStyleOverridesByIndex[index]) {
- const entry = scene.legStyleOverridesByIndex[index]
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- if (scene.gameMode === 'score-o') {
- const entry = scene.courseStyleConfig.sequential.legs.default
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
- const completed = scene.completedLegIndices.includes(index)
- const entry = completed ? scene.courseStyleConfig.sequential.legs.completed : scene.courseStyleConfig.sequential.legs.default
- return { entry, color: hexToRgbaColor(entry.colorHex) }
- }
|