Construction Types Browser - Multipreview now runs smoothly (#2463)

* Construction types multipreview now runs smoothly

* Minor fix

* Minor fix
This commit is contained in:
Carlos Villagrasa
2022-10-02 07:46:14 +02:00
committed by GitHub
parent e4e9db0b3e
commit e9a063ccbd
4 changed files with 70 additions and 27 deletions
@@ -59,6 +59,7 @@ classes = (
slab.SetArcIndex,
prop.ConstrTypeInfo,
prop.ConstrClassInfo,
prop.ConstrBrowserState,
prop.BIMModelProperties,
ui.BIM_PT_authoring,
ui.DisplayConstrTypesUI,
@@ -31,6 +31,7 @@ import blenderbim.core.geometry
from . import wall, slab, profile, mep
from blenderbim.bim.ifc import IfcStore
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 mathutils import Vector, Matrix
from bpy_extras.object_utils import AddObjectHelper
@@ -218,33 +219,37 @@ class ReinvokeOperator(bpy.types.Operator):
bl_options = {"REGISTER"}
bl_description = "Reinvoke a popup operator"
operator: bpy.props.StringProperty()
mouse_x: bpy.props.IntProperty()
mouse_y: bpy.props.IntProperty()
def execute(self, context):
return {"FINISHED"}
def invoke(self, context, event):
event_mouse_x, event_mouse_y = event.mouse_x, event.mouse_y
window_mouse_x, window_mouse_y = self.mouse_x, self.mouse_y
if (event_mouse_x, event_mouse_y) == (10, 10):
return {"FINISHED"}
browser_state = context.scene.BIMModelProperties.constr_browser_state
store_cursor_position(context, event, window=False)
cursor_x, cursor_y = browser_state.cursor_x, browser_state.cursor_y
window_x, window_y = browser_state.window_x, browser_state.window_y
window = context.window
window.cursor_set("WAIT")
window.cursor_warp(10, 10)
run_operator = self.run_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():
window.cursor_warp(event_mouse_x, event_mouse_y)
kwargs = {}
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)
run_operator(operator, "INVOKE_DEFAULT", reinvoked=True)
window.cursor_warp(cursor_x, cursor_y)
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"}
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
def run_operator(operator, *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"]
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):
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
@@ -129,6 +137,17 @@ class ConstrClassInfo(PropertyGroup):
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):
ifc_class: bpy.props.EnumProperty(items=get_ifc_class, name="Construction Class", update=update_ifc_class)
ifc_class_browser: bpy.props.EnumProperty(
@@ -151,6 +170,7 @@ class BIMModelProperties(PropertyGroup):
occurrence_name_function: bpy.props.StringProperty(name="Occurrence Name Function")
getter_enum = {"ifc_class": get_ifc_class, "relating_type": get_relating_type}
constr_classes: bpy.props.CollectionProperty(type=ConstrClassInfo)
constr_browser_state: bpy.props.PointerProperty(type=ConstrBrowserState)
extrusion_depth: bpy.props.FloatProperty(default=42.0)
cardinal_point: bpy.props.EnumProperty(
items=(
@@ -19,6 +19,7 @@
import bpy
from bpy.types import Panel, Operator, Menu
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
@@ -41,20 +42,34 @@ class DisplayConstrTypesUI(Operator):
bl_label = "Browse Construction Types"
bl_options = {"REGISTER"}
bl_description = "Display all available Construction Types to add new instances"
mouse_x: bpy.props.IntProperty(default=0)
mouse_y: bpy.props.IntProperty(default=0)
reinvoked: bpy.props.BoolProperty(default=False)
def execute(self, context):
return {"FINISHED"}
def invoke(self, context, event):
if (self.mouse_x, self.mouse_y) == (0, 0):
self.mouse_x, self.mouse_y = context.window.x, context.window.y
store_cursor_position(context, event, window=not self.reinvoked)
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):
bpy.context.window.cursor_set("DEFAULT")
props = context.scene.BIMModelProperties
if AuthoringData.data["ifc_classes"]:
row = self.layout.row()
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)
relating_types = AuthoringData.relating_types_browser()
num_types = len(relating_types)
for idx, (relating_type_id, name, desc) in enumerate(relating_types):
outer_col = flow.column()
box = outer_col.box()
@@ -72,31 +88,32 @@ class DisplayConstrTypesUI(Operator):
row.label(text=name, icon="FILE_3D")
row.alignment = "CENTER"
row = box.row()
if ifc_class in props.constr_classes:
constr_class_info = props.constr_classes[ifc_class]
constr_types_info = constr_class_info.constr_types
if relating_type_id in constr_types_info:
icon_id = constr_types_info[relating_type_id].icon_id
row.template_icon(icon_value=icon_id, scale=6.0)
else:
mouse_x, mouse_y = self.mouse_x, self.mouse_y
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)
self.reinvoke(context)
return
row = box.row()
op = row.operator("bim.add_constr_type_instance", icon="ADD")
op.from_invoke = True
op.ifc_class = ifc_class
if relating_type_id.isnumeric():
op.relating_type_id = int(relating_type_id)
last_row_cols = num_types % num_cols
if last_row_cols != 0:
for _ in range(num_cols - last_row_cols):
flow.column()
row = self.layout.row()
row.alignment = "RIGHT"
row.operator("bim.help_relating_types", text="", icon="QUESTION")