Create Resizable Window

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Pyxus

Hi! Fairly new to godot and I’ve started experimenting with Control nodes. At the moment I’m attempting to create a Windows 10 style window to the best of my ability. I’m wondering how I would go about expanding and contracting the window with my mouse in game.

Basically what I want:
enter image description here
I was thinking if I could check if the mouse was colliding with a horizontal side / vertical side I could then change the size relative to the mouse, but I’m not sure how to do that beyond putting a node on each side and checking if the mouse entered. Also doubtful that’d be the best way to handle it.

Thanks in advance for any advice given!

Also, my node tree if relevant:
enter image description here

:bust_in_silhouette: Reply From: Pyxus

After two days of messing around I figured something out, seems to work fine though i’m not sure if this is the best way to achieve the resizing. If anyone is interested here is my code, hopefully, it will help you.

Also if anyone is willing to skim through my code and give me any advice that’d be great, could be as simple as some best practice advice. I’m coming from gamemaker studio and have no formal programming knowledge.

:bust_in_silhouette: Reply From: Gianclgar

I did it this way using a ColorRect node, and creating 4 child nodes that warn the parent when pressed. I don’t know if this is more or less efficient than your solution, but here’s the code in case it helps someone:

ColorRect script: (item you want to move, I think this would work with any node that uses rect_size and rect_position)

extends ColorRect

var clicked_pos
var rects_positions = []
var corn_clicked = false

func _ready():
	set_rectangles_positions()
	create_rectangles()


func _gui_input(event):
	if event is InputEventMouseButton:
		if event.pressed:
			clicked_pos = event.position
		else:
			clicked_pos = false
	if event is InputEventMouseMotion:
		if clicked_pos is Vector2:
			move()


func move():
	rect_position = get_global_mouse_position() - clicked_pos

func resize(corner): #triggered from children (squaret.gd)
	var to_size = rect_size
	var to_pos = rect_position
	match corner:
		0: #topleft
			to_pos = get_global_mouse_position() 
			to_size = rect_size - get_local_mouse_position()
		1: #topright
			to_pos.y = get_global_mouse_position().y
			to_size.y = rect_size.y - get_local_mouse_position().y
			to_size.x = get_local_mouse_position().x
		2: #botleft
			to_pos.x = get_global_mouse_position().x
			to_size.x = rect_size.x - get_local_mouse_position().x
			to_size.y = get_local_mouse_position().y
		3: #botright
			to_size = get_local_mouse_position()
	rect_size = to_size
	rect_position = to_pos
	set_rectangles_positions()
	update_rects_positions()

func set_rectangles_positions():
		rects_positions = [
		Vector2(-4, -4), #topleft
		Vector2(rect_size.x-6, -4), #topright
		Vector2(-4, rect_size.y-6), #botleft
		rect_size - Vector2(6, 6) #botright
	]

func create_rectangles():
	for i in 4:
		var newrect = ColorRect.new()
		newrect.rect_size = Vector2(10, 10)
		newrect.color = Color(0,0,0)
		newrect.rect_position = rects_positions[i]
		newrect.name = "squaret" + str(i)
		newrect.set_script(load("res://squaret.gd")) #attach the other script
		newrect.ind = i
		add_child(newrect, true)

func update_rects_positions():
	for item in get_children():
		if item is ColorRect:
			item.rect_position = rects_positions[item.ind]

squaret.gd script (script that gets attached to children squares when created):

extends ColorRect

var ind: int
var clicked = false

func _gui_input(event):
	if event is InputEventMouseButton:
		if event.pressed:
			clicked = true
		else:
			clicked = false
	if event is InputEventMouseMotion:
		if clicked:
			get_parent().resize(ind) #trigger resize function in parent

Maybe this could also be done by using a signal from childen nodes, but I found this cleaner. Performance-wise I don’t have any idea about what is better.