best way to realize zoom and scroll behavior like in editor

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By grol
:warning: Old Version Published before Godot 3 was released.

Hey there,

I am trying to to realize a zoom and scroll in my app that is similar to the zoom and scroll in the editor.

Is there an example abou that?

In my root node script i tried the following:

func _input(event):
if(event.is_pressed()):
	if(Input.is_key_pressed(KEY_ESCAPE)):
		get_tree().quit()

var zoom = get_node("camera").get_zoom()

if (event.type == InputEvent.MOUSE_BUTTON):
	if (event.button_index == BUTTON_WHEEL_UP):
		print("wheel up (event)")
		zoom[0] = zoom[0] + 1
		zoom[1] = zoom[1] + 1
	if (event.button_index == BUTTON_WHEEL_DOWN):
		print("wheel down (event)")
		zoom[0] = zoom[0] - 1
		zoom[1] = zoom[1] - 1

get_node("camera").set_zoom(zoom)

print (zoom)

But it is not working. The zoom is increasing but the camera is not zooming.
Any ideas on that?

:bust_in_silhouette: Reply From: puppetmaster-

Have you set Current to on in Camera2D?

It was set to Current but didnt work. But switching it on and off again solved it somehow.

Thanks!

grol | 2016-03-14 13:03

:bust_in_silhouette: Reply From: grol

Hey there,

Zooming runs great now. Had to implement some Limits to not get into the negative area.
For the drag & drop of the scene position I now have two approaches which are both somehow working.

One approach moves the Camera which causes some impreciseness concerning the relation between mouse, cam and scene position. I think this is caused by the zoom of the camera and the non linar relation between camera and scene position.

The other approach which might be the better one, moves the main node, but makes some problems withe the viewport or similar, which causes the scene to snap back the sceneposition when the mouse leaves a certain area.

Edit: It now works. Just had to disable current for the camera again.

Here is the script:

 
#Input handler, listen for ESC to exit app
func _input(event):
    if(event.is_pressed()):
	if(Input.is_key_pressed(KEY_ESCAPE)):
		get_tree().quit()

var zoom = get_node("camera").get_zoom()

if (event.type == InputEvent.MOUSE_MOTION):
	if(drag == true):
		# print(initPosMouse)
		var mouse_pos = get_global_mouse_pos()
		# var cam_pos = get_node("camera").get_pos()
		var dist_x
		var dist_y
		dist_x = initPosMouse.x - mouse_pos.x
		dist_y = initPosMouse.y - mouse_pos.y
		# var mx = cam_pos.x - (mouse_pos.x)
		# var my = cam_pos.y - (mouse_pos.y)
		var mx = initPosCam.x - (0 - dist_x)
		var my = initPosCam.y - (0 - dist_y)
		
		var nx = initPosNode.x - (0 + dist_x)
		var ny = initPosNode.y - (0 + dist_y)
		
		# get_node("camera").set_pos(Vector2(mx,my))
		get_node(".").set_pos(Vector2(nx,ny))
	elif(drag == false):
		# print("undrag")
		pass

	# get_node("camera").set_pos()

if (event.type == InputEvent.MOUSE_BUTTON):
	if (event.button_index == BUTTON_WHEEL_UP):
		# print("wheel up (event)")
		zoom[0] = zoom[0] + 0.25
		zoom[1] = zoom[1] + 0.25
	if (event.button_index == BUTTON_WHEEL_DOWN):
		# print("wheel down (event)")
		if(zoom[0] - 0.25 > 0 && zoom[1] - 0.25 > 0):
			zoom[0] = zoom[0] - 0.25
			zoom[1] = zoom[1] - 0.25
	if (event.button_index == BUTTON_MIDDLE):
		if(Input.is_mouse_button_pressed(3)):
			print("button middle")
			# print(get_viewport().get_mouse_pos())
			# var mouse_pos = get_global_mouse_pos()
			# initPos = get_viewport().get_mouse_pos()
			initPosMouse = get_global_mouse_pos()
			initPosCam = get_node("camera").get_pos()
			initPosNode = get_node(".").get_pos()
			drag = true
		else:
			print("button middle release")
			drag = false
	get_node("camera").set_zoom(zoom)
:bust_in_silhouette: Reply From: grol

Ok, one last problem. When disabling current in camera settings to get the drag and drop feature running, it breaks the zooming functionality.

I could now set the z of the main node, but seems not to work, maybe because its a 2d scene.

i tried like so: get_node(".").set_z(111)

The other option might be resize the whole main node.
But that sounds not really good. Any ideas?

:bust_in_silhouette: Reply From: grol

I solved it now completely. I hope.
Just made an other node which contains the whole scene which i want to drag and placed the camera outside.

var drag = false
var initPosCam = false
var initPosMouse = false
var initPosNode = false
#Input handler, listen for ESC to exit app
func _input(event):
if(event.is_pressed()):
	if(Input.is_key_pressed(KEY_ESCAPE)):
		get_tree().quit()

var zoom = get_node("camera").get_zoom()

if (event.type == InputEvent.MOUSE_MOTION):
	if(drag == true):
		
		var mouse_pos = get_global_mouse_pos()
		
		var dist_x = initPosMouse.x - mouse_pos.x
		var dist_y = initPosMouse.y - mouse_pos.y
		
		var nx = initPosNode.x - (0 + dist_x)
		var ny = initPosNode.y - (0 + dist_y)
		
		get_node("main").set_pos(Vector2(nx,ny))
		
	elif(drag == false):
		# print("undrag")
		pass

if (event.type == InputEvent.MOUSE_BUTTON):
	if (event.button_index == BUTTON_WHEEL_UP):
		# print("wheel up (event)")
		zoom[0] = zoom[0] + 0.25
		zoom[1] = zoom[1] + 0.25
	if (event.button_index == BUTTON_WHEEL_DOWN):
		# print("wheel down (event)")
		if(zoom[0] - 0.25 > 0 && zoom[1] - 0.25 > 0):
			zoom[0] = zoom[0] - 0.25
			zoom[1] = zoom[1] - 0.25
	if (event.button_index == BUTTON_MIDDLE):
		if(Input.is_mouse_button_pressed(3)):
			print("button middle")
			initPosMouse = get_global_mouse_pos()
			initPosNode = get_node("main").get_pos()
			drag = true
		else:
			print("button middle release")
			drag = false
	get_node("camera").set_zoom(zoom)