def execute(self, context): props = context.scene.quicker_props if bpy.ops.object.mode_set.poll(): bpy.ops.object.mode_set(mode='OBJECT') sx, sy = self.strokes[0]["mouse"] ex, ey = self.strokes[-1]["mouse"] mouse = (sx, sy) ori = region_2d_to_location_3d(context.region, context.space_data.region_3d, mouse, self.cursor) mouse = (ex, ey) rad = region_2d_to_location_3d(context.region, context.space_data.region_3d, mouse, self.cursor) bpy.ops.curve.primitive_bezier_circle_add(radius=(rad - ori).magnitude, view_align=True, location=ori) context.object.data.dimensions = '2D' context.object.data.bevel_depth = props.bevel_depth context.object.data.resolution_u = 24 if not props.fill: context.object.data.fill_mode = 'NONE' mat = bpy.data.materials.new('Material') context.object.data.materials.append(mat) mat.use_shadeless = props.shadeless mat.diffuse_color = props.color context.space_data.cursor_location = self.cursor self.strokes = [] return {'FINISHED'}
def CreateCylinder(self, context): me = bpy.data.meshes.new('C_Cylinder') ob = bpy.data.objects.new('C_Cylinder', me) self.CurrentObj = ob scene = context.scene region = context.region rv3d = context.region_data coord = self.mouse_path[0][0], self.mouse_path[0][1] depthLocation = region_2d_to_vector_3d(region, rv3d, coord) self.ViewVector = depthLocation loc = region_2d_to_location_3d(region, rv3d, coord, depthLocation) mat = context.space_data.region_3d.view_matrix.transposed().to_3x3( ).to_4x4() ob.matrix_world = mat ob.location = loc bpy.context.scene.objects.link(ob) t_bm = bmesh.new() t_bm.from_mesh(me) x0 = self.mouse_path[0][0] y0 = self.mouse_path[0][1] x1 = self.mouse_path[1][0] y1 = self.mouse_path[1][1] v0 = mathutils.Vector((self.mouse_path[0][0], self.mouse_path[0][1], 0)) v1 = mathutils.Vector((self.mouse_path[1][0], self.mouse_path[1][1], 0)) v0 -= v1 radius = self.mouse_path[1][0] - self.mouse_path[0][0] DEG2RAD = 3.14159 / (180 / self.stepAngle[self.step]) if (self.ctrl): shift = (3.14159 / (360 / self.stepAngle[self.step])) * self.stepRotation else: shift = (self.mouse_path[1][1] - self.mouse_path[0][1]) / 50 # Passe en revue tous les points du cercle pour les convertir FacesList = [] for i in range(0, int(360 / self.stepAngle[self.step])): degInRad = i * DEG2RAD v0 = x0 + self.xpos + int( math.cos(degInRad + shift) * radius), y0 + self.ypos + int( math.sin(degInRad + shift) * radius) vec = region_2d_to_vector_3d(region, rv3d, v0) loc0 = region_2d_to_location_3d(region, rv3d, v0, vec) - loc loc0 = loc0 * mat t_v0 = t_bm.verts.new(loc0) FacesList.append(t_v0) t_bm.verts.index_update() t_face = t_bm.faces.new(FacesList) t_bm.to_mesh(me)
def get_factor(self, context, edges_orig): """get the length in the space of edited object which correspond to 1px of 3d view. This method is used to convert the distance of mouse movement to offsetting width in interactive mode. """ ob = context.edit_object mat_w = ob.matrix_world reg = context.region reg3d = context.space_data.region_3d # Don't use context.region_data # because this will cause error # when invoked from header menu. co_median = Vector((0, 0, 0)) for e in edges_orig: co_median += e.verts[0].co co_median /= len(edges_orig) depth_loc = mat_w * co_median # World coords of median point win_left = Vector((0, 0)) win_right = Vector((reg.width, 0)) left = view3d_utils.region_2d_to_location_3d(reg, reg3d, win_left, depth_loc) right = view3d_utils.region_2d_to_location_3d(reg, reg3d, win_right, depth_loc) vec_width = mat_w.inverted_safe() * (right - left) # width vector in the object space width_3d = vec_width.length # window width in the object space return width_3d / reg.width
def CreatePolygon(self, context): me = bpy.data.meshes.new('C_Poly') ob = bpy.data.objects.new('C_Poly', me) self.CurrentObj = ob scene = context.scene region = context.region rv3d = context.region_data coord = self.mouse_path[0][0], self.mouse_path[0][1] depthLocation = region_2d_to_vector_3d(region, rv3d, coord) self.ViewVector = depthLocation loc = region_2d_to_location_3d(region, rv3d, coord, depthLocation) mat = context.space_data.region_3d.view_matrix.transposed().to_3x3().to_4x4() ob.matrix_world = mat ob.location = loc bpy.context.scene.objects.link(ob) t_bm = bmesh.new() t_bm.from_mesh(me) # Parcours tous les points et les convertit avant de les sauvegarder FacesList = [] NbVertices = 0 for x, y in self.mouse_path: v0 = x + self.xpos, y + self.ypos vec = region_2d_to_vector_3d(region, rv3d, v0) loc0 = region_2d_to_location_3d(region, rv3d, v0, vec) - loc loc0 = loc0 * mat x0 = loc0[0] y0 = loc0[1] z0 = loc0[2] NbVertices += 1 if(NbVertices == 1): t_v0 = t_bm.verts.new((x0, y0, z0)) t_init = t_v0 xInit = x0 yInit = y0 zInit = z0 t_bm.verts.index_update() FacesList.append(t_v0) else: t_v1 = t_bm.verts.new((x0, y0, z0)) t_edges = t_bm.edges.new([t_v0, t_v1]) FacesList.append(t_v1) NbVertices = 1 t_v0 = t_v1 if(self.Closed): t_v1 = t_bm.verts.new((xInit, yInit, zInit)) t_edges = t_bm.edges.new([t_v0, t_v1]) FacesList.append(t_v1) t_face = t_bm.faces.new(FacesList) t_bm.to_mesh(me)
def get_click_point_info(x, y, ctx): cp = ClickPoint() view_orient, view_type = get_view_orientation(ctx) region = ctx.region region_data = ctx.space_data.region_3d if view_type in ['PERSP', 'CAMERA']: view_matrix = region_data.view_matrix.inverted() ray_start = view_matrix.to_translation() ray_depth = view_matrix @ Vector((0, 0, -100000)) #TODO from view ray_end = region_2d_to_location_3d(region, region_data, (x, y), ray_depth) p = get_triface_from_orient(view_orient) cp.view = mathutils.geometry.intersect_ray_tri(p[0], p[1], p[2], ray_end, ray_start, False) if cp.view == None: cp.view = Vector((0, 0, 0)) else: cp.view = region_2d_to_location_3d(region, region_data, (x, y), (0, 0, 0)) cp.screen = region_2d_to_location_3d(region, region_data, (x, y), (0, 0, 0)) cp.local = switch_axis_by_orient(view_orient, cp.view) cp.orient = Vector(get_rotation_from_orient(view_orient)) if view_type == 'ORTHO' and view_orient == 'USER': # TODO in orthografic user view not work correctly r3d = ctx.area.spaces.active.region_3d view_rot = r3d.view_matrix.to_euler() cp.view_name = view_orient return cp
def get_zoom_factor(mxw, coords, multiply=10, debug=False): """ create factor based on distance to given location and region width for zoom independet scaling based on work by Hidesato Ikeya from offset edges addon upgraded to 2.8x by Machin3 """ # get center/average location of coords center = mxw @ average_locations(coords) region = bpy.context.region r3d = bpy.context.space_data.region_3d win_left = Vector((0, 0)) win_right = Vector((region.width, 0)) # project window borders into world space to the center of the selection left = region_2d_to_location_3d(region, r3d, win_left, center) right = region_2d_to_location_3d(region, r3d, win_right, center) # width = (right - left).length # region with vector length in world space width = ((right - left) @ mxw.inverted()).length # also compensate for object scaling factor = width / region.width if debug: print("zoom factor:", factor) return factor * multiply
def modal(self, context, event): if event.type == 'LEFTMOUSE': if event.value == 'PRESS': x, y = event.mouse_region_x, event.mouse_region_y loc = region_2d_to_location_3d(context.region, context.space_data.region_3d, (x, y), self.obj.location) self.pre_loc = loc bones = context.active_object.pose.bones min_dist = sys.float_info.max for bone in bones: dist = LA.norm( np.array((loc - bone.center - self.obj.location)), 2) if dist < min_dist: min_dist = dist self.bone = bone # bone.select = True self.left_pressed = True return {'RUNNING_MODAL'} if event.value == 'RELEASE': if self.counter > context.scene.frame_block_nb: context.scene.frame_block_nb = self.counter return {'FINISHED'} if (event.type == 'MOUSEMOVE') and (self.left_pressed == True): x, y = event.mouse_region_x, event.mouse_region_y loc = region_2d_to_location_3d(context.region, context.space_data.region_3d, (x, y), self.obj.location) self.bone.rotation_mode = 'QUATERNION' pivot_loc = self.bone.head + self.obj.location vec1 = loc - pivot_loc vec2 = self.pre_loc - pivot_loc angle = vec1.angle(vec2) normal = -np.cross(np.array(vec1), np.array(vec2)) cam = bpy.data.objects['Camera'] axis = Vector((normal[0], normal[1], normal[2])).normalized() quat = mathutils.Quaternion(axis, angle) # print(quat) mat = (Matrix.Translation(pivot_loc) * quat.to_matrix().to_4x4() * Matrix.Translation(-pivot_loc)) self.bone.matrix = self.obj.matrix_world.inverted( ) * mat * self.obj.matrix_world * self.bone.matrix self.pre_loc = loc self.bone.keyframe_insert(data_path="rotation_quaternion", frame=(self.current_frame + self.counter)) self.counter += 1 return {'RUNNING_MODAL'} return {'PASS_THROUGH'}
def fromTopView(context): '''Create a 2D BBOX from Blender 3dview if the view is top left ortho else return None''' scn = context.scene area = context.area if area.type != 'VIEW_3D': return None reg = context.region reg3d = context.region_data if reg3d.view_perspective != 'ORTHO' or tuple( reg3d.view_matrix.to_euler()) != (0, 0, 0): print("View3d must be in top ortho") return None # w, h = area.width, area.height coords = (w, h) vec = region_2d_to_vector_3d(reg, reg3d, coords) loc_ne = region_2d_to_location_3d(reg, reg3d, coords, vec) xmax, ymax = loc_ne.x, loc_ne.y # coords = (0, 0) vec = region_2d_to_vector_3d(reg, reg3d, coords) loc_sw = region_2d_to_location_3d(reg, reg3d, coords, vec) xmin, ymin = loc_sw.x, loc_sw.y # return BBOX(xmin=xmin, ymin=ymin, xmax=xmax, ymax=ymax)
def get_factor(self, context, edges_orig): """get the length in the space of edited object which correspond to 1px of 3d view. This method is used to convert the distance of mouse movement to offsetting width in interactive mode. """ ob = context.edit_object mat_w = ob.matrix_world reg = context.region reg3d = context.space_data.region_3d # Don't use context.region_data # because this will cause error # when invoked from header menu. co_median = Vector((0, 0, 0)) for e in edges_orig: co_median += e.verts[0].co co_median /= len(edges_orig) depth_loc = mat_w * co_median # World coords of median point win_left = Vector((0, 0)) win_right = Vector((reg.width, 0)) left = view3d_utils.region_2d_to_location_3d(reg, reg3d, win_left, depth_loc) right = view3d_utils.region_2d_to_location_3d(reg, reg3d, win_right, depth_loc) vec_width = mat_w.inverted_safe() * ( right - left) # width vector in the object space width_3d = vec_width.length # window width in the object space return width_3d / reg.width
def execute(self, context): props = context.scene.quicker_props if bpy.ops.object.mode_set.poll(): bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.curve.primitive_bezier_curve_add(enter_editmode=True, view_align=True) bpy.ops.curve.select_all(action='SELECT') bpy.ops.curve.delete(type='VERT') context.object.data.dimensions = '2D' context.object.data.bevel_depth = props.bevel_depth context.object.data.resolution_u = 24 if not props.fill: context.object.data.fill_mode = 'NONE' mat = bpy.data.materials.new('Material') context.object.data.materials.append(mat) mat.use_shadeless = props.shadeless mat.diffuse_color = props.color context.space_data.cursor_location = self.cursor sx, sy = self.strokes[0]["mouse"] ex, ey = self.strokes[-1]["mouse"] o = math.atan2(ey-sy, ex-sx) m = props.star_num d = props.star_depth strokes = [] for n in range(int(m)): ang = 2 * PI/m * n bet = 2 * PI/m * (n+0.5) rad = math.sqrt((ex-sx) ** 2 + (ey-sy) ** 2) x = rad * math.cos(ang + o) + sx y = rad * math.sin(ang + o) + sy mouse = (x, y) loc = region_2d_to_location_3d(context.region, context.space_data.region_3d, mouse, self.cursor) strokes.append({"name": "", "location": loc, "mouse": mouse, "pressure": 1, "pen_flip": False, "time": 0, "is_start": False, "size": 0}) x = d * rad * math.cos(bet + o) + sx y = d * rad * math.sin(bet + o) + sy mouse = (x, y) loc = region_2d_to_location_3d(context.region, context.space_data.region_3d, mouse, self.cursor) strokes.append({"name": "", "location": loc, "mouse": mouse, "pressure": 1, "pen_flip": False, "time": 0, "is_start": False, "size": 0}) if bpy.ops.curve.draw.poll() and len(strokes) > 0: bpy.ops.curve.draw(error_threshold=0.0, use_cyclic=True, stroke=strokes) tool_setting = context.scene.tool_settings if not tool_setting.curve_paint_settings.curve_type == 'BEZIER': bpy.ops.curve.cyclic_toggle() self.strokes = [] if bpy.ops.object.editmode_toggle.poll(): bpy.ops.object.editmode_toggle() return {'FINISHED'}
def get_np_region_cos(coords, region, region_data, depth=1.5): # # Use numpy to get coords in region space # Bottom Left of region is 0,0 # m = np.array(region_data.view_matrix) pmat = m[:3, :3].T # rotates backwards without T loc = m[:3, 3] cent_reg_co = pmat @ Vector(np.array([0, 0, -depth])-loc) bl_reg_co = view3d_utils.region_2d_to_location_3d( region, region_data, [0, 0], cent_reg_co) br_reg_co = view3d_utils.region_2d_to_location_3d( region, region_data, [region.width, 0], cent_reg_co) tl_reg_co = view3d_utils.region_2d_to_location_3d( region, region_data, [0, region.height], cent_reg_co) loc_arr = np.array(coords) loc_arr.shape = [len(coords), 3] view_vec = np.array(view3d_utils.region_2d_to_vector_3d( region, region_data, [region.width/2, region.height/2])) view_vecs = np.tile(view_vec, (loc_arr.shape[0], 1)) if region_data.view_perspective == 'PERSP': scale_center = np.array(view3d_utils.region_2d_to_origin_3d( region, region_data, [region.width/2, region.height/2])) dir_vecs = loc_arr - scale_center dot_offsets = np.sum((loc_arr - scale_center) * view_vec, axis=1) scale_3d = depth/dot_offsets flat_locs = scale_center + dir_vecs*scale_3d[:, None] elif region_data.view_perspective == 'ORTHO': scale_center = np.array(bl_reg_co) dir_vecs = view_vecs dot_offsets = np.sum((loc_arr - scale_center) * view_vec, axis=1) flat_locs = loc_arr - dir_vecs*dot_offsets[:, None] vec_w = np.array((br_reg_co-bl_reg_co).normalized()) vec_h = np.array((tl_reg_co-bl_reg_co).normalized()) h_offsets = (flat_locs - np.array(bl_reg_co)) @ vec_w v_offsets = (flat_locs - np.array(bl_reg_co)) @ vec_h r_cos = np.zeros(loc_arr.size) r_cos.shape = loc_arr.shape r_cos[:, 0] = h_offsets r_cos[:, 1] = v_offsets r_cos *= region.width/(br_reg_co-bl_reg_co).length return r_cos
def handles_to_screen(self,context): region = context.region rv3d = context.space_data.region_3d self.head.world_position = region_2d_to_location_3d(region, rv3d, (self.head.x, self.head.y),self.plane_pt) self.tail.world_position = region_2d_to_location_3d(region, rv3d, (self.tail.x, self.tail.y),self.plane_pt)
def handles_to_screen(self, context): region = context.region rv3d = context.space_data.region_3d self.head.world_position = region_2d_to_location_3d( region, rv3d, (self.head.x, self.head.y), self.plane_pt) self.tail.world_position = region_2d_to_location_3d( region, rv3d, (self.tail.x, self.tail.y), self.plane_pt)
def CreateCylinder(self, context): me = bpy.data.meshes.new('C_Cylinder') ob = bpy.data.objects.new('C_Cylinder', me) self.CurrentObj = ob scene = context.scene region = context.region rv3d = context.region_data coord = self.mouse_path[0][0], self.mouse_path[0][1] depthLocation = region_2d_to_vector_3d(region, rv3d, coord) self.ViewVector = depthLocation loc = region_2d_to_location_3d(region, rv3d, coord, depthLocation) mat = context.space_data.region_3d.view_matrix.transposed().to_3x3().to_4x4() ob.matrix_world = mat ob.location = loc bpy.context.scene.objects.link(ob) t_bm = bmesh.new() t_bm.from_mesh(me) x0 = self.mouse_path[0][0] y0 = self.mouse_path[0][1] x1 = self.mouse_path[1][0] y1 = self.mouse_path[1][1] v0 = mathutils.Vector((self.mouse_path[0][0], self.mouse_path[0][1], 0)) v1 = mathutils.Vector((self.mouse_path[1][0], self.mouse_path[1][1], 0)) v0 -= v1 radius = self.mouse_path[1][0] - self.mouse_path[0][0] DEG2RAD = 3.14159 / (180 / self.stepAngle[self.step]) if(self.ctrl): shift = (3.14159 / (360 / self.stepAngle[self.step])) * self.stepRotation else: shift = (self.mouse_path[1][1] - self.mouse_path[0][1]) / 50 # Passe en revue tous les points du cercle pour les convertir FacesList = [] for i in range(0, int(360 / self.stepAngle[self.step])): degInRad = i * DEG2RAD v0 = x0 + self.xpos + int(math.cos(degInRad + shift) * radius), y0 + self.ypos + int(math.sin(degInRad + shift) * radius) vec = region_2d_to_vector_3d(region, rv3d, v0) loc0 = region_2d_to_location_3d(region, rv3d, v0, vec) - loc loc0 = loc0 * mat t_v0 = t_bm.verts.new(loc0) FacesList.append(t_v0) t_bm.verts.index_update() t_face = t_bm.faces.new(FacesList) t_bm.to_mesh(me)
def ray(self, xy): # 0,0 means region's bottom left corner region = self.region rv3d = self.region_data view_dir = self.forward near, far, origin = self.zbuf_range near = origin + view_dir * near far = origin + view_dir * far # Just to be sure (sometimes scene.ray_cast sayid that ray start/end aren't 3D) a = region_2d_to_location_3d(region, rv3d, Vector(xy).to_2d(), near).to_3d() b = region_2d_to_location_3d(region, rv3d, Vector(xy).to_2d(), far).to_3d() return a, b
def CreateCutSquare(self, context): """ Create a rectangle mesh """ far_limit = 10000.0 faces = [] # Get the mouse coordinates coord = self.mouse_path[0][0], self.mouse_path[0][1] # New mesh me = bpy.data.meshes.new('CMT_Square') bm = bmesh.new() bm.from_mesh(me) # New object and link it to the scene ob = bpy.data.objects.new('CMT_Square', me) self.CurrentObj = ob context.collection.objects.link(ob) # Scene information region = context.region rv3d = context.region_data depth_location = region_2d_to_vector_3d(region, rv3d, coord) self.ViewVector = depth_location # Get a point on a infinite plane and its direction plane_normal = depth_location plane_direction = plane_normal.normalized() if self.snapCursor: plane_point = context.scene.cursor.location else: plane_point = self.OpsObj.location if self.OpsObj is not None else Vector( (0.0, 0.0, 0.0)) # Find the intersection of a line going thru each vertex and the infinite plane for v_co in self.rectangle_coord: vec = region_2d_to_vector_3d(region, rv3d, v_co) p0 = region_2d_to_location_3d(region, rv3d, v_co, vec) p1 = region_2d_to_location_3d(region, rv3d, v_co, vec) + plane_direction * far_limit faces.append( bm.verts.new( intersect_line_plane(p0, p1, plane_point, plane_direction))) # Update vertices index bm.verts.index_update() # New faces t_face = bm.faces.new(faces) # Set mesh bm.to_mesh(me)
def ray(self, xy, coords='REGION'): region = self.region rv3d = self.region_data xy = self.convert_ui_coord(xy, coords, 'REGION') view_dir = self.forward near, far, origin = self.zbuf_range near = origin + view_dir * near far = origin + view_dir * far # Just to be sure (sometimes scene.ray_cast said that ray start/end aren't 3D) a = region_2d_to_location_3d(region, rv3d, xy.to_2d(), near).to_3d() b = region_2d_to_location_3d(region, rv3d, xy.to_2d(), far).to_3d() return a, b
def raycast(self, context, event): # Get the mouse position thanks to the event self.mouse_pos = event.mouse_region_x, event.mouse_region_y # Contextual active object, 2D and 3D regions scene = context.scene region = context.region region3D = context.space_data.region_3d viewlayer = viewlayer_fix_291(self, context) # The direction indicated by the mouse position from the current view self.view_vector = view3d_utils.region_2d_to_vector_3d( region, region3D, self.mouse_pos) # The view point of the user self.view_point = view3d_utils.region_2d_to_origin_3d( region, region3D, self.mouse_pos) # The 3D location in this direction self.world_loc = view3d_utils.region_2d_to_location_3d( region, region3D, self.mouse_pos, self.view_vector) result, self.loc, normal, index, object, matrix = scene.ray_cast( viewlayer, self.view_point, self.view_vector) self.camera.data.dof.use_dof = True if result: self.dis = measure(self.camera.location, self.loc) self.camera.data.dof.focus_distance = self.dis
def handle_mouse_move(self, mouse_pos_2d, mouse_pos_3d, event, context): if self.is_extruding(): dir = self.get_dir() region = context.region rv3d = context.space_data.region_3d mxy = event.mouse_region_x, event.mouse_region_y mpos_3d = region_2d_to_location_3d(region, rv3d, mxy, self._vertices[0]) isect_pt, length = intersect_point_line(mpos_3d, self._vertices[0], self._vertices[0] + dir) self._extrusion = length self.extrude_vertices(context) return True if self._vertex_moving is not None: self._vertices[self._vertex_moving] = mouse_pos_3d return True if self.is_created() and self._is_moving: diff = mouse_pos_3d - self._move_offset self._vertices = [vertex + diff for vertex in self._vertices] self._vertices_extruded = [ vertex + diff for vertex in self._vertices_extruded ] self._move_offset = mouse_pos_3d return True return False
def raycast(self, context, event): # Get the mouse position thanks to the event self.mouse_pos = event.mouse_region_x, event.mouse_region_y # Contextual active object, 2D and 3D regions scene = context.scene region = context.region region3D = context.space_data.region_3d viewlayer = viewlayer_fix_291(self,context) # The direction indicated by the mouse position from the current view self.view_vector = view3d_utils.region_2d_to_vector_3d(region, region3D, self.mouse_pos) # The view point of the user self.view_point = view3d_utils.region_2d_to_origin_3d(region, region3D, self.mouse_pos) # The 3D location in this direction self.world_loc = view3d_utils.region_2d_to_location_3d(region, region3D, self.mouse_pos, self.view_vector) result, self.loc, normal, index, object, matrix = scene.ray_cast(viewlayer, self.view_point, self.view_vector) if result: for obj in context.selected_objects: obj.select_set(False) dg = context.evaluated_depsgraph_get() eval_obj = dg.id_eval_get(object) context.view_layer.objects.active = object.original self.Mat_index = eval_obj.data.polygons[index].material_index object.original.active_material_index = self.Mat_index self.Mat = object.original.active_material
def invoke (self, context, event): viewport_region = context.region viewport_region_data = context.space_data.region_3d viewport_matrix = viewport_region_data.view_matrix.inverted() # Shooting a ray from the camera, through the mouse cursor towards the grid with a length of 100000 # If the camera is more than 100000 units away from the grid it won't detect a point ray_start = viewport_matrix.to_translation() ray_depth = viewport_matrix @ Vector((0,0,-100000)) # Get the 3D vector position of the mouse ray_end = view3d_utils.region_2d_to_location_3d(viewport_region,viewport_region_data, (event.mouse_region_x, event.mouse_region_y), ray_depth ) # A triangle on the grid plane. We use these 3 points to define a plane on the grid point_1 = Vector((0,0,0)) point_2 = Vector((0,1,0)) point_3 = Vector((1,0,0)) # Create a 3D position on the grid under the mouse cursor using the triangle as a grid plane # and the ray cast from the camera position_on_grid = mathutils.geometry.intersect_ray_tri(point_1,point_2,point_3,ray_end,ray_start,False ) # Create an empty for testing empty = self.create_test_empty(context) # Place the empty on the grid under the mouse cursor empty.location = position_on_grid return {'FINISHED'}
def invoke(self, context, event): if context.mode == 'OBJECT': coord = event.mouse_region_x, event.mouse_region_y region = context.region rv3d = context.space_data.region_3d vec = region_2d_to_vector_3d(region, rv3d, coord) loc = region_2d_to_location_3d(region, rv3d, coord, vec) SelectedObjects.storedSelectedObjects = [ obj for obj in context.visible_objects if obj.select ] for obj in SelectedObjects.storedSelectedObjects: obj.select = False oldPivot = bpy.data.objects.get('PivotPro', None) context.scene.tool_settings.use_snap = True if oldPivot is not None: enablePivot(context) oldPivot.location = loc else: createPivot(context) pivot = bpy.data.objects.get( 'PivotPro', None) # it exist now after CreatePivot pivot.location = loc # so put pivot under cursor return {'FINISHED'}
def coords_to_loc_3d(context, coords_2d_seq, depth_location): from bpy_extras.view3d_utils import region_2d_to_location_3d region = context.region rv3d = context.region_data return tuple((region_2d_to_location_3d(region, rv3d, mval, depth_location) for mval in coords_2d_seq))
def mouse_raycast_to_plane(mouse_pos, context, point, normal): ''' Get 3D point on plane from mouse.\n Params:\n \tmouse pos : type = tuple(0,0) \tcontext : type = bpy.context \tpoint : type = Vector, desc = the planes origin \tnormal : type = Vector, desc = the planes direction Returns -> Vector 3D''' # Get the context arguments region = context.region rv3d = context.region_data intersection = Vector((0, 0, 0)) try: # Camera Origin origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, mouse_pos) # Mouse origin mouse = view3d_utils.region_2d_to_vector_3d(region, rv3d, mouse_pos) # Camera Origin + Mouse ray_origin = origin + mouse # From the mouse to the viewport loc = view3d_utils.region_2d_to_location_3d(region, rv3d, mouse_pos, ray_origin - origin) # Ray to plane intersection = mathutils.geometry.intersect_line_plane( ray_origin, loc, point, normal) except: intersection = Vector((0, 0, 0)) if intersection is None: intersection = Vector((0, 0, 0)) return intersection
def add_draw(self, context, event): mouse = (event.mouse_region_x, event.mouse_region_y) loc = region_2d_to_location_3d(context.region, context.space_data.region_3d, mouse, self.cursor) stroke = {"mouse": mouse, "pressure": event.pressure, "location": loc} self.strokes.append(stroke)
def execute(self, context): # Contextual active object, 2D and 3D regions region = bpy.context.region region3D = bpy.context.space_data.region_3d mouse_offset = self.mouse # The direction indicated by the mouse position from the current view view_vector = view3d_utils.region_2d_to_vector_3d( region, region3D, mouse_offset) # The 3D location in this direction offset = view3d_utils.region_2d_to_location_3d(region, region3D, mouse_offset, view_vector) mw = self.active_joint.matrix_world.inverted() mouse_offset_from_first_ja = mw * offset for ja, jb in self.joints: jb.location = ja.location + mouse_offset_from_first_ja # Update active object so the next #exj will get the correct cursor # offset if jb: bpy.context.scene.objects.active = jb return {'FINISHED'}
def modal(self, context, event): verts = self.verts edges = self.edges me = self.me if event.type == 'LEFTMOUSE': if event.value == 'RELEASE': if (self.first): verts = [] found = 'NewMesh' in bpy.data.meshes print(found) if found: bpy.data.meshes.remove(bpy.data.meshes["NewMesh"]) vectorClicked = (view3d_utils.region_2d_to_location_3d( bpy.context.region, bpy.context.space_data.region_3d, (event.mouse_region_x, event.mouse_region_y), mathutils.Vector((0, 0, 0)))) verts.append((vectorClicked[0], vectorClicked[1], 0)) for i in range(len(self.verts) - 1): edges.append((i, i + 1)) self.addVerts(verts) self.verts = verts elif event.type in {'RIGHTMOUSE', 'ESC'}: return {'FINISHED'} return {'RUNNING_MODAL'}
def get_position_on_grid(mouse_pos, ray_max=1e4): viewport_region = bpy.context.region viewport_r3d = bpy.context.region_data viewport_matrix = viewport_r3d.view_matrix.inverted() cam_obj = bpy.context.space_data.camera # Shooting a ray from the camera, through the mouse cursor towards the grid with a length of 1e5 # If the camera is more than 1e5 units away from the grid it won't detect a point ray_start = viewport_matrix.to_translation() ray_depth = viewport_matrix @ Vector((0, 0, -1e5)) # Get the 3D vector position of the mouse ray_end = view3d_utils.region_2d_to_location_3d(viewport_region, viewport_r3d, (mouse_pos[0], mouse_pos[1]), ray_depth) # A triangle on the grid plane. We use these 3 points to define a plane on the grid point_1 = Vector((0, 0, 0)) point_2 = Vector((0, 1, 0)) point_3 = Vector((1, 0, 0)) # Create a 3D position on the grid under the mouse cursor using the triangle as a grid plane # and the ray cast from the camera position_on_grid = mathutils.geometry.intersect_ray_tri(point_1, point_2, point_3, ray_end, ray_start, False) if position_on_grid is None: return None if viewport_is_orthographic(viewport_r3d, None if cam_obj is None else cam_obj.data): # multiply by ray max position_on_grid = position_on_grid * ray_max return position_on_grid
def modal(self, context, event): context.area.tag_redraw() if event.type == 'MOUSEMOVE': #Get the mouse position thanks to the event self.mouse_pos = [event.mouse_region_x, event.mouse_region_y] #Contextual active object, 2D and 3D regions self.object = bpy.context.object region = bpy.context.region region3D = bpy.context.space_data.region_3d #The direction indicated by the mouse position from the current view view_vector = view3d_utils.region_2d_to_vector_3d(region, region3D, self.mouse_pos) #The 3D location in this direction self.loc = view3d_utils.region_2d_to_location_3d(region, region3D, self.mouse_pos, view_vector) #The 3D location converted in object local coordinates self.loc = self.object.matrix_world.inverted() * self.loc elif event.type in {'ESC'}: bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') return {'CANCELLED'} return {'PASS_THROUGH'}
def cursor_2d_to_location_3d(context, event): from bpy_extras.view3d_utils import region_2d_to_vector_3d, region_2d_to_location_3d coords = event.mouse_region_x, event.mouse_region_y region = context.region rv3d = context.space_data.region_3d return region_2d_to_location_3d(region, rv3d, coords, region_2d_to_vector_3d(region, rv3d, coords))
def raycast_mouse(self, context, event): scene = context.scene region = context.region region_3d = context.space_data.region_3d mouse_pos = (event.mouse_region_x, event.mouse_region_y) direction = view3d_utils.region_2d_to_vector_3d( region, region_3d, mouse_pos) endpoint = view3d_utils.region_2d_to_location_3d( region, region_3d, mouse_pos, region_3d.view_location) if region_3d.is_perspective: direction = -direction origin = endpoint + direction * region_3d.view_distance farpoint = origin + direction * 1000 else: origin = endpoint + direction * region_3d.view_distance farpoint = origin - direction * 1000 if self.clone: self.clone.hide = True result, obj, matrix, surface, normal = scene.ray_cast(origin, farpoint) if self.clone: self.clone.hide = False if result: endpoint = surface else: normal = mathutils.Vector((0, 0, 1)) return (endpoint, normal)
def invoke(self, context, event): self.target = bpy.context.active_object if context.space_data.type == 'VIEW_3D': self.scene = context.scene self.region = context.region self.rv3d = context.region_data self.mouse_co = event.mouse_region_x, event.mouse_region_y self.depth = view3d_utils.region_2d_to_vector_3d(self.region, self.rv3d, self.mouse_co) self.emp_co = view3d_utils.region_2d_to_location_3d(self.region, self.rv3d, self.mouse_co, self.depth) bpy.ops.object.select_all(action='DESELECT') # add custom objects bpy.ops.object.empty_add() context.object.location = self.emp_co context.window_manager.modal_handler_add(self) # need active to set origin bpy.context.scene.objects.active = self.target return {'RUNNING_MODAL'} else: self.report({'WARNING'}, "Active space must be a View3d") return {'CANCELLED'}
def raycast_plane(context, event): viewport_region = context.region viewport_region_data = context.space_data.region_3d viewport_matrix = viewport_region_data.view_matrix.inverted() # Shooting a ray from the camera, through the mouse cursor towards the grid with length 100000 # if the camera is more than 10000 units away from the grid it won't detect a hit ray_start = viewport_matrix.to_translation() ray_depth = viewport_matrix @ Vector((0, 0, -10000)) # Get the 3D vector position of the mouse ray_end = view3d_utils.region_2d_to_location_3d( viewport_region, viewport_region_data, (event.mouse_region_x, event.mouse_region_y), ray_depth) # 3 Points to build a plane from point_1 = Vector((0, 0, 0)) point_2 = Vector((0, 1, 0)) point_3 = Vector((1, 0, 0)) # Create a 3D position on the grid under the mouse using the grid plane points # and the ray cast from the camera position_on_grid = mathutils.geometry.intersect_ray_tri( point_1, point_2, point_3, ray_end, ray_start, False) return position_on_grid
def modal(self, context, event): context.area.tag_redraw() if event.type == 'MOUSEMOVE': context.area.header_text_set("WIP") new_pos = region_2d_to_location_3d(context.region, context.space_data.region_3d, (event.mouse_x, event.mouse_y), self.vto0) self.offset = new_pos - self.pos self.vto = self.vto0 + self.offset self.update_shader_batch() elif event.type == 'LEFTMOUSE': cf = self.vto - self.vfrom cf.rotate(self.quat.inverted()) self.bone.simbone.custom_force = cf self.finish(context) return {'FINISHED'} elif event.type in {'RIGHTMOUSE', 'ESC'}: self.finish(context) return {'CANCELLED'} return {'RUNNING_MODAL'}
def get_3d_vertex(context, vertex_2d): region = context.region rv3d = context.space_data.region_3d dir = get_view_direction(context) * -1 return region_2d_to_location_3d(region, rv3d, vertex_2d, dir)
def invoke(self, context, event): rv3d = context.region_data region = context.region self.mode = persistent_settings['mode'] self.transform_all = persistent_settings['transform_all'] self.constrain_x = False self.constrain_y = False if rv3d.view_perspective == 'PERSP': self.report({'WARNING'}, 'Perspective camera unsupported.') return {'CANCELLED'} self.view_perspective = rv3d.view_perspective self.camera_orientation = ( get_view_orientation_from_quaternion(rv3d.view_rotation)) self.region_offset_x = 0 self.region_offset_y = 0 self.initial_mouse = Vector(( event.mouse_region_x, event.mouse_region_y)) self.initial_mouse_location_3d = ( view3d_utils.region_2d_to_location_3d( region, rv3d, self.initial_mouse, Vector())) self.valid_images = [] self.previous_rotation_offset = 0.0 self.revolutions = 0 self.previous_mouse_cp = 1.0 # Get currently visible images for background_image in context.space_data.background_images: image_orientation = background_image.view_axis if (background_image.show_background_image and background_image.image is not None and (rv3d.view_perspective == 'CAMERA' and image_orientation in {'CAMERA', 'ALL'} or rv3d.view_perspective == 'ORTHO' and self.camera_orientation != 'UNDEFINED' and image_orientation in {self.camera_orientation, 'ALL'} )): self.valid_images.append(background_image) if len(self.valid_images): self.active_image = min( persistent_settings['active_image'], len(self.valid_images)-1) self.init_images(self.valid_images) context.window_manager.modal_handler_add(self) args = (self, context) self.do_draw = self.mode in ('ROTATE', 'SCALE') self._handle = bpy.types.SpaceView3D.draw_handler_add( draw_callback_px, args, 'WINDOW', 'POST_PIXEL') return {'RUNNING_MODAL'} else: self.report({'WARNING'}, 'No background image found.') return {'CANCELLED'}
def invoke(self, context, event): if context.area.type == 'VIEW_3D': # the arguments we pass the the callback args = (self, context) # Add the region OpenGL drawing callback self._timer = context.window_manager.event_timer_add(.1, context.window) #bpy.types.WindoManager.event_time_add? self._handle = bpy.types.SpaceView3D.draw_handler_add(bgl_utils.draw_callback_crevice_walking, args, 'WINDOW', 'POST_PIXEL') #initialze important values and gather important info region = context.region rv3d = context.space_data.region_3d coord = event.mouse_region_x, event.mouse_region_y self.tracer_name = context.object.name #adding bpy here because getting weird error self.target_name = [ob.name for ob in context.selected_editable_objects if ob.name != self.tracer_name][0] tracer = bpy.data.objects[self.tracer_name] target = bpy.data.objects[self.target_name] #target.select = False tracer.select = True context.scene.objects.active = tracer #mod = tracer.modifers['Shrinkwrap'] #going to need to do some checking for dumb scenarios #self.target = mod.target vec = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_location_3d(region, rv3d, coord, vec) #raycast onto active object ray_target = ray_origin + 10000*vec [hit, normal, face] = odcutils.obj_ray_cast(target, target.matrix_world, ray_origin, ray_target) self.max_iters = 50 self.keep_iterating = False #turn this off/on when we get convergence on the bias point or add a new bias point self.session_iterations = 0 if hit: self.current_bias_point = target.matrix_world * hit else: self.current_bias_point = target.location self.confirmed_path = [] self.pending_path = [tracer.location.copy()] self.bias_points = [] self.bias_normals = [] #gotta keep track of the normals so we can re-orient the tracker pointed the right way self.step_size = .5 self.convergence_limit = 5 context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} else: self.report({'WARNING'}, "View3D not found, cannot run operator") return {'CANCELLED'}
def mouseTo3d(self, context, x, y): '''Convert event.mouse_region to world coordinates''' coords = (x, y) reg = context.region reg3d = context.region_data vec = region_2d_to_vector_3d(reg, reg3d, coords) loc = region_2d_to_location_3d(reg, reg3d, coords, vec) return loc
def coords_to_loc_3d(context, coords_2d_seq, depth_location): from bpy_extras.view3d_utils import region_2d_to_location_3d region = context.region rv3d = context.region_data return tuple(( region_2d_to_location_3d(region, rv3d, mval, depth_location) for mval in coords_2d_seq ))
def move(self, context, event): xy = region_2d_to_location_3d( context.region, context.space_data.region_3d, (event.mouse_region_x, event.mouse_region_y), Vector(), ).xy self.ob.location.xy = xy
def unproject(points, axis, properties): """Unproject points on a plane to vertices in 3d space.""" for p in points: new_p = p["point"] - p["delta"] * properties["influence"] old_v = p["id"].co new_v = view3d_utils.region_2d_to_location_3d(axis["region"], axis["rv3d"], new_p.to_2d(), p["depth"]) p["v'"] = new_v return points
def unproject(self, xy, pos=None, align=False): # 0,0 means region's bottom left corner if align: xy = snap_pixel_vector(xy) if pos is None: pos = self.focus elif isinstance(pos, (int, float)): pos = self.zbuf_range[2] + self.forward * pos region = self.region rv3d = self.region_data return region_2d_to_location_3d(region, rv3d, xy.copy(), pos.copy())
def unproject(points,axis,properties): """Unproject points on a plane to vertices in 3d space.""" for p in points: new_p = p['point']-p['delta']*properties['influence'] old_v = p['id'].co new_v = view3d_utils.region_2d_to_location_3d(axis['region'],axis['rv3d'],new_p.to_2d(),p['depth']) p["v'"]=new_v return points
def mouseTo3d(context, x, y): '''Convert event.mouse_region to world coordinates''' if context.area.type != 'VIEW_3D': raise Exception('Wrong context') coords = (x, y) reg = context.region reg3d = context.region_data vec = region_2d_to_vector_3d(reg, reg3d, coords) loc = region_2d_to_location_3d(reg, reg3d, coords, vec) #WARNING, this function return indeterminate value when view3d clip distance is too large return loc
def modal(self, context, event): context.area.tag_redraw() if event.type =='LEFT_ALT' or event.type == 'RIGHT_ALT': if event.value == 'PRESS': pt_buf.alt = True if event.value == 'RELEASE': pt_buf.alt = False return {'RUNNING_MODAL'} elif event.type =='LEFT_SHIFT' or event.type == 'RIGHT_SHIFT': if event.value == 'PRESS': pt_buf.shift = True if event.value == 'RELEASE': pt_buf.shift = False return {'RUNNING_MODAL'} elif event.type == 'MOUSEMOVE': if pt_buf.list_m_loc_2d != []: pt_buf_list_m_loc_3d_last_2d = location_3d_to_region_2d(context.region, context.space_data.region_3d, pt_buf.list_m_loc_3d[-1]) if pt_buf.alt == True: pt_buf.x = pt_buf_list_m_loc_3d_last_2d[0] pt_buf.y = event.mouse_region_y elif pt_buf.shift == True: pt_buf.x = event.mouse_region_x pt_buf.y = pt_buf_list_m_loc_3d_last_2d[1] else: pt_buf.x = event.mouse_region_x pt_buf.y = event.mouse_region_y else: pt_buf.x = event.mouse_region_x pt_buf.y = event.mouse_region_y elif event.type == 'LEFTMOUSE': if event.value == 'PRESS': mouse_loc_2d = Vector((pt_buf.x, pt_buf.y)) pt_buf.list_m_loc_2d.append(mouse_loc_2d) mouse_loc_3d = region_2d_to_location_3d(context.region, context.space_data.region_3d, mouse_loc_2d, pt_buf.depth_location) pt_buf.list_m_loc_3d.append(mouse_loc_3d) pt_buf.depth_location = pt_buf.list_m_loc_3d[-1] # <----- depth location elif event.value == 'RELEASE': pass elif event.type == 'RIGHTMOUSE': context.space_data.draw_handler_remove(self._handle_px, 'WINDOW') self.execute(context) pt_buf.sws = 'off' return {'FINISHED'} elif event.type == 'ESC': context.space_data.draw_handler_remove(self._handle_px, 'WINDOW') pt_buf.list_m_loc_2d[:] = [] pt_buf.list_m_loc_3d[:] = [] pt_buf.depth_location = Vector((0.0, 0.0, 0.0)) pt_buf.sws = 'off' return {'CANCELLED'} return {"PASS_THROUGH"}
def unproject(self, xy, pos=None, align=False, coords='REGION'): region = self.region rv3d = self.region_data xy = self.convert_ui_coord(xy, coords, 'REGION') if align: xy = snap_pixel_vector(xy) if pos is None: pos = self.focus elif isinstance(pos, (int, float)): pos = self.zbuf_range[2] + self.forward * pos return region_2d_to_location_3d(region, rv3d, Vector(xy), Vector(pos)).to_3d()
def fromTopView(cls, context): '''Create a 2D BBOX from Blender 3dview if the view is top left ortho else return None''' scn = context.scene area = context.area if area.type != 'VIEW_3D': return None reg = context.region reg3d = context.region_data if reg3d.view_perspective != 'ORTHO' or tuple(reg3d.view_matrix.to_euler()) != (0,0,0): print("View3d must be in top ortho") return None # w, h = area.width, area.height coords = (w, h) vec = region_2d_to_vector_3d(reg, reg3d, coords) loc_ne = region_2d_to_location_3d(reg, reg3d, coords, vec) xmax, ymax = loc_ne.x, loc_ne.y # coords = (0, 0) vec = region_2d_to_vector_3d(reg, reg3d, coords) loc_sw = region_2d_to_location_3d(reg, reg3d, coords, vec) xmin, ymin = loc_sw.x, loc_sw.y # return cls(xmin=xmin, ymin=ymin, xmax=xmax, ymax=ymax)
def get_factor(self, context, pos_mouse, edges): """get the length in the space of edited object which correspond to 1px of 3d view. This method is used to convert the distance of mouse movement to offsetting width in interactive mode. """ ob = context.edit_object mat_w = ob.matrix_world reg = context.region reg3d = context.region_data verts = set(e.verts[0] for e in edges) # get the nearest vertex to the mouse position v_nearest = self.get_nearest_vert(context, pos_mouse, tuple(verts)) depth_loc = mat_w * v_nearest.co # coord of the vertex in the world space win_left = Vector((0, 0)) win_right = Vector((reg.width, 0)) left = view3d_utils.region_2d_to_location_3d(reg, reg3d, win_left, depth_loc) right = view3d_utils.region_2d_to_location_3d(reg, reg3d, win_right, depth_loc) vec_width = mat_w.inverted_safe() * (right - left) # width vector in the object space width_3d = vec_width.length # window width in the object space return width_3d / reg.width
def mouse_path_to_spline( context, mouse_path: list, ) -> None: curve_freehand = context.scene.curve_freehand spline_data = calc_spline( mouse_path, error=curve_freehand.error_threshold, use_detect_corners=curve_freehand.use_detect_corners, detect_corners_angle_threshold=curve_freehand.detect_corners_angle_threshold, ) obj = context.object curve = obj.data matrix_inverse = obj.matrix_world.inverted() from bpy_extras.view3d_utils import region_2d_to_location_3d region = context.region rv3d = context.region_data depth_pt = context_cursor(context) spline_data = [ Cubic(*[ (*(matrix_inverse * region_2d_to_location_3d(region, rv3d, pt, depth_pt)), *pt[2:]) for pt in cubic]) for cubic in spline_data] bpy.ops.curve.select_all(action='DESELECT') spline = curve.splines.new(type='BEZIER') points_to_spline( spline, spline_data, curve_freehand.pressure_min, curve_freehand.pressure_max, ) for bezt in spline.bezier_points: bezt.select_control_point = True bezt.select_left_handle = True bezt.select_right_handle = True # we could get this from the calculation... a, b, c = bezt.handle_left, bezt.co, bezt.handle_right if (a - b).angle(b - c, -1.0) < 1e-2: bezt.handle_left_type = bezt.handle_right_type = 'ALIGNED'
def from_ndc(self, pos, to_01=False): region = self.region rv3d = self.region_data nx = pos[0] ny = pos[1] nz = pos[2] if not to_01: nx = (nx + 1.0) * 0.5 ny = (ny + 1.0) * 0.5 nz = (nz + 1.0) * 0.5 near, far, origin = self.zbuf_range xy = Vector((nx * region.width, ny * region.height)) z = near + nz * (far - near) pos = origin + self.forward * z return region_2d_to_location_3d(region, rv3d, xy, pos).to_3d()
def modal(self, context, event): if event.type == 'MOUSEMOVE': # self.mouse_path.append((event.mouse_region_x, event.mouse_region_y)) new_cell_loc = region_2d_to_location_3d(context.region, context.space_data.region_3d, (event.mouse_region_x, event.mouse_region_y), context.scene.cursor_location) new_cell_loc = [round(c) for c in new_cell_loc] print('CREATING CELL AT: {}'.format(new_cell_loc)) auto.add(*new_cell_loc) elif event.type == 'LEFTMOUSE': return {'FINISHED'} elif event.type in {'RIGHTMOUSE', 'ESC'}: print("NOT DRAWING") return {'CANCELLED'} return{'RUNNING_MODAL'}
def pan(ary): #get reference to all the areas area = bpy.context.window_manager.windows[0].screen.areas[1] viewport = area.regions[4] rv3d = area.spaces[0].region_3d #convert view location's 3D Cords to 2D Cords locCord = rv3d.view_location cord = view3d_utils.location_3d_to_region_2d(viewport, rv3d, locCord) cord[0] += float(ary[1]) cord[1] += float(ary[2]) #convert 2d cords to 3d Cords and apply vec = view3d_utils.region_2d_to_vector_3d(viewport, rv3d, cord) loc = view3d_utils.region_2d_to_location_3d(viewport, rv3d, cord, vec) rv3d.view_location = loc
def modal(self, context, event): context.area.tag_redraw() # allow moving in the 3D View if event.type in { 'MIDDLEMOUSE', 'WHEELUPMOUSE', 'WHEELDOWNMOUSE', 'NUMPAD_1', 'NUMPAD_2', 'NUMPAD_3', 'NUMPAD_4', 'NUMPAD_6', 'NUMPAD_7', 'NUMPAD_8', 'NUMPAD_9', 'NUMPAD_5'}: return {'PASS_THROUGH'} if event.type in {'LEFT_ALT', 'RIGHT_ALT'}: if event.value == 'PRESS': pt_buf.alt = True if event.value == 'RELEASE': pt_buf.alt = False return {'RUNNING_MODAL'} elif event.type in {'LEFT_CTRL', 'RIGHT_CTRL'}: if event.value == 'PRESS': pt_buf.ctrl = not pt_buf.ctrl return {'RUNNING_MODAL'} elif event.type in {'LEFT_SHIFT', 'RIGHT_SHIFT'}: if event.value == 'PRESS': pt_buf.shift = True if event.value == 'RELEASE': pt_buf.shift = False return {'RUNNING_MODAL'} elif event.type == 'MOUSEMOVE': if pt_buf.list_m_loc_2d != []: pt_buf_list_m_loc_3d_last_2d = location_3d_to_region_2d( context.region, context.space_data.region_3d, pt_buf.list_m_loc_3d[-1] ) if pt_buf.alt is True: pt_buf.x = pt_buf_list_m_loc_3d_last_2d[0] pt_buf.y = event.mouse_region_y elif pt_buf.shift is True: pt_buf.x = event.mouse_region_x pt_buf.y = pt_buf_list_m_loc_3d_last_2d[1] else: pt_buf.x = event.mouse_region_x pt_buf.y = event.mouse_region_y else: pt_buf.x = event.mouse_region_x pt_buf.y = event.mouse_region_y elif event.type == 'LEFTMOUSE': if event.value == 'PRESS': mouse_loc_2d = Vector((pt_buf.x, pt_buf.y)) pt_buf.list_m_loc_2d.append(mouse_loc_2d) mouse_loc_3d = region_2d_to_location_3d( context.region, context.space_data.region_3d, mouse_loc_2d, pt_buf.depth_location ) pt_buf.list_m_loc_3d.append(mouse_loc_3d) pt_buf.depth_location = pt_buf.list_m_loc_3d[-1] # <-- depth location # run Extrude at cursor if pt_buf.ctrl: try: bpy.ops.mesh.dupli_extrude_cursor('INVOKE_DEFAULT', rotate_source=False) except: pass elif event.value == 'RELEASE': pass elif event.type == 'RIGHTMOUSE': context.space_data.draw_handler_remove(self._handle_px, 'WINDOW') self.execute(context) pt_buf.sws = 'off' return {'FINISHED'} elif event.type == 'ESC': context.space_data.draw_handler_remove(self._handle_px, 'WINDOW') store_restore_view(context, False) pt_buf.list_m_loc_2d[:] = [] pt_buf.list_m_loc_3d[:] = [] pt_buf.depth_location = Vector((0.0, 0.0, 0.0)) pt_buf.sws = 'off' pt_buf.store_view_matrix = Matrix() pt_buf.view_location = (0.0, 0.0, 0.0) pt_buf.ctrl = False return {'CANCELLED'} # Return has to be modal or the tool can crash # It's better to define PASS_THROUGH as the exception and not the default return {'RUNNING_MODAL'}
def draw_callback_px(self, context): font_id = 0 alpha = context.scene.pen_tool_props.a font_size = context.scene.pen_tool_props.fs bgl.glColor4f(0.0, 0.6, 1.0, alpha) bgl.glPointSize(4.0) bgl.glBegin(bgl.GL_POINTS) bgl.glVertex2f(pt_buf.x, pt_buf.y) bgl.glEnd() bgl.glDisable(bgl.GL_BLEND) # location 3d if context.scene.pen_tool_props.b2 is True: mloc3d = region_2d_to_location_3d( context.region, context.space_data.region_3d, Vector((pt_buf.x, pt_buf.y)), pt_buf.depth_location ) blf.position(font_id, pt_buf.x + 15, pt_buf.y - 15, 0) blf.size(font_id, font_size, context.user_preferences.system.dpi) blf.draw(font_id, '(' + str(round(mloc3d[0], 4)) + ', ' + str(round(mloc3d[1], 4)) + ', ' + str(round(mloc3d[2], 4)) + ')') n = len(pt_buf.list_m_loc_3d) if n != 0: # add points bgl.glEnable(bgl.GL_BLEND) bgl.glPointSize(4.0) bgl.glBegin(bgl.GL_POINTS) for i in pt_buf.list_m_loc_3d: loc_0 = location_3d_to_region_2d( context.region, context.space_data.region_3d, i ) bgl.glVertex2f(loc_0[0], loc_0[1]) bgl.glEnd() bgl.glDisable(bgl.GL_BLEND) # text next to the mouse m_loc_3d = region_2d_to_location_3d( context.region, context.space_data.region_3d, Vector((pt_buf.x, pt_buf.y)), pt_buf.depth_location ) vec0 = pt_buf.list_m_loc_3d[-1] - m_loc_3d blf.position(font_id, pt_buf.x + 15, pt_buf.y + 15, 0) blf.size(font_id, font_size, context.user_preferences.system.dpi) blf.draw(font_id, str(round(vec0.length, 4))) # angle first after mouse if n >= 2: vec1 = pt_buf.list_m_loc_3d[-2] - pt_buf.list_m_loc_3d[-1] if vec0.length == 0.0 or vec1.length == 0.0: pass else: ang = vec0.angle(vec1) if round(degrees(ang), 2) == 180.0: text_0 = '0.0' elif round(degrees(ang), 2) == 0.0: text_0 = '180.0' else: text_0 = str(round(degrees(ang), 2)) loc_4 = location_3d_to_region_2d( context.region, context.space_data.region_3d, pt_buf.list_m_loc_3d[-1] ) bgl.glColor4f(0.0, 1.0, 0.525, alpha) blf.position(font_id, loc_4[0] + 10, loc_4[1] + 10, 0) blf.size(font_id, font_size, context.user_preferences.system.dpi) blf.draw(font_id, text_0 + '') bgl.glLineStipple(4, 0x5555) bgl.glEnable(bgl.GL_LINE_STIPPLE) # enable line stipple bgl.glColor4f(0.0, 0.6, 1.0, alpha) # draw line between last point and mouse bgl.glEnable(bgl.GL_BLEND) bgl.glBegin(bgl.GL_LINES) loc_1 = location_3d_to_region_2d( context.region, context.space_data.region_3d, pt_buf.list_m_loc_3d[-1] ) bgl.glVertex2f(loc_1[0], loc_1[1]) bgl.glVertex2f(pt_buf.x, pt_buf.y) bgl.glEnd() bgl.glDisable(bgl.GL_BLEND) # draw lines between points bgl.glEnable(bgl.GL_BLEND) bgl.glBegin(bgl.GL_LINE_STRIP) for j in pt_buf.list_m_loc_3d: loc_2 = location_3d_to_region_2d(context.region, context.space_data.region_3d, j) bgl.glVertex2f(loc_2[0], loc_2[1]) bgl.glEnd() bgl.glDisable(bgl.GL_BLEND) bgl.glDisable(bgl.GL_LINE_STIPPLE) # disable line stipple # draw line length between points if context.scene.pen_tool_props.b1 is True: for k in range(n - 1): loc_3 = location_3d_to_region_2d( context.region, context.space_data.region_3d, (pt_buf.list_m_loc_3d[k] + pt_buf.list_m_loc_3d[(k + 1) % n]) * 0.5 ) blf.position(font_id, loc_3[0] + 10, loc_3[1] + 10, 0) blf.size(font_id, font_size, context.user_preferences.system.dpi) blf.draw(font_id, str(round((pt_buf.list_m_loc_3d[k] - pt_buf.list_m_loc_3d[(k + 1) % n]).length, 4))) # draw all angles if context.scene.pen_tool_props.b0 is True: for h in range(n - 1): if n >= 2: if h == 0: pass else: vec_ = pt_buf.list_m_loc_3d[h] - pt_buf.list_m_loc_3d[(h - 1) % n] vec_1_ = pt_buf.list_m_loc_3d[h] vec_2_ = pt_buf.list_m_loc_3d[(h - 1) % n] if vec_.length == 0.0 or vec_1_.length == 0.0 or vec_2_.length == 0.0: pass else: ang = vec_.angle(vec_1_ - vec_2_) if round(degrees(ang)) == 0.0: pass else: loc_4 = location_3d_to_region_2d( context.region, context.space_data.region_3d, pt_buf.list_m_loc_3d[h] ) bgl.glColor4f(0.0, 1.0, 0.525, alpha) blf.position(font_id, loc_4[0] + 10, loc_4[1] + 10, 0) blf.size(font_id, font_size, context.user_preferences.system.dpi) blf.draw(font_id, str(round(degrees(ang), 2)) + '') # tools on / off bgl.glColor4f(1.0, 1.0, 1.0, 1.0) blf.position(font_id, self.text_location, 20, 0) blf.size(font_id, 15, context.user_preferences.system.dpi) blf.draw(font_id, "Draw On") blf.position(font_id, self.text_location, 40, 0) blf.draw(font_id, "Extrude On" if pt_buf.ctrl else "Extrude Off")
def draw_callback_px(self, context): if context.mode == "EDIT_MESH": en0 = context.scene.dt_custom_props.en0 font_id = 0 font_size = context.scene.dt_custom_props.fs ob_act = context.active_object bme = bmesh.from_edit_mesh(ob_act.data) mtrx = ob_act.matrix_world list_0 = [v.index for v in bme.verts if v.select] if len(list_0) != 0: p = bme.verts[list_0[0]].co.copy() p_loc_2d = location_3d_to_region_2d(context.region, context.space_data.region_3d, p) q = mtrx * bme.verts[list_0[0]].co.copy() q_loc_2d = location_3d_to_region_2d(context.region, context.space_data.region_3d, q) # -- -- -- -- distance to adjacent vertices if context.scene.dt_custom_props.b0 == True: list_ = [[v.index for v in e.verts] for e in bme.verts[list_0[0]].link_edges] for ek in list_: vi = [i for i in ek if i != list_0[0]][0] p1 = bme.verts[vi].co.copy() loc_0_3d = mtrx * ((p + p1) * 0.5) loc_0_2d = location_3d_to_region_2d(context.region, context.space_data.region_3d, loc_0_3d) bgl.glColor4f(1.0, 1.0, 0.0, context.scene.dt_custom_props.a) blf.position(font_id, loc_0_2d[0] + 4, loc_0_2d[1] + 4, 0) blf.size(font_id, font_size, context.user_preferences.system.dpi) blf.draw(font_id, str(round((p - p1).length, 4))) bgl.glLineStipple(4, 0xAAAA) bgl.glEnable(bgl.GL_LINE_STIPPLE) # -- -- -- -- distance to axis local global if context.scene.dt_custom_props.b1 == True: # -- -- -- -- local if en0 == 'opt0': # -- -- -- -- x axis px = mtrx * Vector((0.0, p[1], p[2])) px_loc_2d = location_3d_to_region_2d(context.region, context.space_data.region_3d, px) bgl.glEnable(bgl.GL_BLEND) bgl.glColor4f(1.0, 0.0, 0.0, context.scene.dt_custom_props.a) bgl.glBegin(bgl.GL_LINES) bgl.glVertex2f(q_loc_2d[0], q_loc_2d[1]) bgl.glVertex2f(px_loc_2d[0], px_loc_2d[1]) bgl.glEnd() bgl.glDisable(bgl.GL_BLEND) if context.scene.dt_custom_props.b2 == False: lx = (q_loc_2d + px_loc_2d) * 0.5 bgl.glColor4f(1.0, 0.0, 0.0, context.scene.dt_custom_props.a) blf.position(font_id, lx[0] + 4, lx[1] + 4, 0) blf.size(font_id, font_size, context.user_preferences.system.dpi) blf.draw(font_id, str(round(p[0], 4))) # -- -- -- -- y axis py = mtrx * Vector((p[0], 0.0, p[2])) py_loc_2d = location_3d_to_region_2d(context.region, context.space_data.region_3d, py) bgl.glEnable(bgl.GL_BLEND) bgl.glColor4f(0.0, 1.0, 0.0, context.scene.dt_custom_props.a) bgl.glBegin(bgl.GL_LINES) bgl.glVertex2f(q_loc_2d[0], q_loc_2d[1]) bgl.glVertex2f(py_loc_2d[0], py_loc_2d[1]) bgl.glEnd() bgl.glDisable(bgl.GL_BLEND) if context.scene.dt_custom_props.b2 == False: ly = (q_loc_2d + py_loc_2d) * 0.5 bgl.glColor4f(0.0, 1.0, 0.0, context.scene.dt_custom_props.a) blf.position(font_id, ly[0] + 4, ly[1] + 4, 0) blf.size(font_id, font_size, context.user_preferences.system.dpi) blf.draw(font_id, str(round(p[1], 4))) # -- -- -- -- z axis pz = mtrx * Vector((p[0], p[1], 0.0)) pz_loc_2d = location_3d_to_region_2d(context.region, context.space_data.region_3d, pz) bgl.glEnable(bgl.GL_BLEND) bgl.glColor4f(0.0, 0.0, 1.0, context.scene.dt_custom_props.a) bgl.glBegin(bgl.GL_LINES) bgl.glVertex2f(q_loc_2d[0], q_loc_2d[1]) bgl.glVertex2f(pz_loc_2d[0], pz_loc_2d[1]) bgl.glEnd() bgl.glDisable(bgl.GL_BLEND) if context.scene.dt_custom_props.b2 == False: lz = (q_loc_2d + pz_loc_2d) * 0.5 bgl.glColor4f(0.0, 0.0, 1.0, context.scene.dt_custom_props.a) blf.position(font_id, lz[0] + 4, lz[1] + 4, 0) blf.size(font_id, font_size, context.user_preferences.system.dpi) blf.draw(font_id, str(round(p[2], 4))) # -- -- -- -- if context.scene.dt_custom_props.b2 == True and context.scene.dt_custom_props.b1 == True: blf.size(font_id, font_size, context.user_preferences.system.dpi) bgl.glColor4f(1.0, 0.0, 0.0, context.scene.dt_custom_props.a) blf.position(font_id, q_loc_2d[0] + 4, q_loc_2d[1] + 4 + font_size + 4 + font_size + 4, 0) blf.draw(font_id, 'x ' + str(round(p[0], 4))) bgl.glColor4f(0.0, 1.0, 0.0, context.scene.dt_custom_props.a) blf.position(font_id, q_loc_2d[0] + 4, q_loc_2d[1] + 4 + font_size + 4, 0) blf.draw(font_id, 'y ' + str(round(p[1], 4))) bgl.glColor4f(0.0, 0.0, 1.0, context.scene.dt_custom_props.a) blf.position(font_id, q_loc_2d[0] + 4, q_loc_2d[1] + 4, 0) blf.draw(font_id, 'z ' + str(round(p[2], 4))) # -- -- -- -- global elif en0 == 'opt1': # -- -- -- -- x axis ip_x = intersect_line_plane(q, q + (Vector((1.0, 0.0, 0.0)) * 0.1), Vector((0.0, 1.0, 0.0)), Vector((1.0, 0.0, 0.0))) ip_x_loc_2d = location_3d_to_region_2d(context.region, context.space_data.region_3d, ip_x) bgl.glEnable(bgl.GL_BLEND) bgl.glColor4f(1.0, 0.0, 0.0, context.scene.dt_custom_props.a) bgl.glBegin(bgl.GL_LINES) bgl.glVertex2f(q_loc_2d[0], q_loc_2d[1]) bgl.glVertex2f(ip_x_loc_2d[0], ip_x_loc_2d[1]) bgl.glEnd() bgl.glDisable(bgl.GL_BLEND) if context.scene.dt_custom_props.b2 == False: loc_1_2d = (q_loc_2d + ip_x_loc_2d) * 0.5 bgl.glColor4f(1.0, 0.0, 0.0, context.scene.dt_custom_props.a) blf.position(font_id, loc_1_2d[0] + 4, loc_1_2d[1] + 4, 0) blf.size(font_id, font_size, context.user_preferences.system.dpi) blf.draw(font_id, str(round((q - ip_x).length, 4))) # -- -- -- -- y axis ip_y = intersect_line_plane(q, q + (Vector((0.0, 1.0, 0.0)) * 0.1), Vector((1.0, 0.0, 0.0)), Vector((0.0, 1.0, 0.0))) ip_y_loc_2d = location_3d_to_region_2d(context.region, context.space_data.region_3d, ip_y) bgl.glEnable(bgl.GL_BLEND) bgl.glColor4f(0.0, 1.0, 0.0, context.scene.dt_custom_props.a) bgl.glBegin(bgl.GL_LINES) bgl.glVertex2f(q_loc_2d[0], q_loc_2d[1]) bgl.glVertex2f(ip_y_loc_2d[0], ip_y_loc_2d[1]) bgl.glEnd() bgl.glDisable(bgl.GL_BLEND) if context.scene.dt_custom_props.b2 == False: loc_2_2d = (q_loc_2d + ip_y_loc_2d) * 0.5 bgl.glColor4f(0.0, 1.0, 0.0, context.scene.dt_custom_props.a) blf.position(font_id, loc_2_2d[0] + 4, loc_2_2d[1] + 4, 0) blf.size(font_id, font_size, context.user_preferences.system.dpi) blf.draw(font_id, str(round((q - ip_y).length, 4))) # -- -- -- -- z axis ip_z = intersect_line_plane(q, q + (Vector((0.0, 0.0, 1.0)) * 0.1), Vector((1.0, 0.0, 0.0)), Vector((0.0, 0.0, 1.0))) ip_z_loc_2d = location_3d_to_region_2d(context.region, context.space_data.region_3d, ip_z) bgl.glEnable(bgl.GL_BLEND) bgl.glColor4f(0.0, 0.0, 1.0, context.scene.dt_custom_props.a) bgl.glBegin(bgl.GL_LINES) bgl.glVertex2f(q_loc_2d[0], q_loc_2d[1]) bgl.glVertex2f(ip_z_loc_2d[0], ip_z_loc_2d[1]) bgl.glEnd() bgl.glDisable(bgl.GL_BLEND) if context.scene.dt_custom_props.b2 == False: loc_3_2d = (q_loc_2d + ip_z_loc_2d) * 0.5 bgl.glColor4f(0.0, 0.0, 1.0, context.scene.dt_custom_props.a) blf.position(font_id, loc_3_2d[0] + 4, loc_3_2d[1] + 4, 0) blf.size(font_id, font_size, context.user_preferences.system.dpi) blf.draw(font_id, str(round((q - ip_z).length, 4))) # -- -- -- -- if context.scene.dt_custom_props.b2 == True and context.scene.dt_custom_props.b1 == True: blf.size(font_id, font_size, context.user_preferences.system.dpi) bgl.glColor4f(1.0, 0.0, 0.0, context.scene.dt_custom_props.a) blf.position(font_id, q_loc_2d[0] + 4, q_loc_2d[1] + 4 + font_size + 4 + font_size + 4, 0) blf.draw(font_id, 'x ' + str(round((q - ip_x).length, 4))) bgl.glColor4f(0.0, 1.0, 0.0, context.scene.dt_custom_props.a) blf.position(font_id, q_loc_2d[0] + 4, q_loc_2d[1] + 4 + font_size + 4, 0) blf.draw(font_id, 'y ' + str(round((q - ip_y).length, 4))) bgl.glColor4f(0.0, 0.0, 1.0, context.scene.dt_custom_props.a) blf.position(font_id, q_loc_2d[0] + 4, q_loc_2d[1] + 4, 0) blf.draw(font_id, 'z ' + str(round((q - ip_z).length, 4))) # -- -- -- -- mouse location if context.scene.dt_custom_props.b4 == True: rgn = context.region # region rgn_3d = context.space_data.region_3d # region 3d bgl.glEnable(bgl.GL_BLEND) bgl.glColor4f(1.0, 1.0, 1.0, context.scene.dt_custom_props.a) bgl.glBegin(bgl.GL_LINES) bgl.glVertex2f(0, dt_buf.y ) bgl.glVertex2f(dt_buf.x - 15, dt_buf.y) bgl.glEnd() bgl.glDisable(bgl.GL_BLEND) bgl.glEnable(bgl.GL_BLEND) bgl.glColor4f(1.0, 1.0, 1.0, context.scene.dt_custom_props.a) bgl.glBegin(bgl.GL_LINES) bgl.glVertex2f(rgn.width, dt_buf.y ) bgl.glVertex2f(dt_buf.x + 15, dt_buf.y) bgl.glEnd() bgl.glDisable(bgl.GL_BLEND) bgl.glEnable(bgl.GL_BLEND) bgl.glColor4f(1.0, 1.0, 1.0, context.scene.dt_custom_props.a) bgl.glBegin(bgl.GL_LINES) bgl.glVertex2f(dt_buf.x, 0 ) bgl.glVertex2f(dt_buf.x, dt_buf.y - 15) bgl.glEnd() bgl.glDisable(bgl.GL_BLEND) bgl.glEnable(bgl.GL_BLEND) bgl.glColor4f(1.0, 1.0, 1.0, context.scene.dt_custom_props.a) bgl.glBegin(bgl.GL_LINES) bgl.glVertex2f(dt_buf.x, rgn.height ) bgl.glVertex2f(dt_buf.x, dt_buf.y + 15) bgl.glEnd() bgl.glDisable(bgl.GL_BLEND) bgl.glDisable(bgl.GL_LINE_STIPPLE) t = str(dt_buf.x) + ', ' + str(dt_buf.y) lo = region_2d_to_location_3d(context.region, context.space_data.region_3d, Vector((dt_buf.x, dt_buf.y)), Vector((0.0, 0.0, 0.0))) t1 = '( ' + str(round(lo[0], 4)) + ', ' + str(round(lo[1], 4)) + ', ' + str(round(lo[2], 4)) + ' )' bgl.glColor4f(1.0, 1.0, 1.0, context.scene.dt_custom_props.a) blf.position(font_id, dt_buf.x + 15, dt_buf.y + 15, 0) blf.size(font_id, 14, context.user_preferences.system.dpi) blf.draw(font_id, t1 if context.scene.dt_custom_props.b5 == True else t) bgl.glDisable(bgl.GL_LINE_STIPPLE) # -- -- -- -- angles if context.scene.dt_custom_props.b3 == True: list_ek = [[v.index for v in e.verts] for e in bme.verts[list_0[0]].link_edges] n1 = len(list_ek) for j in range(n1): vec1 = p - bme.verts[[ i for i in list_ek[j] if i != list_0[0] ][0]].co.copy() vec2 = p - bme.verts[[ i for i in list_ek[(j + 1) % n1] if i != list_0[0]][0]].co.copy() ang = vec1.angle(vec2) a_loc_2d = location_3d_to_region_2d(context.region, context.space_data.region_3d, mtrx * (((p - (vec1.normalized() * 0.1)) + (p - (vec2.normalized() * 0.1))) * 0.5)) bgl.glColor4f(0.0, 0.757, 1.0, context.scene.dt_custom_props.a) blf.position(font_id, a_loc_2d[0], a_loc_2d[1], 0) blf.size(font_id, font_size, context.user_preferences.system.dpi) blf.draw(font_id, str(round(ang, 4) if context.scene.dt_custom_props.b6 == True else round(degrees(ang), 2))) # -- -- -- -- tool on/off bgl.glColor4f(1.0, 1.0, 1.0, 1.0) blf.position(font_id, 150, 10, 0) blf.size(font_id, 20, context.user_preferences.system.dpi) blf.draw(font_id, 'Ruler On')
def modal(self, context, event): scn = context.scene if event.type == 'MOUSEMOVE' and self.LMB_Hold: #bpy.ops.object.mode_set(mode='OBJECT') #bpy.ops.object.mode_set(mode='EDIT') # create variables coord = event.mouse_region_x, event.mouse_region_y region = context.region rv3d = context.space_data.region_3d vec = region_2d_to_vector_3d(region, rv3d, coord) loc = (region_2d_to_location_3d(region, rv3d, coord, vec)) # get face center bpy.ops.object.mode_set(mode='OBJECT') me = bpy.context.object.data # Get the active mesh bm = bmesh.new() # create an empty BMesh bm.from_mesh(me) # fill it in from a Mesh face = bpy.context.object.data.polygons.active face_center = bm.faces[face].calc_center_median() bpy.ops.object.mode_set(mode='EDIT') face_center_2d = location_3d_to_region_2d(region, rv3d, face_center) face_normal = bpy.context.active_object.data.polygons[face].normal angle = 0 if mathutils.Vector((coord)).x >= face_center_2d.x and mathutils.Vector((coord)).y >= face_center_2d.y: angle = loc.angle(face_center)#/math.pi*180 elif mathutils.Vector((coord)).x <= face_center_2d.x and mathutils.Vector((coord)).y <= face_center_2d.x: angle = -(loc.angle(face_center))#/math.pi*180 x = rv3d.perspective_matrix[3].x y = rv3d.perspective_matrix[3].y z = rv3d.perspective_matrix[3].z axis = mathutils.Vector((x,y,z)) nx = face_normal.x ny= face_normal.y nz= face_normal.z spinAngle = scn.spin *math.pi/180 minDisVec = mathutils.Vector((scn.min_distance,scn.min_distance,scn.min_distance)) # if scn['stepsCounter']==0: # # # if scn['min_distance'] >= 1: # # increment = round((loc - face_center).length,0) # # if increment == scn['min_distance'] : # # if scn.auto_rotate: # bpy.ops.transform.rotate(value=(angle), axis=(axis)) # extrusion(coord,region,rv3d,vec,loc,face,face_center,scn['taper_value'],scn.cons_x ,scn.cons_y,scn.cons_z,scn.orientation) # bpy.ops.transform.rotate(value=(spinAngle), axis=(nx,ny,nz)) # # # else: # increment = round((loc - face_center).length,2) # # if increment >= scn['min_distance']: # # if scn.auto_rotate: # bpy.ops.transform.rotate(value=(angle), axis=(axis)) # extrusion(coord,region,rv3d,vec,loc,face,face_center,scn['taper_value'],scn.cons_x ,scn.cons_y,scn.cons_z,scn.orientation) # bpy.ops.transform.rotate(value=(spinAngle), axis=(nx,ny,nz)) # # # else: # # # if scn['min_distance'] >= 1 and scn.steps > scn.stepsCounter: # # increment = round((loc - face_center).length,0) # # if increment == scn['min_distance'] : # # if scn.auto_rotate: # bpy.ops.transform.rotate(value=(angle), axis=(axis)) # extrusion(coord,region,rv3d,vec,loc,face,face_center,scn['taper_value'],scn.cons_x ,scn.cons_y,scn.cons_z,scn.orientation) # bpy.ops.transform.rotate(value=(spinAngle), axis=(nx,ny,nz)) # scn['steps']+=1 # print(scn.steps, scn.stepsCounter) # # # # else: # increment = round((loc - face_center).length,2) # # if increment >= scn['min_distance']: # # if scn.auto_rotate: # bpy.ops.transform.rotate(value=(angle), axis=(axis)) # extrusion(coord,region,rv3d,vec,loc,face,face_center,scn['taper_value'],scn.cons_x ,scn.cons_y,scn.cons_z,scn.orientation) # bpy.ops.transform.rotate(value=(spinAngle), axis=(nx,ny,nz)) # scn.steps+=1 increment = round((loc - face_center).length,5) if scn.stepsCounter >0: if increment >= scn['min_distance'] and scn.steps < scn.stepsCounter: scn.steps += 1 if scn.auto_rotate: bpy.ops.transform.rotate(value=(angle), axis=(axis)) extrusion(loc , face_center,scn['taper_value'], scn.cons_x, scn.cons_y, scn.cons_z,scn.orientation) bpy.ops.transform.rotate(value=(spinAngle), axis=(nx,ny,nz)) else: if increment >= scn['min_distance']: if scn.auto_rotate: bpy.ops.transform.rotate(value=(angle), axis=(axis)) extrusion(loc,face_center,scn['taper_value'],scn.cons_x ,scn.cons_y,scn.cons_z,scn.orientation) bpy.ops.transform.rotate(value=(spinAngle), axis=(nx,ny,nz)) elif event.type == 'LEFTMOUSE': if event.value == 'PRESS': self.LMB_Hold = True elif event.value == 'RELEASE': self.LMB_Hold = False elif event.type in {'RIGHTMOUSE', 'NUMPAD_ENTER'} or (scn.steps >= scn.stepsCounter and scn.stepsCounter !=0): scn.steps = 0 if bpy.context.scene.collapse == True : bpy.ops.mesh.merge(type='COLLAPSE', uvs=True) context.area.header_text_set() return {'FINISHED'} elif event.type == 'ESC': bpy.ops.ed.undo() context.area.header_text_set() return {'CANCELLED'} context.area.header_text_set('Hold LMB and move to extrude, RMB to confirm, ESC to abort ') return {'RUNNING_MODAL'}