Example #1
0
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)
Example #2
0
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)
Example #3
0
        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 pick_voxel(self, context, event, voxelarray):
        """Run this function on left mouse, execute the ray cast
        TODO: report/go through some problems with selecting in the
        operator_modal_view3d_raycast.py. Most of the problem is
        when trying to click close to the edge of the object.
        The distance values are often mucked up"""
        # get the context arguments
        ray_max=10000.0
        region = context.region
        rv3d = context.region_data
        coord = event.mouse_region_x, event.mouse_region_y

        # get the ray from the viewport and mouse
        view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
        ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
        ray_target = ray_origin + (view_vector * ray_max)
        #TODO: raise some kind of error, or do a check/poll on this operator
        #to ensure that there has been a voxel array created and selected

        isects = voxelarray.intersect_ray(ray_origin, ray_target)

        best_dist_squared = ray_max * ray_max
        best_isect = None

        if isects is None:
            return None

        for isect in isects:
            dist_squared = isect.dist_squared
            if(dist_squared < best_dist_squared):
                best_dist_squared = dist_squared
                best_isect = isect

        return best_isect
Example #5
0
def pick_object(region, rv3d, x, y, near, far, objects):
    '''
    Selects an object underneath given screen coordinates

    Parameters:
        region (bpy.types.Region): Section of the UI in which to do picking
        rv3d (bpy.types.RegionView3D): 3D view region data
        near (float): Near clipping plane
        far (float): Far clipping plane
        objects (seq<bpy.types.Object>): Sequence of pickable objects

    Returns:
        (obj, location, normal, index): Reference to picked object and raycast
        hit information; otherwise None
            obj (bpy.types.Object): Nearest object in path of the ray
            location (Vector): Object space location of ray-face intersection
            normal (Vector): Normal vector of intersected face
            index (int): Index of intersected face
    '''
    blender_version = bpy.app.version

    # Determine ray extents.
    coord = Vector((x, y))
    ray_dir = region_2d_to_vector_3d(region, rv3d, coord)
    ray_start = region_2d_to_origin_3d(region, rv3d, coord) + ray_dir * near
    ray_end = ray_start + ray_dir * (far - near)

    # Pick a mesh object underneath given screen coordinates.
    result = None
    min_dist_squared = sys.float_info.max
    for obj in objects:

        # Skip objects that cannot participate in ray casting.
        if (not obj.type == 'MESH' or
            obj.mode == 'EDIT' or
            not obj.data.polygons
        ):
            continue

        # Cast ray in object space.
        inverse_model_matrix = obj.matrix_world.inverted()
        hit =  obj.ray_cast(
            inverse_model_matrix * ray_start,
            inverse_model_matrix * ray_end
        )
        if blender_version < (2, 76, 9):
            location, normal, index = hit
        else:
            location, normal, index = hit[1:]

        # Compare intersection distances.
        if index != -1:
            dist_squared = (obj.matrix_world * location - ray_start).length_squared

            # Record closer of the two hits.
            if dist_squared < min_dist_squared:
                min_dist_squared = dist_squared
                result = (obj, location, normal, index)

    return result
 def click_add_seed(self,context,x,y):
     '''
     x,y = event.mouse_region_x, event.mouse_region_y
     
     this will add a point into the bezier curve or
     close the curve into a cyclic curve
     '''
     region = context.region
     rv3d = context.region_data
     coord = x, y
     view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
     ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
     ray_target = ray_origin + (view_vector * 1000)
     mx = self.cut_ob.matrix_world
     imx = mx.inverted()
     
     if bversion() < '002.077.000':
         loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target)
     else:
         res, loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target - imx * ray_origin)
     
     if face_ind == -1: 
         self.selected = -1
         return
     
     self.seed = self.bme.faces[face_ind]
     self.seed_loc = loc
     
     self.geo_data = [dict(), set(), set(), set()]
Example #7
0
 def raycast_screen(self, loc2d, rgn, r3d):
     o,d = region_2d_to_origin_3d(rgn, r3d, loc2d),region_2d_to_vector_3d(rgn, r3d, loc2d)
     back = 0 if r3d.is_perspective else 100
     p3d,n3d,idx,dist = self.bvh_raycast(self.imx * (o-d*back), self.imx3x3 * d)
     p3d = self.mx * p3d if p3d else None
     n3d = self.nmx * n3d if n3d else None
     return (p3d, n3d)
 def click_add_target(self, context, x, y):
     
     region = context.region
     rv3d = context.region_data
     coord = x, y
     view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
     ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
     ray_target = ray_origin + (view_vector * 1000)
     mx = self.cut_ob.matrix_world
     imx = mx.inverted()
     
     if bversion() < '002.077.000':
         loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target)
     else:
         res, loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target - imx * ray_origin)
     if face_ind == -1: return
         
         
     self.target = self.bme.faces[face_ind]
     self.target_loc = loc
     
     
     vrts, eds, ed_cross, f_cross, error = path_between_2_points(self.bme, self.bvh, mx,mx* self.seed_loc,mx*self.target_loc, 
                                                                 max_tests = 10000, debug = True, 
                                                                 prev_face = None, use_limit = True)
         
     if not error:
         self.path = vrts
     else:
         self.path = []
     return
Example #9
0
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))
Example #10
0
    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 set_ray_from_region(self, x, y):
        context = bpy.context
        mesh_object = self.mesh_object
        region = context.region
        region_co = Vector((x, y))
        rv3d = context.region_data
        sv3d = context.space_data

        # Determine the view's clipping distances.
        if rv3d.view_perspective == 'CAMERA':
            camera_data = sv3d.camera.data
            clip_start = camera_data.clip_start
            clip_end = camera_data.clip_end
        else:
            clip_start = sv3d.clip_start
            clip_end = sv3d.clip_end

        # Determine the ray's direction in world space.
        ray_direction = view3d_utils.region_2d_to_vector_3d(
            region, rv3d, region_co
        )

        # For orthographic projections in Blender versions prior to 2.72, the
        # ray's direction needs to be inverted to point into the scene.
        if bpy.app.version < (2, 72, 0):
            if rv3d.view_perspective == 'ORTHO' or (
                   rv3d.view_perspective == 'CAMERA' and
                   sv3d.camera.data.type == 'ORTHO'
               ):
                ray_direction *= -1

        # Determine the ray's origin in world space.
        ray_origin =\
            view3d_utils.region_2d_to_origin_3d(region, rv3d, region_co)

        # Determine the ray's target in world space.
        ray_target = ray_origin + clip_end * ray_direction

        # If the view is an orthographic projection, the ray's origin may exist
        # behind the mesh object.  Therefore, it is necessary to move the ray's
        # origin a sufficient distance antiparallel to the ray's direction to
        # ensure that the ray's origin is in front of the mesh object.
        if rv3d.view_perspective == 'ORTHO':
            ray_origin -= 10000 * ray_direction

        # Otherwise, if the view is a perspective projection or projected from
        # a camera then advance the ray's origin to the near clipping plane.
        else:
            ray_origin += clip_start * ray_direction

        # Convert the ray's origin and target from world space to object space,
        # if necessary.
        if self.coordinate_system == 'OBJECT':
            inverse_model_matrix = mesh_object.matrix_world.inverted()
            for co in ray_origin, ray_target:
                co.xyz = inverse_model_matrix * co

        # Set the ray caster object's ray attributes.
        self.ray_origin = ray_origin
        self.ray_target = ray_target
    def click_add_target(self, context, x, y):
        
        region = context.region
        rv3d = context.region_data
        coord = x, y
        view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
        ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
        ray_target = ray_origin + (view_vector * 1000)
        mx = self.cut_ob.matrix_world
        imx = mx.inverted()
        loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target)

        if face_ind == -1: return
            
            
        self.target = self.bme.faces[face_ind]
        self.target_loc = loc
        
        
        geos, fixed, close, far = geodesic_walk(self.bme, self.seed, self.seed_loc, 
                                                targets = [self.target], subset = None, max_iters = 100000,
                                                min_dist = None)
        
        path_elements, self.path  = gradient_descent(self.bme, geos, 
                                self.target, self.target_loc, epsilon = .0000001)
        
        self.geo_data = [geos, fixed, close, far]
        return
Example #13
0
    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 sketch_confirm(self, context, eventd):
        print('sketch confirmed')
        if len(self.sketch) < 5 and self.knife.ui_type == 'DENSE_POLY':
            print('sketch too short, cant confirm')
            return
        x,y = eventd['mouse']
        region = context.region
        rv3d = context.region_data
        view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, (x,y))
        
        last_hovered = self.knife.hovered[1] #guaranteed to be a point by criteria to enter sketch mode
        
        
        self.knife.hover(context,x,y)
        print('last hovered %i' % last_hovered)
        
        sketch_3d = common_utilities.ray_cast_path(context, self.knife.cut_ob,self.sketch)
        
        if self.knife.hovered[0] == None:  #drawing out into space
            #add the points in
            if last_hovered == len(self.knife.pts) - 1:
                if last_hovered == 0: self.knife.cyclic = False
                
                self.knife.pts += sketch_3d[0::5]
                self.knife.normals += [view_vector]*len(sketch_3d[0::5]) #TODO optimize...don't slice twice, you are smart enough to calc this length!
                print('add on to the tail')

                
            else:
                self.knife.pts = self.knife.pts[:last_hovered] + sketch_3d[0::5]
                self.knife.normals = self.knife.normals[:last_hovered] + [view_vector]*len(sketch_3d[0::5])
                print('snipped off and added on to the tail')
        
        else:
            print('inserted new segment')
            print('last hovered is %i, now hovered %i' % (last_hovered, self.knife.hovered[1]))
            new_pts = sketch_3d[0::5]
            if last_hovered > self.knife.hovered[1]:
                
                if self.knife.hovered[1] == 0:
                    self.knife.pts = self.knife.pts[:last_hovered] + new_pts
                    self.knife.normals = self.knife.normals[:last_hovered] + [view_vector]*len(new_pts)
            
                else:
                    new_pts.reverse()
                    self.knife.pts = self.knife.pts[:self.knife.hovered[1]] + new_pts + self.knife.pts[last_hovered:]
                    self.knife.normals = self.knife.normals[:self.knife.hovered[1]] + [view_vector]*len(new_pts) + self.knife.normals[last_hovered:]
            
            
            
            else:
                if self.knife.hovered[1] == 0: #drew back into tail
                    self.knife.pts += sketch_3d[0::5]
                    self.knife.normals += [view_vector]*len(sketch_3d[0::5])
                    self.knife.cyclic = True
                else:
                    self.knife.pts = self.knife.pts[:last_hovered] + new_pts + self.knife.pts[self.knife.hovered[1]:]
                    self.knife.normals = self.knife.normals[:last_hovered]  + [view_vector]*len(new_pts) + self.knife.normals[self.knife.hovered[1]:]
        self.knife.snap_poly_line()
Example #15
0
	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
Example #16
0
 def modal(self, context, event):
     region = context.region
     rv3d = context.region_data
     co2d = ((event.mouse_region_x, event.mouse_region_y))
     view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, co2d)
     enterloc = view3d_utils.region_2d_to_origin_3d(region, rv3d, co2d) + view_vector*100
     NP020PL.enterloc = copy.deepcopy(enterloc)
     print('02_GetMouseloc_FINISHED', ';', 'NP020PL.flag = ', NP020PL.flag)
     return{'FINISHED'}
Example #17
0
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
Example #18
0
    def modal(self,context,event):
        print('05_BglPlane_START',';','NP020RM.flag = ', NP020RM.flag)
        context.area.tag_redraw()
        flag = NP020RM.flag
        mode = NP020RM.mode
        plane = NP020RM.plane
        helper = NP020RM.helper
        centerloc = NP020RM.centerloc

        if event.type == 'MOUSEMOVE':
            self.co2d = ((event.mouse_region_x, event.mouse_region_y))
            print('05_BglPlane_mousemove',';','NP020RM.flag = ', NP020RM.flag, 'NP020RM.mode = ', NP020RM.mode, 'NP020RM.plane = ', NP020RM.plane)

        elif event.type in ('LEFTMOUSE', 'RIGHTMOUSE', 'RET', 'NUMPAD_ENTER'):
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            region = context.region
            rv3d = context.region_data
            co2d = self.co2d
            view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, co2d)
            viewloc = view3d_utils.region_2d_to_origin_3d(region, rv3d, co2d)
            away = (centerloc - viewloc).length
            pointloc = viewloc + view_vector * away # to place the helper on centerloc to be in the vicinity of projection plane 
            helper.location = pointloc
            helper.hide = False
            NP020RM.qdef = copy.deepcopy(NP020RM.q)
            NP020RM.ndef = copy.deepcopy(NP020RM.n)
            NP020RM.plane = 'SET'
            NP020RM.flag = 'RUNTRANSSTART'
            print('05_BglPlane_lmb_FINISHED',';','NP020RM.flag = ', NP020RM.flag, 'NP020RM.mode = ', NP020RM.mode, 'NP020RM.plane = ', NP020RM.plane)
            return{'FINISHED'}

        elif event.ctrl and event.value == 'PRESS':
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            if mode == 'FREE':
                NP020RM.mode = 'X'
            elif mode == 'X':
                NP020RM.mode = 'Y'
            elif mode == 'Y':
                NP020RM.mode = 'Z'
            else:
                NP020RM.mode = 'FREE'
            print('05_BglPlane_rmb_FINISHED',';','NP020RM.flag = ', NP020RM.flag, 'NP020RM.mode = ', NP020RM.mode, 'NP020RM.plane = ', NP020RM.plane)

        elif event.type == 'ESC':
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            NP020RM.flag = 'EXIT'
            print('05_BglPlane_esc_FINISHED',';','NP020RM.flag = ', NP020RM.flag)
            return{'FINISHED'}

        elif event.type in {'MIDDLEMOUSE', 'WHEELUPMOUSE', 'WHEELDOWNMOUSE'}:
            print('05_BglPlane_middle_wheel_any_PASS_THROUGH')
            return {'PASS_THROUGH'}

        print('05_BglPlane_standard_RUNNING_MODAL',';','NP020RM.flag = ', NP020RM.flag)
        return {'RUNNING_MODAL'}
    def modal(self,context, event):
        region = context.region
        rv3d = context.region_data
        co2d = ((event.mouse_region_x, event.mouse_region_y))
        view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, co2d) 
        pointloc = view3d_utils.region_2d_to_origin_3d(region, rv3d, co2d) + view_vector/5
        print(pointloc)
        Storage.pointloc=pointloc

        #print('020')         
        return{'FINISHED'}
