From dd6fa94dcc9fa6002d4901f4afe0b1e997f5fa0c Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 2 Nov 2016 15:11:58 +0100 Subject: Add 'Set From Faces' tool to custom split normals. Feature request during bconf, makes sense to have it even as an hack for now, since this is probably one of the most common use cases. This should be redone in bmesh once we have proper custom noramls handling in edit mode... --- release/scripts/startup/bl_operators/mesh.py | 50 ++++++++++++++++++++++ .../scripts/startup/bl_ui/space_view3d_toolbar.py | 1 + 2 files changed, 51 insertions(+) (limited to 'release') diff --git a/release/scripts/startup/bl_operators/mesh.py b/release/scripts/startup/bl_operators/mesh.py index be74f8dbc0e..58eab5436e6 100644 --- a/release/scripts/startup/bl_operators/mesh.py +++ b/release/scripts/startup/bl_operators/mesh.py @@ -198,3 +198,53 @@ class MeshSelectPrev(Operator): bmesh.update_edit_mesh(me, False) return {'FINISHED'} + + +# XXX This is hackish (going forth and back from Object mode...), to be redone once we have proper support of +# custom normals in BMesh/edit mode. +class MehsSetNormalsFromFaces(Operator): + """Set the custom vertex normals from the selected faces ones""" + bl_idname = "mesh.set_normals_from_faces" + bl_label = "Set Normals From Faces" + bl_options = {'REGISTER', 'UNDO'} + + @classmethod + def poll(cls, context): + return (context.mode == 'EDIT_MESH' and context.edit_object.data.polygons) + + def execute(self, context): + import mathutils + + bpy.ops.object.mode_set(mode='OBJECT') + obj = context.active_object + me = obj.data + + v2nors = {} + for p in me.polygons: + if not p.select: + continue + for lidx, vidx in zip(p.loop_indices, p.vertices): + assert(me.loops[lidx].vertex_index == vidx) + v2nors.setdefault(vidx, []).append(p.normal) + + for nors in v2nors.values(): + nors[:] = [sum(nors, mathutils.Vector((0, 0, 0))).normalized()] + + if not me.has_custom_normals: + me.create_normals_split() + me.calc_normals_split() + + normals = [] + for l in me.loops: + nor = v2nors.get(l.vertex_index, [None])[0] + if nor is None: + nor = l.normal + normals.append(nor.to_tuple()) + + me.normals_split_custom_set(normals) + + me.free_normals_split() + bpy.ops.object.mode_set(mode='EDIT') + + return {'FINISHED'} + diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 8019c8d2f34..f97e2d5b2d1 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -431,6 +431,7 @@ class VIEW3D_PT_tools_shading(View3DPanel, Panel): col.label(text="Normals:") col.operator("mesh.normals_make_consistent", text="Recalculate") col.operator("mesh.flip_normals", text="Flip Direction") + col.operator("mesh.set_normals_from_faces", text="Set From Faces") class VIEW3D_PT_tools_uvs(View3DPanel, Panel): -- cgit v1.2.3