Cutting ui.py into pieces, created cam op functions in buttons_panel

pull/217/head
migo101 2022-04-12 19:43:32 +02:00
rodzic 0133759d91
commit e27dccd8f0
6 zmienionych plików z 306 dodań i 253 usunięć

Wyświetl plik

@ -33,29 +33,15 @@ from bpy.types import (Panel, Menu, Operator, PropertyGroup, )
from cam import gcodeimportparser, simple
from cam.simple import *
from cam.ui_panels.buttons_panel import CAMButtonsPanel
from cam.ui_panels.info import CAM_INFO_Panel
from cam.ui_panels.operations import CAM_OPERATIONS_Panel
from cam.ui_panels.cutter import CAM_CUTTER_Panel
from cam.ui_panels.machine import CAM_MACHINE_Panel
from cam.ui_panels.material import CAM_MATERIAL_Panel
from cam.ui_panels.chains import CAM_UL_operations, CAM_UL_chains, CAM_CHAINS_Panel
# Displays percentage of the cutter which is engaged with the material
# Displays a warning for engagements greater than 50%
def EngagementDisplay(operat, layout):
ao = operat
if ao.cutter_type == 'BALLCONE':
if ao.dist_between_paths > ao.ball_radius:
layout.label(text="CAUTION: CUTTER ENGAGEMENT")
layout.label(text="GREATER THAN 50%")
layout.label(text="Cutter engagement: " + str(round(100 * ao.dist_between_paths / ao.ball_radius, 1)) + "%")
else:
if ao.dist_between_paths > ao.cutter_diameter / 2:
layout.label(text="CAUTION: CUTTER ENGAGEMENT")
layout.label(text="GREATER THAN 50%")
layout.label(text="Cutter Engagement: " + str(round(100 * ao.dist_between_paths / ao.cutter_diameter, 1)) + "%")
from cam.ui_panels.buttons_panel import CAMButtonsPanel
from cam.ui_panels.info import CAM_INFO_Panel
from cam.ui_panels.operations import CAM_OPERATIONS_Panel
from cam.ui_panels.cutter import CAM_CUTTER_Panel
from cam.ui_panels.machine import CAM_MACHINE_Panel
from cam.ui_panels.material import CAM_MATERIAL_Panel
from cam.ui_panels.chains import CAM_UL_operations, CAM_UL_chains, CAM_CHAINS_Panel
from cam.ui_panels.op_properties import CAM_OPERATION_PROPERTIES_Panel
from cam.ui_panels.movement import CAM_MOVEMENT_Panel
class CAM_UL_orientations(UIList):
@ -69,222 +55,6 @@ class CAM_UL_orientations(UIList):
class CAM_OPERATION_PROPERTIES_Panel(CAMButtonsPanel, bpy.types.Panel):
"""CAM operation properties panel"""
bl_label = "CAM operation setup"
bl_idname = "WORLD_PT_CAM_OPERATION"
COMPAT_ENGINES = {'BLENDERCAM_RENDER'}
def draw(self, context):
layout = self.layout
scene = bpy.context.scene
use_experimental = bpy.context.preferences.addons['cam'].preferences.experimental
if len(scene.cam_operations) == 0:
layout.label(text='Add operation first')
if len(scene.cam_operations) > 0:
ao = scene.cam_operations[scene.cam_active_operation]
if ao.valid:
if use_experimental:
layout.prop(ao, 'machine_axes')
if ao.machine_axes == '3':
layout.prop(ao, 'strategy')
elif ao.machine_axes == '4':
layout.prop(ao, 'strategy4axis')
if ao.strategy4axis == 'INDEXED':
layout.prop(ao, 'strategy')
layout.prop(ao, 'rotary_axis_1')
elif ao.machine_axes == '5':
layout.prop(ao, 'strategy5axis')
if ao.strategy5axis == 'INDEXED':
layout.prop(ao, 'strategy')
layout.prop(ao, 'rotary_axis_1')
layout.prop(ao, 'rotary_axis_2')
if ao.strategy in ['BLOCK', 'SPIRAL', 'CIRCLES', 'OUTLINEFILL']:
layout.prop(ao, 'movement_insideout')
if ao.strategy in ['CUTOUT', 'CURVE']:
if ao.strategy == 'CUTOUT':
layout.prop(ao, 'cut_type')
layout.label(text="Overshoot works best with curve")
layout.label(text="having C remove doubles")
layout.prop(ao, 'straight')
layout.prop(ao, 'profile_start')
layout.label(text="Lead in / out not fully working")
layout.prop(ao, 'lead_in')
layout.prop(ao, 'lead_out')
layout.prop(ao, 'enable_A')
if ao.enable_A:
layout.prop(ao, 'rotation_A')
layout.prop(ao, 'A_along_x')
if ao.A_along_x:
layout.label(text='A || X - B || Y')
else:
layout.label(text='A || Y - B ||X')
layout.prop(ao, 'enable_B')
if ao.enable_B:
layout.prop(ao, 'rotation_B')
layout.prop(ao, 'outlines_count')
if ao.outlines_count > 1:
layout.prop(ao, 'dist_between_paths')
EngagementDisplay(ao, layout)
layout.prop(ao, 'movement_insideout')
layout.prop(ao, 'dont_merge')
elif ao.strategy == 'WATERLINE':
if ao.waterline_fill:
layout.label(text="Waterline roughing strategy")
layout.label(text="needs a skin margin")
layout.prop(ao, 'skin')
layout.prop(ao, 'dist_between_paths')
EngagementDisplay(ao, layout)
layout.prop(ao, 'stepdown')
layout.prop(ao, 'waterline_project')
elif ao.strategy == 'CARVE':
layout.prop(ao, 'carve_depth')
layout.prop(ao, 'dist_along_paths')
elif ao.strategy == 'MEDIAL_AXIS':
layout.prop(ao, 'medial_axis_threshold')
layout.prop(ao, 'medial_axis_subdivision')
layout.prop(ao, 'add_pocket_for_medial')
layout.prop(ao, 'add_mesh_for_medial')
elif ao.strategy == 'DRILL':
layout.prop(ao, 'drill_type')
layout.prop(ao, 'enable_A')
if ao.enable_A:
layout.prop(ao, 'rotation_A')
layout.prop(ao, 'A_along_x')
if ao.A_along_x:
layout.label(text='A || X - B || Y')
else:
layout.label(text='A || Y - B ||X')
layout.prop(ao, 'enable_B')
if ao.enable_B:
layout.prop(ao, 'rotation_B')
elif ao.strategy == 'POCKET':
layout.prop(ao, 'pocket_option')
layout.prop(ao, 'pocketToCurve')
layout.prop(ao, 'dist_between_paths')
EngagementDisplay(ao, layout)
layout.prop(ao, 'enable_A')
if ao.enable_A:
layout.prop(ao, 'rotation_A')
layout.prop(ao, 'A_along_x')
if ao.A_along_x:
layout.label(text='A || X - B || Y')
else:
layout.label(text='A || Y - B ||X')
layout.prop(ao, 'enable_B')
if ao.enable_B:
layout.prop(ao, 'rotation_B')
else:
layout.prop(ao, 'dist_between_paths')
EngagementDisplay(ao, layout)
layout.prop(ao, 'dist_along_paths')
if ao.strategy == 'PARALLEL' or ao.strategy == 'CROSS':
layout.prop(ao, 'parallel_angle')
layout.prop(ao, 'enable_A')
if ao.enable_A:
layout.prop(ao, 'rotation_A')
layout.prop(ao, 'A_along_x')
if ao.A_along_x:
layout.label(text='A || X - B || Y')
else:
layout.label(text='A || Y - B ||X')
layout.prop(ao, 'enable_B')
if ao.enable_B:
layout.prop(ao, 'rotation_B')
layout.prop(ao, 'inverse')
if ao.strategy not in ['POCKET', 'DRILL', 'CURVE', 'MEDIAL_AXIS']:
layout.prop(ao, 'use_bridges')
if ao.use_bridges:
layout.prop(ao, 'bridges_width')
layout.prop(ao, 'bridges_height')
layout.prop_search(ao, "bridges_collection_name", bpy.data, "collections")
layout.prop(ao, 'use_bridge_modifiers')
layout.operator("scene.cam_bridges_add", text="Autogenerate bridges")
layout.prop(ao, 'skin')
if ao.machine_axes == '3':
layout.prop(ao, 'array')
if ao.array:
layout.prop(ao, 'array_x_count')
layout.prop(ao, 'array_x_distance')
layout.prop(ao, 'array_y_count')
layout.prop(ao, 'array_y_distance')
class CAM_MOVEMENT_Panel(CAMButtonsPanel, bpy.types.Panel):
"""CAM movement panel"""
bl_label = "CAM movement"
bl_idname = "WORLD_PT_CAM_MOVEMENT"
COMPAT_ENGINES = {'BLENDERCAM_RENDER'}
def draw(self, context):
layout = self.layout
scene = bpy.context.scene
use_experimental = bpy.context.preferences.addons['cam'].preferences.experimental
if len(scene.cam_operations) == 0:
layout.label(text='Add operation first')
if len(scene.cam_operations) > 0:
ao = scene.cam_operations[scene.cam_active_operation]
if ao.valid:
layout.prop(ao, 'movement_type')
if ao.movement_type in ['BLOCK', 'SPIRAL', 'CIRCLES']:
layout.prop(ao, 'movement_insideout')
layout.prop(ao, 'spindle_rotation_direction')
layout.prop(ao, 'free_movement_height')
if ao.maxz > ao.free_movement_height:
layout.label(text='Depth start > Free movement')
layout.label(text='POSSIBLE COLLISION')
layout.prop(ao, 'useG64')
if ao.useG64:
layout.prop(ao, 'G64')
if ao.strategy == 'PARALLEL' or ao.strategy == 'CROSS':
if not ao.ramp:
layout.prop(ao, 'parallel_step_back')
if ao.strategy == 'CUTOUT' or ao.strategy == 'POCKET' or ao.strategy == 'MEDIAL_AXIS':
layout.prop(ao, 'first_down')
if ao.strategy == 'POCKET':
layout.prop(ao, 'helix_enter')
if ao.helix_enter:
layout.prop(ao, 'ramp_in_angle')
layout.prop(ao, 'helix_diameter')
layout.prop(ao, 'retract_tangential')
if ao.retract_tangential:
layout.prop(ao, 'retract_radius')
layout.prop(ao, 'retract_height')
layout.prop(ao, 'ramp')
if ao.ramp:
layout.prop(ao, 'ramp_in_angle')
layout.prop(ao, 'ramp_out')
if ao.ramp_out:
layout.prop(ao, 'ramp_out_angle')
layout.prop(ao, 'stay_low')
if ao.stay_low:
layout.prop(ao, 'merge_dist')
if ao.cutter_type != 'BALLCONE':
layout.prop(ao, 'protect_vertical')
if ao.protect_vertical:
layout.prop(ao, 'protect_vertical_limit')
class CAM_FEEDRATE_Panel(CAMButtonsPanel, bpy.types.Panel):
"""CAM feedrate panel"""
bl_label = "CAM feedrate"

