API do Dice View v3

Referência da API física, requests, opções, timeline e visuais da versão 3.0.0-alpha.0.

Este artigo descreve a prévia V3 alpha, que usa apenas física e ainda não está publicada no npm. V2 ↗ Licenças ↗

Esta referência corresponde à revisão ae00d9f da v3, identificada como 3.0.0-alpha.0. O alpha ainda não está no npm; veja instalação da v3. A versão publicada 2.6.1 tem referência própria.

O View recebe valores resolvidos e os apresenta. Ele não interpreta notação nem sorteia resultados. Na v3, DisplayMode é apenas 'physics'; o modo cinemático foi removido.

Entrypoints

Import Conteúdo
@erpg/dice3dview DiceResultViewer, helpers, tipos e visuais; módulo WebGL sem dependências de runtime
@erpg/dice3dview/external Alias para o mesmo módulo, preservado para integrações v2
@erpg/dice3dview/adapters Conversores de dados de sistemas sem carregar o renderer
@erpg/dice3dview/style.css Estilos do canvas

O construtor exige um elemento no DOM. init() exige WebGL2 ou WebGL1; instancie apenas no cliente.

DiceResultViewer

Membro Contrato Função
canvas HTMLCanvasElement Canvas criado e anexado no construtor
constructor(options?) ViewerOptions Valida opções e monta o canvas no container
init() Promise<this> Inicializa WebGL, temas e observação de tamanho; idempotente
display(request) Promise<DisplayResult> Simula e desenha faces recebidas; chama init() se preciso
displayTimeline(request) Promise<DisplayTimelineResult> Executa um journal semântico com física
clear() void Cancela a apresentação e limpa imediatamente a cena
updateOptions(options) Promise<void> Mescla opções; efeitos de timeline usam merge por efeito
applyLook(look) Promise<void> Valida e aplica um visual completo versionado
playParticles(moment, options?) void Dispara partículas nos dados presentes
resize() void Recalcula o palco; também é acionado por ResizeObserver
dispose() void Libera recursos e remove o canvas; não reutilize a instância

Uma nova apresentação ou clear() cancela a Promise anterior com DisplayCancelledError. Reconheça-a com isDisplayCancelledError(error).

display(request)

type DiceSides = 2 | 4 | 6 | 8 | 10 | 12 | 20 | 100
type DisplayMode = 'physics'

interface ResolvedDie {
  readonly id: string
  readonly sides: DiceSides
  readonly value: number
  readonly discarded?: boolean
  readonly theme?: string
  readonly themeColor?: string
}

interface DisplayRequest {
  readonly id: string
  readonly dice: readonly ResolvedDie[]
  readonly seed?: string
  readonly mode?: DisplayMode | 'kinematic' // legado; executa física
}

interface DisplayResult {
  readonly id: string
  readonly dice: readonly ResolvedDie[]
  readonly durationMs: number
}

id e dice devem ser não vazios. value precisa ser inteiro entre 1 e sides. seed usa id por padrão e controla apenas a coreografia. As formas suportadas são d2, d4, d6, d8, d10, d12, d20 e d100; cada d100 consome dois corpos do limite maxDice. mode: 'kinematic' é aceito para compatibilidade, avisa no console uma vez e executa física.

display() retorna dados normalizados e congelados. Depois da validação, uma falha de WebGL ou assets é registrada no console e o resultado ainda é devolvido. Se a apresentação visual for indispensável ao seu fluxo, chame await viewer.init() explicitamente e verifique o palco.

displayTimeline(request)

interface DisplayTimelineRequest {
  readonly id: string
  readonly dice: readonly TimelineDieDefinition[]
  readonly events: readonly DiceTimelineEvent[]
  readonly seed?: string
  readonly mode?: 'physics' | 'kinematic' // legado
}

interface DisplayTimelineResult extends DisplayResult {
  readonly eventCount: number
  readonly phaseCount: number
  readonly degraded: boolean
}

Cada TimelineDieDefinition identifica um dado e seus lados; os eventos roll e reroll informam as faces. Eventos de explosão, rerolagem, descarte e classificação usam o mesmo formato de journal da v2. A v3 cria e relança os dados fisicamente. onTimelineProgress recebe snapshots initial, phase e complete para sincronizar o total exibido pela aplicação. displayTimeline() propaga falhas gráficas ou de assets, além dos erros de validação.

Adaptadores de sistemas

createMixedDisplayRequest({ id, dice, seed?, unsupportedDice?, theme?, themeColor?, keptIds?, themeColors? }) aceita rollMixedDice().dice do Core, preserva a ordem e usa physicalValue ?? rawValue ?? value. Perfis de Vampiro V5, Assimilação, Fate e Daggerheart aplicam seus temas automaticamente. Dados genéricos sem geometria 3D são omitidos por padrão; unsupportedDice: 'error' impede essa omissão. createSystemDisplayRequest() aceita dados já associados a profileId e aplica o perfil de cada sistema.

