diff --git a/OP_eraser_brush.py b/OP_eraser_brush.py index 0e56444..5d4ea52 100644 --- a/OP_eraser_brush.py +++ b/OP_eraser_brush.py @@ -2,6 +2,8 @@ import bpy from bpy.types import Operator import bgl from gpu_extras.presets import draw_circle_2d +from gpu_extras.batch import batch_for_shader +import gpu from time import time from mathutils import Vector, Matrix, Euler from mathutils.kdtree import KDTree @@ -9,6 +11,7 @@ from mathutils.geometry import intersect_line_plane, intersect_line_sphere_2d, i from bpy_extras.view3d_utils import region_2d_to_location_3d, region_2d_to_vector_3d, \ location_3d_to_region_2d, region_2d_to_origin_3d, region_2d_to_location_3d from time import time +from math import pi, cos, sin def get_gp_mat(gp, name, set_active=False): @@ -83,6 +86,7 @@ def get_cuts_data(strokes, mouse, radius): if not is_polyline and not s.select: continue + print('Cut Stroke', s) for i, p in enumerate(s.points): if not p.select and not is_polyline: @@ -132,15 +136,20 @@ def get_cuts_data(strokes, mouse, radius): continue + print('intersects', intersects) + line_intersects = [] for i_2d in intersects: #factor = ((i_2d-p1_2d).length) / length_2d #factor_3d = factor_2d * length_3d #vec = region_2d_to_vector_3d(region, rv3d, i_2d) - p3_3d = region_2d_to_location_3d(region, rv3d, i_2d, org) - p4_3d = region_2d_to_origin_3d(region, rv3d, i_2d) + #p3_3d = region_2d_to_location_3d(region, rv3d, i_2d, org) + #p4_3d = region_2d_to_origin_3d(region, rv3d, i_2d) - #bpy.context.scene.cursor.location = p3_3d + p3_3d = co_2d_to_3d(i_2d, 0.1) + p4_3d = co_2d_to_3d(i_2d, 1000) + + #bpy.context.scene.cursor.location = p4_3d line_intersect = intersect_line_line(p1_3d, p2_3d, p3_3d, p4_3d) if not line_intersect: @@ -153,6 +162,7 @@ def get_cuts_data(strokes, mouse, radius): #context.scene.cursor.location = i1_3d + print('line_intersects', line_intersects) if line_intersects: line_intersects.sort(key=lambda x : (x-p1_3d).length) #cut_data[-1].sort(key=lambda x : (x-p1_3d).length) @@ -161,6 +171,18 @@ def get_cuts_data(strokes, mouse, radius): return cuts_data + +def circle(x, y, radius, segments): + coords = [] + m = (1.0 / (segments - 1)) * (pi * 2) + + for p in range(segments): + p1 = x + cos(m * p) * radius + p2 = y + sin(m * p) * radius + coords.append((p1, p2)) + return coords + + class GPTB_OT_eraser(Operator): """Draw a line with the mouse""" bl_idname = "gp.eraser" @@ -169,9 +191,30 @@ class GPTB_OT_eraser(Operator): def draw_callback_px(self): bgl.glEnable(bgl.GL_BLEND) - draw_circle_2d(self.mouse, (0.75, 0.25, 0.35, 0.85), self.radius, 32) + #bgl.glBlendFunc(bgl.GL_CONSTANT_ALPHA, bgl.GL_ONE_MINUS_CONSTANT_ALPHA) + #bgl.glBlendColor(1.0, 1.0, 1.0, 0.1) + + area = bpy.context.area + #region = bpy.context.region + #rv3d = area.spaces.active.region_3d + + bg_color = area.spaces.active.shading.background_color + #print(bg_color) + + shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR') + shader.bind() + shader.uniform_float("color", (1, 1, 1, 1)) + for mouse in self.mouse_path: + circle_co = circle(*mouse, self.radius, 24) + batch = batch_for_shader(shader, 'TRI_FAN', {"pos": circle_co}) + batch.draw(shader) + + draw_circle_2d(self.mouse, (0.75, 0.25, 0.35, 1.0), self.radius, 24) bgl.glDisable(bgl.GL_BLEND) + + + ''' def draw_holdout(self, context, event): gp = context.object mat_inv = gp.matrix_world.inverted() @@ -193,7 +236,7 @@ class GPTB_OT_eraser(Operator): p.pressure = search_radius * 2000 #context.scene.cursor.location = mouse_3d - + ''' def get_radius(self, context, event): pressure = event.pressure or 1 return context.scene.gptoolprops.eraser_radius * pressure @@ -209,12 +252,12 @@ class GPTB_OT_eraser(Operator): #print(self.cuts_data) - for f in self.gp_frames: - for s in [s for s in f.strokes if s.material_index==self.hld_index]: - f.strokes.remove(s) + # for f in self.gp_frames: + # for s in [s for s in f.strokes if s.material_index==self.hld_index]: + # f.strokes.remove(s) - gp.data.materials.pop(index=self.hld_index) - bpy.data.materials.remove(self.hld_mat) + #gp.data.materials.pop(index=self.hld_index) + #bpy.data.materials.remove(self.hld_mat) bpy.ops.object.mode_set(mode='EDIT_GPENCIL') @@ -229,7 +272,7 @@ class GPTB_OT_eraser(Operator): t0 = time() print() - print('Number of cuts', len(self.mouse_path)) + #print('Number of cuts', len(self.mouse_path)) for mouse in self.mouse_path: t1 = time() @@ -240,12 +283,15 @@ class GPTB_OT_eraser(Operator): bpy.ops.gpencil.select_circle(x=x, y=y, radius=self.radius, wait_for_input=False) strokes = [s for f in self.gp_frames for s in f.strokes] - print('select_circle', time()-t1) + #print('select_circle', time()-t1) t2 = time() cut_data = get_cuts_data(strokes, mouse, self.radius) - print('get_cuts_data', time()-t2) + #print('get_cuts_data', time()-t2) + #print([s for s in strokes if s.select]) + print('cut_data', cut_data) + t3 = time() for p1_index, p2_index, stroke, intersects in cut_data[::-1]: bpy.ops.gpencil.select_all(action='DESELECT') @@ -263,7 +309,6 @@ class GPTB_OT_eraser(Operator): bpy.ops.gpencil.stroke_subdivide(number_cuts=number_cuts, only_selected=True) - new_p1 = stroke.points[p1_index+1] new_p1.co = mat_inv@intersects[0] new_points += [(stroke, p1_index+1)] @@ -279,9 +324,11 @@ class GPTB_OT_eraser(Operator): new_p3.co = mat_inv@intersects[1] new_points += [(stroke, p1_index+3)] - print('subdivide', time() - t3) + #print('subdivide', time() - t3) - bpy.ops.gpencil.select_circle(x=x, y=y, radius=self.radius-2, wait_for_input=False) + + bpy.ops.gpencil.select_all(action='DESELECT') + bpy.ops.gpencil.select_circle(x=x, y=y, radius=self.radius-4, wait_for_input=False) ''' selected_strokes = [s for f in self.gp_frames for s in f.strokes if s.select] @@ -304,9 +351,9 @@ class GPTB_OT_eraser(Operator): print('remove points', time()- t4) - print('Total one cut', time()-t1) + #print('Total one cut', time()-t1) - print('Total all cuts', time()-t0) + #print('Total all cuts', time()-t0) #bpy.ops.gpencil.select_less() #for stroke, index in new_points: # stroke.points[index].select = False @@ -317,7 +364,7 @@ class GPTB_OT_eraser(Operator): #bpy.ops.object.mode_set(mode='PAINT_GPENCIL') def modal(self, context, event): - mouse = Vector((event.mouse_region_x, event.mouse_region_y)) + self.mouse = Vector((event.mouse_region_x, event.mouse_region_y)) self.radius = self.get_radius(context, event) context.area.tag_redraw() @@ -329,13 +376,13 @@ class GPTB_OT_eraser(Operator): bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') return {'FINISHED'} - if (mouse-self.mouse).length < min(self.radius, 2): + if (self.mouse-self.mouse_prev).length < max(self.radius/1.33, 2): return {'RUNNING_MODAL'} - - self.mouse = mouse + + self.mouse_prev = self.mouse if event.type in {'MOUSEMOVE', 'INBETWEEN_MOUSEMOVE'}: - self.draw_holdout(context, event) + #self.draw_holdout(context, event) self.mouse_path.append(self.mouse) #self.update_cuts_data(context, event) #self.erase(context, event) @@ -351,8 +398,8 @@ class GPTB_OT_eraser(Operator): gp = context.object matrix = gp.matrix_world - self.mouse = Vector((event.mouse_region_x, event.mouse_region_y)) - self.mouse_path = [self.mouse] + self.mouse_prev = Vector((event.mouse_region_x, event.mouse_region_y)) + self.mouse_path = [self.mouse_prev] area = context.area region = context.region @@ -421,6 +468,7 @@ class GPTB_OT_eraser(Operator): print('create kdtree', time()-t0) ''' + ''' # Create holdout mat self.hld_mat = get_gp_mat(gp, name='Eraser Holdout Stroke') self.hld_mat.grease_pencil.use_stroke_holdout = True @@ -442,7 +490,7 @@ class GPTB_OT_eraser(Operator): self.hld_strokes.append((f, hld_stroke)) self.draw_holdout(context, event) - + ''' context.area.tag_redraw()