From 56428eb605f5ecc217f5a9a48497a36b350f6687 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Thu, 5 Sep 2024 17:13:25 +0500 Subject: [PATCH] Ooops, fix black formatter ignoring bonsai folder #5178 --- pyproject.toml | 2 +- src/bonsai/bonsai/bim/module/cost/operator.py | 2 +- src/bonsai/bonsai/bim/module/cost/ui.py | 8 +- .../bonsai/bim/module/model/__init__.py | 5 +- .../bonsai/bim/module/model/decorator.py | 19 ++-- src/bonsai/bonsai/bim/module/model/prop.py | 2 + src/bonsai/bonsai/bim/module/model/wall.py | 2 +- .../bonsai/bim/module/model/workspace.py | 11 +- .../bonsai/bim/module/project/operator.py | 2 +- src/bonsai/bonsai/bim/module/search/ui.py | 1 - .../bonsai/bim/module/spatial/operator.py | 4 +- src/bonsai/bonsai/core/cost.py | 2 +- src/bonsai/bonsai/tool/cad.py | 21 ++-- src/bonsai/bonsai/tool/cost.py | 5 +- src/bonsai/bonsai/tool/raycast.py | 6 +- src/bonsai/bonsai/tool/snap.py | 4 +- src/bonsai/bonsai/tool/web.py | 56 ++++------ src/bonsai/scripts/generate_png_icons.py | 102 ++++++++++-------- 18 files changed, 129 insertions(+), 125 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8e329ff191..88fc4867e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ include = ''' src/( bcf |bcfserver - |blenderbim + |bonsai |bsdd |foundationserver |ifc2ca diff --git a/src/bonsai/bonsai/bim/module/cost/operator.py b/src/bonsai/bonsai/bim/module/cost/operator.py index 42d4bf0ff4..b541702f89 100644 --- a/src/bonsai/bonsai/bim/module/cost/operator.py +++ b/src/bonsai/bonsai/bim/module/cost/operator.py @@ -800,4 +800,4 @@ class GenerateCostScheduleBrowser(bpy.types.Operator): def execute(self, context): core.generate_cost_schedule_browser(tool.Cost, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule)) - return {"FINISHED"} \ No newline at end of file + return {"FINISHED"} diff --git a/src/bonsai/bonsai/bim/module/cost/ui.py b/src/bonsai/bonsai/bim/module/cost/ui.py index db0401b8cb..7be6605318 100644 --- a/src/bonsai/bonsai/bim/module/cost/ui.py +++ b/src/bonsai/bonsai/bim/module/cost/ui.py @@ -73,8 +73,12 @@ class BIM_PT_cost_schedules(Panel): row1.label(text="Schedule tools") row1 = col.row(align=True) row1.alignment = "RIGHT" - row1.operator("bim.export_cost_schedules", text="Export spreadsheet", icon="EXPORT").cost_schedule = cost_schedule["id"] - row1.operator("bim.generate_cost_schedule_browser", text="Generate spreadsheet browsser", icon="URL").cost_schedule = cost_schedule["id"] + row1.operator("bim.export_cost_schedules", text="Export spreadsheet", icon="EXPORT").cost_schedule = ( + cost_schedule["id"] + ) + row1.operator( + "bim.generate_cost_schedule_browser", text="Generate spreadsheet browsser", icon="URL" + ).cost_schedule = cost_schedule["id"] row2 = col.row(align=True) row2.alignment = "RIGHT" op = row2.operator("bim.select_cost_schedule_products", icon="RESTRICT_SELECT_OFF", text="Assigned") diff --git a/src/bonsai/bonsai/bim/module/model/__init__.py b/src/bonsai/bonsai/bim/module/model/__init__.py index a5e4566c81..0d87693dfc 100644 --- a/src/bonsai/bonsai/bim/module/model/__init__.py +++ b/src/bonsai/bonsai/bim/module/model/__init__.py @@ -218,6 +218,7 @@ def register(): workspace.load_custom_icons() + def unregister(): if not bpy.app.background: bpy.utils.unregister_tool(workspace.WallTool) @@ -231,7 +232,7 @@ def unregister(): bpy.utils.unregister_tool(workspace.CableCarrierTool) bpy.utils.unregister_tool(workspace.CableTool) bpy.utils.unregister_tool(workspace.BimTool) - + del bpy.types.Scene.BIMModelProperties del bpy.types.Object.BIMArrayProperties del bpy.types.Object.BIMStairProperties @@ -245,4 +246,4 @@ def unregister(): bpy.types.VIEW3D_MT_mesh_add.remove(ui.add_mesh_object_menu) bpy.types.VIEW3D_MT_add.remove(ui.add_menu) - workspace.unload_custom_icons() \ No newline at end of file + workspace.unload_custom_icons() diff --git a/src/bonsai/bonsai/bim/module/model/decorator.py b/src/bonsai/bonsai/bim/module/model/decorator.py index 4a28f7e2de..6ccedfa660 100644 --- a/src/bonsai/bonsai/bim/module/model/decorator.py +++ b/src/bonsai/bonsai/bim/module/model/decorator.py @@ -413,7 +413,9 @@ class PolylineDecorator: distance = (snap_vector - last_point).length if distance > 0: - angle = tool.Cad.angle_3_vectors(second_to_last_point, last_point, snap_vector, new_angle=None, degrees=True) + angle = tool.Cad.angle_3_vectors( + second_to_last_point, last_point, snap_vector, new_angle=None, degrees=True + ) # Round angle to the nearest 0.05 angle = round(angle / 0.05) * 0.05 @@ -547,12 +549,17 @@ class PolylineDecorator: if context.scene.unit_settings.length_unit == "MILLIMETERS": factor = 1000 - return format_distance( - value * factor, precision=precision, suppress_zero_inches=True, in_unit_length=True - ) + return format_distance(value * factor, precision=precision, suppress_zero_inches=True, in_unit_length=True) def draw_input_panel(self, context): - texts = {"D": "Distance: ", "A": "Angle: ", "X": "X coord: ", "Y": "Y coord: ", "Z": "Z coord:", "AREA": "Area: "} + texts = { + "D": "Distance: ", + "A": "Angle: ", + "X": "X coord: ", + "Y": "Y coord: ", + "Z": "Z coord:", + "AREA": "Area: ", + } self.addon_prefs = tool.Blender.get_addon_preferences() self.font_id = 0 @@ -687,7 +694,6 @@ class PolylineDecorator: for i in range(len(polyline_points) - 1): polyline_edges.append([i, i + 1]) - # Line for angle axis snap if snap_prop.snap_type == "Axis": self.line_shader.uniform_float("lineWidth", 0.75) @@ -728,4 +734,3 @@ class PolylineDecorator: self.draw_batch("POINTS", polyline_points, decorator_color_selected) if len(polyline_points) > 1: self.draw_batch("LINES", polyline_points, decorator_color_selected, polyline_edges) - diff --git a/src/bonsai/bonsai/bim/module/model/prop.py b/src/bonsai/bonsai/bim/module/model/prop.py index b02df5ec43..8d970ec166 100644 --- a/src/bonsai/bonsai/bim/module/model/prop.py +++ b/src/bonsai/bonsai/bim/module/model/prop.py @@ -111,11 +111,13 @@ class PolylinePoint(PropertyGroup): y: bpy.props.FloatProperty(name="Y") z: bpy.props.FloatProperty(name="Z") + class PolylineMeasurement(PropertyGroup): dim: bpy.props.StringProperty(name="Dimension") angle: bpy.props.StringProperty(name="Angle") position: bpy.props.FloatVectorProperty(name="Decorator Position", size=3) + class BIMModelProperties(PropertyGroup): ifc_class: bpy.props.EnumProperty(items=get_ifc_class, name="Construction Class", update=update_ifc_class) relating_type_id: bpy.props.EnumProperty( diff --git a/src/bonsai/bonsai/bim/module/model/wall.py b/src/bonsai/bonsai/bim/module/model/wall.py index 104426feb0..f458627d0e 100644 --- a/src/bonsai/bonsai/bim/module/model/wall.py +++ b/src/bonsai/bonsai/bim/module/model/wall.py @@ -435,7 +435,7 @@ class DrawPolylineWall(bpy.types.Operator): self.number_output = "".join(self.number_input) if self.input_type != "A": self.number_output = PolylineDecorator.format_input_panel_units(context, float(self.number_output)) - + self.input_panel[self.input_type] = self.number_output PolylineDecorator.set_input_panel(self.input_panel, self.input_type) diff --git a/src/bonsai/bonsai/bim/module/model/workspace.py b/src/bonsai/bonsai/bim/module/model/workspace.py index b74141b62c..ea29f468d3 100644 --- a/src/bonsai/bonsai/bim/module/model/workspace.py +++ b/src/bonsai/bonsai/bim/module/model/workspace.py @@ -33,7 +33,7 @@ from bonsai.bim.module.model.prop import get_ifc_class def check_display_mode(): global display_mode try: - theme = bpy.context.preferences.themes['Default'] + theme = bpy.context.preferences.themes["Default"] text_color = theme.user_interface.wcol_menu_item.text background_color = theme.user_interface.wcol_menu_item.outline print(f"text_color = {text_color}") @@ -50,12 +50,12 @@ def load_custom_icons(): global custom_icon_previews if display_mode is None: check_display_mode() - + icons_dir = os.path.join(os.path.dirname(__file__), "..", "..", "data", "icons") custom_icon_previews = bpy.utils.previews.new() - + prefix = f"{display_mode}_" - + for entry in os.scandir(icons_dir): if entry.name.endswith(".png") and entry.name.startswith(prefix): name = os.path.splitext(entry.name)[0].replace(prefix, "", 1) @@ -1181,6 +1181,7 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator): else: bpy.ops.bim.show_openings() + custom_icon_previews = None display_mode = None @@ -1190,4 +1191,4 @@ MODIFIERS = { "A": ("EVENT_ALT", "OPTION" if sys.platform == "Darwin" else "ALT"), "C": ("EVENT_CTRL", "CTRL"), "S": ("EVENT_SHIFT", "⇧"), -} \ No newline at end of file +} diff --git a/src/bonsai/bonsai/bim/module/project/operator.py b/src/bonsai/bonsai/bim/module/project/operator.py index af99eed7fe..c9dca610ff 100644 --- a/src/bonsai/bonsai/bim/module/project/operator.py +++ b/src/bonsai/bonsai/bim/module/project/operator.py @@ -2410,7 +2410,7 @@ class MeasureTool(bpy.types.Operator): self.number_output = "".join(self.number_input) if self.input_type != "A": self.number_output = PolylineDecorator.format_input_panel_units(context, float(self.number_output)) - + self.input_panel[self.input_type] = self.number_output PolylineDecorator.set_input_panel(self.input_panel, self.input_type) diff --git a/src/bonsai/bonsai/bim/module/search/ui.py b/src/bonsai/bonsai/bim/module/search/ui.py index 05dfcb9e4d..a18a7e2409 100644 --- a/src/bonsai/bonsai/bim/module/search/ui.py +++ b/src/bonsai/bonsai/bim/module/search/ui.py @@ -102,7 +102,6 @@ class BIM_PT_colour_by_property(Panel): if props.max_mode == "MANUAL": row.prop(props, "max_value", text="") - row = self.layout.row(align=True) row.operator("bim.colour_by_property", icon="BRUSH_DATA") row.operator("bim.reset_object_colours") diff --git a/src/bonsai/bonsai/bim/module/spatial/operator.py b/src/bonsai/bonsai/bim/module/spatial/operator.py index 007b4716e5..5ce3032555 100644 --- a/src/bonsai/bonsai/bim/module/spatial/operator.py +++ b/src/bonsai/bonsai/bim/module/spatial/operator.py @@ -87,9 +87,7 @@ class AssignContainer(bpy.types.Operator, tool.Ifc.Operator): elif (container_obj := props.container_obj) and (container := tool.Ifc.get_entity(container_obj)): pass for element_obj in context.selected_objects: - core.assign_container( - tool.Ifc, tool.Collector, tool.Spatial, container=container, element_obj=element_obj - ) + core.assign_container(tool.Ifc, tool.Collector, tool.Spatial, container=container, element_obj=element_obj) class EnableEditingContainer(bpy.types.Operator, tool.Ifc.Operator): diff --git a/src/bonsai/bonsai/core/cost.py b/src/bonsai/bonsai/core/cost.py index 7700502a89..0b5e4a30dc 100644 --- a/src/bonsai/bonsai/core/cost.py +++ b/src/bonsai/bonsai/core/cost.py @@ -402,4 +402,4 @@ def add_currency(ifc: tool.Ifc, cost: tool.Cost) -> ifcopenshell.entity_instance def generate_cost_schedule_browser(cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance) -> bpy.types.Panel: cost_schedule_data = cost.create_cost_schedule_json(cost_schedule) - return cost.generate_cost_schedule_browser(cost_schedule_data) \ No newline at end of file + return cost.generate_cost_schedule_browser(cost_schedule_data) diff --git a/src/bonsai/bonsai/tool/cad.py b/src/bonsai/bonsai/tool/cad.py index 8aae8e7bf9..44b4b58d92 100644 --- a/src/bonsai/bonsai/tool/cad.py +++ b/src/bonsai/bonsai/tool/cad.py @@ -102,10 +102,13 @@ class Cad: # Calculate the unsigned angle between the "d1" and "d2" vectors a = d1.angle(d2) - # Determine the sign of the angle based on the provided axis # If new_angle, determine the direction of the rotation - parameter = round(axis.z, 2) < 0 or (round(axis.y, 2) == 0 and round(axis.x < 0)) or (round(axis.x, 2) == 0 and round(axis.y < 0)) + parameter = ( + round(axis.z, 2) < 0 + or (round(axis.y, 2) == 0 and round(axis.x < 0)) + or (round(axis.x, 2) == 0 and round(axis.y < 0)) + ) if new_angle is not None: rot_mat = Matrix.Rotation(new_angle, 3, axis) rot_vector = (d1 @ rot_mat) if parameter else (rot_mat @ d1) @@ -181,7 +184,7 @@ class Cad: """ Calculate the closest points on two line segments. Note: This function doesn't use intersect_line_line - + > edge1: tuple of two vectors (v1, v2) representing the first segment > edge2: tuple of two vectors (v3, v4) representing the second segment < returns: tuple of two vectors (C1, C2) or (None, None) if lines are parallel @@ -199,19 +202,19 @@ class Cad: d2 = (P2_end - P2).normalized() n = d1.cross(d2) - + # if n is zero, lines are parallel if n.length == 0: return None, None - + n2 = d2.cross(n) - + C1 = P1 + ((P2 - P1).dot(n2) / (d1.dot(n2))) * d1 - + n1 = d1.cross(n) - + C2 = P2 + ((P1 - P2).dot(n1) / (d2.dot(n1))) * d2 - + return C1, C2 @classmethod diff --git a/src/bonsai/bonsai/tool/cost.py b/src/bonsai/bonsai/tool/cost.py index 5fa98c32e7..1aa24eb9c3 100644 --- a/src/bonsai/bonsai/tool/cost.py +++ b/src/bonsai/bonsai/tool/cost.py @@ -811,6 +811,7 @@ class Cost(bonsai.core.tool.Cost): @classmethod def create_cost_schedule_json(cls, cost_schedule: ifcopenshell.entity_instance) -> dict: from bonsai.bim.module.cost.data import CostSchedulesData + CostSchedulesData.load() cost_items = CostSchedulesData.data["cost_items"] data = [] @@ -832,7 +833,7 @@ class Cost(bonsai.core.tool.Cost): return None for rel in cost_item.IsNestedBy or []: for sub_cost_item in rel.RelatedObjects or []: - cls.create_cost_item_json(sub_cost_item, cost_items,cost_item_data["is_nested_by"]) + cls.create_cost_item_json(sub_cost_item, cost_items, cost_item_data["is_nested_by"]) @classmethod def is_cost_item_sum(cls, cost_item: ifcopenshell.entity_instance) -> bool: @@ -856,4 +857,4 @@ class Cost(bonsai.core.tool.Cost): def generate_cost_schedule_browser(cls, cost_schedule_data: list[dict[str, Any]]) -> None: if not bpy.context.scene.WebProperties.is_connected: bpy.ops.bim.connect_websocket_server(page="costing") - tool.Web.send_webui_data(data=cost_schedule_data, data_key="cost_items", event="cost_items") \ No newline at end of file + tool.Web.send_webui_data(data=cost_schedule_data, data_key="cost_items", event="cost_items") diff --git a/src/bonsai/bonsai/tool/raycast.py b/src/bonsai/bonsai/tool/raycast.py index ac49ce3f7c..2d84659bea 100644 --- a/src/bonsai/bonsai/tool/raycast.py +++ b/src/bonsai/bonsai/tool/raycast.py @@ -70,7 +70,7 @@ class Raycast(bonsai.core.tool.Raycast): xmin, xmax, ymin, ymax = bbox # extends bbox boundaries to improve snap - if offset: + if offset: xmin -= offset xmax += offset ymin -= offset @@ -193,7 +193,9 @@ class Raycast(bonsai.core.tool.Raycast): loc = Vector((0, 0, 0)) polyline_data = bpy.context.scene.BIMModelProperties.polyline_point - polyline_data = polyline_data[: len(polyline_data) - 1] # It doesn't make sense to snap to the last point created + polyline_data = polyline_data[ + : len(polyline_data) - 1 + ] # It doesn't make sense to snap to the last point created polyline_points = [] for point_data in polyline_data: point = Vector((point_data.x, point_data.y, point_data.z)) diff --git a/src/bonsai/bonsai/tool/snap.py b/src/bonsai/bonsai/tool/snap.py index 319f5fcf71..4f51e85ca6 100644 --- a/src/bonsai/bonsai/tool/snap.py +++ b/src/bonsai/bonsai/tool/snap.py @@ -70,7 +70,6 @@ class Snap(bonsai.core.tool.Snap): return snap_point - @classmethod def select_snap_point(cls, snap_points, hit, threshold): shortest_distance = None @@ -168,7 +167,7 @@ class Snap(bonsai.core.tool.Snap): if len(polyline_data) > 2: first_point = polyline_data[0] last_point = polyline_data[-1] - if not(first_point.x == last_point.x and first_point.y == last_point.y and first_point.z == last_point.z): + if not (first_point.x == last_point.x and first_point.y == last_point.y and first_point.z == last_point.z): polyline_point = bpy.context.scene.BIMModelProperties.polyline_point.add() polyline_point.x = first_point.x polyline_point.y = first_point.y @@ -361,7 +360,6 @@ class Snap(bonsai.core.tool.Snap): best_hit = hit_world best_face_index = face_index - if best_obj is not None: return best_obj, best_hit, best_face_index diff --git a/src/bonsai/bonsai/tool/web.py b/src/bonsai/bonsai/tool/web.py index 6c59b075d3..2b4247fd89 100644 --- a/src/bonsai/bonsai/tool/web.py +++ b/src/bonsai/bonsai/tool/web.py @@ -333,7 +333,6 @@ class Web(bonsai.core.tool.Web): bpy.context.view_layer.objects.active = obj obj.select_set(True) - @classmethod def handle_cost_operator(cls, operator_data: dict) -> None: """ @@ -348,10 +347,11 @@ class Web(bonsai.core.tool.Web): cost_schedules = ifc_file.by_type("IfcCostSchedule") cost_schedules_json = [cs.get_info(recursive=True) for cs in cost_schedules] currency = tool.Cost.currency() - cls.send_webui_data(data={ - "cost_schedules": cost_schedules_json, - "currency": currency - }, data_key="cost_schedules", event="cost_schedules") + cls.send_webui_data( + data={"cost_schedules": cost_schedules_json, "currency": currency}, + data_key="cost_schedules", + event="cost_schedules", + ) if operator_data["type"] == "loadCostSchedule": cost_schedule = ifc_file.by_id(operator_data["costScheduleId"]) bonsai.core.cost.enable_editing_cost_items(tool.Cost, cost_schedule=cost_schedule) @@ -375,36 +375,28 @@ class Web(bonsai.core.tool.Web): cls.load_cost_schedule_web_ui(cost_schedule) if operator_data["type"] == "editCostItemName": cost_item = tool.Ifc.get().by_id(operator_data["costItemId"]) - tool.Ifc.run( - "cost.edit_cost_item", - cost_item=cost_item, - attributes = {"Name": operator_data["name"]} - ) + tool.Ifc.run("cost.edit_cost_item", cost_item=cost_item, attributes={"Name": operator_data["name"]}) tool.Cost.load_cost_schedule_tree() if operator_data["type"] == "enableEditingCostValues": cost_item = tool.Ifc.get().by_id(operator_data["costItemId"]) cost_values = ifcopenshell.util.cost.get_cost_values(cost_item) - cls.send_webui_data(data={ - "cost_values": cost_values, - "cost_item_id": operator_data["costItemId"] - }, data_key="cost_values", event="cost_values") + cls.send_webui_data( + data={"cost_values": cost_values, "cost_item_id": operator_data["costItemId"]}, + data_key="cost_values", + event="cost_values", + ) if operator_data["type"] == "addCostValue": value = ifcopenshell.api.cost.add_cost_value( ifc_file, parent=ifc_file.by_id(operator_data["costItemId"]), ) cls.send_webui_data( - data={ - "cost_value_id" : value.id(), - "cost_item_id":operator_data["costItemId"]}, - data_key="cost_value", - event="cost_value" + data={"cost_value_id": value.id(), "cost_item_id": operator_data["costItemId"]}, + data_key="cost_value", + event="cost_value", ) if operator_data["type"] == "deleteCostValue": - bpy.ops.bim.remove_cost_value( - parent=operator_data["costItemId"], - cost_value=operator_data["costValueId"] - ) + bpy.ops.bim.remove_cost_value(parent=operator_data["costItemId"], cost_value=operator_data["costValueId"]) cost_item = ifc_file.by_id(operator_data["costItemId"]) cost_schedule = tool.Cost.get_cost_schedule(cost_item=cost_item) cls.load_cost_schedule_web_ui(cost_schedule) @@ -416,29 +408,19 @@ class Web(bonsai.core.tool.Web): print("editing cost value data", value_data) value = ifc_file.by_id(value_data["id"]) if value_data["costType"] == "FIXED": - attributes= { - "AppliedValue": value_data["appliedValue"], - "Category": None - } + attributes = {"AppliedValue": value_data["appliedValue"], "Category": None} elif value_data["costType"] == "CATEGORY": - attributes= { + attributes = { "AppliedValue": value_data["appliedValue"], "Category": value_data["costCategory"], } elif value_data["costType"] == "SUM": - attributes= { - "Category": '*' - } - ifcopenshell.api.cost.edit_cost_value( - file=ifc_file, - cost_value=value, - attributes= attributes - ) + attributes = {"Category": "*"} + ifcopenshell.api.cost.edit_cost_value(file=ifc_file, cost_value=value, attributes=attributes) print(value.get_info()) tool.Cost.load_cost_schedule_tree() cls.load_cost_schedule_web_ui(cost_schedule) - @classmethod def load_cost_schedule_web_ui(cls, cost_schedule): json_data = tool.Cost.create_cost_schedule_json(cost_schedule) diff --git a/src/bonsai/scripts/generate_png_icons.py b/src/bonsai/scripts/generate_png_icons.py index e2b268ac79..d24b69fe90 100644 --- a/src/bonsai/scripts/generate_png_icons.py +++ b/src/bonsai/scripts/generate_png_icons.py @@ -10,98 +10,106 @@ import xml.etree.ElementTree as ET import re SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) -SVG_FILE = os.path.join(SCRIPT_DIR, 'bonsai_icons.svg') -EXPORT_FOLDER = os.path.join(SCRIPT_DIR, '..', 'bonsai', 'bim', 'data', 'icons') +SVG_FILE = os.path.join(SCRIPT_DIR, "bonsai_icons.svg") +EXPORT_FOLDER = os.path.join(SCRIPT_DIR, "..", "bonsai", "bim", "data", "icons") overwrite_all = False skip_all = False + def dark_to_light(svg_content): - svg_content = re.sub(r'#ffffff', '#434343', svg_content, flags=re.IGNORECASE) # white to drak grey + svg_content = re.sub(r"#ffffff", "#434343", svg_content, flags=re.IGNORECASE) # white to drak grey - svg_content = re.sub(r'#00d27b', '#009d5c', svg_content, flags=re.IGNORECASE) # make green darker - svg_content = re.sub(r'#009a5f', '#00663f', svg_content, flags=re.IGNORECASE) # make dark green darker - svg_content = re.sub(r'#75ffaf', '#3dff8f', svg_content, flags=re.IGNORECASE) # make light green darker + svg_content = re.sub(r"#00d27b", "#009d5c", svg_content, flags=re.IGNORECASE) # make green darker + svg_content = re.sub(r"#009a5f", "#00663f", svg_content, flags=re.IGNORECASE) # make dark green darker + svg_content = re.sub(r"#75ffaf", "#3dff8f", svg_content, flags=re.IGNORECASE) # make light green darker - svg_content = re.sub(r'#cce3ff', '#3391ff', svg_content, flags=re.IGNORECASE) # make blue darker - svg_content = re.sub(r'#4c9fff', '#005fcc', svg_content, flags=re.IGNORECASE) # make dark blue darker - svg_content = re.sub(r'#c9e0ff', '#80b8ff', svg_content, flags=re.IGNORECASE) # make light blue darker + svg_content = re.sub(r"#cce3ff", "#3391ff", svg_content, flags=re.IGNORECASE) # make blue darker + svg_content = re.sub(r"#4c9fff", "#005fcc", svg_content, flags=re.IGNORECASE) # make dark blue darker + svg_content = re.sub(r"#c9e0ff", "#80b8ff", svg_content, flags=re.IGNORECASE) # make light blue darker return svg_content + def prompt_overwrite(file_path, png_name): global overwrite_all, skip_all - + if skip_all and os.path.exists(file_path): - return 'n' - + return "n" + if overwrite_all: - return 'y' - + return "y" + if os.path.exists(file_path): while True: - response = input(f"File '{png_name}' already exists.\nOverwrite? (Enter = yes, s = skip, y = yes all, n = no all): ").strip().lower() - if response in {'', 'y', 'n', 's'}: - if response == 'y': + response = ( + input( + f"File '{png_name}' already exists.\nOverwrite? (Enter = yes, s = skip, y = yes all, n = no all): " + ) + .strip() + .lower() + ) + if response in {"", "y", "n", "s"}: + if response == "y": overwrite_all = True - elif response == 'n': + elif response == "n": skip_all = True return response else: print("Invalid option. Please enter Enter, y, n, or s.") - return '' + return "" + def export_svg_group(group_content, group_label, mode, output_folder): - temp_svg_file = os.path.join(output_folder, f'{group_label}_{mode}.svg') + temp_svg_file = os.path.join(output_folder, f"{group_label}_{mode}.svg") svg_content = f""" {group_content} """ - with open(temp_svg_file, 'w') as file: + with open(temp_svg_file, "w") as file: file.write(svg_content) - - png_name = f'{mode}_{group_label}.png' + + png_name = f"{mode}_{group_label}.png" output_png_file = os.path.join(output_folder, png_name) - + user_choice = prompt_overwrite(output_png_file, png_name) - - if user_choice in {'y', ''}: - subprocess.run(['inkscape', temp_svg_file, '--export-type=png', '--export-filename=' + output_png_file]) - print(f'\033[32mExported PNG file: {output_png_file}\033[0m') - - elif user_choice == 'n': + if user_choice in {"y", ""}: + subprocess.run(["inkscape", temp_svg_file, "--export-type=png", "--export-filename=" + output_png_file]) + print(f"\033[32mExported PNG file: {output_png_file}\033[0m") + + elif user_choice == "n": print(f"Skipping {png_name}") - - elif user_choice == 's': - print(f'Skipped exporting {output_png_file}.') - - os.remove(temp_svg_file) + elif user_choice == "s": + print(f"Skipped exporting {output_png_file}.") + + os.remove(temp_svg_file) def export_svg_groups_to_png(svg_file, output_folder): tree = ET.parse(svg_file) root = tree.getroot() - ns = {'svg': 'http://www.w3.org/2000/svg'} + ns = {"svg": "http://www.w3.org/2000/svg"} - for group in root.findall('.//svg:g', ns): - group_label = group.get('{http://www.inkscape.org/namespaces/inkscape}label') + for group in root.findall(".//svg:g", ns): + group_label = group.get("{http://www.inkscape.org/namespaces/inkscape}label") if not group_label: continue - style = group.get('style', '') - if 'display:none' in style: - style = style.replace('display:none', 'display:inline') - elif 'display' not in style: - style += ';display:inline' - group.set('style', style) + style = group.get("style", "") + if "display:none" in style: + style = style.replace("display:none", "display:inline") + elif "display" not in style: + style += ";display:inline" + group.set("style", style) - group_content = ET.tostring(group, encoding='unicode', method='xml') - export_svg_group(group_content, group_label, 'dm', output_folder) + group_content = ET.tostring(group, encoding="unicode", method="xml") + export_svg_group(group_content, group_label, "dm", output_folder) light_mode_svg = dark_to_light(group_content) - export_svg_group(light_mode_svg, group_label, 'lm', output_folder) + export_svg_group(light_mode_svg, group_label, "lm", output_folder) + if __name__ == "__main__": os.makedirs(EXPORT_FOLDER, exist_ok=True)