evert gist felülvizsgálása 4 days ago. Revízióhoz ugrás
1 file changed, 22 insertions, 20 deletions
gizmo.gd
| @@ -2,6 +2,7 @@ | |||
| 2 | 2 | extends EditorNode3DGizmoPlugin | |
| 3 | 3 | ||
| 4 | 4 | const ONE_VEC = Vector3(1.0, 1.0, 1.0) | |
| 5 | + | const MAX_DEFLECTION = 4096.0 | |
| 5 | 6 | ||
| 6 | 7 | var undo_redo: EditorUndoRedoManager | |
| 7 | 8 | ||
| @@ -19,24 +20,27 @@ var directions: Array[String] = [ | |||
| 19 | 20 | "+Y", "+Z", "+X", "-Y", "-Z", "-X" | |
| 20 | 21 | ] | |
| 21 | 22 | ||
| 23 | + | var visible = true | |
| 24 | + | ||
| 22 | 25 | var first_pos: Variant | |
| 23 | 26 | var first_scale: Vector3 | |
| 24 | 27 | var first_position: Vector3 | |
| 25 | - | var first_transform: Transform3D | |
| 28 | + | var first_global: Vector3 | |
| 26 | 29 | ||
| 27 | 30 | func _has_gizmo(node): | |
| 28 | 31 | return node is Node3D | |
| 29 | 32 | ||
| 30 | 33 | func _get_gizmo_name() -> String: | |
| 31 | - | return "Rodot gizmo" | |
| 34 | + | return "Rodot Resize" | |
| 32 | 35 | ||
| 33 | 36 | func _init(undo_redo: EditorUndoRedoManager): | |
| 34 | 37 | self.undo_redo = undo_redo | |
| 35 | 38 | create_handle_material("handles") | |
| 36 | 39 | ||
| 37 | - | func _redraw(gizmo): | |
| 40 | + | func _redraw(gizmo: EditorNode3DGizmo): | |
| 38 | 41 | gizmo.clear() | |
| 39 | - | gizmo.add_handles(handles, get_material("handles", gizmo), []) | |
| 42 | + | if visible: | |
| 43 | + | gizmo.add_handles(handles, get_material("handles", gizmo), []) | |
| 40 | 44 | ||
| 41 | 45 | func _get_handle_name(gizmo: EditorNode3DGizmo, handle_id: int, secondary: bool) -> String: | |
| 42 | 46 | return "Resize " + directions[handle_id] | |
| @@ -49,7 +53,7 @@ func _begin_handle_action(gizmo: EditorNode3DGizmo, handle_id: int, secondary: b | |||
| 49 | 53 | first_pos = null | |
| 50 | 54 | first_scale = node.scale | |
| 51 | 55 | first_position = node.position | |
| 52 | - | first_transform = Transform3D(node.transform) | |
| 56 | + | first_global = node.global_position | |
| 53 | 57 | ||
| 54 | 58 | func _commit_handle(gizmo: EditorNode3DGizmo, handle_id: int, secondary: bool, restore: Variant, cancel: bool) -> void: | |
| 55 | 59 | var node = gizmo.get_node_3d() | |
| @@ -69,10 +73,12 @@ func _commit_handle(gizmo: EditorNode3DGizmo, handle_id: int, secondary: bool, r | |||
| 69 | 73 | undo_redo.commit_action() | |
| 70 | 74 | ||
| 71 | 75 | func _update_node(node: Node3D, change: Vector3, axis: Vector3, minimum_deflection = 1.0) -> void: | |
| 76 | + | # Reset to default | |
| 77 | + | node.position = first_position | |
| 78 | + | node.scale = first_scale | |
| 79 | + | ||
| 72 | 80 | if change.length() == 0: | |
| 73 | - | # Reset to default, no size change | |
| 74 | - | node.position = first_position | |
| 75 | - | node.scale = first_scale | |
| 81 | + | # No size change | |
| 76 | 82 | return | |
| 77 | 83 | ||
| 78 | 84 | var axis_direction = sign(change.dot(axis)) | |
| @@ -93,8 +99,6 @@ func _update_node(node: Node3D, change: Vector3, axis: Vector3, minimum_deflecti | |||
| 93 | 99 | ||
| 94 | 100 | var pos_factor = ((apply_scale - ONE_VEC) / 2) * axis | |
| 95 | 101 | ||
| 96 | - | node.position = first_position | |
| 97 | - | node.scale = first_scale | |
| 98 | 102 | node.translate_object_local(pos_factor) | |
| 99 | 103 | node.scale_object_local(apply_scale) | |
| 100 | 104 | ||
| @@ -115,9 +119,12 @@ func _set_handle(gizmo: EditorNode3DGizmo, handle_id: int, secondary: bool, came | |||
| 115 | 119 | ||
| 116 | 120 | var offset := (m_pos - o_pos) * axis | |
| 117 | 121 | ||
| 118 | - | var scale_snap: float = EditorInterface.get_node_3d_translate_snap() | |
| 122 | + | var scale_snap: float = EditorInterface.get_node_3d_scale_snap() / 100.0 | |
| 119 | 123 | ||
| 120 | 124 | var handle_diff := offset.length() | |
| 125 | + | if is_nan(handle_diff) or is_inf(handle_diff) or handle_diff >= MAX_DEFLECTION: | |
| 126 | + | return | |
| 127 | + | ||
| 121 | 128 | var snap_diff = handle_diff | |
| 122 | 129 | ||
| 123 | 130 | if EditorInterface.is_node_3d_snap_enabled(): | |
| @@ -129,19 +136,14 @@ func _set_handle(gizmo: EditorNode3DGizmo, handle_id: int, secondary: bool, came | |||
| 129 | 136 | var handle_diff_vec = axis * snap_diff * handle_dir | |
| 130 | 137 | ||
| 131 | 138 | _update_node(node, handle_diff_vec, axis, scale_snap) | |
| 132 | - | ||
| 139 | + | ||
| 133 | 140 | node.update_gizmos() | |
| 134 | 141 | ||
| 135 | 142 | func _get_projected_pos(gizmo: EditorNode3DGizmo, handle_id: int, camera: Camera3D, screen_pos: Vector2) -> Variant: | |
| 136 | 143 | var node := gizmo.get_node_3d() | |
| 137 | - | var pos_vector = Vector3(0, node.global_position.y, 0) | |
| 138 | - | var plane = Plane(node.global_basis.y, pos_vector) | |
| 139 | - | if handle_id == 0 or handle_id == 3: | |
| 140 | - | pos_vector = Vector3(node.global_position.x, 0, node.global_position.z) | |
| 141 | - | plane = Plane(node.global_basis.z, pos_vector) | |
| 142 | - | ||
| 143 | 144 | var from := camera.project_ray_origin(screen_pos) | |
| 144 | - | var pos = plane.intersects_ray(from, camera.project_ray_normal(screen_pos) * 4096.0) | |
| 145 | 145 | ||
| 146 | - | return pos | |
| 146 | + | var plane = Plane(from, first_global) | |
| 147 | + | var pos = plane.intersects_ray(from, camera.project_ray_normal(screen_pos) * MAX_DEFLECTION) | |
| 147 | 148 | ||
| 149 | + | return pos | |
evert gist felülvizsgálása 5 days ago. Revízióhoz ugrás
1 file changed, 147 insertions
gizmo.gd(fájl létrehozva)
| @@ -0,0 +1,147 @@ | |||
| 1 | + | @tool | |
| 2 | + | extends EditorNode3DGizmoPlugin | |
| 3 | + | ||
| 4 | + | const ONE_VEC = Vector3(1.0, 1.0, 1.0) | |
| 5 | + | ||
| 6 | + | var undo_redo: EditorUndoRedoManager | |
| 7 | + | ||
| 8 | + | var handles: PackedVector3Array = [ | |
| 9 | + | Vector3.UP, | |
| 10 | + | -Vector3.FORWARD, | |
| 11 | + | Vector3.RIGHT, | |
| 12 | + | ||
| 13 | + | -Vector3.UP, | |
| 14 | + | Vector3.FORWARD, | |
| 15 | + | -Vector3.RIGHT | |
| 16 | + | ] | |
| 17 | + | ||
| 18 | + | var directions: Array[String] = [ | |
| 19 | + | "+Y", "+Z", "+X", "-Y", "-Z", "-X" | |
| 20 | + | ] | |
| 21 | + | ||
| 22 | + | var first_pos: Variant | |
| 23 | + | var first_scale: Vector3 | |
| 24 | + | var first_position: Vector3 | |
| 25 | + | var first_transform: Transform3D | |
| 26 | + | ||
| 27 | + | func _has_gizmo(node): | |
| 28 | + | return node is Node3D | |
| 29 | + | ||
| 30 | + | func _get_gizmo_name() -> String: | |
| 31 | + | return "Rodot gizmo" | |
| 32 | + | ||
| 33 | + | func _init(undo_redo: EditorUndoRedoManager): | |
| 34 | + | self.undo_redo = undo_redo | |
| 35 | + | create_handle_material("handles") | |
| 36 | + | ||
| 37 | + | func _redraw(gizmo): | |
| 38 | + | gizmo.clear() | |
| 39 | + | gizmo.add_handles(handles, get_material("handles", gizmo), []) | |
| 40 | + | ||
| 41 | + | func _get_handle_name(gizmo: EditorNode3DGizmo, handle_id: int, secondary: bool) -> String: | |
| 42 | + | return "Resize " + directions[handle_id] | |
| 43 | + | ||
| 44 | + | func _get_handle_value(gizmo: EditorNode3DGizmo, handle_id: int, secondary: bool) -> Variant: | |
| 45 | + | return handles[handle_id] | |
| 46 | + | ||
| 47 | + | func _begin_handle_action(gizmo: EditorNode3DGizmo, handle_id: int, secondary: bool) -> void: | |
| 48 | + | var node = gizmo.get_node_3d() | |
| 49 | + | first_pos = null | |
| 50 | + | first_scale = node.scale | |
| 51 | + | first_position = node.position | |
| 52 | + | first_transform = Transform3D(node.transform) | |
| 53 | + | ||
| 54 | + | func _commit_handle(gizmo: EditorNode3DGizmo, handle_id: int, secondary: bool, restore: Variant, cancel: bool) -> void: | |
| 55 | + | var node = gizmo.get_node_3d() | |
| 56 | + | if cancel: | |
| 57 | + | node.scale = first_scale | |
| 58 | + | node.position = first_position | |
| 59 | + | return | |
| 60 | + | ||
| 61 | + | if node.scale.is_equal_approx(first_scale) and node.position.is_equal_approx(first_position): | |
| 62 | + | return | |
| 63 | + | ||
| 64 | + | undo_redo.create_action("Resize Node3D") | |
| 65 | + | undo_redo.add_do_property(node, "position", node.position) | |
| 66 | + | undo_redo.add_undo_property(node, "position", first_position) | |
| 67 | + | undo_redo.add_do_property(node, "scale", node.scale) | |
| 68 | + | undo_redo.add_undo_property(node, "scale", first_scale) | |
| 69 | + | undo_redo.commit_action() | |
| 70 | + | ||
| 71 | + | func _update_node(node: Node3D, change: Vector3, axis: Vector3, minimum_deflection = 1.0) -> void: | |
| 72 | + | if change.length() == 0: | |
| 73 | + | # Reset to default, no size change | |
| 74 | + | node.position = first_position | |
| 75 | + | node.scale = first_scale | |
| 76 | + | return | |
| 77 | + | ||
| 78 | + | var axis_direction = sign(change.dot(axis)) | |
| 79 | + | var direction = axis_direction * sign(axis.dot(axis.abs())) | |
| 80 | + | var amount_to_add = change.length() * direction | |
| 81 | + | var current_scale = (first_scale * axis.abs()).length() | |
| 82 | + | ||
| 83 | + | # If user attempts to go negative or zero, force them back to the minimum amount | |
| 84 | + | var deflection = current_scale + amount_to_add | |
| 85 | + | if deflection < minimum_deflection: | |
| 86 | + | amount_to_add = amount_to_add - deflection + minimum_deflection | |
| 87 | + | ||
| 88 | + | var abs_axis: Vector3 = axis.abs() | |
| 89 | + | var scale_vec: Vector3 = ONE_VEC - abs_axis | |
| 90 | + | var factor: float = (current_scale + amount_to_add) / current_scale | |
| 91 | + | var axis_factor: Vector3 = abs_axis * factor | |
| 92 | + | var apply_scale: Vector3 = scale_vec + axis_factor | |
| 93 | + | ||
| 94 | + | var pos_factor = ((apply_scale - ONE_VEC) / 2) * axis | |
| 95 | + | ||
| 96 | + | node.position = first_position | |
| 97 | + | node.scale = first_scale | |
| 98 | + | node.translate_object_local(pos_factor) | |
| 99 | + | node.scale_object_local(apply_scale) | |
| 100 | + | ||
| 101 | + | func _set_handle(gizmo: EditorNode3DGizmo, handle_id: int, secondary: bool, camera: Camera3D, screen_pos: Vector2) -> void: | |
| 102 | + | var node := gizmo.get_node_3d() | |
| 103 | + | var pos = _get_projected_pos(gizmo, handle_id, camera, screen_pos) | |
| 104 | + | ||
| 105 | + | if not pos is Vector3: | |
| 106 | + | return | |
| 107 | + | ||
| 108 | + | if not first_pos: | |
| 109 | + | first_pos = pos | |
| 110 | + | return | |
| 111 | + | ||
| 112 | + | var o_pos := first_pos as Vector3 | |
| 113 | + | var m_pos := pos as Vector3 | |
| 114 | + | var axis := handles[handle_id] | |
| 115 | + | ||
| 116 | + | var offset := (m_pos - o_pos) * axis | |
| 117 | + | ||
| 118 | + | var scale_snap: float = EditorInterface.get_node_3d_translate_snap() | |
| 119 | + | ||
| 120 | + | var handle_diff := offset.length() | |
| 121 | + | var snap_diff = handle_diff | |
| 122 | + | ||
| 123 | + | if EditorInterface.is_node_3d_snap_enabled(): | |
| 124 | + | snap_diff = roundf(handle_diff / scale_snap) * scale_snap | |
| 125 | + | ||
| 126 | + | var handle_dot := offset.normalized().dot(axis) | |
| 127 | + | var handle_dir = sign(handle_dot) | |
| 128 | + | ||
| 129 | + | var handle_diff_vec = axis * snap_diff * handle_dir | |
| 130 | + | ||
| 131 | + | _update_node(node, handle_diff_vec, axis, scale_snap) | |
| 132 | + | ||
| 133 | + | node.update_gizmos() | |
| 134 | + | ||
| 135 | + | func _get_projected_pos(gizmo: EditorNode3DGizmo, handle_id: int, camera: Camera3D, screen_pos: Vector2) -> Variant: | |
| 136 | + | var node := gizmo.get_node_3d() | |
| 137 | + | var pos_vector = Vector3(0, node.global_position.y, 0) | |
| 138 | + | var plane = Plane(node.global_basis.y, pos_vector) | |
| 139 | + | if handle_id == 0 or handle_id == 3: | |
| 140 | + | pos_vector = Vector3(node.global_position.x, 0, node.global_position.z) | |
| 141 | + | plane = Plane(node.global_basis.z, pos_vector) | |
| 142 | + | ||
| 143 | + | var from := camera.project_ray_origin(screen_pos) | |
| 144 | + | var pos = plane.intersects_ray(from, camera.project_ray_normal(screen_pos) * 4096.0) | |
| 145 | + | ||
| 146 | + | return pos | |
| 147 | + | ||