mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 18:16:40 +00:00
Light/ Ran black formatting
This commit is contained in:
@@ -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"}
|
||||
|
||||
|
||||
@@ -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"}
|
||||
|
||||
|
||||
@@ -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"}
|
||||
|
||||
@@ -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"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user