def _selectObjects(self): #get selection_box quad = self._getScreenQuad() #check if going to [Apend to] or [Create a new] Selection List if not logic.keyboard.events[ events. LEFTSHIFTKEY] == logic.KX_INPUT_ACTIVE or not logic.keyboard.events[ events.RIGHTSHIFTKEY] == logic.KX_INPUT_ACTIVE: for obj in self.selected: obj.deselect() self.selected = [] #get all Objects in and ccheck if they are Units for obj in self.scene.objects: if "UnitType" in obj: #get the Object's 3D World Position relative to the screen and check if it intersects with 2D selection_box point = Vector(self.camera.getScreenPosition( obj.worldPosition)) test = [point] + quad in_quad = geometry.intersect_point_quad_2d(*test) #if it intersects set Object selected property and Apend it to the Selection Lis if in_quad: hit_obj = self.camera.getScreenRay(point.x, point.y, 1000) if hit_obj == obj: obj.select() self.selected.append(obj)
def select_inside(a, b): cont = logic.getCurrentController() shift = cont.sensors["Keyboard"] p1 = Vector((a.x, a.y)) p2 = Vector((b.x, a.y)) p3 = Vector((b.x, b.y)) p4 = Vector((a.x, b.y)) scene = logic.getCurrentScene() cam = scene.active_camera for obj in scene.objects: if "ant" in obj: # if both points are in the same place, deselect everything if a == b: obj["selected"] = False else: # remove existing selection unless shift is held if not shift.positive: if obj.get("selected", False): obj["selected"] = False if geometry.intersect_point_quad_2d(obj.worldPosition.xy, p1, p2, p3, p4): print("selected", obj) obj["selected"] = True
def get_perpendicular_point(pt, bl, tl, tr, br): ''' Return the point if it is inside the quad, else, return a point on the border of the quad. This function helps prevent the user from dragging crop handles outside the strip's area. ''' intersects = intersect_point_quad_2d( pt, bl, tl, tr, br) if intersects: return pt elif pt.x <= bl.x and pt.y <= bl.y: return Vector(bl) elif pt.x <= tl.x and pt.y >= tl.y: return Vector(tl) elif pt.x >= tr.x and pt.y >= tr.y: return Vector(tr) elif pt.x >= br.x and pt.y <= br.y: return Vector(br) max_x = max([tr.x, br.x]) min_x = min([tl.x, bl.x]) max_y = max([tl.y, tr.y]) min_y = min([bl.y, br.y]) # pt left of left side if (pt.x <= tl.x or pt.x <= bl.x) and (pt.y >= bl.y and pt.y <= tl.y): right = Vector([max_x, pt.y]) intersection = intersect_line_line_2d(bl, tl, pt, right) # pt right of right side elif (pt.x >= br.x or pt.x >= tr.x) and (pt.y >= br.y and pt.y <= tr.y): left = Vector([min_x, pt.y]) intersection = intersect_line_line_2d(br, tr, pt, left) # pt above top side elif (pt.y >= tl.y or pt.y >= tr.y) and (pt.x >= tl.x and pt.x <= tr.x): bottom = Vector([pt.x, min_y]) intersection = intersect_line_line_2d(tl, tr, pt, bottom) # pt below bottom side elif (pt.y <= bl.y or pt.y <= br.y) and (pt.x >= bl.x and pt.x <= br.x): top = Vector([pt.x, max_y]) intersection = intersect_line_line_2d(bl, br, pt, top) return intersection
def is_triangle_in_rect(verts, x_range, y_range): x1 = x_range[0] x2 = x_range[1] y1 = y_range[0] y2 = y_range[1] p1 = Vector((x1, y1)) p2 = Vector((x1, y2)) p3 = Vector((x2, y2)) p4 = Vector((x2, y1)) for v in verts: if intersect_point_quad_2d(v, p1, p2, p3, p4): return True
def test_select(self, context, location): rv3d = context.region_data if rv3d.view_perspective == 'CAMERA': return -1 curr_img_pos = get_curr_img_pos_from_context(context) if not curr_img_pos: return -1 possible = curr_img_pos[2] if not possible: return -1 mouse_pos = Vector(location) mpr_pos = self.pixel_pos quad_p1 = mpr_pos quad_p2 = mpr_pos + Vector((0.0, self.pixel_size.y)) quad_p3 = mpr_pos + self.pixel_size quad_p4 = mpr_pos + Vector((self.pixel_size.x, 0.0)) res = intersect_point_quad_2d(mouse_pos, quad_p1, quad_p2, quad_p3, quad_p4) if res == -1: return 0 return -1
def intersect_line_quad_2d(line_p1, line_p2, quad_p1, quad_p2, quad_p3, quad_p4, clip=False): """二次元の直線(線分)を凸包の四角形で切り取る。quad_p1~4は反時計回り :rtype: None | (Vector, Vector) """ eps = 1e-8 p1, p2 = line_p1.copy(), line_p2.copy() quad = [quad_p1, quad_p2, quad_p3, quad_p4] # lineが点の場合 if p1 == p2: if geom.intersect_point_quad_2d(p1, *quad) == 1: return p1, p2 else: return None # quadが点の場合 if quad_p1 == quad_p2 == quad_p3 == quad_p4: line = p2 - p1 f = cross2d(line, quad_p1 - p1) if f < eps: # p = (quad_p1 - p1).project(line) + p1 d = dot2d(line, quad_p1 - p1) l = line.length f = d / l**2 if clip and (f < 0 or f > 1): return None p = f * line + p1 return p, p.copy() else: return None # lineがquadの内側に有る場合 if clip: if geom.intersect_point_quad_2d(p1, *quad) == 1: if geom.intersect_point_quad_2d(p2, *quad) == 1: return p1, p2 # quadの各辺との判定 intersected = False for i in range(4): q1 = quad[i - 1] q2 = quad[i] if q1 == q2: # TODO: 何かしらの処理が要る? continue line = p2 - p1 edge = q2 - q1 # 平行 if abs(cross2d(line, edge)) < eps: continue f1 = cross2d(edge, p1 - q1) f2 = cross2d(edge, p2 - q1) f3 = cross2d(line, q1 - p1) f4 = cross2d(line, q2 - p1) # 交点計算 # if clip: # # 線分が外側 # if f1 < 0 and f2 < 0: # return None # # NOTE: # # intersect_line_line_2d()は線分同士の判定を行う。 # # 平行でも線分同士が片方の頂点だけで重なるならその座標が返る # # (0, 0), (1, 0), (1, 0), (2, 0) -> (1, 0) # p = geom.intersect_line_line_2d(p1, p2, q1, q2) # else: # if f3 * f4 <= 0: # edge上で交差 # d1 = cross2d(edge, q1 - p1) # 省略 '/ edge.length' # d2 = cross2d(edge, line) # 省略 '/ edge.length' # p = p1 + (d1 / d2) * line # else: # p = None if clip and f1 < 0 and f2 < 0: # 線分が外側 return None if (f1 * f2 <= 0 or not clip) and f3 * f4 <= 0: d1 = cross2d(edge, q1 - p1) # 省略 '/ edge.length' d2 = cross2d(edge, line) # 省略 '/ edge.length' p = p1 + (d1 / d2) * line else: p = None if p: if clip: if f1 < 0: # p1が外側 p1 = p if f2 < 0: # p2が外側 p2 = p.copy() else: if f1 < f2: p1 = p else: p2 = p if p1 == p2: return p1, p2 intersected = True if intersected: return p1, p2 else: return None
def intersect_line_quad_2d(line_p1, line_p2, quad_p1, quad_p2, quad_p3, quad_p4, clip=False): """二次元の直線(線分)を凸包の四角形で切り取る。quad_p1~4は反時計回り :rtype: None | (Vector, Vector) """ eps = 1e-8 p1, p2 = line_p1.copy(), line_p2.copy() quad = [quad_p1, quad_p2, quad_p3, quad_p4] # lineが点の場合 if p1 == p2: if geom.intersect_point_quad_2d(p1, *quad) == 1: return p1, p2 else: return None # quadが点の場合 if quad_p1 == quad_p2 == quad_p3 == quad_p4: line = p2 - p1 f = cross2d(line, quad_p1 - p1) if f < eps: # p = (quad_p1 - p1).project(line) + p1 d = dot2d(line, quad_p1 - p1) l = line.length f = d / l ** 2 if clip and (f < 0 or f > 1): return None p = f * line + p1 return p, p.copy() else: return None # lineがquadの内側に有る場合 if clip: if geom.intersect_point_quad_2d(p1, *quad) == 1: if geom.intersect_point_quad_2d(p2, *quad) == 1: return p1, p2 # quadの各辺との判定 intersected = False for i in range(4): q1 = quad[i - 1] q2 = quad[i] if q1 == q2: # TODO: 何かしらの処理が要る? continue line = p2 - p1 edge = q2 - q1 # 平行 if abs(cross2d(line, edge)) < eps: continue f1 = cross2d(edge, p1 - q1) f2 = cross2d(edge, p2 - q1) f3 = cross2d(line, q1 - p1) f4 = cross2d(line, q2 - p1) # 交点計算 # if clip: # # 線分が外側 # if f1 < 0 and f2 < 0: # return None # # NOTE: # # intersect_line_line_2d()は線分同士の判定を行う。 # # 平行でも線分同士が片方の頂点だけで重なるならその座標が返る # # (0, 0), (1, 0), (1, 0), (2, 0) -> (1, 0) # p = geom.intersect_line_line_2d(p1, p2, q1, q2) # else: # if f3 * f4 <= 0: # edge上で交差 # d1 = cross2d(edge, q1 - p1) # 省略 '/ edge.length' # d2 = cross2d(edge, line) # 省略 '/ edge.length' # p = p1 + (d1 / d2) * line # else: # p = None if clip and f1 < 0 and f2 < 0: # 線分が外側 return None if (f1 * f2 <= 0 or not clip) and f3 * f4 <= 0: d1 = cross2d(edge, q1 - p1) # 省略 '/ edge.length' d2 = cross2d(edge, line) # 省略 '/ edge.length' p = p1 + (d1 / d2) * line else: p = None if p: if clip: if f1 < 0: # p1が外側 p1 = p if f2 < 0: # p2が外側 p2 = p.copy() else: if f1 < f2: p1 = p else: p2 = p if p1 == p2: return p1, p2 intersected = True if intersected: return p1, p2 else: return None
def modal(self, context, event): context.area.tag_redraw() if event.type == 'LEFTMOUSE' and event.value == 'PRESS': mouse_x = event.mouse_region_x mouse_y = event.mouse_region_y self.mouse_pos = Vector([mouse_x, mouse_y]) self.current_mouse = Vector([mouse_x, mouse_y]) for i in range(len(self.corner_quads)): quad = self.corner_quads[i] bl = quad[0] tl = quad[1] tr = quad[2] br = quad[3] intersects = intersect_point_quad_2d(self.mouse_pos, bl, tl, tr, br) if intersects: self.clicked_quad = i elif event.type == 'LEFTMOUSE' and event.value == 'RELEASE': offset_x, offset_y, fac, preview_zoom = get_preview_offset() active_strip = context.scene.sequence_editor.active_strip if active_strip.type == "TRANSFORM": angle = math.radians(active_strip.rotation_start) else: angle = 0 origin = self.max_corners[2] - self.max_corners[0] bl = rotate_point(self.max_corners[0], -angle, origin) tl = rotate_point(self.max_corners[1], -angle, origin) tr = rotate_point(self.max_corners[2], -angle, origin) br = rotate_point(self.max_corners[3], -angle, origin) bl_current = rotate_point(self.corners[0], -angle, origin) tl_current = rotate_point(self.corners[1], -angle, origin) tr_current = rotate_point(self.corners[2], -angle, origin) br_current = rotate_point(self.corners[3], -angle, origin) if self.clicked_quad is not None: for i in range(len(self.corners)): if i == 0: self.crop_left = bl_current.x - bl.x self.crop_left /= preview_zoom * fac self.crop_bottom = bl_current.y - bl.y self.crop_bottom /= preview_zoom * fac elif i == 1: self.crop_left = tl_current.x - tl.x self.crop_left /= preview_zoom * fac self.crop_top = tl.y - tl_current.y self.crop_top /= preview_zoom * fac elif i == 2: self.crop_right = tr.x - tr_current.x self.crop_right /= preview_zoom * fac self.crop_top = tr.y - tr_current.y self.crop_top /= preview_zoom * fac elif i == 3: self.crop_right = br.x - br_current.x self.crop_right /= preview_zoom * fac self.crop_bottom = br_current.y - br.y self.crop_bottom /= preview_zoom * fac self.clicked_quad = None self.mouse_pos = Vector([-1, -1]) elif event.type == 'MOUSEMOVE' and self.clicked_quad is not None: mouse_x = event.mouse_region_x mouse_y = event.mouse_region_y self.current_mouse = Vector([mouse_x, mouse_y]) elif event.type in [ 'MIDDLEMOUSE', 'WHEELDOWNMOUSE', 'WHEELUPMOUSE', 'RIGHT_ARROW', 'LEFT_ARROW' ]: return {'PASS_THROUGH'} elif event.type in ['C', 'RET', 'NUMPAD_ENTER' ] and event.value == 'PRESS': offset_x, offset_y, fac, preview_zoom = get_preview_offset() active_strip = context.scene.sequence_editor.active_strip crops = [ self.crop_left / self.scale_factor_x, self.crop_right / self.scale_factor_x, self.crop_bottom / self.scale_factor_y, self.crop_top / self.scale_factor_y, ] scene = context.scene if active_strip.type == "TRANSFORM": crop_scale(self, active_strip, crops) strip_in = active_strip.input_1 if scene.tool_settings.use_keyframe_insert_auto: cf = context.scene.frame_current active_strip.keyframe_insert(data_path='translate_start_x') active_strip.keyframe_insert(data_path='translate_start_y') active_strip.keyframe_insert(data_path='scale_start_x') active_strip.keyframe_insert(data_path='scale_start_y') strip_in.crop.keyframe_insert(data_path='min_x') strip_in.crop.keyframe_insert(data_path='max_x') strip_in.crop.keyframe_insert(data_path='min_y') strip_in.crop.keyframe_insert(data_path='max_y') else: active_strip.use_crop = True active_strip.crop.min_x = crops[0] active_strip.crop.max_x = crops[1] active_strip.crop.min_y = crops[2] active_strip.crop.max_y = crops[3] active_strip.transform.offset_x = self.init_pos_x - self.init_crop_left + crops[ 0] active_strip.transform.offset_y = self.init_pos_y - self.init_crop_bottom + crops[ 2] if scene.tool_settings.use_keyframe_insert_auto: active_strip.crop.keyframe_insert(data_path='min_x') active_strip.crop.keyframe_insert(data_path='max_x') active_strip.crop.keyframe_insert(data_path='min_y') active_strip.crop.keyframe_insert(data_path='max_y') active_strip.transform.keyframe_insert( data_path="offset_x") active_strip.transform.keyframe_insert( data_path="offset_y") bpy.types.SpaceSequenceEditor.draw_handler_remove( self.handle_crop, 'PREVIEW') return {'FINISHED'} elif (event.alt and event.type == 'C') or event.type == 'ESC': active_strip = context.scene.sequence_editor.active_strip crops = [ self.init_crop_left, self.init_crop_right, self.init_crop_bottom, self.init_crop_top ] if active_strip.type == "TRANSFORM": crop_scale(self, active_strip, crops) else: active_strip.use_crop = True active_strip.crop.min_x = crops[0] active_strip.crop.max_x = crops[1] active_strip.crop.min_y = crops[2] active_strip.crop.max_y = crops[3] active_strip.transform.offset_x = crops[0] active_strip.transform.offset_y = crops[2] bpy.types.SpaceSequenceEditor.draw_handler_remove( self.handle_crop, 'PREVIEW') return {'FINISHED'} return {'RUNNING_MODAL'}
def invoke(self, context, event): #bpy.ops.vse_transform_tools.initialize_pivot() scene = context.scene mouse_x = event.mouse_region_x mouse_y = event.mouse_region_y mouse_vec = Vector([mouse_x, mouse_y]) vector = mouse_to_res(mouse_vec) current_frame = scene.frame_current current_strips = [] sequence_editor = scene.sequence_editor selection_list = [] strips = get_visible_strips() if 'MOUSE' in event.type: for strip in reversed(strips): corners = get_strip_corners(strip) bottom_left = Vector(corners[0]) top_left = Vector(corners[1]) top_right = Vector(corners[2]) bottom_right = Vector(corners[3]) intersects = intersect_point_quad_2d(vector, bottom_left, top_left, top_right, bottom_right) if intersects and not event.type == 'A': selection_list.append(strip) if not event.shift: bpy.ops.sequencer.select_all(action='DESELECT') strip.select = True scene.sequence_editor.active_strip = strip break else: if not strip.select: strip.select = True scene.sequence_editor.active_strip = strip break else: strip.select = True break if not selection_list and not event.shift and not event.type == 'A': bpy.ops.sequencer.select_all(action='DESELECT') if strip.blend_type in ['CROSS', 'REPLACE']: return {'FINISHED'} elif event.type == 'A': all_selected = True for strip in strips: if not strip.select: all_selected = False bpy.ops.sequencer.select_all(action='DESELECT') if not all_selected: for strip in strips: strip.select = True args = (self, context) self.handle_select = bpy.types.SpaceSequenceEditor.draw_handler_add( draw_select, args, 'PREVIEW', 'POST_PIXEL') self.timer = context.window_manager.event_timer_add( 0.01, window=context.window) context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'}
def invoke(self, context, event): #bpy.ops.vse_transform_tools.initialize_pivot() global prev_mouse_x global prev_mouse_y global current_selection_depth scene = context.scene mouse_x = event.mouse_region_x mouse_y = event.mouse_region_y if mouse_x == prev_mouse_x and mouse_y == prev_mouse_y and not event.shift: # when click the same point as before current_selection_depth += 1 else: prev_mouse_x = mouse_x prev_mouse_y = mouse_y current_selection_depth = 1 mouse_vec = Vector([mouse_x, mouse_y]) vector = mouse_to_res(mouse_vec) current_frame = scene.frame_current current_strips = [] sequence_editor = scene.sequence_editor selection_list = [] strips = get_visible_strips() depth_counter = current_selection_depth if 'MOUSE' in event.type: for strip in reversed(strips): corners = get_strip_corners(strip) bottom_left = Vector(corners[0]) top_left = Vector(corners[1]) top_right = Vector(corners[2]) bottom_right = Vector(corners[3]) intersects = intersect_point_quad_2d(vector, bottom_left, top_left, top_right, bottom_right) if intersects and not event.type == 'A' and not strip.mute: # ignore the hidden strip # support cross-selection depth_counter -= 1 if depth_counter != 0: continue selection_list.append(strip) if not event.shift: bpy.ops.sequencer.select_all(action='DESELECT') strip.select = True scene.sequence_editor.active_strip = strip break else: if not strip.select: strip.select = True scene.sequence_editor.active_strip = strip break else: strip.select = True break # when cross all selections. repeate it. if depth_counter > 0: prev_mouse_x = -1 prev_mouse_y = -1 current_selection_depth = 0 if not selection_list and not event.shift and not event.type == 'A': # when u click the outside or depth_counter is not zero which makes selection_list empty bpy.ops.sequencer.select_all(action='DESELECT') if selection_list and selection_list[0].blend_type in [ 'CROSS', 'REPLACE' ]: return {'FINISHED'} elif event.type == 'A': # Reverse select action. Type A to deselect. Type A again to select all. all_not_selected = True for strip in strips: if strip.select: all_not_selected = False bpy.ops.sequencer.select_all(action='DESELECT') if all_not_selected: for strip in strips: strip.select = True args = (self, context) self.handle_select = bpy.types.SpaceSequenceEditor.draw_handler_add( draw_select, args, 'PREVIEW', 'POST_PIXEL') self.timer = context.window_manager.event_timer_add( 0.01, window=context.window) context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'}