def unProject(region, rv3d, mcursor):
    view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, mcursor)
    ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, mcursor)
    ray_target = ray_origin + (view_vector * 1000)    
    scene = bpy.context.scene

    # cast the ray
    result, object, matrix, location, normal = scene.ray_cast(ray_origin, ray_target)
    if location == None:
        location = Vector((0,0,0))

    return result, object, matrix, location, normal
    def hover_non_man(self,context,x,y):
        region = context.region
        rv3d = context.region_data
        coord = x, y
        self.mouse = Vector((x, y))
        
        loc3d_reg2D = view3d_utils.location_3d_to_region_2d
        
        view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
        ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
        ray_target = ray_origin + (view_vector * 1000)
        mx = self.cut_ob.matrix_world
        imx = mx.inverted()
        loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target)
        
        if len(self.non_man_points):
            co3d, index, dist = self.kd.find(mx * loc)

            #get the actual non man vert from original list
            close_bmvert = self.bme.verts[self.non_man_bmverts[index]] #stupid mapping, unreadable, terrible, fix this, because can't keep a list of actual bmverts
            close_eds = [ed for ed in close_bmvert.link_edges if not ed.is_manifold]
            if len(close_eds) == 2:
                bm0 = close_eds[0].other_vert(close_bmvert)
                bm1 = close_eds[1].other_vert(close_bmvert)
            
                a0 = bm0.co
                b   = close_bmvert.co
                a1  = bm1.co 
                
                inter_0, d0 = intersect_point_line(loc, a0, b)
                inter_1, d1 = intersect_point_line(loc, a1, b)
                
                screen_0 = loc3d_reg2D(region, rv3d, mx * inter_0)
                screen_1 = loc3d_reg2D(region, rv3d, mx * inter_1)
                screen_v = loc3d_reg2D(region, rv3d, mx * b)
                
                screen_d0 = (self.mouse - screen_0).length
                screen_d1 = (self.mouse - screen_1).length
                screen_dv = (self.mouse - screen_v).length
                
                if 0 < d0 <= 1 and screen_d0 < 30:
                    self.hovered = ['NON_MAN_ED', (close_eds[0], mx*inter_0)]
                    return
                elif 0 < d1 <= 1 and screen_d1 < 30:
                    self.hovered = ['NON_MAN_ED', (close_eds[1], mx*inter_1)]
                    return
                elif screen_dv < 30:
                    if abs(d0) < abs(d1):
                        self.hovered = ['NON_MAN_VERT', (close_eds[0], mx*b)]
                        return
                    else:
                        self.hovered = ['NON_MAN_VERT', (close_eds[1], mx*b)]
                        return
Example #22
0
  def grab_mouse_move(self,context,x,y):
      region = context.region
      rv3d = context.region_data
      coord = x, y
      view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
      ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
      ray_target = ray_origin + (view_vector * 1000)
      
      crv_mx = self.crv_obj.matrix_world
      i_crv_mx = crv_mx.inverted()  
      
      
      hit = False
      if self.snap_type == 'SCENE':
          
          mx = Matrix.Identity(4) #scene ray cast returns world coords
          if bversion() < '002.077.000':
              res, obj, omx, loc, no = context.scene.ray_cast(ray_origin, ray_target)
          else:
              res, loc, no, ind, obj, omx = context.scene.ray_cast(ray_origin, view_vector)
          
          if res:
              hit = True
      
          else:
              #cast the ray into a plane a
              #perpendicular to the view dir, at the last bez point of the curve
              hit = True
              view_direction = rv3d.view_rotation * Vector((0,0,-1))
              plane_pt = self.grab_undo_loc
              loc = intersect_line_plane(ray_origin, ray_target,plane_pt, view_direction)
              
      elif self.snap_type == 'OBJECT':
          mx = self.snap_ob.matrix_world
          imx = mx.inverted()
          
          if bversion() < '002.077.000':
              loc, no, face_ind = self.snap_ob.ray_cast(imx * ray_origin, imx * ray_target)
              if face_ind != -1:
                  hit = True
          else:
              ok, loc, no, face_ind = self.snap_ob.ray_cast(imx * ray_origin, imx * ray_target - imx*ray_origin)
              if ok:
                  hit = True
 
      if not hit:
          self.grab_cancel()
          
      else:
          local_loc = i_crv_mx * mx * loc
          self.crv_data.splines[0].bezier_points[self.selected].co = local_loc
          self.b_pts[self.selected] = mx * loc
Example #23
0
    def modal(self, context, event):
        props = context.scene.son_props

        if context.mode == 'OBJECT':
            # マウスカーソルのリージョン座標を取得
            mv = Vector((event.mouse_region_x, event.mouse_region_y))
            # 3Dビューエリアのウィンドウリージョンと、スペースを取得する
            region, space = ShowObjectName.__get_region_space(
                context, 'VIEW_3D', 'WINDOW', 'VIEW_3D'
            )
            # マウスカーソルの位置に向けて発したレイの方向を求める
            ray_dir = view3d_utils.region_2d_to_vector_3d(
                region,
                space.region_3d,
                mv
            )
            # マウスカーソルの位置に向けて発したレイの発生源を求める
            ray_orig = view3d_utils.region_2d_to_origin_3d(
                region,
                space.region_3d,
                mv
            )
            # レイの始点
            start = ray_orig
            # レイの終点(線分の長さは2000とした)
            end = ray_orig + ray_dir * 2000
            # カメラやライトなど、メッシュ型ではないオブジェクトは除く
            objs = [o for o in bpy.data.objects if o.type == 'MESH']
            self.__intersected_objs = []
            for o in objs:
                try:
                    # レイとオブジェクトの交差判定
                    mwi = o.matrix_world.inverted()
                    result = o.ray_cast(mwi * start, mwi * end)
                    # オブジェクトとレイが交差した場合は交差した面のインデックス、交差しない場合は-1が返ってくる
                    if result[2] != -1:
                        self.__intersected_objs.append(o)
                # メッシュタイプのオブジェクトが作られているが、ray_cast対象の面が存在しない場合
                except RuntimeError:
                    print("""サンプル5-4: オブジェクト生成タイミングの問題により、
                             例外エラー「レイキャスト可能なデータなし」が発生""")

        # 3Dビューの画面を更新
        if context.area:
            context.area.tag_redraw()

        # 作業時間計測を停止
        if props.running is False:
            self.__handle_remove(context)
            return {'FINISHED'}

        return {'PASS_THROUGH'}
Example #24
0
def get_mouse_on_plane(context, plane_pos, mouse_coords):
    region = context.region
    rv3d = context.region_data
    cam_dir = rv3d.view_rotation * Vector((0.0, 0.0, -1.0))
    #cam_pos = view3d_utils.region_2d_to_origin_3d(region, rv3d, (region.width/2.0, region.height/2.0))
    mouse_pos = view3d_utils.region_2d_to_origin_3d(region, rv3d, mouse_coords)
    mouse_dir = view3d_utils.region_2d_to_vector_3d(region, rv3d, mouse_coords)
    new_pos = mathu.geometry.intersect_line_plane(mouse_pos, mouse_pos+(mouse_dir*10000.0), plane_pos, cam_dir, False)

    if new_pos:
        return new_pos

    return None
Example #25
0
 def mouse_to_scene_raycast(self, context, event):
     """
         convert mouse pos to 3d point over plane defined by origin and normal
     """
     region = context.region
     rv3d = context.region_data
     co2d = (event.mouse_region_x, event.mouse_region_y)
     view_vector_mouse = region_2d_to_vector_3d(region, rv3d, co2d)
     ray_origin_mouse = region_2d_to_origin_3d(region, rv3d, co2d)
     res, pos, normal, face_index, object, matrix_world = context.scene.ray_cast(
         ray_origin_mouse,
         view_vector_mouse)
     return res, pos, normal, face_index, object, matrix_world
Example #26
0
	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 out_Location(rv3d, region, mcursor):
    view_matrix = rv3d.view_matrix.transposed()
    orig = view3d_utils.region_2d_to_origin_3d(region, rv3d, mcursor)
    vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, mcursor)
    v1 = Vector((int(view_matrix[0][0]*1.5),int(view_matrix[1][0]*1.5),int(view_matrix[2][0]*1.5)))
    v2 = Vector((int(view_matrix[0][1]*1.5),int(view_matrix[1][1]*1.5),int(view_matrix[2][1]*1.5)))
    
    hit = mathutils.geometry.intersect_ray_tri(Vector((1,0,0)), Vector((0,1,0)), Vector((0,0,0)), (vector), (orig), False)
    if hit == None:
        hit = mathutils.geometry.intersect_ray_tri(v1, v2, Vector((0,0,0)), (vector), (orig), False)        
    if hit == None:
        hit = mathutils.geometry.intersect_ray_tri(v1, v2, Vector((0,0,0)), (-vector), (orig), False)
    if hit == None:
        hit = Vector((0,0,0))
    return hit
 def mousemove_drawing(self, context, event):
     screen_v = Vector((event.mouse_region_x, event.mouse_region_y))
     self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))
    
     #this will just add in apoint every 10 recorded mouse positions
     #later you will want to do something smarter :-)
     if len(self.mouse_path) > self.draw_points_max or (screen_v - Vector(self.mouse_path[0])).length >= self.extrusion_radius:
         region = context.region
         rv3d = context.region_data
         #this is the view_vector @ the mous coord
         #which is not the same as the view_direction!!!
         view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, self.mouse_path[-1])
         ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, self.mouse_path[-1])
         ray_target = ray_origin + (view_vector * 10000)
        
         #cast the ray into a plane a
         #perpendicular to the view dir, at the last bez point of the curve
         
         view_direction = rv3d.view_rotation * Vector((0,0,-1))
         if self.active_spline.type == 'BEZIER':
             plane_pt = self.curve_object.matrix_world * self.active_spline.bezier_points[-1].co
         elif self.active_spline.type == 'NURBS':
             plane_pt = self.curve_object.matrix_world * self.active_spline.points[-1].co
             
         new_coord = intersect_line_plane(ray_origin, ray_target,plane_pt, view_direction)
        
         if new_coord:
             if self.active_spline.type == 'BEZIER':
                 self.active_spline.bezier_points.add(1)
                 self.active_spline.bezier_points[-1].co = self.curve_object.matrix_world.inverted() * new_coord
                 self.active_spline.bezier_points[-1].handle_right.xyz = self.active_spline.bezier_points[-1].co
                 self.active_spline.bezier_points[-1].handle_left.xyz = self.active_spline.bezier_points[-1].co
                 self.active_spline.bezier_points[-1].handle_left_type = 'AUTO'
                 self.active_spline.bezier_points[-1].handle_right_type = 'AUTO'
                 
             elif self.active_spline.type == 'NURBS':
                 self.active_spline.points.add(1)
                 loc = self.curve_object.matrix_world.inverted() * new_coord
                 #NURBS pahts have 4 dim points
                 self.active_spline.points[-1].co = Vector((loc[0], loc[1], loc[2], 1))
                 
            
             #udpate everything
             #udpate modifiers and objects etc.
             self.curve_object.update_tag()
             context.scene.update()
            
         self.mouse_path = []
def get_mouse_on_plane(context, plane_pos, plane_dir, mouse_coords):
    region = context.region
    rv3d = context.region_data

    final_dir = plane_dir
    if plane_dir is None:
        final_dir = rv3d.view_rotation * Vector((0.0, 0.0, -1.0))

    mouse_pos = view3d_utils.region_2d_to_origin_3d(region, rv3d, mouse_coords)
    mouse_dir = view3d_utils.region_2d_to_vector_3d(region, rv3d, mouse_coords)
    new_pos = mathu.geometry.intersect_line_plane(
        mouse_pos, mouse_pos + (mouse_dir * 10000.0), plane_pos, final_dir, False)
    if new_pos:
        return new_pos

    return None
Example #30
0
 def mouse_to_plane(self, context, event, origin=Vector((0, 0, 0)), normal=Vector((0, 0, 1))):
     """
         convert mouse pos to 3d point over plane defined by origin and normal
     """
     region = context.region
     rv3d = context.region_data
     co2d = (event.mouse_region_x, event.mouse_region_y)
     view_vector_mouse = region_2d_to_vector_3d(region, rv3d, co2d)
     ray_origin_mouse = region_2d_to_origin_3d(region, rv3d, co2d)
     pt = intersect_line_plane(ray_origin_mouse, ray_origin_mouse + view_vector_mouse,
        origin, normal, False)
     # fix issue with parallel plane
     if pt is None:
         pt = intersect_line_plane(ray_origin_mouse, ray_origin_mouse + view_vector_mouse,
             origin, view_vector_mouse, False)
     return pt
Example #31
0
def PickObject(context, event, self, ray_max=10000.0):
    scene = context.scene
    region = context.region
    rv3d = context.region_data
    coord = event.mouse_region_x, event.mouse_region_y
    view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
    ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
    ray_target = ray_origin + (view_vector * ray_max)

    def obj_ray_cast(obj, matrix):
        matrix_inv = matrix.inverted()
        ray_origin_obj = matrix_inv * ray_origin
        ray_target_obj = matrix_inv * ray_target
        hit, normal, face_index = obj.ray_cast(ray_origin_obj, ray_target_obj)
        if face_index != -1:
            return hit, normal, face_index
        else:
            return None, None, None

    for obj in bpy.context.visible_objects:
        if (obj.type == "MESH"):
            fcanv = False
            for oc in self.CList:
                if (oc == obj):
                    fcanv = True
            for oc in self.OPList:
                if (oc == obj):
                    fcanv = True
            if (fcanv == False):
                matrix = obj.matrix_world
                hit, normal, face_index = obj_ray_cast(obj, matrix)
                if hit is not None:
                    hit_world = matrix * hit
                    return obj

    return None
Example #32
0
    def grab_mouse_move(self, context, x, y):
        region = context.region
        rv3d = context.region_data
        coord = x, y
        view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
        ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
        ray_target = ray_origin + (view_vector * 1000)

        mx = self.cut_ob.matrix_world
        imx = mx.inverted()
        if bversion() < '002.077.000':
            loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin,
                                                     imx * ray_target)
        else:
            ok, loc, no, face_ind = self.cut_ob.ray_cast(
                imx * ray_origin, imx * ray_target - imx * ray_origin)

        if face_ind == -1:
            self.grab_cancel()
        else:
            self.pts[self.selected] = mx * loc
            self.cut_pts[self.selected] = loc
            self.normals[self.selected] = no
            self.face_map[self.selected] = face_ind
