feat: GPU rendering + material matching + perf improvements

- GPU: fix Cycles device activation order — set compute_device_type
  BEFORE engine init, re-set AFTER open_mainfile wipes preferences
- GPU: remove _mark_sharp_and_seams edit-mode loop (redundant with
  Blender 5.0 shade_smooth_by_angle), saves ~200s/render on 175 parts
- Material: fix _AFN suffix mismatch — build AF-stripped mat_map keys
  and add prefix fallback in _apply_material_library (blender_render.py)
- Material: production GLB now uses get_material_library_path() which
  checks active AssetLibrary instead of empty legacy system setting
- Admin: RenderTemplateTable multi-select output types (M2M frontend)
- Admin: MaterialLibraryPanel replaced with link to Asset Libraries
- UX: move Toaster to top-left to avoid dispatch button overlap
- SQLAlchemy: add .unique() to all RenderTemplate M2M collection queries
- Logging: flush=True on all Blender progress prints, stdout reconfigure

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 19:05:03 +01:00
parent 934728da77
commit ee6eb34b4c
34 changed files with 1274 additions and 511 deletions
+29
View File
@@ -348,3 +348,32 @@ async def regenerate_thumbnail(
}
@router.post("/{id}/reset-stuck", status_code=status.HTTP_200_OK)
async def reset_stuck_processing(
id: uuid.UUID,
user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
"""Force-reset a CAD file that is stuck in 'processing' to 'failed'.
Use when a file shows 'processing' indefinitely due to a worker crash.
After resetting, click 'Regen thumbnail' to retry.
"""
if user.role.value not in ("admin", "project_manager"):
raise HTTPException(status_code=403, detail="Insufficient permissions")
cad = await _get_cad_file(id, db)
if cad.processing_status != ProcessingStatus.processing:
raise HTTPException(
status_code=400,
detail=f"CAD file is not stuck — current status: {cad.processing_status.value}",
)
cad.processing_status = ProcessingStatus.failed
cad.error_message = "Manually reset — worker may have crashed. Use 'Regen thumbnail' to retry."
await db.commit()
return {"cad_file_id": str(cad.id), "status": "failed", "message": "Reset to 'failed'. Use 'Regen thumbnail' to retry."}