I’m trying to scale an object given some mouse input (wheel up/down) and I’d like for the center point of the scaling action to be where the mouse is located on the object.
I tested this in the editor with fixed values, by moving the PivotOffset to the right of my 2d node, the scale attribute is correctly taking that point as scaling pivot.
Then I switched to doing the same thing in GDScript, I would:
if event.button_index == BUTTON_WHEEL_UP:
var pos = get_global_mouse_position()
pivot_offset = pos
scale += Vector2(0.1,0.1)
(and similar for the wheel down)
The whole thing seems to work, the object gets scaled, if I print the value of pivot_offset I can see it getting set to the mouse coordinates, but regardless, the scaling ignores the pivot’s new position and will always scale it up or down from the top-left corner.
there’s no pivot_offset property to change for Node2D nodes and its inherited nodes, so this is a Control node?
if it’s a Control node/its inherited, then it’s easily scale the Control Parent Node of this child. the child who you put in center of this control node will scale accordingly at center
So when the mouse pointer is -say- at [300,300] in global coordinates, that position corresponds to an out-of-screen position on the Control node.
I have to offset the mouse position by the top-left coordinate of the Control node and then the position of the cursor will match the underlying area of the Control.
The scaling works, but there’s something else I’m not getting.
Every time I scroll the wheel, before starting to scale, the Control suddenly jumps towards the cursor.
I thought this was a refresh issue with moving the pivot_offset inside an if statement, so I moved the offset outside of it:
func _input(event):
var pos = get_global_mouse_position()
control_node.pivot_offset = pos-position #convert global position to local relative to the Control
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
control_node.scale += Vector2(scale_factor,scale_factor)
if event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
control_node.scale -= Vector2(scale_factor,scale_factor)
And something odd happens.
I scale the Control up or down, no problem
now the Control is set to some scale
I start moving the mouse around, without touching any button or wheel, just moving the pointer
as per above code, this will shift the pivot to a different position and will ALSO move the Control ??
I’d like to attach a video capture, but I’m not allowed as I’m a new user
oki… I had to implement my own offset by hand, since the pivotOffset won’t be stable.
Here’s what I’m doing after making sure that the pivotOffset is at coordinate (0,0) of my Control node:
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
# first scale the Control up
control_node.scale += Vector2(scale_factor,scale_factor)
# compute the location of the Control node's center after resizing
var newCenter = (control_node.position + (Vector2(control_node.size)/2)) * scale_factor
# compute the vector from the new center to the mouse position
# this gives me the direction I should shift the whole Control node
# in order to have its center going towards the cursor
var direction_to_mouse = mouse_position - newCenter
#offset the control node position proportionally to the scale factor
control_node.position += direction_to_mouse*scale_factor
For the scale-down case (MOUSE_BUTTON_WHEEL_DOWN) I would just reverse the vector to the mouse position.
This gives me the correct behaviour while keeping pivot_offest at zero