OverviewFilesCommitsIssuesDocsReleasesPeers

blender-bridge commits / a7640e0

Fix texture timing: re-flush meshes after texture registration
First flush has tex_id=0 because texture registration is async (request → response takes 1+ poll ticks). After texture_registered: is received, invalidate_meshes_with_image() clears geometry hashes for meshes using that image, forcing UPDATE_VERTEX re-flush with the correct tex_id in the material blob. v0.18.1 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
a7640e0e1c5bb8842b87a45ee96da6b585308697
by plankatron <fleeky@gmail.com> · 2026-03-04T20:10:02.000Z

Changed files (4) +36 -2

blender_addon/__init__.py +5 -0
……@@ -263,6 +263,11 @@ def _poll_timer_impl(generation: int):
263263 print(f"BlenderBridge: Registered texture '{img_name}' id={tex_id}")
264264 # Send full image file to Godot (replaces VT tile pipeline)
265265 _send_image_file(img_name, tex_id)
266 # Force re-flush of meshes using this texture so tex_id is written
267 # to the material blob (first flush had tex_id=0 because registration
268 # hadn't completed yet)
269 if _detector is not None:
270 _detector.invalidate_meshes_with_image(img_name)
266271
267272 # Flush accumulated Blender changes to SHM and notify Godot
268273 if _detector is not None:
blender_addon/blender_manifest.toml +1 -1
……@@ -2,7 +2,7 @@ schema_version = "1.0.0"
22id = "blender_godot_bridge"
33name = "Blender-Godot Bridge"
44tagline = "Real-time bidirectional scene sync with Godot"
5version = "0.18.0"
5version = "0.18.1"
66blender_version_min = "4.2.0"
77type = "add-on"
88maintainer = "blender-bridge <noreply@localhost>"
blender_addon/change_detector.py +29 -0
……@@ -195,6 +195,35 @@ class ChangeDetector:
195195 self._had_shading_update = False
196196 return val
197197
198 def invalidate_meshes_with_image(self, image_name: str):
199 """Force re-flush of meshes whose Base Color uses the given image.
200
201 Called after texture registration so the material blob gets the correct
202 tex_id (first flush had tex_id=0 because registration was pending).
203 """
204 if bpy is None:
205 return
206 for obj in bpy.data.objects:
207 if obj.type != "MESH" or obj.active_material is None:
208 continue
209 mat = obj.active_material
210 if not mat.use_nodes or not mat.node_tree:
211 continue
212 for node in mat.node_tree.nodes:
213 if node.type != "BSDF_PRINCIPLED":
214 continue
215 bc = node.inputs.get("Base Color")
216 if bc is None or not bc.is_linked:
217 continue
218 for link in bc.links:
219 if (link.from_node.type == "TEX_IMAGE" and
220 link.from_node.image and
221 link.from_node.image.name == image_name):
222 # Clear geometry hash → forces UPDATE_VERTEX re-flush
223 self._geometry_hashes.pop(obj.name, None)
224 self._pending[obj.name] = UPDATE_VERTEX
225 break
226
198227 def set_resize_callback(self, callback):
199228 """Set a callback for SHM resize notifications: callback(new_size, new_region_size)."""
200229 self._resize_callback = callback
src/blender_bridge.cpp +1 -1
……@@ -264,7 +264,7 @@ Error BlenderBridge::start_server(const String &socket_path) {
264264 _known_instance_ids.clear();
265265 _next_object_id = 1;
266266
267 UtilityFunctions::print("BlenderBridge v0.18.0: Server started (shm=", _shm_name, ", sock=", socket_path, ", regions=2x", (int)_region_size, ")");
267 UtilityFunctions::print("BlenderBridge v0.18.1: Server started (shm=", _shm_name, ", sock=", socket_path, ", regions=2x", (int)_region_size, ")");
268268 return OK;
269269}
270270