Example #33
0
def RayCast(self, context, event, ray_max=1000.0):
    """Run this function on left mouse, execute the ray cast"""
    # get the context arguments
    scene = context.scene
    region = context.region
    rv3d = context.region_data
    coord = event.mouse_region_x, event.mouse_region_y

    # get the ray from the viewport and mouse
    view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d,
                                                      coord).normalized()
    ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)

    ray_target = ray_origin + view_vector

    def visible_objects_and_duplis():
        """Loop over (object, matrix) pairs (mesh only)"""

        for obj in context.visible_objects:
            if obj.type == 'MESH':
                yield (obj, obj.matrix_world.copy())

            if obj.dupli_type != 'NONE':
                obj.dupli_list_create(scene)
                for dob in obj.dupli_list:
                    obj_dupli = dob.object
                    if obj_dupli.type == 'MESH':
                        yield (obj_dupli, dob.matrix.copy())

            obj.dupli_list_clear()

    def obj_ray_cast(obj, matrix):
        """Wrapper for ray casting that moves the ray into object space"""

        # get the ray relative to the object
        matrix_inv = matrix.inverted()
        ray_origin_obj = matrix_inv * ray_origin
        ray_target_obj = matrix_inv * ray_target
        ray_direction_obj = ray_target_obj - ray_origin_obj
        d = ray_direction_obj.length

        ray_direction_obj.normalize()

        # cast the ray
        if context.mode == 'OBJECT':
            #print("object")

            if obj.modifiers == 0:
                bvh = BVHTree.FromObject(obj, context.scene)
                location, normal, face_index, d = bvh.ray_cast(
                    ray_origin_obj, ray_direction_obj)
            else:
                scene = bpy.context.scene
                #obj = obj.to_mesh(scene, apply_modifiers=True, settings='PREVIEW')
                bvh = BVHTree.FromObject(obj, context.scene)
                location, normal, face_index, d = bvh.ray_cast(
                    ray_origin_obj, ray_direction_obj)
                #success, location, normal, face_index = obj.ray_cast(ray_origin_obj, ray_direction_obj)
                #bpy.data.meshes.remove(obj)

        elif context.mode == 'EDIT_MESH':
            obj.update_from_editmode()
            bvh = BVHTree.FromBMesh(bmesh.from_edit_mesh(obj.data))
            location, normal, face_index, d = bvh.ray_cast(
                ray_origin_obj, ray_direction_obj)

        if face_index != -1:
            return location, normal, face_index
        else:
            return None, None, None

    # cast rays and find the closest object
    best_length_squared = -1.0
    best_obj = None
    best_matrix = None
    best_face = None
    best_hit = None

    for obj, matrix in visible_objects_and_duplis():
        if obj.type == 'MESH':

            hit, normal, face_index = obj_ray_cast(obj, matrix)
            if hit is not None:
                hit_world = matrix * hit
                scene.cursor_location = hit_world
                length_squared = (hit_world - ray_origin).length_squared
                if best_obj is None or length_squared < best_length_squared:
                    best_length_squared = length_squared
                    best_obj = obj
                    best_matrix = matrix
                    best_face = face_index
                    best_hit = hit
                    break

    def run(best_obj, best_matrix, best_face, best_hit):
        best_distance = float(
            "inf"
        )  # use float("inf") (infinity) to have unlimited search range
        if context.mode == 'EDIT_MESH':
            mesh = best_obj.data
        else:
            mesh = best_obj
        #best_matrix = best_obj.matrix_world
        for vert_index in mesh.polygons[best_face].vertices:
            vert_coord = mesh.vertices[vert_index].co
            distance = (vert_coord - best_hit).magnitude
            if distance < best_distance:
                best_distance = distance
                CreateOrientation(self, context, event, vert_coord)
                scene.cursor_location = best_matrix * vert_coord

        for v0, v1 in mesh.polygons[best_face].edge_keys:
            p0 = mesh.vertices[v0].co
            p1 = mesh.vertices[v1].co
            p = (p0 + p1) / 2
            distance = (p - best_hit).magnitude
            if distance < best_distance:
                best_distance = distance
                vec = p0 - p1
                CreateOrientation(self, context, event, vec)
                scene.cursor_location = best_matrix * p

        face_pos = Vector(mesh.polygons[best_face].center)
        distance = (face_pos - best_hit).magnitude
        if distance < best_distance:
            best_distance = distance
            vec = mesh.polygons[best_face].normal.copy()
            CreateOrientation(self, context, event, vec)
            scene.cursor_location = best_matrix * face_pos

    if best_obj is not None:
        if best_obj.modifiers == 0:
            run(best_obj.data, best_matrix, best_face, best_hit)
        else:
            if context.mode == 'OBJECT':
                scene = bpy.context.scene
                obj_data = best_obj.to_mesh(scene,
                                            apply_modifiers=True,
                                            settings='PREVIEW')
                run(obj_data, best_matrix, best_face, best_hit)
                bpy.data.meshes.remove(obj_data)
            elif context.mode == 'EDIT_MESH':
                run(best_obj, best_matrix, best_face, best_hit)
Example #34
0
def main(context, event):
    """Run this function on left mouse, execute the ray cast"""
    # get the context arguments
    scene = context.scene
    region = context.region
    rv3d = context.region_data
    coord = event.mouse_region_x, event.mouse_region_y

    # get the ray from the viewport and mouse
    view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
    ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)

    ray_target = ray_origin + view_vector

    def visible_objects_and_duplis():
        """Loop over (object, matrix) pairs (mesh only)"""

        for obj in context.visible_objects:
            if obj.type == 'MESH':
                yield (obj, obj.matrix_world.copy())

            if obj.dupli_type != 'NONE':
                obj.dupli_list_create(scene)
                for dob in obj.dupli_list:
                    obj_dupli = dob.object
                    if obj_dupli.type == 'MESH':
                        yield (obj_dupli, dob.matrix.copy())

            obj.dupli_list_clear()

    def obj_ray_cast(obj, matrix):
        """Wrapper for ray casting that moves the ray into object space"""

        # get the ray relative to the object
        matrix_inv = matrix.inverted()
        ray_origin_obj = matrix_inv @ ray_origin
        ray_target_obj = matrix_inv @ ray_target
        ray_direction_obj = ray_target_obj - ray_origin_obj

        # cast the ray
        success, location, normal, face_index = obj.ray_cast(
            ray_origin_obj, ray_direction_obj)

        if success:
            return location, normal, face_index
        else:
            return None, None, None

    # cast rays and find the closest object
    best_length_squared = -1.0
    best_obj = None

    for obj, matrix in visible_objects_and_duplis():
        if obj.type == 'MESH':
            hit, normal, face_index = obj_ray_cast(obj, matrix)
            if hit is not None:
                hit_world = matrix @ hit
                scene.cursor_location = hit_world
                length_squared = (hit_world - ray_origin).length_squared
                if best_obj is None or length_squared < best_length_squared:
                    best_length_squared = length_squared
                    best_obj = obj

    # now we have the object under the mouse cursor,
    # we could do lots of stuff but for the example just select.
    if best_obj is not None:
        best_obj.select_set(True)
        context.view_layer.objects.active = best_obj
Example #35
0
def pick_and_clone(self, context, event, ray_max=10000.0):
    """Run this function on left mouse, execute the ray cast"""
    # get the context arguments
    scene = context.scene
    region = context.region
    rv3d = context.region_data
    coord = event.mouse_region_x, event.mouse_region_y

    def obj_ray_cast(obj, matrix, view_vector, ray_origin):
        """Wrapper for ray casting that moves the ray into object space"""

        ray_target = ray_origin + (view_vector * ray_max)

        # get the ray relative to the object
        matrix_inv = matrix.inverted()
        ray_origin_obj = matrix_inv * ray_origin
        ray_target_obj = matrix_inv * ray_target
        ray_vector_obj = ray_target_obj - ray_origin_obj

        # cast the ray
        hit_result, hit, normal, face_index = obj.ray_cast(
            ray_origin_obj, ray_vector_obj, ray_max)

        if hit_result:
            hit_world = matrix * hit

            length_squared = (hit_world - ray_origin).length_squared

            if face_index != -1:
                #normal_world = (matrix.to_quaternion() * normal).normalized()

                normal_world = (matrix.to_quaternion() * normal).to_4d()
                normal_world.w = 0
                normal_world = (
                    matrix.to_quaternion() *
                    (matrix_inv * normal_world).to_3d()).normalized()

                return normal_world, hit_world, length_squared

        return None, None, None

    # cast rays and find the closest object
    best_length_squared = ray_max * ray_max
    best_obj, best_obj_nor, best_obj_pos = None, None, None
    best_obj_rand, best_obj_nor_rand, best_obj_pos_rand = None, None, None
    best_obj_hit = None

    pct = context.scene.paintClonesTools
    thePressure = max(1.0 - pct.drawPressure,
                      self.tabletPressure)  # The pressure of a pen!

    for obj, matrix in self.dupliList:
        # get the ray from the viewport and mouse
        view_vector_mouse = view3d_utils.region_2d_to_vector_3d(
            region, rv3d, coord)
        ray_origin_mouse = view3d_utils.region_2d_to_origin_3d(
            region, rv3d, coord)

        # Do RayCast! t1,t2,t3,t4 - temp values
        t1, t2, t3 = obj_ray_cast(obj, matrix, view_vector_mouse,
                                  ray_origin_mouse)
        if t1 is not None and t3 < best_length_squared:
            best_obj = obj
            best_obj_nor, best_obj_pos, best_length_squared = t1, t2, t3
            best_obj_hit = t2

        # Check for stroke length
        if best_obj is not None:
            previousHit = None
            if len(self.currentStrokeList) > 0:
                previousHit = self.currentStrokeList[-1]  # get Last Element

            # Check for stroke
            strokeLength = pct.drawStrokeLength
            if pct.drawPressureScale is True and pct.drawPressureRelativeStroke is True and self.tabletPressure < 1.0 and pct.drawPressure > 0.0:
                strokeLength *= thePressure
            if previousHit is not None and (
                    best_obj_pos - previousHit.hitPoint).length < strokeLength:
                best_obj = None  # Don't do cloning

    # random scatter things
    if pct.drawRandomStrokeScatter > 0.0 and best_obj is not None and t1 is not None:
        # Random Vec
        randX = random.uniform(
            -1.0, 1.0) * pct.drawRandomStrokeScatter  # 3.0 is random addition
        randY = random.uniform(
            -1.0, 1.0) * pct.drawRandomStrokeScatter  # 3.0 is random addition
        randZ = random.uniform(-1.0, 1.0) * pct.drawRandomStrokeScatter

        if pct.drawPressureScatter is True and self.tabletPressure < 1.0 and pct.drawPressure > 0.0:
            randX *= thePressure
            randY *= thePressure
            randZ *= thePressure

        randVect = Vector((randX, randY, randZ))

        for obj, matrix in self.dupliList:
            ray_origin_rand = best_obj_pos + randVect
            ray_origin_rand_2d = view3d_utils.location_3d_to_region_2d(
                region, rv3d, ray_origin_rand)

            view_vector_rand = view3d_utils.region_2d_to_vector_3d(
                region, rv3d, (ray_origin_rand_2d.x, ray_origin_rand_2d.y))

            t1, t2, t3 = obj_ray_cast(obj, matrix, view_vector_rand,
                                      ray_origin_rand)
            # 3.0 is random addition
            if t1 is not None and (
                    t2 -
                    best_obj_hit).length <= pct.drawRandomStrokeScatter * 3.0:
                best_obj_nor, best_obj_pos = t1, t2

    # now we have the object under the mouse cursor,
    if best_obj is not None:
        objToClone = bpy.data.objects.get(random.choice(paintClonesSourceList))
        best_obj_nor = best_obj_nor.normalized()

        # Rotation To LookAt
        previousHit = None
        if len(self.currentStrokeList) > 0:
            previousHit = self.currentStrokeList[-1]  # get Last Element
        else:
            if len(self.allStrokesList) > 0:
                previousHit = self.allStrokesList[-1][
                    -1]  # get Last Element of previous Stroke
        if previousHit is not None:
            stroke_axis = (best_obj_hit - previousHit.hitPoint).normalized()
        else:
            stroke_axis = xAxis
        # clone object
        newDup = bpy.data.objects.new(objToClone.name, objToClone.data)

        # copy draw type
        newDup.draw_type = objToClone.draw_type
        newDup.show_wire = objToClone.show_wire

        # copy transformation
        newDup.matrix_world = objToClone.matrix_world
        newDup.location = best_obj_pos
        newDup.scale = objToClone.scale
        newDup.rotation_euler = objToClone.rotation_euler
        # bpy.ops.object.rotation_clear()

        context.scene.objects.link(newDup)
        newDup.select = True
        context.scene.objects.active = newDup

        # Random Rotation (PreRotate)
        randRotX, randRotY, randRotZ = random.uniform(
            -1.0, 1.0), random.uniform(-1.0, 1.0), random.uniform(-1.0, 1.0)
        bpy.ops.transform.rotate(value=randRotX * pct.randRotationX,
                                 axis=get_obj_axis(newDup, 'X'),
                                 proportional='DISABLED')
        bpy.ops.transform.rotate(value=randRotY * pct.randRotationY,
                                 axis=get_obj_axis(newDup, 'Y'),
                                 proportional='DISABLED')
        bpy.ops.transform.rotate(value=randRotZ * pct.randRotationZ,
                                 axis=get_obj_axis(newDup, 'Z'),
                                 proportional='DISABLED')

        # Rotation To Stroke direction
        if pct.align_mode == 'STROKE':
            track_vec = stroke_axis
            up_vec = best_obj_nor

        # Rotation To Normal
        if pct.align_mode == 'NORMAL':
            track_vec = best_obj_nor
            up_vec = stroke_axis

        # Rotation To X_AXIS
        if pct.align_mode == 'X_AXIS':
            track_vec = xAxis
            up_vec = stroke_axis

        # Rotation To Y_AXIS
        if pct.align_mode == 'Y_AXIS':
            track_vec = yAxis
            up_vec = stroke_axis

        # Rotation To Z_AXIS
        if pct.align_mode == 'Z_AXIS':
            track_vec = zAxis
            up_vec = stroke_axis

        q = get_rot_quat(newDup, track_vec, up_vec, pct.track_axis,
                         pct.up_axis)

        bpy.ops.transform.rotate(value=q.angle,
                                 axis=(q.axis),
                                 proportional='DISABLED')

        # Scale
        if pct.drawPressure > 0.0 or pct.randScale > 0.0:
            newSize = newDup.scale
            if self.tabletPressure < 1.0 and pct.drawPressure > 0.0 and pct.drawPressureScale is True:
                newSize *= thePressure

            if pct.randScale > 0.0:
                randScale = 1.0 - \
                    (random.uniform(0.0, 1.0) *
                     pct.randScale / 100.0)
                newSize *= randScale

        # do optimization for a stroke or not
        if pct.drawClonesOptimize is False:
            copy_settings_clones(pct, newDup, objToClone)

        newDup.select = False  # Clear Selection

        # Add this point with all its stuff
        self.currentStrokeList.append(
            StrokePoint(newDup, objToClone, best_obj_hit, best_obj_nor))
Example #36
0
def get_selection_point(context, event, ray_max=10000.0,objects=None,floor=None,exclude_objects=[]):
    """Gets the point to place an object based on selection"""
    # get the context arguments
    scene = context.scene
    region = context.region
    rv3d = context.region_data
    coord = event.mouse_region_x, event.mouse_region_y

    # get the ray from the viewport and mouse
    view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
    ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
    ray_target = ray_origin + view_vector
 
    def visible_objects_and_duplis():
        """Loop over (object, matrix) pairs (mesh only)"""
 
        for obj in context.visible_objects:
             
            if objects:
                if obj in objects and obj not in exclude_objects:
                    yield (obj, obj.matrix_world.copy())
             
            else:
                if obj not in exclude_objects:
                    if floor is not None and obj == floor:
                        yield (obj, obj.matrix_world.copy())
                         
    #                 if obj.draw_type != 'WIRE':
                    if obj.type == 'MESH' and obj.hide_select == False:
                        yield (obj, obj.matrix_world.copy())
    
                    if obj.instance_type != 'NONE':
                        obj.dupli_list_create(scene)
                        for dob in obj.dupli_list:
                            obj_dupli = dob.object
                            if obj_dupli.type == 'MESH':
                                yield (obj_dupli, dob.matrix.copy())
 
            # obj.dupli_list_clear()
 
    def obj_ray_cast(obj, matrix):
        """Wrapper for ray casting that moves the ray into object space"""
        try:
            # get the ray relative to the object
            matrix_inv = matrix.inverted()
            ray_origin_obj = matrix_inv @ ray_origin
            ray_target_obj = matrix_inv @ ray_target
            ray_direction_obj = ray_target_obj - ray_origin_obj
     
            # cast the ray
            success, location, normal, face_index = obj.ray_cast(ray_origin_obj, ray_direction_obj)
     
            if success:
                return location, normal, face_index
            else:
                return None, None, None
        except:
            print("ERROR IN obj_ray_cast",obj)
            return None, None, None
             
    best_length_squared = ray_max * ray_max
    best_obj = None
    best_hit = (0,0,0)
    for obj, matrix in visible_objects_and_duplis():
        if obj.type == 'MESH':
            if obj.data:
                hit, normal, face_index = obj_ray_cast(obj, matrix)
                if hit is not None:
                    hit_world = matrix @ hit
                    length_squared = (hit_world - ray_origin).length_squared
                    if length_squared < best_length_squared:
                        best_hit = hit_world
                        best_length_squared = length_squared
                        best_obj = obj
                        
    return best_hit, best_obj    
Example #37
0
    def modal(self, context, event):
        if not self._handers_installed:
            self.add_viewport_handlers(context)

        context.window.cursor_modal_set('CROSSHAIR')
        context.area.tag_redraw()

        if context.mode != 'EDIT_MESH' or not self.active:
            self.cleanup(context, event)
            if self.touched:
                return {'FINISHED'}
            else:
                return {'CANCELLED'}
            
        update_mesh = False

        if self.obj != context.active_object:
            self.obj = context.active_object
            update_mesh = True
        if self.mesh_changed:
            update_mesh = True
            self.select_changed = True
            self.mesh_changed = False

        if update_mesh:
            self.mesh = bmesh.from_edit_mesh(self.obj.data)
            self.select_changed = True

        obj = self.obj
        mesh = self.mesh
        scene = context.scene
        vps = obj.data.vertex_paint_settings
        radius = float(vps.radius)

        region = context.region
        region_3d = context.space_data.region_3d
        mouse_pos = mouse_x, mouse_y = (event.mouse_region_x, event.mouse_region_y)
        to_obj = obj.matrix_world.inverted()
        direction = to_obj * view3d_utils.region_2d_to_vector_3d(region, region_3d, mouse_pos).normalized()
        mouse = mu.Vector(mouse_pos)

        self.mouse_pos = mouse_pos

        if event.type in ('RIGHTMOUSE', 'A') and event.value == 'RELEASE':
            self.mesh_changed = True

        if not self.painting and (
                mouse_x < 0 or mouse_x > region.width or
                mouse_y < 0 or mouse_y > region.height):
            return {'PASS_THROUGH'}

        if event.type == 'LEFTMOUSE':
            if event.value == 'PRESS':
                self.last_daub_position = mu.Vector((-1000, -1000))
                self.last_daub_time = 0
                self.painting = True

            elif event.value == 'RELEASE':
                ops.ed.undo_push()
                bmesh.update_edit_mesh(obj.data)
                scene.update()
                self.painting = False

        if self.painting:
            self.touched = True

            update_mask = False
            apply_daub = False

            if event.type in ('LEFTMOUSE', 'MOUSEMOVE'):
                if vps.stroke_method == 'SHIFT':
                    delta = (mouse - self.last_daub_position).magnitude
                    if delta < vps.stroke_spacing:
                        return {'RUNNING_MODAL'}
                    else:
                        self.last_daub_position = mouse
                        apply_daub = True
                        update_mask = True
                else:
                    update_mask = True
    
            if vps.stroke_method == 'TIME' and event.type == 'TIMER':
                now = time.time()
                delta = now - self.last_daub_time
                if delta < vps.stroke_timestep:
                    return {'RUNNING_MODAL'}
                else:
                    self.last_daub_time = now
                    apply_daub = True

            if update_mask:
                if self.select_changed:
                    mesh.verts.index_update()
                    mesh.edges.index_update()
                    mesh.faces.index_update()
                    self.vert_select = [v.select for v in mesh.verts]
                    self.edge_select = [e.select for e in mesh.edges]
                    self.face_select = [f.select for f in mesh.faces]
                    self.select_none = (
                        (True not in self.vert_select) and
                        (True not in self.edge_select) and
                        (True not in self.face_select))
                    self.select_all = (
                        (False not in self.vert_select) and
                        (False not in self.edge_select) and
                        (False not in self.face_select))
                    self.select_some = not (self.select_none or self.select_all)
                    if self.select_some:
                        self.mask_select_verts = set(v.index for v in mesh.verts if v.select)
                        self.mask_select_faces = set(f.index for f in mesh.faces if f.select)
                    self.select_changed = False

                occlude = (vps.mask == 'OCCLUDE')

                mesh_select_mode = tuple(context.tool_settings.mesh_select_mode)
                use_occlude_geometry = context.space_data.use_occlude_geometry
                context.tool_settings.mesh_select_mode = (True, True, True)
                context.space_data.use_occlude_geometry = occlude
                ops.mesh.select_all(action='DESELECT')
                ops.view3d.select_circle(x=mouse_x, y=mouse_y, radius=radius, gesture_mode=3)
                self.mask_daub_verts = set([vert.index for vert in mesh.verts if vert.select])
                self.mask_daub_faces = set([face.index for face in mesh.faces if face.select])
                context.tool_settings.mesh_select_mode = mesh_select_mode
                context.space_data.use_occlude_geometry = use_occlude_geometry
                ops.mesh.select_all(action='DESELECT')

                if self.select_all:
                    ops.mesh.select_all(action='SELECT')
                    scene.update()

                elif not self.select_none:
                    if mesh_select_mode[0]:
                        [v.select_set(s) for (v, s) in zip(mesh.verts, self.vert_select) if s]
                    if mesh_select_mode[1]:
                        [e.select_set(s) for (e, s) in zip(mesh.edges, self.edge_select) if s]
                    if mesh_select_mode[2]:
                        [f.select_set(s) for (f, s) in zip(mesh.faces, self.face_select) if s]

                bias = vps.bias
                scale = vps.scale
                weights = self.weights = {}

                if self.select_some:
                    verts = self.mask_select_verts.intersection(self.mask_daub_verts)
                else:
                    verts = self.mask_daub_verts

                falloff = lambda x: x

                if vps.falloff == 'SMOOTH':
                    falloff = cc.utils.smooth
                elif vps.falloff == 'SHARP':
                    falloff = math.sqrt
                elif vps.falloff == 'ROOT':
                    falloff = lambda x: x * x

                for vid in verts:
                    vert = mesh.verts[vid]
                    p = obj.matrix_world * vert.co
                    p = view3d_utils.location_3d_to_region_2d(region, region_3d, p)
                    dist = min(1, max(0, (p - mouse).magnitude / radius))
                    dist = max(min((dist - bias) / scale, 1), 0)
                    dist = falloff(dist)
                    weights[vid] = 1 - dist

            if apply_daub:
                weights = self.weights
                layer = mesh.loops.layers.color.active

                if self.select_some:
                    faces = self.mask_select_faces.intersection(self.mask_daub_faces)
                else:
                    faces = self.mask_daub_faces

                b = vps.color
                white = mu.Color((1, 1, 1))
                black = mu.Color((0, 0, 0))
                strength = vps.strength
                nbias = vps.normal_bias
                nscale = vps.normal_scale

                if vps.mask == 'NORMAL':
                    if vps.normal == 'VERTEX':
                        normal_mask = lambda f, v: max(min((
                            (direction.dot(v.normal) * 0.5 + 0.5) -
                            nbias) / nscale, 1), 0)
                    else:
                        normal_mask = lambda f, v: max(min((
                            (direction.dot(f.normal) * 0.5 + 0.5) -
                            nbias) / nscale, 1), 0)
                else:
                    normal_mask = lambda f, v: 1

                if vps.blend == 'MIX':
                    for fid in faces:
                        face = mesh.faces[fid]
                        for loop in face.loops:
                            weight = weights[loop.vert.index]
                            mask = normal_mask(face, loop.vert)
                            a = loop[layer]
                            a.r = lerp(a.r, b.r, weight * strength * mask)
                            a.g = lerp(a.g, b.g, weight * strength * mask)
                            a.b = lerp(a.b, b.b, weight * strength * mask)

                if vps.blend == 'MULTIPLY':
                    for fid in faces:
                        face = mesh.faces[fid]
                        for loop in face.loops:
                            weight = weights[loop.vert.index]
                            mask = normal_mask(face, loop.vert)
                            a = loop[layer]
                            a.r *= lerp(1, b.r, weight * strength * mask)
                            a.g *= lerp(1, b.g, weight * strength * mask)
                            a.b *= lerp(1, b.b, weight * strength * mask)

                if vps.blend == 'ADD':
                    for fid in faces:
                        face = mesh.faces[fid]
                        for loop in face.loops:
                            weight = weights[loop.vert.index]
                            mask = normal_mask(face, loop.vert)
                            a = loop[layer]
                            a.r += lerp(0, b.r, weight * strength * mask)
                            a.g += lerp(0, b.g, weight * strength * mask)
                            a.b += lerp(0, b.b, weight * strength * mask)

                if vps.blend == 'SUBTRACT':
                    for fid in faces:
                        face = mesh.faces[fid]
                        for loop in face.loops:
                            weight = weights[loop.vert.index]
                            mask = normal_mask(face, loop.vert)
                            a = loop[layer]
                            a.r -= lerp(0, b.r, weight * strength * mask)
                            a.g -= lerp(0, b.g, weight * strength * mask)
                            a.b -= lerp(0, b.b, weight * strength * mask)

                bmesh.update_edit_mesh(obj.data)

            return {'RUNNING_MODAL'}

        else:
            if event.type == 'D' and event.value == 'PRESS':
                vps.color = sample_color(context, event)
                return {'RUNNING_MODAL'}

            if event.type in ('I', 'S') and event.value == 'PRESS':
                a = mu.Color((vps.color.r, vps.color.g, vps.color.b))
                b = mu.Color((vps.swap.r, vps.swap.g, vps.swap.b))
                vps.color = b
                vps.swap = a
                return {'RUNNING_MODAL'}
    
            if event.type == 'WHEELUPMOUSE':
                if event.ctrl:
                    vps.radius = max(1, math.floor(vps.radius * 0.9))
                    return {'RUNNING_MODAL'}
                elif event.shift:
                    if event.alt:
                        vps.strength = max(0.01, cc.utils.roundq(vps.strength - 0.01, 0.01))
                    else:
                        vps.strength = max(0.1, cc.utils.roundq(vps.strength - 0.1, 0.1))
                    return {'RUNNING_MODAL'}

            if event.type == 'WHEELDOWNMOUSE':
                if event.ctrl:
                    vps.radius = max(1, math.ceil(vps.radius * 1.1))
                    return {'RUNNING_MODAL'}
                elif event.shift:
                    if event.alt:
                        vps.strength = min(1, cc.utils.roundq(vps.strength + 0.01, 0.01))
                    else:
                        vps.strength = min(1, cc.utils.roundq(vps.strength + 0.1, 0.1))
                    return {'RUNNING_MODAL'}

            if event.type == 'ESC':
                self.cleanup(context, event)
                return {'CANCELLED'}

            if event.type == 'SPACE':
                self.cleanup(context, event)
                return {'FINISHED'}

        return {'PASS_THROUGH'}
Example #38
0
    def click_add_point(self, context, x, y):
        '''
        x,y = event.mouse_region_x, event.mouse_region_y
        
        this will add a point into the bezier curve or
        close the curve into a cyclic curve
        '''
        region = context.region
        rv3d = context.region_data
        coord = x, y
        view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
        ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
        ray_target = ray_origin + (view_vector * 1000)

        crv_mx = self.crv_obj.matrix_world
        i_crv_mx = crv_mx.inverted()

        hit = False
        if self.snap_type == 'SCENE':
            mx = Matrix.Identity(
                4
            )  #loc is given in world loc...no need to multiply by obj matrix
            if bversion() < '002.077.000':
                res, obj, omx, loc, no = context.scene.ray_cast(
                    ray_origin, ray_target)  #changed in 2.77
            else:
                res, loc, no, ind, obj, omx = context.scene.ray_cast(
                    ray_origin, view_vector)

            hit = res
            if not hit:
                #cast the ray into a plane a
                #perpendicular to the view dir, at the last bez point of the curve

                view_direction = rv3d.view_rotation * Vector((0, 0, -1))

                if len(self.b_pts):
                    if self.hovered[0] == 'EDGE':
                        plane_pt = self.b_pts[self.hovered[1]]
                    else:
                        plane_pt = self.b_pts[-1]
                else:
                    plane_pt = context.scene.cursor_location
                loc = intersect_line_plane(ray_origin, ray_target, plane_pt,
                                           view_direction)
                hit = True
        elif self.snap_type == 'OBJECT':
            mx = self.snap_ob.matrix_world
            imx = mx.inverted()

            if bversion() < '002.077.000':
                loc, no, face_ind = self.snap_ob.ray_cast(
                    imx * ray_origin, imx * ray_target)
                if face_ind != -1:
                    hit = True
            else:
                ok, loc, no, face_ind = self.snap_ob.ray_cast(
                    imx * ray_origin, imx * ray_target - imx * ray_origin)
                if ok:
                    hit = True

            if face_ind != -1:
                hit = True

        if not hit:
            self.selected = -1
            return

        if self.hovered[0] == None:  #adding in a new point
            if self.started:
                self.crv_data.splines[0].bezier_points.add(count=1)
                bp = self.crv_data.splines[0].bezier_points[-1]
                bp.handle_right_type = 'AUTO'
                bp.handle_left_type = 'AUTO'
                bp.co = i_crv_mx * mx * loc
                self.b_pts.append(mx * loc)

            else:
                self.started = True
                delta = i_crv_mx * mx * loc - self.crv_data.splines[
                    0].bezier_points[-1].co
                bp = self.crv_data.splines[0].bezier_points[0]
                bp.co += delta
                bp.handle_left += delta
                bp.handle_right += delta
                self.b_pts.append(mx * loc)

        if self.hovered[0] == 'POINT':
            self.selected = self.hovered[1]
            if self.hovered[1] == 0:  #clicked on first bpt, close loop
                self.crv_data.splines[0].use_cyclic_u = self.crv_data.splines[
                    0].use_cyclic_u == False
            return

        elif self.hovered[0] == 'EDGE':  #cut in a new point
            self.b_pts.insert(self.hovered[1] + 1, mx * loc)
            self.update_blender_curve_data()
            return
    def modal(self, context, event):
        self.mouse_x = event.mouse_region_x
        self.mouse_y = event.mouse_region_y

        self.region = context.region

        if context.space_data is not None:
            self.region_3d = context.space_data.region_3d

            self.updateSelectionModes(context)

            # self.flag_redraw -> one more redraw needed at the end of modals
            # (which block this very one)
            if self.flag and not self.flag_redraw:
                self.region.tag_redraw()
                self.flag_redraw = True
            elif self.flag_redraw:
                self.flag_redraw = False
                
            self.flag = False

            if (self.region_3d is not None and context.mode == 'EDIT_MESH'
                and self.running):

                coords = (self.mouse_x, self.mouse_y)

                self.ray_origin = region_2d_to_origin_3d(
                    self.region,
                    self.region_3d,
                    coords)
                self.ray_direction = region_2d_to_vector_3d(
                    self.region,
                    self.region_3d,
                    coords)*RAY_MAX

                obj = context.object
                matrix_world = obj.matrix_world

                if self.bmesh is None or not self.bmesh.is_valid:
                    self.bmesh = from_edit_mesh(obj.data)

                df = self.draw_face
                de = self.draw_edges
                dv = self.draw_verts

                found = False

                if self.select_verts:

                    min_dist_sqr = None
                    point_vert = None

                    for vert in self.bmesh.verts:
                        if not vert.hide:
                            point = matrix_world*vert.co
                            point_2d = self.location_3d_to_region_2d(point)

                            dist_sqr = self.testVert2D(point_2d)

                            if dist_sqr is not None:
                                if (min_dist_sqr is None
                                    or min_dist_sqr > dist_sqr):
                                    min_dist_sqr = dist_sqr
                                    point_vert = point

                    if point_vert is None or min_dist_sqr > DIST_MAX_SQR:
                        #????
                        self.draw_face = None
                        self.draw_edges = []
                        self.draw_verts = []

                    else:
                        found = True
                        self.draw_face = None
                        self.draw_edges = []
                        self.draw_verts = [point_vert]


                if self.select_edges and not found:

                    min_dist_sqr = None
                    points_edge = None

                    for edge in self.bmesh.edges:
                        if not edge.hide:
                            points = [matrix_world*v.co for v in edge.verts]
                            points_2d = [self.location_3d_to_region_2d(point)
                                         for point in points]

                            dist_sqr = self.testEdge2D(points_2d)

                            if dist_sqr is not None:
                                if (min_dist_sqr is None
                                    or min_dist_sqr > dist_sqr):
                                    min_dist_sqr = dist_sqr
                                    points_edge = points

                    if points_edge is None or min_dist_sqr > DIST_MAX_SQR:
                        #????
                        self.draw_face = None
                        self.draw_edges = []
                        self.draw_verts = []

                    else:
                        found = True
                        self.draw_face = None
                        self.draw_edges = [points_edge]
                        self.draw_verts = points_edge
                        

                if self.select_faces and not found:

                    min_dist = None
                    points_face = None
                    
                    for face in self.bmesh.faces:
                        if not face.hide:
                            points = [matrix_world*v.co for v in face.verts]
                            points_2d = [self.location_3d_to_region_2d(point)
                                         for point in points]
                            tess_face = tessellate_polygon((points,))

                            possible_tris = []

                            for tri in tess_face:
                                if self.testTri2D([points_2d[i] for i in tri]):
                                    possible_tris.append(tri)

                            for tri in possible_tris:
                                dist = self.testTri3D([points[i] for i in tri])
                                if dist is not None:
                                    if min_dist is None or min_dist > dist:
                                        min_dist = dist
                                        points_face = points
                                        break

                    if points_face is None:
                        self.draw_face = None
                        self.draw_edges = [] # XXX TEMP!!!
                        self.draw_verts = [] # XXX
                    else:
                        self.draw_face = points_face
                        self.draw_edges = [(points_face[i - 1], v)
                                           for i, v in enumerate(points_face)]
                        self.draw_verts = points_face

                if (df != self.draw_face or de != self.draw_edges
                    or dv != self.draw_verts):
                    self.region.tag_redraw()
                    # forced redraw -> not another modal
                    # -> no need for a new one
                    self.flag_redraw = True
Example #40
0
 def Point2D_to_Ray(self, p2d):
     o = Point(region_2d_to_origin_3d(self.rgn, self.r3d, p2d))
     d = Direction(region_2d_to_vector_3d(self.rgn, self.r3d, p2d))
     return Ray(o, d)
Example #41
0
def mouse_vector(op):
    return region_2d_to_vector_3d(region(), region3d(), op.mouse)
Example #42
0
    def modal(self, context, event):

        tag_redraw_all_view3d()

        if len(self.align_points) < 3:
            self.align_msg = "Pick at least %s more pts" % str(
                3 - len(self.align_points))
        else:
            self.align_msg = "More points optional"

        if len(self.base_points) < 3:
            self.base_msg = "Pick at last %s more pts" % str(
                3 - len(self.base_points))
        else:
            self.base_msg = "More points optional"

        if len(self.base_points) > 3 and len(self.align_points) > 3 and len(
                self.base_points) != len(self.align_points):

            if len(self.align_points) < len(self.base_points):
                self.align_msg = "Pick %s more pts to match" % str(
                    len(self.base_points) - len(self.align_points))
            else:
                self.base_msg = "Pick %s more pts to match" % str(
                    len(self.align_points) - len(self.base_points))

        if len(self.base_points) == len(
                self.align_points) and len(self.base_points) >= 3:
            self.base_msg = "Hit Enter to Align"
            self.align_msg = "Hit Enter to Align"

        if event.type == 'LEFTMOUSE' and event.value == 'PRESS':

            ray_max = 10000

            if event.mouse_x > self.area_align.x and event.mouse_x < self.area_align.x + self.area_align.width:

                for reg in self.area_align.regions:
                    if reg.type == 'WINDOW':
                        region = reg
                for spc in self.area_align.spaces:
                    if spc.type == 'VIEW_3D':
                        rv3d = spc.region_3d

                #just transform the mouse window coords into the region coords
                coord = (event.mouse_x - region.x, event.mouse_y - region.y)

                #are the cords the problem
                print('align cords: ' + str(coord))
                print(str((event.mouse_region_x, event.mouse_region_y)))

                view_vector = view3d_utils.region_2d_to_vector_3d(
                    region, rv3d, coord)
                ray_origin = view3d_utils.region_2d_to_origin_3d(
                    region, rv3d, coord)
                ray_target = ray_origin + (view_vector * ray_max)

                print('in the align object window')
                (d, (ok, hit, normal,
                     face_index)) = ray_cast_region2d(region, rv3d, coord,
                                                      self.obj_align)
                if hit:
                    print('hit! align_obj %s' % self.obj_align.name)
                    #local space of align object
                    self.align_points.append(hit)

            else:

                for reg in self.area_base.regions:
                    if reg.type == 'WINDOW':
                        region = reg
                for spc in self.area_base.spaces:
                    if spc.type == 'VIEW_3D':
                        rv3d = spc.region_3d

                coord = (event.mouse_x - region.x, event.mouse_y - region.y)
                view_vector = view3d_utils.region_2d_to_vector_3d(
                    region, rv3d, coord)
                ray_origin = view3d_utils.region_2d_to_origin_3d(
                    region, rv3d, coord)
                ray_target = ray_origin + (view_vector * ray_max)

                print('in the base object window')
                (d, (ok, hit, normal,
                     face_index)) = ray_cast_region2d(region, rv3d, coord,
                                                      self.obj_base)
                if ok:
                    print('hit! base_obj %s' % self.obj_base.name)
                    #points in local space of align object
                    self.base_points.append(
                        self.obj_align.matrix_world.inverted() *
                        self.obj_base.matrix_world * hit)

            return {'RUNNING_MODAL'}

        elif event.type == 'RIGHTMOUSE' and event.value == 'PRESS':

            if event.mouse_x > self.area_align.x and event.mouse_x < self.area_align.x + self.area_align.width:
                self.align_points.pop()
            else:
                self.base_points.pop()

            return {'RUNNING_MODAL'}

        if event.type in {'WHEELUPMOUSE', 'WHEELDOWNMOUSE'}:

            return {'PASS_THROUGH'}

        if self.modal_state == 'NAVIGATING':

            if (event.type in {
                    'MOUSEMOVE', 'MIDDLEMOUSE', 'NUMPAD_2', 'NUMPAD_4',
                    'NUMPAD_6', 'NUMPAD_8', 'NUMPAD_1', 'NUMPAD_3', 'NUMPAD_5',
                    'NUMPAD_7', 'NUMPAD_9'
            } and event.value == 'RELEASE'):

                self.modal_state = 'WAITING'
                return {'PASS_THROUGH'}

        if (event.type in {
                'MIDDLEMOUSE', 'NUMPAD_2', 'NUMPAD_4', 'NUMPAD_6', 'NUMPAD_8',
                'NUMPAD_1', 'NUMPAD_3', 'NUMPAD_5', 'NUMPAD_7', 'NUMPAD_9'
        } and event.value == 'PRESS'):

            self.modal_state = 'NAVIGATING'

            return {'PASS_THROUGH'}

        elif event.type in {'ESC'}:
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            return {'CANCELLED'}

        elif event.type == 'RET':

            if len(self.align_points) >= 3 and len(
                    self.base_points) >= 3 and len(self.align_points) == len(
                        self.base_points):
                bpy.types.SpaceView3D.draw_handler_remove(
                    self._handle, 'WINDOW')
                self.de_localize(context)
                self.align_obj(context)

                context.scene.objects.active = self.obj_align
                self.obj_align.select = True
                self.obj_base = True

                return {'FINISHED'}

        return {'RUNNING_MODAL'}
Example #43
0
    def modal(self, context, event):
        do_exit = False
        sprytile_data = context.scene.sprytile_data

        # Check that the mouse is inside the region
        region = context.region
        coord = Vector((event.mouse_region_x, event.mouse_region_y))
        out_of_region = coord.x < 0 or coord.y < 0 or coord.x > region.width or coord.y > region.height

        if sprytile_data.is_running is False:
            do_exit = True
        if event.type == 'ESC':
            do_exit = True
        if event.type == 'RIGHTMOUSE' and out_of_region:
            do_exit = True
        if context.object.mode != 'EDIT':
            do_exit = True
        if do_exit:
            self.exit_modal(context)
            return {'CANCELLED'}

        if self.no_undo and sprytile_data.is_grid_translate is False:
            # print("no undo on, grid translate off")
            self.no_undo = False

        if event.type == 'TIMER':
            view_axis = self.find_view_axis(context)
            if view_axis is not None:
                if view_axis != sprytile_data.normal_mode:
                    self.virtual_cursor.clear()
                    sprytile_data.normal_mode = view_axis
                    sprytile_data.lock_normal = False
            return {'PASS_THROUGH'}

        # Mouse in Sprytile UI, eat this event without doing anything
        if context.scene.sprytile_ui.use_mouse:
            self.set_preview_data(None, None)
            return {'RUNNING_MODAL'}

        # Mouse move triggers preview drawing
        draw_preview = sprytile_data.paint_mode in {
            'MAKE_FACE', 'FILL', 'PAINT'
        }
        if draw_preview:
            if (event.alt or context.scene.sprytile_ui.use_mouse
                ) or sprytile_data.is_snapping:
                draw_preview = False

        # Refreshing the mesh, preview needs constantly refreshed
        # mesh or bad things seem to happen. This can potentially get expensive
        if self.refresh_mesh or self.bmesh.is_valid is False or draw_preview:
            self.update_bmesh_tree(context, True)
            self.refresh_mesh = False

        # Potentially expensive, test if there is a selected mesh element
        if event.type == 'MOUSEMOVE':
            sprytile_data.has_selection = False
            for v in self.bmesh.verts:
                if v.select:
                    sprytile_data.has_selection = True
                    break

        context.area.tag_redraw()

        # If outside the region, pass through
        if out_of_region:
            # If preview data exists, clear it
            if SprytileModalTool.preview_verts is not None:
                self.set_preview_data(None, None)
            return {'PASS_THROUGH'}

        modal_return = {'PASS_THROUGH'}

        # Process keyboard events, if returned something end here
        key_return = self.handle_keys(context, event)
        if key_return is not None:
            self.set_preview_data(None, None)
            modal_return = key_return
        # Didn't process keyboard, process mouse now
        else:
            mouse_return = self.handle_mouse(context, event, draw_preview)
            if mouse_return is not None:
                modal_return = mouse_return

        # Signals tools to draw preview
        self.draw_preview = draw_preview and self.refresh_mesh is False
        # Clear preview data if not drawing preview
        if not self.draw_preview:
            SprytileModalTool.preview_verts = None
            SprytileModalTool.preview_uvs = None

        # Build the data that will be used by tool observers
        region = context.region
        rv3d = context.region_data
        coord = event.mouse_region_x, event.mouse_region_y
        no_data = self.tree is None or rv3d is None

        if no_data is False:
            # get the ray from the viewport and mouse
            ray_vector = view3d_utils.region_2d_to_vector_3d(
                region, rv3d, coord)
            ray_origin = view3d_utils.region_2d_to_origin_3d(
                region, rv3d, coord)
            self.rx_data = DataObjectDict(context=context,
                                          ray_vector=ray_vector,
                                          ray_origin=ray_origin)
        else:
            self.rx_data = None

        # Push the event data out through rx_observer for tool observers
        if self.rx_observer is not None:
            self.rx_observer.on_next(
                DataObjectDict(
                    paint_mode=sprytile_data.paint_mode,
                    event=event,
                    left_down=self.left_down,
                    build_preview=self.draw_preview,
                ))

        return modal_return
Example #44
0
    def cursor_snap(self, context, event):
        if self.tree is None or context.scene.sprytile_ui.use_mouse is True:
            return

        # get the context arguments
        scene = context.scene
        region = context.region
        rv3d = context.region_data
        coord = event.mouse_region_x, event.mouse_region_y

        # get the ray from the viewport and mouse
        ray_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
        ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)

        up_vector, right_vector, plane_normal = sprytile_utils.get_current_grid_vectors(
            scene)

        if event.type in self.is_keyboard_list and event.shift and event.value == 'PRESS':
            if scene.sprytile_data.cursor_snap == 'GRID':
                scene.sprytile_data.cursor_snap = 'VERTEX'
            else:
                scene.sprytile_data.cursor_snap = 'GRID'

        # Snap cursor, depending on setting
        if scene.sprytile_data.cursor_snap == 'GRID':
            location = intersect_line_plane(ray_origin,
                                            ray_origin + ray_vector,
                                            scene.cursor_location,
                                            plane_normal)
            if location is None:
                return
            world_pixels = scene.sprytile_data.world_pixels
            target_grid = sprytile_utils.get_grid(
                context, context.object.sprytile_gridid)
            grid_x = target_grid.grid[0]
            grid_y = target_grid.grid[1]

            grid_position, x_vector, y_vector = sprytile_utils.get_grid_pos(
                location, scene.cursor_location, right_vector.copy(),
                up_vector.copy(), world_pixels, grid_x, grid_y)
            scene.cursor_location = grid_position

        elif scene.sprytile_data.cursor_snap == 'VERTEX':
            location, normal, face_index, distance = self.raycast_object(
                context.object, ray_origin, ray_vector)
            if location is None:
                return
            # Location in world space, convert to object space
            matrix = context.object.matrix_world.copy()
            matrix_inv = matrix.inverted()
            location, normal, face_index, dist = self.tree.find_nearest(
                matrix_inv * location)
            if location is None:
                return

            # Found the nearest face, go to BMesh to find the nearest vertex
            if self.bmesh is None:
                self.refresh_mesh = True
                return
            if face_index >= len(self.bmesh.faces) or face_index < 0:
                return
            face = self.bmesh.faces[face_index]
            closest_vtx = -1
            closest_dist = float('inf')
            # positions are in object space
            for vtx_idx, vertex in enumerate(face.verts):
                test_dist = (location - vertex.co).magnitude
                if test_dist < closest_dist:
                    closest_vtx = vtx_idx
                    closest_dist = test_dist
            # convert back to world space
            if closest_vtx != -1:
                scene.cursor_location = matrix * face.verts[closest_vtx].co
Example #45
0
    def find_face_tile(self, context, event):
        if self.tree is None or context.scene.sprytile_ui.use_mouse is True:
            return

        # get the context arguments
        region = context.region
        rv3d = context.region_data
        coord = event.mouse_region_x, event.mouse_region_y

        # get the ray from the viewport and mouse
        ray_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
        ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)

        location, normal, face_index, distance = self.raycast_object(
            context.object, ray_origin, ray_vector)
        if location is None:
            return

        face = self.bmesh.faces[face_index]

        grid_id, tile_packed_id, width, height, origin_id = self.get_face_tiledata(
            face)
        if None in {grid_id, tile_packed_id}:
            return

        tilegrid = sprytile_utils.get_grid(context, grid_id)
        if tilegrid is None:
            return

        texture = sprytile_utils.get_grid_texture(context.object, tilegrid)
        if texture is None:
            return

        paint_setting_layer = self.bmesh.faces.layers.int.get('paint_settings')
        if paint_setting_layer is not None:
            paint_setting = face[paint_setting_layer]
            sprytile_utils.from_paint_settings(context.scene.sprytile_data,
                                               paint_setting)

        row_size = math.ceil(texture.size[0] / tilegrid.grid[0])
        tile_y = math.floor(tile_packed_id / row_size)
        tile_x = tile_packed_id % row_size
        if event.ctrl:
            width = 1
            height = 1
        elif origin_id > -1:
            origin_y = math.floor(origin_id / row_size)
            origin_x = origin_id % row_size
            tile_x = min(origin_x, tile_x)
            tile_y = min(origin_y, tile_y)

        if width == 0:
            width = 1
        if height == 0:
            height = 1

        context.object.sprytile_gridid = grid_id
        tilegrid.tile_selection[0] = tile_x
        tilegrid.tile_selection[1] = tile_y
        tilegrid.tile_selection[2] = width
        tilegrid.tile_selection[3] = height

        bpy.ops.sprytile.build_grid_list()
Example #46
0
def raycast(context, event, diff):
    controller = getLightController()
    #####
    """Run this function on left mouse, execute the ray cast"""
    # get the context arguments
    scene = context.scene
    region = context.region
    rv3d = context.region_data
    coord = event.mouse_region_x, event.mouse_region_y

    # get the ray from the viewport and mouse
    view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
    ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
    
    ray_target = ray_origin + view_vector
    
    def visible_objects_and_duplis():
        """Loop over (object, matrix) pairs (mesh only)"""

        for obj in context.visible_objects:
            if isFamily(obj):
                continue
            
            if obj.type == 'MESH':
                yield (obj, obj.matrix_world.copy())

            if obj.dupli_type != 'NONE':
                obj.dupli_list_create(scene)
                for dob in obj.dupli_list:
                    obj_dupli = dob.object
                    if obj_dupli.type == 'MESH':
                        yield (obj_dupli, dob.matrix.copy())

            obj.dupli_list_clear()

    def obj_ray_cast(obj, matrix):
        """Wrapper for ray casting that moves the ray into object space"""

        # get the ray relative to the object
        matrix_inv = matrix.inverted()
        ray_origin_obj = matrix_inv * ray_origin
        ray_target_obj = matrix_inv * ray_target
        ray_direction_obj = ray_target_obj - ray_origin_obj

        # cast the ray
        success, location, normal, face_index = obj.ray_cast(ray_origin_obj, ray_direction_obj)

        if success:
            return location, normal, face_index
        else:
            return None, None, None
    
    # cast rays and find the closest object
    best_length_squared = -1.0
    best_obj = None
    normal = None
    location = None

    for obj, matrix in visible_objects_and_duplis():
        if obj.type == 'MESH':
            hit, hit_normal, face_index = obj_ray_cast(obj, matrix)
            if hit is not None:
                hit_world = matrix * hit
                length_squared = (hit_world - ray_origin).length_squared
                if best_obj is None or length_squared < best_length_squared:
                    best_length_squared = length_squared
                    best_obj = obj
                    normal = hit_normal # local space
                    location = hit_world
                    

    if best_obj is None:
        return {'RUNNING_MODAL'}
    
    # convert normal from local space to global
    matrix = best_obj.matrix_world
    matrix_new = matrix.to_3x3().inverted().transposed()
    normal = matrix_new * normal
    normal.normalize()
    
    #####
    profile = findLightGrp(controller).parent
    handle = [ob for ob in profile.children if ob.name.startswith('BLS_HANDLE')][0]
    lightmesh = getLightMesh()
    position = intersect_line_sphere(
        location - handle.location,
        (normal if diff else view_vector.reflect(normal)) + location - handle.location,
        Vector((0,0,0)),
        lightmesh.location.x,
        False,
        )[0]
    
    
    if not position:
        return {'RUNNING_MODAL'}
   
    # ctrl x
    x,y,z = position
    ctrl_x = (degrees(atan2(-x, y)) % 360) * (4/360) -2 +0.015
    
    # ctrl y
    deg = copysign(degrees(Vector.angle(Vector((x,y,z)), Vector((x,y,0)))), z)
    ctrl_y = deg / 90
    
    controller.location.x = ctrl_x
    controller.location.y = ctrl_y
 def Point2D_to_Direction(self, xy: Point2D):
     if xy is None: return None
     return Direction(
         region_2d_to_vector_3d(self.actions.region, self.actions.r3d, xy))
Example #48
0
    def modal(self, context, event):
        if context.area is None:
            self.exit(context)
            return {'CANCELLED'}

        if not sprytile_utils.get_current_tool(context).startswith("sprytile"):
            self.exit(context)
            return {'CANCELLED'}

        if context.mode != 'EDIT_MESH':
            self.exit(context)
            return {'CANCELLED'}
        elif not VIEW3D_OP_SprytileGui.is_running:
            VIEW3D_OP_SprytileGui.is_running = True

        # Check that the mouse is inside the region
        region = context.region
        coord = Vector((event.mouse_region_x, event.mouse_region_y))
        VIEW3D_OP_SprytileGui.out_of_region = coord.x < 0 or coord.y < 0 or coord.x > region.width or coord.y > region.height

        if event.type == 'TIMER':
            self.update_view_axis(context)

            if self.label_counter > 0:
                self.label_counter -= 1

        # Check if current_grid is different from current sprytile grid
        if context.object.sprytile_gridid != VIEW3D_OP_SprytileGui.current_grid:
            # Setup the offscreen texture for the new grid
            setup_off_return = VIEW3D_OP_SprytileGui.setup_offscreen(
                self, context)
            if setup_off_return is not None:
                return setup_off_return
            # Skip redrawing on this frame
            return {'PASS_THROUGH'}

        ret_val = self.handle_ui(context, event)
        VIEW3D_OP_SprytileGui.tile_ui_active = ret_val == 'RUNNING_MODAL'

        # Build the data that will be used by tool observers
        rv3d = context.region_data
        coord = event.mouse_region_x, event.mouse_region_y
        no_data = rv3d is None

        if no_data is False:
            # get the ray from the viewport and mouse
            ray_vector = view3d_utils.region_2d_to_vector_3d(
                region, rv3d, coord)
            ray_origin = view3d_utils.region_2d_to_origin_3d(
                region, rv3d, coord)

            mode = bpy.context.scene.sprytile_data.paint_mode
            if VIEW3D_OP_SprytileGui.build_previews[mode]:
                sprytile_modal.VIEW3D_OP_SprytileModalTool.verify_bmesh_layers(
                    bmesh.from_edit_mesh(context.object.data))
                VIEW3D_OP_SprytileGui.build_previews[mode].build_preview(
                    context, context.scene, ray_origin, ray_vector)
            else:
                sprytile_preview.set_preview_data(None, None)

        context.scene.sprytile_ui.is_dirty = False
        context.area.tag_redraw()
        return {ret_val}
    def click_add_point(self, context, x, y):
        '''
        x,y = event.mouse_region_x, event.mouse_region_y

        this will add a point into the bezier curve or
        close the curve into a cyclic curve
        '''
        region = context.region
        rv3d = context.region_data
        coord = x, y
        view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
        ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
        ray_target = ray_origin + (view_vector * 1000)

        hit = False
        # ray cast on the any object
        if self.snap_type == 'SCENE':
            mx = Matrix.Identity(4)  # loc is given in world loc...no need to multiply by obj matrix
            imx = Matrix.Identity(4)
            no_mx = Matrix.Identity(3)
            if bversion() < '002.077.000':
                hit, obj, omx, loc, no = context.scene.ray_cast(ray_origin, ray_target)  #changed in 2.77
            else:
                hit, loc, no, ind, obj, omx = context.scene.ray_cast(ray_origin, view_vector)
                iomx = omx.inverted()
                no_mx = iomx.to_3x3().transposed()
            # if not hit:
            #     # cast the ray into a plane perpendicular to the view dir, at the last bez point of the curve
            #
            #     view_direction = rv3d.view_rotation * Vector((0,0,-1))
            #
            #     if len(self.b_pts):
            #         plane_pt = self.b_pts[-1].location
            #     else:
            #         plane_pt = context.scene.cursor_location
            #     loc = intersect_line_plane(ray_origin, ray_target,plane_pt, view_direction)
            #     hit = True
        # ray cast on self.snap_ob
        elif self.snap_type == 'OBJECT':
            mx = self.snap_ob.matrix_world
            imx = mx.inverted()
            no_mx = imx.to_3x3().transposed()

            if bversion() < '002.077.000':
                loc, no, face_ind = self.snap_ob.ray_cast(imx * ray_origin, imx * ray_target)[0 if bversion() < '002.077.000' else 1:]
            else:
                hit, loc, no, face_ind = self.snap_ob.ray_cast(imx * ray_origin, imx * ray_target - imx*ray_origin)

            if face_ind != -1:
                hit = True

        # no object was hit
        if not hit:
            self.selected = -1
            return False

        # select existing point
        if self.hovered[0] == 'POINT':
            self.selected = self.hovered[1]
            return False
        # add new point
        elif self.hovered[0] == None:
            new_point = D3Point(location=mx * loc, surface_normal=no_mx * no, view_direction=view_vector, source_object=obj if self.snap_type == "SCENE" else self.snap_ob)
            self.b_pts.append(new_point)
            new_point.label = self.getLabel(len(self.b_pts) - 1)
            self.hovered = ['POINT', len(self.b_pts) - 1]
            return True
Example #50
0
 def getLoc(self, context, event):
     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)
     return region_2d_to_location_3d(region, rv3d, coord, vec)
def mft_pick_and_clone(self, context, event, ray_max=10000.0):
    """Run this function on left mouse, execute the ray cast"""
    # get the context arguments
    scene = context.scene
    region = context.region
    rv3d = context.region_data
    coord = event.mouse_region_x, event.mouse_region_y

    def mft_obj_ray_cast(obj, matrix, view_vector, ray_origin):
        """Wrapper for ray casting that moves the ray into object space"""

        ray_target = ray_origin + (view_vector * ray_max)

        # get the ray relative to the object
        matrix_inv = matrix.inverted()
        ray_origin_obj = matrix_inv * ray_origin
        ray_target_obj = matrix_inv * ray_target

        # cast the ray
        hit_result, hit, normal, face_index = obj.ray_cast(
            ray_origin_obj, ray_target_obj)

        if hit_result:
            hit_world = matrix * hit

            length_squared = (hit_world - ray_origin).length_squared

            if face_index != -1:
                #normal_world = (matrix.to_quaternion() * normal).normalized()

                normal_world = (matrix.to_quaternion() * normal).to_4d()
                normal_world.w = 0
                normal_world = (
                    matrix.to_quaternion() *
                    (matrix_inv * normal_world).to_3d()).normalized()

                return normal_world, hit_world, length_squared

        return None, None, None

    # cast rays and find the closest object
    best_length_squared = ray_max * ray_max
    best_obj, best_obj_nor, best_obj_pos = None, None, None
    best_obj_rand, best_obj_nor_rand, best_obj_pos_rand = None, None, None
    best_obj_hit = None

    mifthCloneTools = bpy.context.scene.mifthCloneTools
    thePressure = max(1.0 - mifthCloneTools.drawPressure,
                      self.tabletPressure)  # The pressure of a pen!

    for obj, matrix in self.dupliList:
        # get the ray from the viewport and mouse
        view_vector_mouse = view3d_utils.region_2d_to_vector_3d(
            region, rv3d, coord)
        ray_origin_mouse = view3d_utils.region_2d_to_origin_3d(
            region, rv3d, coord)

        # Do RayCast! t1,t2,t3,t4 - temp values
        t1, t2, t3 = mft_obj_ray_cast(obj, matrix, view_vector_mouse,
                                      ray_origin_mouse)
        if t1 is not None and t3 < best_length_squared:
            best_obj = obj
            best_obj_nor, best_obj_pos, best_length_squared = t1, t2, t3
            best_obj_hit = t2

        # Check for stroke length
        if best_obj is not None:
            previousHit = None
            if len(self.currentStrokeList) > 0:
                previousHit = self.currentStrokeList[-1]  # get Last Element

            # Check for stroke
            strokeLength = mifthCloneTools.drawStrokeLength
            if mifthCloneTools.drawPressureScale is True and mifthCloneTools.drawPressureRelativeStroke is True and self.tabletPressure < 1.0 and mifthCloneTools.drawPressure > 0.0:
                strokeLength *= thePressure
            if previousHit is not None and (
                    best_obj_pos - previousHit.hitPoint).length < strokeLength:
                best_obj = None  # Don't do cloning

    # random scatter things
    if mifthCloneTools.drawRandomStrokeScatter > 0.0 and best_obj is not None and t1 is not None:
        # Random Vec
        randX = random.uniform(
            -1.0, 1.0
        ) * mifthCloneTools.drawRandomStrokeScatter  # 3.0 is random addition
        randY = random.uniform(
            -1.0, 1.0
        ) * mifthCloneTools.drawRandomStrokeScatter  # 3.0 is random addition
        randZ = random.uniform(-1.0,
                               1.0) * mifthCloneTools.drawRandomStrokeScatter

        if mifthCloneTools.drawPressureScatter is True and self.tabletPressure < 1.0 and mifthCloneTools.drawPressure > 0.0:
            randX *= thePressure
            randY *= thePressure
            randZ *= thePressure

        randVect = Vector((randX, randY, randZ))

        for obj, matrix in self.dupliList:
            ray_origin_rand = best_obj_pos + randVect
            ray_origin_rand_2d = view3d_utils.location_3d_to_region_2d(
                region, rv3d, ray_origin_rand)

            view_vector_rand = view3d_utils.region_2d_to_vector_3d(
                region, rv3d, (ray_origin_rand_2d.x, ray_origin_rand_2d.y))

            t1, t2, t3 = mft_obj_ray_cast(obj, matrix, view_vector_rand,
                                          ray_origin_rand)
            # 3.0 is random addition
            if t1 is not None and (
                    t2 - best_obj_hit
            ).length <= mifthCloneTools.drawRandomStrokeScatter * 3.0:
                best_obj_nor, best_obj_pos = t1, t2

    # now we have the object under the mouse cursor,
    if best_obj is not None:
        objToClone = bpy.data.objects.get(random.choice(drawForClonesObj))
        best_obj_nor = best_obj_nor.normalized()

        # clone object
        newDup = bpy.data.objects.new(objToClone.name, objToClone.data)

        # copy draw type
        newDup.draw_type = objToClone.draw_type
        newDup.show_wire = objToClone.show_wire

        # copy transformation
        newDup.matrix_world = objToClone.matrix_world
        newDup.location = best_obj_pos
        newDup.scale = objToClone.scale
        newDup.rotation_euler = objToClone.rotation_euler
        # bpy.ops.object.rotation_clear()

        context.scene.objects.link(newDup)
        newDup.select = True
        context.scene.objects.active = newDup

        # Rotation To Normal
        if mifthCloneTools.drawClonesNormalRotate is True:
            # rotate To Normal
            newDupZAxis = get_obj_axis(newDup, 'Z')
            angleRotate = newDupZAxis.angle(best_obj_nor)
            rotateAxis = newDupZAxis.cross(best_obj_nor).normalized()

            bpy.ops.transform.rotate(value=angleRotate,
                                     axis=((rotateAxis.x, rotateAxis.y,
                                            rotateAxis.z)),
                                     proportional='DISABLED')

        # Change Axis
        if mifthCloneTools.drawClonesAxis == 'Y':
            bpy.ops.transform.rotate(value=math.radians(90),
                                     axis=get_obj_axis(newDup, 'X'),
                                     proportional='DISABLED')
        elif mifthCloneTools.drawClonesAxis == '-Y':
            bpy.ops.transform.rotate(value=math.radians(-90),
                                     axis=get_obj_axis(newDup, 'X'),
                                     proportional='DISABLED')
            bpy.ops.transform.rotate(value=math.radians(180),
                                     axis=get_obj_axis(newDup, 'Y'),
                                     proportional='DISABLED')
        elif mifthCloneTools.drawClonesAxis == '-Z':
            bpy.ops.transform.rotate(value=math.radians(180),
                                     axis=get_obj_axis(newDup, 'X'),
                                     proportional='DISABLED')
        elif mifthCloneTools.drawClonesAxis == 'X':
            bpy.ops.transform.rotate(value=math.radians(-90),
                                     axis=get_obj_axis(newDup, 'Y'),
                                     proportional='DISABLED')
        elif mifthCloneTools.drawClonesAxis == '-X':
            bpy.ops.transform.rotate(value=math.radians(90),
                                     axis=get_obj_axis(newDup, 'Y'),
                                     proportional='DISABLED')

        # Other rotate
        if mifthCloneTools.drawClonesRadialRotate is True or mifthCloneTools.drawClonesDirectionRotate is True:

            # Ratate to Direction
            newDirRotLookAtt = None
            if mifthCloneTools.drawClonesDirectionRotate is True:
                previousHit = None
                if len(self.currentStrokeList) > 0:
                    previousHit = self.currentStrokeList[
                        -1]  # get Last Element
                else:
                    if len(self.allStrokesList) > 0:
                        previousHit = self.allStrokesList[-1][
                            -1]  # get Last Element of previous Stroke

                if previousHit is not None:
                    newDirRotLookAtt = (best_obj_hit -
                                        previousHit.hitPoint).normalized()
            else:
                newDirRotLookAtt = Vector((0.0, 0.0, 1.0))

            # Get the axis to rotate
            if newDirRotLookAtt is not None:
                tempYCross = best_obj_nor.cross(newDirRotLookAtt).normalized()
                if tempYCross != Vector((0.0, 0.0, 0.0)):
                    tempYCross.negate()
                    radialVec = best_obj_nor.cross(tempYCross).normalized()

                    axisPickTemp = 'Y'
                    if mifthCloneTools.drawClonesAxis == 'Y':
                        axisPickTemp = 'Z'
                    if mifthCloneTools.drawClonesAxis == '-Y':
                        axisPickTemp = 'Z'
                    if mifthCloneTools.drawClonesAxis == '-Z':
                        axisPickTemp = 'Y'
                    if mifthCloneTools.drawClonesAxis == 'X':
                        axisPickTemp = 'Z'
                    if mifthCloneTools.drawClonesAxis == '-X':
                        axisPickTemp = 'Z'

                    tempY = get_obj_axis(newDup, axisPickTemp)
                    xyAngleRotate = Vector(radialVec).angle(tempY)

                    if tempYCross.angle(tempY) > math.radians(90.0):
                        xyAngleRotate = -xyAngleRotate

                    bpy.ops.transform.rotate(value=xyAngleRotate,
                                             axis=best_obj_nor,
                                             proportional='DISABLED')

                # newDupMatrix2 = newDup.matrix_world
                # newDupZAxisTuple2 = (
                # newDupMatrix2[0][2], newDupMatrix2[1][2], newDupMatrix2[2][2])
                # newDupZAxis2 = (
                # Vector(newDupZAxisTuple2)).normalized()
                # newDirRotVec2 = (newDirRotLookAtt.cross(best_obj_nor)).normalized().cross(
                # best_obj_nor).normalized()
                # newDirRotAngle = newDirRotVec2.angle(newDupZAxis2)
                # fixDirRotAngle = newDirRotLookAtt.cross(
                # best_obj_nor).angle(newDupZAxis2)
                # if fixDirRotAngle < math.radians(90.0):
                # newDirRotAngle = - \
                # newDirRotAngle  # As we do it in negative axis
                # Main rotation
                # bpy.ops.transform.rotate(value=newDirRotAngle, axis=(
                #(best_obj_nor.x, best_obj_nor.y, best_obj_nor.z)), proportional='DISABLED')
        # set PreviousClone position
        # self.prevClonePos = best_obj_hit
        # Random rotation along Picked Normal
        if mifthCloneTools.randNormalRotateClone > 0.0:
            randNorAngle = random.uniform(
                math.radians(-mifthCloneTools.randNormalRotateClone),
                math.radians(mifthCloneTools.randNormalRotateClone))
            randNorAxis = (best_obj_nor.x, best_obj_nor.y, best_obj_nor.z)
            if mifthCloneTools.drawClonesRadialRotate is False and mifthCloneTools.drawClonesNormalRotate is False:
                randNorAxis = (0.0, 0.0, 1.0)
            bpy.ops.transform.rotate(value=randNorAngle,
                                     axis=(randNorAxis),
                                     proportional='DISABLED')

        # Random rotation along Picked Normal
        if mifthCloneTools.randDirectionRotateClone > 0.0:
            randDirX, randDirY, randDirZ = random.uniform(
                0.0, 1.0), random.uniform(0.0, 1.0), random.uniform(0.0, 1.0)
            randDirVec = (Vector((randDirX, randDirY, randDirZ))).normalized()
            randDirAngle = random.uniform(
                math.radians(-mifthCloneTools.randDirectionRotateClone),
                math.radians(mifthCloneTools.randDirectionRotateClone))
            bpy.ops.transform.rotate(value=randDirAngle,
                                     axis=(randDirVec),
                                     proportional='DISABLED')

        # change Size
        if mifthCloneTools.drawPressure > 0.0 or mifthCloneTools.randScaleClone > 0.0:
            newSize = newDup.scale
            if self.tabletPressure < 1.0 and mifthCloneTools.drawPressure > 0.0 and mifthCloneTools.drawPressureScale is True:
                newSize *= thePressure

            if mifthCloneTools.randScaleClone > 0.0:
                randScaleClone = 1.0 - \
                    (random.uniform(0.0, 0.99) *
                     mifthCloneTools.randScaleClone)
                newSize *= randScaleClone

        # Add this point with all its stuff
        self.currentStrokeList.append(
            MTFDCPoint(newDup, objToClone, best_obj_hit, best_obj_nor))

        # do optimization for a stroke or not
        if mifthCloneTools.drawClonesOptimize is False:
            copy_settings_clones(newDup, objToClone)

        newDup.select = False  # Clear Selection
def get_ray_hit(context, x, y):
    current_obj = context.object
    current_obj_matrix = current_obj.matrix_world
    current_obj_matrix_inv = current_obj_matrix.inverted()
    scene = context.scene
    region = context.region
    rv3d = context.region_data
    coord = x, y

    view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
    ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)

    ray_target = ray_origin + view_vector

    def visible_objects_and_duplis():
        """Loop over (object, matrix) pairs (mesh only)"""

        depsgraph = context.evaluated_depsgraph_get()
        for dup in depsgraph.object_instances:

            if dup.is_instance:  # Real dupli instance
                obj = dup.instance_object
                yield (obj)
            else:  # Usual object
                obj = dup.object
                yield (obj)

    def obj_ray_cast(obj):
        matrix = obj.matrix_world
        matrix_inv = matrix.inverted()
        ray_origin_obj = matrix_inv @ ray_origin
        ray_target_obj = matrix_inv @ ray_target
        ray_direction_obj = ray_target_obj - ray_origin_obj

        success, location, normal, face_index = obj.ray_cast(
            ray_origin_obj, ray_direction_obj)

        if success:
            return location, normal, face_index, matrix, matrix_inv
        else:
            return None, None, None, None, None

    best_length_squared = float("inf")
    best_obj = None
    best_normal = None
    best_face_index = -1
    best_location = None

    for obj in visible_objects_and_duplis():
        if obj.name in [
                ob.name
                for ob in context.view_layer.objects if ob.visible_get()
        ] and obj.type == 'MESH' and obj.name != current_obj.name and len(
                obj.data.polygons) > 0:
            hit, normal, face_index, matrix, matrix_inv = obj_ray_cast(obj)
            if hit is not None:
                hit_world = matrix @ hit
                length_squared = (hit_world - ray_origin).length_squared
                if best_obj is None or length_squared < best_length_squared:
                    best_length_squared = length_squared
                    best_obj = obj
                    best_normal = normal @ matrix_inv @ current_obj_matrix

                    best_location = hit
                    best_face_index = face_index

    if best_obj is not None:  # and matrix != None:
        best_location = best_obj.matrix_world @ best_location
        best_location = current_obj_matrix_inv @ best_location

        return best_location, best_normal, best_obj, best_face_index
    else:
        return None, None, None, -1
def razor2(vertice1, vertice2, vertice3, anglecorte, anglefijo):
    oa = bpy.context.active_object
    obj = bpy.context.object
    me = obj.data
    bm = bmesh.from_edit_mesh(me)
    pi = math.pi  # constante de pi
    v1 = vertice1
    v2 = vertice2
    v3 = vertice3

    angulocorte = anglecorte
    angulofijo = anglefijo
    angulocomplementario = pi - (angulocorte + angulofijo)
    print(angulocorte)
    print("angulo corte: " + str((180 * angulocorte) / pi))
    print("angulo fijo: " + str((180 * angulofijo) / pi))
    print("angulo complementario: " + str((180 * angulocomplementario) / pi))
    #distancia entre los dos vertices

    dv2v3 = math.sqrt(
        math.fabs(
            (((((v3.co.x) - (v2.co.x))**2)) + ((((v3.co.y) - (v2.co.y))**2)) +
             ((((v3.co.z) - (v2.co.z))**2)))))

    print("distancia entre vertices opuestos v2v3: " + str(dv2v3))
    dv1v3 = math.sqrt(
        math.fabs(
            (((((v1.co.x) - (v3.co.x))**2)) + ((((v1.co.y) - (v3.co.y))**2)) +
             ((((v1.co.z) - (v3.co.z))**2)))))
    #dv1v3 = math.sqrt(math.fabs((((((v1.co.x)-(v2.co.x))**2))+((((v1.co.y)-(v2.co.y))**2))+((((v1.co.z)-(v2.co.z))**2)))))
    print("distancia entre vertices opuestos v1v3: " + str(dv1v3))
    #distancia nuevo vertice:
    # asigno la distancia del nuevo vertice colinear respecto al vertice 1

    dv1v2 = (dv1v3 * math.sin(angulocorte)) / (math.sin(angulocomplementario))

    print("distancia entre vertices v1v2: " + str(dv1v2))

    #formula para cordenadas del nuevo vertice
    u = (dv1v2 / dv2v3)

    cox = (1 - u) * (v3.co.x) + (u * v2.co.x)

    coy = (1 - u) * (v3.co.y) + (u * v2.co.y)

    coz = (1 - u) * (v3.co.z) + (u * v2.co.z)

    #creacion nuevo vertice colinear
    vnuevo = mathutils.Vector((tuple((cox, coy, coz))))

    v3 = bm.verts.new((cox, coy, coz))

    veje = v1.co
    vdestino = v3.co

    listado = [v3]
    bmesh.ops.dissolve_verts(bm, verts=listado)
    for area in bpy.context.screen.areas:
        if area.type == 'VIEW_3D':
            override = bpy.context.copy()
            viewport = area.regions[4]

            #coo in 3d space
            co_3d = oa.matrix_world * vdestino
            #coo in the 3d view area (2d)
            co_2d = view3d_utils.location_3d_to_region_2d(
                viewport, area.spaces[0].region_3d, co_3d)

            try:
                v4 = view3d_utils.region_2d_to_vector_3d(
                    viewport, area.spaces[0].region_3d, co_2d)
                v4 = v4 + vdestino

                normal = mathutils.geometry.normal(veje, vdestino, v4)

                #print("thenormal " + str(normal))

                plane_no = normal
                plane_co = veje
                #print('cordenadas plano:\n', plane_no, '\n', plane_co)
                dist = 0.0001

                # hidden geometry will not be affected.
                visible_geom = [
                    g for g in bm.faces[:] + bm.verts[:] + bm.edges[:]
                    if not g.hide
                ]

                newdata = bmesh.ops.bisect_plane(bm,
                                                 geom=visible_geom,
                                                 dist=dist,
                                                 plane_co=plane_co,
                                                 plane_no=plane_no,
                                                 use_snap_center=False,
                                                 clear_outer=False,
                                                 clear_inner=False)
            except:
                print("normal zero")
    #cortador(v2,v3)
    bmesh.update_edit_mesh(me, True)
Example #54
0
    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 pick_object(context, event, pick_objects, ray_max=10000.0):
    """Run this function on left mouse, execute the ray cast"""
    # get the context arguments
    scene = context.scene
    region = context.region
    rv3d = context.region_data
    coord = event.mouse_region_x, event.mouse_region_y

    # get the ray from the viewport and mouse
    view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
    ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
    ray_target = ray_origin + (view_vector * ray_max)

    scene.cursor.location = ray_target

    def visible_objects_and_duplis():
        """Loop over (object, matrix) pairs (mesh only)"""

        for obj in context.visible_objects:  # scene.objects:
            if obj.hide:
                continue

            if obj.type == 'MESH':
                yield (None, obj, obj.matrix_world.copy())

            if obj.instance_type != 'NONE':
                print("DupliInst: %r" % obj)
                obj.dupli_list_create(scene)
                # matrix = obj.matrix_world.copy()
                for dob in obj.dupli_list:
                    obj_dupli = dob.object
                    if not obj_dupli.hide:
                        # print("Dupli: %r" % obj_dupli)
                        if obj_dupli.type == 'MESH':
                            yield (obj, obj_dupli, dob.matrix.copy())

                obj.dupli_list_clear()

    def obj_ray_cast(obj, matrix):
        """Wrapper for ray casting that moves the ray into object space"""

        # get the ray relative to the object
        matrix_inv = matrix.inverted()
        ray_origin_obj = matrix_inv * ray_origin
        ray_target_obj = matrix_inv * ray_target

        mesh = obj.data
        if not mesh.polygons:
            return None, None, None

        hit, normal, face_index = obj.ray_cast(ray_origin_obj, ray_target_obj)

        if face_index == -1:
            hit, normal, face_index = obj.ray_cast(ray_target_obj,
                                                   ray_origin_obj)

        if face_index != -1:
            return hit, normal, face_index
        else:
            return None, None, None

    # cast rays and find the closest object
    best_length_squared = ray_max * ray_max
    best_obj = None
    best_obj_parent = None

    for obj_parent, obj, matrix in visible_objects_and_duplis():
        if obj.type == 'MESH':
            hit, normal, face_index = obj_ray_cast(obj, matrix)
            if hit is not None:
                length_squared = (hit - ray_origin).length_squared
                if length_squared < best_length_squared:
                    best_length_squared = length_squared
                    best_obj = obj
                    best_obj_parent = obj_parent

    # now we have the object under the mouse cursor,
    # we could do lots of stuff but for the example just select.
    if best_obj is not None:
        pick_objects.append((best_obj, best_obj.hide, best_obj.hide_render))
        best_obj.hide = True
        best_obj.hide_render = True

        #if best_obj_parent:
        #    best_obj_parent.update_tag(refresh={'OBJECT'})
        #scene.update()
        return True
    else:
        print("found none")
        return False
