1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
extends SubViewport
class_name EditorViewport
@onready var editor: TrackEditor = owner
const map = {
TrackEditor.Mode.Select: preload("res://addons/@bendn/gizmo3d/selection_marker.tscn"),
TrackEditor.Mode.Move: preload("res://addons/@bendn/gizmo3d/translate/translate.tscn"),
TrackEditor.Mode.Scale: preload("res://addons/@bendn/gizmo3d/scale/scale.tscn"),
TrackEditor.Mode.Rotate: preload("res://addons/@bendn/gizmo3d/rotation/rotation.tscn"),
}
var current: Gizmo
var gizmo_holder := Node3D.new()
var original_gh_p: Vector3
var original_scales: PackedVector3Array = []
var original_transforms: Array[Transform3D] = []
func _ready() -> void:
add_child(gizmo_holder)
func _position_gizmo_holder() -> void:
var sum := Vector3.ZERO
for block in editor.selected:
sum += block.live_node.global_position
gizmo_holder.global_position = sum / len(editor.selected)
func _setup_originals() -> void:
original_transforms.resize(len(editor.selected))
original_scales.resize(len(editor.selected))
for i in len(editor.selected):
var n := editor.selected[i].live_node
original_transforms[i] = n.global_transform
original_scales[i] = n.scale
original_gh_p = gizmo_holder.global_position
func update_gizmo(mode: TrackEditor.Mode) -> void:
if current != null:
current.queue_free()
current = null
original_transforms.clear()
original_scales.clear()
match mode:
_:
if editor.selected.size() == 0:
return
current = map[mode].instantiate()
_position_gizmo_holder()
gizmo_holder.add_child(current)
_setup_originals()
current.finalize.connect(_gizmo_finalize)
current.displaced.connect(_gizmo_displace)
current.scaled.connect(_gizmo_scale)
current.rotated.connect(_gizmo_rotate)
current.clicked.connect(%mousecast.gizmo_clicked)
func snap(v: Vector3, step: Vector3 = Globals.SNAP) -> Vector3:
return v.snapped(step) if editor.snapping else v
func _gizmo_displace(offset: Vector3):
const prop := &"global_position"
editor.history.create_action("move %d nodes" % editor.selected.size(), UndoRedo.MERGE_ENDS)
for i in len(editor.selected):
var n := editor.selected[i].live_node
editor.history.add_do_property(n, prop, snap(original_transforms[i].origin + offset))
editor.history.add_undo_property(n, prop, original_transforms[i].origin)
editor.history.add_do_property(gizmo_holder, prop, original_gh_p + snap(offset))
editor.history.add_undo_property(gizmo_holder, prop, original_gh_p)
editor.history.commit_action()
func _gizmo_scale(change: Vector3):
const prop := &"scale"
editor.history.create_action("scale %d nodes" % editor.selected.size(), UndoRedo.MERGE_ENDS)
for i in len(editor.selected):
var n := editor.selected[i].live_node
var scl := snap(original_scales[i] + change, Vector3.ONE)
if scl.x <= 0 || scl.y <= 0: # pls no flip
scl = Vector3.ONE
editor.history.add_do_property(n, prop, scl)
editor.history.add_undo_property(n, prop, original_scales[i])
editor.history.commit_action()
func _gizmo_rotate(change: Vector3):
const prop := &"global_transform"
editor.history.create_action("rotate %d nodes" % editor.selected.size(), UndoRedo.MERGE_ENDS)
for i in len(editor.selected):
var n := editor.selected[i].live_node
var rotation := Transform3D(Basis.from_euler(change), Vector3())
editor.history.add_do_property(
n,
prop,
(rotation * original_transforms[i].translated(-original_gh_p)).translated(original_gh_p)
)
editor.history.add_undo_property(n, prop, original_transforms[i])
editor.history.commit_action()
func _gizmo_finalize():
for i in len(editor.selected):
var n := editor.selected[i].live_node
original_scales[i] = n.scale
original_transforms[i] = n.global_transform
original_gh_p = gizmo_holder.global_position
func _on_remove_tobj() -> void:
if current != null:
current.queue_free()
current = null
|