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$
1
  • $\begingroup$ You can try overriding the context, see this question $\endgroup$
    – gandalf3
    Dec 8, 2013 at 0:49

3 Answers 3

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
  • 3
    $\begingroup$ you could construct a transformation matrix and use Mesh.transform() to mirror and avoid any operators and contexts. $\endgroup$
    – CodeManX
    Dec 8, 2013 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$ Nov 9, 2018 at 10:03
2
$\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='X',  
        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$
2
  • $\begingroup$ JFYI, the axis parameter seems to now require a string - 'X, Y, Z' rather than ints. $\endgroup$
    – DrewTNBD
    Jul 6, 2021 at 8:57
  • $\begingroup$ Cheers. No issues if you wish to make edit to update. $\endgroup$
    – batFINGER
    Jul 6, 2021 at 8:58
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$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .