WindowPanel.gd 5.2 KB

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