Merge branch 'master' into blender2.8
[blender-addons.git] / mesh_custom_normals_tools.py
blob462b7609b68cca74f0420ee4f8b961f6686ce82b
1 # ***** BEGIN GPL LICENSE BLOCK *****
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # ***** END GPL LICENCE BLOCK *****
20 bl_info = {
21 "name": "Custom Normals Tools",
22 "author": "Bastien Montagne (mont29)",
23 "version": (0, 0, 1),
24 "blender": (2, 75, 0),
25 "location": "3DView > Tools",
26 "description": "Various tools/helpers for custom normals",
27 "warning": "",
28 "support": 'OFFICIAL',
29 "category": "Mesh",
33 import bpy
36 class MESH_OT_flip_custom_normals(bpy.types.Operator):
37 """Flip active mesh's normals, including custom ones (only in Object mode)"""
38 bl_idname = "mesh.flip_custom_normals"
39 bl_label = "Flip Custom Normals"
40 bl_options = {'UNDO'}
42 @classmethod
43 def poll(cls, context):
44 return context.object and context.object.type == 'MESH' and context.object.mode == 'OBJECT'
46 def execute(self, context):
47 me = context.object.data
49 if me.has_custom_normals:
50 me.calc_normals_split()
51 clnors = [0.0] * 3 * len(me.loops)
52 me.loops.foreach_get("normal", clnors)
54 bpy.ops.object.mode_set(mode='EDIT')
55 bpy.ops.mesh.select_all(action='SELECT')
56 bpy.ops.mesh.flip_normals()
57 bpy.ops.object.mode_set(mode='OBJECT')
59 me = context.object.data
60 if me.has_custom_normals:
61 clnors[:] = list(zip(*[(-n for n in clnors)] * 3))
62 # We also have to take in account that the winding was reverted...
63 for p in me.polygons:
64 ls = p.loop_start + 1
65 le = ls + p.loop_total - 1
66 clnors[ls:le] = reversed(clnors[ls:le])
67 me.normals_split_custom_set(clnors)
69 context.scene.update()
70 return {'FINISHED'}
73 def flip_custom_normals_draw_func(self, context):
74 if isinstance(self, bpy.types.Panel):
75 self.layout.label("Custom Normal Tools:")
76 self.layout.operator(MESH_OT_flip_custom_normals.bl_idname)
79 def register():
80 bpy.utils.register_module(__name__)
81 bpy.types.VIEW3D_PT_tools_object.append(flip_custom_normals_draw_func)
84 def unregister():
85 bpy.types.VIEW3D_PT_tools_object.remove(flip_custom_normals_draw_func)
86 bpy.utils.unregister_module(__name__)
89 if __name__ == "__main__":
90 register()