view3d.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. # ##### BEGIN GPL LICENSE BLOCK #####
  2. #
  3. # This program is free software; you can redistribute it and/or
  4. # modify it under the terms of the GNU General Public License
  5. # as published by the Free Software Foundation; either version 2
  6. # of the License, or (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software Foundation,
  15. # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. #
  17. # ##### END GPL LICENSE BLOCK #####
  18. # <pep8-80 compliant>
  19. import bpy
  20. from bpy.types import Operator
  21. from bpy.props import (
  22. BoolProperty,
  23. EnumProperty,
  24. )
  25. class VIEW3D_OT_edit_mesh_extrude_individual_move(Operator):
  26. """Extrude each individual face separately along local normals"""
  27. bl_label = "Extrude Individual and Move"
  28. bl_idname = "view3d.edit_mesh_extrude_individual_move"
  29. @classmethod
  30. def poll(cls, context):
  31. obj = context.active_object
  32. return (obj is not None and obj.mode == 'EDIT')
  33. def execute(self, context):
  34. mesh = context.object.data
  35. select_mode = context.tool_settings.mesh_select_mode
  36. totface = mesh.total_face_sel
  37. totedge = mesh.total_edge_sel
  38. # totvert = mesh.total_vert_sel
  39. if select_mode[2] and totface == 1:
  40. bpy.ops.mesh.extrude_region_move(
  41. 'INVOKE_REGION_WIN',
  42. TRANSFORM_OT_translate={
  43. "orient_type": 'NORMAL',
  44. "constraint_axis": (False, False, True),
  45. }
  46. )
  47. elif select_mode[2] and totface > 1:
  48. bpy.ops.mesh.extrude_faces_move('INVOKE_REGION_WIN')
  49. elif select_mode[1] and totedge >= 1:
  50. bpy.ops.mesh.extrude_edges_move('INVOKE_REGION_WIN')
  51. else:
  52. bpy.ops.mesh.extrude_vertices_move('INVOKE_REGION_WIN')
  53. # ignore return from operators above because they are 'RUNNING_MODAL',
  54. # and cause this one not to be freed. [#24671]
  55. return {'FINISHED'}
  56. def invoke(self, context, _event):
  57. return self.execute(context)
  58. class VIEW3D_OT_edit_mesh_extrude_move(Operator):
  59. """Extrude region together along the average normal"""
  60. bl_label = "Extrude and Move on Normals"
  61. bl_idname = "view3d.edit_mesh_extrude_move_normal"
  62. @classmethod
  63. def poll(cls, context):
  64. obj = context.active_object
  65. return (obj is not None and obj.mode == 'EDIT')
  66. @staticmethod
  67. def extrude_region(context, use_vert_normals):
  68. mesh = context.object.data
  69. totface = mesh.total_face_sel
  70. totedge = mesh.total_edge_sel
  71. # totvert = mesh.total_vert_sel
  72. if totface >= 1:
  73. if use_vert_normals:
  74. bpy.ops.mesh.extrude_region_shrink_fatten(
  75. 'INVOKE_REGION_WIN',
  76. TRANSFORM_OT_shrink_fatten={},
  77. )
  78. else:
  79. bpy.ops.mesh.extrude_region_move(
  80. 'INVOKE_REGION_WIN',
  81. TRANSFORM_OT_translate={
  82. "orient_type": 'NORMAL',
  83. "constraint_axis": (False, False, True),
  84. },
  85. )
  86. elif totedge == 1:
  87. bpy.ops.mesh.extrude_region_move(
  88. 'INVOKE_REGION_WIN',
  89. TRANSFORM_OT_translate={
  90. # Don't set the constraint axis since users will expect MMB
  91. # to use the user setting, see: T61637
  92. # "orient_type": 'NORMAL',
  93. # Not a popular choice, too restrictive for retopo.
  94. # "constraint_axis": (True, True, False)})
  95. "constraint_axis": (False, False, False),
  96. })
  97. else:
  98. bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN')
  99. # ignore return from operators above because they are 'RUNNING_MODAL',
  100. # and cause this one not to be freed. [#24671]
  101. return {'FINISHED'}
  102. def execute(self, context):
  103. return VIEW3D_OT_edit_mesh_extrude_move.extrude_region(context, False)
  104. def invoke(self, context, _event):
  105. return self.execute(context)
  106. class VIEW3D_OT_edit_mesh_extrude_shrink_fatten(Operator):
  107. """Extrude region together along local normals"""
  108. bl_label = "Extrude and Move on Individual Normals"
  109. bl_idname = "view3d.edit_mesh_extrude_move_shrink_fatten"
  110. @classmethod
  111. def poll(cls, context):
  112. obj = context.active_object
  113. return (obj is not None and obj.mode == 'EDIT')
  114. def execute(self, context):
  115. return VIEW3D_OT_edit_mesh_extrude_move.extrude_region(context, True)
  116. def invoke(self, context, _event):
  117. return self.execute(context)
  118. class VIEW3D_OT_transform_gizmo_set(Operator):
  119. """Set the current transform gizmo"""
  120. bl_label = "Transform Gizmo Set"
  121. bl_options = {'REGISTER', 'UNDO'}
  122. bl_idname = "view3d.transform_gizmo_set"
  123. extend: BoolProperty(
  124. default=False,
  125. )
  126. type: EnumProperty(
  127. items=(
  128. ('TRANSLATE', "Move", ""),
  129. ('ROTATE', "Rotate", ""),
  130. ('SCALE', "Scale", ""),
  131. ),
  132. options={'ENUM_FLAG'},
  133. )
  134. @classmethod
  135. def poll(cls, context):
  136. return context.area.type == 'VIEW_3D'
  137. def execute(self, context):
  138. space_data = context.space_data
  139. space_data.show_gizmo = True
  140. attrs = ("show_gizmo_object_translate", "show_gizmo_object_rotate", "show_gizmo_object_scale")
  141. attr_active = tuple(
  142. attrs[('TRANSLATE', 'ROTATE', 'SCALE').index(t)]
  143. for t in self.type
  144. )
  145. if self.extend:
  146. for attr in attrs:
  147. if attr in attr_active:
  148. setattr(space_data, attr, True)
  149. else:
  150. for attr in attrs:
  151. setattr(space_data, attr, attr in attr_active)
  152. return {'FINISHED'}
  153. def invoke(self, context, event):
  154. if not self.properties.is_property_set("extend"):
  155. self.extend = event.shift
  156. return self.execute(context)
  157. classes = (
  158. VIEW3D_OT_edit_mesh_extrude_individual_move,
  159. VIEW3D_OT_edit_mesh_extrude_move,
  160. VIEW3D_OT_edit_mesh_extrude_shrink_fatten,
  161. VIEW3D_OT_transform_gizmo_set,
  162. )