import bpy
import bmesh
import bpy.utils.previews
from math import radians
from ... utility import addon
from ... utils.blender_ui import get_dpi_factor
from ... utils.context import ExecutionContext
from ... utility import modifier
from bpy.props import EnumProperty, FloatProperty, BoolProperty
from ...ui_framework.operator_ui import Master
class HOPS_OT_ClearClean(bpy.types.Operator):
bl_idname = "hops.clearclean"
bl_label = "Cleans Mesh / Removes Sharpening"
bl_options = {'REGISTER', 'INTERNAL'}
bl_description = """LMB - Clean Mesh (CleanMesh)
LMB + CTRL - Remove Sharp Edges / Bevel Mod (clear-sharp)
"""
@classmethod
def poll(cls, context):
return getattr(context.active_object, "type", "") == "MESH"
def invoke(self, context, event):
if event.ctrl:
self.report({'INFO'}, F'Sharp Markings Removed')
bpy.ops.hops.clean_sharps('INVOKE_DEFAULT')
else:
self.report({'INFO'}, F'Mesh Cleaned')
bpy.ops.view3d.clean_mesh('INVOKE_DEFAULT')
return {'FINISHED'}
class HOPS_OT_TwistApply(bpy.types.Operator):
bl_idname = "hops.twist_apply"
bl_label = "Twist 360 / Apply 360"
bl_options = {'REGISTER', 'INTERNAL'}
bl_description = """LMB - Twist 360
LMB + CTRL - Apply 360
"""
@classmethod
def poll(cls, context):
return getattr(context.active_object, "type", "") == "MESH"
def invoke(self, context, event):
if event.ctrl:
self.report({'INFO'}, F'Radial 360 Applied')
bpy.ops.hops.clean_reorigin('INVOKE_DEFAULT', origin_set=True)
else:
self.report({'INFO'}, F'Twist 360')
bpy.ops.hops.array_twist('INVOKE_DEFAULT')
#bpy.ops.hops.array_twist()
return {'FINISHED'}
class HOPS_OT_EditMultiTool(bpy.types.Operator):
bl_idname = "hops.edit_multi_tool"
bl_label = "Edit Multi-Tool"
bl_options = {'REGISTER', 'INTERNAL'}
bl_description = """ Mark/Bevel/Weld Multi-tool
LMB - Mark / Unmark Edge
CTRL - Add Bevel (vgroup)
SHIFT - Edit Multi Tool
ALT - Adjust Bevel Weight
CTRL + SHIFT - Add Weld (vgroup)
"""
called_ui = False
header = "nothing"
text = "nothing"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
HOPS_OT_EditMultiTool.called_ui = False
@classmethod
def poll(cls, context):
return getattr(context.active_object, "type", "") == "MESH"
def invoke(self, context, event):
if event.ctrl and event.shift:
header = "Weld Vgroup"
text = "Vgroup Weld Added"
bpy.ops.hops.mod_weld('INVOKE_DEFAULT')
#bpy.ops.hops.clean1_objects(clearsharps=False)
elif event.ctrl:
try:
bpy.ops.hops.adjust_bevel('INVOKE_DEFAULT')
self.report({'INFO'}, F'Bevel Added')
header = "Bevel"
text = "Vgroup Bevel Added"
except:
header = "Failed"
text = "Operation failed due to selection."
elif event.shift:
bpy.ops.hops.fast_mesh_editor('INVOKE_DEFAULT')
self.report({'INFO'}, F'Bevel Added')
header = "Edit Multi"
text = "Edit Multi Tool Launched"
elif event.alt:
self.report({'INFO'}, F'Bevel Weight Adjustment')
header = "Bevel Weight"
text = "Bevel Weight Adjustment"
bpy.ops.hops.bevel_weight('INVOKE_DEFAULT')
else:
if addon.preference().property.sharp_use_crease == False and addon.preference().property.sharp_use_sharp == False and addon.preference().property.sharp_use_seam == False and addon.preference().property.sharp_use_bweight == False:
header = "No Mark"
text = "Nothing was set for marking in settings"
else:
header = "Mark"
text = "Selection marked / unmarked"
self.report({'INFO'}, F'Sharp Marked / Unmarked')
bpy.ops.hops.set_edit_sharpen()
# Operator UI
if not HOPS_OT_EditMultiTool.called_ui:
HOPS_OT_EditMultiTool.called_ui = True
ui = Master()
draw_data = [
[header],
[text]
]
ui.receive_draw_data(draw_data=draw_data)
ui.draw(draw_bg=addon.preference().ui.Hops_operator_draw_bg, draw_border=addon.preference().ui.Hops_operator_draw_border)
return {'FINISHED'}
class HOPS_OT_Bevel_Half_Add(bpy.types.Operator):
bl_idname = "hops.bevel_half_add"
bl_label = "Bevel Half"
bl_options = {'REGISTER'}
bl_description = """Add Bevel at half of last bevel.
Cstep 3.0 ND
"""
called_ui = False
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
HOPS_OT_Bevel_Half_Add.called_ui = False
@classmethod
def poll(cls, context):
return getattr(context.active_object, "type", "") == "MESH"
def execute(self, context):
# Get Bevels
obj = context.active_object
bevel_widths = [mod.width for mod in obj.modifiers if mod.type == 'BEVEL']
default = 0.2
lw = bevel_widths[-1] if bevel_widths else default
factor = 0.55
lw = lw - lw * factor
bevel_modifier = obj.modifiers.new(name="Bevel", type="BEVEL")
bevel_modifier.width = lw
bevel_modifier.miter_outer = 'MITER_ARC'
bevel_modifier.limit_method = "ANGLE"
bevel_modifier.segments = 6
bevel_modifier.use_clamp_overlap = False
bevel_modifier.harden_normals = False
bevel_modifier.angle_limit = radians(60)
bevel_modifier.loop_slide = addon.preference().property.bevel_loop_slide
bevel_modifier.profile = addon.preference().property.bevel_profile
modifier.sort(obj, types=['WEIGHTED_NORMAL'], last=True)
# Operator UI
if not HOPS_OT_Bevel_Half_Add.called_ui:
HOPS_OT_Bevel_Half_Add.called_ui = True
ui = Master()
draw_data = [
["Bevel Half"],
["Half Bevel Added", "60°"],
["Total Modifiers ", len(context.active_object.modifiers[:])]
]
ui.receive_draw_data(draw_data=draw_data)
ui.draw(draw_bg=addon.preference().ui.Hops_operator_draw_bg, draw_border=addon.preference().ui.Hops_operator_draw_border)
return {'FINISHED'}
class HOPS_OT_BVL_MULTI(bpy.types.Operator):
bl_idname = "hops.bevel_assist"
bl_label = "Bevel Multi_Assist"
bl_options = {'REGISTER'}
bl_description = """Bevel Assist Multi-tool
LMB - Bevel / Bool Helper
CTRL - Bevel Divider
ALT - Bevel Multiply
LMB + SHIFT - Edge Manager
"""
@classmethod
def poll(cls, context):
return getattr(context.active_object, "type", "") == "MESH"
def invoke(self, context, event):
if event.ctrl:
self.report({'INFO'}, F'Bevel Divider')
bpy.ops.hops.display_notification(info="Bevels Divided")
bpy.ops.view3d.bevel_multiplier('INVOKE_DEFAULT',multiply=False)
elif event.shift:
self.report({'INFO'}, F'Bevel Weight Adjustment')
bpy.ops.hops.sharp_manager('INVOKE_DEFAULT')
#bpy.ops.hops.bevel_weight()
elif event.alt:
bpy.ops.hops.display_notification(info="Bevels Multiplied")
self.report({'INFO'}, F'Bevel Multiplier')
bpy.ops.view3d.bevel_multiplier('INVOKE_DEFAULT',multiply=True)
else:
try:
bpy.ops.hops.bevel_helper('INVOKE_DEFAULT')
self.report({'INFO'}, F'Bevel Helper')
except:
#bpy.ops.hops.display_notification(info="No Bevels Present")
bpy.ops.hops.sharp_manager('INVOKE_DEFAULT')
self.report({'INFO'}, F'No Bevels Present')
return {'FINISHED'}
class HOPS_OT_BevBoolMulti(bpy.types.Operator):
bl_idname = "hops.bev_multi"
bl_label = "Bevel Boolean Multi_Assist"
bl_options = {'REGISTER'}
bl_description = """
"""
@classmethod
def poll(cls, context):
return getattr(context.active_object, "type", "") == "MESH"
def invoke(self, context, event):
active_object = context.active_object
is_bevel = len([mod for mod in bpy.context.active_object.modifiers if mod.type == 'BEVEL'])
is_bool = len([mod for mod in bpy.context.active_object.modifiers if modifier.mod_type(mod) == 'BOOLEAN'])
if not addon.preference().property.bev_bool_helper:
try:
if len(bpy.context.selected_objects) == 1:
if context.active_object.hops.status == 'BOOLSHAPE':
bpy.ops.hops.bool_shift('INVOKE_DEFAULT')
elif is_bevel and context.active_object.hops.status != 'BOOLSHAPE':
bpy.ops.hops.bevel_helper('INVOKE_DEFAULT')
self.report({'INFO'}, F'Bevel Helper')
elif is_bool:
bpy.ops.hops.bool_scroll_objects('INVOKE_DEFAULT')
self.report({'INFO'}, F'BoolScroll Fallback')
else:
bpy.ops.hops.display_notification(info="Not Used")
self.report({'INFO'}, F'Not Used')
# elif object.mode == "EDIT":
# bpy.ops.hops.bool_modal('INVOKE_DEFAULT', operation='DIFFERENCE', ignore_sort=False)
elif len(bpy.context.selected_objects) == 2:
bpy.ops.hops.bool_modal('INVOKE_DEFAULT', operation='DIFFERENCE', ignore_sort=False)
elif len(bpy.context.selected_objects) >= 3:
bpy.ops.hops.bool_modal('INVOKE_DEFAULT', operation='SLASH', ignore_sort=False)
else:
bpy.ops.hops.display_notification(info="No")
self.report({'INFO'}, F'No Selection')
return {'FINISHED'}
except:
self.report({'INFO'}, F'Nah')
return {'FINISHED'}
else:
try:
bpy.ops.hops.bevel_helper('INVOKE_DEFAULT')
self.report({'INFO'}, F'Bevel Helper')
except:
bpy.ops.hops.display_notification(info="No")
return {'FINISHED'}
class HOPS_OT_EditMeshMacro(bpy.types.Operator):
bl_idname = "hops.edit_mesh_macro"
bl_label = "Edit Multi-Tool V1"
bl_options = {'REGISTER', 'INTERNAL'}
bl_description = """Experimental Multi Tool
LMB - Grate
LMB + CTRL - Knurl
LMB + SHIFT - Panel (Edge)
LMB + ALT - Panel (Face)
CTRL + SHIFT - Panel (Face)
"""
called_ui = False
header = "nothing"
text = "nothing"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
HOPS_OT_EditMeshMacro.called_ui = False
@classmethod
def poll(cls, context):
return getattr(context.active_object, "type", "") == "MESH"
def invoke(self, context, event):
if event.ctrl and not event.shift and not event.alt:
header = "Face Knurl"
text = "Face Knurl Initialized"
result = bpy.ops.hops.fknurl_op('INVOKE_DEFAULT')
if "CANCELLED" in result :
header = "Failed"
text = "Operation requires QUADS in selection."
elif event.shift and not event.ctrl and not event.alt:
header = "Panel (edge)"
text = "Quick Panel (edge) Initialized"
result = bpy.ops.hops.quick_panel('INVOKE_DEFAULT')
if "CANCELLED" in result :
header = "Failed"
text = "Operation requires FACES or EDGES in selection."
elif event.alt and not event.shift and not event.ctrl or event.ctrl and event.shift and not event.alt:
#Alt or Ctrl + Shift
header = "Panel Face"
text = "Quick Panel (Face) Initialized"
bpy.ops.hops.entrench_selection('INVOKE_DEFAULT')
else:
header = "Face Grate"
text = "Face Grate Initialized"
result = bpy.ops.hops.fgrate_op('INVOKE_DEFAULT')
if "CANCELLED" in result :
header = "Failed"
text = "Operation requires QUADS in selection."
# Operator UI
if not HOPS_OT_EditMeshMacro.called_ui:
HOPS_OT_EditMeshMacro.called_ui = True
ui = Master()
draw_data = [
[header],
[text]
]
ui.receive_draw_data(draw_data=draw_data)
ui.draw(draw_bg=addon.preference().ui.Hops_operator_draw_bg, draw_border=addon.preference().ui.Hops_operator_draw_border)
return {'FINISHED'}
class HOPS_OT_FlattenAlign(bpy.types.Operator):
bl_idname = "hops.flatten_align"
bl_label = "Reset / Flatten / View Align / Select"
bl_options = {'REGISTER', 'INTERNAL'}
bl_description = """Reset / Flatten - View Align Multi-tool
LMB - Reset (Object) / Flatten (Edit)
CTRL - View Align
SHIFT - Select Tool
"""
@classmethod
def poll(cls, context):
return getattr(context.active_object, "type", "") == "MESH"
def invoke(self, context, event):
if event.ctrl or event.alt:
bpy.ops.hops.display_notification(info=F'View Align ' )
self.report({'INFO'}, F'View Align Modal')
bpy.ops.view3d.view_align('INVOKE_DEFAULT')
elif event.shift:
bpy.ops.hops.display_notification(info=F'Select Tool ' )
self.report({'INFO'}, F'Select Tool')
bpy.ops.hops.fast_mesh_editor('INVOKE_DEFAULT')
else:
bpy.ops.hops.display_notification(info=F'Reset Axis ' )
self.report({'INFO'}, F'Reset Axis Modal')
bpy.ops.hops.reset_axis_modal('INVOKE_DEFAULT')
#bpy.ops.hops.array_twist()
return {'FINISHED'}