From c2e857a414a6e485b3de10edb67e4c529774bf59 Mon Sep 17 00:00:00 2001 From: SpectralVectors Date: Fri, 25 Oct 2024 21:17:12 -0400 Subject: [PATCH] Add files via upload --- scripts/addons/cam/__init__.py | 5 - scripts/addons/cam/basrelief.py | 4 +- scripts/addons/cam/engine.py | 2 +- scripts/addons/cam/machine_settings.py | 6 +- scripts/addons/cam/ui/panels/area.py | 24 +-- scripts/addons/cam/ui/panels/chains.py | 24 ++- scripts/addons/cam/ui/panels/cutter.py | 58 +++--- scripts/addons/cam/ui/panels/feedrate.py | 8 +- scripts/addons/cam/ui/panels/gcode.py | 29 +-- scripts/addons/cam/ui/panels/info.py | 9 +- scripts/addons/cam/ui/panels/machine.py | 107 +++++----- scripts/addons/cam/ui/panels/material.py | 30 +-- scripts/addons/cam/ui/panels/movement.py | 49 +++-- scripts/addons/cam/ui/panels/op_properties.py | 188 ++++++++++-------- scripts/addons/cam/ui/panels/operations.py | 40 ++-- scripts/addons/cam/ui/panels/optimisation.py | 12 +- scripts/addons/cam/ui/panels/pack.py | 29 +-- scripts/addons/cam/ui/panels/slice.py | 21 +- 18 files changed, 368 insertions(+), 277 deletions(-) diff --git a/scripts/addons/cam/__init__.py b/scripts/addons/cam/__init__.py index e06a7096..78129371 100644 --- a/scripts/addons/cam/__init__.py +++ b/scripts/addons/cam/__init__.py @@ -23,11 +23,6 @@ from bpy_extras.object_utils import object_data_add # Relative Imports - from 'cam' module from . import basrelief -from .autoupdate import ( - UpdateChecker, - Updater, - UpdateSourceOperator, -) from .cam_operation import camOperation from .chain import ( camChain, diff --git a/scripts/addons/cam/basrelief.py b/scripts/addons/cam/basrelief.py index 7b9e7b4d..52de32fc 100644 --- a/scripts/addons/cam/basrelief.py +++ b/scripts/addons/cam/basrelief.py @@ -1613,7 +1613,6 @@ class BASRELIEF_Panel(bpy.types.Panel): bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "render" - COMPAT_ENGINES = {"FABEX_RENDER"} # def draw_header(self, context): @@ -1656,6 +1655,9 @@ class BASRELIEF_Panel(bpy.types.Panel): """ layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + # print(dir(layout)) s = bpy.context.scene diff --git a/scripts/addons/cam/engine.py b/scripts/addons/cam/engine.py index e4d0ddf8..f2f5bd47 100644 --- a/scripts/addons/cam/engine.py +++ b/scripts/addons/cam/engine.py @@ -30,7 +30,7 @@ from .ui.panels.slice import CAM_SLICE_Panel class FABEX_ENGINE(RenderEngine): bl_idname = "FABEX_RENDER" - bl_label = "Fabex" + bl_label = "Fabex CNC/CAM" bl_use_eevee_viewport = True diff --git a/scripts/addons/cam/machine_settings.py b/scripts/addons/cam/machine_settings.py index f2710f21..9bb93ea8 100644 --- a/scripts/addons/cam/machine_settings.py +++ b/scripts/addons/cam/machine_settings.py @@ -148,12 +148,12 @@ class machineSettings(PropertyGroup): ) axis4: BoolProperty( - name="#4th Axis", + name="4th Axis", description="Machine has 4th axis", default=0, ) axis5: BoolProperty( - name="#5th Axis", + name="5th Axis", description="Machine has 5th axis", default=0, ) @@ -180,7 +180,7 @@ class machineSettings(PropertyGroup): # default='X', update = updateOffsetImage) collet_size: FloatProperty( - name="#Collet Size", + name="Collet Size", description="Collet size for collision detection", default=33, min=0.00001, diff --git a/scripts/addons/cam/ui/panels/area.py b/scripts/addons/cam/ui/panels/area.py index 667aab5d..b27a7f29 100644 --- a/scripts/addons/cam/ui/panels/area.py +++ b/scripts/addons/cam/ui/panels/area.py @@ -19,18 +19,20 @@ class CAM_AREA_Panel(CAMButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + # Use Layers - col = layout.column(align=True) - row = col.row(align=True) - row.prop(self.op, "use_layers") - if self.op.use_layers: - row.prop(self.op, "stepdown") + header, panel = layout.panel_prop(self.op, "use_layers") + header.label(text="Layers") + if panel: + col = panel.column(align=True) + if self.op.use_layers: + col.prop(self.op, "stepdown", text="Layer Height") # First Down if self.level >= 1 and self.op.strategy in ["CUTOUT", "POCKET", "MEDIAL_AXIS"]: - row = col.row(align=True) - row.label(text="") - row.prop(self.op, "first_down") + col.prop(self.op, "first_down") # Max Z if self.level >= 1: @@ -48,11 +50,9 @@ class CAM_AREA_Panel(CAMButtonsPanel, Panel): if self.op.strategy == "CURVE": col.label(text="Cannot Use Depth from Object Using Curves") - row = col.row(align=True) - row.label(text="Set Max Depth from") - row.prop(self.op, "minz_from", text="") + col.prop(self.op, "minz_from", text="Set Max Depth from") if self.op.minz_from == "CUSTOM": - row.prop(self.op, "minz") + col.prop(self.op, "minz") else: col.prop(self.op, "source_image_scale_z") diff --git a/scripts/addons/cam/ui/panels/chains.py b/scripts/addons/cam/ui/panels/chains.py index d5683e5b..bb26ab64 100644 --- a/scripts/addons/cam/ui/panels/chains.py +++ b/scripts/addons/cam/ui/panels/chains.py @@ -43,12 +43,17 @@ class CAM_CHAINS_Panel(CAMButtonsPanel, Panel): bl_label = "CAM Chains" bl_idname = "WORLD_PT_CAM_CHAINS" + # bl_space_type = "VIEW_3D" + # bl_region_type = "UI" + # bl_category = "Fabex" panel_interface_level = 1 always_show_panel = True def draw(self, context): if self.level >= 1 and self.op is not None: layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False row = layout.row() scene = bpy.context.scene @@ -73,20 +78,23 @@ class CAM_CHAINS_Panel(CAMButtonsPanel, Panel): col.operator("scene.cam_chain_operation_up", icon="TRIA_UP", text="") col.operator("scene.cam_chain_operation_down", icon="TRIA_DOWN", text="") + col = layout.column(align=True) if not chain.computing: - layout.operator( + col.operator( "object.calculate_cam_paths_chain", text="Calculate Chain Paths & Export Gcode", ) - layout.operator("object.cam_export_paths_chain", text="Export Chain G-code") - layout.operator("object.cam_simulate_chain", text="Simulate This Chain") + col.operator("object.cam_export_paths_chain", text="Export Chain G-code") + col.operator("object.cam_simulate_chain", text="Simulate This Chain") valid, reason = isChainValid(chain, context) if not valid: - layout.label(icon="ERROR", text=f"Can't Compute Chain - Reason:\n") - layout.label(text=reason) + col.label(icon="ERROR", text=f"Can't Compute Chain - Reason:\n") + col.label(text=reason) else: - layout.label(text="Chain Is Currently Computing") + col.label(text="Chain Is Currently Computing") - layout.prop(chain, "name") - layout.prop(chain, "filename") + box = layout.box() + col = box.column(align=True) + col.prop(chain, "name") + col.prop(chain, "filename") diff --git a/scripts/addons/cam/ui/panels/cutter.py b/scripts/addons/cam/ui/panels/cutter.py index c1c25936..4e528f84 100644 --- a/scripts/addons/cam/ui/panels/cutter.py +++ b/scripts/addons/cam/ui/panels/cutter.py @@ -18,6 +18,9 @@ class CAM_CUTTER_Panel(CAMButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + # Cutter Preset Menu if self.level >= 1: row = layout.row(align=True) @@ -27,63 +30,66 @@ class CAM_CUTTER_Panel(CAMButtonsPanel, Panel): True ) - # Cutter ID - if self.level >= 2: - layout.prop(self.op, "cutter_id") - + box = layout.box() + col = box.column(align=True) # Cutter Type - layout.prop(self.op, "cutter_type") + col.prop(self.op, "cutter_type", text="Type") # Ball Radius if self.op.cutter_type in ["BALLCONE"]: - layout.prop(self.op, "ball_radius") + col.prop(self.op, "ball_radius") # Bullnose Radius if self.op.cutter_type in ["BULLNOSE"]: - layout.prop(self.op, "bull_corner_radius") + col.prop(self.op, "bull_corner_radius") # Cyclone Diameter if self.op.cutter_type in ["CYLCONE"]: - layout.prop(self.op, "cylcone_diameter") + col.prop(self.op, "cylcone_diameter") # Cutter Tip Angle if self.op.cutter_type in ["VCARVE", "BALLCONE", "BULLNOSE", "CYLCONE"]: - layout.prop(self.op, "cutter_tip_angle") + col.prop(self.op, "cutter_tip_angle") # Laser if self.op.cutter_type in ["LASER"]: - layout.prop(self.op, "Laser_on") - layout.prop(self.op, "Laser_off") - layout.prop(self.op, "Laser_cmd") - layout.prop(self.op, "Laser_delay") + col.prop(self.op, "Laser_on") + col.prop(self.op, "Laser_off") + col.prop(self.op, "Laser_cmd") + col.prop(self.op, "Laser_delay") # Plasma if self.op.cutter_type in ["PLASMA"]: - layout.prop(self.op, "Plasma_on") - layout.prop(self.op, "Plasma_off") - layout.prop(self.op, "Plasma_delay") - layout.prop(self.op, "Plasma_dwell") - layout.prop(self.op, "lead_in") - layout.prop(self.op, "lead_out") + col.prop(self.op, "Plasma_on") + col.prop(self.op, "Plasma_off") + col.prop(self.op, "Plasma_delay") + col.prop(self.op, "Plasma_dwell") + col.prop(self.op, "lead_in") + col.prop(self.op, "lead_out") # Custom if self.op.cutter_type in ["CUSTOM"]: if self.op.optimisation.use_exact: - layout.label(text="Warning - only Convex Shapes Are Supported. ", icon="COLOR_RED") - layout.label(text="If Your Custom Cutter Is Concave,") - layout.label(text="Switch Exact Mode Off.") - layout.prop_search(self.op, "cutter_object_name", bpy.data, "objects") + col.label(text="Warning - only Convex Shapes Are Supported. ", icon="COLOR_RED") + col.label(text="If Your Custom Cutter Is Concave,") + col.label(text="Switch Exact Mode Off.") + col.prop_search(self.op, "cutter_object_name", bpy.data, "objects") # Cutter Diameter - layout.prop(self.op, "cutter_diameter") + col.prop(self.op, "cutter_diameter", text="Diameter") # Cutter Flutes if self.level >= 1: if self.op.cutter_type not in ["LASER", "PLASMA"]: - layout.prop(self.op, "cutter_flutes") + col.prop(self.op, "cutter_flutes", text="Flutes") + + # Cutter ID + if self.level >= 2: + col = box.column(align=True) + col.prop(self.op, "cutter_id") # Cutter Description - layout.prop(self.op, "cutter_description") + col.prop(self.op, "cutter_description") # Cutter Engagement if self.op.cutter_type in ["LASER", "PLASMA"]: diff --git a/scripts/addons/cam/ui/panels/feedrate.py b/scripts/addons/cam/ui/panels/feedrate.py index 1851dff5..f9a264f9 100644 --- a/scripts/addons/cam/ui/panels/feedrate.py +++ b/scripts/addons/cam/ui/panels/feedrate.py @@ -18,6 +18,9 @@ class CAM_FEEDRATE_Panel(CAMButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + # Feedrate layout.prop(self.op, "feedrate") @@ -27,9 +30,10 @@ class CAM_FEEDRATE_Panel(CAMButtonsPanel, Panel): # Plunge Feedrate if self.level >= 1: - layout.prop(self.op, "plunge_feedrate") + col = layout.column(align=True) + col.prop(self.op, "plunge_feedrate") # Plunge Angle - layout.prop(self.op, "plunge_angle") + col.prop(self.op, "plunge_angle") # Spindle RPM layout.prop(self.op, "spindle_rpm") diff --git a/scripts/addons/cam/ui/panels/gcode.py b/scripts/addons/cam/ui/panels/gcode.py index afcb9914..a2dc0687 100644 --- a/scripts/addons/cam/ui/panels/gcode.py +++ b/scripts/addons/cam/ui/panels/gcode.py @@ -19,31 +19,34 @@ class CAM_GCODE_Panel(CAMButtonsPanel, Panel): def draw(self, context): if self.level >= 1 and self.op is not None: layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + col = layout.column(align=True) # Output Header - layout.prop(self.op, "output_header") + col.prop(self.op, "output_header") if self.op.output_header: - layout.prop(self.op, "gcode_header") + col.prop(self.op, "gcode_header") # Output Trailer - layout.prop(self.op, "output_trailer") + col.prop(self.op, "output_trailer") if self.op.output_trailer: - layout.prop(self.op, "gcode_trailer") + col.prop(self.op, "gcode_trailer") # Enable Dust - layout.prop(self.op, "enable_dust") + col.prop(self.op, "enable_dust") if self.op.enable_dust: - layout.prop(self.op, "gcode_start_dust_cmd") - layout.prop(self.op, "gcode_stop_dust_cmd") + col.prop(self.op, "gcode_start_dust_cmd") + col.prop(self.op, "gcode_stop_dust_cmd") # Enable Hold - layout.prop(self.op, "enable_hold") + col.prop(self.op, "enable_hold") if self.op.enable_hold: - layout.prop(self.op, "gcode_start_hold_cmd") - layout.prop(self.op, "gcode_stop_hold_cmd") + col.prop(self.op, "gcode_start_hold_cmd") + col.prop(self.op, "gcode_stop_hold_cmd") # Enable Mist - layout.prop(self.op, "enable_mist") + col.prop(self.op, "enable_mist") if self.op.enable_mist: - layout.prop(self.op, "gcode_start_mist_cmd") - layout.prop(self.op, "gcode_stop_mist_cmd") + col.prop(self.op, "gcode_start_mist_cmd") + col.prop(self.op, "gcode_stop_mist_cmd") diff --git a/scripts/addons/cam/ui/panels/info.py b/scripts/addons/cam/ui/panels/info.py index f54fcbae..96547059 100644 --- a/scripts/addons/cam/ui/panels/info.py +++ b/scripts/addons/cam/ui/panels/info.py @@ -66,17 +66,20 @@ class CAM_INFO_Panel(CAMButtonsPanel, Panel): # Display the Info Panel def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + col = layout.column(align=True) # Fabex Version - layout.label(text=f'Fabex v{".".join([str(x) for x in cam_version])}') + col.label(text=f'Fabex v{".".join([str(x) for x in cam_version])}') # OpenCAMLib Version if self.level >= 1: ocl_version = opencamlib_version() if ocl_version is None: - layout.label(text="OpenCAMLib is not Installed") + col.label(text="OpenCAMLib is not Installed") else: - layout.label(text=f"OpenCAMLib v{ocl_version}") + col.label(text=f"OpenCAMLib v{ocl_version}") if self.op is None: return diff --git a/scripts/addons/cam/ui/panels/machine.py b/scripts/addons/cam/ui/panels/machine.py index 36711f7f..71e7596d 100644 --- a/scripts/addons/cam/ui/panels/machine.py +++ b/scripts/addons/cam/ui/panels/machine.py @@ -19,6 +19,8 @@ class CAM_MACHINE_Panel(CAMButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False # Presets if self.level >= 1: @@ -35,65 +37,78 @@ class CAM_MACHINE_Panel(CAMButtonsPanel, Panel): icon="REMOVE", ).remove_active = True + col = layout.column(align=True) # Post Processor - layout.prop(self.machine, "post_processor") - - # Split Files - if self.level >= 2: - layout.prop(self.machine, "eval_splitting") - if self.machine.eval_splitting: - layout.prop(self.machine, "split_limit") - + col.prop(self.machine, "post_processor") # System - layout.prop(bpy.context.scene.unit_settings, "system") + col.prop(context.scene.unit_settings, "system") + col.prop(context.scene.unit_settings, "length_unit", text="Unit") - # Position Definitions + # Supplemental Axis + if self.level >= 3: + col.prop(self.machine, "axis4") + col.prop(self.machine, "axis5") + + # Collet Size if self.level >= 2: - layout.prop(self.machine, "use_position_definitions") - if self.machine.use_position_definitions: - layout.prop(self.machine, "starting_position") - layout.prop(self.machine, "mtc_position") - layout.prop(self.machine, "ending_position") + col.prop(self.machine, "collet_size") # Working Area layout.prop(self.machine, "working_area") + # Position Definitions + if self.level >= 2: + header, panel = layout.panel_prop(self.machine, "use_position_definitions") + header.label(text="Position Definitions") + if panel: + panel.prop(self.machine, "starting_position") + panel.prop(self.machine, "mtc_position") + panel.prop(self.machine, "ending_position") + # Feedrates if self.level >= 1: - layout.prop(self.machine, "feedrate_min") - layout.prop(self.machine, "feedrate_max") - layout.prop(self.machine, "feedrate_default") + header, panel = layout.panel(idname="feedrate", default_closed=True) + header.label(text="Feedrate (/min)") + if panel: + panel.prop(self.machine, "feedrate_default", text="Default") + panel.prop(self.machine, "feedrate_min", text="Minimum") + panel.prop(self.machine, "feedrate_max", text="Maximum") # Spindle Speeds # TODO: spindle default and feedrate default should become part of the cutter definition... - layout.prop(self.machine, "spindle_min") - layout.prop(self.machine, "spindle_max") - layout.prop(self.machine, "spindle_start_time") - layout.prop(self.machine, "spindle_default") + header, panel = layout.panel(idname="spindle", default_closed=True) + header.label(text="Spindle Speed (RPM)") + if panel: + panel.prop(self.machine, "spindle_default", text="Default") + panel.prop(self.machine, "spindle_min", text="Minimum") + panel.prop(self.machine, "spindle_max", text="Maximum") + panel.prop(self.machine, "spindle_start_time", text="Start Delay (seconds)") - # Tool Options - if self.level >= 2: - layout.prop(self.machine, "output_tool_definitions") - layout.prop(self.machine, "output_tool_change") - if self.machine.output_tool_change: - layout.prop(self.machine, "output_g43_on_tool_change") - - # Supplemental Axis - if self.level >= 3: - layout.prop(self.machine, "axis4") - layout.prop(self.machine, "axis5") - - # Collet Size - if self.level >= 2: - layout.prop(self.machine, "collet_size") - - # Block Numbers - if self.level >= 2: - layout.prop(self.machine, "output_block_numbers") - if self.machine.output_block_numbers: - layout.prop(self.machine, "start_block_number") - layout.prop(self.machine, "block_number_increment") - - # Hourly Rate + # Gcode Options if self.level >= 1: + header, panel = layout.panel(idname="gcode", default_closed=True) + header.label(text="Gcode Options") + if panel: + col = panel.column(align=True) + # Tool Options + if self.level >= 2: + col.prop(self.machine, "output_tool_definitions") + col.prop(self.machine, "output_tool_change") + if self.machine.output_tool_change: + col.prop(self.machine, "output_g43_on_tool_change") + + # Block Numbers + if self.level >= 2: + col.prop(self.machine, "output_block_numbers") + if self.machine.output_block_numbers: + col.prop(self.machine, "start_block_number") + col.prop(self.machine, "block_number_increment") + + # Split Files + if self.level >= 2: + col.prop(self.machine, "eval_splitting") + if self.machine.eval_splitting: + col.prop(self.machine, "split_limit") + + # Hourly Rate layout.prop(self.machine, "hourly_rate") diff --git a/scripts/addons/cam/ui/panels/material.py b/scripts/addons/cam/ui/panels/material.py index a38854bb..8bfeb58b 100644 --- a/scripts/addons/cam/ui/panels/material.py +++ b/scripts/addons/cam/ui/panels/material.py @@ -117,26 +117,32 @@ class CAM_MATERIAL_Panel(CAMButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + box = layout.box() + col = box.column(align=True) + col.label(text="Size") # Estimate from Image if self.op.geometry_source not in ["OBJECT", "COLLECTION"]: - layout.label(text="Estimated from Image") + col.label(text="Estimated from Image") # Estimate from Object if self.level >= 1: if self.op.geometry_source in ["OBJECT", "COLLECTION"]: - layout.prop(self.op.material, "estimate_from_model") + col.prop(self.op.material, "estimate_from_model") if self.op.material.estimate_from_model: - row_radius = layout.row() - row_radius.label(text="Additional Radius") - row_radius.prop(self.op.material, "radius_around_model", text="") + col.prop(self.op.material, "radius_around_model", text="Additional Radius") else: - layout.prop(self.op.material, "origin") - layout.prop(self.op.material, "size") + col.prop(self.op.material, "origin") + col.prop(self.op.material, "size") # Axis Alignment if self.op.geometry_source in ["OBJECT", "COLLECTION"]: - row_axis = layout.row() - row_axis.prop(self.op.material, "center_x") - row_axis.prop(self.op.material, "center_y") - layout.prop(self.op.material, "z_position") - layout.operator("object.material_cam_position", text="Position Object") + box = layout.box() + col = box.column(align=True) + col.label(text="Position") + col.prop(self.op.material, "center_x") + col.prop(self.op.material, "center_y") + col.prop(self.op.material, "z_position") + col.operator("object.material_cam_position", text="Position Object") diff --git a/scripts/addons/cam/ui/panels/movement.py b/scripts/addons/cam/ui/panels/movement.py index 7e1a7eba..25b967e6 100644 --- a/scripts/addons/cam/ui/panels/movement.py +++ b/scripts/addons/cam/ui/panels/movement.py @@ -230,6 +230,9 @@ class CAM_MOVEMENT_Panel(CAMButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + # Cut Type if self.level >= 1: layout.prop(self.op.movement, "type") @@ -249,9 +252,11 @@ class CAM_MOVEMENT_Panel(CAMButtonsPanel, Panel): # Use G64 if self.level >= 2: if context.scene.cam_machine.post_processor not in G64_INCOMPATIBLE_MACHINES: - layout.prop(self.op.movement, "useG64") - if self.op.movement.useG64: - layout.prop(self.op.movement, "G64") + header, panel = layout.panel_prop(self.op.movement, "useG64") + header.label(text="G64 Trajectory") + if panel: + col = panel.column(align=True) + col.prop(self.op.movement, "G64") # Parallel Stepback if self.level >= 1: @@ -269,30 +274,38 @@ class CAM_MOVEMENT_Panel(CAMButtonsPanel, Panel): # Ramp if self.level >= 1: - layout.prop(self.op.movement, "ramp") - if self.op.movement.ramp: - layout.prop(self.op.movement, "ramp_in_angle") - layout.prop(self.op.movement, "ramp_out") + header, panel = layout.panel_prop(self.op.movement, "ramp") + header.label(text="Ramp (Experimental)") + if panel: + col = panel.column(align=True) + col.prop(self.op.movement, "ramp_in_angle") + col.prop(self.op.movement, "ramp_out") if self.op.movement.ramp_out: - layout.prop(self.op.movement, "ramp_out_angle") + col.prop(self.op.movement, "ramp_out_angle") # Retract Tangential if self.level >= 2: if self.op.strategy in ["POCKET"]: - layout.prop(self.op.movement, "retract_tangential") - if self.op.movement.retract_tangential: - layout.prop(self.op.movement, "retract_radius") - layout.prop(self.op.movement, "retract_height") + header, panel = layout.panel_prop(self.op.movement, "retract_tangential") + header.label(text="Retract Tangential") + if panel: + col = panel.column(align=True) + col.prop(self.op.movement, "retract_radius") + col.prop(self.op.movement, "retract_height") # Stay Low if self.level >= 1: - layout.prop(self.op.movement, "stay_low") - if self.op.movement.stay_low: - layout.prop(self.op.movement, "merge_dist") + header, panel = layout.panel_prop(self.op.movement, "stay_low") + header.label(text="Stay Low (if possible)") + if panel: + col = panel.column(align=True) + col.prop(self.op.movement, "merge_dist") # Protect Vertical if self.level >= 1: if self.op.cutter_type not in ["BALLCONE"]: - layout.prop(self.op.movement, "protect_vertical") - if self.op.movement.protect_vertical: - layout.prop(self.op.movement, "protect_vertical_limit") + header, panel = layout.panel_prop(self.op.movement, "protect_vertical") + header.label(text="Protect Vertical") + if panel: + col = panel.column(align=True) + col.prop(self.op.movement, "protect_vertical_limit") diff --git a/scripts/addons/cam/ui/panels/op_properties.py b/scripts/addons/cam/ui/panels/op_properties.py index dd892308..4964a0cd 100644 --- a/scripts/addons/cam/ui/panels/op_properties.py +++ b/scripts/addons/cam/ui/panels/op_properties.py @@ -16,9 +16,9 @@ class CAM_OPERATION_PROPERTIES_Panel(CAMButtonsPanel, Panel): bl_idname = "WORLD_PT_CAM_OPERATION" panel_interface_level = 0 - def draw_cutter_engagement(self): + def draw_cutter_engagement(self, col): if self.op is not None: - layout = self.layout + # layout = self.layout # Cutter Engagement # Warns if cutter engagement is greater than 50% if self.op.cutter_type in ["BALLCONE"]: @@ -27,119 +27,135 @@ class CAM_OPERATION_PROPERTIES_Panel(CAMButtonsPanel, Panel): engagement = round(100 * self.op.dist_between_paths / self.op.cutter_diameter, 1) if engagement > 50: - layout.label(text="Warning: High Cutter Engagement") + col.label(text="Warning: High Cutter Engagement") - layout.label(text=f"Cutter Engagement: {engagement}%") + col.label(text=f"Cutter Engagement: {engagement}%") - def draw_enable_A_B_axis(self): + def draw_enable_A_B_axis(self, col): # Enable A & B Axes if self.level >= 1: - layout = self.layout - layout.prop(self.op, "enable_A") + # layout = self.layout + col.prop(self.op, "enable_A") if self.op.enable_A: - layout.prop(self.op, "rotation_A") - layout.prop(self.op, "A_along_x") + col.prop(self.op, "rotation_A") + col.prop(self.op, "A_along_x") if self.op.A_along_x: - layout.label(text="A || X - B || Y") + col.label(text="A || X - B || Y") else: - layout.label(text="A || Y - B || X") + col.label(text="A || Y - B || X") - layout.prop(self.op, "enable_B") + col.prop(self.op, "enable_B") if self.op.enable_B: - layout.prop(self.op, "rotation_B") + col.prop(self.op, "rotation_B") - def draw_overshoot(self): - layout = self.layout + def draw_overshoot(self, col): + # layout = self.layout # Overshoot - layout.prop(self.op, "straight") + col.prop(self.op, "straight") def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + col = layout.column(align=True) # Machine Axis if self.level >= 2: - layout.prop(self.op, "machine_axes") + col.prop(self.op, "machine_axes") # Strategy if self.op.machine_axes == "4": - layout.prop(self.op, "strategy4axis") + col.prop(self.op, "strategy4axis") if self.op.strategy4axis == "INDEXED": - layout.prop(self.op, "strategy") - layout.prop(self.op, "rotary_axis_1") + col.prop(self.op, "strategy") + col.prop(self.op, "rotary_axis_1") elif self.op.machine_axes == "5": - layout.prop(self.op, "strategy5axis") + col.prop(self.op, "strategy5axis") if self.op.strategy5axis == "INDEXED": - layout.prop(self.op, "strategy") - layout.prop(self.op, "rotary_axis_1") - layout.prop(self.op, "rotary_axis_2") + col.prop(self.op, "strategy") + col.prop(self.op, "rotary_axis_1") + col.prop(self.op, "rotary_axis_2") else: - layout.prop(self.op, "strategy") + col.prop(self.op, "strategy") # Cutout Options if self.op.strategy in ["CUTOUT"]: + box = layout.box() + col = box.column(align=True) # Cutout Type - layout.prop(self.op, "cut_type") + col.prop(self.op, "cut_type") if self.op.cut_type in ["OUTSIDE", "INSIDE"]: - self.draw_overshoot() + self.draw_overshoot(col=col) # Startpoint - layout.prop(self.op, "profile_start") + col.prop(self.op, "profile_start") # Lead In & Out - layout.prop(self.op, "lead_in") - layout.prop(self.op, "lead_out") + col.prop(self.op, "lead_in") + col.prop(self.op, "lead_out") if self.op.strategy in ["CUTOUT", "CURVE"]: - self.draw_enable_A_B_axis() + self.draw_enable_A_B_axis(col=col) # Outlines - layout.prop(self.op, "outlines_count") + col.prop(self.op, "outlines_count") if self.op.outlines_count > 1: - layout.prop(self.op, "dist_between_paths") - self.draw_cutter_engagement() - layout.prop(self.op.movement, "insideout") + col.prop(self.op, "dist_between_paths") + self.draw_cutter_engagement(col=col) + col.prop(self.op.movement, "insideout") # Merge - layout.prop(self.op, "dont_merge") + col.prop(self.op, "dont_merge") # Waterline Options if self.op.strategy in ["WATERLINE"]: - layout.label(text="Ocl Doesn't Support Fill Areas") + box = layout.box() + col = box.column(align=True) + col.label(text="Ocl Doesn't Support Fill Areas") if not self.op.optimisation.use_opencamlib: - layout.prop(self.op, "slice_detail") - layout.prop(self.op, "waterline_fill") + col.prop(self.op, "slice_detail") + col.prop(self.op, "waterline_fill") if self.op.waterline_fill: - layout.prop(self.op, "dist_between_paths") - layout.prop(self.op, "waterline_project") - layout.label(text="Waterline Needs a Skin Margin") + col.prop(self.op, "dist_between_paths") + col.prop(self.op, "waterline_project") + col.label(text="Waterline Needs a Skin Margin") # Carve Options if self.op.strategy in ["CARVE"]: - layout.prop(self.op, "carve_depth") - layout.prop(self.op, "dist_along_paths") + box = layout.box() + col = box.column(align=True) + col.prop(self.op, "carve_depth") + col.prop(self.op, "dist_along_paths") # Medial Axis Options if self.op.strategy in ["MEDIAL_AXIS"]: - layout.prop(self.op, "medial_axis_threshold") - layout.prop(self.op, "medial_axis_subdivision") - layout.prop(self.op, "add_pocket_for_medial") - layout.prop(self.op, "add_mesh_for_medial") + box = layout.box() + col = box.column(align=True) + col.prop(self.op, "medial_axis_threshold") + col.prop(self.op, "medial_axis_subdivision") + col.prop(self.op, "add_pocket_for_medial") + col.prop(self.op, "add_mesh_for_medial") # Drill Options if self.op.strategy in ["DRILL"]: - layout.prop(self.op, "drill_type") - self.draw_enable_A_B_axis() + box = layout.box() + col = box.column(align=True) + col.prop(self.op, "drill_type") + self.draw_enable_A_B_axis(col=col) # Pocket Options if self.op.strategy in ["POCKET"]: - self.draw_overshoot() - layout.prop(self.op, "pocketType") + box = layout.box() + col = box.column(align=True) + self.draw_overshoot(col=col) + col.prop(self.op, "pocketType") if self.op.pocketType == "PARALLEL": - layout.label(text="Warning:Parallel pocket Experimental", icon="ERROR") - layout.prop(self.op, "parallelPocketCrosshatch") - layout.prop(self.op, "parallelPocketContour") - layout.prop(self.op, "parallelPocketAngle") + col.label(text="Warning:Parallel pocket Experimental", icon="ERROR") + col.prop(self.op, "parallelPocketCrosshatch") + col.prop(self.op, "parallelPocketContour") + col.prop(self.op, "parallelPocketAngle") else: - layout.prop(self.op, "pocket_option") - layout.prop(self.op, "pocketToCurve") - layout.prop(self.op, "dist_between_paths") - self.draw_cutter_engagement() - self.draw_enable_A_B_axis() + col.prop(self.op, "pocket_option") + col.prop(self.op, "pocketToCurve") + col.prop(self.op, "dist_between_paths") + self.draw_cutter_engagement(col=col) + self.draw_enable_A_B_axis(col=col) # Default Options if self.op.strategy not in [ @@ -151,33 +167,39 @@ class CAM_OPERATION_PROPERTIES_Panel(CAMButtonsPanel, Panel): "DRILL", "POCKET", ]: - layout.prop(self.op, "dist_between_paths") - self.draw_cutter_engagement() - layout.prop(self.op, "dist_along_paths") + box = layout.box() + col = box.column(align=True) + col.prop(self.op, "dist_between_paths") + self.draw_cutter_engagement(col=col) + col.prop(self.op, "dist_along_paths") if self.op.strategy in ["PARALLEL", "CROSS"]: - layout.prop(self.op, "parallel_angle") - self.draw_enable_A_B_axis() - layout.prop(self.op, "inverse") + col.prop(self.op, "parallel_angle") + self.draw_enable_A_B_axis(col=col) + col.prop(self.op, "inverse") # Bridges Options if self.level >= 1: if self.op.strategy not in ["POCKET", "DRILL", "CURVE", "MEDIAL_AXIS"]: - layout.prop(self.op, "use_bridges") - if self.op.use_bridges: - layout.prop(self.op, "bridges_width") - layout.prop(self.op, "bridges_height") - layout.prop_search(self.op, "bridges_collection_name", bpy.data, "collections") - layout.prop(self.op, "use_bridge_modifiers") - layout.operator("scene.cam_bridges_add", text="Autogenerate Bridges / Tabs") - - # Skin - self.layout.prop(self.op, "skin") + header, panel = layout.panel_prop(self.op, "use_bridges") + header.label(text="Bridges / Tabs") + if panel: + col = panel.column(align=True) + col.prop(self.op, "bridges_width", text="Width") + col.prop(self.op, "bridges_height", text="Height") + col.prop_search(self.op, "bridges_collection_name", bpy.data, "collections") + col.prop(self.op, "use_bridge_modifiers") + col.operator("scene.cam_bridges_add", text="Autogenerate") # Array if self.op.machine_axes == "3": - layout.prop(self.op, "array") - if self.op.array: - layout.prop(self.op, "array_x_count") - layout.prop(self.op, "array_x_distance") - layout.prop(self.op, "array_y_count") - layout.prop(self.op, "array_y_distance") + header, panel = layout.panel_prop(self.op, "array") + header.label(text="Array") + if panel: + col = panel.column(align=True) + col.prop(self.op, "array_x_count") + col.prop(self.op, "array_x_distance") + col.prop(self.op, "array_y_count") + col.prop(self.op, "array_y_distance") + + # Skin + self.layout.prop(self.op, "skin") diff --git a/scripts/addons/cam/ui/panels/operations.py b/scripts/addons/cam/ui/panels/operations.py index 4707b4c0..3d2f15c8 100644 --- a/scripts/addons/cam/ui/panels/operations.py +++ b/scripts/addons/cam/ui/panels/operations.py @@ -28,6 +28,9 @@ class CAM_OPERATIONS_Panel(CAMButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + # Presets if self.level >= 1: row = layout.row(align=True) @@ -69,7 +72,8 @@ class CAM_OPERATIONS_Panel(CAMButtonsPanel, Panel): if not self.op.valid: layout.label(text="Select a Valid Object to Calculate the Path.") # will be disabled if not valid - layout.operator("object.calculate_cam_path", text="Calculate Path & Export Gcode") + col = layout.column(align=True) + col.operator("object.calculate_cam_path", text="Calculate Path & Export Gcode") # Export Gcode if self.level >= 1: @@ -77,39 +81,39 @@ class CAM_OPERATIONS_Panel(CAMButtonsPanel, Panel): if self.op.name is not None: name = f"cam_path_{self.op.name}" if bpy.context.scene.objects.get(name) is not None: - layout.operator("object.cam_export", text="Export Gcode ") + col.operator("object.cam_export", text="Export Gcode ") # Simulate Op - layout.operator("object.cam_simulate", text="Simulate This Operation") - - # Op Name - layout.prop(self.op, "name") + col.operator("object.cam_simulate", text="Simulate This Operation") + box = layout.box() + col = box.column(align=True) + # Op Name + col.prop(self.op, "name") # Op Filename - layout.prop(self.op, "filename") - + col.prop(self.op, "filename") # Op Source - layout.prop(self.op, "geometry_source") + col.prop(self.op, "geometry_source") if self.op.strategy == "CURVE": if self.op.geometry_source == "OBJECT": - layout.prop_search(self.op, "object_name", bpy.data, "objects") + col.prop_search(self.op, "object_name", bpy.data, "objects") elif self.op.geometry_source == "COLLECTION": - layout.prop_search(self.op, "collection_name", bpy.data, "collections") + col.prop_search(self.op, "collection_name", bpy.data, "collections") else: if self.op.geometry_source == "OBJECT": - layout.prop_search(self.op, "object_name", bpy.data, "objects") + col.prop_search(self.op, "object_name", bpy.data, "objects") if self.op.enable_A: - layout.prop(self.op, "rotation_A") + col.prop(self.op, "rotation_A") if self.op.enable_B: - layout.prop(self.op, "rotation_B") + col.prop(self.op, "rotation_B") elif self.op.geometry_source == "COLLECTION": - layout.prop_search(self.op, "collection_name", bpy.data, "collections") + col.prop_search(self.op, "collection_name", bpy.data, "collections") else: - layout.prop_search(self.op, "source_image_name", bpy.data, "images") + col.prop_search(self.op, "source_image_name", bpy.data, "images") if self.op.strategy in ["CARVE", "PROJECTED_CURVE"]: - layout.prop_search(self.op, "curve_object", bpy.data, "objects") + col.prop_search(self.op, "curve_object", bpy.data, "objects") if self.op.strategy == "PROJECTED_CURVE": - layout.prop_search(self.op, "curve_object1", bpy.data, "objects") + col.prop_search(self.op, "curve_object1", bpy.data, "objects") diff --git a/scripts/addons/cam/ui/panels/optimisation.py b/scripts/addons/cam/ui/panels/optimisation.py index ad8e0cdb..cf8a6025 100644 --- a/scripts/addons/cam/ui/panels/optimisation.py +++ b/scripts/addons/cam/ui/panels/optimisation.py @@ -113,11 +113,15 @@ class CAM_OPTIMISATION_Panel(CAMButtonsPanel, Panel): def draw(self, context): if self.level >= 2 and self.op is not None: layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + # Optimize - layout.prop(self.op.optimisation, "optimize") - if self.op.optimisation.optimize: - layout.prop(self.op.optimisation, "optimize_threshold") - layout.separator() + header, panel = layout.panel_prop(self.op.optimisation, "optimize") + header.label(text="Reduce Path Points") + if panel: + col = panel.column(align=True) + col.prop(self.op.optimisation, "optimize_threshold", text="Threshold (μm)") # Exact Mode if not self.op.geometry_source == "OBJECT" or self.op.geometry_source == "COLLECTION": diff --git a/scripts/addons/cam/ui/panels/pack.py b/scripts/addons/cam/ui/panels/pack.py index 2c5bf134..8b2e548d 100644 --- a/scripts/addons/cam/ui/panels/pack.py +++ b/scripts/addons/cam/ui/panels/pack.py @@ -15,18 +15,21 @@ class CAM_PACK_Panel(CAMButtonsPanel, Panel): bl_label = "Pack Curves on Sheet" bl_idname = "WORLD_PT_CAM_PACK" panel_interface_level = 2 + use_property_split = True def draw(self, context): - if self.level >= 2: - layout = self.layout - scene = bpy.context.scene - settings = scene.cam_pack - layout.operator("object.cam_pack_objects") - layout.prop(settings, "sheet_fill_direction") - layout.prop(settings, "sheet_x") - layout.prop(settings, "sheet_y") - layout.prop(settings, "distance") - layout.prop(settings, "tolerance") - layout.prop(settings, "rotate") - if settings.rotate: - layout.prop(settings, "rotate_angle") + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + scene = bpy.context.scene + settings = scene.cam_pack + layout.operator("object.cam_pack_objects") + layout.prop(settings, "sheet_fill_direction") + layout.prop(settings, "sheet_x") + layout.prop(settings, "sheet_y") + layout.prop(settings, "distance") + layout.prop(settings, "tolerance") + layout.prop(settings, "rotate") + if settings.rotate: + layout.prop(settings, "rotate_angle") diff --git a/scripts/addons/cam/ui/panels/slice.py b/scripts/addons/cam/ui/panels/slice.py index e42f5a2b..8d4b5a3f 100644 --- a/scripts/addons/cam/ui/panels/slice.py +++ b/scripts/addons/cam/ui/panels/slice.py @@ -15,14 +15,17 @@ class CAM_SLICE_Panel(CAMButtonsPanel, Panel): bl_label = "Slice Model to Plywood Sheets" bl_idname = "WORLD_PT_CAM_SLICE" panel_interface_level = 2 + use_property_split = True def draw(self, context): - if self.level >= 2: - layout = self.layout - scene = bpy.context.scene - settings = scene.cam_slice - layout.operator("object.cam_slice_objects") - layout.prop(settings, "slice_distance") - layout.prop(settings, "slice_above0") - layout.prop(settings, "slice_3d") - layout.prop(settings, "indexes") + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + scene = bpy.context.scene + settings = scene.cam_slice + layout.operator("object.cam_slice_objects") + layout.prop(settings, "slice_distance") + layout.prop(settings, "slice_above0") + layout.prop(settings, "slice_3d") + layout.prop(settings, "indexes")