this is an example using a context manager in Bender to help with switching modes for running a tool.
its also an example of setting a material on a face using python in Blender. the mesh is assumed to be topologically symmetric and it only works with the source side in +x.
the tool may have bugs so please use/modify at your own risk. (tested in Blender 2.79)
before:
after:
import bpy
from mathutils import Vector
from math import sqrt
import logging
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG) #without this info logs wouldnt show in
class EnterModeContext(object):
"""gives ability to enter a needed mode > then run needed > then return to original mode
ex entering into edit mode:
#subdivide selected mesh in edit mode
with EnterModeContext("EDIT"):
bpy.ops.mesh.subdivide()
"""
def __init__(self, toMode):
"""
@param toMode (str) mode to go into ex: 'EDIT' or 'POSE' etc
"""
self._toMode = toMode #mode to go into
def __enter__(self):
#print("enter")
self._currentMode = bpy.context.object.mode
#go into to mode if not already in it
if self._currentMode != self._toMode:
bpy.ops.object.mode_set(mode=self._toMode)
def __exit__(self, ext, exv, trb):
#print("exiting")
logger.info("ext:{}".format(ext))
logger.info("exv:{}".format(exv))
logger.info("trb:{}".format(trb))
#return into starting mode if not already in it
if self._currentMode != self._toMode:
bpy.ops.object.mode_set(mode=self._currentMode)
return True
def makeMaterialSymmetric(meshName):
"""make materials symmetric. given a topology symmetric mesh.
Args:
meshName (str) data object name for mesh we want to make material symmetric
Returns:
(bool) whether successfully made material symmetric
"""
epsilon = 0.000001 #how close is enough to say found a matched point
numFaces = len(bpy.data.objects[meshName].data.polygons)
faceMirrorData = []
for faceIndex in range(0, numFaces):
facePos = bpy.data.objects[meshName].data.polygons[faceIndex].center
#we are only editing right side faces
if facePos >= 0:
continue
#loop through all faces trying to find closest face to mirror point
#negate x to get left side mirror face position
mirrorPos = Vector((-1*facePos.x, facePos.y, facePos.z))
for f in range(0, numFaces):
fPos = bpy.data.objects[meshName].data.polygons[f].center
#ignore left side faces as they are not on right side of mesh
if fPos <= 0:
continue
#check if found a mirrored face
dist = sqrt((fPos.x - mirrorPos.x)**2 + (fPos.y - mirrorPos.y)**2 + (fPos.z - mirrorPos.z)**2)
#if distance too big we know we havent found our mirrored face yet
if dist > epsilon:
continue
#we found our mirrored face
dat = dict(faceIndex=faceIndex, mirrorIndex=f)
faceMirrorData.append(dat)
break #exit loop as we dont need to check any others
#continue to next left side face we want to search for a mirror
#done with loops
#appy the material on mirror side
for data in faceMirrorData:
sourceIndex = data.get('faceIndex', None)
destinationIndex = data.get('mirrorIndex', None)
if (not sourceIndex) or (not destinationIndex):
print("cannot find a mirrored face for source face {}. mesh is more than likely not symmetric".format(sourceIndex))
continue
sourceMaterialIndex = bpy.data.objects[meshName].data.polygons[sourceIndex].material_index
#set mirror side material
bpy.data.objects[meshName].data.polygons[destinationIndex].material_index = sourceMaterialIndex
return True
"""
import imp
testTool = imp.load_source("tool","/Users/Nathaniel/Documents/src_blender/python/snippets/texture_snippets.py") #for mac. change to path to python file
with testTool.EnterModeContext("OBJECT"):
testTool.makeMaterialSymmetric("Sphere")
""" Thanks for looking

