def modal(self, context, event): context.area.tag_redraw() if event.type in {'RET', 'NUMPAD_ENTER'} and event.value == 'PRESS': back_to_edit = False if context.mode == 'EDIT_MESH': bpy.ops.object.mode_set(mode='OBJECT') back_to_edit = True bm = self.tmp_bme else: bm = self.dest_bme #the world_matris of the orignal form orig_mx = self.original_form.matrix_world orig_ims = orig_mx.inverted() #the world matrix of the destination (retopo) mesh reto_mx = self.desination_ob.matrix_world reto_imx = reto_mx.inverted() #make list of bmverts...these should go smoothly into bmverts = [] for vert in self.verts: bmverts.append(bm.verts.new(tuple(reto_imx * (orig_mx * vert)))) # Initialize the index values of this sequence...stupi they aren't going in there!) self.dest_bme.verts.index_update() #this is tricky, I'm hoping that because my vert list is #actually composed of BMVerts that this will add in mesh data #smoothly with no problems. bmfaces = [] for face in self.faces: #actual BMVerts not indices I think? new_face = tuple([bmverts[i] for i in face]) bmfaces.append(bm.faces.new(new_face)) if not back_to_edit: # Finish up, write the bmesh back to the mesh bm.to_mesh(self.dest_me) #thies means we created a new object context.scene.objects.link(self.desination_ob) else: #disabled unti the BMesh API supports the dest keyword argument #bmesh.ops.duplicate(bm, geom = bm.verts[:] + bm.edges[:] + bm.faces[:],dest = self.dest_bme) # Finish up, write the bmesh back to the mesh bm.to_mesh(self.dest_me) context.scene.objects.link(self.retopo_ob) self.retopo_ob.update_tag() bpy.ops.object.select_all(action='DESELECT') self.retopo_ob.select = True context.scene.objects.active = self.desination_ob self.desination_ob.select = True bpy.ops.object.join() self.original_form.select = True self.desination_ob.update_tag() context.scene.update() if back_to_edit: bpy.ops.object.mode_set(mode='EDIT') context.area.header_text_set() contour_utilities.callback_cleanup(self, context) bm.free() self.dest_bme.free() self.bme.free() return {'FINISHED'} if event.type == 'MOUSEMOVE': if self.drag and self.drag_target: if hasattr(self.drag_target, "head"): #then it's a line, we need to move both? delta = Vector( (event.mouse_region_x, event.mouse_region_y)) - Vector( (self.initial_location_mouse)) self.drag_target.head.x = self.initial_location_head[ 0] + delta[0] self.drag_target.head.y = self.initial_location_head[ 1] + delta[1] self.drag_target.tail.x = self.initial_location_tail[ 0] + delta[0] self.drag_target.tail.y = self.initial_location_tail[ 1] + delta[1] self.drag_target.plane_tan.x = self.initial_location_tan[ 0] + delta[0] self.drag_target.plane_tan.y = self.initial_location_tan[ 1] + delta[1] self.drag_target.head.screen_to_world(context) self.drag_target.tail.screen_to_world(context) self.drag_target.plane_tan.screen_to_world(context) else: self.drag_target.x = event.mouse_region_x self.drag_target.y = event.mouse_region_y self.drag_target.screen_to_world(context) return {'RUNNING_MODAL'} #else detect proximity to items around else: #identify hover target for highlighting if self.cut_lines: new_target = False for c_cut in self.cut_lines: h_target = c_cut.active_element( context, event.mouse_region_x, event.mouse_region_y) if h_target: new_target = True self.hover_target = h_target if not new_target: self.hover_target = None return {'RUNNING_MODAL'} return {'RUNNING_MODAL'} #even right click or escape if event.type in ('RIGHTMOUSE', 'ESC'): if event.type == 'RIGHTMOUSE' and event.value == 'PRESS' and self.hover_target: if hasattr(self.hover_target, "head"): self.cut_lines.remove(self.hover_target) self.hover_target = None else: self.cut_lines.remove(self.hover_target.parent) self.hover_target = None self.push_mesh_data(context) return {'RUNNING_MODAL'} elif event.type == 'RIGHTMOUSE' and event.value == 'RELEASE': return {'RUNNING_MODAL'} else: #clean up callbacks to prevent crash context.area.header_text_set() contour_utilities.callback_cleanup(self, context) self.bme.free() return {'CANCELLED'} if event.type in {'MIDDLEMOUSE'}: for cut_line in self.cut_lines: if cut_line.head.world_position: cut_line.head.screen_from_world(context) cut_line.tail.screen_from_world(context) return {'PASS_THROUGH'} if event.type in { 'WHEELDOWNMOUSE', 'WHEELUPMOUSE', 'NUMPAD_PLUS', 'NUMPAD_MINUS' }: if (event.type == 'WHEELUPMOUSE' and event.ctrl) or (event.type == 'NUMPAD_PLUS' and event.value == 'PRESS'): if len(self.cut_lines): max_segments = min( [len(cut.verts) for cut in self.cut_lines]) else: max_segments = 10 if self.segments >= max_segments: self.segments = max_segments return {'RUNNING_MODAL'} else: self.segments += 1 message = "Segments: %i" % self.segments context.area.header_text_set(text=message) for cut_line in self.cut_lines: if not cut_line.verts: cut_line.hit_object(context, self.original_form) cut_line.cut_object(context, self.original_form, self.bme) cut_line.simplify_cross(self.segments) cut_line.simplify_cross(self.segments) self.push_mesh_data(context, re_order=False) return {'RUNNING_MODAL'} elif (event.type == 'WHEELDOWNMOUSE' and event.ctrl) or (event.type == 'NUMPAD_MINUS' and event.value == 'PRESS'): if self.segments < 4: self.segments = 3 else: self.segments -= 1 message = "Segments: %i" % self.segments context.area.header_text_set(text=message) for cut_line in self.cut_lines: if not cut_line.verts: cut_line.hit_object(context, self.original_form) cut_line.cut_object(context, self.original_form, self.bme) cut_line.simplify_cross(self.segments) cut_line.simplify_cross(self.segments) self.push_mesh_data(context, re_order=False) return {'RUNNING_MODAL'} else: for cut_line in self.cut_lines: if cut_line.head.world_position: cut_line.head.screen_from_world(context) cut_line.tail.screen_from_world(context) return {'PASS_THROUGH'} #event click elif event.type == 'LEFTMOUSE': if event.value == 'RELEASE': if self.drag and self.drag_target: if hasattr(self.drag_target, "head"): #then it's a line delta = Vector((event.mouse_region_x, event.mouse_region_y)) - Vector( (self.initial_location_mouse)) self.drag_target.head.x = self.initial_location_head[ 0] + delta[0] self.drag_target.head.y = self.initial_location_head[ 1] + delta[1] self.drag_target.tail.x = self.initial_location_tail[ 0] + delta[0] self.drag_target.tail.y = self.initial_location_tail[ 1] + delta[1] self.drag_target.plane_tan.x = self.initial_location_tan[ 0] + delta[0] self.drag_target.plane_tan.y = self.initial_location_tan[ 1] + delta[1] self.drag_target.head.screen_to_world(context) self.drag_target.tail.screen_to_world(context) self.drag_target.plane_tan.screen_to_world(context) if self.drag_target.head.world_position: self.drag_target.hit_object(context, self.original_form, update_normal=False, method='HANDLE') else: self.drag_target.hit_object(context, self.original_form, update_normal=True, method='VIEW') self.drag_target.cut_object(context, self.original_form, self.bme) #now we have a new cut, make sure our max segments aren't overwhelmed if len(self.cut_lines): max_segments = min( [len(cut.verts) for cut in self.cut_lines]) else: max_segments = 10 if self.segments >= max_segments: self.segments = max_segments self.drag_target.simplify_cross(self.segments) self.push_mesh_data(context) else: self.drag_target.x = event.mouse_region_x self.drag_target.y = event.mouse_region_y if self.drag_target == self.drag_target.parent.plane_tan: print('changing handle') self.drag_target.screen_to_world(context) self.drag_target.parent.hit_object( context, self.original_form, update_normal=False, method='HANDLE') else: self.drag_target.parent.hit_object( context, self.original_form, update_normal=True, method='VIEW') self.drag_target.parent.cut_object( context, self.original_form, self.bme) self.drag_target.parent.simplify_cross(self.segments) if self.new: self.new = False self.push_mesh_data(context) #clear the drag and hover self.drag = False self.hover_target = None return {'RUNNING_MODAL'} if event.value == 'PRESS': self.drag = True self.drag_target = self.hover_target #presume them ose cant move w/o making it through modal? if hasattr(self.drag_target, "head"): self.initial_location_head = (self.drag_target.head.x, self.drag_target.head.y) self.initial_location_tail = (self.drag_target.tail.x, self.drag_target.tail.y) self.initial_location_tan = (self.drag_target.plane_tan.x, self.drag_target.plane_tan.y) self.initial_location_mouse = (event.mouse_region_x, event.mouse_region_y) if not self.drag_target: v3d = context.space_data region = v3d.region_3d view = region.view_rotation * Vector((0, 0, 1)) self.cut_lines.append( ContourCutLine(event.mouse_region_x, event.mouse_region_y, view)) self.drag_target = self.cut_lines[-1].tail self.new = True return {'RUNNING_MODAL'} return {'RUNNING_MODAL'} return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
def modal(self, context, event): context.area.tag_redraw() if event.type in {'RET', 'NUMPAD_ENTER'} and event.value == 'PRESS': back_to_edit = False if context.mode == 'EDIT_MESH': bpy.ops.object.mode_set(mode='OBJECT') back_to_edit = True bm = self.tmp_bme else: bm = self.dest_bme #the world_matris of the orignal form orig_mx = self.original_form.matrix_world orig_ims = orig_mx.inverted() #the world matrix of the destination (retopo) mesh reto_mx = self.desination_ob.matrix_world reto_imx = reto_mx.inverted() #make list of bmverts...these should go smoothly into bmverts = [] for vert in self.verts: bmverts.append(bm.verts.new(tuple(reto_imx * (orig_mx * vert)))) # Initialize the index values of this sequence...stupi they aren't going in there!) self.dest_bme.verts.index_update() #this is tricky, I'm hoping that because my vert list is #actually composed of BMVerts that this will add in mesh data #smoothly with no problems. bmfaces = [] for face in self.faces: #actual BMVerts not indices I think? new_face = tuple([bmverts[i] for i in face]) bmfaces.append(bm.faces.new(new_face)) if not back_to_edit: # Finish up, write the bmesh back to the mesh bm.to_mesh(self.dest_me) #thies means we created a new object context.scene.objects.link(self.desination_ob) else: #disabled unti the BMesh API supports the dest keyword argument #bmesh.ops.duplicate(bm, geom = bm.verts[:] + bm.edges[:] + bm.faces[:],dest = self.dest_bme) # Finish up, write the bmesh back to the mesh bm.to_mesh(self.dest_me) context.scene.objects.link(self.retopo_ob) self.retopo_ob.update_tag() bpy.ops.object.select_all(action='DESELECT') self.retopo_ob.select = True context.scene.objects.active = self.desination_ob self.desination_ob.select = True bpy.ops.object.join() self.original_form.select = True self.desination_ob.update_tag() context.scene.update() if back_to_edit: bpy.ops.object.mode_set(mode = 'EDIT') context.area.header_text_set() contour_utilities.callback_cleanup(self,context) bm.free() self.dest_bme.free() self.bme.free() return{'FINISHED'} if event.type == 'MOUSEMOVE': if self.drag and self.drag_target: if hasattr(self.drag_target,"head"): #then it's a line, we need to move both? delta = Vector((event.mouse_region_x,event.mouse_region_y)) - Vector((self.initial_location_mouse)) self.drag_target.head.x = self.initial_location_head[0] + delta[0] self.drag_target.head.y = self.initial_location_head[1] + delta[1] self.drag_target.tail.x = self.initial_location_tail[0] + delta[0] self.drag_target.tail.y = self.initial_location_tail[1] + delta[1] self.drag_target.plane_tan.x = self.initial_location_tan[0] + delta[0] self.drag_target.plane_tan.y = self.initial_location_tan[1] + delta[1] self.drag_target.head.screen_to_world(context) self.drag_target.tail.screen_to_world(context) self.drag_target.plane_tan.screen_to_world(context) else: self.drag_target.x = event.mouse_region_x self.drag_target.y = event.mouse_region_y self.drag_target.screen_to_world(context) return {'RUNNING_MODAL'} #else detect proximity to items around else: #identify hover target for highlighting if self.cut_lines: new_target = False for c_cut in self.cut_lines: h_target = c_cut.active_element(context,event.mouse_region_x,event.mouse_region_y) if h_target: new_target = True self.hover_target = h_target if not new_target: self.hover_target = None return {'RUNNING_MODAL'} return {'RUNNING_MODAL'} #even right click or escape if event.type in ('RIGHTMOUSE', 'ESC'): if event.type == 'RIGHTMOUSE' and event.value == 'PRESS' and self.hover_target: if hasattr(self.hover_target, "head"): self.cut_lines.remove(self.hover_target) self.hover_target = None else: self.cut_lines.remove(self.hover_target.parent) self.hover_target = None self.push_mesh_data(context) return {'RUNNING_MODAL'} elif event.type == 'RIGHTMOUSE' and event.value == 'RELEASE': return {'RUNNING_MODAL'} else: #clean up callbacks to prevent crash context.area.header_text_set() contour_utilities.callback_cleanup(self,context) self.bme.free() return {'CANCELLED'} if event.type in {'MIDDLEMOUSE'}: for cut_line in self.cut_lines: if cut_line.head.world_position: cut_line.head.screen_from_world(context) cut_line.tail.screen_from_world(context) return {'PASS_THROUGH'} if event.type in {'WHEELDOWNMOUSE','WHEELUPMOUSE','NUMPAD_PLUS','NUMPAD_MINUS'}: if (event.type == 'WHEELUPMOUSE' and event.ctrl) or (event.type == 'NUMPAD_PLUS' and event.value == 'PRESS'): if len(self.cut_lines): max_segments = min([len(cut.verts) for cut in self.cut_lines]) else: max_segments = 10 if self.segments >= max_segments: self.segments = max_segments return {'RUNNING_MODAL'} else: self.segments += 1 message = "Segments: %i" % self.segments context.area.header_text_set(text = message) for cut_line in self.cut_lines: if not cut_line.verts: cut_line.hit_object(context, self.original_form) cut_line.cut_object(context, self.original_form, self.bme) cut_line.simplify_cross(self.segments) cut_line.simplify_cross(self.segments) self.push_mesh_data(context,re_order = False) return {'RUNNING_MODAL'} elif (event.type == 'WHEELDOWNMOUSE' and event.ctrl) or (event.type == 'NUMPAD_MINUS' and event.value == 'PRESS'): if self.segments < 4: self.segments = 3 else: self.segments -= 1 message = "Segments: %i" % self.segments context.area.header_text_set(text = message) for cut_line in self.cut_lines: if not cut_line.verts: cut_line.hit_object(context, self.original_form) cut_line.cut_object(context, self.original_form, self.bme) cut_line.simplify_cross(self.segments) cut_line.simplify_cross(self.segments) self.push_mesh_data(context,re_order = False) return {'RUNNING_MODAL'} else: for cut_line in self.cut_lines: if cut_line.head.world_position: cut_line.head.screen_from_world(context) cut_line.tail.screen_from_world(context) return{'PASS_THROUGH'} #event click elif event.type == 'LEFTMOUSE': if event.value == 'RELEASE': if self.drag and self.drag_target: if hasattr(self.drag_target,"head"): #then it's a line delta =Vector((event.mouse_region_x,event.mouse_region_y)) - Vector((self.initial_location_mouse)) self.drag_target.head.x = self.initial_location_head[0] + delta[0] self.drag_target.head.y = self.initial_location_head[1] + delta[1] self.drag_target.tail.x = self.initial_location_tail[0] + delta[0] self.drag_target.tail.y = self.initial_location_tail[1] + delta[1] self.drag_target.plane_tan.x = self.initial_location_tan[0] + delta[0] self.drag_target.plane_tan.y = self.initial_location_tan[1] + delta[1] self.drag_target.head.screen_to_world(context) self.drag_target.tail.screen_to_world(context) self.drag_target.plane_tan.screen_to_world(context) if self.drag_target.head.world_position: self.drag_target.hit_object(context, self.original_form, update_normal = False, method = 'HANDLE') else: self.drag_target.hit_object(context, self.original_form, update_normal = True, method = 'VIEW') self.drag_target.cut_object(context, self.original_form, self.bme) #now we have a new cut, make sure our max segments aren't overwhelmed if len(self.cut_lines): max_segments = min([len(cut.verts) for cut in self.cut_lines]) else: max_segments = 10 if self.segments >= max_segments: self.segments = max_segments self.drag_target.simplify_cross(self.segments) self.push_mesh_data(context) else: self.drag_target.x = event.mouse_region_x self.drag_target.y = event.mouse_region_y if self.drag_target == self.drag_target.parent.plane_tan: print('changing handle') self.drag_target.screen_to_world(context) self.drag_target.parent.hit_object(context, self.original_form, update_normal = False, method = 'HANDLE') else: self.drag_target.parent.hit_object(context, self.original_form, update_normal = True, method = 'VIEW') self.drag_target.parent.cut_object(context, self.original_form, self.bme) self.drag_target.parent.simplify_cross(self.segments) if self.new: self.new = False self.push_mesh_data(context) #clear the drag and hover self.drag = False self.hover_target = None return {'RUNNING_MODAL'} if event.value == 'PRESS': self.drag = True self.drag_target = self.hover_target #presume them ose cant move w/o making it through modal? if hasattr(self.drag_target,"head"): self.initial_location_head = (self.drag_target.head.x, self.drag_target.head.y) self.initial_location_tail = (self.drag_target.tail.x, self.drag_target.tail.y) self.initial_location_tan = (self.drag_target.plane_tan.x, self.drag_target.plane_tan.y) self.initial_location_mouse = (event.mouse_region_x,event.mouse_region_y) if not self.drag_target: v3d = context.space_data region = v3d.region_3d view = region.view_rotation * Vector((0,0,1)) self.cut_lines.append(ContourCutLine(event.mouse_region_x, event.mouse_region_y, view)) self.drag_target = self.cut_lines[-1].tail self.new = True return {'RUNNING_MODAL'} return {'RUNNING_MODAL'} return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
def modal(self, context, event): context.area.tag_redraw() if event.type == 'MOUSEMOVE': if self.drag and self.drag_target: if hasattr(self.drag_target,"head"): #then it's a line, we need to move both? delta = Vector((event.mouse_region_x,event.mouse_region_y)) - Vector((self.initial_location_mouse)) self.drag_target.head.x = self.initial_location_head[0] + delta[0] self.drag_target.head.y = self.initial_location_head[1] + delta[1] self.drag_target.tail.x = self.initial_location_tail[0] + delta[0] self.drag_target.tail.y = self.initial_location_tail[1] + delta[1] else: self.drag_target.x = event.mouse_region_x self.drag_target.y = event.mouse_region_y return {'RUNNING_MODAL'} #else detect proximity to items around else: #identify hover target for highlighting if self.cut_lines: new_target = False for c_cut in self.cut_lines: h_target = c_cut.active_element(context,event.mouse_region_x,event.mouse_region_y) if h_target: new_target = True self.hover_target = h_target if not new_target: self.hover_target = None return {'RUNNING_MODAL'} return {'RUNNING_MODAL'} #even right click or escape if event.type in ('RIGHTMOUSE', 'ESC'): #clean up callbacks to prevent crash contour_utilities.callback_cleanup(self,context) return {'CANCELLED'} #event click elif event.type == 'LEFTMOUSE': if event.value == 'RELEASE': if self.drag and self.drag_target: if hasattr(self.drag_target,"head"): #then it's a line delta =Vector((event.mouse_region_x,event.mouse_region_y)) - Vector((self.initial_location_mouse)) self.drag_target.head.x = self.initial_location_head[0] + delta[0] self.drag_target.head.y = self.initial_location_head[1] + delta[1] self.drag_target.tail.x = self.initial_location_tail[0] + delta[0] self.drag_target.tail.y = self.initial_location_tail[1] + delta[1] else: self.drag_target.x = event.mouse_region_x self.drag_target.y = event.mouse_region_y #clear the drag and hover self.drag = False self.hover_target = None return {'RUNNING_MODAL'} if event.value == 'PRESS': self.drag = True self.drag_target = self.hover_target #presume them ose cant move w/o making it through modal? if hasattr(self.drag_target,"head"): self.initial_location_head = (self.drag_target.head.x, self.drag_target.head.y) self.initial_location_tail = (self.drag_target.tail.x, self.drag_target.tail.y) self.initial_location_mouse = (event.mouse_region_x,event.mouse_region_y) if not self.drag_target: v3d = context.space_data region = v3d.region_3d view = region.view_rotation * Vector((0,0,1)) self.cut_lines.append(ContourCutLine(event.mouse_region_x, event.mouse_region_y, view)) self.drag_target = self.cut_lines[-1].tail return {'RUNNING_MODAL'} return {'RUNNING_MODAL'} return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}