mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-16 13:46:54 +00:00
Construction Types Browser - Multipreview now runs smoothly (#2463)
* Construction types multipreview now runs smoothly * Minor fix * Minor fix
This commit is contained in:
committed by
GitHub
parent
e4e9db0b3e
commit
e9a063ccbd
@@ -59,6 +59,7 @@ classes = (
|
|||||||
slab.SetArcIndex,
|
slab.SetArcIndex,
|
||||||
prop.ConstrTypeInfo,
|
prop.ConstrTypeInfo,
|
||||||
prop.ConstrClassInfo,
|
prop.ConstrClassInfo,
|
||||||
|
prop.ConstrBrowserState,
|
||||||
prop.BIMModelProperties,
|
prop.BIMModelProperties,
|
||||||
ui.BIM_PT_authoring,
|
ui.BIM_PT_authoring,
|
||||||
ui.DisplayConstrTypesUI,
|
ui.DisplayConstrTypesUI,
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import blenderbim.core.geometry
|
|||||||
from . import wall, slab, profile, mep
|
from . import wall, slab, profile, mep
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from blenderbim.bim.module.model.data import AuthoringData
|
from blenderbim.bim.module.model.data import AuthoringData
|
||||||
|
from blenderbim.bim.module.model.prop import store_cursor_position
|
||||||
from ifcopenshell.api.pset.data import Data as PsetData
|
from ifcopenshell.api.pset.data import Data as PsetData
|
||||||
from mathutils import Vector, Matrix
|
from mathutils import Vector, Matrix
|
||||||
from bpy_extras.object_utils import AddObjectHelper
|
from bpy_extras.object_utils import AddObjectHelper
|
||||||
@@ -218,33 +219,37 @@ class ReinvokeOperator(bpy.types.Operator):
|
|||||||
bl_options = {"REGISTER"}
|
bl_options = {"REGISTER"}
|
||||||
bl_description = "Reinvoke a popup operator"
|
bl_description = "Reinvoke a popup operator"
|
||||||
operator: bpy.props.StringProperty()
|
operator: bpy.props.StringProperty()
|
||||||
mouse_x: bpy.props.IntProperty()
|
|
||||||
mouse_y: bpy.props.IntProperty()
|
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
event_mouse_x, event_mouse_y = event.mouse_x, event.mouse_y
|
browser_state = context.scene.BIMModelProperties.constr_browser_state
|
||||||
window_mouse_x, window_mouse_y = self.mouse_x, self.mouse_y
|
store_cursor_position(context, event, window=False)
|
||||||
if (event_mouse_x, event_mouse_y) == (10, 10):
|
cursor_x, cursor_y = browser_state.cursor_x, browser_state.cursor_y
|
||||||
return {"FINISHED"}
|
window_x, window_y = browser_state.window_x, browser_state.window_y
|
||||||
window = context.window
|
window = context.window
|
||||||
window.cursor_set("WAIT")
|
|
||||||
window.cursor_warp(10, 10)
|
|
||||||
run_operator = self.run_operator
|
|
||||||
operator = self.operator
|
operator = self.operator
|
||||||
|
self.move_cursor_away(context, window)
|
||||||
|
|
||||||
|
def move_cursor_to_window():
|
||||||
|
window.cursor_warp(window_x, window_y)
|
||||||
|
|
||||||
|
def run_operator(operator, *args, **kwargs):
|
||||||
|
reduce(lambda x, arg: getattr(x, arg), operator.split("."), bpy.ops)(*args, **kwargs)
|
||||||
|
|
||||||
def reinvoke():
|
def reinvoke():
|
||||||
window.cursor_warp(event_mouse_x, event_mouse_y)
|
run_operator(operator, "INVOKE_DEFAULT", reinvoked=True)
|
||||||
kwargs = {}
|
window.cursor_warp(cursor_x, cursor_y)
|
||||||
if (window_mouse_x, window_mouse_y) != (0, 0):
|
|
||||||
kwargs.update({"mouse_x": window_mouse_x, "mouse_y": window_mouse_y})
|
|
||||||
run_operator(operator, "INVOKE_DEFAULT", **kwargs)
|
|
||||||
|
|
||||||
bpy.app.timers.register(reinvoke)
|
bpy.app.timers.register(move_cursor_to_window, first_interval=browser_state.update_delay)
|
||||||
|
bpy.app.timers.register(reinvoke, first_interval=3*browser_state.update_delay)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
def move_cursor_away(self, context, window): # closes current popup
|
||||||
|
browser_state = context.scene.BIMModelProperties.constr_browser_state
|
||||||
|
window.cursor_warp(browser_state.far_away_x, browser_state.far_away_y)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run_operator(operator, *args, **kwargs):
|
def run_operator(operator, *args, **kwargs):
|
||||||
reduce(lambda x, arg: getattr(x, arg), operator.split("."), bpy.ops)(*args, **kwargs)
|
reduce(lambda x, arg: getattr(x, arg), operator.split("."), bpy.ops)(*args, **kwargs)
|
||||||
|
|||||||
@@ -41,6 +41,14 @@ def get_relating_type_browser(self, context):
|
|||||||
return AuthoringData.data["relating_types_ids_browser"]
|
return AuthoringData.data["relating_types_ids_browser"]
|
||||||
|
|
||||||
|
|
||||||
|
def store_cursor_position(context, event, cursor=True, window=True):
|
||||||
|
browser_state = context.scene.BIMModelProperties.constr_browser_state
|
||||||
|
if cursor:
|
||||||
|
browser_state.cursor_x, browser_state.cursor_y = event.mouse_x, event.mouse_y
|
||||||
|
if window:
|
||||||
|
browser_state.window_x, browser_state.window_y = event.mouse_x, event.mouse_y
|
||||||
|
|
||||||
|
|
||||||
def update_icon_id(self, context, browser=False):
|
def update_icon_id(self, context, browser=False):
|
||||||
if context == "lost_context" or (context.region is not None and context.region.type != "TOOL_HEADER"):
|
if context == "lost_context" or (context.region is not None and context.region.type != "TOOL_HEADER"):
|
||||||
ifc_class = self.ifc_class_browser if browser else self.ifc_class
|
ifc_class = self.ifc_class_browser if browser else self.ifc_class
|
||||||
@@ -129,6 +137,17 @@ class ConstrClassInfo(PropertyGroup):
|
|||||||
fully_loaded: bpy.props.BoolProperty(default=False)
|
fully_loaded: bpy.props.BoolProperty(default=False)
|
||||||
|
|
||||||
|
|
||||||
|
class ConstrBrowserState(PropertyGroup):
|
||||||
|
cursor_x: bpy.props.IntProperty()
|
||||||
|
cursor_y: bpy.props.IntProperty()
|
||||||
|
window_x: bpy.props.IntProperty()
|
||||||
|
window_y: bpy.props.IntProperty()
|
||||||
|
far_away_x: bpy.props.IntProperty(default=10) # lower left corner to temporarily warp the mouse
|
||||||
|
far_away_y: bpy.props.IntProperty(default=10) # useful to close popup operators
|
||||||
|
updating: bpy.props.BoolProperty()
|
||||||
|
update_delay: bpy.props.FloatProperty(default=3e-2)
|
||||||
|
|
||||||
|
|
||||||
class BIMModelProperties(PropertyGroup):
|
class BIMModelProperties(PropertyGroup):
|
||||||
ifc_class: bpy.props.EnumProperty(items=get_ifc_class, name="Construction Class", update=update_ifc_class)
|
ifc_class: bpy.props.EnumProperty(items=get_ifc_class, name="Construction Class", update=update_ifc_class)
|
||||||
ifc_class_browser: bpy.props.EnumProperty(
|
ifc_class_browser: bpy.props.EnumProperty(
|
||||||
@@ -151,6 +170,7 @@ class BIMModelProperties(PropertyGroup):
|
|||||||
occurrence_name_function: bpy.props.StringProperty(name="Occurrence Name Function")
|
occurrence_name_function: bpy.props.StringProperty(name="Occurrence Name Function")
|
||||||
getter_enum = {"ifc_class": get_ifc_class, "relating_type": get_relating_type}
|
getter_enum = {"ifc_class": get_ifc_class, "relating_type": get_relating_type}
|
||||||
constr_classes: bpy.props.CollectionProperty(type=ConstrClassInfo)
|
constr_classes: bpy.props.CollectionProperty(type=ConstrClassInfo)
|
||||||
|
constr_browser_state: bpy.props.PointerProperty(type=ConstrBrowserState)
|
||||||
extrusion_depth: bpy.props.FloatProperty(default=42.0)
|
extrusion_depth: bpy.props.FloatProperty(default=42.0)
|
||||||
cardinal_point: bpy.props.EnumProperty(
|
cardinal_point: bpy.props.EnumProperty(
|
||||||
items=(
|
items=(
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Panel, Operator, Menu
|
from bpy.types import Panel, Operator, Menu
|
||||||
from blenderbim.bim.module.model.data import AuthoringData
|
from blenderbim.bim.module.model.data import AuthoringData
|
||||||
|
from blenderbim.bim.module.model.prop import store_cursor_position
|
||||||
from blenderbim.bim.helper import prop_with_search, close_operator_panel
|
from blenderbim.bim.helper import prop_with_search, close_operator_panel
|
||||||
|
|
||||||
|
|
||||||
@@ -41,20 +42,34 @@ class DisplayConstrTypesUI(Operator):
|
|||||||
bl_label = "Browse Construction Types"
|
bl_label = "Browse Construction Types"
|
||||||
bl_options = {"REGISTER"}
|
bl_options = {"REGISTER"}
|
||||||
bl_description = "Display all available Construction Types to add new instances"
|
bl_description = "Display all available Construction Types to add new instances"
|
||||||
mouse_x: bpy.props.IntProperty(default=0)
|
reinvoked: bpy.props.BoolProperty(default=False)
|
||||||
mouse_y: bpy.props.IntProperty(default=0)
|
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
if (self.mouse_x, self.mouse_y) == (0, 0):
|
store_cursor_position(context, event, window=not self.reinvoked)
|
||||||
self.mouse_x, self.mouse_y = context.window.x, context.window.y
|
|
||||||
return context.window_manager.invoke_popup(self, width=550)
|
return context.window_manager.invoke_popup(self, width=550)
|
||||||
|
|
||||||
|
def reinvoke(self, context):
|
||||||
|
browser_state = context.scene.BIMModelProperties.constr_browser_state
|
||||||
|
|
||||||
|
def set_updating_transaction():
|
||||||
|
browser_state.updating = True
|
||||||
|
|
||||||
|
def run_operator():
|
||||||
|
bpy.ops.bim.reinvoke_operator(
|
||||||
|
"INVOKE_DEFAULT", operator="bim.display_constr_types_ui"
|
||||||
|
)
|
||||||
|
browser_state.updating = False
|
||||||
|
|
||||||
|
if not browser_state.updating:
|
||||||
|
bpy.app.timers.register(set_updating_transaction)
|
||||||
|
bpy.app.timers.register(run_operator, first_interval=browser_state.update_delay)
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
bpy.context.window.cursor_set("DEFAULT")
|
|
||||||
props = context.scene.BIMModelProperties
|
props = context.scene.BIMModelProperties
|
||||||
|
|
||||||
if AuthoringData.data["ifc_classes"]:
|
if AuthoringData.data["ifc_classes"]:
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
row.label(text="", icon="FILE_VOLUME")
|
row.label(text="", icon="FILE_VOLUME")
|
||||||
@@ -65,6 +80,7 @@ class DisplayConstrTypesUI(Operator):
|
|||||||
flow = self.layout.grid_flow(row_major=True, columns=num_cols, even_columns=True, even_rows=True, align=True)
|
flow = self.layout.grid_flow(row_major=True, columns=num_cols, even_columns=True, even_rows=True, align=True)
|
||||||
relating_types = AuthoringData.relating_types_browser()
|
relating_types = AuthoringData.relating_types_browser()
|
||||||
num_types = len(relating_types)
|
num_types = len(relating_types)
|
||||||
|
|
||||||
for idx, (relating_type_id, name, desc) in enumerate(relating_types):
|
for idx, (relating_type_id, name, desc) in enumerate(relating_types):
|
||||||
outer_col = flow.column()
|
outer_col = flow.column()
|
||||||
box = outer_col.box()
|
box = outer_col.box()
|
||||||
@@ -72,31 +88,32 @@ class DisplayConstrTypesUI(Operator):
|
|||||||
row.label(text=name, icon="FILE_3D")
|
row.label(text=name, icon="FILE_3D")
|
||||||
row.alignment = "CENTER"
|
row.alignment = "CENTER"
|
||||||
row = box.row()
|
row = box.row()
|
||||||
|
|
||||||
if ifc_class in props.constr_classes:
|
if ifc_class in props.constr_classes:
|
||||||
constr_class_info = props.constr_classes[ifc_class]
|
constr_class_info = props.constr_classes[ifc_class]
|
||||||
constr_types_info = constr_class_info.constr_types
|
constr_types_info = constr_class_info.constr_types
|
||||||
|
|
||||||
if relating_type_id in constr_types_info:
|
if relating_type_id in constr_types_info:
|
||||||
icon_id = constr_types_info[relating_type_id].icon_id
|
icon_id = constr_types_info[relating_type_id].icon_id
|
||||||
row.template_icon(icon_value=icon_id, scale=6.0)
|
row.template_icon(icon_value=icon_id, scale=6.0)
|
||||||
else:
|
else:
|
||||||
mouse_x, mouse_y = self.mouse_x, self.mouse_y
|
self.reinvoke(context)
|
||||||
|
return
|
||||||
def run_operator():
|
|
||||||
bpy.ops.bim.reinvoke_operator(
|
|
||||||
"INVOKE_DEFAULT", operator="bim.display_constr_types_ui", mouse_x=mouse_x, mouse_y=mouse_y
|
|
||||||
)
|
|
||||||
bpy.app.timers.register(run_operator)
|
|
||||||
|
|
||||||
row = box.row()
|
row = box.row()
|
||||||
op = row.operator("bim.add_constr_type_instance", icon="ADD")
|
op = row.operator("bim.add_constr_type_instance", icon="ADD")
|
||||||
op.from_invoke = True
|
op.from_invoke = True
|
||||||
op.ifc_class = ifc_class
|
op.ifc_class = ifc_class
|
||||||
|
|
||||||
if relating_type_id.isnumeric():
|
if relating_type_id.isnumeric():
|
||||||
op.relating_type_id = int(relating_type_id)
|
op.relating_type_id = int(relating_type_id)
|
||||||
|
|
||||||
last_row_cols = num_types % num_cols
|
last_row_cols = num_types % num_cols
|
||||||
|
|
||||||
if last_row_cols != 0:
|
if last_row_cols != 0:
|
||||||
for _ in range(num_cols - last_row_cols):
|
for _ in range(num_cols - last_row_cols):
|
||||||
flow.column()
|
flow.column()
|
||||||
|
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
row.alignment = "RIGHT"
|
row.alignment = "RIGHT"
|
||||||
row.operator("bim.help_relating_types", text="", icon="QUESTION")
|
row.operator("bim.help_relating_types", text="", icon="QUESTION")
|
||||||
|
|||||||
Reference in New Issue
Block a user