OverviewFilesCommitsIssuesDocsReleasesPeers

blender-bridge commits / f03a90a

Trigger full texture bake on connection (v0.13.3)
Blender-side: after scene_exported import, scans all materials for Image Texture nodes connected to Principled BSDF Base Color input. Sends request_texture:name to Godot for each discovered image. Godot-side: handles request_texture:name by registering with VirtualTexture and replying texture_registered:name,id. Blender-side: on receiving texture_registered, immediately bakes the full image and streams tiles via SHM ring buffer. Flow: scene_exported → scan → request_texture → texture_registered → bake_full_image → tile_ready messages → Godot uploads to atlas. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
f03a90a8c369075b35d3921c38679bc74ed8b6a1
by plankatron <fleeky@gmail.com> · 2026-03-03T20:52:10.000Z

Changed files (3) +67 -5

blender_addon/__init__.py +46 -3
……@@ -11,7 +11,7 @@ Usage:
1111
1212import bpy
1313
14ADDON_VERSION = "0.13.2"
14ADDON_VERSION = "0.13.3"
1515
1616# Support hot-reload (F3 > Reload Scripts)
1717if "shm_protocol" in locals():
……@@ -57,6 +57,42 @@ def _make_poll_timer(generation: int):
5757 return _poll_timer
5858
5959
60def _request_texture_registrations():
61 """Scan Blender scene for materials with image textures and request VT registration."""
62 global _conn, _baker
63
64 if _conn is None or _baker is None:
65 return
66
67 import bpy
68
69 requested = set()
70 for obj in bpy.data.objects:
71 if obj.type != "MESH" or obj.active_material is None:
72 continue
73 mat = obj.active_material
74 if not mat.use_nodes or not mat.node_tree:
75 continue
76 for node in mat.node_tree.nodes:
77 if node.type == "BSDF_PRINCIPLED":
78 # Check if Base Color has an image texture connected
79 base_color_input = node.inputs.get("Base Color")
80 if base_color_input is None or not base_color_input.is_linked:
81 continue
82 for link in base_color_input.links:
83 from_node = link.from_node
84 if from_node.type == "TEX_IMAGE" and from_node.image is not None:
85 img_name = from_node.image.name
86 if img_name not in requested and img_name not in _baker._texture_ids:
87 requested.add(img_name)
88 msg = f"request_texture:{img_name}"
89 _conn.send_message(msg.encode())
90 print(f"BlenderBridge: Requesting texture registration for '{img_name}'")
91
92 if requested:
93 print(f"BlenderBridge: Requested {len(requested)} texture(s)")
94
95
6096def _poll_timer_impl(generation: int):
6197 """Called by Blender's timer to poll for updates from Godot."""
6298 global _conn, _shm, _importer, _detector, _baker, _timer_running
……@@ -103,6 +139,8 @@ def _poll_timer_impl(generation: int):
103139 _detector.suppress(set(_importer._id_to_name.values()), 5)
104140 got_incoming = True
105141 print(f"BlenderBridge: Synced scene from Godot")
142 # Scan Blender scene for image textures and request VT registration
143 _request_texture_registrations()
106144 elif text in ("updated", "transform_update"):
107145 # Incremental update from Godot (region 0)
108146 if _importer is not None:
……@@ -116,8 +154,13 @@ def _poll_timer_impl(generation: int):
116154 # Godot registered a texture: texture_registered:name,id
117155 parts = text.split(":", 1)[1].split(",")
118156 if len(parts) == 2 and _baker is not None:
119 _baker.register_texture(parts[0], int(parts[1]))
120 print(f"BlenderBridge: Registered texture '{parts[0]}' id={parts[1]}")
157 img_name = parts[0]
158 tex_id = int(parts[1])
159 _baker.register_texture(img_name, tex_id)
160 print(f"BlenderBridge: Registered texture '{img_name}' id={tex_id}")
161 # Bake immediately so tiles flow on this tick
162 _baker.bake_full_image(img_name)
163 print(f"BlenderBridge: Baked texture '{img_name}'")
121164
122165 # Flush accumulated Blender changes to SHM and notify Godot
123166 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.13.2"
5version = "0.13.3"
66blender_version_min = "4.2.0"
77type = "add-on"
88maintainer = "blender-bridge <noreply@localhost>"
src/blender_bridge.cpp +20 -1
……@@ -163,7 +163,7 @@ Error BlenderBridge::start_server(const String &socket_path) {
163163 _known_instance_ids.clear();
164164 _next_object_id = 1;
165165
166 UtilityFunctions::print("BlenderBridge v0.13.2: Server started (shm=", _shm_name, ", sock=", socket_path, ", regions=2x", (int)_region_size, ")");
166 UtilityFunctions::print("BlenderBridge v0.13.3: Server started (shm=", _shm_name, ", sock=", socket_path, ", regions=2x", (int)_region_size, ")");
167167 return OK;
168168}
169169
……@@ -1086,6 +1086,7 @@ void BlenderBridge::_handle_uds_message(const UdsMessage &msg) {
10861086
10871087 // Messages are simple text-based signaling:
10881088 // "hello" — handshake
1089 // "request_texture:name" — Blender asks Godot to register a texture with VT
10891090 // "texture_dirty:tex_id,tile_x,tile_y,w,h,mip" — texture invalidation
10901091 // "tile_ready:tex_id,tile_x,tile_y,mip,shm_offset,size" — tile data ready in shm
10911092
……@@ -1109,6 +1110,24 @@ void BlenderBridge::_handle_uds_message(const UdsMessage &msg) {
11091110 return;
11101111 }
11111112
1113 if (text.substr(0, 16) == "request_texture:") {
1114 // Blender discovered an image texture and wants Godot to register it with VT
1115 std::string tex_name = text.substr(16);
1116 if (!tex_name.empty() && !_virtual_texture_path.is_empty()) {
1117 Node *vt_node = get_node_or_null(_virtual_texture_path);
1118 VirtualTexture *vt = Object::cast_to<VirtualTexture>(vt_node);
1119 if (vt) {
1120 String gd_name = String::utf8(tex_name.c_str(), (int)tex_name.size());
1121 int vt_id = vt->register_texture(gd_name);
1122 // Reply so Blender's baker knows the ID
1123 String reply = "texture_registered:" + gd_name + "," + String::num_int64(vt_id);
1124 CharString reply_utf8 = reply.utf8();
1125 _uds.send_to(msg.client_id, reply_utf8.get_data(), (uint32_t)reply_utf8.length());
1126 }
1127 }
1128 return;
1129 }
1130
11121131 if (text.substr(0, 14) == "texture_dirty:") {
11131132 // Parse: texture_dirty:tex_id,tile_x,tile_y,w,h,mip
11141133 int tex_id, tx, ty, w, h, mip;