WindowPanel.gd 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. @tool
  2. extends PanelContainer
  3. class_name WindowPanel
  4. #
  5. signal MoveFloatingWindowToTop
  6. #
  7. enum EdgeOrientation { NONE, RIGHT, BOTTOM_RIGHT, BOTTOM, BOTTOM_LEFT, LEFT, TOP_LEFT, TOP, TOP_RIGHT }
  8. #
  9. @export var blockActions : bool = false
  10. @export var saveOverlayState : bool = false
  11. @export var maxSize : Vector2 = Vector2(-1, -1)
  12. const edgeSize : int = 5
  13. const cornerSize : int = 15
  14. var clickPosition : Vector2 = Vector2.INF
  15. var isResizing : bool = false
  16. var selectedEdge : EdgeOrientation = EdgeOrientation.NONE
  17. #
  18. func ClampFloatingWindow(globalPos : Vector2, moveLimit : Vector2):
  19. if selectedEdge == EdgeOrientation.BOTTOM_LEFT || selectedEdge == EdgeOrientation.LEFT || selectedEdge == EdgeOrientation.TOP_LEFT:
  20. moveLimit.x -= custom_minimum_size.x
  21. elif selectedEdge == EdgeOrientation.TOP_LEFT || selectedEdge == EdgeOrientation.TOP || selectedEdge == EdgeOrientation.TOP_RIGHT:
  22. moveLimit.y -= custom_minimum_size.y
  23. return Vector2( clampf(globalPos.x, 0.0, moveLimit.x), clampf(globalPos.y, 0.0, moveLimit.y))
  24. func ClampToMargin(marginSize : Vector2):
  25. if anchors_preset != LayoutPreset.PRESET_CENTER:
  26. position = ClampFloatingWindow(position, marginSize - size)
  27. func ResizeWindow(pos : Vector2, globalPos : Vector2):
  28. var rectSize = size
  29. var rectPos = position
  30. match selectedEdge:
  31. EdgeOrientation.RIGHT:
  32. rectSize.x = pos.x
  33. EdgeOrientation.BOTTOM_RIGHT:
  34. rectSize = pos
  35. EdgeOrientation.BOTTOM:
  36. rectSize.y = pos.y
  37. EdgeOrientation.BOTTOM_LEFT:
  38. rectSize.x -= globalPos.x - rectPos.x
  39. rectPos.x = globalPos.x
  40. rectSize.y = pos.y
  41. EdgeOrientation.LEFT:
  42. rectSize.x -= globalPos.x - rectPos.x
  43. rectPos.x = globalPos.x
  44. EdgeOrientation.TOP_LEFT:
  45. rectSize.x -= globalPos.x - rectPos.x
  46. rectPos.x = globalPos.x
  47. rectSize.y -= globalPos.y - rectPos.y
  48. rectPos.y = globalPos.y
  49. EdgeOrientation.TOP:
  50. rectSize.y -= globalPos.y - rectPos.y
  51. rectPos.y = globalPos.y
  52. EdgeOrientation.TOP_RIGHT:
  53. rectSize.y -= globalPos.y - rectPos.y
  54. rectPos.y = globalPos.y
  55. rectSize.x = pos.x
  56. if maxSize.x != -1:
  57. rectSize.x = clamp(rectSize.x, custom_minimum_size.x, maxSize.x)
  58. if maxSize.y != -1:
  59. rectSize.y = clamp(rectSize.y, custom_minimum_size.y, maxSize.y)
  60. if rectPos.x < 0:
  61. rectPos.x = 0
  62. if rectPos.y < 0:
  63. rectPos.y = 0
  64. size = rectSize
  65. position = rectPos
  66. func GetEdgeOrientation(pos : Vector2):
  67. var cornersArray = []
  68. var edgesArray = []
  69. if pos.y >= size.y - cornerSize:
  70. cornersArray.append(EdgeOrientation.BOTTOM)
  71. if pos.y >= size.y - edgeSize:
  72. edgesArray.append(EdgeOrientation.BOTTOM)
  73. elif pos.y <= cornerSize:
  74. cornersArray.append(EdgeOrientation.TOP)
  75. if pos.y <= edgeSize:
  76. edgesArray.append(EdgeOrientation.TOP)
  77. if pos.x >= size.x - cornerSize:
  78. cornersArray.append(EdgeOrientation.RIGHT)
  79. if pos.x >= size.x - edgeSize:
  80. edgesArray.append(EdgeOrientation.RIGHT)
  81. elif pos.x <= cornerSize:
  82. cornersArray.append(EdgeOrientation.LEFT)
  83. if pos.x <= edgeSize:
  84. edgesArray.append(EdgeOrientation.LEFT)
  85. if cornersArray.size() >= 2 && edgesArray.size() >= 1:
  86. match cornersArray[1]:
  87. EdgeOrientation.LEFT:
  88. match cornersArray[0]:
  89. EdgeOrientation.BOTTOM: selectedEdge = EdgeOrientation.BOTTOM_LEFT
  90. EdgeOrientation.TOP: selectedEdge = EdgeOrientation.TOP_LEFT
  91. EdgeOrientation.RIGHT:
  92. match cornersArray[0]:
  93. EdgeOrientation.BOTTOM: selectedEdge = EdgeOrientation.BOTTOM_RIGHT
  94. EdgeOrientation.TOP: selectedEdge = EdgeOrientation.TOP_RIGHT
  95. elif edgesArray.size() >= 1:
  96. selectedEdge = edgesArray[0]
  97. isResizing = selectedEdge != EdgeOrientation.NONE
  98. func ResetWindowModifier():
  99. clickPosition = Vector2.INF
  100. isResizing = false
  101. selectedEdge = EdgeOrientation.NONE
  102. func ToggleControl():
  103. EnableControl(!is_visible())
  104. func EnableControl(state : bool):
  105. set_visible(state)
  106. if state:
  107. SetFloatingWindowToTop()
  108. if Launcher.Action && blockActions:
  109. Launcher.Action.Enable(!state)
  110. func SetFloatingWindowToTop():
  111. set_draw_behind_parent(false)
  112. emit_signal('MoveFloatingWindowToTop', self)
  113. func CanBlockActions():
  114. return blockActions
  115. #
  116. func OnGuiInput(event : InputEvent):
  117. if event is InputEventMouseButton:
  118. var isInPanel = event.position >= Vector2.ZERO && event.position <= size
  119. if isInPanel:
  120. if event.pressed:
  121. clickPosition = event.position
  122. GetEdgeOrientation(event.position)
  123. SetFloatingWindowToTop()
  124. else:
  125. ResetWindowModifier()
  126. else:
  127. ResetWindowModifier()
  128. if event is InputEventMouseMotion:
  129. if clickPosition != Vector2.INF:
  130. UpdateWindow(event.position)
  131. func UpdateWindow(eventPosition : Vector2 = Vector2.ZERO):
  132. var floatingWindowSize : Vector2 = Launcher.GUI.windows.get_size()
  133. if isResizing:
  134. ResizeWindow(ClampFloatingWindow(eventPosition, floatingWindowSize), eventPosition + position)
  135. else:
  136. if clickPosition != Vector2.INF:
  137. position += eventPosition - clickPosition
  138. if get_minimum_size().x > 0 and get_minimum_size().y > 0:
  139. size.x = clamp(size.x, get_minimum_size().x, max(get_minimum_size().x, Launcher.GUI.windows.get_size().x))
  140. size.y = clamp(size.y, get_minimum_size().y, max(get_minimum_size().y, Launcher.GUI.windows.get_size().y))
  141. ClampToMargin(Launcher.GUI.windows.get_size())
  142. func Center():
  143. reset_size()
  144. global_position = get_viewport_rect().size / 2 - get_rect().size / 2
  145. #
  146. func _on_CloseButton_pressed():
  147. set_visible(false)