Refactor misc functions into new misc module for better organisation.

This commit is contained in:
Dion Moult
2021-10-18 11:21:49 +11:00
parent 8ed395a29f
commit a9a48bdd1d
13 changed files with 257 additions and 113 deletions
+1 -3
View File
@@ -30,6 +30,7 @@ modules = {
"georeference": None, "georeference": None,
"context": None, "context": None,
"drawing": None, "drawing": None,
"misc": None,
"attribute": None, "attribute": None,
"type": None, "type": None,
"spatial": None, "spatial": None,
@@ -80,9 +81,6 @@ classes = [
operator.ReloadIfcFile, operator.ReloadIfcFile,
operator.AddIfcFile, operator.AddIfcFile,
operator.RemoveIfcFile, operator.RemoveIfcFile,
operator.SetOverrideColour,
operator.SetViewportShadowFromSun,
operator.SnapSpacesTogether,
prop.StrProperty, prop.StrProperty,
prop.Attribute, prop.Attribute,
prop.BIMProperties, prop.BIMProperties,
@@ -0,0 +1,36 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
from . import ui, prop, operator
classes = (
operator.SetOverrideColour,
operator.SetViewportShadowFromSun,
operator.SnapSpacesTogether,
prop.BIMMiscProperties,
ui.BIM_PT_misc_utilities,
)
def register():
bpy.types.Scene.BIMMiscProperties = bpy.props.PointerProperty(type=prop.BIMMiscProperties)
def unregister():
del bpy.types.Scene.BIMMiscProperties
@@ -0,0 +1,111 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
import blenderbim.bim.handler
from blenderbim.bim.ifc import IfcStore
from mathutils import Vector, Matrix, Euler
class Operator:
def execute(self, context):
IfcStore.execute_ifc_operator(self, context)
blenderbim.bim.handler.refresh_ui_data()
return {"FINISHED"}
class SetOverrideColour(bpy.types.Operator):
bl_idname = "bim.set_override_colour"
bl_label = "Set Override Colour"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return context.selected_objects
def execute(self, context):
for obj in context.selected_objects:
obj.color = context.scene.BIMMiscProperties.override_colour
area = next(area for area in context.screen.areas if area.type == "VIEW_3D")
area.spaces[0].shading.color_type = "OBJECT"
return {"FINISHED"}
class SetViewportShadowFromSun(bpy.types.Operator):
bl_idname = "bim.set_viewport_shadow_from_sun"
bl_label = "Set Viewport Shadow from Sun"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return context.active_object
def execute(self, context):
# Does this belong in the drawing module? Perhaps.
# The vector used for the light direction is a bit funny
mat = Matrix(((-1.0, 0.0, 0.0, 0.0), (0.0, 0, 1.0, 0.0), (-0.0, -1.0, 0, 0.0), (0.0, 0.0, 0.0, 1.0)))
context.scene.display.light_direction = mat.inverted() @ (
context.active_object.matrix_world.to_quaternion() @ Vector((0, 0, -1))
)
return {"FINISHED"}
class SnapSpacesTogether(bpy.types.Operator):
bl_idname = "bim.snap_spaces_together"
bl_label = "Snap Spaces Together"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return context.selected_objects
def execute(self, context):
threshold = 0.5
processed_polygons = set()
selected_mesh_objects = [o for o in context.selected_objects if o.type == "MESH"]
for obj in selected_mesh_objects:
for polygon in obj.data.polygons:
center = obj.matrix_world @ polygon.center
distance = None
for obj2 in selected_mesh_objects:
if obj2 == obj:
continue
result = obj2.ray_cast(obj2.matrix_world.inverted() @ center, polygon.normal, distance=threshold)
if not result[0]:
continue
hit = obj2.matrix_world @ result[1]
distance = (hit - center).length / 2
if distance < 0.01:
distance = None
break
if (obj2.name, result[3]) in processed_polygons:
distance *= 2
continue
offset = polygon.normal * distance * -1
processed_polygons.add((obj2.name, result[3]))
for v in obj2.data.polygons[result[3]].vertices:
obj2.data.vertices[v].co += offset
break
if distance:
offset = polygon.normal * distance
processed_polygons.add((obj.name, polygon.index))
for v in polygon.vertices:
obj.data.vertices[v].co += offset
return {"FINISHED"}
@@ -0,0 +1,37 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
from blenderbim.bim.prop import StrProperty, Attribute
from bpy.types import PropertyGroup
from bpy.props import (
PointerProperty,
StringProperty,
EnumProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
CollectionProperty,
)
class BIMMiscProperties(PropertyGroup):
override_colour: FloatVectorProperty(
name="Override Colour", subtype="COLOR", default=(1, 0, 0, 1), min=0.0, max=1.0, size=4
)
@@ -0,0 +1,40 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
class BIM_PT_misc_utilities(bpy.types.Panel):
bl_idname = "BIM_PT_misc_utilities"
bl_label = "Miscellaneous"
bl_options = {"DEFAULT_CLOSED"}
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "BlenderBIM"
def draw(self, context):
layout = self.layout
props = context.scene.BIMMiscProperties
row = layout.split(factor=0.2, align=True)
row.prop(props, "override_colour", text="")
row.operator("bim.set_override_colour")
row = layout.row(align=True)
row.operator("bim.set_viewport_shadow_from_sun")
row = layout.row(align=True)
row.operator("bim.snap_spaces_together")
@@ -34,7 +34,6 @@ classes = (
prop.BIMModelProperties, prop.BIMModelProperties,
ui.BIM_PT_authoring, ui.BIM_PT_authoring,
ui.BIM_PT_authoring_architectural, ui.BIM_PT_authoring_architectural,
ui.BIM_PT_misc_utilities,
grid.BIM_OT_add_object, grid.BIM_OT_add_object,
stair.BIM_OT_add_object, stair.BIM_OT_add_object,
door.BIM_OT_add_object, door.BIM_OT_add_object,
@@ -74,24 +74,3 @@ class BIM_PT_authoring_architectural(Panel):
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.operator("bim.flip_wall", icon="ORIENTATION_NORMAL", text="Flip") row.operator("bim.flip_wall", icon="ORIENTATION_NORMAL", text="Flip")
row.operator("bim.split_wall", icon="MOD_PHYSICS", text="Split") row.operator("bim.split_wall", icon="MOD_PHYSICS", text="Split")
class BIM_PT_misc_utilities(Panel):
bl_idname = "BIM_PT_misc_utilities"
bl_label = "Miscellaneous"
bl_options = {"DEFAULT_CLOSED"}
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "BlenderBIM"
def draw(self, context):
layout = self.layout
props = context.scene.BIMProperties
row = layout.split(factor=0.2, align=True)
row.prop(props, "override_colour", text="")
row.operator("bim.set_override_colour")
row = layout.row(align=True)
row.operator("bim.set_viewport_shadow_from_sun")
row = layout.row(align=True)
row.operator("bim.snap_spaces_together")
@@ -20,7 +20,6 @@ import bpy
import ifcopenshell.api import ifcopenshell.api
import blenderbim.tool as tool import blenderbim.tool as tool
import blenderbim.core.owner as core import blenderbim.core.owner as core
import blenderbim.bim.module.owner.data
import blenderbim.bim.handler import blenderbim.bim.handler
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
-84
View File
@@ -18,10 +18,7 @@
import os import os
import bpy import bpy
import time
import json import json
import tempfile
import logging
import webbrowser import webbrowser
import ifcopenshell import ifcopenshell
import blenderbim.bim.handler import blenderbim.bim.handler
@@ -361,87 +358,6 @@ class RemoveIfcFile(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class SetOverrideColour(bpy.types.Operator):
bl_idname = "bim.set_override_colour"
bl_label = "Set Override Colour"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return context.selected_objects
def execute(self, context):
for obj in context.selected_objects:
obj.color = context.scene.BIMProperties.override_colour
area = next(area for area in context.screen.areas if area.type == "VIEW_3D")
area.spaces[0].shading.color_type = "OBJECT"
return {"FINISHED"}
class SetViewportShadowFromSun(bpy.types.Operator):
bl_idname = "bim.set_viewport_shadow_from_sun"
bl_label = "Set Viewport Shadow from Sun"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return context.active_object
def execute(self, context):
# The vector used for the light direction is a bit funny
mat = Matrix(((-1.0, 0.0, 0.0, 0.0), (0.0, 0, 1.0, 0.0), (-0.0, -1.0, 0, 0.0), (0.0, 0.0, 0.0, 1.0)))
context.scene.display.light_direction = mat.inverted() @ (
context.active_object.matrix_world.to_quaternion() @ Vector((0, 0, -1))
)
return {"FINISHED"}
class SnapSpacesTogether(bpy.types.Operator):
bl_idname = "bim.snap_spaces_together"
bl_label = "Snap Spaces Together"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return context.selected_objects
def execute(self, context):
threshold = 0.5
processed_polygons = set()
selected_mesh_objects = [o for o in context.selected_objects if o.type == "MESH"]
for obj in selected_mesh_objects:
for polygon in obj.data.polygons:
center = obj.matrix_world @ polygon.center
distance = None
for obj2 in selected_mesh_objects:
if obj2 == obj:
continue
result = obj2.ray_cast(obj2.matrix_world.inverted() @ center, polygon.normal, distance=threshold)
if not result[0]:
continue
hit = obj2.matrix_world @ result[1]
distance = (hit - center).length / 2
if distance < 0.01:
distance = None
break
if (obj2.name, result[3]) in processed_polygons:
distance *= 2
continue
offset = polygon.normal * distance * -1
processed_polygons.add((obj2.name, result[3]))
for v in obj2.data.polygons[result[3]].vertices:
obj2.data.vertices[v].co += offset
break
if distance:
offset = polygon.normal * distance
processed_polygons.add((obj.name, polygon.index))
for v in polygon.vertices:
obj.data.vertices[v].co += offset
return {"FINISHED"}
class SelectExternalMaterialDir(bpy.types.Operator): class SelectExternalMaterialDir(bpy.types.Operator):
bl_idname = "bim.select_external_material_dir" bl_idname = "bim.select_external_material_dir"
bl_label = "Select Material File" bl_label = "Select Material File"
-3
View File
@@ -234,9 +234,6 @@ class BIMProperties(PropertyGroup):
], ],
name="Drawing Imperial Precision", name="Drawing Imperial Precision",
) )
override_colour: FloatVectorProperty(
name="Override Colour", subtype="COLOR", default=(1, 0, 0, 1), min=0.0, max=1.0, size=4
)
class IfcParameter(PropertyGroup): class IfcParameter(PropertyGroup):
+1
View File
@@ -4,6 +4,7 @@ markers =
context context
geometry geometry
material material
misc
owner owner
project project
pset_template pset_template
@@ -0,0 +1,25 @@
@misc
Feature: Misc
Scenario: Set override colour
Given an empty IFC project
And I add a cube
And the object "Cube" is selected
When I press "bim.set_override_colour"
Then nothing happens
Scenario: Set viewport shadow from sun
Given an empty IFC project
And I add a sun
And the object "Sun" is selected
When I press "bim.set_viewport_shadow_from_sun"
Then nothing happens
Scenario: Snap spaces together
Given an empty IFC project
And I add a cube
And I add a cube
And the object "Cube" is selected
And additionally the object "Cube.001" is selected
When I press "bim.snap_spaces_together"
Then nothing happens
+6
View File
@@ -78,6 +78,12 @@ def i_add_an_empty():
bpy.ops.object.empty_add() bpy.ops.object.empty_add()
@given("I add a sun")
@when("I add an sun")
def i_add_an_empty():
bpy.ops.object.light_add(type="SUN")
@given("I add a material") @given("I add a material")
def i_add_a_material(): def i_add_a_material():
bpy.context.active_object.active_material = bpy.data.materials.new("Material") bpy.context.active_object.active_material = bpy.data.materials.new("Material")