Light/ Ran black formatting

This commit is contained in:
Chirag Singh
2026-04-03 01:30:59 +05:30
parent d835577750
commit f91f44cd4a
5 changed files with 147 additions and 71 deletions
+16 -8
View File
@@ -162,12 +162,12 @@ class ExportOBJ(bpy.types.Operator):
# exported by _export_linked_models() via the IFC serializer.
instance_parents = set()
for obj in bpy.data.objects:
if obj.instance_type == 'COLLECTION' and obj.instance_collection is not None:
if obj.instance_type == "COLLECTION" and obj.instance_collection is not None:
if not obj.visible_get():
continue
# Check if this collection contains linked IFC objects
coll = obj.instance_collection
is_linked_ifc = any("guids" in child for child in coll.all_objects if child.type == 'MESH')
is_linked_ifc = any("guids" in child for child in coll.all_objects if child.type == "MESH")
if is_linked_ifc:
print(f"Skipping collection instance '{obj.name}' (linked IFC model, exported via IFC serializer)")
continue
@@ -200,7 +200,7 @@ class ExportOBJ(bpy.types.Operator):
continue
eval_obj = dep_inst.object
if eval_obj.type != 'MESH':
if eval_obj.type != "MESH":
continue
try:
@@ -252,7 +252,7 @@ class ExportOBJ(bpy.types.Operator):
"""
non_ifc_meshes = []
for obj in bpy.data.objects:
if obj.type != 'MESH':
if obj.type != "MESH":
continue
if not obj.visible_get():
continue
@@ -338,7 +338,9 @@ class ExportOBJ(bpy.types.Operator):
mtl_file_path = os.path.join(output_dir, "model.mtl")
visible_elements = self._get_exportable_elements(ifc_file, filter_visibility=True)
mats = self._export_ifc_to_obj(ifc_file, obj_file_path, mtl_file_path, settings, serializer_settings, visible_elements)
mats = self._export_ifc_to_obj(
ifc_file, obj_file_path, mtl_file_path, settings, serializer_settings, visible_elements
)
ifc_materials.extend(mats)
self.report({"INFO"}, f"Exported main model OBJ to: {obj_file_path}")
@@ -451,9 +453,15 @@ class CleanupRadianceFiles(bpy.types.Operator):
return {"CANCELLED"}
cleanup_patterns = (
"model.obj", "model.mtl", "model.rtm",
"sky.rad", "materials.rad", "scene.rad",
"ascene.oct", "mascene.oct", "ascene.amb",
"model.obj",
"model.mtl",
"model.rtm",
"sky.rad",
"materials.rad",
"scene.rad",
"ascene.oct",
"mascene.oct",
"ascene.amb",
)
cleanup_extensions = (".hdr", ".tiff", ".rad", ".dat")
cleanup_prefixes = ("instance_", "linked_", "blender_meshes")
@@ -78,4 +78,3 @@ class RemoveIESLight(bpy.types.Operator):
self.report({"WARNING"}, "Invalid IES light index")
return {"CANCELLED"}
+108 -49
View File
@@ -254,10 +254,15 @@ class PrepareRadianceScene(bpy.types.Operator):
return {"CANCELLED"}
sky_data = {
"year": sun_props.year, "month": sun_props.month, "day": sun_props.day,
"hour": sun_props.hour, "minute": sun_props.minute,
"latitude": sun_props.latitude, "longitude": sun_props.longitude,
"UTC_zone": sun_props.UTC_zone, "sun_year": sun_pos_props.year,
"year": sun_props.year,
"month": sun_props.month,
"day": sun_props.day,
"hour": sun_props.hour,
"minute": sun_props.minute,
"latitude": sun_props.latitude,
"longitude": sun_props.longitude,
"UTC_zone": sun_props.UTC_zone,
"sun_year": sun_pos_props.year,
"sky_condition": props.sky_condition,
"ground_reflectance": props.ground_reflectance,
"turbidity": props.turbidity,
@@ -286,26 +291,30 @@ class PrepareRadianceScene(bpy.types.Operator):
ies_light_data.append(None)
continue
ies_light_data.append({
"ies_file_path": ies_light.ies_file_path,
"lamp_type": ies_light.lamp_type,
"lamp_color": ies_light.lamp_color,
"multiply_factor": ies_light.multiply_factor,
"radius": ies_light.radius,
"rotation_z": ies_light.rotation_z,
"positions": positions,
"is_enabled": ies_light.is_enabled,
})
ies_light_data.append(
{
"ies_file_path": ies_light.ies_file_path,
"lamp_type": ies_light.lamp_type,
"lamp_color": ies_light.lamp_color,
"multiply_factor": ies_light.multiply_factor,
"radius": ies_light.radius,
"rotation_z": ies_light.rotation_z,
"positions": positions,
"is_enabled": ies_light.is_enabled,
}
)
# Collect material mapping data (must be on main thread)
material_mappings = []
for m in props.materials:
material_mappings.append({
"style_id": m.style_id,
"is_mapped": m.is_mapped,
"category": m.category,
"subcategory": m.subcategory,
})
material_mappings.append(
{
"style_id": m.style_id,
"is_mapped": m.is_mapped,
"category": m.category,
"subcategory": m.subcategory,
}
)
linked_exports_snapshot = list(linked_model_exports)
@@ -315,17 +324,30 @@ class PrepareRadianceScene(bpy.types.Operator):
self._error = None
import bonsai.bim.module.light.shared as shared
shared.scene = None
self._thread = threading.Thread(
target=self._prepare_worker,
args=(
output_dir, obj_file_path, sky_file_path,
use_hdr, choose_hdr_image, hdr_image_path, hdr_mask_path, sky_map_cal_path,
sky_data, ies_light_data, material_mappings,
output_dir,
obj_file_path,
sky_file_path,
use_hdr,
choose_hdr_image,
hdr_image_path,
hdr_mask_path,
sky_map_cal_path,
sky_data,
ies_light_data,
material_mappings,
linked_exports_snapshot,
camera_position, camera_direction, camera_up,
camera_type, camera_fov, camera_ortho_scale,
camera_position,
camera_direction,
camera_up,
camera_type,
camera_fov,
camera_ortho_scale,
aspect_ratio,
),
daemon=True,
@@ -337,41 +359,80 @@ class PrepareRadianceScene(bpy.types.Operator):
wm.modal_handler_add(self)
self.report({"INFO"}, "Scene preparation started in background...")
context.window.cursor_set('WAIT')
context.window.cursor_set("WAIT")
return {"RUNNING_MODAL"}
def _prepare_worker(
self, output_dir, obj_file_path, sky_file_path,
use_hdr, choose_hdr_image, hdr_image_path, hdr_mask_path, sky_map_cal_path,
sky_data, ies_light_data, material_mappings,
self,
output_dir,
obj_file_path,
sky_file_path,
use_hdr,
choose_hdr_image,
hdr_image_path,
hdr_mask_path,
sky_map_cal_path,
sky_data,
ies_light_data,
material_mappings,
linked_exports_snapshot,
camera_position, camera_direction, camera_up,
camera_type, camera_fov, camera_ortho_scale,
camera_position,
camera_direction,
camera_up,
camera_type,
camera_fov,
camera_ortho_scale,
aspect_ratio,
):
"""Runs in a background thread — no Blender API calls allowed here."""
try:
self._do_prepare(
output_dir, obj_file_path, sky_file_path,
use_hdr, choose_hdr_image, hdr_image_path, hdr_mask_path, sky_map_cal_path,
sky_data, ies_light_data, material_mappings,
output_dir,
obj_file_path,
sky_file_path,
use_hdr,
choose_hdr_image,
hdr_image_path,
hdr_mask_path,
sky_map_cal_path,
sky_data,
ies_light_data,
material_mappings,
linked_exports_snapshot,
camera_position, camera_direction, camera_up,
camera_type, camera_fov, camera_ortho_scale,
camera_position,
camera_direction,
camera_up,
camera_type,
camera_fov,
camera_ortho_scale,
aspect_ratio,
)
except Exception as e:
self._error = str(e)
import traceback
traceback.print_exc()
def _do_prepare(
self, output_dir, obj_file_path, sky_file_path,
use_hdr, choose_hdr_image, hdr_image_path, hdr_mask_path, sky_map_cal_path,
sky_data, ies_light_data, material_mappings,
self,
output_dir,
obj_file_path,
sky_file_path,
use_hdr,
choose_hdr_image,
hdr_image_path,
hdr_mask_path,
sky_map_cal_path,
sky_data,
ies_light_data,
material_mappings,
linked_exports_snapshot,
camera_position, camera_direction, camera_up,
camera_type, camera_fov, camera_ortho_scale,
camera_position,
camera_direction,
camera_up,
camera_type,
camera_fov,
camera_ortho_scale,
aspect_ratio,
):
"""The actual preparation logic (no Blender API)."""
@@ -379,8 +440,7 @@ class PrepareRadianceScene(bpy.types.Operator):
# --- Generate sky file ---
if sky_data is not None:
dt = datetime(sky_data["year"], sky_data["month"], sky_data["day"],
sky_data["hour"], sky_data["minute"])
dt = datetime(sky_data["year"], sky_data["month"], sky_data["day"], sky_data["hour"], sky_data["minute"])
print(f"Sun position data for Radiance gensky:")
print(f" DateTime: {dt}")
@@ -559,8 +619,7 @@ ground_glow source ground
file.write("\n# Linked Models\n")
for link_idx, (link_rtm_path, link_matrix) in enumerate(linked_rtm_files):
is_identity = all(
abs(link_matrix[i][j] - (1.0 if i == j else 0.0)) < 1e-6
for i in range(4) for j in range(4)
abs(link_matrix[i][j] - (1.0 if i == j else 0.0)) < 1e-6 for i in range(4) for j in range(4)
)
if is_identity:
@@ -647,7 +706,7 @@ ground_glow source ground
print("Scene preparation complete.")
def modal(self, context, event):
if event.type == 'TIMER':
if event.type == "TIMER":
if self._thread is not None and self._thread.is_alive():
return {"RUNNING_MODAL"}
@@ -655,7 +714,7 @@ ground_glow source ground
self._cleanup_timer(context)
props = tool.Blender.get_radiance_exporter_props()
props.is_preparing = False
context.window.cursor_set('DEFAULT')
context.window.cursor_set("DEFAULT")
if self._error:
self.report({"ERROR"}, f"Scene preparation failed: {self._error}")
@@ -666,11 +725,11 @@ ground_glow source ground
print(f"Scene preparation completed in {elapsed:.2f} seconds")
return {"FINISHED"}
elif event.type == 'ESC':
elif event.type == "ESC":
self._cleanup_timer(context)
props = tool.Blender.get_radiance_exporter_props()
props.is_preparing = False
context.window.cursor_set('DEFAULT')
context.window.cursor_set("DEFAULT")
self.report({"WARNING"}, "Scene preparation cannot be cancelled mid-operation")
return {"RUNNING_MODAL"}
+15 -9
View File
@@ -91,7 +91,7 @@ class RadianceRender(bpy.types.Operator):
wm.modal_handler_add(self)
self.report({"INFO"}, "Radiance render started in background...")
context.window.cursor_set('WAIT')
context.window.cursor_set("WAIT")
return {"RUNNING_MODAL"}
def _render_worker(self, render_scene, output_dir, res_x, res_y, quality, detail, variability, ambient_bounces):
@@ -114,14 +114,14 @@ class RadianceRender(bpy.types.Operator):
os.chdir(cwd_saved)
def modal(self, context, event):
if event.type == 'TIMER':
if event.type == "TIMER":
if self._thread is not None and self._thread.is_alive():
return {"RUNNING_MODAL"}
self._cleanup_timer(context)
props = tool.Blender.get_radiance_exporter_props()
props.is_rendering = False
context.window.cursor_set('DEFAULT')
context.window.cursor_set("DEFAULT")
if self._error:
self.report({"ERROR"}, f"Radiance render failed: {self._error}")
@@ -156,11 +156,11 @@ class RadianceRender(bpy.types.Operator):
return {"FINISHED"}
elif event.type == 'ESC':
elif event.type == "ESC":
self._cleanup_timer(context)
props = tool.Blender.get_radiance_exporter_props()
props.is_rendering = False
context.window.cursor_set('DEFAULT')
context.window.cursor_set("DEFAULT")
self.report({"WARNING"}, "Render cancelled by user. Background process may still be running.")
return {"CANCELLED"}
@@ -210,9 +210,11 @@ class FalseColorRadiance(bpy.types.Operator):
# fc (foot-candles) = 16.629..., lux & cd/m2 = 179.0
multiplier = 179.0 if props.false_color_label in ("lux", "cd/m2") else 16.629505759940542
print(f"False color parameters: label={props.false_color_label}, scale={fc_scale}, "
f"steps={props.false_color_steps}, multiplier={multiplier}, "
f"contour={props.false_color_contour_lines}")
print(
f"False color parameters: label={props.false_color_label}, scale={fc_scale}, "
f"steps={props.false_color_steps}, multiplier={multiplier}, "
f"contour={props.false_color_contour_lines}"
)
try:
fc_output_name = props.false_color_output_name
@@ -229,9 +231,12 @@ class FalseColorRadiance(bpy.types.Operator):
return {"CANCELLED"}
else:
import shutil
falsecolor_bin = shutil.which("falsecolor") or shutil.which("falsecolor.exe")
if not falsecolor_bin:
self.report({"ERROR"}, "Set the Radiance Bin path in False Color settings, or add Radiance to system PATH.")
self.report(
{"ERROR"}, "Set the Radiance Bin path in False Color settings, or add Radiance to system PATH."
)
return {"CANCELLED"}
radiance_bin_dir = os.path.dirname(falsecolor_bin)
@@ -299,5 +304,6 @@ class FalseColorRadiance(bpy.types.Operator):
except Exception as e:
self.report({"ERROR"}, f"Failed to generate false color image: {str(e)}")
import traceback
traceback.print_exc()
return {"CANCELLED"}
+8 -4
View File
@@ -30,6 +30,7 @@ from bonsai.bim.module.light.data import SolarData
# Root panel (replaces the old "Radiance Exporter" nested panel)
# ---------------------------------------------------------------------------
class BIM_PT_radiance_exporter(bpy.types.Panel):
bl_label = "Radiance Exporter"
bl_idname = "BIM_PT_radiance_exporter"
@@ -47,6 +48,7 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
# 1. Scene Setup
# ---------------------------------------------------------------------------
class BIM_PT_radiance_scene_setup(bpy.types.Panel):
bl_label = "Scene Setup"
bl_idname = "BIM_PT_radiance_scene_setup"
@@ -80,6 +82,7 @@ class BIM_PT_radiance_scene_setup(bpy.types.Panel):
# 2. Materials
# ---------------------------------------------------------------------------
class BIM_PT_radiance_materials(bpy.types.Panel):
bl_label = "Materials"
bl_idname = "BIM_PT_radiance_materials"
@@ -125,6 +128,7 @@ class BIM_PT_radiance_materials(bpy.types.Panel):
# 3. Lighting (Environment + IES)
# ---------------------------------------------------------------------------
class BIM_PT_radiance_lighting(bpy.types.Panel):
bl_label = "Lighting"
bl_idname = "BIM_PT_radiance_lighting"
@@ -161,10 +165,7 @@ class BIM_PT_radiance_lighting(bpy.types.Panel):
col = row.column(align=True)
col.operator("radiance.add_ies_light", text="", icon="ADD")
if (
len(props.ies_lights) > 0
and 0 <= props.active_ies_light_index < len(props.ies_lights)
):
if len(props.ies_lights) > 0 and 0 <= props.active_ies_light_index < len(props.ies_lights):
active_light = props.ies_lights[props.active_ies_light_index]
col = box.column(align=True)
@@ -198,6 +199,7 @@ class BIM_PT_radiance_lighting(bpy.types.Panel):
# 4. Render Settings
# ---------------------------------------------------------------------------
class BIM_PT_radiance_render_settings(bpy.types.Panel):
bl_label = "Render Settings"
bl_idname = "BIM_PT_radiance_render_settings"
@@ -236,6 +238,7 @@ class BIM_PT_radiance_render_settings(bpy.types.Panel):
# 5. Pipeline (Steps 1-4 + Cleanup)
# ---------------------------------------------------------------------------
class BIM_PT_radiance_pipeline(bpy.types.Panel):
bl_label = "Pipeline"
bl_idname = "BIM_PT_radiance_pipeline"
@@ -318,6 +321,7 @@ class BIM_PT_radiance_pipeline(bpy.types.Panel):
# Solar Panel (unchanged)
# ---------------------------------------------------------------------------
class BIM_PT_solar(bpy.types.Panel):
"""Creates a Panel in the render properties window"""