概述
在一些情况下我们可能需要使用鼠标控制对一个图形或对象(如控件)进行旋转。
通过如下图的分析:
我们可以知道:
- 我们只需要求出对象(如控件)中心点C到鼠标点击的位置start的向量与中心点C到鼠标移动后的位置start的向量之间的夹角θ
- 然后将这个角度加到对象(如控件)的rotation属性上就可以了。
测试
原理清楚,实践开始。我们创建一个如下的UI场景:
为Control节点添加如下代码:
extends Control
@export var border_color = Color.YELLOW_GREEN
@export var border_width = 2
var rect = get_draw_safety_rect()
func _draw():
# 绘制边框和对角线
draw_rect(rect,border_color,false,border_width)
draw_line(rect.position,rect.position+rect.size,border_color,border_width)
draw_line(rect.position+Vector2(rect.size.x,0),rect.position++Vector2(0,rect.size.y),border_color,border_width)
# 获取绘制函数能正确使用的控件Rect2
func get_draw_safety_rect() -> Rect2:
var rect = get_rect()
return Rect2(rect.position - position,rect.size/scale)
它主要是绘制出控件的矩形边界,并绘制出对角线:
为根节点添加如下代码:
extends Control
@onready var control = $Control
@export var line_color = Color.YELLOW # 辅助线颜色
var can_rotate:bool # 是否处于旋转状态
var start_vector:Vector2 # 起始向量
var line:Array[Vector2] = [] # 记录辅助线
func _input(event):
# 鼠标左键
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT:
if event.is_pressed(): # 按下
# 开启旋转状态
can_rotate = true
# 计算和记录初始控件中心到鼠标位置的向量
var pos = event.position
var c = control.position + control.pivot_offset
start_vector = pos - c
# 构造控件中心到鼠标位置的线段
line.clear()
line.append(c)
line.append(pos)
# 申请重绘
queue_redraw()
else: # 松开
# 关闭旋转状态
can_rotate = false
# 申请重绘
queue_redraw()
# 鼠标移动
if event is InputEventMouseMotion:
# 如果是可旋转状态
if can_rotate:
# 计算和新的控件中心到鼠标位置的向量
var pos = event.position
var c = control.position + control.pivot_offset
var end_vector:Vector2 = pos - c
# control跟随鼠标旋转
control.rotation += start_vector.angle_to(end_vector)
# 将新的向量记录到start_vector
start_vector = end_vector
# 构造新的控件中心到鼠标位置的线段
line.clear()
line.append(c)
line.append(pos)
# 申请重绘
queue_redraw()
func _draw():
# 绘制控件中心到鼠标位置的线段
if line.size()>0 and can_rotate:
draw_line(line[0],line[1],line_color,1)
注意:默认情况下Control类型的位置是从左上角顶点算起的,而且其旋转中心也位于左上角。
所以我们需要手动或代码形式将其旋转中心设定为其矩形范围的中心。
运行后就可以使用鼠标控制控件进行旋转。