Wyświetl plik

@ -1,3 +1,4 @@
import bpy
# Panel definitions
class CAMButtonsPanel:
@ -11,3 +12,26 @@ class CAMButtonsPanel:
def poll(cls, context):
rd = context.scene.render
return rd.engine in cls.COMPAT_ENGINES
def __init__(self):
self.scene = bpy.context.scene
def active_operation_index(self):
return(self.scene.cam_active_operation)
def active_operation(self):
self.scene = bpy.context.scene
active_op = None
try:
active_op = self.scene.cam_operations[self.active_operation_index()]
#active_op = self.scene.cam_operations[12]
except IndexError:
print(f"Invalid operation index {self.active_operation_index()}")
return(active_op)
def operations_count(self):
return(len(self.scene.cam_operations))
def has_operations(self):
return (self.operations_count() > 0)

Wyświetl plik

@ -10,6 +10,23 @@ class CAM_CUTTER_Panel(CAMButtonsPanel, bpy.types.Panel):
COMPAT_ENGINES = {'BLENDERCAM_RENDER'}
# Displays percentage of the cutter which is engaged with the material
# Displays a warning for engagements greater than 50%
def EngagementDisplay(self, operat, layout):
ao = operat
if ao.cutter_type == 'BALLCONE':
if ao.dist_between_paths > ao.ball_radius:
layout.label(text="CAUTION: CUTTER ENGAGEMENT")
layout.label(text="GREATER THAN 50%")
layout.label(text="Cutter engagement: " + str(round(100 * ao.dist_between_paths / ao.ball_radius, 1)) + "%")
else:
if ao.dist_between_paths > ao.cutter_diameter / 2:
layout.label(text="CAUTION: CUTTER ENGAGEMENT")
layout.label(text="GREATER THAN 50%")
layout.label(text="Cutter Engagement: " + str(round(100 * ao.dist_between_paths / ao.cutter_diameter, 1)) + "%")
def draw_header(self, context):
self.layout.menu("CAM_CUTTER_MT_presets", text="CAM Cutter")
@ -31,17 +48,17 @@ class CAM_CUTTER_Panel(CAMButtonsPanel, bpy.types.Panel):
layout.prop(ao, 'cutter_tip_angle')
if ao.cutter_type == 'BALLCONE':
layout.prop(ao, 'ball_radius')
EngagementDisplay(ao, layout)
self.EngagementDisplay(ao, layout)
layout.prop(ao, 'cutter_tip_angle')
layout.label(text='Cutter diameter = shank diameter')
if ao.cutter_type == 'CYLCONE':
layout.prop(ao, 'cylcone_diameter')
EngagementDisplay(ao, layout)
self.EngagementDisplay(ao, layout)
layout.prop(ao, 'cutter_tip_angle')
layout.label(text='Cutter diameter = shank diameter')
if ao.cutter_type == 'BULLNOSE':
layout.prop(ao, 'bull_corner_radius')
EngagementDisplay(ao, layout)
self.EngagementDisplay(ao, layout)
layout.label(text='Cutter diameter = shank diameter')
if ao.cutter_type == 'LASER':
@ -69,7 +86,7 @@ class CAM_CUTTER_Panel(CAMButtonsPanel, bpy.types.Panel):
layout.prop(ao, 'cutter_diameter')
if ao.strategy == "POCKET" or ao.strategy == "PARALLEL" or ao.strategy == "CROSS" \
or ao.strategy == "WATERLINE":
EngagementDisplay(ao, layout)
self.EngagementDisplay(ao, layout)
if ao.cutter_type != "LASER":
layout.prop(ao, 'cutter_flutes')
layout.prop(ao, 'cutter_description')

