kopia lustrzana https://github.com/vilemduha/blendercam
Remodeled display calculation, converted operations, working on op_properties
rodzic
b4643389e0
commit
e828a138f4
|
@ -9,26 +9,26 @@ class CAM_AREA_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
panel_interface_level = 0
|
||||
|
||||
prop_level = {
|
||||
'use_layers': 0,
|
||||
'maxz': 1,
|
||||
'minz': 1,
|
||||
'ambient': 1,
|
||||
'limit_curve': 1
|
||||
'draw_use_layers': 0,
|
||||
'draw_maxz': 1,
|
||||
'draw_minz': 1,
|
||||
'draw_ambient': 1,
|
||||
'draw_limit_curve': 1
|
||||
}
|
||||
|
||||
def draw_use_layers(self):
|
||||
if not self.has_correct_level('use_layers'): return
|
||||
if not self.has_correct_level(): return
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.op, 'use_layers')
|
||||
if self.op.use_layers:
|
||||
row.prop(self.op, 'stepdown')
|
||||
|
||||
def draw_maxz(self):
|
||||
if not self.has_correct_level('maxz'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'maxz')
|
||||
|
||||
def draw_minz(self):
|
||||
if not self.has_correct_level('minz'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.geometry_source in ['OBJECT', 'COLLECTION']:
|
||||
if self.op.strategy == 'CURVE':
|
||||
self.layout.label(text="cannot use depth from object using CURVES")
|
||||
|
@ -58,7 +58,7 @@ class CAM_AREA_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
col.prop(self.op, 'source_image_crop_end_y', text='end y')
|
||||
|
||||
def draw_ambient(self):
|
||||
if not self.has_correct_level('ambient'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.strategy in ['BLOCK', 'SPIRAL', 'CIRCLES', 'PARALLEL', 'CROSS']:
|
||||
self.layout.prop(self.op, 'ambient_behaviour')
|
||||
if self.op.ambient_behaviour == 'AROUND':
|
||||
|
@ -66,7 +66,7 @@ class CAM_AREA_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
self.layout.prop(self.op, "ambient_cutter_restrict")
|
||||
|
||||
def draw_limit_curve(self):
|
||||
if not self.has_correct_level('limit_curve'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.strategy in ['BLOCK', 'SPIRAL', 'CIRCLES', 'PARALLEL', 'CROSS']:
|
||||
self.layout.prop(self.op, 'use_limit_curve')
|
||||
if self.op.use_limit_curve:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import bpy
|
||||
import inspect
|
||||
|
||||
# Panel definitions
|
||||
class CAMButtonsPanel:
|
||||
|
@ -47,9 +48,13 @@ class CAMButtonsPanel:
|
|||
def has_operations(self):
|
||||
return (self.operations_count() > 0)
|
||||
|
||||
def has_correct_level(self, prop_name):
|
||||
def has_correct_level(self):
|
||||
if not hasattr(self, 'prop_level'):
|
||||
return True
|
||||
if not prop_name in self.prop_level:
|
||||
|
||||
caller_function = inspect.stack()[1][3]
|
||||
|
||||
if not caller_function in self.prop_level:
|
||||
return True
|
||||
return self.prop_level[prop_name] <= int(self.context.scene.interface.level)
|
||||
|
||||
return self.prop_level[caller_function] <= int(self.context.scene.interface.level)
|
||||
|
|
|
@ -38,8 +38,6 @@ class CAM_CHAINS_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
bl_idname = "WORLD_PT_CAM_CHAINS"
|
||||
panel_interface_level = 1
|
||||
|
||||
COMPAT_ENGINES = {'BLENDERCAM_RENDER'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
|
|
|
@ -10,60 +10,59 @@ class CAM_CUTTER_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
panel_interface_level = 0
|
||||
|
||||
prop_level = {
|
||||
'preset_menu': 1,
|
||||
'cutter_id': 2,
|
||||
'cutter_type': 0,
|
||||
'ball_radius': 0,
|
||||
'bull_radius': 0,
|
||||
'cylcone_diameter': 0,
|
||||
'tip_angle': 0,
|
||||
'laser': 0,
|
||||
'plasma': 0,
|
||||
'custom': 0,
|
||||
'diameter': 0,
|
||||
'flutes': 1,
|
||||
'description': 1,
|
||||
'engagement': 0
|
||||
'draw_cutter_preset_menu': 1,
|
||||
'draw_cutter_id': 2,
|
||||
'draw_cutter_type': 0,
|
||||
'draw_ball_radius': 0,
|
||||
'draw_bull_radius': 0,
|
||||
'draw_cylcone_diameter': 0,
|
||||
'draw_cutter_tip_angle': 0,
|
||||
'draw_laser': 0,
|
||||
'draw_plasma': 0,
|
||||
'draw_custom': 0,
|
||||
'draw_cutter_diameter': 0,
|
||||
'draw_cutter_flutes': 1,
|
||||
'draw_cutter_description': 1,
|
||||
'draw_engagement': 0
|
||||
}
|
||||
|
||||
|
||||
def draw_cutter_preset_menu(self):
|
||||
if not self.has_correct_level('preset_menu'): return
|
||||
if not self.has_correct_level(): return
|
||||
row = self.layout.row(align=True)
|
||||
row.menu("CAM_CUTTER_MT_presets", text=bpy.types.CAM_CUTTER_MT_presets.bl_label)
|
||||
row.operator("render.cam_preset_cutter_add", text="", icon='ADD')
|
||||
row.operator("render.cam_preset_cutter_add", text="", icon='REMOVE').remove_active = True
|
||||
|
||||
def draw_cutter_id(self):
|
||||
if not self.has_correct_level('cutter_id'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'cutter_id')
|
||||
|
||||
def draw_cutter_type(self):
|
||||
if not self.has_correct_level('cutter_type'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'cutter_type')
|
||||
|
||||
def draw_ball_radius(self):
|
||||
if not self.has_correct_level('ball_radius'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.cutter_type in ['BALLCONE']:
|
||||
self.layout.prop(self.op, 'ball_radius')
|
||||
|
||||
def draw_bull_radius(self):
|
||||
if not self.has_correct_level('bull_radius'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.cutter_type in ['BULLNOSE']:
|
||||
self.layout.prop(self.op, 'bull_corner_radius')
|
||||
|
||||
def draw_cylcone_diameter(self):
|
||||
if not self.has_correct_level('cylcone_diameter'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.cutter_type in ['CYLCONE']:
|
||||
self.layout.prop(self.op, 'cylcone_diameter')
|
||||
|
||||
def draw_cutter_tip_angle(self):
|
||||
if not self.has_correct_level('tip_angle'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.cutter_type in ['VCARVE', 'BALLCONE', 'BULLNOSE', 'CYLCONE']:
|
||||
self.layout.prop(self.op, 'cutter_tip_angle')
|
||||
|
||||
def draw_laser(self):
|
||||
if not self.has_correct_level('laser'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.cutter_type in ['LASER']:
|
||||
self.layout.prop(self.op, 'Laser_on')
|
||||
self.layout.prop(self.op, 'Laser_off')
|
||||
|
@ -71,7 +70,7 @@ class CAM_CUTTER_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
self.layout.prop(self.op, 'Laser_delay')
|
||||
|
||||
def draw_plasma(self):
|
||||
if not self.has_correct_level('plasma'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.cutter_type in ['PLASMA']:
|
||||
self.layout.prop(self.op, 'Plasma_on')
|
||||
self.layout.prop(self.op, 'Plasma_off')
|
||||
|
@ -81,7 +80,7 @@ class CAM_CUTTER_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
self.layout.prop(self.op, 'lead_out')
|
||||
|
||||
def draw_custom(self):
|
||||
if not self.has_correct_level('custom'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.cutter_type in ['CUSTOM']:
|
||||
if self.op.optimisation.use_exact:
|
||||
self.layout.label(text='Warning - only convex shapes are supported. ', icon='COLOR_RED')
|
||||
|
@ -90,20 +89,20 @@ class CAM_CUTTER_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
self.layout.prop_search(self.op, "cutter_object_name", bpy.data, "objects")
|
||||
|
||||
def draw_cutter_diameter(self):
|
||||
if not self.has_correct_level('diameter'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'cutter_diameter')
|
||||
|
||||
def draw_cutter_flutes(self):
|
||||
if not self.has_correct_level('flutes'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.cutter_type not in ['LASER', 'PLASMA']:
|
||||
self.layout.prop(self.op, 'cutter_flutes')
|
||||
|
||||
def draw_cutter_description(self):
|
||||
if not self.has_correct_level('description'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'cutter_description')
|
||||
|
||||
def draw_engagement(self):
|
||||
if not self.has_correct_level('engagement'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.cutter_type in ['LASER', 'PLASMA']: return
|
||||
if self.op.strategy in ['CUTOUT']: return
|
||||
|
||||
|
|
|
@ -8,31 +8,31 @@ class CAM_FEEDRATE_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
panel_interface_level = 0
|
||||
|
||||
prop_level = {
|
||||
'feedrate': 0,
|
||||
'sim_feedrate': 2,
|
||||
'plunge_feedrate': 1,
|
||||
'plunge_angle': 1,
|
||||
'spindle_rpm': 0
|
||||
'draw_feedrate': 0,
|
||||
'draw_sim_feedrate': 2,
|
||||
'draw_plunge_feedrate': 1,
|
||||
'draw_plunge_angle': 1,
|
||||
'draw_spindle_rpm': 0
|
||||
}
|
||||
|
||||
def draw_feedrate(self):
|
||||
if not self.has_correct_level('feedrate'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'feedrate')
|
||||
|
||||
def draw_sim_feedrate(self):
|
||||
if not self.has_correct_level('sim_feedrate'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'do_simulation_feedrate')
|
||||
|
||||
def draw_plunge_feedrate(self):
|
||||
if not self.has_correct_level('plunge_feedrate'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'plunge_feedrate')
|
||||
|
||||
def draw_plunge_angle(self):
|
||||
if not self.has_correct_level('plunge_angle'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'plunge_angle')
|
||||
|
||||
def draw_spindle_rpm(self):
|
||||
if not self.has_correct_level('spindle_rpm'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'spindle_rpm')
|
||||
|
||||
def draw(self, context):
|
||||
|
|
|
@ -10,41 +10,41 @@ class CAM_GCODE_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
panel_interface_level = 1
|
||||
|
||||
prop_level = {
|
||||
'output_header': 1,
|
||||
'output_trailer': 1,
|
||||
'enable_dust': 1,
|
||||
'enable_hold': 1,
|
||||
'enable_mist': 1
|
||||
'draw_output_header': 1,
|
||||
'draw_output_trailer': 1,
|
||||
'draw_enable_dust': 1,
|
||||
'draw_enable_hold': 1,
|
||||
'draw_enable_mist': 1
|
||||
}
|
||||
|
||||
def draw_output_header(self):
|
||||
if not self.has_correct_level('output_header'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'output_header')
|
||||
if self.op.output_header:
|
||||
self.layout.prop(self.op, 'gcode_header')
|
||||
|
||||
def draw_output_trailer(self):
|
||||
if not self.has_correct_level('output_trailer'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'output_trailer')
|
||||
if self.op.output_trailer:
|
||||
self.layout.prop(self.op, 'gcode_trailer')
|
||||
|
||||
def draw_enable_dust(self):
|
||||
if not self.has_correct_level('enable_dust'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'enable_dust')
|
||||
if self.op.enable_dust:
|
||||
self.layout.prop(self.op, 'gcode_start_dust_cmd')
|
||||
self.layout.prop(self.op, 'gcode_stop_dust_cmd')
|
||||
|
||||
def draw_enable_hold(self):
|
||||
if not self.has_correct_level('enable_hold'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'enable_hold')
|
||||
if self.op.enable_hold:
|
||||
self.layout.prop(self.op, 'gcode_start_hold_cmd')
|
||||
self.layout.prop(self.op, 'gcode_stop_hold_cmd')
|
||||
|
||||
def draw_enable_mist(self):
|
||||
if not self.has_correct_level('enable_mist'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'enable_mist')
|
||||
if self.op.enable_mist:
|
||||
self.layout.prop(self.op, 'gcode_start_mist_cmd')
|
||||
|
|
|
@ -33,16 +33,16 @@ class CAM_INFO_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
panel_interface_level = 0
|
||||
|
||||
prop_level = {
|
||||
'opencamlib_version': 1,
|
||||
'warnings': 0,
|
||||
'time': 0,
|
||||
'chipload': 0,
|
||||
'money_cost': 1
|
||||
'draw_opencamlib_version': 1,
|
||||
'draw_op_warnings': 0,
|
||||
'draw_op_time': 0,
|
||||
'draw_op_chipload': 0,
|
||||
'draw_op_money_cost': 1
|
||||
}
|
||||
|
||||
# Display the OpenCamLib version
|
||||
def draw_opencamlib_version(self):
|
||||
if not self.has_correct_level('opencamlib_version'): return
|
||||
if not self.has_correct_level(): return
|
||||
opencamlib_version = cam.utils.opencamlib_version()
|
||||
if opencamlib_version is None:
|
||||
self.layout.label(text="Opencamlib is not installed")
|
||||
|
@ -52,14 +52,14 @@ class CAM_INFO_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
|
||||
# Display warnings related to the current operation
|
||||
def draw_op_warnings(self):
|
||||
if not self.has_correct_level('warnings'): return
|
||||
if not self.has_correct_level(): return
|
||||
for line in self.op.info.warnings.rstrip("\n").split("\n"):
|
||||
if len(line) > 0:
|
||||
self.layout.label(text=line, icon='ERROR')
|
||||
|
||||
# Display the time estimation for the current operation
|
||||
def draw_op_time(self):
|
||||
if not self.has_correct_level('time'): return
|
||||
if not self.has_correct_level(): return
|
||||
if not int(self.op.info.duration * 60) > 0:
|
||||
return
|
||||
|
||||
|
@ -74,7 +74,7 @@ class CAM_INFO_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
|
||||
# Display the chipload (does this work ?)
|
||||
def draw_op_chipload(self):
|
||||
if not self.has_correct_level('chipload'): return
|
||||
if not self.has_correct_level(): return
|
||||
if not self.op.info.chipload > 0:
|
||||
return
|
||||
|
||||
|
@ -83,7 +83,7 @@ class CAM_INFO_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
|
||||
# Display the current operation money cost
|
||||
def draw_op_money_cost(self):
|
||||
if not self.has_correct_level('money_cost'): return
|
||||
if not self.has_correct_level(): return
|
||||
if not int(self.op.info.duration * 60) > 0:
|
||||
return
|
||||
|
||||
|
|
|
@ -4,62 +4,116 @@ from cam.ui_panels.buttons_panel import CAMButtonsPanel
|
|||
|
||||
class CAM_MACHINE_Panel(CAMButtonsPanel, bpy.types.Panel):
|
||||
"""CAM machine panel"""
|
||||
bl_label = " "
|
||||
bl_label = "CAM Machine"
|
||||
bl_idname = "WORLD_PT_CAM_MACHINE"
|
||||
always_show_panel = True
|
||||
panel_interface_level = 0
|
||||
|
||||
COMPAT_ENGINES = {'BLENDERCAM_RENDER'}
|
||||
prop_level = {
|
||||
'draw_presets': 1,
|
||||
'draw_post_processor': 0,
|
||||
'draw_split_files': 2,
|
||||
'draw_system': 1,
|
||||
'draw_position_definitions': 2,
|
||||
'draw_working_area': 2,
|
||||
'draw_feedrates': 2,
|
||||
'draw_splindle_speeds': 2,
|
||||
'draw_tool_options': 2,
|
||||
'draw_suplemental_axis': 2,
|
||||
'draw_collet_size': 2,
|
||||
'draw_block_numbers': 2,
|
||||
'draw_hourly_rate': 2
|
||||
}
|
||||
|
||||
def draw_header(self, context):
|
||||
self.layout.menu("CAM_MACHINE_MT_presets", text="CAM Machine")
|
||||
def draw_presets(self):
|
||||
if not self.has_correct_level(): return
|
||||
row = self.layout.row(align=True)
|
||||
row.menu("CAM_MACHINE_MT_presets", text=bpy.types.CAM_MACHINE_MT_presets.bl_label)
|
||||
row.operator("render.cam_preset_machine_add", text="", icon='ADD')
|
||||
row.operator("render.cam_preset_machine_add", text="", icon='REMOVE').remove_active = True
|
||||
|
||||
def draw_post_processor(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.machine, 'post_processor')
|
||||
|
||||
def draw_split_files(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.machine, 'eval_splitting')
|
||||
if self.machine.eval_splitting:
|
||||
self.layout.prop(self.machine, 'split_limit')
|
||||
|
||||
def draw_system(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(bpy.context.scene.unit_settings, 'system')
|
||||
|
||||
def draw_position_definitions(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.machine, 'use_position_definitions')
|
||||
if self.machine.use_position_definitions:
|
||||
self.layout.prop(self.machine, 'starting_position')
|
||||
self.layout.prop(self.machine, 'mtc_position')
|
||||
self.layout.prop(self.machine, 'ending_position')
|
||||
|
||||
def draw_working_area(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.machine, 'working_area')
|
||||
|
||||
def draw_feedrates(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.machine, 'feedrate_min')
|
||||
self.layout.prop(self.machine, 'feedrate_max')
|
||||
self.layout.prop(self.machine, 'feedrate_default')
|
||||
|
||||
def draw_splindle_speeds(self):
|
||||
if not self.has_correct_level(): return
|
||||
# TODO: spindle default and feedrate default should become part of the cutter definition...
|
||||
self.layout.prop(self.machine, 'spindle_min')
|
||||
self.layout.prop(self.machine, 'spindle_max')
|
||||
self.layout.prop(self.machine, 'spindle_start_time')
|
||||
self.layout.prop(self.machine, 'spindle_default')
|
||||
|
||||
def draw_tool_options(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.machine, 'output_tool_definitions')
|
||||
self.layout.prop(self.machine, 'output_tool_change')
|
||||
if self.machine.output_tool_change:
|
||||
self.layout.prop(self.machine, 'output_g43_on_tool_change')
|
||||
|
||||
def draw_suplemental_axis(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.machine, 'axis4')
|
||||
self.layout.prop(self.machine, 'axis5')
|
||||
|
||||
def draw_collet_size(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.machine, 'collet_size')
|
||||
|
||||
def draw_block_numbers(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.machine, 'output_block_numbers')
|
||||
if self.machine.output_block_numbers:
|
||||
self.layout.prop(self.machine, 'start_block_number')
|
||||
self.layout.prop(self.machine, 'block_number_increment')
|
||||
|
||||
def draw_hourly_rate(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.machine, 'hourly_rate')
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
s = bpy.context.scene
|
||||
us = s.unit_settings
|
||||
self.context = context
|
||||
self.machine = bpy.context.scene.cam_machine
|
||||
|
||||
ao = s.cam_machine
|
||||
self.draw_presets()
|
||||
self.draw_post_processor()
|
||||
self.draw_split_files()
|
||||
self.draw_system()
|
||||
self.draw_position_definitions()
|
||||
self.draw_working_area()
|
||||
self.draw_feedrates()
|
||||
self.draw_splindle_speeds()
|
||||
self.draw_tool_options()
|
||||
self.draw_suplemental_axis()
|
||||
self.draw_collet_size()
|
||||
self.draw_block_numbers()
|
||||
self.draw_hourly_rate()
|
||||
|
||||
if ao:
|
||||
# machine preset
|
||||
row = layout.row(align=True)
|
||||
row.menu("CAM_MACHINE_MT_presets", text=bpy.types.CAM_MACHINE_MT_presets.bl_label)
|
||||
row.operator("render.cam_preset_machine_add", text="", icon='ADD')
|
||||
row.operator("render.cam_preset_machine_add", text="", icon='REMOVE').remove_active = True
|
||||
layout.prop(ao, 'post_processor')
|
||||
layout.prop(ao, 'eval_splitting')
|
||||
if ao.eval_splitting:
|
||||
layout.prop(ao, 'split_limit')
|
||||
|
||||
layout.prop(us, 'system')
|
||||
|
||||
layout.prop(ao, 'use_position_definitions')
|
||||
if ao.use_position_definitions:
|
||||
layout.prop(ao, 'starting_position')
|
||||
layout.prop(ao, 'mtc_position')
|
||||
layout.prop(ao, 'ending_position')
|
||||
layout.prop(ao, 'working_area')
|
||||
layout.prop(ao, 'feedrate_min')
|
||||
layout.prop(ao, 'feedrate_max')
|
||||
layout.prop(ao, 'feedrate_default')
|
||||
# TODO: spindle default and feedrate default should become part of the cutter definition...
|
||||
layout.prop(ao, 'spindle_min')
|
||||
layout.prop(ao, 'spindle_max')
|
||||
layout.prop(ao, 'spindle_start_time')
|
||||
layout.prop(ao, 'spindle_default')
|
||||
layout.prop(ao, 'output_tool_definitions')
|
||||
layout.prop(ao, 'output_tool_change')
|
||||
if ao.output_tool_change:
|
||||
layout.prop(ao, 'output_g43_on_tool_change')
|
||||
|
||||
if self.use_experimental:
|
||||
layout.prop(ao, 'axis4')
|
||||
layout.prop(ao, 'axis5')
|
||||
layout.prop(ao, 'collet_size')
|
||||
|
||||
layout.prop(ao, 'output_block_numbers')
|
||||
if ao.output_block_numbers:
|
||||
layout.prop(ao, 'start_block_number')
|
||||
layout.prop(ao, 'block_number_increment')
|
||||
layout.prop(ao, 'hourly_rate')
|
||||
|
|
|
@ -85,31 +85,31 @@ class CAM_MATERIAL_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
panel_interface_level = 0
|
||||
|
||||
prop_level = {
|
||||
'estimate_from_model': 0,
|
||||
'radius_around_model': 1,
|
||||
'position_object': 0
|
||||
'draw_estimate_from_image': 0,
|
||||
'draw_estimate_from_object': 1,
|
||||
'draw_axis_alignment': 0
|
||||
}
|
||||
|
||||
def draw_estimate_from_image(self):
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.geometry_source not in ['OBJECT', 'COLLECTION']:
|
||||
self.layout.label(text='Estimated from image')
|
||||
|
||||
def draw_estimate_from_object(self):
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.geometry_source in ['OBJECT', 'COLLECTION']:
|
||||
if not self.has_correct_level('estimate_from_model'): return
|
||||
self.layout.prop(self.op.material, 'estimate_from_model')
|
||||
if self.op.material.estimate_from_model:
|
||||
row_radius = self.layout.row()
|
||||
if self.has_correct_level('radius_around_model'):
|
||||
row_radius.label(text="Additional radius")
|
||||
row_radius.prop(self.op.material, 'radius_around_model', text='')
|
||||
row_radius.label(text="Additional radius")
|
||||
row_radius.prop(self.op.material, 'radius_around_model', text='')
|
||||
else:
|
||||
self.layout.prop(self.op.material, 'origin')
|
||||
self.layout.prop(self.op.material, 'size')
|
||||
|
||||
# Display Axis alignment section
|
||||
def draw_axis_alignment(self):
|
||||
if not self.has_correct_level('position_object'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.geometry_source in ['OBJECT', 'COLLECTION']:
|
||||
row_axis = self.layout.row()
|
||||
row_axis.prop(self.op.material, 'center_x')
|
||||
|
@ -120,9 +120,6 @@ class CAM_MATERIAL_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
def draw(self, context):
|
||||
self.context = context
|
||||
|
||||
if self.op is None:
|
||||
return
|
||||
|
||||
# FIXME: This function displays the progression of a job with a progress bar
|
||||
# Commenting because it makes no sense here
|
||||
# Consider removing it entirely
|
||||
|
|
|
@ -111,50 +111,50 @@ class CAM_MOVEMENT_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
panel_interface_level = 0
|
||||
|
||||
prop_level = {
|
||||
'type': 1,
|
||||
'spindle_rotation': 2,
|
||||
'free_height': 0,
|
||||
'useG64': 2,
|
||||
'parallel_step_back': 1,
|
||||
'first_down': 1,
|
||||
'helix_enter': 2,
|
||||
'ramp': 1,
|
||||
'retract_tangential': 2,
|
||||
'stay_low': 1,
|
||||
'protect_vertical': 1
|
||||
'draw_cut_type': 1,
|
||||
'draw_spindle_rotation': 2,
|
||||
'draw_free_height': 0,
|
||||
'draw_use_g64': 2,
|
||||
'draw_parallel_stepback': 1,
|
||||
'draw_first_down': 1,
|
||||
'draw_helix_enter': 2,
|
||||
'draw_ramp': 1,
|
||||
'draw_retract_tangential': 2,
|
||||
'draw_stay_low': 1,
|
||||
'draw_protect_vertical': 1
|
||||
}
|
||||
|
||||
def draw_cut_type(self):
|
||||
if not self.has_correct_level('type'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op.movement, 'type')
|
||||
if self.op.movement.type in ['BLOCK', 'SPIRAL', 'CIRCLES']:
|
||||
self.layout.prop(self.op.movement, 'insideout')
|
||||
|
||||
def draw_spindle_rotation(self):
|
||||
if not self.has_correct_level('spindle_rotation'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op.movement, 'spindle_rotation')
|
||||
|
||||
def draw_free_height(self):
|
||||
if not self.has_correct_level('free_height'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op.movement, 'free_height')
|
||||
if self.op.maxz > self.op.movement.free_height:
|
||||
self.layout.label(text='Depth start > Free movement')
|
||||
self.layout.label(text='POSSIBLE COLLISION')
|
||||
|
||||
def draw_use_g64(self):
|
||||
if not self.has_correct_level('useG64'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op.movement, 'useG64')
|
||||
if self.op.movement.useG64:
|
||||
self.layout.prop(self.op.movement, 'G64')
|
||||
|
||||
def draw_parallel_stepback(self):
|
||||
if not self.has_correct_level('parallel_step_back'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.strategy in ['PARALLEL','CROSS']:
|
||||
if not self.op.movement.ramp:
|
||||
self.layout.prop(self.op.movement, 'parallel_step_back')
|
||||
|
||||
def draw_helix_enter(self):
|
||||
if not self.has_correct_level('helix_enter'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.strategy in ['POCKET']:
|
||||
self.layout.prop(self.op.movement, 'helix_enter')
|
||||
if self.op.movement.helix_enter:
|
||||
|
@ -162,12 +162,12 @@ class CAM_MOVEMENT_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
self.layout.prop(self.op.movement, 'helix_diameter')
|
||||
|
||||
def draw_first_down(self):
|
||||
if not self.has_correct_level('first_down'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.strategy in ['CUTOUT','POCKET','MEDIAL_AXIS']:
|
||||
self.layout.prop(self.op.movement, 'first_down')
|
||||
|
||||
def draw_ramp(self):
|
||||
if not self.has_correct_level('ramp'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op.movement, 'ramp')
|
||||
if self.op.movement.ramp:
|
||||
self.layout.prop(self.op.movement, 'ramp_in_angle')
|
||||
|
@ -176,7 +176,7 @@ class CAM_MOVEMENT_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
self.layout.prop(self.movement, 'ramp_out_angle')
|
||||
|
||||
def draw_retract_tangential(self):
|
||||
if not self.has_correct_level('retract_tangential'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.strategy in ['POCKET']:
|
||||
self.layout.prop(self.op.movement, 'retract_tangential')
|
||||
if self.op.movement.retract_tangential:
|
||||
|
@ -184,13 +184,13 @@ class CAM_MOVEMENT_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
self.layout.prop(self.op.movement, 'retract_height')
|
||||
|
||||
def draw_stay_low(self):
|
||||
if not self.has_correct_level('stay_low'): return
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op.movement, 'stay_low')
|
||||
if self.op.movement.stay_low:
|
||||
self.layout.prop(self.op.movement, 'merge_dist')
|
||||
|
||||
def draw_protect_vertical(self):
|
||||
if not self.has_correct_level('protect_vertical'): return
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.cutter_type not in ['BALLCONE']:
|
||||
self.layout.prop(self.op.movement, 'protect_vertical')
|
||||
if self.op.movement.protect_vertical:
|
||||
|
@ -199,9 +199,6 @@ class CAM_MOVEMENT_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
def draw(self, context):
|
||||
self.context = context
|
||||
|
||||
if not self.op.valid:
|
||||
return
|
||||
|
||||
self.draw_cut_type()
|
||||
self.draw_spindle_rotation()
|
||||
self.draw_free_height()
|
||||
|
|
|
@ -9,169 +9,179 @@ class CAM_OPERATION_PROPERTIES_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
bl_idname = "WORLD_PT_CAM_OPERATION"
|
||||
panel_interface_level = 0
|
||||
|
||||
COMPAT_ENGINES = {'BLENDERCAM_RENDER'}
|
||||
prop_level = {
|
||||
'draw_cutter_engagement': 0,
|
||||
'draw_machine_axis': 2,
|
||||
'draw_strategy': 0
|
||||
}
|
||||
|
||||
|
||||
# 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
|
||||
def draw_cutter_engagement(self):
|
||||
if not self.has_correct_level(): return
|
||||
|
||||
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)) + "%")
|
||||
if self.op.cutter_type in ['BALLCONE']:
|
||||
engagement = round(100 * self.op.dist_between_paths / self.op.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)) + "%")
|
||||
engagement = round(100 * self.op.dist_between_paths / self.op.cutter_diameter, 1)
|
||||
|
||||
if engagement > 50:
|
||||
self.layout.label(text="Warning: High cutter engagement")
|
||||
|
||||
self.layout.label(text=f"Cutter engagement: {engagement}%")
|
||||
|
||||
def draw_machine_axis(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'machine_axes')
|
||||
|
||||
def draw_strategy(self):
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.machine_axes == '4':
|
||||
self.layout.prop(self.op, 'strategy4axis')
|
||||
if self.op.strategy4axis == 'INDEXED':
|
||||
self.layout.prop(self.op, 'strategy')
|
||||
self.layout.prop(self.op, 'rotary_axis_1')
|
||||
elif self.op.machine_axes == '5':
|
||||
self.layout.prop(self.op, 'strategy5axis')
|
||||
if self.op.strategy5axis == 'INDEXED':
|
||||
self.layout.prop(self.op, 'strategy')
|
||||
self.layout.prop(self.op, 'rotary_axis_1')
|
||||
self.layout.prop(self.op, 'rotary_axis_2')
|
||||
else:
|
||||
self.layout.prop(self.op, 'strategy')
|
||||
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
scene = bpy.context.scene
|
||||
self.context = context
|
||||
|
||||
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 self.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')
|
||||
self.draw_machine_axis()
|
||||
self.draw_strategy()
|
||||
|
||||
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')
|
||||
if self.op.strategy in ['BLOCK', 'SPIRAL', 'CIRCLES', 'OUTLINEFILL']:
|
||||
self.layout.prop(self.op.movement, 'insideout')
|
||||
|
||||
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')
|
||||
if self.op.strategy in ['CUTOUT', 'CURVE']:
|
||||
if self.op.strategy == 'CUTOUT':
|
||||
self.layout.prop(self.op, 'cut_type')
|
||||
self.layout.label(text="Overshoot works best with curve")
|
||||
self.layout.label(text="having C remove doubles")
|
||||
self.layout.prop(self.op, 'straight')
|
||||
self.layout.prop(self.op, 'profile_start')
|
||||
self.layout.label(text="Lead in / out not fully working")
|
||||
self.layout.prop(self.op, 'lead_in')
|
||||
self.layout.prop(self.op, 'lead_out')
|
||||
|
||||
elif ao.strategy == 'WATERLINE':
|
||||
layout.label(text="OCL doesn't support fill areas")
|
||||
if not ao.optimisation.use_opencamlib:
|
||||
layout.prop(ao, 'slice_detail')
|
||||
layout.prop(ao, 'waterline_fill')
|
||||
if ao.waterline_fill:
|
||||
layout.prop(ao, 'dist_between_paths')
|
||||
self.EngagementDisplay(ao, layout)
|
||||
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')
|
||||
self.layout.prop(self.op, 'enable_A')
|
||||
if self.op.enable_A:
|
||||
self.layout.prop(self.op, 'rotation_A')
|
||||
self.layout.prop(self.op, 'A_along_x')
|
||||
if self.op.A_along_x:
|
||||
self.layout.label(text='A || X - B || Y')
|
||||
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')
|
||||
self.layout.label(text='A || Y - B ||X')
|
||||
|
||||
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')
|
||||
self.layout.prop(self.op, 'enable_B')
|
||||
if self.op.enable_B:
|
||||
self.layout.prop(self.op, 'rotation_B')
|
||||
|
||||
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")
|
||||
if ao.strategy == 'WATERLINE':
|
||||
layout.label(text="Waterline roughing strategy")
|
||||
layout.label(text="needs a skin margin")
|
||||
layout.prop(ao, 'skin')
|
||||
self.layout.prop(self.op, 'outlines_count')
|
||||
if self.op.outlines_count > 1:
|
||||
self.layout.prop(self.op, 'dist_between_paths')
|
||||
self.draw_cutter_engagement()
|
||||
self.layout.prop(self.op.movement, 'insideout')
|
||||
self.layout.prop(self.op, 'dont_merge')
|
||||
|
||||
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')
|
||||
elif self.op.strategy == 'WATERLINE':
|
||||
self.layout.label(text="OCL doesn't support fill areas")
|
||||
if not self.op.optimisation.use_opencamlib:
|
||||
self.layout.prop(self.op, 'slice_detail')
|
||||
self.layout.prop(self.op, 'waterline_fill')
|
||||
if self.op.waterline_fill:
|
||||
self.layout.prop(self.op, 'dist_between_paths')
|
||||
self.draw_cutter_engagement()
|
||||
self.layout.prop(self.op, 'waterline_project')
|
||||
|
||||
elif self.op.strategy == 'CARVE':
|
||||
self.layout.prop(self.op, 'carve_depth')
|
||||
self.layout.prop(self.op, 'dist_along_paths')
|
||||
elif self.op.strategy == 'MEDIAL_AXIS':
|
||||
self.layout.prop(self.op, 'medial_axis_threshold')
|
||||
self.layout.prop(self.op, 'medial_axis_subdivision')
|
||||
self.layout.prop(self.op, 'add_pocket_for_medial')
|
||||
self.layout.prop(self.op, 'add_mesh_for_medial')
|
||||
elif self.op.strategy == 'DRILL':
|
||||
self.layout.prop(self.op, 'drill_type')
|
||||
self.layout.prop(self.op, 'enable_A')
|
||||
if self.op.enable_A:
|
||||
self.layout.prop(self.op, 'rotation_A')
|
||||
self.layout.prop(self.op, 'A_along_x')
|
||||
if self.op.A_along_x:
|
||||
self.layout.label(text='A || X - B || Y')
|
||||
else:
|
||||
self.layout.label(text='A || Y - B ||X')
|
||||
self.layout.prop(self.op, 'enable_B')
|
||||
if self.op.enable_B:
|
||||
self.layout.prop(self.op, 'rotation_B')
|
||||
|
||||
elif self.op.strategy == 'POCKET':
|
||||
self.layout.prop(self.op, 'pocket_option')
|
||||
self.layout.prop(self.op, 'pocketToCurve')
|
||||
self.layout.prop(self.op, 'dist_between_paths')
|
||||
self.draw_cutter_engagement()
|
||||
self.layout.prop(self.op, 'enable_A')
|
||||
if self.op.enable_A:
|
||||
self.layout.prop(self.op, 'rotation_A')
|
||||
self.layout.prop(self.op, 'A_along_x')
|
||||
if self.op.A_along_x:
|
||||
self.layout.label(text='A || X - B || Y')
|
||||
else:
|
||||
self.layout.label(text='A || Y - B ||X')
|
||||
self.layout.prop(self.op, 'enable_B')
|
||||
if self.op.enable_B:
|
||||
self.layout.prop(self.op, 'rotation_B')
|
||||
else:
|
||||
self.layout.prop(self.op, 'dist_between_paths')
|
||||
self.draw_cutter_engagement()
|
||||
self.layout.prop(self.op, 'dist_along_paths')
|
||||
if self.op.strategy == 'PARALLEL' or self.op.strategy == 'CROSS':
|
||||
self.layout.prop(self.op, 'parallel_angle')
|
||||
self.layout.prop(self.op, 'enable_A')
|
||||
if self.op.enable_A:
|
||||
self.layout.prop(self.op, 'rotation_A')
|
||||
self.layout.prop(self.op, 'A_along_x')
|
||||
if self.op.A_along_x:
|
||||
self.layout.label(text='A || X - B || Y')
|
||||
else:
|
||||
self.layout.label(text='A || Y - B ||X')
|
||||
self.layout.prop(self.op, 'enable_B')
|
||||
if self.op.enable_B:
|
||||
self.layout.prop(self.op, 'rotation_B')
|
||||
|
||||
self.layout.prop(self.op, 'inverse')
|
||||
|
||||
if self.op.strategy not in ['POCKET', 'DRILL', 'CURVE', 'MEDIAL_AXIS']:
|
||||
self.layout.prop(self.op, 'use_bridges')
|
||||
if self.op.use_bridges:
|
||||
self.layout.prop(self.op, 'bridges_width')
|
||||
self.layout.prop(self.op, 'bridges_height')
|
||||
|
||||
self.layout.prop_search(self.op, "bridges_collection_name", bpy.data, "collections")
|
||||
self.layout.prop(self.op, 'use_bridge_modifiers')
|
||||
self.layout.operator("scene.cam_bridges_add", text="Autogenerate bridges")
|
||||
|
||||
if self.op.strategy == 'WATERLINE':
|
||||
self.layout.label(text="Waterline roughing strategy")
|
||||
self.layout.label(text="needs a skin margin")
|
||||
self.layout.prop(self.op, 'skin')
|
||||
|
||||
if self.op.machine_axes == '3':
|
||||
self.layout.prop(self.op, 'array')
|
||||
if self.op.array:
|
||||
self.layout.prop(self.op, 'array_x_count')
|
||||
self.layout.prop(self.op, 'array_x_distance')
|
||||
self.layout.prop(self.op, 'array_y_count')
|
||||
self.layout.prop(self.op, 'array_y_distance')
|
||||
|
|
|
@ -18,25 +18,20 @@ class CAM_OPERATIONS_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
always_show_panel = True
|
||||
panel_interface_level = 0
|
||||
|
||||
# Main draw function
|
||||
def draw(self, context):
|
||||
self.draw_operations_list()
|
||||
if (not self.has_operations()): return
|
||||
if self.op is None: return
|
||||
|
||||
self.draw_presets()
|
||||
self.draw_output_buttons()
|
||||
|
||||
sub = self.layout.column()
|
||||
sub.active = not self.op.computing
|
||||
|
||||
# Draw operation name and filename
|
||||
sub.prop(self.op, 'name')
|
||||
sub.prop(self.op, 'filename')
|
||||
|
||||
self.draw_operation_source()
|
||||
self.draw_operation_options()
|
||||
|
||||
prop_level = {
|
||||
'draw_presets': 1,
|
||||
'draw_operations_list': 0,
|
||||
'draw_calculate_path': 0,
|
||||
'draw_export_gcode': 1,
|
||||
'draw_simulate_op': 1,
|
||||
'draw_op_name': 1,
|
||||
'draw_op_filename': 0,
|
||||
'draw_operation_source': 0,
|
||||
'draw_simplify_gcode': 1,
|
||||
'draw_use_modifiers': 1,
|
||||
'draw_hide_all_others': 2,
|
||||
'draw_parent_path_to_object': 2
|
||||
}
|
||||
|
||||
# Draw the list of operations and the associated buttons:
|
||||
# create, delete, duplicate, reorder
|
||||
|
@ -54,37 +49,47 @@ class CAM_OPERATIONS_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
|
||||
# Draw the list of preset operations, and preset add and remove buttons
|
||||
def draw_presets(self):
|
||||
if not self.has_correct_level(): return
|
||||
row = self.layout.row(align=True)
|
||||
row.menu("CAM_OPERATION_MT_presets", text=bpy.types.CAM_OPERATION_MT_presets.bl_label)
|
||||
row.operator("render.cam_preset_operation_add", text="", icon='ADD')
|
||||
row.operator("render.cam_preset_operation_add", text="", icon='REMOVE').remove_active = True
|
||||
|
||||
|
||||
# Draw buttons "Calculate path & export Gcode", "Export Gcode ", and "Simulate this operation"
|
||||
def draw_output_buttons(self):
|
||||
# FIXME This does not seem to work - there is never a "Computing" label displayed
|
||||
# while an operation is being calculated
|
||||
if self.op.computing:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text='computing')
|
||||
row.operator('object.kill_calculate_cam_paths_background', text="", icon='CANCEL')
|
||||
def draw_calculate_path(self):
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.valid:
|
||||
self.layout.operator("object.calculate_cam_path", text="Calculate path & export Gcode")
|
||||
else:
|
||||
if self.op.valid:
|
||||
self.layout.operator("object.calculate_cam_path", text="Calculate path & export Gcode")
|
||||
if self.op.name is not None:
|
||||
name = "cam_path_{}".format(self.op.name)
|
||||
if bpy.context.scene.objects.get(name) is not None:
|
||||
self.layout.operator("object.cam_export", text="Export Gcode ")
|
||||
self.layout.operator("object.cam_simulate", text="Simulate this operation")
|
||||
else:
|
||||
self.layout.label(text="operation invalid, can't compute")
|
||||
self.layout.label(text="operation invalid, can't compute")
|
||||
|
||||
def draw_export_gcode(self):
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.valid:
|
||||
if self.op.name is not None:
|
||||
name = f"cam_path_{self.op.name}"
|
||||
if bpy.context.scene.objects.get(name) is not None:
|
||||
self.layout.operator("object.cam_export", text="Export Gcode ")
|
||||
|
||||
def draw_simulate_op(self):
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.valid:
|
||||
self.layout.operator("object.cam_simulate", text="Simulate this operation")
|
||||
|
||||
def draw_op_name(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'name')
|
||||
|
||||
def draw_op_filename(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'filename')
|
||||
|
||||
|
||||
# Draw a list of objects which will be used as the source of the operation
|
||||
# FIXME Right now, cameras or lights may be used, which crashes
|
||||
# The user should only be able to choose meshes and curves
|
||||
def draw_operation_source(self):
|
||||
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'geometry_source')
|
||||
|
||||
if self.op.strategy == 'CURVE':
|
||||
|
@ -110,25 +115,45 @@ class CAM_OPERATIONS_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
if self.op.strategy == 'PROJECTED_CURVE':
|
||||
self.layout.prop_search(self.op, "curve_object1", bpy.data, "objects")
|
||||
|
||||
# Draw Operation options:
|
||||
# Remove redundant points (optimizes operation)
|
||||
# Use modifiers of the object
|
||||
# Hide all other paths
|
||||
# Parent path to object (?)
|
||||
def draw_simplify_gcode(self):
|
||||
if not self.has_correct_level(): return
|
||||
|
||||
def draw_operation_options(self):
|
||||
|
||||
# TODO This should be in some optimization menu
|
||||
if self.op.strategy != 'DRILL':
|
||||
if self.op.strategy not in ['DRILL']:
|
||||
self.layout.prop(self.op, 'remove_redundant_points')
|
||||
|
||||
if self.op.remove_redundant_points:
|
||||
self.layout.label(text='Revise your Code before running!')
|
||||
self.layout.label(text='Quality will suffer if tolerance')
|
||||
self.layout.label(text='is high')
|
||||
self.layout.prop(self.op, 'simplify_tol')
|
||||
|
||||
def draw_use_modifiers(self):
|
||||
if not self.has_correct_level(): return
|
||||
if self.op.geometry_source in ['OBJECT', 'COLLECTION']:
|
||||
self.layout.prop(self.op, 'use_modifiers')
|
||||
|
||||
def draw_hide_all_others(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'hide_all_others')
|
||||
|
||||
def draw_parent_path_to_object(self):
|
||||
if not self.has_correct_level(): return
|
||||
self.layout.prop(self.op, 'parent_path_to_object')
|
||||
|
||||
|
||||
def draw(self, context):
|
||||
self.context = context
|
||||
|
||||
self.draw_presets()
|
||||
self.draw_operations_list()
|
||||
|
||||
if self.op is None: return
|
||||
|
||||
self.draw_calculate_path()
|
||||
self.draw_export_gcode()
|
||||
self.draw_simulate_op()
|
||||
self.draw_op_name()
|
||||
self.draw_op_filename()
|
||||
self.draw_operation_source()
|
||||
self.draw_simplify_gcode()
|
||||
self.draw_use_modifiers()
|
||||
self.draw_hide_all_others()
|
||||
self.draw_parent_path_to_object()
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue