Troche A quick and dirty custom implementation of rectangular Separating Axis Theorem should do the trick. It's been a while since I implemented one of those, so challenge accepted π
main.gd:
extends Node2D
func separate(window1, window2, bias = .5):
var r1 = window1.get_rect()
var r2 = window2.get_rect()
var ri = r1.intersection(r2)
if not ri.has_area():
return
var displace = Vector2.ZERO
var o1 = r1.end - r2.position
var o2 = r2.end - r1.position
if(ri.size.x < ri.size.y):
if abs(o1.x) < abs(o2.x):
displace.x += o1.x
else:
displace.x -= o2.x
else:
if abs(o1.y) < abs(o2.y):
displace.y += o1.y
else:
displace.y -= o2.y
window2.position += displace * bias
window1.position -= displace * (1-bias)
func _process(delta):
for w1 in get_children():
for w2 in get_children():
if w1 != w2:
var bias = .5
if w1.dragging:
bias = 1
elif w2.dragging:
bias = 0
separate(w1, w2, bias)
window.gd:
extends ColorRect
var dragging = false
func _gui_input(event):
if event is InputEventMouseButton:
if event.is_pressed():
dragging = true
modulate = Color(1.0, 0.0, 0.0, 1.0)
if event is InputEventMouseMotion and dragging:
position += event.relative
func _input(event):
if event is InputEventMouseButton and not event.is_pressed():
dragging = false
modulate = Color(1.0, 1.0, 1.0, 1.0)
Note that running it once cannot guarantee cascaded separation in very crowded situations. However we run it every frame and it eventually sorts itself out throughout several frames, which is mostly unnoticeable.
You homework is to adapt it for multiple dragging windows, and optimize for performance π