import bpy
import gpu
from gpu_extras.batch import batch_for_shader
from mathutils import Vector
from ... utils.blender_ui import get_dpi, get_dpi_factor
from ... graphics.drawing2d import draw_text, set_drawing_dpi
from ... utility import addon
from ... utility import method_handler
from . import infobar
class HOPS_OT_TwoDBevelOperator(bpy.types.Operator):
bl_idname = "hops.2d_bevel"
bl_label = "2 Dimensional Bevel"
bl_description = """Interactively and non destructively adds BEVEL modifier to single flat FACES
Press H for help"""
bl_options = {"REGISTER", "UNDO", "GRAB_CURSOR", "BLOCKING"}
@classmethod
def poll(cls, context):
return any(o.type == 'MESH' for o in context.selected_objects)
def invoke(self, context, event):
self.objects = [o for o in context.selected_objects if o.type == 'MESH']
self.object = context.active_object if context.active_object.type == 'MESH' else self.objects[0]
self.modal_scale = addon.preference().ui.Hops_modal_scale
bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
bpy.ops.view3d.clean_mesh()
self.bevel = self.get_bevel_modifier()
self.weld = self.weld_mod()
self.start_mouse_position = Vector((event.mouse_region_x, event.mouse_region_y))
self.start_bevel_width = self.bevel.width
self.start_bevel_profile = self.bevel.profile
self.start_bevel_segments = self.bevel.segments
self.bevel_offset = 0
self.profile_offset = 0
self.last_mouse_x = event.mouse_region_x
args = (context, )
self.draw_handler = bpy.types.SpaceView3D.draw_handler_add(self.draw_ui, args, "WINDOW", "POST_PIXEL")
context.window_manager.modal_handler_add(self)
infobar.initiate(self)
return {"RUNNING_MODAL"}
def get_bevel_modifier(self):
bevel_modifier = None
for modifier in self.object.modifiers:
if modifier.type == "BEVEL":
bevel_modifier = modifier
self.created_bevel_modifier = False
if bevel_modifier is None:
bevel_modifier = self.object.modifiers.new("Bevel", "BEVEL")
bevel_modifier.limit_method = "NONE"
bevel_modifier.width = 0.200
bevel_modifier.profile = 0.50
bevel_modifier.segments = 6
if bpy.app.version < (2, 90, 0):
bevel_modifier.use_only_vertices = True
else:
bevel_modifier.affect = 'VERTICES'
bevel_modifier.use_clamp_overlap = True
self.created_bevel_modifier = True
return bevel_modifier
def weld_mod(self):
if bpy.app.version >= (2, 82, 0):
weld_modifier = None
for modifier in self.object.modifiers:
if modifier.type == "WELD":
weld_modifier = modifier
self.created_bevel_modifier = False
if weld_modifier is None:
self.object.modifiers.new(name='HOPS_weld', type="WELD")
return weld_modifier
else:
pass
def modal(self, context, event):
divisor = 10000 * self.modal_scale if event.shift else 10000000 if event.ctrl else 1000 * self.modal_scale
divisor_profile = 500 * self.modal_scale if event.ctrl else 100000000000
offset_x = event.mouse_region_x - self.last_mouse_x
self.bevel_offset += offset_x / divisor / get_dpi_factor()
self.bevel.width = self.start_bevel_width - self.bevel_offset
self.profile_offset += offset_x / divisor_profile / get_dpi_factor()
if event.ctrl:
self.bevel.profile = self.start_bevel_profile - self.profile_offset
if event.type == "WHEELUPMOUSE" or event.type == 'NUMPAD_PLUS' and event.value == 'PRESS':
self.bevel.segments += 1
self.report({'INFO'}, F'Bevel Segments : {self.bevel.segments}')
if event.type == "WHEELDOWNMOUSE" or event.type == 'NUMPAD_MINUS' and event.value == 'PRESS':
self.bevel.segments -= 1
self.report({'INFO'}, F'Bevel Segments : {self.bevel.segments}')
if event.type == "H" and event.value == "PRESS":
addon.preference().property.hops_modal_help = not addon.preference().property.hops_modal_help
if event.type in ("ESC", "RIGHTMOUSE"):
self.reset_object()
return self.finish()
if event.type in ("SPACE", "LEFTMOUSE"):
return self.finish()
if event.type == 'W' and event.value == 'PRESS':
offset_types = ["OFFSET", "WIDTH", "DEPTH", "PERCENT"]
modifier.offset_type = offset_types[(offset_types.index(modifier.offset_type) + 1) % len(offset_types)]
self.last_mouse_x = event.mouse_region_x
context.area.tag_redraw()
return {"RUNNING_MODAL"}
def reset_object(self):
self.bevel.width = self.start_bevel_width
self.bevel.segments = self.start_bevel_segments
self.bevel.profile = self.start_bevel_profile
if self.created_bevel_modifier:
self.object.modifiers.remove(self.bevel)
def finish(self):
# bpy.types.SpaceView3D.draw_handler_remove(self.draw_handler, "WINDOW")
self.remove_ui()
infobar.remove(self)
return {"FINISHED"}
def draw_ui(self, context):
method_handler(self._draw_ui,
arguments = (context, ),
identifier = 'Bevel2D UI Shader',
exit_method = self.remove_ui)
def _draw_ui(self, context):
x, y = self.start_mouse_position
set_drawing_dpi(get_dpi())
factor = get_dpi_factor()
offset = 5
l1 = (3, 23, 4, 44)
l2 = (46, 23, 4, 146)
l3 = (149, 23, 4, 220)
l4 = (223, 23, 4, 280)
vertices = (
(x + (l1[0] - offset) * factor, y + l1[1] * factor), (x + l1[0] * factor, y + l1[2] * factor), (x + (l1[3] - offset) * factor, y + l1[1] * factor), (x + l1[3] * factor, y + l1[2] * factor),
(x + (l2[0] - offset) * factor, y + l2[1] * factor), (x + l2[0] * factor, y + l2[2] * factor), (x + (l2[3] - offset) * factor, y + l2[1] * factor), (x + l2[3] * factor, y + l2[2] * factor),
(x + (l3[0] - offset) * factor, y + l3[1] * factor), (x + l3[0] * factor, y + l3[2] * factor), (x + (l3[3] - offset) * factor, y + l3[1] * factor), (x + l3[3] * factor, y + l3[2] * factor),
(x + (l4[0] - offset) * factor, y + l4[1] * factor), (x + l4[0] * factor, y + l4[2] * factor), (x + (l4[3] - offset) * factor, y + l4[1] * factor), (x + l4[3] * factor, y + l4[2] * factor))
l1 = (l1[0] - 15, l1[1], l1[2], l1[0] - 6)
vertices2 = (
(x + (l1[0] - offset) * factor, y + l1[1] * factor), (x + l1[0] * factor, y + l1[2] * factor), (x + (l1[3] - offset) * factor, y + l1[1] * factor), (x + l1[3] * factor, y + l1[2] * factor))
indices = (
(0, 1, 2), (1, 2, 3), (4, 5, 6), (5, 6, 7), (8, 9, 10), (9, 10, 11), (12, 13, 14), (13, 14, 15))
indices2 = (
(0, 1, 2), (1, 2, 3))
built_in_shader = 'UNIFORM_COLOR' if bpy.app.version[0] >=4 else '2D_UNIFORM_COLOR'
shader = gpu.shader.from_builtin(built_in_shader)
batch = batch_for_shader(shader, 'TRIS', {"pos": vertices}, indices=indices)
shader.bind()
shader.uniform_float("color", addon.preference().color.Hops_hud_color)
gpu.state.blend_set('ALPHA')
batch.draw(shader)
gpu.state.blend_set('NONE')
shader2 = gpu.shader.from_builtin(built_in_shader)
batch2 = batch_for_shader(shader2, 'TRIS', {"pos": vertices2}, indices=indices2)
shader2.bind()
shader2.uniform_float("color", addon.preference().color.Hops_hud_help_color)
gpu.state.blend_set('ALPHA')
batch2.draw(shader2)
gpu.state.blend_set('NONE')
draw_text("{}".format(self.bevel.segments),
x + 27 * factor, y + 9 * factor, size=12, color=addon.preference().color.Hops_hud_text_color)
draw_text(" B-Width: {:.3f}".format(self.bevel.width),
x + 50 * factor, y + 9 * factor, size=12, color=addon.preference().color.Hops_hud_text_color)
draw_text("Profile:{:.2f}".format(self.bevel.profile),
x + 154 * factor, y + 9 * factor, size=12, color=addon.preference().color.Hops_hud_text_color)
draw_text("{}".format(self.bevel.offset_type),
x + 227 * factor, y + 9 * factor, size=12, color=addon.preference().color.Hops_hud_text_color)
self.draw_help(context, x, y, factor)
def draw_help(self, context, x, y, factor):
color_text1 = addon.preference().color.Hops_text_color
color_text2 = addon.preference().color.Hops_hud_help_color
color_border = addon.preference().color.Hops_border_color
color_border2 = addon.preference().color.Hops_border2_color
if addon.preference().property.hops_modal_help:
draw_text(" scroll - set segment",
x + 45 * factor, y - 14 * factor, size=11, color=color_text2)
draw_text(" ctrl - set profile",
x + 45 * factor, y - 26 * factor, size=11, color=color_text2)
draw_text(" W - choose offset type",
x + 45 * factor, y - 38 * factor, size=11, color=color_text2)
else:
draw_text(" H - Show/Hide Help",
x + 45 * factor, y - 14 * factor, size=11, color=color_text2)
def remove_ui(self):
if self.draw_handler:
self.draw_handler = bpy.types.SpaceView3D.draw_handler_remove(self.draw_handler, "WINDOW")