[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [25967] trunk/blender: UV mirror tool ( copies UVs from one side of the mesh to the other)
Campbell Barton
ideasman42 at gmail.com
Wed Jan 13 18:58:26 CET 2010
Revision: 25967
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25967
Author: campbellbarton
Date: 2010-01-13 18:58:26 +0100 (Wed, 13 Jan 2010)
Log Message:
-----------
UV mirror tool (copies UVs from one side of the mesh to the other)
WIP, suffers from editmode bug where editmode python tools cant have redo-options set. and needs options for precission.
Modified Paths:
--------------
trunk/blender/release/scripts/modules/bpy_types.py
trunk/blender/release/scripts/op/mesh.py
trunk/blender/release/scripts/ui/space_image.py
trunk/blender/source/blender/editors/animation/anim_markers.c
trunk/blender/source/blender/makesrna/intern/CMakeLists.txt
Modified: trunk/blender/release/scripts/modules/bpy_types.py
===================================================================
--- trunk/blender/release/scripts/modules/bpy_types.py 2010-01-13 17:43:42 UTC (rev 25966)
+++ trunk/blender/release/scripts/modules/bpy_types.py 2010-01-13 17:58:26 UTC (rev 25967)
@@ -388,10 +388,19 @@
class MeshFace(StructRNA):
__slots__ = ()
+ @property
+ def center(self):
+ """The midpoint of the face."""
+ face_verts = self.verts[:]
+ mesh_verts = self.id_data.verts
+ if len(face_verts) == 3:
+ return (mesh_verts[face_verts[0]].co + mesh_verts[face_verts[1]].co + mesh_verts[face_verts[2]].co) / 3.0
+ else:
+ return (mesh_verts[face_verts[0]].co + mesh_verts[face_verts[1]].co + mesh_verts[face_verts[2]].co + mesh_verts[face_verts[3]].co) / 4.0
@property
def edge_keys(self):
- verts = tuple(self.verts)
+ verts = self.verts[:]
if len(verts) == 3:
return ord_ind(verts[0], verts[1]), ord_ind(verts[1], verts[2]), ord_ind(verts[2], verts[0])
Modified: trunk/blender/release/scripts/op/mesh.py
===================================================================
--- trunk/blender/release/scripts/op/mesh.py 2010-01-13 17:43:42 UTC (rev 25966)
+++ trunk/blender/release/scripts/op/mesh.py 2010-01-13 17:58:26 UTC (rev 25967)
@@ -20,56 +20,162 @@
import bpy
+class MeshSelectInteriorFaces(bpy.types.Operator):
+ '''Select faces where all edges have more then 2 face users.'''
-def main(context):
- ob = context.active_object
- bpy.ops.mesh.selection_type(type='FACE')
- is_editmode = (ob.mode == 'EDIT')
- if is_editmode:
- bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+ bl_idname = "mesh.faces_select_interior"
+ bl_label = "Select Interior Faces"
+ bl_register = True
+ bl_undo = True
- mesh = ob.data
+ def poll(self, context):
+ ob = context.active_object
+ return (ob and ob.type == 'MESH')
- face_list = [face for face in mesh.faces]
- face_edge_keys = [face.edge_keys for face in face_list]
+ def execute(self, context):
+ ob = context.active_object
+ bpy.ops.mesh.selection_type(type='FACE')
+ is_editmode = (ob.mode == 'EDIT')
+ if is_editmode:
+ bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
- edge_face_count = mesh.edge_face_count_dict
+ mesh = ob.data
- def test_interior(index):
- for key in face_edge_keys[index]:
- if edge_face_count[key] < 3:
- return False
- return True
+ face_list = [face for face in mesh.faces]
+ face_edge_keys = [face.edge_keys for face in face_list]
- for index, face in enumerate(face_list):
- if(test_interior(index)):
- face.selected = True
- else:
- face.selected = False
+ edge_face_count = mesh.edge_face_count_dict
- if is_editmode:
- bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+ def test_interior(index):
+ for key in face_edge_keys[index]:
+ if edge_face_count[key] < 3:
+ return False
+ return True
+ for index, face in enumerate(face_list):
+ if(test_interior(index)):
+ face.selected = True
+ else:
+ face.selected = False
-class MeshSelectInteriorFaces(bpy.types.Operator):
- '''Select faces where all edges have more then 2 face users.'''
+ if is_editmode:
+ bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+ return {'FINISHED'}
- bl_idname = "mesh.faces_select_interior"
- bl_label = "Select Interior Faces"
+
+class MeshMirrorUV(bpy.types.Operator):
+ '''Copy mirror UV coordinates on the X axis based on a mirrored mesh'''
+ bl_idname = "mesh.faces_miror_uv"
+ bl_label = "Copy Mirrored UV coords"
bl_register = True
bl_undo = True
-
+
def poll(self, context):
ob = context.active_object
return (ob and ob.type == 'MESH')
+
+ def execute(self, context):
+ DIR = 1 # TODO, make an option
+
+ from Mathutils import Vector
+
+ ob = context.active_object
+ is_editmode = (ob.mode == 'EDIT')
+ if is_editmode:
+ bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
- def execute(self, context):
- main(context)
+ mesh = ob.data
+
+ # mirror lookups
+ mirror_gt = {}
+ mirror_lt = {}
+
+ vcos = [v.co.toTuple(5) for v in mesh.verts]
+
+ for i, co in enumerate(vcos):
+ if co[0] > 0.0:
+ mirror_gt[co] = i
+ elif co[0] < 0.0:
+ mirror_lt[co] = i
+ else:
+ mirror_gt[co] = i
+ mirror_lt[co] = i
+
+ #for i, v in enumerate(mesh.verts):
+ vmap = {}
+ for mirror_a, mirror_b in (mirror_gt, mirror_lt), (mirror_lt, mirror_gt):
+ for co, i in mirror_a.items():
+ nco = (-co[0], co[1], co[2])
+ j = mirror_b.get(nco)
+ if j is not None:
+ vmap[i] = j
+
+
+ active_uv_layer = None
+ for lay in mesh.uv_textures:
+ if lay.active:
+ active_uv_layer = lay.data
+ break
+
+ fuvs = [(uv.uv1, uv.uv2, uv.uv3, uv.uv4) for uv in active_uv_layer]
+ fuvs_cpy = [(uv[0].copy(), uv[1].copy(), uv[2].copy(), uv[3].copy()) for uv in fuvs]
+
+ # as a list
+ faces = mesh.faces[:]
+
+ fuvsel = [(False not in uv.uv_selected) for uv in active_uv_layer]
+ fcents = [f.center for f in faces]
+
+ # find mirror faces
+ mirror_fm = {}
+ for i, f in enumerate(faces):
+ verts = f.verts[:]
+ verts.sort()
+ verts = tuple(verts)
+ mirror_fm[verts] = i
+
+ fmap = {}
+ for i, f in enumerate(faces):
+ verts = [vmap.get(j) for j in f.verts]
+ if None not in verts:
+ verts.sort()
+ j = mirror_fm.get(tuple(verts))
+ if j is not None:
+ fmap[i] = j
+
+ done = [False] * len(faces)
+ for i, j in fmap.items():
+
+ if not fuvsel[i] or not fuvsel[j]:
+ continue
+ elif DIR == 0 and fcents[i][0] < 0.0:
+ continue
+ elif DIR == 1 and fcents[i][0] > 0.0:
+ continue
+
+ # copy UVs
+ uv1= fuvs[i]
+ uv2= fuvs_cpy[j]
+
+ # get the correct rotation
+ v1 = faces[j].verts[:]
+ v2 = [vmap[k] for k in faces[i].verts[:]]
+
+
+ for k in range(len(uv1)):
+ k_map = v1.index(v2[k])
+ uv1[k].x = -(uv2[k_map].x-0.5) + 0.5
+ uv1[k].y = uv2[k_map].y
+
+ if is_editmode:
+ bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+
return {'FINISHED'}
-
# Register the operator
bpy.types.register(MeshSelectInteriorFaces)
+bpy.types.register(MeshMirrorUV)
if __name__ == "__main__":
- bpy.ops.mesh.faces_select_interior()
+ # bpy.ops.mesh.faces_select_interior()
+ bpy.ops.mesh.faces_miror_uv()
Modified: trunk/blender/release/scripts/ui/space_image.py
===================================================================
--- trunk/blender/release/scripts/ui/space_image.py 2010-01-13 17:43:42 UTC (rev 25966)
+++ trunk/blender/release/scripts/ui/space_image.py 2010-01-13 17:58:26 UTC (rev 25967)
@@ -219,6 +219,7 @@
layout.operator("uv.average_islands_scale")
layout.operator("uv.minimize_stretch")
layout.operator("uv.stitch")
+ layout.operator("mesh.faces_miror_uv")
layout.separator()
Modified: trunk/blender/source/blender/editors/animation/anim_markers.c
===================================================================
--- trunk/blender/source/blender/editors/animation/anim_markers.c 2010-01-13 17:43:42 UTC (rev 25966)
+++ trunk/blender/source/blender/editors/animation/anim_markers.c 2010-01-13 17:58:26 UTC (rev 25967)
@@ -1012,7 +1012,6 @@
}
}
- /* one day multiple scenes will be visible, then we should have some update function for them */
return OPERATOR_FINISHED;
}
Modified: trunk/blender/source/blender/makesrna/intern/CMakeLists.txt
===================================================================
--- trunk/blender/source/blender/makesrna/intern/CMakeLists.txt 2010-01-13 17:43:42 UTC (rev 25966)
+++ trunk/blender/source/blender/makesrna/intern/CMakeLists.txt 2010-01-13 17:58:26 UTC (rev 25967)
@@ -99,7 +99,7 @@
# Output rna_*_gen.c
ADD_CUSTOM_COMMAND(
OUTPUT ${GENSRC}
- # with crashes try add this after COMMEND: valgrind --leak-check=full --track-origins=yes
+ # with crashes try add this after COMMAND: valgrind --leak-check=full --track-origins=yes
COMMAND ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/makesrna ${CMAKE_CURRENT_BINARY_DIR}/
DEPENDS makesrna
)
More information about the Bf-blender-cvs
mailing list