mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 02:02:22 +00:00
Initial implementation of unit handling for wall polyline tool.
The input panel now works with meters, millimeters and imperial units.
This commit is contained in:
@@ -28,6 +28,7 @@ from bpy_extras import view3d_utils
|
||||
from mathutils import Vector, Matrix
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
from typing import Union
|
||||
from bonsai.bim.module.drawing.helper import format_distance
|
||||
|
||||
|
||||
def transparent_color(color, alpha=0.1):
|
||||
@@ -511,6 +512,15 @@ class PolylineDecorator:
|
||||
|
||||
def draw_input_panel(self, context):
|
||||
texts = {"D": "Distance:", "A": "Angle:", "X": "X coord:", "Y": "Y coord:", "Z": "Z coord:", "AREA": "Area:"}
|
||||
|
||||
unit_system = tool.Drawing.get_unit_system()
|
||||
if unit_system == "IMPERIAL":
|
||||
precision = context.scene.DocProperties.imperial_precision
|
||||
factor = 3.28084
|
||||
else:
|
||||
precision = None
|
||||
factor = 1
|
||||
|
||||
self.addon_prefs = tool.Blender.get_addon_preferences()
|
||||
self.font_id = 0
|
||||
blf.size(self.font_id, 12)
|
||||
@@ -521,6 +531,15 @@ class PolylineDecorator:
|
||||
offset = 20
|
||||
new_line = 20
|
||||
for i, (key, value) in enumerate(self.input_panel.items()):
|
||||
|
||||
if key != "A" and key != self.input_type:
|
||||
value = float(value)
|
||||
if context.scene.unit_settings.length_unit == 'MILLIMETERS':
|
||||
value = value * 1000
|
||||
formatted_value = format_distance(value*factor, precision=precision, suppress_zero_inches=True, in_unit_length=True)
|
||||
else:
|
||||
formatted_value = value
|
||||
|
||||
if key not in list(texts.keys()):
|
||||
continue
|
||||
if key == self.input_type:
|
||||
@@ -528,7 +547,7 @@ class PolylineDecorator:
|
||||
else:
|
||||
blf.color(self.font_id, *color)
|
||||
blf.position(self.font_id, self.mouse_pos[0] + offset, self.mouse_pos[1] - (new_line * i), 0)
|
||||
blf.draw(self.font_id, texts[key] + value)
|
||||
blf.draw(self.font_id, texts[key] + formatted_value)
|
||||
|
||||
def draw_measurements(self, context):
|
||||
region = context.region
|
||||
@@ -550,8 +569,23 @@ class PolylineDecorator:
|
||||
continue
|
||||
pos_dim = (Vector(measurement_prop[i].position) + Vector(measurement_prop[i-1].position)) / 2
|
||||
coords_dim = view3d_utils.location_3d_to_region_2d(region, rv3d, pos_dim)
|
||||
|
||||
unit_system = tool.Drawing.get_unit_system()
|
||||
if unit_system == "IMPERIAL":
|
||||
precision = context.scene.DocProperties.imperial_precision
|
||||
factor = 3.28084
|
||||
else:
|
||||
precision = None
|
||||
factor = 1
|
||||
|
||||
value = measurement_prop[i].dim
|
||||
value = float(value)
|
||||
if context.scene.unit_settings.length_unit == 'MILLIMETERS':
|
||||
value = value * 1000
|
||||
formatted_value = format_distance(value*factor, precision=precision, suppress_zero_inches=True, in_unit_length=True)
|
||||
|
||||
blf.position(self.font_id, coords_dim[0], coords_dim[1], 0)
|
||||
blf.draw(self.font_id, "d: " + measurement_prop[i].dim)
|
||||
blf.draw(self.font_id, "d: " + formatted_value)
|
||||
|
||||
pos_angle = measurement_prop[i-1].position
|
||||
coords_angle = view3d_utils.location_3d_to_region_2d(region, rv3d, pos_angle)
|
||||
|
||||
@@ -294,7 +294,7 @@ class DrawPolylineWall(bpy.types.Operator):
|
||||
self.action_count = 0
|
||||
self.visible_objs = []
|
||||
self.objs_2d_bbox = []
|
||||
self.number_options = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "+", "-", "*", "/"}
|
||||
self.number_options = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", " ", ".", "+", "-", "*", "/", "'", "\"", "="}
|
||||
self.number_input = []
|
||||
self.number_output = ""
|
||||
self.number_is_negative = False
|
||||
@@ -416,6 +416,7 @@ class DrawPolylineWall(bpy.types.Operator):
|
||||
self.is_input_on = True
|
||||
self.input_type = event.type
|
||||
self.number_input = []
|
||||
self.input_panel[self.input_type] = ""
|
||||
PolylineDecorator.set_input_panel(self.input_panel, self.input_type)
|
||||
tool.Blender.update_viewport()
|
||||
|
||||
|
||||
@@ -455,10 +455,21 @@ class Snap(bonsai.core.tool.Snap):
|
||||
|
||||
@classmethod
|
||||
def validate_input(cls, input_number):
|
||||
|
||||
grammar = """
|
||||
start: dim expr?
|
||||
dim: NUMBER
|
||||
expr: (ADD | SUB | MUL | DIV) NUMBER
|
||||
start: FORMULA? dim expr?
|
||||
dim: metric | imperial
|
||||
|
||||
FORMULA: "="
|
||||
|
||||
metric: NUMBER
|
||||
|
||||
imperial: feet? "-"? inches?
|
||||
feet: NUMBER? " "? fraction? "'"
|
||||
inches: NUMBER? " "? fraction? "\\""
|
||||
fraction: NUMBER "/" NUMBER
|
||||
|
||||
expr: (ADD | SUB | MUL | DIV) dim
|
||||
|
||||
NUMBER: /-?\\d+(?:\\.\\d+)?/
|
||||
ADD: "+"
|
||||
@@ -470,8 +481,34 @@ class Snap(bonsai.core.tool.Snap):
|
||||
"""
|
||||
|
||||
class InputTransform(Transformer):
|
||||
def NUMBER(self, n):
|
||||
return float(n)
|
||||
|
||||
def fraction(self, numbers):
|
||||
return numbers[0] / numbers[1]
|
||||
|
||||
def inches(self, args):
|
||||
if len(args) > 1:
|
||||
result = (args[0] + args[1])
|
||||
else:
|
||||
result = args[0]
|
||||
return result / 12
|
||||
|
||||
def feet(self, args):
|
||||
return args[0]
|
||||
|
||||
def imperial(self, args):
|
||||
if len(args) > 1:
|
||||
result = (args[0] + args[1])
|
||||
else:
|
||||
result = args[0]
|
||||
return result * 0.3048
|
||||
|
||||
def metric(self, args):
|
||||
return args[0]
|
||||
|
||||
def dim(self, args):
|
||||
return float(args[0])
|
||||
return args[0]
|
||||
|
||||
def expr(self, args):
|
||||
op = args[0]
|
||||
@@ -485,17 +522,32 @@ class Snap(bonsai.core.tool.Snap):
|
||||
elif op == "/":
|
||||
return lambda x: x / value
|
||||
|
||||
def FORMULA(cls, args):
|
||||
return args[0]
|
||||
|
||||
def start(self, args):
|
||||
dimension = args[0]
|
||||
if len(args) > 1:
|
||||
expression = args[1]
|
||||
i = 0
|
||||
if args[0] == "=":
|
||||
i += 1
|
||||
else:
|
||||
if len(args) > 1:
|
||||
raise ValueError("Invalid input.")
|
||||
dimension = args[i]
|
||||
if len(args) > i+1:
|
||||
expression = args[i + 1]
|
||||
return expression(dimension)
|
||||
else:
|
||||
return dimension
|
||||
|
||||
|
||||
try:
|
||||
parser = Lark(grammar, parser="lalr", transformer=InputTransform())
|
||||
result = parser.parse(input_number)
|
||||
parser = Lark(grammar)
|
||||
parse_tree = parser.parse(input_number)
|
||||
|
||||
transformer = InputTransform()
|
||||
result = transformer.transform(parse_tree)
|
||||
if bpy.context.scene.unit_settings.length_unit == 'MILLIMETERS':
|
||||
result /= 1000
|
||||
return True, str(result)
|
||||
except:
|
||||
return False, "0"
|
||||
|
||||
Reference in New Issue
Block a user