Moved everything to explore tool

This commit is contained in:
falken10
2025-05-16 11:06:10 +02:00
committed by Bruno Perdigão
parent 8b4305360e
commit d3f2711fe4
7 changed files with 290 additions and 292 deletions
@@ -77,7 +77,6 @@ classes = (
operator.UpdateItemAttributes,
operator.UpdateParametricRepresentation,
operator.UpdateRepresentation,
operator.BIM_OT_local_coordinates_gizmo,
operator.CreateInstance,
prop.RepresentationItem,
prop.RepresentationItemObject,
@@ -135,15 +134,6 @@ def register():
bpy.types.Object.BIMGeometryProperties = bpy.props.PointerProperty(type=prop.BIMObjectGeometryProperties)
bpy.types.Scene.BIMGeometryProperties = bpy.props.PointerProperty(type=prop.BIMGeometryProperties)
bpy.types.Scene.show_colored_dimensions = bpy.props.BoolProperty(
name="Show Colored Dimensions",
description="Show XYZ dimensions in color. Local coordinates for single selection. Global coordinates for multiple selection. Toggles gizmo",
default=False,
update=ui.BIM_PT_derived_coordinates.update_show_colored_dimensions,
)
bpy.types.Scene.bonsai_prev_orientation_type = bpy.props.StringProperty(name="Prev Orientation Type")
bpy.types.Scene.bonsai_prev_gizmo_translate = bpy.props.BoolProperty(name="Prev Gizmo Translate")
bpy.types.VIEW3D_MT_object.append(ui.object_menu)
bpy.types.OUTLINER_MT_object.append(ui.outliner_menu)
bpy.types.VIEW3D_MT_object_context_menu.append(ui.object_menu)
@@ -225,6 +215,3 @@ def unregister():
km.keymap_items.remove(kmi)
addon_keymaps.clear()
del bpy.types.Scene.show_colored_dimensions
del bpy.types.Scene._bonsai_prev_orientation_type
del bpy.types.Scene._bonsai_prev_gizmo_translate
@@ -3470,79 +3470,3 @@ class CreateInstance(bpy.types.Operator, tool.Ifc.Operator):
return {"FINISHED"}
previous_selection = set()
def selection_monitor_handler(scene, depsgraph):
global previous_selection
# Get the current selection
current_selection = {obj.name for obj in scene.objects if obj.select_get()}
# If selection changed, print and update
if current_selection != previous_selection:
if len(bpy.context.selected_objects) == 1:
scene.transform_orientation_slots[1].type = "LOCAL"
else:
scene.transform_orientation_slots[1].type = "GLOBAL"
area = next((a for a in bpy.context.screen.areas if a.type == "VIEW_3D"), None)
space = next((s for s in area.spaces if s.type == "VIEW_3D"), None)
space.show_gizmo_object_translate = True
previous_selection = current_selection
def register_handler():
unregister_handler()
bpy.app.handlers.depsgraph_update_post.append(selection_monitor_handler)
def unregister_handler():
handlers = bpy.app.handlers.depsgraph_update_post
handlers[:] = [h for h in handlers if h.__name__ != "selection_monitor_handler"]
class BIM_OT_local_coordinates_gizmo(bpy.types.Operator):
bl_idname = "bim.toggle_local_gizmo"
bl_label = "Show Local Gizmo"
def execute(self, context):
scene = bpy.context.scene
area_3d = next((area for area in bpy.context.screen.areas if area.type == "VIEW_3D"), None)
space_3d = next((space for space in area_3d.spaces if space.type == "VIEW_3D"), None) if area_3d else None
try:
if context.scene.show_colored_dimensions:
register_handler()
bpy.app.handlers.depsgraph_update_post.append(
selection_monitor_handler
) # Save initial state only if not already saved
if not scene.get("bonsai_prev_orientation_type", None):
scene["bonsai_prev_orientation_type"] = scene.transform_orientation_slots[1].type
if not scene.get("bonsai_prev_gizmo_translate", None):
scene["bonsai_prev_gizmo_translate"] = space_3d.show_gizmo_object_translate if space_3d else False
# Set orientation and gizmo based on selection count
if space_3d:
if len(context.selected_objects) == 1:
scene.transform_orientation_slots[1].type = "LOCAL"
else:
scene.transform_orientation_slots[1].type = "GLOBAL"
space_3d.show_gizmo_object_translate = True
else:
unregister_handler()
# Restore previous state
if space_3d:
prev_orientation = scene.get("bonsai_prev_orientation_type", None)
if prev_orientation:
scene.transform_orientation_slots[1].type = prev_orientation
scene["bonsai_prev_orientation_type"] = ""
prev_gizmo = scene.get("bonsai_prev_gizmo_translate", None)
if prev_gizmo is not None:
space_3d.show_gizmo_object_translate = prev_gizmo
scene["bonsai_prev_gizmo_translate"] = None
except Exception:
self.report({"WARNING"}, "Could not set transform orientation.")
return {"FINISHED"}
+1 -202
View File
@@ -19,10 +19,6 @@
import bpy
import bonsai.bim
import bonsai.tool as tool
import gpu
import mathutils
import blf
from gpu_extras.batch import batch_for_shader
from bpy.types import Panel, Menu, UIList
from bonsai.bim.helper import prop_with_search
from bonsai.bim.module.geometry.data import (
@@ -35,196 +31,6 @@ from bonsai.bim.module.geometry.data import (
from bonsai.bim.module.layer.data import LayersData
_draw_handler_box = None
_draw_handler_text = None
def get_combined_bounding_box_corners(objects):
import mathutils
if not objects:
return None, None, None
if len(objects) == 1:
obj = bpy.context.active_object
corners = [obj.matrix_world @ mathutils.Vector(corner) for corner in obj.bound_box]
else:
all_corners = []
for obj in objects:
if hasattr(obj, "bound_box"):
all_corners.extend([obj.matrix_world @ mathutils.Vector(corner) for corner in obj.bound_box])
min_corner = mathutils.Vector(
(min(v.x for v in all_corners), min(v.y for v in all_corners), min(v.z for v in all_corners))
)
max_corner = mathutils.Vector(
(max(v.x for v in all_corners), max(v.y for v in all_corners), max(v.z for v in all_corners))
)
corners = [
mathutils.Vector((min_corner.x, min_corner.y, min_corner.z)),
mathutils.Vector((min_corner.x, min_corner.y, max_corner.z)),
mathutils.Vector((min_corner.x, max_corner.y, max_corner.z)),
mathutils.Vector((min_corner.x, max_corner.y, min_corner.z)),
mathutils.Vector((max_corner.x, min_corner.y, min_corner.z)),
mathutils.Vector((max_corner.x, min_corner.y, max_corner.z)),
mathutils.Vector((max_corner.x, max_corner.y, max_corner.z)),
mathutils.Vector((max_corner.x, max_corner.y, min_corner.z)),
]
edges = [
(0, 1, "Z"),
(1, 2, "Y"),
(2, 3, "Z"),
(3, 0, "Y"),
(4, 5, "Z"),
(5, 6, "Y"),
(6, 7, "Z"),
(7, 4, "Y"),
(0, 4, "X"),
(1, 5, "X"),
(2, 6, "X"),
(3, 7, "X"),
]
axis_colors = {
"X": (0.956, 0.282, 0.322, 1),
"Y": (0.565, 0.812, 0.125, 1),
"Z": (0.196, 0.529, 0.929, 1),
}
return corners, edges, axis_colors
def find_closest_trihedron(corners, edges, region, rv3d):
from bpy_extras.view3d_utils import location_3d_to_region_2d
# Project all corners to 2D and find the one with the lowest Y value
min_y = float("inf")
best_origin = None
for idx, corner in enumerate(corners):
screen_co = location_3d_to_region_2d(region, rv3d, corner)
if screen_co is not None and screen_co.y < min_y:
min_y = screen_co.y
best_origin = idx
trihedron = [
{"X": (0, 4), "Y": (0, 3), "Z": (0, 1)},
{"X": (1, 5), "Y": (1, 2), "Z": (1, 0)},
{"X": (2, 6), "Y": (2, 1), "Z": (2, 3)},
{"X": (3, 7), "Y": (3, 0), "Z": (3, 2)},
{"X": (4, 0), "Y": (4, 7), "Z": (4, 5)},
{"X": (5, 1), "Y": (5, 6), "Z": (5, 4)},
{"X": (6, 2), "Y": (6, 5), "Z": (6, 7)},
{"X": (7, 3), "Y": (7, 4), "Z": (7, 6)},
]
return trihedron[best_origin]
def draw_bounding_box_wire_cube():
selected_objects = [obj for obj in bpy.context.selected_objects if hasattr(obj, "bound_box")]
if not selected_objects:
return
corners, edges, axis_colors = get_combined_bounding_box_corners(selected_objects)
region = bpy.context.region
rv3d = bpy.context.region_data
shader = gpu.shader.from_builtin("UNIFORM_COLOR")
gpu.state.line_width_set(2.0)
# Draw the bounding box edges
for i1, i2, axis in edges:
color = (0.5, 0.5, 0.5, 0.75)
shader.bind()
shader.uniform_float("color", color)
batch = batch_for_shader(shader, "LINES", {"pos": [corners[i1], corners[i2]]})
batch.draw(shader)
# Draw the trihedron edges
closest_indices = find_closest_trihedron(corners, edges, region, rv3d)
for axis in "XYZ":
pair = closest_indices[axis]
if pair is not None:
i1, i2 = pair
color = axis_colors[axis]
shader.bind()
shader.uniform_float("color", color)
batch = batch_for_shader(shader, "LINES", {"pos": [corners[i1], corners[i2]]})
batch.draw(shader)
def draw_dimension_text():
from bpy_extras.view3d_utils import location_3d_to_region_2d
from bonsai.bim.module.drawing.helper import format_distance
selected_objects = [obj for obj in bpy.context.selected_objects if hasattr(obj, "bound_box")]
if not selected_objects:
return
corners, edges, axis_colors = get_combined_bounding_box_corners(selected_objects)
if not corners:
return
dims = mathutils.Vector(
(
(corners[4] - corners[0]).length,
(corners[3] - corners[0]).length,
(corners[1] - corners[0]).length,
)
)
region = bpy.context.region
rv3d = bpy.context.region_data
closest_indices = find_closest_trihedron(corners, edges, region, rv3d)
font_id = 0
blf.size(font_id, 20)
for axis in "XYZ":
pair = closest_indices[axis]
if pair is not None:
i1, i2 = pair
center = (corners[i1] + corners[i2]) / 2
value = getattr(dims, axis.lower())
screen_co = location_3d_to_region_2d(region, rv3d, center)
if screen_co is not None:
# Draw axis label in color
blf.position(font_id, screen_co.x, screen_co.y, 0)
blf.color(font_id, *axis_colors[axis])
blf.draw(font_id, f"{axis}: ")
axis_width, _ = blf.dimensions(font_id, f"{axis}: ")
# Draw value+unit in white
blf.position(font_id, screen_co.x + axis_width, screen_co.y, 0)
blf.color(font_id, 1, 1, 1, 1)
value_str = format_distance(value, hide_units=False)
blf.draw(font_id, value_str)
# To show the corners indexes, uncomment the following lines
# for idx, corner in enumerate(corners):
# screen_co = location_3d_to_region_2d(region, rv3d, corner)
# if screen_co is not None:
# blf.position(font_id, screen_co.x, screen_co.y, 0)
# blf.color(font_id, 1, 1, 0, 1)
# blf.draw(font_id, str(idx))
def enable_bounding_box_wire_cube():
global _draw_handler_box, _draw_handler_text
if _draw_handler_box is None:
_draw_handler_box = bpy.types.SpaceView3D.draw_handler_add(
draw_bounding_box_wire_cube, (), "WINDOW", "POST_VIEW"
)
if _draw_handler_text is None:
_draw_handler_text = bpy.types.SpaceView3D.draw_handler_add(draw_dimension_text, (), "WINDOW", "POST_PIXEL")
def disable_bounding_box_wire_cube():
global _draw_handler_box, _draw_handler_text
if _draw_handler_box is not None:
bpy.types.SpaceView3D.draw_handler_remove(_draw_handler_box, "WINDOW")
_draw_handler_box = None
if _draw_handler_text is not None:
bpy.types.SpaceView3D.draw_handler_remove(_draw_handler_text, "WINDOW")
_draw_handler_text = None
class UIData:
data = {}
is_loaded = False
@@ -709,9 +515,6 @@ class BIM_PT_derived_coordinates(Panel):
def poll(cls, context):
return context.active_object is not None
def update_show_colored_dimensions(self, context):
bpy.ops.bim.toggle_local_gizmo()
def draw(self, context):
if not DerivedCoordinatesData.is_loaded:
DerivedCoordinatesData.load()
@@ -722,23 +525,19 @@ class BIM_PT_derived_coordinates(Panel):
text += "*"
row.operator("bim.edit_object_placement", text=text, icon="EXPORT")
# --- XYZ Dimensions with checkbox ---
row = self.layout.row(align=True)
row.label(text="XYZ Dimensions")
row.prop(context.scene, "show_colored_dimensions", text="Show colored dimensions")
row = self.layout.row(align=True)
row.enabled = False
area_3d = next((area for area in context.screen.areas if area.type == "VIEW_3D"), None)
space_3d = next((space for space in area_3d.spaces if space.type == "VIEW_3D"), None)
if context.scene.show_colored_dimensions:
enable_bounding_box_wire_cube()
if bpy.context.scene.MeasureToolSettings.measurement_type == "XYZ_DIMENSIONS":
for axis, icon, idx in [("X", "STRIP_COLOR_01", 0), ("Y", "STRIP_COLOR_04", 1), ("Z", "STRIP_COLOR_05", 2)]:
row.label(text="", icon=icon)
row.prop(context.active_object, "dimensions", text=axis, index=idx)
else:
disable_bounding_box_wire_cube()
row.prop(context.active_object, "dimensions", text="X", index=0)
row.prop(context.active_object, "dimensions", text="Y", index=1)
row.prop(context.active_object, "dimensions", text="Z", index=2)
@@ -49,6 +49,7 @@ classes = (
operator.LoadProjectElements,
operator.MeasureTool,
operator.MeasureFaceAreaTool,
operator.MeasureXYZDimensionsTool,
operator.ClearMeasurement,
operator.NewProject,
operator.QueryLinkedElement,
@@ -100,6 +101,8 @@ def register():
bpy.types.TOPBAR_MT_file_import.append(ui.file_import_menu)
bpy.types.TOPBAR_MT_file.prepend(ui.file_menu)
bpy.types.TOPBAR_MT_file_context_menu.prepend(ui.file_menu)
bpy.types.Scene.prev_transform_orientation_slot_type = bpy.props.StringProperty(name="Previous Gizmo Orientation Type")
bpy.types.Scene.prev_show_gizmo_object_translate = bpy.props.BoolProperty(name="Previous Gizmo Translate")
wm = bpy.context.window_manager
if wm.keyconfigs.addon:
km = wm.keyconfigs.addon.keymaps.get("Window")
@@ -120,6 +123,8 @@ def unregister():
bpy.utils.unregister_tool(workspace.ExploreTool)
del bpy.types.Scene.BIMProjectProperties
del bpy.types.Scene.MeasureToolSettings
del bpy.types.Scene.prev_transform_orientation_slot_type
del bpy.types.Scene.prev_show_gizmo_object_translate
bpy.app.handlers.load_post.remove(decorator.toggle_decorations_on_load)
bpy.types.TOPBAR_MT_file.remove(ui.file_menu)
bpy.types.TOPBAR_MT_file_context_menu.remove(ui.file_menu)
@@ -25,6 +25,9 @@ import tempfile
import traceback
import subprocess
import datetime
import blf
import mathutils
import gpu
import ifcopenshell.api.attribute
import numpy as np
import ifcopenshell
@@ -64,6 +67,7 @@ from bonsai.bim.module.project.prop import BreadcrumbType
from bonsai.bim.module.model.decorator import PolylineDecorator, FaceAreaDecorator
from bonsai.bim.module.model.polyline import PolylineOperator
from typing import Union, TYPE_CHECKING, get_args, Literal
from gpu_extras.batch import batch_for_shader
if TYPE_CHECKING:
import bpy.stub_internal.rna_enums as rna_enums
@@ -2787,6 +2791,278 @@ class MeasureFaceAreaTool(bpy.types.Operator, PolylineOperator):
FaceAreaDecorator.install(context)
return {"RUNNING_MODAL"}
_draw_handler_box = None
_draw_handler_text = None
def get_combined_bounding_box_corners(objects):
import mathutils
if not objects:
return None, None, None
if len(objects) == 1:
obj = bpy.context.active_object
corners = [obj.matrix_world @ mathutils.Vector(corner) for corner in obj.bound_box]
else:
all_corners = []
for obj in objects:
if hasattr(obj, "bound_box"):
all_corners.extend([obj.matrix_world @ mathutils.Vector(corner) for corner in obj.bound_box])
min_corner = mathutils.Vector(
(min(v.x for v in all_corners), min(v.y for v in all_corners), min(v.z for v in all_corners))
)
max_corner = mathutils.Vector(
(max(v.x for v in all_corners), max(v.y for v in all_corners), max(v.z for v in all_corners))
)
corners = [
mathutils.Vector((min_corner.x, min_corner.y, min_corner.z)),
mathutils.Vector((min_corner.x, min_corner.y, max_corner.z)),
mathutils.Vector((min_corner.x, max_corner.y, max_corner.z)),
mathutils.Vector((min_corner.x, max_corner.y, min_corner.z)),
mathutils.Vector((max_corner.x, min_corner.y, min_corner.z)),
mathutils.Vector((max_corner.x, min_corner.y, max_corner.z)),
mathutils.Vector((max_corner.x, max_corner.y, max_corner.z)),
mathutils.Vector((max_corner.x, max_corner.y, min_corner.z)),
]
edges = [
(0, 1, "Z"),
(1, 2, "Y"),
(2, 3, "Z"),
(3, 0, "Y"),
(4, 5, "Z"),
(5, 6, "Y"),
(6, 7, "Z"),
(7, 4, "Y"),
(0, 4, "X"),
(1, 5, "X"),
(2, 6, "X"),
(3, 7, "X"),
]
axis_colors = {
"X": (0.956, 0.282, 0.322, 1),
"Y": (0.565, 0.812, 0.125, 1),
"Z": (0.196, 0.529, 0.929, 1),
}
return corners, edges, axis_colors
def find_closest_trihedron(corners, edges, region, rv3d):
from bpy_extras.view3d_utils import location_3d_to_region_2d
# Project all corners to 2D and find the one with the lowest Y value
min_y = float("inf")
best_origin = None
for idx, corner in enumerate(corners):
screen_co = location_3d_to_region_2d(region, rv3d, corner)
if screen_co is not None and screen_co.y < min_y:
min_y = screen_co.y
best_origin = idx
trihedron = [
{"X": (0, 4), "Y": (0, 3), "Z": (0, 1)},
{"X": (1, 5), "Y": (1, 2), "Z": (1, 0)},
{"X": (2, 6), "Y": (2, 1), "Z": (2, 3)},
{"X": (3, 7), "Y": (3, 0), "Z": (3, 2)},
{"X": (4, 0), "Y": (4, 7), "Z": (4, 5)},
{"X": (5, 1), "Y": (5, 6), "Z": (5, 4)},
{"X": (6, 2), "Y": (6, 5), "Z": (6, 7)},
{"X": (7, 3), "Y": (7, 4), "Z": (7, 6)},
]
return trihedron[best_origin]
def draw_bounding_box_wire_cube():
selected_objects = [obj for obj in bpy.context.selected_objects if hasattr(obj, "bound_box")]
if not selected_objects:
return
corners, edges, axis_colors = get_combined_bounding_box_corners(selected_objects)
region = bpy.context.region
rv3d = bpy.context.region_data
shader = gpu.shader.from_builtin("UNIFORM_COLOR")
gpu.state.line_width_set(2.0)
# Draw the bounding box edges
for i1, i2, axis in edges:
color = (0.5, 0.5, 0.5, 0.75)
shader.bind()
shader.uniform_float("color", color)
batch = batch_for_shader(shader, "LINES", {"pos": [corners[i1], corners[i2]]})
batch.draw(shader)
# Draw the trihedron edges
closest_indices = find_closest_trihedron(corners, edges, region, rv3d)
for axis in "XYZ":
pair = closest_indices[axis]
if pair is not None:
i1, i2 = pair
color = axis_colors[axis]
shader.bind()
shader.uniform_float("color", color)
batch = batch_for_shader(shader, "LINES", {"pos": [corners[i1], corners[i2]]})
batch.draw(shader)
def draw_dimension_text():
from bpy_extras.view3d_utils import location_3d_to_region_2d
from bonsai.bim.module.drawing.helper import format_distance
selected_objects = [obj for obj in bpy.context.selected_objects if hasattr(obj, "bound_box")]
if not selected_objects:
return
corners, edges, axis_colors = get_combined_bounding_box_corners(selected_objects)
if not corners:
return
dims = mathutils.Vector(
(
(corners[4] - corners[0]).length,
(corners[3] - corners[0]).length,
(corners[1] - corners[0]).length,
)
)
region = bpy.context.region
rv3d = bpy.context.region_data
closest_indices = find_closest_trihedron(corners, edges, region, rv3d)
font_id = 0
blf.size(font_id, 20)
for axis in "XYZ":
pair = closest_indices[axis]
if pair is not None:
i1, i2 = pair
center = (corners[i1] + corners[i2]) / 2
value = getattr(dims, axis.lower())
screen_co = location_3d_to_region_2d(region, rv3d, center)
if screen_co is not None:
# Draw axis label in color
blf.position(font_id, screen_co.x, screen_co.y, 0)
blf.color(font_id, *axis_colors[axis])
blf.draw(font_id, f"{axis}: ")
axis_width, _ = blf.dimensions(font_id, f"{axis}: ")
# Draw value+unit in white
blf.position(font_id, screen_co.x + axis_width, screen_co.y, 0)
blf.color(font_id, 1, 1, 1, 1)
value_str = format_distance(value, hide_units=False)
blf.draw(font_id, value_str)
# To show the corners indexes, uncomment the following lines
# for idx, corner in enumerate(corners):
# screen_co = location_3d_to_region_2d(region, rv3d, corner)
# if screen_co is not None:
# blf.position(font_id, screen_co.x, screen_co.y, 0)
# blf.color(font_id, 1, 1, 0, 1)
# blf.draw(font_id, str(idx))
def enable_bounding_box_wire_cube():
global _draw_handler_box, _draw_handler_text
if _draw_handler_box is None:
_draw_handler_box = bpy.types.SpaceView3D.draw_handler_add(
draw_bounding_box_wire_cube, (), "WINDOW", "POST_VIEW"
)
if _draw_handler_text is None:
_draw_handler_text = bpy.types.SpaceView3D.draw_handler_add(draw_dimension_text, (), "WINDOW", "POST_PIXEL")
def disable_bounding_box_wire_cube():
global _draw_handler_box, _draw_handler_text
if _draw_handler_box is not None:
bpy.types.SpaceView3D.draw_handler_remove(_draw_handler_box, "WINDOW")
_draw_handler_box = None
if _draw_handler_text is not None:
bpy.types.SpaceView3D.draw_handler_remove(_draw_handler_text, "WINDOW")
_draw_handler_text = None
previous_selection = set()
def selection_monitor_handler(scene, depsgraph):
global previous_selection
# Get the current selection
current_selection = {obj.name for obj in scene.objects if obj.select_get()}
# If selection changed, print and update
print("Selection changed:", current_selection)
if current_selection != previous_selection:
if len(bpy.context.selected_objects) == 1:
scene.transform_orientation_slots[1].type = "LOCAL"
else:
scene.transform_orientation_slots[1].type = "GLOBAL"
area = next((a for a in bpy.context.screen.areas if a.type == "VIEW_3D"), None)
space = next((s for s in area.spaces if s.type == "VIEW_3D"), None)
space.show_gizmo_object_translate = True
previous_selection = current_selection
def register_handler():
unregister_handler()
bpy.app.handlers.depsgraph_update_post.append(selection_monitor_handler)
def unregister_handler():
handlers = bpy.app.handlers.depsgraph_update_post
handlers[:] = [h for h in handlers if h.__name__ != "selection_monitor_handler"]
class MeasureXYZDimensionsTool(bpy.types.Operator):
bl_idname = "bim.measure_xyz_dimensions_tool"
bl_label = "Show bonding box dimensions"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
scene = bpy.context.scene
area_3d = next((area for area in bpy.context.screen.areas if area.type == "VIEW_3D"), None)
space_3d = next((space for space in area_3d.spaces if space.type == "VIEW_3D"), None) if area_3d else None
try:
if bpy.context.scene.MeasureToolSettings.measurement_type == "XYZ_DIMENSIONS":
enable_bounding_box_wire_cube()
register_handler()
if not scene.get("prev_transform_orientation_slot_type", None):
scene["prev_transform_orientation_slot_type"] = scene.transform_orientation_slots[1].type
if not scene.get("prev_show_gizmo_object_translate", None):
scene["prev_show_gizmo_object_translate"] = space_3d.show_gizmo_object_translate if space_3d else False
# Set orientation and gizmo based on selection count
if space_3d:
if len(context.selected_objects) == 1:
scene.transform_orientation_slots[1].type = "LOCAL"
else:
scene.transform_orientation_slots[1].type = "GLOBAL"
space_3d.show_gizmo_object_translate = True
else:
disable_bounding_box_wire_cube()
unregister_handler()
# Restore previous state
if space_3d:
prev_orientation = scene.get("prev_transform_orientation_slot_type", None)
if prev_orientation:
scene.transform_orientation_slots[1].type = prev_orientation
scene["prev_transform_orientation_slot_type"] = ""
prev_gizmo = scene.get("prev_show_gizmo_object_translate", None)
if prev_gizmo is not None:
space_3d.show_gizmo_object_translate = prev_gizmo
scene["prev_show_gizmo_object_translate"] = None
except Exception:
self.report({"WARNING"}, "Could not set transform orientation.")
return {"FINISHED"}
class ClearMeasurement(bpy.types.Operator):
bl_idname = "bim.clear_measurement"
+6 -1
View File
@@ -507,15 +507,20 @@ class BIMProjectProperties(PropertyGroup):
yield link
def measurement_type_update(self, context):
print(f"Measurement type changed to: {self.measurement_type}")
bpy.ops.bim.measure_xyz_dimensions_tool()
class MeasureToolSettings(PropertyGroup):
measurement_type_items = [
("SINGLE", "SINGLE", "Single", "FIXED_SIZE", 1),
("POLYLINE", "POLYLINE", "Polyline", "DRIVER_ROTATIONAL_DIFFERENCE", 2),
("POLY_AREA", "POLY_AREA", "Poyline Area", "OUTLINER_DATA_LIGHTPROBE", 3),
("FACE_AREA", "FACE_AREA", "Face Area", "FACESEL", 4),
("XYZ_DIMENSIONS", "XYZ_DIMENSIONS", "XYZ Dimensions", "ORIENTATION_LOCAL", 5),
]
measurement_type: bpy.props.EnumProperty(items=measurement_type_items, default="POLYLINE")
measurement_type: bpy.props.EnumProperty(items=measurement_type_items, default="POLYLINE", update= measurement_type_update)
if TYPE_CHECKING:
measurement_type: Literal["SINGLE", "POLYLINE", "AREA"]
@@ -108,5 +108,7 @@ class ExploreHotkey(bpy.types.Operator):
measure_type = bpy.context.scene.MeasureToolSettings.measurement_type
if measure_type == "FACE_AREA":
bpy.ops.bim.measure_face_area_tool("INVOKE_DEFAULT")
elif measure_type == "XYZ_DIMENSIONS":
pass
else:
bpy.ops.bim.measure_tool("INVOKE_DEFAULT", measure_type=measure_type)