import { rollMixedDice } from '@erpg/dicecore'
import { createMixedDisplayRequest } from '@erpg/dice3dview/adapters'

const mixed = rollMixedDice('2d20+5; v5(7,3,4); fate(4)', { seed: 'mesa-42' })
await viewer.display(createMixedDisplayRequest({
  id: 'mesa-42',
  seed: 'mesa-42',
  dice: mixed.dice
}))

ViewerOptions

Núcleo e cena

Opção Padrão Uso
container null Seletor ou elemento; obrigatório na prática
assetPath /assets/dice-box/ Raiz pública de themes/
origin origem da página Origem dos assets internos
theme / themeColor default / #2e8555 Tema e cor padrão
preloadThemes / externalThemes [] / {} Pré-carregamento e mapa de temas externos
maxDice 120 Limite de corpos; d100 conta como dois
enableShadows / shadowTransparency true / 0.8 Sombras de contato suaves
lightIntensity / antialias / scale 1 / true / 5 Iluminação, WebGL e escala
delay / wallPadding 10 ms / 0.25 Liberação sequencial e limite do palco
spawnSpacing / spawnHeightStep / spawnOverscan 1.72 / 0 / 0.15 Distribuição de lançamentos
reducedMotion auto auto, always ou never; auto segue o sistema

mode usa physics e é opcional. shadowResolution e duration continuam aceitos para compilar clientes v2, mas são ignorados.

Física

Opção Padrão Uso
gravity 1.3 Multiplicador da gravidade
mass 1.08 Massa base
startingHeight 7.6 Altura inicial
spinForce 5.8 Giro inicial
throwForce 6.4 Energia do lançamento
aggressiveThrowChance 0.12 Chance seedada de lançamento mais energético
colliderScale 1.02 Escala do collider dos poliedros
friction / restitution 0.54 / 0.29 Atrito e elasticidade
linearDamping / angularDamping 0.10 / 0.08 Amortecimento
settleTimeout 4200 ms Janela de acomodação; não decide o resultado

wallBounceChance permanece como alias obsoleto de aggressiveThrowChance. physicsWasmUrl é ignorada: o motor v3 é JavaScript e não usa Havok.

Timeline e callbacks

timeline.enabled usa true, maxEvents usa 500, maxDurationMs usa 12000 e phaseGapMs usa 180. Os efeitos incluem explode, reroll, unique, compound, penetrate, keep, drop, success, failure, neutral e críticos. explode.origin aceita source ou edge; reroll.style e unique.style aceitam hop, edge ou spin. Se o orçamento for excedido, o resultado da timeline marca degraded: true e apresenta o estado final como rolagem plana.

Callbacks disponíveis: onCollision, onThemeConfigLoaded, onThemeLoaded e onTimelineProgress. onCollision recebe IDs opcionais dos dois corpos e force; onTimelineProgress recebe os dados revelados e sequências concluídas em cada fase.

Skins, partículas e brilho

const viewer = new DiceResultViewer({
  container: '#dice-stage',
  skin: {
    texture: '/skins/marmore.webp',
    scale: 1,
    blend: 'multiply',
    opacity: 0.8,
    labels: 'auto'
  },
  particles: { preset: 'sparkle', intensity: 1 },
  glow: { color: '#ff4f93', intensity: 0.7, light: true }
})

skin projeta uma imagem sobre materiais de tipo color; números e símbolos permanecem acima dela. blend aceita normal, multiply, screen e overlay. Partículas podem usar um dos 15 presets ou uma definição effect própria, com emissores para trail, ground, impact, collision, settle, aura, explode e critical. glow controla cor, intensidade, luz na mesa e pulso. Os três recursos são opcionais (null por padrão) e podem ser trocados por updateOptions().

Um DiceLook reúne cor, skin, partículas e brilho num objeto versionado para salvar e aplicar:

import { createDiceLook } from '@erpg/dice3dview'

const look = createDiceLook({
  name: 'Rosa',
  themeColor: '#e60049',
  particles: { preset: 'sparkle' },
  glow: { intensity: 0.7 }
})

await viewer.applyLook(look)
viewer.playParticles('critical')

O formato usa format: 'dice3dview-look' e version: 1. applyLook() valida antes de alterar o viewer; partes ausentes são desligadas. playParticles() aceita impact, collision, settle, aura, explode e critical, opcionalmente com { dice: ['id'] }.

Assets, ciclo de vida e cancelamento

Publique dist/assets/dice-box/ em /assets/dice-box/; a v3 precisa dos temas, modelos e texturas, mas não de havok/. Para tema externo, configure externalThemes e CORS do servidor de assets. Alterações de container, id, antialias ou da raiz de assets já carregados exigem uma nova instância.

import { isDisplayCancelledError } from '@erpg/dice3dview'

try {
  await viewer.display(request)
} catch (error) {
  if (isDisplayCancelledError(error)) return
  throw error
}

Fonte técnica: API oficial da revisão v3 e tipos públicos.