Write a plugin for Dentra Viewer
Un plugin aggiunge funzioni al Viewer. Lo scrivi tu, lo proviamo noi, e se ci piace lo trovano tutti nel pannello «Plugin».
Introduzione
I plugin li scrive la comunità: servono a chi vuole personalizzare il Viewer o aggiungergli funzioni. Noi diamo l'ambiente e questa documentazione.
Un plugin è una piccola pagina web (HTML, JavaScript e CSS) che il Viewer apre in un suo riquadro. Dal riquadro il plugin parla col Viewer attraverso il kit DentraViewer, che trova già caricato.
Il plugin gira chiuso in un recinto: non vede la pagina, il conto né i dati di Dentra. Può fare solo quello che chiede nei permessi, e il dentista legge i permessi prima di attivarlo.
Cosa si può costruire
- Comandi nuovi per la vista: gesti della mano davanti alla webcam, controller da gioco, comandi a voce.
- Misure e annotazioni: clic sul modello, punti, linee e scritte nella scena.
- Analisi dei modelli: controlli sulla mesh, conti, risultati salvati in un file.
- Collegamenti con altri servizi: modelli portati da fuori, telefono come telecomando.
Per iniziare
- 1
Diventa developer
Ti serve un conto Dentra. Da /app, nella voce «Developer», chiedi l'accesso: lo approviamo noi.
- 2
Parti dall'esempio
Scarica il plugin d'esempio: quattro frecce che girano il modello. Dentro c'è tutto quello che serve.
- 3
Scrivi il tuo
Cambia dentra-plugin.json (id, name, permissions) e la pagina. Il kit DentraViewer c'è già: non va importato.
- 4
Provalo nel Viewer
Comprimi la cartella in uno zip e caricalo dalla tua area Developer con «Carica come bozza»: lo vedi solo tu e non va in revisione. «Prova nel Viewer» apre il Viewer col tuo plugin acceso, su due arcate di esempio o sui tuoi modelli. Hai cambiato qualcosa? Ricarica lo zip con lo stesso numero di versione e riprova.
- 5
Presentalo
Quando funziona, premi «Presenta per la revisione» accanto alla bozza. Se qualcosa nello zip non va, te lo diciamo subito, già quando lo carichi.
La struttura dello zip
my-plugin.zip
├── dentra-plugin.json
├── index.html ← "entry"
├── plugin.js
├── style.css
└── icon.png ← "icon" (optional)Nello zip possono stare solo questi tipi di file: html, js, mjs, css, json, wasm, png, jpg, jpeg, svg, webp, gif, ico, woff, woff2, txt, md, task, tflite, bin, data, onnx. Al massimo 400 file e 120 MB una volta scompattato; lo zip pesa fino a 40 MB.
dentra-plugin.json
Il file sta nella radice dello zip e dice chi è il plugin e cosa gli serve.
{
"id": "click-markers",
"name": "Markers",
"version": "1.0.0",
"description": "Places a numbered marker wherever you click on the model.",
"author": {
"name": "Your name",
"email": "[email protected]",
"website": "https://example.com"
},
"entry": "index.html",
"permissions": [
"pick",
"draw",
"toolbar"
],
"reasons": {
"pick": "To place a marker where you click.",
"draw": "To draw the marker on the model.",
"toolbar": "A button to clear the markers."
},
"platforms": [
"web",
"desktop"
],
"api": 1
}- id
- Il nome tecnico: 3-40 caratteri fra lettere minuscole, numeri e trattini, con una lettera o un numero all'inizio e alla fine. Resta del conto che lo carica per primo, anche come bozza: nessun altro può usarlo.
- name
- Il nome che vede il dentista, fino a 40 caratteri.
- version
- Tre numeri, per esempio 1.0.0. Per una versione nuova alzalo: un numero già presentato per la revisione viene rifiutato, mentre una bozza si ricarica con lo stesso numero.
- description
- Una riga su cosa fa, fino a 300 caratteri.
- author
- Il tuo nome; email e sito sono facoltativi.
- entry
- La pagina HTML che il Viewer apre nel riquadro. Se manca, index.html.
- permissions
- Cosa chiede al Viewer: vedi «Permessi».
- reasons
- Per ogni permesso (tranne view), una riga sul perché, fino a 160 caratteri. Il dentista la legge prima di attivarlo.
- platforms
- Dove funziona: web, desktop o tutti e due. Se manca, tutti e due. Con internet e models insieme vale solo desktop.
- send
- Obbligatorio solo se chiedi internet e models insieme: to (il dominio che riceve le scansioni, per esempio api.example.com, senza https://) e why (perché).
- icon
- Facoltativa: un .png, .svg o .webp dentro lo zip.
- api
- La versione del kit: oggi 1.
Permessi
Si dichiarano nel campo permissions. Ogni permesso è una cosa sola. Prima di attivare il plugin il dentista legge cosa chiede, con i motivi che hai scritto in reasons.
- view
- girare, spostare e avvicinare il modello, rimettere la vista com'era, sapere dove guarda.
- pick
- sapere dove il dentista clicca sul modello: punto, direzione della superficie e quale modello.
- draw
- disegnare nella scena punti, linee, scritte e modelli portati dal plugin (STL, PLY, OBJ).
- edit
- nascondere, colorare o rendere trasparenti i modelli aperti.
- models
- leggere i file dei modelli aperti.
- files
- salvare un file sul computer del dentista.
- toolbar
- mettere fino a 4 pulsanti nella barra del Viewer.
- camera
- ricevere le immagini della fotocamera. La apre il Viewer, chiedendo il permesso al dentista; al plugin arrivano solo le immagini.
- microphone
- ricevere l'audio del microfono. Lo apre il Viewer, chiedendo il permesso al dentista.
- internet
- collegarsi a internet. Senza, il plugin non può collegarsi a nessun altro sito.
- clipboard
- copiare un testo negli appunti.
Sito e app per computer
Un plugin può funzionare nel Viewer sul sito (web), nell'app per computer (desktop) o in tutti e due. Lo dichiari nel campo platforms, e lo mostriamo nell'elenco e nella scheda del plugin. Oggi il pannello dei plugin c'è nel Viewer sul sito; nell'app per computer, per ora, non c'è.
Internet e models insieme vuol dire che il plugin può mandare fuori le scansioni dei pazienti. Questo si può solo nell'app per computer, dove i file sono del dentista, e solo dichiarando nel campo send a chi vanno e perché. Il dentista lo legge in chiaro prima di attivarlo; sul sito un plugin così non si può attivare.
"platforms": ["web", "desktop"]
// internet + models: desktop only, and you must say where the scans go
"permissions": ["internet", "models"],
"send": { "to": "api.example.com", "why": "Analyses the scan and returns a report." }Riferimento del kit
Nella pagina d'entrata del plugin (entry) trovi già window.DentraViewer: il Viewer lo carica da sé. Le funzioni scritte con await restituiscono una Promise; le altre non aspettano risposta. Ogni funzione richiede il permesso indicato; senza, il Viewer la ignora o la Promise fallisce con un errore. DentraViewer c'è solo dentro il Viewer: se apri la pagina del plugin da sola, dal tuo computer, non lo trovi.
await DentraViewer.ready()aspetta il Viewer; restituisce { language, permissions, api }: la lingua di chi lo usa, i permessi concessi e la versione del kit.
DentraViewer.view.move({ rotate: { x, y, z }, pan: { x, y }, zoom })rotate in radianti attorno agli assi dello schermo (x su e giù, y destra e sinistra, z rotazione sul posto), pan in frazioni della grandezza del modello, zoom positivo avvicina (0.1 = il 10%). Ogni valore conta al massimo 0.5 per chiamata.
Permesso: view
DentraViewer.view.reset()rimette la vista com'era.
Permesso: view
await DentraViewer.view.get()dove guarda la camera adesso: position e target, ciascuno [x, y, z].
Permesso: view
DentraViewer.pick.onClick(({ point, normal, model }) => …)a ogni clic sul modello (non quando lo trascinano): point e normal come [x, y, z], e model, l'id del modello cliccato oppure null.
Permesso: pick
DentraViewer.scene.draw(key, { shape, … })disegna una forma: shape "points" (points, color, size), "line" (points, color, closed), "text" (point, text, color, size) o "mesh" (data, format stl/ply/obj, color, opacity). Le coordinate sono quelle di pick.onClick. La stessa key la sostituisce. Fino a 500 forme, una mesh fino a 100 MB.
Permesso: draw
DentraViewer.scene.remove(key) / DentraViewer.scene.clear()toglie una forma, o tutte quelle del plugin.
Permesso: draw
await DentraViewer.models.list()i modelli aperti: id, name, format.
Permesso: models
await DentraViewer.models.read(id)il file di un modello: data è un ArrayBuffer.
Permesso: models
DentraViewer.models.change(id, { visible, opacity, color })mostra o nasconde (visible), cambia la trasparenza (opacity, da 0 a 1) o il colore (color, "#rrggbb"; null torna al colore di prima) di un modello aperto.
Permesso: edit
DentraViewer.files.save(name, data, type)scarica un file sul computer (stringa o ArrayBuffer, fino a 200 MB); type è il tipo del file, per esempio "text/csv".
Permesso: files
DentraViewer.toolbar.button(key, label) / toolbar.onPress((key) => …) / toolbar.remove(key)un pulsante nella barra del Viewer (fino a 4, etichetta fino a 24 caratteri), cosa succede quando lo premono, e toolbar.remove(key) per toglierlo.
Permesso: toolbar
DentraViewer.camera.start({ fps, width }) / camera.onFrame((image, t) => …)accende la fotocamera: fps da 1 a 30 (di base 15), width da 160 a 1280 pixel (di base 640). Le immagini arrivano come ImageBitmap; camera.onStatus dice se è accesa o perché no. camera.stop() la spegne.
Permesso: camera
DentraViewer.microphone.start() / microphone.onAudio((samples, sampleRate) => …)accende il microfono; l'audio arriva in pezzi Float32Array, con la frequenza di campionamento. microphone.onStatus dice se è acceso o perché no; microphone.stop() lo spegne.
Permesso: microphone
await DentraViewer.storage.get() / DentraViewer.storage.set(value)un valore JSON salvato su questo dispositivo, solo per il tuo plugin, fino a 100 KB: oltre non si salva. get() restituisce null se non c'è niente.
DentraViewer.clipboard.write(text)copia un testo negli appunti, fino a 2000 caratteri.
Permesso: clipboard
DentraViewer.panel.height(px)l'altezza del riquadro del plugin in pixel, da 80 a 560 (di base 180).
Un esempio completo
// plugin.js: place a numbered marker wherever the dentist clicks
// Permissions in dentra-plugin.json: "pick", "draw", "toolbar" (the manifest above)
let n = 0;
DentraViewer.ready().then(({ language, permissions }) => {
// language: the dentist's language ("it", "en", "de"…), to translate your labels
DentraViewer.panel.height(120);
DentraViewer.toolbar.button("clear", "Clear");
});
DentraViewer.pick.onClick(({ point }) => {
n++;
DentraViewer.scene.draw("dot-" + n, { shape: "points", points: [point], color: "#e5484d", size: 0.6 });
DentraViewer.scene.draw("label-" + n, { shape: "text", point: [point[0], point[1] + 2, point[2]], text: "#" + n });
});
DentraViewer.toolbar.onPress((key) => {
if (key === "clear") { DentraViewer.scene.clear(); n = 0; }
});Revisione e pubblicazione
- Presenti lo zip dalla tua area Developer, oppure premi «Presenta per la revisione» su una bozza che hai già provato. File e dentra-plugin.json li controlliamo appena carichi lo zip, anche come bozza, e ti diciamo cosa manca (i messaggi sono in inglese). Quando entra in revisione ti arriva un'email di conferma.
- Lo proviamo nel Viewer prima di pubblicarlo. Se legge i modelli e usa internet, passa anche una verifica sulla privacy.
- Se lo approviamo lo pubblichiamo: compare nell'elenco pubblico dei plugin e nel pannello del Viewer. Se no, ti scriviamo cosa cambiare, e nella tua area Developer quella versione è segnata «Da cambiare», con la nostra nota. In tutti e due i casi ti arriva un'email.
- Per una versione nuova, anche dopo un rifiuto, alza il numero di version e presentala di nuovo: un numero già presentato non si ripresenta. Una bozza invece la ricarichi con lo stesso numero finché non la presenti. Passa la stessa prova, e finché non la approviamo nel Viewer resta quella di prima. Quando la approviamo, chi ha già acceso il plugin usa da solo la versione nuova. Se però chiede permessi che la versione di prima non chiedeva, chi l'aveva acceso la trova in pausa: il Viewer gli mostra i permessi nuovi con i tuoi motivi, e il plugin riparte solo quando li accetta.
Regole
- I plugin sono gratuiti per chi li usa.
- Serve un conto Dentra con l'accesso Developer, che approviamo noi. Poi proviamo ogni plugin, uno per uno.
- Il plugin gira chiuso nel suo recinto: non vede la pagina, i conti né i dati di Dentra.
- Ogni permesso va motivato in una riga.
- Le scansioni escono solo nell'app per computer, dichiarando in send a chi vanno e perché.
- Presentandolo accetti che lo proviamo e, se ci piace, lo pubblichiamo gratis nel Viewer. Il plugin resta tuo.
- Possiamo ritirare un plugin dal catalogo: per un problema di sicurezza lo facciamo subito, senza aspettare. Ti scriviamo il motivo per email e lo ritrovi nella tua area Developer; chi l'aveva acceso lo trova spento.
Diventa developer
Ti serve un conto Dentra, con i dati di fatturazione come per ogni conto. Dal conto chiedi l'accesso Developer; quando lo approviamo, nella tua area presenti i plugin e vedi a che punto sono.
L'accesso Developer è l'inizio: domani da lì passeranno anche le API di Dentra.