Wyświetl plik

@ -1,7 +1,7 @@
import bpy
import sys
import ocl
import bpy
from cam.simple import strInUnits
from cam.ui_panels.buttons_panel import CAMButtonsPanel
@ -17,11 +17,9 @@ class CAM_INFO_Panel(CAMButtonsPanel, bpy.types.Panel):
COMPAT_ENGINES = {'BLENDERCAM_RENDER'}
def draw(self, context):
self.scene = bpy.context.scene
self.draw_opencamlib_version()
if len(self.scene.cam_operations) > 0:
if self.has_operations():
self.draw_active_op_warnings()
self.draw_active_op_data()
self.draw_active_op_money_cost()
@ -30,18 +28,21 @@ class CAM_INFO_Panel(CAMButtonsPanel, bpy.types.Panel):
def draw_opencamlib_version(self):
if "ocl" in sys.modules:
self.layout.label(text = "Opencamlib v%s installed" % ocl.version())
self.layout.label(text = f"Opencamlib v{ocl.version()} installed")
else:
self.layout.label(text = "Opencamlib is not installed")
def draw_active_op_warnings(self):
active_op = self.scene.cam_operations[self.scene.cam_active_operation]
if active_op.warnings != '':
for line in active_op.warnings.rstrip("\n").split("\n"):
active_op = self.active_operation()
if active_op is None: return
for line in active_op.warnings.rstrip("\n").split("\n"):
if len(line) > 0 :
self.layout.label(text=line, icon='ERROR')
def draw_active_op_data(self):
active_op = self.scene.cam_operations[self.scene.cam_active_operation]
active_op = self.active_operation()
if active_op is None: return
if not active_op.valid: return
if not int(active_op.duration*60) > 0: return
@ -56,7 +57,8 @@ class CAM_INFO_Panel(CAMButtonsPanel, bpy.types.Panel):
self.layout.label(text="Chipload: %s/tooth" % strInUnits(active_op.chipload, 4))
def draw_active_op_money_cost(self):
active_op = self.scene.cam_operations[self.scene.cam_active_operation]
active_op = self.active_operation()
if active_op is None: return
if not active_op.valid: return
if not int(active_op.duration*60) > 0: return

