Skip to content

blendertk v0.5.45

Latest

Choose a tag to compare

@m3trik m3trik released this 01 Aug 23:09
  • 2026-08-01 — Exporter blind spots: duplicate-material merges are now VERIFIED, NLA/data-level animation reaches the bake range, and the selection funnel can no longer silently drop (or be killed by) unshippable objects. Three fixes, mirrors of mayatk's new two-phase duplicate design where one exists. (1) MatUtils.find_materials_with_duplicate_textures(materials, strict=False, verify=True) is now two-phase (mirror of mtk's): phase 1 fingerprints on (surface shader idname, {(surface socket, texture id)}) — TEX_IMAGE nodes are collected through nested node groups (previously invisible) and attributed to the surface-shader input they feed, so one shared detail/normal map no longer merges two different materials (confirmed false positive: reassign_duplicate_materials(delete=True), the default-on exporter task, DELETED one of them); phase 2 (verify=True, default) pairwise-verifies each candidate against its group's keeper — same shader type, equal unlinked shader inputs (1e-5), and per-slot identical color space, ShaderNodeMapping placement, and image CONTENT (size + partial hash via the new _texture_content_id, library-aware paths). reassign_duplicate_materials(..., verify=True) re-proves each group right before its destructive merge. (2) AnimUtils.get_animated_extent / has_nla_or_data_animation: _actions reads only o.animation_data.action, so NLA-strip-only or shape-key/data-level animation was invisible while the FBX write bakes the evaluated scene — set_bake_animation_range now covers active-action fcurves ∪ non-muted NLA strip extents (scene time) ∪ data/shape-key fcurve ranges, and check_untied_keyframes / check_floating_point_keys / check_framerate WARN once per run ("NLA/data-level animation present — only validates active object actions") instead of staying vacuously green (edit tasks deliberately NOT extended to strips: strip actions may be shared/library-linked with their own frame mapping). (3) Export funnel content loss: FbxUtils.export selected with unguarded select_set — hidden objects silently vanished from the FBX and a view-layer-excluded member RAISED and killed the export; unselectable members are now collected + WARNED (count + names; new strict=True raises instead), the selection restore tolerates a no-longer-selectable prior member, SceneExporter pre-filters the export set with an INFO log (the funnel warning is the backstop; check_hidden_geometry remains the failing gate), and export_data_node links a collection-hidden/excluded data_export carrier to the scene root for the write (deferred unlink after) so its metadata ships regardless. test_mat_anim_utils.py +12 checks (socket identity, tiling/content/colorspace/settings near-misses each NOT duplicates, node-group texture seen, true duplicates merged, reassign's own verify gate) → 160/160; test_smart_bake.py +11 (NLA-only strip extent reaches the scene range, muted strips skipped, shape-key extent, once-per-run check advisory) → 138/138; test_scene_exporter.py +10 (funnel drop warning + strict raise, excluded member no longer fatal, pre-filter INFO + FBX content, excluded-collection carrier ships + root link removed) → 58/58.

  • 2026-08-01 — Texture checks become storage-aware (library / packed / UDIM), and the glb-only sidecar no longer rolls forward on a failed conversion. Three fixes from the exporter tasks/checks audit. (1) _MatUtilsInternal._abspath is now library-aware: an image linked from a library .blend stores its // path relative to the LIBRARY file, so resolving without library=img.library pointed every linked texture at the wrong directory — false "missing" in check_valid_paths/get_image_records, wrong duplicate fingerprints and size probes for every _abspath consumer. (2) Packed + UDIM images in the three texture checks (mirrors mayatk's <UDIM>-collapse semantics): PACKED images are skipped by check_valid_paths, check_absolute_paths, and check_texture_file_size — the FBX embeds them from memory, so their (often stale, absolute) bookkeeping path never ships; TILED (UDIM) images — previously invisible to check_valid_paths (get_image_records is FILE-only, so a deleted tile set passed) — are validated by probing the first declared tile on disk (tiles[0].number, 1001 fallback), and size-gated at their largest existing tile via the new _MatUtilsInternal._udim_first_tile_path / _udim_tile_paths (previously os.path.getsize on the raw token path raised OSError into a silent continue, letting multi-GB tile sets through unmeasured). (3) _write_export writes the scene-data sidecar only after the deliverable is confirmed: in glb-only mode it was written before the FBX→GLB conversion, so a failed conversion produced no deliverable but still rolled the hierarchy-diff baseline forward (same ordering bug as mayatk's). test_scene_exporter.py +10 checks (packed passes both path checks, tile-less UDIM fails / first-tile UDIM passes validity, largest-tile size gate, failed-glb-leaves-no-sidecar + success-writes-it) → 48/48; test_texture_path_editor.py +3 (a linked image resolves against its library and reports as existing) → 16/16.

  • 2026-08-01 — Naming.rename collapses separator residue after strip/replace formatting (mayatk parity). Stripping a token from 'a__tok__tokB' left 'a____B'; now collapsed to 'a_B' via the new ptk.collapse_delimiter_runs — an explicit __ typed in the pattern is honored. Mirror of the mayatk fix root-caused from the VDATS mangled-shape-name incident (mayatk CHANGELOG 2026-08-01 has the full story; the uninstance scratch-token source is Maya-only, so only the rename half applies here).

  • 2026-08-01 — Scene Exporter: the smart_bake session is now actually RESTORED after export (first fix from the tasks/checks audit). The task stored result.session_id but nothing in production ever consumed it, so every export with Smart Bake on (default) permanently muted the user's constraints/drivers and left the baked Action in place — despite the task docstring's and tooltip's "restorable" contract. perform_export's outer finally now mirrors mayatk's: SmartBake.restore(session_id) on every exit path (successful write, failed check, raising task), restore-failure surfaced at WARNING with the session id (the session stays in the manifest for a manual retry), and exceptions never mask the export result. Also: a check-blocked export now warns that task edits (material cleanup, key snapping/tying, path rewrites) remain in the scene — checks run after tasks and there is no automatic rollback; and check_hidden_geometry's message + tooltip now state the actual Blender hazard: the selection-based funnel (use_selection=True) silently DROPS hidden meshes from the FBX — the old Maya-inherited message claimed they "will be exported", the exact inverse. test_smart_bake.py +10 exporter-level checks (_run_exporter_bake_restore_checks: success path and blocked-export path, both asserting the constraint unmutes and no session is left) → 127/127.

  • 2026-08-01 — BlenderUiHandler + BlenderNativeMenus join the package namespace (mayatk parity). mayatk exposes mtk.MayaUiHandler / mtk.MayaNativeMenus; blendertk exposed neither, so tcl_blender composed its handler set with mtk.MayaUiHandler's twin spelled as a deep module path — the two DCC hosts reading differently for no reason, in a package whose whole contract is mirroring mayatk's names. Now btk.BlenderUiHandler / btk.BlenderNativeMenus, class-only like their Maya counterparts.

  • 2026-08-01 — Scene Exporter now refreshes every metadata producer at export: FbxUtils.run_export_preparers + _KNOWN_PRODUCERS (mayatk parity), so a mesh deleted after the last bake can no longer ship a stale data_export manifest. From the DCC→Unity data_nodes architecture review. Blender has no before-FBX-export event, so authoring-time publishes were the only refresh — export_data_node claimed "the carrier is already current at export", which scene edits since the last bake/commit quietly falsified. The task now runs the new producer registry (shadow / emissive_groups / lightmap — LightmapBaker.refresh_export_metadata added as the public no-arg entry point, mirroring the other producers) via _refresh_scene_data_node before folding the carrier in; producers are isolated and clear-on-empty, and non-Scene-Exporter export paths still ship the authoring-time state (documented as the remaining divergence from mayatk's session hook). Also: DataNodes._set_string honors its documented return contract (None when an empty value had nothing to clear — it returned the carrier name), and docs/data_nodes.md's channel table gains the shadow_metadata / emissive_groups rows it was missing (plus de-staled Shots wording). test_scene_exporter.py's carrier round-trip now authors a real lightmap marker and publishes through the producer instead of hand-stamping producer-owned state (which the refresh correctly regenerates away — that's the feature). Suites: emissive_groups 60/60, lightmap_baker 38/38, node_utils 58/58, shadow_rig 63/63, smart_bake 117/117, scene_exporter 38/38.