From f72c128ba6407924c7134213dd6ac1fdd66c7e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Perdig=C3=A3o?= Date: Fri, 23 Aug 2024 23:10:58 -0300 Subject: [PATCH] Improved validation for inputs in polyline wall and measure tool. --- src/bonsai/bonsai/bim/module/model/wall.py | 29 ++++++++++++-- .../bonsai/bim/module/project/operator.py | 29 ++++++++++++-- src/bonsai/bonsai/tool/snap.py | 39 +++++++++++++++---- 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/model/wall.py b/src/bonsai/bonsai/bim/module/model/wall.py index 769b5bb84b..a371492b33 100644 --- a/src/bonsai/bonsai/bim/module/model/wall.py +++ b/src/bonsai/bonsai/bim/module/model/wall.py @@ -294,7 +294,27 @@ 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 @@ -311,6 +331,7 @@ class DrawPolylineWall(bpy.types.Operator): self.input_panel[self.input_type] = self.number_output if not is_valid: self.report({"WARNING"}, "The number typed is not valid.") + return is_valid else: if self.input_type in {"X", "Y"}: self.input_panel = PolylineDecorator.calculate_distance_and_angle(context, self.is_input_on) @@ -321,6 +342,7 @@ class DrawPolylineWall(bpy.types.Operator): PolylineDecorator.set_input_panel(self.input_panel, self.input_type) tool.Blender.update_viewport() + return is_valid # TODO This is creating a hack in generate function from DumbWallGenerator # Come up with a better solution @@ -448,8 +470,9 @@ class DrawPolylineWall(bpy.types.Operator): return {"FINISHED"} if self.is_input_on and event.value == "RELEASE" and event.type in {"RET", "NUMPAD_ENTER", "RIGHTMOUSE"}: - self.recalculate_inputs(context) - tool.Snap.insert_polyline_point(self.input_panel) + is_valid = self.recalculate_inputs(context) + if is_valid: + tool.Snap.insert_polyline_point(self.input_panel) self.is_input_on = False self.input_type = "OFF" self.number_input = [] diff --git a/src/bonsai/bonsai/bim/module/project/operator.py b/src/bonsai/bonsai/bim/module/project/operator.py index 1f81224e28..80febfd08d 100644 --- a/src/bonsai/bonsai/bim/module/project/operator.py +++ b/src/bonsai/bonsai/bim/module/project/operator.py @@ -2303,7 +2303,27 @@ class MeasureTool(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 @@ -2320,6 +2340,7 @@ class MeasureTool(bpy.types.Operator): self.input_panel[self.input_type] = self.number_output if not is_valid: self.report({"WARNING"}, "The number typed is not valid.") + return is_valid else: if self.input_type in {"X", "Y", "Z"}: self.input_panel = PolylineDecorator.calculate_distance_and_angle(context, self.is_input_on) @@ -2330,6 +2351,7 @@ class MeasureTool(bpy.types.Operator): PolylineDecorator.set_input_panel(self.input_panel, self.input_type) tool.Blender.update_viewport() + return is_valid def modal(self, context, event): @@ -2424,8 +2446,9 @@ class MeasureTool(bpy.types.Operator): tool.Blender.update_viewport() if self.is_input_on and event.value == "RELEASE" and event.type in {"RET", "NUMPAD_ENTER", "RIGHTMOUSE"}: - self.recalculate_inputs(context) - tool.Snap.insert_polyline_point(self.input_panel) + is_valid = self.recalculate_inputs(context) + if is_valid: + tool.Snap.insert_polyline_point(self.input_panel) self.is_input_on = False self.input_type = "OFF" self.number_input = [] diff --git a/src/bonsai/bonsai/tool/snap.py b/src/bonsai/bonsai/tool/snap.py index 23b5c8e94e..0e950f1625 100644 --- a/src/bonsai/bonsai/tool/snap.py +++ b/src/bonsai/bonsai/tool/snap.py @@ -456,19 +456,36 @@ class Snap(bonsai.core.tool.Snap): @classmethod def validate_input(cls, input_number): - grammar = """ + grammar_imperial = """ start: FORMULA? dim expr? - dim: metric | imperial + dim: imperial FORMULA: "=" - metric: NUMBER - imperial: feet? "-"? inches? feet: NUMBER? " "? fraction? "'" inches: NUMBER? " "? fraction? "\\"" fraction: NUMBER "/" NUMBER + expr: (ADD | SUB) dim | (MUL | DIV) NUMBER + + NUMBER: /-?\\d+(?:\\.\\d+)?/ + ADD: "+" + SUB: "-" + MUL: "*" + DIV: "/" + + %ignore " " + """ + + grammar_metric = """ + start: FORMULA? dim expr? + dim: metric + + FORMULA: "=" + + metric: NUMBER + expr: (ADD | SUB | MUL | DIV) dim NUMBER: /-?\\d+(?:\\.\\d+)?/ @@ -502,7 +519,7 @@ class Snap(bonsai.core.tool.Snap): result = (args[0] + args[1]) else: result = args[0] - return result * 0.3048 + return result def metric(self, args): return args[0] @@ -535,13 +552,19 @@ class Snap(bonsai.core.tool.Snap): dimension = args[i] if len(args) > i+1: expression = args[i + 1] - return expression(dimension) + return expression(dimension) * factor else: - return dimension + return dimension * factor try: - parser = Lark(grammar) + if bpy.context.scene.unit_settings.system == 'IMPERIAL': + parser = Lark(grammar_imperial) + factor = 0.3048 + else: + parser = Lark(grammar_metric) + factor = 1 + parse_tree = parser.parse(input_number) transformer = InputTransform()