From e546971ada72454e27ac2a3efb45d9d00fbbeb9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Perdig=C3=A3o?= Date: Fri, 6 Sep 2024 14:26:31 -0300 Subject: [PATCH] Changed input validation to tool/polyline.py --- src/bonsai/bonsai/bim/module/model/wall.py | 2 +- .../bonsai/bim/module/project/operator.py | 2 +- src/bonsai/bonsai/tool/polyline.py | 130 ++++++++++++++++++ src/bonsai/bonsai/tool/snap.py | 127 ----------------- 4 files changed, 132 insertions(+), 129 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/model/wall.py b/src/bonsai/bonsai/bim/module/model/wall.py index 5dbc53351a..d06323ae95 100644 --- a/src/bonsai/bonsai/bim/module/model/wall.py +++ b/src/bonsai/bonsai/bim/module/model/wall.py @@ -339,7 +339,7 @@ class DrawPolylineWall(bpy.types.Operator): def recalculate_inputs(self, context): if self.number_input: - is_valid, self.number_output = tool.Snap.validate_input(self.number_output, self.input_type) + is_valid, self.number_output = tool.Polyline.validate_input(self.number_output, self.input_type) self.input_ui.set_value(self.input_type, self.number_output) if not is_valid: self.report({"WARNING"}, "The number typed is not valid.") diff --git a/src/bonsai/bonsai/bim/module/project/operator.py b/src/bonsai/bonsai/bim/module/project/operator.py index 0758348d04..b862a9cee2 100644 --- a/src/bonsai/bonsai/bim/module/project/operator.py +++ b/src/bonsai/bonsai/bim/module/project/operator.py @@ -2324,7 +2324,7 @@ class MeasureTool(bpy.types.Operator): def recalculate_inputs(self, context): if self.number_input: - is_valid, self.number_output = tool.Snap.validate_input(self.number_output, self.input_type) + is_valid, self.number_output = tool.Polyline.validate_input(self.number_output, self.input_type) self.input_ui.set_value(self.input_type, self.number_output) if not is_valid: self.report({"WARNING"}, "The number typed is not valid.") diff --git a/src/bonsai/bonsai/tool/polyline.py b/src/bonsai/bonsai/tool/polyline.py index 8934ffe4c7..9095f99fdb 100644 --- a/src/bonsai/bonsai/tool/polyline.py +++ b/src/bonsai/bonsai/tool/polyline.py @@ -21,6 +21,7 @@ import bonsai.core.tool import bonsai.tool as tool from bonsai.bim.module.drawing.helper import format_distance from dataclasses import dataclass, field +from lark import Lark, Transformer from math import sin, cos, radians, degrees, atan2, acos from mathutils import Vector, Matrix from typing import Optional @@ -282,3 +283,132 @@ class Polyline(bonsai.core.tool.Polyline): input_ui.set_value("Z", last_point.z) return + + + @classmethod + def validate_input(cls, input_number, input_type): + + grammar_imperial = """ + start: (FORMULA dim expr) | dim + dim: imperial + + FORMULA: "=" + + 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+)?/ + ADD: "+" + SUB: "-" + MUL: "*" + DIV: "/" + + %ignore " " + """ + + 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: + if args[0] <= 0: + result = args[0] - args[1] + else: + result = args[0] + args[1] + else: + result = args[0] + return result + + def metric(self, args): + return args[0] + + def dim(self, args): + return args[0] + + def expr(self, args): + op = args[0] + value = float(args[1]) + if op == "+": + return lambda x: x + value + elif op == "-": + return lambda x: x - value + elif op == "*": + return lambda x: x * value + elif op == "/": + return lambda x: x / value + + def FORMULA(cls, args): + return args[0] + + def start(self, args): + 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) * factor + else: + return dimension * factor + + try: + if bpy.context.scene.unit_settings.system == "IMPERIAL": + parser = Lark(grammar_imperial) + factor = 0.3048 + else: + parser = Lark(grammar_metric) + factor = 1 + if bpy.context.scene.unit_settings.length_unit == "MILLIMETERS": + factor = 0.001 + + if input_type == "A": + parser = Lark(grammar_metric) + factor = 1 + + parse_tree = parser.parse(input_number) + + transformer = InputTransform() + result = transformer.transform(parse_tree) + return True, str(result) + except: + return False, "0" diff --git a/src/bonsai/bonsai/tool/snap.py b/src/bonsai/bonsai/tool/snap.py index 9f0cc5f9bf..e75db3aadc 100644 --- a/src/bonsai/bonsai/tool/snap.py +++ b/src/bonsai/bonsai/tool/snap.py @@ -509,130 +509,3 @@ class Snap(bonsai.core.tool.Snap): cls.update_snapping_point(shifted_list[0][0], shifted_list[0][1]) return shifted_list - @classmethod - def validate_input(cls, input_number, input_type): - - grammar_imperial = """ - start: (FORMULA dim expr) | dim - dim: imperial - - FORMULA: "=" - - 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+)?/ - ADD: "+" - SUB: "-" - MUL: "*" - DIV: "/" - - %ignore " " - """ - - 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: - if args[0] <= 0: - result = args[0] - args[1] - else: - result = args[0] + args[1] - else: - result = args[0] - return result - - def metric(self, args): - return args[0] - - def dim(self, args): - return args[0] - - def expr(self, args): - op = args[0] - value = float(args[1]) - if op == "+": - return lambda x: x + value - elif op == "-": - return lambda x: x - value - elif op == "*": - return lambda x: x * value - elif op == "/": - return lambda x: x / value - - def FORMULA(cls, args): - return args[0] - - def start(self, args): - 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) * factor - else: - return dimension * factor - - try: - if bpy.context.scene.unit_settings.system == "IMPERIAL": - parser = Lark(grammar_imperial) - factor = 0.3048 - else: - parser = Lark(grammar_metric) - factor = 1 - if bpy.context.scene.unit_settings.length_unit == "MILLIMETERS": - factor = 0.001 - - if input_type == "A": - parser = Lark(grammar_metric) - factor = 1 - - parse_tree = parser.parse(input_number) - - transformer = InputTransform() - result = transformer.transform(parse_tree) - return True, str(result) - except: - return False, "0"