Wyświetl plik

@ -0,0 +1,65 @@
import bpy
from cam.ui_panels.buttons_panel import CAMButtonsPanel
class CAM_MOVEMENT_Panel(CAMButtonsPanel, bpy.types.Panel):
"""CAM movement panel"""
bl_label = "CAM movement"
bl_idname = "WORLD_PT_CAM_MOVEMENT"
COMPAT_ENGINES = {'BLENDERCAM_RENDER'}
def draw(self, context):
layout = self.layout
scene = bpy.context.scene
use_experimental = bpy.context.preferences.addons['cam'].preferences.experimental
if len(scene.cam_operations) == 0:
layout.label(text='Add operation first')
if len(scene.cam_operations) > 0:
ao = scene.cam_operations[scene.cam_active_operation]
if ao.valid:
layout.prop(ao, 'movement_type')
if ao.movement_type in ['BLOCK', 'SPIRAL', 'CIRCLES']:
layout.prop(ao, 'movement_insideout')
layout.prop(ao, 'spindle_rotation_direction')
layout.prop(ao, 'free_movement_height')
if ao.maxz > ao.free_movement_height:
layout.label(text='Depth start > Free movement')
layout.label(text='POSSIBLE COLLISION')
layout.prop(ao, 'useG64')
if ao.useG64:
layout.prop(ao, 'G64')
if ao.strategy == 'PARALLEL' or ao.strategy == 'CROSS':
if not ao.ramp:
layout.prop(ao, 'parallel_step_back')
if ao.strategy == 'CUTOUT' or ao.strategy == 'POCKET' or ao.strategy == 'MEDIAL_AXIS':
layout.prop(ao, 'first_down')
if ao.strategy == 'POCKET':
layout.prop(ao, 'helix_enter')
if ao.helix_enter:
layout.prop(ao, 'ramp_in_angle')
layout.prop(ao, 'helix_diameter')
layout.prop(ao, 'retract_tangential')
if ao.retract_tangential:
layout.prop(ao, 'retract_radius')
layout.prop(ao, 'retract_height')
layout.prop(ao, 'ramp')
if ao.ramp:
layout.prop(ao, 'ramp_in_angle')
layout.prop(ao, 'ramp_out')
if ao.ramp_out:
layout.prop(ao, 'ramp_out_angle')
layout.prop(ao, 'stay_low')
if ao.stay_low:
layout.prop(ao, 'merge_dist')
if ao.cutter_type != 'BALLCONE':
layout.prop(ao, 'protect_vertical')
if ao.protect_vertical:
layout.prop(ao, 'protect_vertical_limit')

