Anatomija Blender-add-ona, ki govori OAuth in REST — brez zamrznitve UI-ja
Blenderjev bpy-API teče v main threadu. Blokirni HTTP-call za 500-MB-.blend-upload pusti Blender 90 sekund „ne odziva se več“ — večina uporabnikov proces prisili v ponovni zagon. Fix je Background-Worker s Timer-Callbackom v main thread plus OAuth device flow (brez browser-callbacka).
Naš zer0one-blender-addon (na GitHubu) doda Blenderju menu `File → Send to ZER0ONE Lab`. Klik, in aktualna scena gre na Cinema-Render-backend. Prva verzija je vzela ~2 tedna — prve dni je vsaka iteracija prišla nazaj z „zakaj se Blender ne odziva več“. Trije problemi, ki jih je bilo pri tem treba rešiti, so razmeroma tipični za vse Blender-add-one, ki hočejo komunicirati z zunanjimi API-ji.
Problem 1: Auth-Flow brez browser-callbacka
Standardni OAuth-flow: uporabnik klikne „Login“, odpre se brskalnik, uporabnik na Provider-strani avtorizira, Provider redirecta nazaj na endpoint `localhost:8080/callback`, tvoja app kodo prebere iz URL-ja. Deluje za web-app-e. V Blenderju: ne — Blender ne more zanesljivo zagnati HTTP-serverja v ozadju (oziroma gre, ampak se lomi na Windows-firewall-setupih, macOS-sandboxu in nekaterih Linux-distribucijah z različnimi vrstami napak).
Čista rešitev je OAuth 2.0 Device Flow (RFC 8628). Flow:
- Add-on naredi `POST /oauth/device/code` s Client-ID. Server odgovori z `device_code`, `user_code`, `verification_uri`.
- Add-on uporabniku pokaže: „Odpri `https://zer0onelab.com/device\` v svojem brskalniku in vnesi kodo `ABCD-1234`.“ Uporabnik to naredi (na poljubni napravi — telefon, drug laptop, vseeno).
- Add-on poll-a `POST /oauth/token` z `device_code` vsakih 5 sekund. Server odgovarja z `authorization_pending`, dokler uporabnik ne potrdi, nato z resničnim access-tokenom.
Brez browser-callbacka, brez HTTP-serverja v Blender-procesu. Uporabnik avtorizacijo izvede na napravi po lastni izbiri. Na laptopu z lokalnim brskalnikom istega računalnika, na studio-render-mašinah, ki brskalnika nimajo, prav tako.
Opomba k implementaciji: Blenderjev embedded Python nima `requests`, a `urllib.request` zadošča za vse OAuth-klice. To prihrani dependencies-bundle-vprašanje, ki bi drugače postalo versioning-hell.
Problem 2: Async brez asyncio (ker bpy z asyncio ne igra)
Blender zaganja Python v main threadu. `bpy.ops` in vse scene-modifikacije morajo teči v main threadu — če jih poskusiš klicati iz background-threada, dobiš bodisi crash bodisi undefined behavior.
Vendar 500-MB-upload pri 100 Mbit traja ~45 sekund. Če to počneš v main threadu, je Blender v tem času trdo zamrznjen — Windows kaže „not responding“, macOS okno pobarva sivo, uporabnik proces zapre.
Vzorec, ki smo ga našli:
```python class UploadThread(threading.Thread): def init(self, blend_path): super().init() self.blend_path = blend_path self.progress = 0.0 self.done = False self.result = None
def run(self):
# blocking upload, ampak v background-threadu
with open(self.blend_path, 'rb') as f:
# chunked upload s progress-callbackom
response = upload_with_progress(f, callback=lambda p: setattr(self, 'progress', p))
self.result = response
self.done = True
Timer v main threadu, ki polla upload-status:
def upload_status_poll(thread): if thread.done: # ovrednoti uspeh ali napako, v main threadu (bpy safe) show_result_popup(thread.result) return None # None = Timer se ustavi # progress-bar update (bpy.context.scene.frame_current += 0 forces a redraw) bpy.context.workspace.status_text_set(f"Upload {thread.progress:.0%}") return 0.2 # naslednji call čez 200 ms ```
Trik je `bpy.app.timers.register(upload_status_poll)` — Blender callback pokliče v main threadu vsakih 200 ms. Background-thread opravi dejansko delo, timer status komunicira nazaj. Brez asyncio, brez bpy-race-condition-ov.
Problem 3: Chunked upload in retry
500-MB-.blend-upload se pri prekinjenem WLAN-u po 3 minutah prekine z „connection reset“. Uporabnik mora upload popolnoma na novo začeti. Po tretjem poskusu je add-on odinstaliran.
Fix: chunked upload z resume-tokenom. Upload je razdeljen na 8-MB-bloke. Vsak blok dobi svojo HTTP-PUT-zahtevo. Server si zapomni indeks zadnjega uspešnega bloka. Ob reconnectu add-on vpraša za zadnji sprejeti blok in začne od tam naprej.
Implementirali smo to preko S3-kompatibilnega R2-API-ja Cloudflare-a (naš storage-backend) z `Multipart Upload`. Na strani Blenderja je koda ~120 vrstic vključno z retry-logiko. Na strani serverja ni potrebno nič dodatnega — R2 ima to vgrajeno.
Kaj smo še odnesli
- Blender 4.2+ ima nov Extensions-sistem. Stari Add-on-Zip-format še vedno deluje, a novi add-oni bi morali priložiti Extensions-Manifest-datoteko — potem lahko Blender add-on distribuira preko Blender Extensions Marketplace. To je SEO-kanal za Blender-add-one.
- Version-kompatibilnost je committee. Add-on za Blender 4.2 v 4.3 večinoma še teče, v 5.0 pogosto ne. Imamo `bl_info`-blok, ki eksplicitno lista „4.2, 4.3, 4.4“ — Blender sicer opozarja.
- Uporabniki obožujejo change-log v samem add-onu. Pri vsaki novi verziji pri prvem zagonu po posodobitvi pokažemo kratek „What's new“-popup. Vidno zmanjša support-vprašanja.
Meta-lekcija
Dober Blender-add-on se od slabega razlikuje v točno treh detajlih: auth brez brskalnika (device flow), uploads brez freeze-a (background-thread + timer-callback), napake z recovery-jem (chunked + resume). Vsi trije so standardni distributed-systems-vzorci iz web-developmenta, ampak v Blender-skupnosti redko čisto implementirani. Če svoj add-on tako zgradiš, se vidno dvigneš nad 80 % cloud-integracij v Blender-ekosistemu.
Celoten add-on je open source na GitHubu, MIT-licenciran. Če sam gradiš Blender-add-on in imaš vprašanja o device-flow-u ali chunked-uploadu — [email protected]. Add-on je eden izmed client-layerjev ZER0ONE Lab Cinema Render.