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:
@@ -115,7 +115,7 @@ export default function RenderTemplateTable() {
|
||||
setEditDraft({
|
||||
name: t.name,
|
||||
category_key: t.category_key,
|
||||
output_type_id: t.output_type_id,
|
||||
output_type_ids: t.output_type_ids ?? [],
|
||||
target_collection: t.target_collection,
|
||||
material_replace_enabled: t.material_replace_enabled,
|
||||
lighting_only: t.lighting_only,
|
||||
@@ -320,18 +320,39 @@ export default function RenderTemplateTable() {
|
||||
</td>
|
||||
<td className="px-3 py-2">
|
||||
{isEditing ? (
|
||||
<select
|
||||
className={inputCls}
|
||||
value={editDraft.output_type_id ?? t.output_type_id ?? ''}
|
||||
onChange={(e) => setEditDraft({ ...editDraft, output_type_id: e.target.value || null })}
|
||||
>
|
||||
<option value="">Any</option>
|
||||
{outputTypes?.map((ot: OutputType) => (
|
||||
<option key={ot.id} value={ot.id}>{ot.name}</option>
|
||||
))}
|
||||
</select>
|
||||
<div className="flex flex-col gap-0.5 max-h-32 overflow-y-auto">
|
||||
{outputTypes?.map((ot: OutputType) => {
|
||||
const checked = (editDraft.output_type_ids ?? []).includes(ot.id)
|
||||
return (
|
||||
<label key={ot.id} className="flex items-center gap-1 text-xs cursor-pointer whitespace-nowrap">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checked}
|
||||
onChange={() => {
|
||||
const current = editDraft.output_type_ids ?? []
|
||||
const next = checked
|
||||
? current.filter((id: string) => id !== ot.id)
|
||||
: [...current, ot.id]
|
||||
setEditDraft({ ...editDraft, output_type_ids: next })
|
||||
}}
|
||||
/>
|
||||
{ot.name}
|
||||
</label>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
t.output_type_name || <span className="text-content-muted">Any</span>
|
||||
t.output_type_names && t.output_type_names.length > 0 ? (
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{t.output_type_names.map((name, i) => (
|
||||
<span key={i} className="inline-block text-xs px-1.5 py-0.5 bg-blue-100 text-blue-800 rounded">
|
||||
{name}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-content-muted">Any</span>
|
||||
)
|
||||
)}
|
||||
</td>
|
||||
<td className="px-3 py-2">
|
||||
|
||||
Reference in New Issue
Block a user