Wyświetl plik

@ -0,0 +1,175 @@
import bpy
from cam.ui_panels.buttons_panel import CAMButtonsPanel
class CAM_OPERATION_PROPERTIES_Panel(CAMButtonsPanel, bpy.types.Panel):
"""CAM operation properties panel"""
bl_label = "CAM operation setup"
bl_idname = "WORLD_PT_CAM_OPERATION"
COMPAT_ENGINES = {'BLENDERCAM_RENDER'}
# Displays percentage of the cutter which is engaged with the material
# Displays a warning for engagements greater than 50%
def EngagementDisplay(self, operat, layout):
ao = operat
if ao.cutter_type == 'BALLCONE':
if ao.dist_between_paths > ao.ball_radius:
layout.label(text="CAUTION: CUTTER ENGAGEMENT")
layout.label(text="GREATER THAN 50%")
layout.label(text="Cutter engagement: " + str(round(100 * ao.dist_between_paths / ao.ball_radius, 1)) + "%")
else:
if ao.dist_between_paths > ao.cutter_diameter / 2:
layout.label(text="CAUTION: CUTTER ENGAGEMENT")
layout.label(text="GREATER THAN 50%")
layout.label(text="Cutter Engagement: " + str(round(100 * ao.dist_between_paths / ao.cutter_diameter, 1)) + "%")
def draw(self, context):
layout = self.layout
scene = bpy.context.scene
use_experimental = bpy.context.preferences.addons['cam'].preferences.experimental
if len(scene.cam_operations) == 0:
layout.label(text='Add operation first')
if len(scene.cam_operations) > 0:
ao = scene.cam_operations[scene.cam_active_operation]
if ao.valid:
if use_experimental:
layout.prop(ao, 'machine_axes')
if ao.machine_axes == '3':
layout.prop(ao, 'strategy')
elif ao.machine_axes == '4':
layout.prop(ao, 'strategy4axis')
if ao.strategy4axis == 'INDEXED':
layout.prop(ao, 'strategy')
layout.prop(ao, 'rotary_axis_1')
elif ao.machine_axes == '5':
layout.prop(ao, 'strategy5axis')
if ao.strategy5axis == 'INDEXED':
layout.prop(ao, 'strategy')
layout.prop(ao, 'rotary_axis_1')
layout.prop(ao, 'rotary_axis_2')
if ao.strategy in ['BLOCK', 'SPIRAL', 'CIRCLES', 'OUTLINEFILL']:
layout.prop(ao, 'movement_insideout')
if ao.strategy in ['CUTOUT', 'CURVE']:
if ao.strategy == 'CUTOUT':
layout.prop(ao, 'cut_type')
layout.label(text="Overshoot works best with curve")
layout.label(text="having C remove doubles")
layout.prop(ao, 'straight')
layout.prop(ao, 'profile_start')
layout.label(text="Lead in / out not fully working")
layout.prop(ao, 'lead_in')
layout.prop(ao, 'lead_out')
layout.prop(ao, 'enable_A')
if ao.enable_A:
layout.prop(ao, 'rotation_A')
layout.prop(ao, 'A_along_x')
if ao.A_along_x:
layout.label(text='A || X - B || Y')
else:
layout.label(text='A || Y - B ||X')
layout.prop(ao, 'enable_B')
if ao.enable_B:
layout.prop(ao, 'rotation_B')
layout.prop(ao, 'outlines_count')
if ao.outlines_count > 1:
layout.prop(ao, 'dist_between_paths')
self.EngagementDisplay(ao, layout)
layout.prop(ao, 'movement_insideout')
layout.prop(ao, 'dont_merge')
elif ao.strategy == 'WATERLINE':
if ao.waterline_fill:
layout.label(text="Waterline roughing strategy")
layout.label(text="needs a skin margin")
layout.prop(ao, 'skin')
layout.prop(ao, 'dist_between_paths')
self.EngagementDisplay(ao, layout)
layout.prop(ao, 'stepdown')
layout.prop(ao, 'waterline_project')
elif ao.strategy == 'CARVE':
layout.prop(ao, 'carve_depth')
layout.prop(ao, 'dist_along_paths')
elif ao.strategy == 'MEDIAL_AXIS':
layout.prop(ao, 'medial_axis_threshold')
layout.prop(ao, 'medial_axis_subdivision')
layout.prop(ao, 'add_pocket_for_medial')
layout.prop(ao, 'add_mesh_for_medial')
elif ao.strategy == 'DRILL':
layout.prop(ao, 'drill_type')
layout.prop(ao, 'enable_A')
if ao.enable_A:
layout.prop(ao, 'rotation_A')
layout.prop(ao, 'A_along_x')
if ao.A_along_x:
layout.label(text='A || X - B || Y')
else:
layout.label(text='A || Y - B ||X')
layout.prop(ao, 'enable_B')
if ao.enable_B:
layout.prop(ao, 'rotation_B')
elif ao.strategy == 'POCKET':
layout.prop(ao, 'pocket_option')
layout.prop(ao, 'pocketToCurve')
layout.prop(ao, 'dist_between_paths')
self.EngagementDisplay(ao, layout)
layout.prop(ao, 'enable_A')
if ao.enable_A:
layout.prop(ao, 'rotation_A')
layout.prop(ao, 'A_along_x')
if ao.A_along_x:
layout.label(text='A || X - B || Y')
else:
layout.label(text='A || Y - B ||X')
layout.prop(ao, 'enable_B')
if ao.enable_B:
layout.prop(ao, 'rotation_B')
else:
layout.prop(ao, 'dist_between_paths')
self.EngagementDisplay(ao, layout)
layout.prop(ao, 'dist_along_paths')
if ao.strategy == 'PARALLEL' or ao.strategy == 'CROSS':
layout.prop(ao, 'parallel_angle')
layout.prop(ao, 'enable_A')
if ao.enable_A:
layout.prop(ao, 'rotation_A')
layout.prop(ao, 'A_along_x')
if ao.A_along_x:
layout.label(text='A || X - B || Y')
else:
layout.label(text='A || Y - B ||X')
layout.prop(ao, 'enable_B')
if ao.enable_B:
layout.prop(ao, 'rotation_B')
layout.prop(ao, 'inverse')
if ao.strategy not in ['POCKET', 'DRILL', 'CURVE', 'MEDIAL_AXIS']:
layout.prop(ao, 'use_bridges')
if ao.use_bridges:
layout.prop(ao, 'bridges_width')
layout.prop(ao, 'bridges_height')
layout.prop_search(ao, "bridges_collection_name", bpy.data, "collections")
layout.prop(ao, 'use_bridge_modifiers')
layout.operator("scene.cam_bridges_add", text="Autogenerate bridges")
layout.prop(ao, 'skin')
if ao.machine_axes == '3':
layout.prop(ao, 'array')
if ao.array:
layout.prop(ao, 'array_x_count')
layout.prop(ao, 'array_x_distance')
layout.prop(ao, 'array_y_count')
layout.prop(ao, 'array_y_distance')