Saltar al contenido principal

Paquetes compartidos

Puedes importar estos paquetes en tu propio código. Aquí verás qué puedes usar en cada sitio y qué te da cada paquete.

Las entidades son objetos

En el código, los objetos que ves en el editor se llaman entidades (entities). Son lo mismo.

Los paquetes que puedes importar dependen de dónde se ejecuta tu código:

PaqueteQué te daEn un scriptEn un pluginEn una extensión de componente
@was/ecsentidades, componentes, el mundo✓✓✓
@was/enginelas clases de componente✓✓✓
@was/signalsvalores reactivos—✓✓
@was/svdtesquemas y validación✓✓—
@was/utilspequeñas utilidades✓✓—
@was/uila propia biblioteca de componentes del editor—✓✓
@was/iconsel juego de iconos del editor—✓✓
reactReact 19—✓✓
En un script, usa ctx.effect

Un script no puede importar @was/signals directamente. Usa ctx.effect en su lugar. Funciona igual y se detiene cuando desaparece su objeto, así que no queda nada en marcha.

@was/signals: valores reactivos​

Una señal (signal) es un valor que sabe quién lo lee. Cuando cambia, solo se actualiza lo que depende de él.

import { signal, computed, effect, batch, untracked } from '@was/signals';

const score = signal(0);
const doubled = computed(() => score.value * 2);

const stop = effect(() => {
render(score.value); // vuelve a ejecutarse solo cuando cambia score
});

batch(() => {
score.value += 1;
score.value += 1; // los efectos se ejecutan una vez, no dos
});

stop();
FunciónQué hace
signal(v)un valor que se puede observar; lees y escribes .value
computed(fn)un valor derivado, que solo se recalcula cuando cambia lo que lee
effect(fn)se ejecuta ahora y otra vez cada vez que cambia lo que ha leído; devuelve una función para detenerlo
batch(fn)agrupa escrituras para que los observadores se ejecuten una sola vez al final
untracked(fn)lee un valor sin depender de él
ref(obj)hace reactivo un objeto entero, hasta el último valor anidado
snapshot(obj)una copia simple, no reactiva
raw(obj)el objeto original, sin seguimiento
readonly(obj)una vista en la que no se puede escribir

Para paneles de React, un paquete complementario te da useSignal, useComputed, useSignalEffect y useLiveSignal. Así un componente se vuelve a renderizar a partir de una señal sin ninguna conexión extra.

@was/ui: componentes del editor​

Crea los paneles de tus plugins y tus extensiones de componente con los mismos componentes que usa el editor. Así tus paneles parecen parte del editor, y no una página web incrustada. La biblioteca tiene estos componentes:

Accordion · Avatar · Button · Card · Checkbox · Chip · CloseButton
DimensionInput · Draggable · Dropdown · Flag · Icon · IconButton · Input
Menu · Modal · Outside · Panel · Popover · Portal · Render · Scroll
Search · Section · Segmented · Select · Skeleton · Switcher · Tabs
Toast · Toolbar · Tooltip

Para los iconos, usa @was/icons.

La hoja de estilos viene ya generada

Los paneles solo pueden usar las clases de utilidad que incluye la biblioteca. Los valores arbitrarios como text-[13px] no están incluidos. Para tamaños que no están en la escala, usa un style en línea.

@was/ecs: entidades y componentes​

Este paquete tiene Entity, Component y Space. Con él, un plugin lee y cambia una escena a través de la API completa, no de una API aparte y limitada.

Space: el mundo​

LlamadaDevuelve
getEntity(id)una entidad, o nada
hasEntity(id)si existe
getEntities()todas
queryEntities(A, B, …)todas las entidades que tienen todos esos componentes
makeQueryEntities(A, B, …)la misma consulta, creada una vez para usarla muchas veces
createEntity(id?, components?)una entidad nueva, añadida al mundo
addEntity(…e) · removeEntity(…e)añade una entidad al mundo o la quita
getSystem(S) · hasSystem(S)un sistema, o si existe
execute()ejecuta un fotograma
Usa queryEntities para encontrar entidades

Así, pedir «todo lo que tenga una luz y un transform» es rápido. getEntities() te da el mundo entero, y tienes que filtrarlo tú.

Entity: un objeto del mundo​

LlamadaQué hace
getComponent(Type)devuelve un componente, o null
getComponents(A, B)devuelve varios a la vez, en ese orden
hasComponent(A, B)comprueba si los tiene todos
addComponent(…c)añade componentes; si ya tiene uno de ese tipo, se ignora
removeComponent(…c)quita componentes, por clase o por instancia
component(fn)ejecuta fn para cada componente, ahora y en el futuro
clone() · clean()copia la entidad, o le quita todos sus componentes
.id · .componentssu id y sus componentes, indexados por tipo

Component: los datos​

LlamadaQué hace
.x o get('x')lee un campo; dentro de un efecto, además se suscribe a él
$datael componente entero como objeto simple
$rawDatael objeto guardado, sin suscribirse; de solo lectura
update({ … })escribe datos. Es la única forma de escribir.
updateAt(path, value)escribe en lo profundo de un componente grande sin volver a validarlo entero
version(field?)un contador que sube cuando algo cambia, para que puedas depender de un campo sin leerlo
reset(data?)vuelve a los valores por defecto
clone()hace una copia
Usa version() para listas grandes

Leer un valor grande te suscribe a cada elemento que contiene. Depende mejor de su contador de versión: sabes que ha cambiado sin observar cada elemento. Así es como un panel sigue siendo rápido con una lista de veinte mil elementos.

@was/engine: clases de componente​

Cada tipo de componente es una clase: TransformComponent, MaterialComponent, RigidBodyComponent y las demás. Importa la clase y pásala a getComponent, hasComponent o query.

Para ver la lista completa con todos los campos, consulta la referencia de componentes.

@was/svdt: esquemas​

Con este paquete describes la forma de tus datos y los compruebas.

import { s, compile } from '@was/svdt';

const schema = s.object({ speed: s.f64(1), name: s.string('') });
const codec = compile(schema); // compila una vez, donde lo declaras, nunca en cada llamada
const value = codec.parse(input);

Describe una forma​

  • Números: s.f32 s.f64 s.i8 s.u8 s.i16 s.u16 s.i32 s.u32, cada uno con un valor por defecto.
  • Escalares: s.bool, s.string, s.color, s.literal, s.enum, s.unknown, s.ref.
  • Vectores: s.vec2, s.vec3, s.mat4.
  • Compuestos: s.object, s.variant, s.array, s.record, s.union, s.preprocess, s.lazy.

Puedes encadenar estos métodos en cualquiera de ellos: .default(v), .optional(), .nullable(), .min(n), .max(n), .int().

Usa un códec compilado​

LlamadaQué hace
parse(input)valida y normaliza; lanza un error si la entrada no es válida
safeParse(input)lo mismo, pero devuelve un resultado correcto o un error en lugar de lanzarlo
parseAt(path, v)valida un campo sin tocar el resto
equals(a, b)comparación profunda
diff(a, b)devuelve lo que ha cambiado
apply(target, p)aplica un diff
invert(p)invierte un diff
pack · unpackconvierte a una forma binaria compacta y viceversa

Para inspeccionar el propio esquema en lugar de los datos, usa introspect, keys y requiredKeys.

@was/utils​

Pequeñas utilidades: pick, omit, assign, keys, values, entries, capitalize, basename, extname, dispose (combina varias funciones de limpieza en una) y utilidades de tipos MIME para comprobar tipos de archivo.


Siguiente: Glosario: los términos que se usan en esta documentación.