Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI Panel Refactor #207

Merged
merged 2 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading