3
$\begingroup$

I have pivot point and cursor set as in this answer. Now I want to use it to mirror mesh of an object by running script from the text editor. Mirror works fine, but it does not use the pivot point. Does it mean I have to run the code from the 3D View, or there is a way to switch to the context, and still run it in Text Editor?

import bpy

def areas_tuple():
    res = {}                                                               
    count = 0
    for area in bpy.context.screen.areas:                                  
        res[area.type] = count                                             
        count += 1
    return res  

areas = areas_tuple()
view3d = bpy.context.screen.areas[areas['VIEW_3D']].spaces[0]
view3d.pivot_point='CURSOR'
view3d.cursor_location = (0.0, 0.0, 0.0)

bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.transform.mirror(
    constraint_axis=(True, False, False),
    constraint_orientation='GLOBAL',
    proportional='DISABLED')
bpy.ops.mesh.flip_normals()
$\endgroup$
3
$\begingroup$

After reading gandalf3 comment all works!

import bpy

def areas_tuple():
    res = {}      
    count = 0                                                             
    for area in bpy.context.screen.areas:
        res[area.type] = count                                            
        count += 1
    return res   

def get_region(area):
    res = None
    for region in area.regions:
        if region.type == 'VIEW_3D':
            res = region
            break 
    return region

areas = areas_tuple()
view3d = bpy.context.screen.areas[areas['VIEW_3D']].spaces[0]
view3d.pivot_point='CURSOR'
view3d.cursor_location = (0.0, 0.0, 0.0)

bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.mesh.select_all(action='SELECT')
override = {
    'window': bpy.context.window,
    'screen': bpy.context.screen,
    'area': area,
    'region': get_region(area)
    } 

bpy.ops.transform.mirror(
    override,
    constraint_axis=(True, False, False),
    constraint_orientation='GLOBAL',
    proportional='DISABLED')
bpy.ops.mesh.flip_normals()
$\endgroup$
  • 2
    $\begingroup$ you could construct a transformation matrix and use Mesh.transform() to mirror and avoid any operators and contexts. $\endgroup$ – CodeManX Dec 8 '13 at 3:46
  • $\begingroup$ @Dimus can you please provide the definition of your variable area? I get the same error as @ThePie which is NameError: name 'area' is not defined. $\endgroup$ – Bruno Bieri Nov 9 '18 at 10:03
1
$\begingroup$

Bmesh Mirror operator

bmesh.ops.mirror(...)

Mirrors geometry along an axis. The resulting geometry is welded on using merge_dist. Pairs of original/mirrored vertices are welded using the merge_dist parameter (which defines the minimum distance for welding to happen)

Test script run in edit mode. Will mirror the whole mesh on x to the scene cursor location's local x location.

enter image description here

import bpy
import bmesh
from mathutils import Vector, Matrix
from math import radians, degrees
context = bpy.context
scene = context.scene
ob = context.edit_object
me = ob.data

bm = bmesh.from_edit_mesh(me)

bmesh.ops.mirror(bm, 
        geom=bm.faces[:] + bm.verts[:] + bm.edges[:],
        axis=0,  # x, y, z <==> 0, 1, 2
        matrix=Matrix.Translation(-scene.cursor_location).to_4x4() * ob.matrix_world, 
        merge_dist=-1 # disable so center verts dont merge.
        )
bmesh.update_edit_mesh(me)

This mirrors on the GLOBAL x axis by using the world matrix translated such that the cursor is the origin to mirror over.

Note: Similar answer for How to mirror a mesh on x-axis on pivot point with python? which has an example of mirroring on the LOCAL axis about cursor.

$\endgroup$
0
$\begingroup$

Looking for exactly the same problem, I found another solution (the dimus's answer is not working : NameError: name 'area' is not defined ) :

Rotate object around cursor with Python

So, with transform:

import bpy

def get_override(area_type, region_type):
    for area in bpy.context.screen.areas: 
        if area.type == area_type:             
            for region in area.regions:                 
                if region.type == region_type:                    
                    override = {'area': area, 'region': region} 
                    return override
    #error message if the area or region wasn't found
    raise RuntimeError("Wasn't able to find", region_type," in area ", area_type,
                        "\n Make sure it's open while executing script.")


#we need to override the context of our operator    
override = get_override( 'VIEW_3D', 'WINDOW' )

bpy.ops.transform.mirror(
    override,
    constraint_axis=(False, True, False),
    constraint_orientation='GLOBAL',
    proportional='DISABLED')
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.