Skip to content

Commit

Permalink
Merge pull request #207 from SpectralVectors/ui-panel-refactor
Browse files Browse the repository at this point in the history
UI Panel Refactor
  • Loading branch information
pppalain authored Oct 24, 2024
2 parents a4c3938 + 8c418cb commit 953d9c2
Show file tree
Hide file tree
Showing 16 changed files with 733 additions and 1,160 deletions.
152 changes: 64 additions & 88 deletions scripts/addons/cam/ui/panels/area.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,96 +17,72 @@ class CAM_AREA_Panel(CAMButtonsPanel, Panel):
bl_idname = "WORLD_PT_CAM_OPERATION_AREA"
panel_interface_level = 0

prop_level = {
"draw_use_layers": 0,
"draw_maxz": 1,
"draw_minz": 1,
"draw_ambient": 1,
"draw_limit_curve": 1,
"draw_first_down": 1,
}

def draw_use_layers(self):
if not self.has_correct_level():
return
col = self.layout.column(align=True)
def draw(self, context):
layout = self.layout
# 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")
self.draw_first_down(col)

def draw_first_down(self, col):
if not self.has_correct_level():
return
if self.op.strategy in ["CUTOUT", "POCKET", "MEDIAL_AXIS"]:
row = col.row(align=True)
row.label(text="")
row.prop(self.op, "first_down")

def draw_maxz(self):
if not self.has_correct_level():
return
self.layout.prop(self.op, "maxz")
self.layout.prop(self.op.movement, "free_height")
if self.op.maxz > self.op.movement.free_height:
self.layout.label(text="!ERROR! COLLISION!")
self.layout.label(text="Depth Start > Free Movement Height")
self.layout.label(text="!ERROR! COLLISION!")

def draw_minz(self):
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")

row = self.layout.row(align=True)
row.label(text="Set Max Depth from")
row.prop(self.op, "minz_from", text="")
if self.op.minz_from == "CUSTOM":
self.layout.prop(self.op, "minz")

else:
self.layout.prop(self.op, "source_image_scale_z")
self.layout.prop(self.op, "source_image_size_x")
if self.op.source_image_name != "":
i = bpy.data.images[self.op.source_image_name]
if i is not None:
sy = int((self.op.source_image_size_x / i.size[0]) * i.size[1] * 1000000) / 1000
self.layout.label(text="Image Size on Y Axis: " + strInUnits(sy, 8))
self.layout.separator()
self.layout.prop(self.op, "source_image_offset")
col = self.layout.column(align=True)
col.prop(self.op, "source_image_crop", text="Crop Source Image")
if self.op.source_image_crop:
col.prop(self.op, "source_image_crop_start_x", text="Start X")
col.prop(self.op, "source_image_crop_start_y", text="Start Y")
col.prop(self.op, "source_image_crop_end_x", text="End X")
col.prop(self.op, "source_image_crop_end_y", text="End Y")

def draw_ambient(self):
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":
self.layout.prop(self.op, "ambient_radius")
self.layout.prop(self.op, "ambient_cutter_restrict")

def draw_limit_curve(self):
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:
self.layout.prop_search(self.op, "limit_curve", bpy.data, "objects")

def draw(self, context):
self.context = context

self.draw_use_layers()
self.draw_maxz()
self.draw_minz()
self.draw_ambient()
self.draw_limit_curve()
# 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")

# Max Z
if self.level >= 1:
col = layout.column(align=True)
col.prop(self.op, "maxz")
col.prop(self.op.movement, "free_height")
if self.op.maxz > self.op.movement.free_height:
col.label(text="!ERROR! COLLISION!")
col.label(text="Depth Start > Free Movement Height")
col.label(text="!ERROR! COLLISION!")

# Min Z
if self.level >= 1:
if self.op.geometry_source in ["OBJECT", "COLLECTION"]:
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="")
if self.op.minz_from == "CUSTOM":
row.prop(self.op, "minz")

else:
col.prop(self.op, "source_image_scale_z")
col.prop(self.op, "source_image_size_x")
if self.op.source_image_name != "":
i = bpy.data.images[self.op.source_image_name]
if i is not None:
size_x = self.op.source_image_size_x / i.size[0]
size_y = int(x_size * i.size[1] * 1000000) / 1000
col.label(text="Image Size on Y Axis: " + strInUnits(size_y, 8))
col.separator()
col.prop(self.op, "source_image_offset")
col.prop(self.op, "source_image_crop", text="Crop Source Image")
if self.op.source_image_crop:
col.prop(self.op, "source_image_crop_start_x", text="Start X")
col.prop(self.op, "source_image_crop_start_y", text="Start Y")
col.prop(self.op, "source_image_crop_end_x", text="End X")
col.prop(self.op, "source_image_crop_end_y", text="End Y")

# Draw Ambient
if self.level >= 1:
if self.op.strategy in ["BLOCK", "SPIRAL", "CIRCLES", "PARALLEL", "CROSS"]:
col.prop(self.op, "ambient_behaviour")
if self.op.ambient_behaviour == "AROUND":
col.prop(self.op, "ambient_radius")
col.prop(self.op, "ambient_cutter_restrict")

# Draw Limit Curve
if self.level >= 1:
if self.op.strategy in ["BLOCK", "SPIRAL", "CIRCLES", "PARALLEL", "CROSS"]:
col.prop(self.op, "use_limit_curve")
if self.op.use_limit_curve:
col.prop_search(self.op, "limit_curve", bpy.data, "objects")
62 changes: 23 additions & 39 deletions scripts/addons/cam/ui/panels/buttons_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,53 +17,37 @@ class CAMButtonsPanel:
always_show_panel = False
COMPAT_ENGINES = {"CNCCAM_RENDER"}

# COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here

@classmethod
def poll(cls, context):
rd = bpy.context.scene.render
if rd.engine in cls.COMPAT_ENGINES:
if cls.always_show_panel:
return True
op = cls.active_operation()
if op and op.valid:
if hasattr(cls, "panel_interface_level"):
return cls.panel_interface_level <= int(context.scene.interface.level)
else:
return True
return False
engine = context.scene.render.engine
engine_check = engine in cls.COMPAT_ENGINES

@classmethod
def active_operation_index(cls):
return bpy.context.scene.cam_active_operation
show_check = cls.always_show_panel

@classmethod
def active_operation(cls):
active_op = None
try:
active_op = bpy.context.scene.cam_operations[cls.active_operation_index()]
except IndexError:
pass
return active_op
operations = context.scene.cam_operations
operations_count = len(operations)
operation_index = context.scene.cam_active_operation
operation = operations[operation_index] if operations_count > 0 else None
op_check = operation is not None

def __init__(self):
self.op = self.active_operation()
addon_prefs = bpy.context.preferences.addons["bl_ext.user_default.blendercam"].preferences
self.use_experimental = addon_prefs.experimental
level = int(context.scene.interface.level)
level_check = cls.panel_interface_level <= level

def operations_count(self):
return len(bpy.context.scene.cam_operations)
check_1 = engine_check and show_check
check_2 = engine_check and op_check and level_check

def has_operations(self):
return self.operations_count() > 0
return True if check_1 or check_2 else False

def has_correct_level(self):
if not hasattr(self, "prop_level"):
return True
def __init__(self):
context = bpy.context

caller_function = inspect.stack()[1][3]
self.level = int(context.scene.interface.level)
self.machine = context.scene.cam_machine

if caller_function not in self.prop_level:
return True
addon_prefs = context.preferences.addons["bl_ext.user_default.blendercam"].preferences
self.use_experimental = addon_prefs.experimental

return self.prop_level[caller_function] <= int(self.context.scene.interface.level)
operations = context.scene.cam_operations
operations_count = len(operations)
operation_index = context.scene.cam_active_operation
self.op = operations[operation_index] if operations_count > 0 else None
83 changes: 42 additions & 41 deletions scripts/addons/cam/ui/panels/chains.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,45 +47,46 @@ class CAM_CHAINS_Panel(CAMButtonsPanel, Panel):
always_show_panel = True

def draw(self, context):
layout = self.layout

row = layout.row()
scene = bpy.context.scene

row.template_list("CAM_UL_chains", "", scene, "cam_chains", scene, "cam_active_chain")
col = row.column(align=True)
col.operator("scene.cam_chain_add", icon="ADD", text="")
col.operator("scene.cam_chain_remove", icon="REMOVE", text="")

if len(scene.cam_chains) > 0:
chain = scene.cam_chains[scene.cam_active_chain]
row = layout.row(align=True)

if chain:
row.template_list(
"CAM_UL_operations", "", chain, "operations", chain, "active_operation"
)
col = row.column(align=True)
col.operator("scene.cam_chain_operation_add", icon="ADD", text="")
col.operator("scene.cam_chain_operation_remove", icon="REMOVE", text="")
if len(chain.operations) > 0:
col.operator("scene.cam_chain_operation_up", icon="TRIA_UP", text="")
col.operator("scene.cam_chain_operation_down", icon="TRIA_DOWN", text="")

if not chain.computing:
layout.operator(
"object.calculate_cam_paths_chain",
text="Calculate Chain Paths & Export Gcode",
if self.level >= 1 and self.op is not None:
layout = self.layout

row = layout.row()
scene = bpy.context.scene

row.template_list("CAM_UL_chains", "", scene, "cam_chains", scene, "cam_active_chain")
col = row.column(align=True)
col.operator("scene.cam_chain_add", icon="ADD", text="")
col.operator("scene.cam_chain_remove", icon="REMOVE", text="")

if len(scene.cam_chains) > 0:
chain = scene.cam_chains[scene.cam_active_chain]
row = layout.row(align=True)

if chain:
row.template_list(
"CAM_UL_operations", "", chain, "operations", chain, "active_operation"
)
layout.operator("object.cam_export_paths_chain", text="Export Chain G-code")
layout.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)
else:
layout.label(text="Chain Is Currently Computing")

layout.prop(chain, "name")
layout.prop(chain, "filename")
col = row.column(align=True)
col.operator("scene.cam_chain_operation_add", icon="ADD", text="")
col.operator("scene.cam_chain_operation_remove", icon="REMOVE", text="")
if len(chain.operations) > 0:
col.operator("scene.cam_chain_operation_up", icon="TRIA_UP", text="")
col.operator("scene.cam_chain_operation_down", icon="TRIA_DOWN", text="")

if not chain.computing:
layout.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")

valid, reason = isChainValid(chain, context)
if not valid:
layout.label(icon="ERROR", text=f"Can't Compute Chain - Reason:\n")
layout.label(text=reason)
else:
layout.label(text="Chain Is Currently Computing")

layout.prop(chain, "name")
layout.prop(chain, "filename")
Loading

0 comments on commit 953d9c2

Please sign in to comment.