gizmo_custom_geometry.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. # Example of a custom widget that defines it's own geometry.
  2. #
  3. # Usage: Select a light in the 3D view and drag the arrow at it's rear
  4. # to change it's energy value.
  5. #
  6. import bpy
  7. from bpy.types import (
  8. Gizmo,
  9. GizmoGroup,
  10. )
  11. # Coordinates (each one is a triangle).
  12. custom_shape_verts = (
  13. (3.0, 1.0, -1.0), (2.0, 2.0, -1.0), (3.0, 3.0, -1.0),
  14. (1.0, 3.0, 1.0), (3.0, 3.0, -1.0), (1.0, 3.0, -1.0),
  15. (3.0, 3.0, 1.0), (3.0, 1.0, -1.0), (3.0, 3.0, -1.0),
  16. (2.0, 0.0, 1.0), (3.0, 1.0, -1.0), (3.0, 1.0, 1.0),
  17. (2.0, 0.0, -1.0), (2.0, 2.0, 1.0), (2.0, 2.0, -1.0),
  18. (2.0, 2.0, -1.0), (0.0, 2.0, 1.0), (0.0, 2.0, -1.0),
  19. (1.0, 3.0, 1.0), (2.0, 2.0, 1.0), (3.0, 3.0, 1.0),
  20. (0.0, 2.0, -1.0), (1.0, 3.0, 1.0), (1.0, 3.0, -1.0),
  21. (2.0, 2.0, 1.0), (3.0, 1.0, 1.0), (3.0, 3.0, 1.0),
  22. (2.0, 2.0, -1.0), (1.0, 3.0, -1.0), (3.0, 3.0, -1.0),
  23. (-3.0, -1.0, -1.0), (-2.0, -2.0, -1.0), (-3.0, -3.0, -1.0),
  24. (-1.0, -3.0, 1.0), (-3.0, -3.0, -1.0), (-1.0, -3.0, -1.0),
  25. (-3.0, -3.0, 1.0), (-3.0, -1.0, -1.0), (-3.0, -3.0, -1.0),
  26. (-2.0, 0.0, 1.0), (-3.0, -1.0, -1.0), (-3.0, -1.0, 1.0),
  27. (-2.0, 0.0, -1.0), (-2.0, -2.0, 1.0), (-2.0, -2.0, -1.0),
  28. (-2.0, -2.0, -1.0), (0.0, -2.0, 1.0), (0.0, -2.0, -1.0),
  29. (-1.0, -3.0, 1.0), (-2.0, -2.0, 1.0), (-3.0, -3.0, 1.0),
  30. (0.0, -2.0, -1.0), (-1.0, -3.0, 1.0), (-1.0, -3.0, -1.0),
  31. (-2.0, -2.0, 1.0), (-3.0, -1.0, 1.0), (-3.0, -3.0, 1.0),
  32. (-2.0, -2.0, -1.0), (-1.0, -3.0, -1.0), (-3.0, -3.0, -1.0),
  33. (1.0, -1.0, 0.0), (-1.0, -1.0, 0.0), (0.0, 0.0, -5.0),
  34. (-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (0.0, 0.0, 5.0),
  35. (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (0.0, 0.0, 5.0),
  36. (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0), (0.0, 0.0, 5.0),
  37. (-1.0, 1.0, 0.0), (-1.0, -1.0, 0.0), (0.0, 0.0, 5.0),
  38. (-1.0, -1.0, 0.0), (-1.0, 1.0, 0.0), (0.0, 0.0, -5.0),
  39. (-1.0, 1.0, 0.0), (1.0, 1.0, 0.0), (0.0, 0.0, -5.0),
  40. (1.0, 1.0, 0.0), (1.0, -1.0, 0.0), (0.0, 0.0, -5.0),
  41. (3.0, 1.0, -1.0), (2.0, 0.0, -1.0), (2.0, 2.0, -1.0),
  42. (1.0, 3.0, 1.0), (3.0, 3.0, 1.0), (3.0, 3.0, -1.0),
  43. (3.0, 3.0, 1.0), (3.0, 1.0, 1.0), (3.0, 1.0, -1.0),
  44. (2.0, 0.0, 1.0), (2.0, 0.0, -1.0), (3.0, 1.0, -1.0),
  45. (2.0, 0.0, -1.0), (2.0, 0.0, 1.0), (2.0, 2.0, 1.0),
  46. (2.0, 2.0, -1.0), (2.0, 2.0, 1.0), (0.0, 2.0, 1.0),
  47. (1.0, 3.0, 1.0), (0.0, 2.0, 1.0), (2.0, 2.0, 1.0),
  48. (0.0, 2.0, -1.0), (0.0, 2.0, 1.0), (1.0, 3.0, 1.0),
  49. (2.0, 2.0, 1.0), (2.0, 0.0, 1.0), (3.0, 1.0, 1.0),
  50. (2.0, 2.0, -1.0), (0.0, 2.0, -1.0), (1.0, 3.0, -1.0),
  51. (-3.0, -1.0, -1.0), (-2.0, 0.0, -1.0), (-2.0, -2.0, -1.0),
  52. (-1.0, -3.0, 1.0), (-3.0, -3.0, 1.0), (-3.0, -3.0, -1.0),
  53. (-3.0, -3.0, 1.0), (-3.0, -1.0, 1.0), (-3.0, -1.0, -1.0),
  54. (-2.0, 0.0, 1.0), (-2.0, 0.0, -1.0), (-3.0, -1.0, -1.0),
  55. (-2.0, 0.0, -1.0), (-2.0, 0.0, 1.0), (-2.0, -2.0, 1.0),
  56. (-2.0, -2.0, -1.0), (-2.0, -2.0, 1.0), (0.0, -2.0, 1.0),
  57. (-1.0, -3.0, 1.0), (0.0, -2.0, 1.0), (-2.0, -2.0, 1.0),
  58. (0.0, -2.0, -1.0), (0.0, -2.0, 1.0), (-1.0, -3.0, 1.0),
  59. (-2.0, -2.0, 1.0), (-2.0, 0.0, 1.0), (-3.0, -1.0, 1.0),
  60. (-2.0, -2.0, -1.0), (0.0, -2.0, -1.0), (-1.0, -3.0, -1.0),
  61. )
  62. class MyCustomShapeWidget(Gizmo):
  63. bl_idname = "VIEW3D_GT_auto_facemap"
  64. bl_target_properties = (
  65. {"id": "offset", "type": 'FLOAT', "array_length": 1},
  66. )
  67. __slots__ = (
  68. "custom_shape",
  69. "init_mouse_y",
  70. "init_value",
  71. )
  72. def _update_offset_matrix(self):
  73. # offset behind the light
  74. self.matrix_offset.col[3][2] = self.target_get_value("offset") / -10.0
  75. def draw(self, context):
  76. self._update_offset_matrix()
  77. self.draw_custom_shape(self.custom_shape)
  78. def draw_select(self, context, select_id):
  79. self._update_offset_matrix()
  80. self.draw_custom_shape(self.custom_shape, select_id=select_id)
  81. def setup(self):
  82. if not hasattr(self, "custom_shape"):
  83. self.custom_shape = self.new_custom_shape('TRIS', custom_shape_verts)
  84. def invoke(self, context, event):
  85. self.init_mouse_y = event.mouse_y
  86. self.init_value = self.target_get_value("offset")
  87. return {'RUNNING_MODAL'}
  88. def exit(self, context, cancel):
  89. context.area.header_text_set(None)
  90. if cancel:
  91. self.target_set_value("offset", self.init_value)
  92. def modal(self, context, event, tweak):
  93. delta = (event.mouse_y - self.init_mouse_y) / 10.0
  94. if 'SNAP' in tweak:
  95. delta = round(delta)
  96. if 'PRECISE' in tweak:
  97. delta /= 10.0
  98. value = self.init_value - delta
  99. self.target_set_value("offset", value)
  100. context.area.header_text_set("My Gizmo: %.4f" % value)
  101. return {'RUNNING_MODAL'}
  102. class MyCustomShapeWidgetGroup(GizmoGroup):
  103. bl_idname = "OBJECT_GGT_light_test"
  104. bl_label = "Test Light Widget"
  105. bl_space_type = 'VIEW_3D'
  106. bl_region_type = 'WINDOW'
  107. bl_options = {'3D', 'PERSISTENT'}
  108. @classmethod
  109. def poll(cls, context):
  110. ob = context.object
  111. return (ob and ob.type == 'LIGHT')
  112. def setup(self, context):
  113. # Assign the 'offset' target property to the light energy.
  114. ob = context.object
  115. mpr = self.gizmos.new(MyCustomShapeWidget.bl_idname)
  116. mpr.target_set_prop("offset", ob.data, "energy")
  117. mpr.color = 1.0, 0.5, 1.0
  118. mpr.alpha = 0.5
  119. mpr.color_highlight = 1.0, 1.0, 1.0
  120. mpr.alpha_highlight = 0.5
  121. # units are large, so shrink to something more reasonable.
  122. mpr.scale_basis = 0.1
  123. mpr.use_draw_modal = True
  124. self.energy_widget = mpr
  125. def refresh(self, context):
  126. ob = context.object
  127. mpr = self.energy_widget
  128. mpr.matrix_basis = ob.matrix_world.normalized()
  129. classes = (
  130. MyCustomShapeWidget,
  131. MyCustomShapeWidgetGroup,
  132. )
  133. for cls in classes:
  134. bpy.utils.register_class(cls)