Dragging a RigidBody2D or CharacterBody2D while allowing it to rotate

Godot Version

4.7.1

Question

How can I make a RigidBody2D or a CharacterBody2D draggable by the player, but still rotate based on gravity?

Currently this is the code I have for dragging a RigidBody2D with a rectangular collision area, and with an Area2D child (for detecting clicks):

var button_clicked := false
var previous_mouse_position := Vector2(0.0, 0.0)


func _on_area_2d_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	var global_mouse_position := get_global_mouse_position()
	
	if event is InputEventMouseButton:
		button_clicked = event.pressed
		if event.pressed:
			previous_mouse_position = global_mouse_position


func _physics_process(_delta: float) -> void:
	var global_mouse_position := get_global_mouse_position()
	if button_clicked:
		position += global_mouse_position - previous_mouse_position
		previous_mouse_position = global_mouse_position

I can’t figure out a way to even get close to my goal.

How do I lock linear movement but not rotation?

How do I make the node rotate based on gravity and on the local mouse position (which would be the pivot)?

How do I keep the point (on the node) on which my mouse is clicking in the same global position, even though the rotation of the node should be constantly changing?

You should apply forces to the to the rigidbody2d towards the position of the click. Forces that nutralize gravity at the point of the grab and add forces of the mouse movement.

On a rigid body this is easy since it has apply force/impulse API that you can plug in the mouse position, tip use the standard equation to find the exact force , force = mass * acceleration ( f = ma ).

Maybe easier is to attach a physics joint (most likely a sping joint) to the rigid body to another invisible body (static, animatable) where the mouse is. That way you dont have to manage the forces yourself.

A character body will be harder because it does not have generic physics api but you can do something very similar you just need to write your own physics. My suggestion for easiest path is make all grabable objects as rigid bodies. Otherwise you will have to be creative or reinvent the wheel.

I found a Reddit post from 3 years ago by a person who made something very similar

They create a StaticBody2D and a PinJoint2D as its child, and move the StaticBody2D when the mouse moves