custom_gui_controls.rst 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. :article_outdated: True
  2. .. _doc_custom_gui_controls:
  3. Custom GUI controls
  4. ===================
  5. So many controls...
  6. -------------------
  7. Yet there are never enough. Creating your own custom controls that act
  8. just the way you want them to is an obsession of almost every GUI
  9. programmer. Godot provides plenty of them, but they may not work exactly
  10. the way you want. Before contacting the developers with a pull-request
  11. to support diagonal scrollbars, at least it will be good to know how to
  12. create these controls easily from script.
  13. Drawing
  14. -------
  15. For drawing, it is recommended to check the :ref:`doc_custom_drawing_in_2d` tutorial.
  16. The same applies. Some functions are worth mentioning due to their
  17. usefulness when drawing, so they will be detailed next:
  18. Checking control size
  19. ~~~~~~~~~~~~~~~~~~~~~
  20. Unlike 2D nodes, "size" is important with controls, as it helps to
  21. organize them in proper layouts. For this, the
  22. :ref:`Control.size <class_Control_property_size>`
  23. property is provided. Checking it during ``_draw()`` is vital to ensure
  24. everything is kept in-bounds.
  25. Checking focus
  26. ~~~~~~~~~~~~~~
  27. Some controls (such as buttons or text editors) might provide input
  28. focus for keyboard or joypad input. Examples of this are entering text
  29. or pressing a button. This is controlled with the
  30. :ref:`Control.focus_mode <class_Control_property_focus_mode>`
  31. property. When drawing, and if the control supports input focus, it is
  32. always desired to show some sort of indicator (highlight, box, etc.) to
  33. indicate that this is the currently focused control. To check for this
  34. status, the :ref:`Control.has_focus() <class_Control_method_has_focus>` method
  35. exists. Example
  36. .. tabs::
  37. .. code-tab:: gdscript GDScript
  38. func _draw():
  39. if has_focus():
  40. draw_selected()
  41. else:
  42. draw_normal()
  43. .. code-tab:: csharp
  44. public override void _Draw()
  45. {
  46. if (HasFocus())
  47. {
  48. DrawSelected()
  49. }
  50. else
  51. {
  52. DrawNormal();
  53. }
  54. }
  55. Sizing
  56. ------
  57. As mentioned before, size is important to controls. This allows
  58. them to lay out properly, when set into grids, containers, or anchored.
  59. Controls, most of the time, provide a *minimum size* to help properly
  60. lay them out. For example, if controls are placed vertically on top of
  61. each other using a :ref:`VBoxContainer <class_VBoxContainer>`,
  62. the minimum size will make sure your custom control is not squished by
  63. the other controls in the container.
  64. To provide this callback, just override
  65. :ref:`Control._get_minimum_size() <class_Control_private_method__get_minimum_size>`,
  66. for example:
  67. .. tabs::
  68. .. code-tab:: gdscript GDScript
  69. func _get_minimum_size():
  70. return Vector2(30, 30)
  71. .. code-tab:: csharp
  72. public override Vector2 _GetMinimumSize()
  73. {
  74. return new Vector2(20, 20);
  75. }
  76. Alternatively, set it using a function:
  77. .. tabs::
  78. .. code-tab:: gdscript GDScript
  79. func _ready():
  80. set_custom_minimum_size(Vector2(30, 30))
  81. .. code-tab:: csharp
  82. public override void _Ready()
  83. {
  84. CustomMinimumSize = new Vector2(20, 20);
  85. }
  86. Input
  87. -----
  88. Controls provide a few helpers to make managing input events much easier
  89. than regular nodes.
  90. Input events
  91. ~~~~~~~~~~~~
  92. There are a few tutorials about input before this one, but it's worth
  93. mentioning that controls have a special input method that only works
  94. when:
  95. - The mouse pointer is over the control.
  96. - The button was pressed over this control (control always
  97. captures input until button is released)
  98. - Control provides keyboard/joypad focus via
  99. :ref:`Control.focus_mode <class_Control_property_focus_mode>`.
  100. This function is
  101. :ref:`Control._gui_input() <class_Control_private_method__gui_input>`.
  102. To use it, override it in your control. No processing needs to be set.
  103. .. tabs::
  104. .. code-tab:: gdscript GDScript
  105. extends Control
  106. func _gui_input(event):
  107. if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
  108. print("Left mouse button was pressed!")
  109. .. code-tab:: csharp
  110. public override void _GuiInput(InputEvent @event)
  111. {
  112. if (@event is InputEventMouseButton mbe && mbe.ButtonIndex == MouseButton.Left && mbe.Pressed)
  113. {
  114. GD.Print("Left mouse button was pressed!");
  115. }
  116. }
  117. For more information about events themselves, check the :ref:`doc_inputevent`
  118. tutorial.
  119. Notifications
  120. ~~~~~~~~~~~~~
  121. Controls also have many useful notifications for which no dedicated callback
  122. exists, but which can be checked with the _notification callback:
  123. .. tabs::
  124. .. code-tab:: gdscript GDScript
  125. func _notification(what):
  126. match what:
  127. NOTIFICATION_MOUSE_ENTER:
  128. pass # Mouse entered the area of this control.
  129. NOTIFICATION_MOUSE_EXIT:
  130. pass # Mouse exited the area of this control.
  131. NOTIFICATION_FOCUS_ENTER:
  132. pass # Control gained focus.
  133. NOTIFICATION_FOCUS_EXIT:
  134. pass # Control lost focus.
  135. NOTIFICATION_THEME_CHANGED:
  136. pass # Theme used to draw the control changed;
  137. # update and redraw is recommended if using a theme.
  138. NOTIFICATION_VISIBILITY_CHANGED:
  139. pass # Control became visible/invisible;
  140. # check new status with is_visible().
  141. NOTIFICATION_RESIZED:
  142. pass # Control changed size; check new size
  143. # with get_size().
  144. NOTIFICATION_MODAL_CLOSE:
  145. pass # For modal pop-ups, notification
  146. # that the pop-up was closed.
  147. .. code-tab:: csharp
  148. public override void _Notification(int what)
  149. {
  150. switch (what)
  151. {
  152. case NotificationMouseEnter:
  153. // Mouse entered the area of this control.
  154. break;
  155. case NotificationMouseExit:
  156. // Mouse exited the area of this control.
  157. break;
  158. case NotificationFocusEnter:
  159. // Control gained focus.
  160. break;
  161. case NotificationFocusExit:
  162. // Control lost focus.
  163. break;
  164. case NotificationThemeChanged:
  165. // Theme used to draw the control changed;
  166. // update and redraw is recommended if using a theme.
  167. break;
  168. case NotificationVisibilityChanged:
  169. // Control became visible/invisible;
  170. // check new status with is_visible().
  171. break;
  172. case NotificationResized:
  173. // Control changed size; check new size with get_size().
  174. break;
  175. case NotificationModalClose:
  176. // For modal pop-ups, notification that the pop-up was closed.
  177. break;
  178. }
  179. }