Example #56
0
    def grab_mouse_move(self, context, x, y, normal=False):
        region = context.region
        rv3d = context.region_data
        coord = x, y
        view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
        ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
        ray_target = ray_origin + (view_vector * 1000)

        hit = False
        if self.snap_type == 'SCENE':

            if bversion() < '002.077.000':
                res, obj, mx, loc, no = context.scene.ray_cast(
                    ray_origin, ray_target)
            else:
                res, loc, no, ind, obj, mx = context.scene.ray_cast(
                    ray_origin, view_vector)
            if res:
                hit = True

        elif self.snap_type == 'OBJECT':
            mx = self.snap_ob.matrix_world
            imx = mx.inverted()

            if bversion() < '002.077.000':
                loc, no, face_ind = self.snap_ob.ray_cast(
                    imx * ray_origin, imx * ray_target)
                if face_ind != -1:
                    hit = True
            else:
                ok, loc, no, face_ind = self.snap_ob.ray_cast(
                    imx * ray_origin, imx * ray_target - imx * ray_origin)
                if ok:
                    hit = True

        if not hit:
            self.grab_cancel()

        else:
            world_location = mx * loc
            imx = mx.inverted()

            #this will be the object Z axis
            world_normal = imx.transposed().to_3x3() * no

            if normal:
                ob_Z = world_normal
                ob_Z.normalize()

                view_Y = rv3d.view_rotation * Vector((0, 1, 0))
                if self.bracket_obj.name.startswith(
                        "U") or self.bracket_obj.name.startswith("u"):
                    view_Y *= -1

                #project view y into the tangetnt plane of teh surface
                ob_Y = view_Y - view_Y.dot(ob_Z) * ob_Z
                ob_Y.normalize()

                ob_X = ob_Y.cross(ob_Z)
                ob_X.normalize()

                #rotation matrix from principal axes
                T = Matrix.Identity(3)  #make the columns of matrix X, Y, Z
                T[0][0], T[0][1], T[0][2] = ob_X[0], ob_Y[0], ob_Z[0]
                T[1][0], T[1][1], T[1][2] = ob_X[1], ob_Y[1], ob_Z[1]
                T[2][0], T[2][1], T[2][2] = ob_X[2], ob_Y[2], ob_Z[2]

                rot = T.to_4x4()

            else:
                rot = self.bracket_obj.matrix_world.to_3x3().to_4x4()

            loc = Matrix.Translation(world_location)
            self.bracket_obj.matrix_world = loc * rot
Example #57
0
def pick_object(region, rv3d, x, y, near, far, objects):
    '''
    Selects an object underneath given screen coordinates

    Parameters:
        region (bpy.types.Region): Section of the UI in which to do picking
        rv3d (bpy.types.RegionView3D): 3D view region data
        near (float): Near clipping plane
        far (float): Far clipping plane
        objects (seq<bpy.types.Object>): Sequence of pickable objects

    Returns:
        (obj, location, normal, index): Reference to picked object and raycast
        hit information; otherwise None
            obj (bpy.types.Object): Nearest object in path of the ray
            location (mathutils.Vector): Object space location of ray-face intersection
            normal (mathutils.Vector): Normal vector of intersected face
            index (int): Index of intersected face
    '''
    blender_version = bpy.app.version

    # Determine ray extents.
    coord = mathutils.Vector((x, y))
    ray_dir = region_2d_to_vector_3d(region, rv3d, coord)
    ray_start = region_2d_to_origin_3d(region, rv3d, coord) + ray_dir * near
    ray_end = ray_start + ray_dir * (far - near)

    # If the view is an orthographic projection, the ray's end may exist in
    # front of the mesh object. Therefore, it is necessary to move the ray's
    # end a sufficient distance parallel to the ray's direction to ensure that
    # the ray potentially intersects the mesh object.
    if rv3d.view_perspective == 'ORTHO':
        ray_end += sys.maxsize * ray_dir

    # Pick a mesh object underneath given screen coordinates.
    result = None
    min_dist_squared = sys.float_info.max
    for obj in objects:

        # Skip objects that cannot participate in ray casting.
        if (not obj.type == 'MESH' or obj.mode == 'EDIT'
                or not obj.data.polygons):
            continue

        # Cast ray in object space.
        inverse_model_matrix = obj.matrix_world.inverted()
        hit = obj.ray_cast(inverse_model_matrix @ ray_start,
                           inverse_model_matrix @ ray_end)
        location, normal, index = hit[1:]

        # Compare intersection distances.
        if index != -1:
            dist_squared = (obj.matrix_world @ location -
                            ray_start).length_squared

            # Record closer of the two hits.
            if dist_squared < min_dist_squared:
                min_dist_squared = dist_squared
                result = (obj, location, normal, index)

    return result
Example #58
0
    def modal(self, context, event):
        np_print('05_BglPlane_START', ';', 'NP020RM.flag = ', NP020RM.flag)
        context.area.tag_redraw()
        flag = NP020RM.flag
        mode = NP020RM.mode
        plane = NP020RM.plane
        helper = NP020RM.helper
        centerloc = NP020RM.centerloc

        if event.type == 'MOUSEMOVE':
            self.co2d = ((event.mouse_region_x, event.mouse_region_y))
            np_print('05_BglPlane_mousemove', ';', 'NP020RM.flag = ',
                     NP020RM.flag, 'NP020RM.mode = ', NP020RM.mode,
                     'NP020RM.plane = ', NP020RM.plane)

        elif event.type in ('LEFTMOUSE', 'RIGHTMOUSE', 'RET', 'NUMPAD_ENTER'):
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            region = context.region
            rv3d = context.region_data
            co2d = self.co2d
            view_vector = view3d_utils.region_2d_to_vector_3d(
                region, rv3d, co2d)
            viewloc = view3d_utils.region_2d_to_origin_3d(region, rv3d, co2d)
            away = (centerloc - viewloc).length
            pointloc = viewloc + view_vector * away  # to place the helper on centerloc to be in the vicinity of projection plane
            helper.location = pointloc
            helper.hide = False
            NP020RM.qdef = copy.deepcopy(NP020RM.q)
            NP020RM.ndef = copy.deepcopy(NP020RM.n)
            NP020RM.plane = 'SET'
            NP020RM.flag = 'RUNTRANSSTART'
            np_print('05_BglPlane_lmb_FINISHED', ';', 'NP020RM.flag = ',
                     NP020RM.flag, 'NP020RM.mode = ', NP020RM.mode,
                     'NP020RM.plane = ', NP020RM.plane)
            return {'FINISHED'}

        elif event.ctrl and event.value == 'PRESS':
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            if mode == 'FREE':
                NP020RM.mode = 'X'
            elif mode == 'X':
                NP020RM.mode = 'Y'
            elif mode == 'Y':
                NP020RM.mode = 'Z'
            else:
                NP020RM.mode = 'FREE'
            np_print('05_BglPlane_rmb_FINISHED', ';', 'NP020RM.flag = ',
                     NP020RM.flag, 'NP020RM.mode = ', NP020RM.mode,
                     'NP020RM.plane = ', NP020RM.plane)

        elif event.type == 'ESC':
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            NP020RM.flag = 'EXIT'
            np_print('05_BglPlane_esc_FINISHED', ';', 'NP020RM.flag = ',
                     NP020RM.flag)
            return {'FINISHED'}

        elif event.type in {'MIDDLEMOUSE', 'WHEELUPMOUSE', 'WHEELDOWNMOUSE'}:
            np_print('05_BglPlane_middle_wheel_any_PASS_THROUGH')
            return {'PASS_THROUGH'}

        np_print('05_BglPlane_standard_RUNNING_MODAL', ';', 'NP020RM.flag = ',
                 NP020RM.flag)
        return {'RUNNING_MODAL'}
Example #59
0
    def __stroke_apply(self, context, _):
        sc = context.scene
        objs = common.get_uv_editable_objects(context)

        for obj in objs:
            world_mat = obj.matrix_world
            bm = bmesh.from_edit_mesh(obj.data)
            uv_layer = bm.loops.layers.uv.verify()
            mco = self.current_mco

            if sc.muv_uv_sculpt_tools == 'GRAB':
                for info in self.__loop_info[obj]:
                    diff_uv = (mco - self.__initial_mco) * info["strength"]
                    l = bm.faces[info["face_idx"]].loops[info["loop_idx"]]
                    l[uv_layer].uv = info["initial_uv"] + diff_uv / 100.0

            elif sc.muv_uv_sculpt_tools == 'PINCH':
                _, region, space = common.get_space('VIEW_3D', 'WINDOW',
                                                    'VIEW_3D')
                loop_info = []
                for f in bm.faces:
                    if not f.select:
                        continue
                    for i, l in enumerate(f.loops):
                        loc_2d = location_3d_to_region_2d_extra(
                            region, space.region_3d,
                            compat.matmul(world_mat, l.vert.co))
                        diff = loc_2d - self.__initial_mco
                        if diff.length < sc.muv_uv_sculpt_radius:
                            info = {
                                "face_idx":
                                f.index,
                                "loop_idx":
                                i,
                                "initial_vco":
                                l.vert.co.copy(),
                                "initial_vco_2d":
                                loc_2d,
                                "initial_uv":
                                l[uv_layer].uv.copy(),
                                "strength":
                                _get_strength(diff.length,
                                              sc.muv_uv_sculpt_radius,
                                              sc.muv_uv_sculpt_strength)
                            }
                            loop_info.append(info)

                # mouse coordinate to UV coordinate
                ray_vec = view3d_utils.region_2d_to_vector_3d(
                    region, space.region_3d, mco)
                ray_vec.normalize()
                ray_orig = view3d_utils.region_2d_to_origin_3d(
                    region, space.region_3d, mco)
                ray_tgt = ray_orig + ray_vec * 1000000.0
                mwi = world_mat.inverted()
                ray_orig_obj = compat.matmul(mwi, ray_orig)
                ray_tgt_obj = compat.matmul(mwi, ray_tgt)
                ray_dir_obj = ray_tgt_obj - ray_orig_obj
                ray_dir_obj.normalize()
                tree = BVHTree.FromBMesh(bm)
                loc, _, fidx, _ = tree.ray_cast(ray_orig_obj, ray_dir_obj)
                if not loc:
                    return
                loops = [l for l in bm.faces[fidx].loops]
                uvs = [
                    Vector((l[uv_layer].uv.x, l[uv_layer].uv.y, 0.0))
                    for l in loops
                ]
                target_uv = barycentric_transform(loc, loops[0].vert.co,
                                                  loops[1].vert.co,
                                                  loops[2].vert.co, uvs[0],
                                                  uvs[1], uvs[2])
                target_uv = Vector((target_uv.x, target_uv.y))

                # move to target UV coordinate
                for info in loop_info:
                    l = bm.faces[info["face_idx"]].loops[info["loop_idx"]]
                    if sc.muv_uv_sculpt_pinch_invert:
                        diff_uv = \
                            (l[uv_layer].uv - target_uv) * info["strength"]
                    else:
                        diff_uv = \
                            (target_uv - l[uv_layer].uv) * info["strength"]
                    l[uv_layer].uv = l[uv_layer].uv + diff_uv / 10.0

            elif sc.muv_uv_sculpt_tools == 'RELAX':
                _, region, space = common.get_space('VIEW_3D', 'WINDOW',
                                                    'VIEW_3D')

                # get vertex and loop relation
                vert_db = {}
                for f in bm.faces:
                    for l in f.loops:
                        if l.vert in vert_db:
                            vert_db[l.vert]["loops"].append(l)
                        else:
                            vert_db[l.vert] = {"loops": [l]}

                # get relaxation information
                for k in vert_db.keys():
                    d = vert_db[k]
                    d["uv_sum"] = Vector((0.0, 0.0))
                    d["uv_count"] = 0

                    for l in d["loops"]:
                        ln = l.link_loop_next
                        lp = l.link_loop_prev
                        d["uv_sum"] = d["uv_sum"] + ln[uv_layer].uv
                        d["uv_sum"] = d["uv_sum"] + lp[uv_layer].uv
                        d["uv_count"] = d["uv_count"] + 2
                    d["uv_p"] = d["uv_sum"] / d["uv_count"]
                    d["uv_b"] = d["uv_p"] - d["loops"][0][uv_layer].uv
                for k in vert_db.keys():
                    d = vert_db[k]
                    d["uv_sum_b"] = Vector((0.0, 0.0))
                    for l in d["loops"]:
                        ln = l.link_loop_next
                        lp = l.link_loop_prev
                        dn = vert_db[ln.vert]
                        dp = vert_db[lp.vert]
                        d["uv_sum_b"] = d["uv_sum_b"] + dn["uv_b"] + dp["uv_b"]

                # apply
                for f in bm.faces:
                    if not f.select:
                        continue
                    for i, l in enumerate(f.loops):
                        loc_2d = location_3d_to_region_2d_extra(
                            region, space.region_3d,
                            compat.matmul(world_mat, l.vert.co))
                        diff = loc_2d - self.__initial_mco
                        if diff.length >= sc.muv_uv_sculpt_radius:
                            continue
                        db = vert_db[l.vert]
                        strength = _get_strength(diff.length,
                                                 sc.muv_uv_sculpt_radius,
                                                 sc.muv_uv_sculpt_strength)

                        base = (1.0 - strength) * l[uv_layer].uv
                        if sc.muv_uv_sculpt_relax_method == 'HC':
                            t = 0.5 * \
                                (db["uv_b"] + db["uv_sum_b"] / d["uv_count"])
                            diff = strength * (db["uv_p"] - t)
                            target_uv = base + diff
                        elif sc.muv_uv_sculpt_relax_method == 'LAPLACIAN':
                            diff = strength * db["uv_p"]
                            target_uv = base + diff
                        else:
                            continue

                        l[uv_layer].uv = target_uv

            bmesh.update_edit_mesh(obj.data)
Example #60
0
    def modal(self, context, event):
        context.area.tag_redraw()

        if event.type in {'MIDDLEMOUSE', 'WHELLUPMOUSE', 'WHEELDOWNMOUSE'}:
            #let the user pan and rotate around (translate?)
            return {'PASS_THROUGH'}

        if event.type == 'TIMER':
            #iterate....check convergence.
            if self.keep_iterating:
                self.iterate(context)

            return {'PASS_THROUGH'}

        elif event.type == 'MOUSEMOVE':
            #change the active bias
            region = context.region
            rv3d = context.space_data.region_3d
            coord = event.mouse_region_x, event.mouse_region_y
            vec = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
            ray_origin = view3d_utils.region_2d_to_location_3d(
                region, rv3d, coord, vec) - 5000 * vec
            target = bpy.data.objects[self.target_name]
            #raycast onto active object
            ray_target = ray_origin + 5000 * vec
            [hit, normal,
             face] = odcutils.obj_ray_cast(target, target.matrix_world,
                                           ray_origin, ray_target)

            if hit:
                self.current_bias_point = target.matrix_world * hit
            '''
            if not self.keep_iterating:
                self.bias_point = (event.mouse_region_x, event.mouse_region_y)
                self.keep_iterating = True
            '''

        elif event.type == 'LEFTMOUSE' and event.value == "PRESS":
            #confirm the existing walking cache

            #if continue_iterating still true, append the last confirmed point to the bias points
            #change the active bias
            region = context.region
            rv3d = context.space_data.region_3d
            coord = event.mouse_region_x, event.mouse_region_y
            target = bpy.data.objects[self.target_name]
            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 + 3000 * vec
            [hit, normal,
             face] = odcutils.obj_ray_cast(target, target.matrix_world,
                                           ray_origin, ray_target)

            if hit:
                self.bias_points.append(target.matrix_world * hit)

            #keep iterating to mouse projection on model
            self.keep_iterating = not self.keep_iterating
            return {'RUNNING_MODAL'}

        elif event.type == 'RIGHTMOUSE' and event.value == "PRESS":
            #pop off a bias point
            self.bias_points.pop()
            #pop off a bias normal

            #pop off stack of confirmed crevice points prior to that
            #keep iterating to mouse projection on model
            self.keep_iterating = not self.keep_iterating
            return {'RUNNING_MODAL'}

        elif event.type in {'ESC'}:
            context.window_manager.event_timer_remove(self._timer)
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            return {'CANCELLED'}

        elif event.type in {'RETURN'}:
            context.window_manager.event_time_remove(self._timer)
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            return {'CANCELLED'}

        return {'RUNNING_MODAL'}