Write a plugin for Dentra Viewer
Wtyczka dodaje funkcje do Viewera. Ty ją piszesz, my ją testujemy, a jeśli nam się spodoba, wszyscy znajdą ją w panelu «Wtyczki».
Wprowadzenie
Wtyczki pisze społeczność: są dla każdego, kto chce dostosować Viewer albo dodać do niego funkcje. My dajemy środowisko i tę dokumentację.
Wtyczka to mała strona internetowa (HTML, JavaScript i CSS), którą Viewer otwiera we własnej ramce. Z ramki wtyczka rozmawia z Viewerem przez zestaw DentraViewer, który jest już załadowany.
Wtyczka działa w zamkniętej ramce: nie widzi strony, konta ani danych Dentra. Może robić tylko to, o co prosi w uprawnieniach, a dentysta czyta je, zanim ją włączy.
Co możesz zbudować
- Nowe sposoby sterowania widokiem: gesty dłoni przed kamerą internetową, kontrolery do gier, komendy głosowe.
- Pomiary i adnotacje: kliknięcia na modelu, punkty, linie i napisy w scenie.
- Analiza modeli: kontrole siatki, obliczenia, wyniki zapisane do pliku.
- Połączenia z innymi usługami: modele z zewnątrz, telefon jako pilot.
Pierwsze kroki
- 1
Zostań developerem
Potrzebujesz konta Dentra. W /app, w pozycji «Developer», poproś o dostęp: my go zatwierdzamy.
- 2
Zacznij od przykładu
Pobierz przykładową wtyczkę: cztery strzałki, które obracają model. Jest w niej wszystko, czego potrzebujesz.
- 3
Napisz własną
Zmień dentra-plugin.json (id, name, permissions) i stronę. Zestaw DentraViewer już tam jest: nie trzeba go importować.
- 4
Wypróbuj ją w Viewerze
Spakuj folder do zipa i wgraj go ze swojej strefy Developer przyciskiem «Wgraj jako wersję roboczą»: widzisz ją tylko ty i nie trafia do weryfikacji. «Wypróbuj w Viewerze» otwiera Viewer z włączoną twoją wtyczką, na dwóch przykładowych łukach albo na twoich własnych modelach. Po każdej zmianie wgraj zip ponownie z tym samym numerem wersji i spróbuj jeszcze raz.
- 5
Zgłoś ją
Gdy działa, naciśnij «Zgłoś do weryfikacji» obok wersji roboczej. Jeśli coś w zipie jest nie tak, powiemy ci od razu, już przy wgrywaniu.
Struktura zipa
my-plugin.zip
├── dentra-plugin.json
├── index.html ← "entry"
├── plugin.js
├── style.css
└── icon.png ← "icon" (optional)W zipie mogą być tylko te typy plików: html, js, mjs, css, json, wasm, png, jpg, jpeg, svg, webp, gif, ico, woff, woff2, txt, md, task, tflite, bin, data, onnx. Najwyżej 400 plików i 120 MB po rozpakowaniu; sam zip może mieć do 40 MB.
dentra-plugin.json
Plik leży w katalogu głównym zipa i mówi, czym jest wtyczka i czego potrzebuje.
{
"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
- Nazwa techniczna: 3-40 znaków spośród małych liter, cyfr i myślników, z literą albo cyfrą na początku i na końcu. Należy do konta, które wgra ją pierwsze, także jako wersję roboczą: nikt inny nie może jej użyć.
- name
- Nazwa, którą widzi dentysta, do 40 znaków.
- version
- Trzy liczby, np. 1.0.0. Przy nowej wersji ją podnieś: numer już zgłoszony do weryfikacji zostaje odrzucony, a wersję roboczą możesz wgrać ponownie z tym samym numerem.
- description
- Jedna linijka o tym, co robi, do 300 znaków.
- author
- Twoje imię i nazwisko; e-mail i strona są opcjonalne.
- entry
- Strona HTML, którą Viewer otwiera w ramce. Jeśli brak, index.html.
- permissions
- O co prosi Viewer: zobacz «Uprawnienia».
- reasons
- Dla każdego uprawnienia (oprócz view) jedna linijka o tym, po co, do 160 znaków. Dentysta czyta ją, zanim włączy wtyczkę.
- platforms
- Gdzie działa: web, desktop albo oba. Jeśli brak, oba. Z internet i models razem tylko desktop.
- send
- Wymagane tylko, jeśli prosisz o internet i models razem: to (domena, która odbiera skany, np. api.example.com, bez https://) i why (po co).
- icon
- Opcjonalna: plik .png, .svg lub .webp w zipie.
- api
- Wersja zestawu: dziś 1.
Uprawnienia
Deklaruje się je w polu permissions. Każde uprawnienie to jedna rzecz. Zanim dentysta włączy wtyczkę, czyta, o co prosi, razem z powodami, które wpisałeś w reasons.
- view
- obracać, przesuwać i przybliżać model, przywracać widok, wiedzieć, gdzie patrzy.
- pick
- wiedzieć, gdzie dentysta klika na modelu: punkt, kierunek powierzchni i który model.
- draw
- rysować w scenie punkty, linie, napisy i modele przyniesione przez wtyczkę (STL, PLY, OBJ).
- edit
- ukrywać, kolorować lub robić przezroczyste otwarte modele.
- models
- czytać pliki otwartych modeli.
- files
- zapisać plik na komputerze dentysty.
- toolbar
- dodać do 4 przycisków na pasku Viewera.
- camera
- otrzymywać obrazy z kamery. Otwiera ją Viewer, prosząc dentystę o zgodę; wtyczka dostaje tylko obrazy.
- microphone
- otrzymywać dźwięk z mikrofonu. Otwiera go Viewer, prosząc dentystę o zgodę.
- internet
- łączyć się z internetem. Bez tego wtyczka nie może połączyć się z żadną inną stroną.
- clipboard
- kopiować tekst do schowka.
Przeglądarka i aplikacja na komputer
Wtyczka może działać w Viewerze w przeglądarce (web), w aplikacji na komputer (desktop) albo w obu. Deklarujesz to w polu platforms, a my pokazujemy to na liście i na stronie wtyczki. Dziś panel wtyczek jest w Viewerze w przeglądarce; aplikacja na komputer na razie go nie ma.
Internet i models razem oznaczają, że wtyczka może wysyłać skany pacjentów na zewnątrz. Da się to zrobić tylko w aplikacji na komputer, gdzie pliki należą do dentysty, i tylko deklarując w polu send, dokąd idą i po co. Dentysta czyta to wprost, zanim ją włączy; w przeglądarce takiej wtyczki nie da się włączyć.
"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." }Opis zestawu
Na stronie wejściowej twojej wtyczki (entry) jest już window.DentraViewer: Viewer ładuje go sam. Funkcje zapisane z await zwracają Promise; pozostałe nie czekają na odpowiedź. Każda funkcja wymaga podanego uprawnienia; bez niego Viewer ją ignoruje albo Promise kończy się błędem. DentraViewer istnieje tylko wewnątrz Viewera: jeśli otworzysz stronę wtyczki osobno, ze swojego komputera, nie znajdziesz go.
await DentraViewer.ready()czeka na Viewer; zwraca { language, permissions, api }: język użytkownika, przyznane uprawnienia i wersję zestawu.
DentraViewer.view.move({ rotate: { x, y, z }, pan: { x, y }, zoom })rotate w radianach wokół osi ekranu (x góra i dół, y lewo i prawo, z obrót w miejscu), pan w ułamkach rozmiaru modelu, dodatni zoom przybliża (0.1 = 10%). Każda wartość liczy się najwyżej jako 0.5 na wywołanie.
Uprawnienie: view
DentraViewer.view.reset()przywraca widok do poprzedniego stanu.
Uprawnienie: view
await DentraViewer.view.get()gdzie kamera patrzy teraz: position i target, każde [x, y, z].
Uprawnienie: view
DentraViewer.pick.onClick(({ point, normal, model }) => …)przy każdym kliknięciu na modelu (nie przy przeciąganiu): point i normal jako [x, y, z] oraz model, id klikniętego modelu albo null.
Uprawnienie: pick
DentraViewer.scene.draw(key, { shape, … })rysuje kształt: shape "points" (points, color, size), "line" (points, color, closed), "text" (point, text, color, size) albo "mesh" (data, format stl/ply/obj, color, opacity). Współrzędne są takie same jak w pick.onClick. Ten sam key go zastępuje. Do 500 kształtów, mesh do 100 MB.
Uprawnienie: draw
DentraViewer.scene.remove(key) / DentraViewer.scene.clear()usuwa jeden kształt albo wszystkie kształty wtyczki.
Uprawnienie: draw
await DentraViewer.models.list()otwarte modele: id, name, format.
Uprawnienie: models
await DentraViewer.models.read(id)plik modelu: data to ArrayBuffer.
Uprawnienie: models
DentraViewer.models.change(id, { visible, opacity, color })pokazuje albo ukrywa (visible), zmienia przezroczystość (opacity, od 0 do 1) albo kolor (color, "#rrggbb"; null przywraca poprzedni kolor) otwartego modelu.
Uprawnienie: edit
DentraViewer.files.save(name, data, type)pobiera plik na komputer (string albo ArrayBuffer, do 200 MB); type to typ pliku, np. "text/csv".
Uprawnienie: files
DentraViewer.toolbar.button(key, label) / toolbar.onPress((key) => …) / toolbar.remove(key)przycisk na pasku Viewera (do 4, etykieta do 24 znaków), to, co się dzieje po jego naciśnięciu, i toolbar.remove(key), żeby go usunąć.
Uprawnienie: toolbar
DentraViewer.camera.start({ fps, width }) / camera.onFrame((image, t) => …)włącza kamerę: fps od 1 do 30 (domyślnie 15), width od 160 do 1280 pikseli (domyślnie 640). Obrazy przychodzą jako ImageBitmap; camera.onStatus mówi, czy jest włączona, a jeśli nie, dlaczego. camera.stop() ją wyłącza.
Uprawnienie: camera
DentraViewer.microphone.start() / microphone.onAudio((samples, sampleRate) => …)włącza mikrofon; dźwięk przychodzi w kawałkach Float32Array, z częstotliwością próbkowania. microphone.onStatus mówi, czy jest włączony, a jeśli nie, dlaczego; microphone.stop() go wyłącza.
Uprawnienie: microphone
await DentraViewer.storage.get() / DentraViewer.storage.set(value)jedna wartość JSON zapisana na tym urządzeniu, tylko dla twojej wtyczki, do 100 KB: większa się nie zapisuje. get() zwraca null, jeśli nic nie ma.
DentraViewer.clipboard.write(text)kopiuje tekst do schowka, do 2000 znaków.
Uprawnienie: clipboard
DentraViewer.panel.height(px)wysokość ramki wtyczki w pikselach, od 80 do 560 (domyślnie 180).
Pełny przykład
// 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; }
});Weryfikacja i publikacja
- Zgłaszasz zip ze swojej strefy Developer albo naciskasz «Zgłoś do weryfikacji» przy wersji roboczej, którą już wypróbowałeś. Pliki i dentra-plugin.json sprawdzamy od razu, gdy wgrywasz zip, także jako wersję roboczą, i mówimy ci, czego brakuje (komunikaty są po angielsku). Gdy wtyczka trafia do weryfikacji, dostajesz e-mail z potwierdzeniem.
- Testujemy wtyczkę w Viewerze, zanim ją opublikujemy. Jeśli czyta modele i korzysta z internetu, przechodzi też kontrolę prywatności.
- Jeśli ją zatwierdzimy, publikujemy ją: pojawia się na publicznej liście wtyczek i w panelu Viewera. Jeśli nie, piszemy ci, co zmienić, a w twojej strefie Developer ta wersja ma oznaczenie «Do zmiany» z naszą notatką. W obu przypadkach dostajesz e-mail.
- Przy nowej wersji, także po odrzuceniu, podnieś numer w version i zgłoś ją ponownie: numeru już zgłoszonego nie da się użyć drugi raz. Wersję roboczą natomiast wgrywasz ponownie z tym samym numerem, dopóki jej nie zgłosisz. Przechodzi ten sam test, a dopóki jej nie zatwierdzimy, w Viewerze zostaje poprzednia. Gdy ją zatwierdzimy, każdy, kto już włączył wtyczkę, automatycznie korzysta z nowej wersji. Jeśli jednak prosi o uprawnienia, o które poprzednia wersja nie prosiła, każdy, kto ją włączył, zastanie ją wstrzymaną: Viewer pokaże mu nowe uprawnienia z twoimi uzasadnieniami, a wtyczka ruszy znowu dopiero, gdy je zaakceptuje.
Zasady
- Wtyczki są darmowe dla tych, którzy z nich korzystają.
- Potrzebujesz konta Dentra z dostępem Developer, który zatwierdzamy. Potem testujemy każdą wtyczkę, jedną po drugiej.
- Wtyczka działa we własnej zamkniętej ramce: nie widzi strony, kont ani danych Dentra.
- Każde uprawnienie wymaga uzasadnienia w jednej linijce.
- Skany wychodzą na zewnątrz tylko w aplikacji na komputer, gdy w send podasz, dokąd i po co.
- Zgłaszając wtyczkę, zgadzasz się, że ją przetestujemy i, jeśli nam się spodoba, opublikujemy za darmo w Viewerze. Wtyczka pozostaje twoja.
- Możemy wycofać wtyczkę z katalogu: przy problemie z bezpieczeństwem robimy to od razu, bez czekania. Powód wysyłamy ci e-mailem i znajdziesz go w swojej strefie Developer; kto ją włączył, zastanie ją wyłączoną.
Zostań developerem
Potrzebujesz konta Dentra, z danymi do faktury jak każde konto. Ze swojego konta prosisz o dostęp Developer; gdy go zatwierdzimy, w swojej strefie zgłaszasz wtyczki i widzisz, na jakim są etapie.
Dostęp Developer to początek: wkrótce przejdą przez niego także API Dentra.