Tutorial 18: Plugins — extender el renderer sin forkearlo
Nivel: Avanzado Tiempo: 20 minutos Aprenderás: cómo el sistema de plugins en
@joroya/core/pluginste permite shippear un nuevo tipo de componente con su propio comportamiento de rendering, sin modificarThreeRenderer.
Estabilidad:
PluginRegistry,Plugin, yComponentHandlerson@experimentalen v1.0.
Cuándo necesitarías un plugin
El renderer built-in maneja Geometry, Material, Camera, Light, ParticleSystem, audio, instancing, y skinned meshes. Cualquier cosa más allá — voxel grids, shaders custom, salida de GPU compute, visualizadores de física terceros — es territorio de plugin.
Un plugin es un módulo chico que:
- Define un
ComponentHandlerpara unComponentTypeo ID string custom. - Devuelve un
THREE.Object3D(o cualquier objeto backend) desde sucreate(node). - Opcionalmente sincroniza estado por frame en
update(node, obj, dt)y libera GPU endispose(node, obj).
El renderer consulta el registry antes de sus ramas built-in.
Paso 1 — Definir un componente custom
import { Component } from "@joroya/core";
export class VoxelGridComponent extends Component {
readonly type = "VoxelGrid";
constructor(
public readonly size: { x: number; y: number; z: number },
public readonly cellSize: number,
public readonly voxels: Uint8Array,
) { super(); }
}
Paso 2 — Escribir el handler
import type { ComponentHandler } from "@joroya/core";
import * as THREE from "three";
export const voxelHandler: ComponentHandler<THREE.Object3D> = {
componentType: "VoxelGrid",
create(node) {
// Construir un THREE.InstancedMesh — un cubo por voxel no-cero.
// … código del builder …
return mesh;
},
update(node, mesh, dt) {
// Hook opcional por frame
},
dispose(node, mesh) {
// Liberar GPU resources
},
};
Paso 3 — Bundle y registro
import type { Plugin } from "@joroya/core";
export const voxelPlugin: Plugin = {
name: "voxel-renderer",
handlers: [voxelHandler],
};
renderer.usePlugin(voxelPlugin);
Precedencia de plugins
- Para cada componente del nodo, consulta el registry de plugins.
- Si un handler existe y devuelve no-
null, ese objeto se usa. - Si devuelve
null, cae al siguiente componente del nodo. - Si ningún handler matchea, corre la cadena built-in.
Los plugins pueden reemplazar defaults (devolver objeto) o augmentar (devolver null pero recibir update(dt)).
Lifecycle de disposal
renderer.rebuildScene() y renderer.dispose() recorren cada objeto de plugin y llaman handler.dispose(node, obj). Ahí liberás geometry.dispose() / material.dispose() / texture.dispose().
Próximos pasos
- Plugin multi-handler: registrá handlers para múltiples tipos desde el mismo paquete.
- Publicar tu plugin:
@<tu-org>/oroya-plugin-voxels— la convención es nombrar plugins por sucomponentType.