small godot addon for gizmo creation
init
31 files changed, 772 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dceb116 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +* text=auto eol=lf + +/** export-ignore +/addons !export-ignore +/addons/** !export-ignore diff --git a/.github/image.png b/.github/image.png Binary files differnew file mode 100644 index 0000000..6010617 --- /dev/null +++ b/.github/image.png diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..16293bd --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.godot @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 bendn + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..4636bae --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# gizmo3d + +[](https://godotengine.org "Made with godot") +[](https://www.npmjs.com/package/@bendn/gizmo3d) +<a href='https://ko-fi.com/bendn' title='Buy me a coffee' target='_blank'><img height='28' src='https://storage.ko-fi.com/cdn/brandasset/kofi_button_red.png' alt='Buy me a coffee'> </a> + +Smalll addon for gizmo creation. + +[](_blank "Picture!") + +## Usage + +See [test.gd](https://raw.githubusercontent.com/bend-n/gizmo3d/main/test.gd) for a usage example. + +## Installation + +See [gpm#using-packages](https://github.com/godot-package-manager#using-packages-quickstart). diff --git a/addons/@bendn/LICENSE b/addons/@bendn/LICENSE new file mode 100644 index 0000000..1fafc15 --- /dev/null +++ b/addons/@bendn/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 bendn + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/addons/@bendn/gizmo3d/README.md b/addons/@bendn/gizmo3d/README.md new file mode 100644 index 0000000..45ab827 --- /dev/null +++ b/addons/@bendn/gizmo3d/README.md @@ -0,0 +1,16 @@ +# gizmo3d + +[](https://godotengine.org "Made with godot") +<a href='https://ko-fi.com/bendn' title='Buy me a coffee' target='_blank'><img height='28' src='https://storage.ko-fi.com/cdn/brandasset/kofi_button_red.png' alt='Buy me a coffee'> </a> + +Smalll addon for gizmo creation. + +[](_blank "Picture!") + +## Usage + +See [test.gd](https://raw.githubusercontent.com/bend-n/gizmo3d/main/test.gd) for a usage example. + +## Installation + +See [gpm#using-packages](https://github.com/godot-package-manager#using-packages-quickstart). diff --git a/addons/@bendn/gizmo3d/center.tres b/addons/@bendn/gizmo3d/center.tres new file mode 100644 index 0000000..ac77ed2 --- /dev/null +++ b/addons/@bendn/gizmo3d/center.tres @@ -0,0 +1,6 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://boc66segplbdg"] + +[resource] +no_depth_test = true +shading_mode = 0 +albedo_color = Color(0.92549, 0.886275, 0, 1) diff --git a/addons/@bendn/gizmo3d/gizmo.gd b/addons/@bendn/gizmo3d/gizmo.gd new file mode 100644 index 0000000..8bb4791 --- /dev/null +++ b/addons/@bendn/gizmo3d/gizmo.gd @@ -0,0 +1,36 @@ +extends Node3D +class_name Gizmo + +## A 3D Gizmo, doesn't directly move objects, instead emits signals. +## Thereby allowing you to do anything, including use the [UndoRedo] system, +## without being constrained by defaults. + +## Emitted when this gizmo is clicked. +signal clicked +## Gizmo was rotated by [param change]. +signal rotated(change: Vector3) +## Gizmo was translated by [param offset]. +signal displaced(offset: Vector3) +## Gizmo scaled by [param change]. +signal scaled(change: Vector3) +## Gizmo finished moving, lock it in. +signal finalize + +## I couldn't get [member BaseMaterial3D.fixed_size] to work soooo. +@export_exp_easing("attenuation") var scale_multiplier := 0.00011 + +@onready var _camera := get_viewport().get_camera_3d() + +func _physics_process(_delta: float) -> void: + _update_scale() + +func _update_scale(): + var distance := (_camera.global_position - global_position).length() + var size := distance * .00011 * _camera.fov + scale = size * Vector3.ONE + +func _ready() -> void: + _update_scale() + for c in get_children(): + if c.has_signal(&"clicked"): + c.clicked.connect(emit_signal.bind(&"clicked")) diff --git a/addons/@bendn/gizmo3d/package.json b/addons/@bendn/gizmo3d/package.json new file mode 100644 index 0000000..54266c7 --- /dev/null +++ b/addons/@bendn/gizmo3d/package.json @@ -0,0 +1,25 @@ +{ + "name": "@bendn/gizmo3d", + "version": "1.0.2", + "description": "small addon for gizmo creation", + "main": "gizmo.gd", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/bend-n/gizmo3d.git" + }, + "keywords": [ + "godot", + "godot-engine", + "3d", + "gizmo" + ], + "author": "bendn", + "license": "MIT", + "bugs": { + "url": "https://github.com/bend-n/gizmo3d/issues" + }, + "homepage": "https://github.com/bend-n/gizmo3d#readme" +} diff --git a/addons/@bendn/gizmo3d/rotation/rotation.gd b/addons/@bendn/gizmo3d/rotation/rotation.gd new file mode 100644 index 0000000..eda9f7a --- /dev/null +++ b/addons/@bendn/gizmo3d/rotation/rotation.gd @@ -0,0 +1,13 @@ +extends Gizmo +class_name RotationGizmo + +@export var rotate_cw: Shortcut +@export var rotate_ccw: Shortcut + +func _input(event: InputEvent) -> void: + if rotate_cw.matches_event(event) and event.is_pressed(): + rotated.emit(Vector3(0, PI/2, 0)) + finalize.emit() + elif rotate_ccw.matches_event(event) and event.is_pressed(): + rotated.emit(Vector3(0, -(PI/2), 0)) + finalize.emit() diff --git a/addons/@bendn/gizmo3d/rotation/rotation.tscn b/addons/@bendn/gizmo3d/rotation/rotation.tscn new file mode 100644 index 0000000..4f29f61 --- /dev/null +++ b/addons/@bendn/gizmo3d/rotation/rotation.tscn @@ -0,0 +1,65 @@ +[gd_scene load_steps=11 format=3 uid="uid://b5deeyfr2umhx"] + +[ext_resource type="Script" path="res://addons/@bendn/gizmo3d/rotation/rotation.gd" id="1_7laj6"] +[ext_resource type="TorusMesh" uid="uid://bw6rig250ekqw" path="res://addons/@bendn/gizmo3d/rotation/torus.tres" id="2_wpi22"] +[ext_resource type="Material" uid="uid://dc4qnnjootkhu" path="res://addons/@bendn/gizmo3d/y.tres" id="3_cf2qn"] +[ext_resource type="Shape3D" uid="uid://cai5e0kk8b0sq" path="res://addons/@bendn/gizmo3d/rotation/torus.shape" id="4_aoydv"] +[ext_resource type="Material" uid="uid://do26tijfu1ibj" path="res://addons/@bendn/gizmo3d/x.tres" id="5_ohutw"] +[ext_resource type="Material" uid="uid://btbrwby3db6t5" path="res://addons/@bendn/gizmo3d/z.tres" id="6_61do5"] + +[sub_resource type="InputEventKey" id="InputEventKey_3st8s"] +device = -1 +keycode = 82 +unicode = 114 + +[sub_resource type="Shortcut" id="Shortcut_jvc8g"] +events = [SubResource("InputEventKey_3st8s")] + +[sub_resource type="InputEventKey" id="InputEventKey_gor3q"] +device = -1 +shift_pressed = true +keycode = 82 +unicode = 82 + +[sub_resource type="Shortcut" id="Shortcut_0sfr4"] +events = [SubResource("InputEventKey_gor3q")] + +[node name="rotation" type="Node3D"] +script = ExtResource("1_7laj6") +rotate_cw = SubResource("Shortcut_jvc8g") +rotate_ccw = SubResource("Shortcut_0sfr4") + +[node name="Y" type="StaticBody3D" parent="."] + +[node name="mesh" type="MeshInstance3D" parent="Y"] +mesh = ExtResource("2_wpi22") +skeleton = NodePath("../..") +surface_material_override/0 = ExtResource("3_cf2qn") + +[node name="collider" type="CollisionShape3D" parent="Y"] +visible = false +shape = ExtResource("4_aoydv") + +[node name="X" type="StaticBody3D" parent="."] +transform = Transform3D(-4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0, 1, 0, 0, 0) + +[node name="mesh" type="MeshInstance3D" parent="X"] +mesh = ExtResource("2_wpi22") +skeleton = NodePath("../..") +surface_material_override/0 = ExtResource("5_ohutw") + +[node name="collider" type="CollisionShape3D" parent="X"] +visible = false +shape = ExtResource("4_aoydv") + +[node name="Z" type="StaticBody3D" parent="."] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0) + +[node name="mesh" type="MeshInstance3D" parent="Z"] +mesh = ExtResource("2_wpi22") +skeleton = NodePath("../..") +surface_material_override/0 = ExtResource("6_61do5") + +[node name="collider" type="CollisionShape3D" parent="Z"] +visible = false +shape = ExtResource("4_aoydv") diff --git a/addons/@bendn/gizmo3d/rotation/torus.shape b/addons/@bendn/gizmo3d/rotation/torus.shape Binary files differnew file mode 100644 index 0000000..2c7dbee --- /dev/null +++ b/addons/@bendn/gizmo3d/rotation/torus.shape diff --git a/addons/@bendn/gizmo3d/rotation/torus.tres b/addons/@bendn/gizmo3d/rotation/torus.tres new file mode 100644 index 0000000..3fa5889 --- /dev/null +++ b/addons/@bendn/gizmo3d/rotation/torus.tres @@ -0,0 +1,6 @@ +[gd_resource type="TorusMesh" format=3 uid="uid://bw6rig250ekqw"] + +[resource] +inner_radius = 14.0 +outer_radius = 15.0 +ring_segments = 8 diff --git a/addons/@bendn/gizmo3d/scale/box.tres b/addons/@bendn/gizmo3d/scale/box.tres new file mode 100644 index 0000000..76aab11 --- /dev/null +++ b/addons/@bendn/gizmo3d/scale/box.tres @@ -0,0 +1,4 @@ +[gd_resource type="BoxMesh" format=3 uid="uid://dqf33w5edcobv"] + +[resource] +size = Vector3(3, 3, 3) diff --git a/addons/@bendn/gizmo3d/scale/cylinder.tres b/addons/@bendn/gizmo3d/scale/cylinder.tres new file mode 100644 index 0000000..88f9e73 --- /dev/null +++ b/addons/@bendn/gizmo3d/scale/cylinder.tres @@ -0,0 +1,9 @@ +[gd_resource type="CylinderMesh" format=3 uid="uid://lc08lgqf086"] + +[resource] +top_radius = 1.0 +bottom_radius = 1.0 +height = 14.0 +radial_segments = 8 +cap_top = false +cap_bottom = false diff --git a/addons/@bendn/gizmo3d/scale/scale.tscn b/addons/@bendn/gizmo3d/scale/scale.tscn new file mode 100644 index 0000000..957fc54 --- /dev/null +++ b/addons/@bendn/gizmo3d/scale/scale.tscn @@ -0,0 +1,94 @@ +[gd_scene load_steps=11 format=3 uid="uid://bqcjdbse5n5lb"] + +[ext_resource type="Script" path="res://addons/@bendn/gizmo3d/gizmo.gd" id="1_ocjut"] +[ext_resource type="Script" path="res://addons/@bendn/gizmo3d/translate/handle.gd" id="2_dbfpj"] +[ext_resource type="CylinderMesh" uid="uid://lc08lgqf086" path="res://addons/@bendn/gizmo3d/scale/cylinder.tres" id="3_15ibc"] +[ext_resource type="Material" uid="uid://dc4qnnjootkhu" path="res://addons/@bendn/gizmo3d/y.tres" id="4_cm82e"] +[ext_resource type="BoxMesh" uid="uid://dqf33w5edcobv" path="res://addons/@bendn/gizmo3d/scale/box.tres" id="5_dsdp5"] +[ext_resource type="Shape3D" uid="uid://k6i72vyyvx5a" path="res://addons/@bendn/gizmo3d/translate/translate_arm.shape" id="6_d5tgp"] +[ext_resource type="Material" uid="uid://do26tijfu1ibj" path="res://addons/@bendn/gizmo3d/x.tres" id="7_n5pes"] +[ext_resource type="Material" uid="uid://btbrwby3db6t5" path="res://addons/@bendn/gizmo3d/z.tres" id="8_pk3gt"] +[ext_resource type="Material" uid="uid://boc66segplbdg" path="res://addons/@bendn/gizmo3d/center.tres" id="9_ka3tc"] + +[sub_resource type="SphereMesh" id="SphereMesh_qsd58"] +radius = 1.0 +height = 2.0 +radial_segments = 16 +rings = 8 + +[node name="scale" type="Node3D"] +transform = Transform3D(0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0) +script = ExtResource("1_ocjut") + +[node name="handle_y" type="StaticBody3D" parent="."] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 10, 0) +collision_layer = 1073741824 +collision_mask = 0 +script = ExtResource("2_dbfpj") +dir = 2 +mode = 1 + +[node name="cylinder" type="MeshInstance3D" parent="handle_y"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 1.31134e-07, 3) +mesh = ExtResource("3_15ibc") +surface_material_override/0 = ExtResource("4_cm82e") + +[node name="point" type="MeshInstance3D" parent="handle_y"] +transform = Transform3D(-1, -8.74228e-08, 3.82137e-15, 0, -4.37114e-08, -1, 8.74228e-08, -1, 4.37114e-08, 0, -2.84217e-14, -5) +mesh = ExtResource("5_dsdp5") +surface_material_override/0 = ExtResource("4_cm82e") + +[node name="collider" type="CollisionShape3D" parent="handle_y"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4.37114e-08, 1) +visible = false +shape = ExtResource("6_d5tgp") + +[node name="handle_x" type="StaticBody3D" parent="."] +transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 10, 0, 0) +collision_layer = 1073741824 +collision_mask = 0 +script = ExtResource("2_dbfpj") +dir = 0 +mode = 1 + +[node name="cylinder" type="MeshInstance3D" parent="handle_x"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 1.31134e-07, 0, -3) +mesh = ExtResource("3_15ibc") +surface_material_override/0 = ExtResource("7_n5pes") + +[node name="point" type="MeshInstance3D" parent="handle_x"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, -2.84217e-14, 0, 5) +mesh = ExtResource("5_dsdp5") +surface_material_override/0 = ExtResource("7_n5pes") + +[node name="collider" type="CollisionShape3D" parent="handle_x"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.37114e-08, 0, -1) +visible = false +shape = ExtResource("6_d5tgp") + +[node name="handle_z" type="StaticBody3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 10) +collision_layer = 1073741824 +collision_mask = 0 +script = ExtResource("2_dbfpj") +dir = 1 +mode = 1 + +[node name="cylinder" type="MeshInstance3D" parent="handle_z"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, -3) +mesh = ExtResource("3_15ibc") +surface_material_override/0 = ExtResource("8_pk3gt") + +[node name="point" type="MeshInstance3D" parent="handle_z"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 5) +mesh = ExtResource("5_dsdp5") +surface_material_override/0 = ExtResource("8_pk3gt") + +[node name="collider" type="CollisionShape3D" parent="handle_z"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -1) +visible = false +shape = ExtResource("6_d5tgp") + +[node name="center" type="MeshInstance3D" parent="."] +mesh = SubResource("SphereMesh_qsd58") +surface_material_override/0 = ExtResource("9_ka3tc") diff --git a/addons/@bendn/gizmo3d/selection_marker.gd b/addons/@bendn/gizmo3d/selection_marker.gd new file mode 100644 index 0000000..08b4e01 --- /dev/null +++ b/addons/@bendn/gizmo3d/selection_marker.gd @@ -0,0 +1,2 @@ +extends Gizmo +class_name SelectionMarker diff --git a/addons/@bendn/gizmo3d/selection_marker.tscn b/addons/@bendn/gizmo3d/selection_marker.tscn new file mode 100644 index 0000000..0ad4415 --- /dev/null +++ b/addons/@bendn/gizmo3d/selection_marker.tscn @@ -0,0 +1,13 @@ +[gd_scene load_steps=4 format=3] + +[ext_resource type="Material" uid="uid://boc66segplbdg" path="res://addons/@bendn/gizmo3d/center.tres" id="1_sojt7"] +[ext_resource type="Script" path="res://addons/@bendn/gizmo3d/selection_marker.gd" id="2_gai3n"] + +[sub_resource type="BoxMesh" id="BoxMesh_8slg5"] +size = Vector3(10, 10, 10) + +[node name="selection marker" type="MeshInstance3D"] +transform = Transform3D(0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0) +mesh = SubResource("BoxMesh_8slg5") +surface_material_override/0 = ExtResource("1_sojt7") +script = ExtResource("2_gai3n") diff --git a/addons/@bendn/gizmo3d/translate/center.gd b/addons/@bendn/gizmo3d/translate/center.gd new file mode 100644 index 0000000..db00bf6 --- /dev/null +++ b/addons/@bendn/gizmo3d/translate/center.gd @@ -0,0 +1,40 @@ +extends StaticBody3D +class_name TranslateGizmoCenter + +var dragged := false +var clicked_position := Vector3.ZERO +var click_plane: Plane + +signal clicked + +func _process(_delta: float): + if dragged and not Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): + dragged = false + owner.finalize.emit() + if dragged: + var cam := get_viewport().get_camera_3d() + var mp := get_viewport().get_mouse_position() + + var from := cam.project_ray_origin(mp) + var toward := cam.project_ray_normal(mp) + var intersection_of_movement_point = click_plane.intersects_ray(from, toward) + if intersection_of_movement_point == null: + # dont move if its exactly parallel to plane + return + var displacement: Vector3 = intersection_of_movement_point - clicked_position + owner.displaced.emit(displacement) + +func _ready() -> void: + input_event.connect(click) + +func click(camera: Camera3D, event: InputEvent, click_position: Vector3, _click_normal: Vector3, _shape_idx: int): + if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: + clicked.emit() + dragged = true + var mp := get_viewport().get_mouse_position() + var plane_normal := camera.project_ray_normal(mp).normalized() + var distance := Plane(plane_normal, 0).distance_to(click_position) + click_plane = Plane(plane_normal, distance) + + clicked_position = click_position + diff --git a/addons/@bendn/gizmo3d/translate/cylinder.tres b/addons/@bendn/gizmo3d/translate/cylinder.tres new file mode 100644 index 0000000..4dc8f04 --- /dev/null +++ b/addons/@bendn/gizmo3d/translate/cylinder.tres @@ -0,0 +1,8 @@ +[gd_resource type="CylinderMesh" format=3 uid="uid://c3hxlx3k1jmfb"] + +[resource] +top_radius = 1.0 +bottom_radius = 1.0 +height = 10.0 +radial_segments = 8 +cap_top = false diff --git a/addons/@bendn/gizmo3d/translate/handle.gd b/addons/@bendn/gizmo3d/translate/handle.gd new file mode 100644 index 0000000..3a1a1ff --- /dev/null +++ b/addons/@bendn/gizmo3d/translate/handle.gd @@ -0,0 +1,55 @@ +extends StaticBody3D +class_name TranslateGizmoHandle +# copied from https://github.com/TinyLegions/runtime-spatial-gizmos/ vaguely + +@export var dir: Direction = Direction.NONE +enum Direction { X, Z, Y, RELATIVE, NONE } # relative not implemented +var direction2vector := { Direction.X: Vector3.RIGHT, Direction.Y: Vector3.UP, Direction.Z: Vector3.BACK } +@onready var drag_direction: Vector3 = direction2vector[dir] + +var dragged := false +var clicked_position := Vector3.ZERO +var click_plane: Plane + +@onready var gizmo: Gizmo = owner +enum Mode { Translate, Scale } +@export var mode: Mode + +signal clicked + +func _process(_delta: float): + if dragged and not Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): + dragged = false + gizmo.finalize.emit() + if dragged: + var cam := get_viewport().get_camera_3d() + var mp := get_viewport().get_mouse_position() + + var from := cam.project_ray_origin(mp) + var toward := cam.project_ray_normal(mp) + var intersection_of_movement_point = click_plane.intersects_ray(from, toward) + if intersection_of_movement_point == null: + # dont move if its exactly parallel to plane + return + var dist = intersection_of_movement_point - clicked_position + var displacement: Vector3 = dist.project(drag_direction) + match mode: + Mode.Translate: + gizmo.displaced.emit(displacement) + Mode.Scale: + gizmo.scaled.emit(displacement) + +func _ready() -> void: + input_event.connect(click) + +func click(camera: Camera3D, event: InputEvent, click_position: Vector3, _click_normal: Vector3, _shape_idx: int): + if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: + clicked.emit() + dragged = true + var mp := get_viewport().get_mouse_position() + var vertical_vector = camera.project_ray_normal(mp).normalized().cross(drag_direction) + var plane_normal := drag_direction.cross(vertical_vector) + var distance := Plane(plane_normal, 0).distance_to(click_position) + click_plane = Plane(plane_normal, distance) + + clicked_position = click_position diff --git a/addons/@bendn/gizmo3d/translate/point.tres b/addons/@bendn/gizmo3d/translate/point.tres new file mode 100644 index 0000000..8e59ed2 --- /dev/null +++ b/addons/@bendn/gizmo3d/translate/point.tres @@ -0,0 +1,8 @@ +[gd_resource type="CylinderMesh" format=3 uid="uid://cd0844dj635dv"] + +[resource] +top_radius = 0.0 +bottom_radius = 2.0 +height = 3.0 +radial_segments = 16 +cap_top = false diff --git a/addons/@bendn/gizmo3d/translate/translate.tscn b/addons/@bendn/gizmo3d/translate/translate.tscn new file mode 100644 index 0000000..231e7cb --- /dev/null +++ b/addons/@bendn/gizmo3d/translate/translate.tscn @@ -0,0 +1,104 @@ +[gd_scene load_steps=13 format=3 uid="uid://d2recqdx4hj38"] + +[ext_resource type="Script" path="res://addons/@bendn/gizmo3d/gizmo.gd" id="1_e30nb"] +[ext_resource type="Script" path="res://addons/@bendn/gizmo3d/translate/center.gd" id="2_vs4q7"] +[ext_resource type="Material" uid="uid://boc66segplbdg" path="res://addons/@bendn/gizmo3d/center.tres" id="3_t3mv1"] +[ext_resource type="Script" path="res://addons/@bendn/gizmo3d/translate/handle.gd" id="4_3ja1b"] +[ext_resource type="CylinderMesh" uid="uid://c3hxlx3k1jmfb" path="res://addons/@bendn/gizmo3d/translate/cylinder.tres" id="5_tlymd"] +[ext_resource type="Material" uid="uid://dc4qnnjootkhu" path="res://addons/@bendn/gizmo3d/y.tres" id="6_ohmps"] +[ext_resource type="CylinderMesh" uid="uid://cd0844dj635dv" path="res://addons/@bendn/gizmo3d/translate/point.tres" id="7_j0wec"] +[ext_resource type="Shape3D" uid="uid://k6i72vyyvx5a" path="res://addons/@bendn/gizmo3d/translate/translate_arm.shape" id="8_upb4q"] +[ext_resource type="Material" uid="uid://do26tijfu1ibj" path="res://addons/@bendn/gizmo3d/x.tres" id="9_ivepe"] +[ext_resource type="Material" uid="uid://btbrwby3db6t5" path="res://addons/@bendn/gizmo3d/z.tres" id="10_4d87b"] + +[sub_resource type="BoxMesh" id="BoxMesh_rttof"] +size = Vector3(10, 10, 10) + +[sub_resource type="BoxShape3D" id="BoxShape3D_tep2a"] +size = Vector3(10, 10, 10) + +[node name="translate" type="Node3D"] +transform = Transform3D(0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0) +script = ExtResource("1_e30nb") + +[node name="center" type="StaticBody3D" parent="."] +collision_layer = 1073741824 +collision_mask = 0 +script = ExtResource("2_vs4q7") + +[node name="mesh" type="MeshInstance3D" parent="center"] +mesh = SubResource("BoxMesh_rttof") +skeleton = NodePath("../..") +surface_material_override/0 = ExtResource("3_t3mv1") + +[node name="collider" type="CollisionShape3D" parent="center"] +shape = SubResource("BoxShape3D_tep2a") + +[node name="handle_y" type="StaticBody3D" parent="."] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 10, 0) +collision_layer = 1073741824 +collision_mask = 0 +script = ExtResource("4_3ja1b") +dir = 2 + +[node name="cylinder" type="MeshInstance3D" parent="handle_y"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0) +mesh = ExtResource("5_tlymd") +skeleton = NodePath("../..") +surface_material_override/0 = ExtResource("6_ohmps") + +[node name="point" type="MeshInstance3D" parent="handle_y"] +transform = Transform3D(-1, -8.74228e-08, 3.82137e-15, 0, -4.37114e-08, -1, 8.74228e-08, -1, 4.37114e-08, 0, 0, -6) +mesh = ExtResource("7_j0wec") +skeleton = NodePath("../..") +surface_material_override/0 = ExtResource("6_ohmps") + +[node name="collider" type="CollisionShape3D" parent="handle_y"] +visible = false +shape = ExtResource("8_upb4q") + +[node name="handle_x" type="StaticBody3D" parent="."] +transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 10, 0, 0) +collision_layer = 1073741824 +collision_mask = 0 +script = ExtResource("4_3ja1b") +dir = 0 + +[node name="cylinder" type="MeshInstance3D" parent="handle_x"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0) +mesh = ExtResource("5_tlymd") +skeleton = NodePath("../..") +surface_material_override/0 = ExtResource("9_ivepe") + +[node name="point" type="MeshInstance3D" parent="handle_x"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 6) +mesh = ExtResource("7_j0wec") +skeleton = NodePath("../..") +surface_material_override/0 = ExtResource("9_ivepe") + +[node name="collider" type="CollisionShape3D" parent="handle_x"] +visible = false +shape = ExtResource("8_upb4q") + +[node name="handle_z" type="StaticBody3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 10) +collision_layer = 1073741824 +collision_mask = 0 +script = ExtResource("4_3ja1b") +dir = 1 + +[node name="cylinder" type="MeshInstance3D" parent="handle_z"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0) +mesh = ExtResource("5_tlymd") +skeleton = NodePath("../..") +surface_material_override/0 = ExtResource("10_4d87b") + +[node name="point" type="MeshInstance3D" parent="handle_z"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 6) +mesh = ExtResource("7_j0wec") +skeleton = NodePath("../..") +surface_material_override/0 = ExtResource("10_4d87b") + +[node name="collider" type="CollisionShape3D" parent="handle_z"] +visible = false +shape = ExtResource("8_upb4q") diff --git a/addons/@bendn/gizmo3d/translate/translate_arm.shape b/addons/@bendn/gizmo3d/translate/translate_arm.shape Binary files differnew file mode 100644 index 0000000..59b63d0 --- /dev/null +++ b/addons/@bendn/gizmo3d/translate/translate_arm.shape diff --git a/addons/@bendn/gizmo3d/x.tres b/addons/@bendn/gizmo3d/x.tres new file mode 100644 index 0000000..ef88641 --- /dev/null +++ b/addons/@bendn/gizmo3d/x.tres @@ -0,0 +1,7 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://do26tijfu1ibj"] + +[resource] +render_priority = 2 +no_depth_test = true +shading_mode = 0 +albedo_color = Color(0.980392, 0.239216, 0.403922, 1) diff --git a/addons/@bendn/gizmo3d/y.tres b/addons/@bendn/gizmo3d/y.tres new file mode 100644 index 0000000..9348031 --- /dev/null +++ b/addons/@bendn/gizmo3d/y.tres @@ -0,0 +1,6 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://dc4qnnjootkhu"] + +[resource] +no_depth_test = true +shading_mode = 0 +albedo_color = Color(0.666667, 0.917647, 0, 1) diff --git a/addons/@bendn/gizmo3d/z.tres b/addons/@bendn/gizmo3d/z.tres new file mode 100644 index 0000000..201bdc6 --- /dev/null +++ b/addons/@bendn/gizmo3d/z.tres @@ -0,0 +1,7 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://btbrwby3db6t5"] + +[resource] +render_priority = 1 +no_depth_test = true +shading_mode = 0 +albedo_color = Color(0.180392, 0.686275, 0.980392, 1) diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..d71750b --- /dev/null +++ b/project.godot @@ -0,0 +1,26 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="gizmo test" +run/main_scene="res://test.tscn" +config/features=PackedStringArray("4.1") + +[display] + +window/stretch/mode="viewport" +window/stretch/aspect="expand" +window/stretch/scale=2.0 + +[rendering] + +anti_aliasing/quality/msaa_3d=3 +anti_aliasing/quality/screen_space_aa=1 @@ -0,0 +1,67 @@ +extends Node3D + +var current: Gizmo +var gizmo_holder := Node3D.new() + +var original_gh_p: Vector3 +var original_positions: PackedVector3Array = [] +var original_rotations: PackedVector3Array = [] +var original_scales: PackedVector3Array = [] + +@export var target: Node3D +@export var gizmo: PackedScene +@onready var targets: Array[Node3D] = [target] + +func _ready() -> void: + add_child(gizmo_holder) + current = gizmo.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) + +func _position_gizmo_holder() -> void: + var sum := Vector3.ZERO + for node in targets: + sum += node.global_position + gizmo_holder.global_position = sum / len(targets) + +func _setup_originals() -> void: + original_positions.resize(len(targets)) + original_rotations.resize(len(targets)) + original_scales.resize(len(targets)) + for i in len(targets): + var n := targets[i] + original_positions[i] = n.global_position + original_rotations[i] = n.global_rotation + original_scales[i] = n.scale + original_gh_p = gizmo_holder.global_position + +func _gizmo_displace(offset: Vector3): + for i in len(targets): + targets[i].global_position = original_positions[i] + offset + gizmo_holder.global_position = original_gh_p + offset + +func _gizmo_scale(change: Vector3): + for i in len(targets): + var n := targets[i] + var scl := original_scales[i] + change + if scl.x <= 0 || scl.y <= 0: # no flipping allowed + scl = Vector3.ONE + n.scale = scl + +func _gizmo_rotate(change: Vector3): + for i in len(targets): + var n := targets[i] + n.global_rotation = original_rotations[i] + change + +func _gizmo_finalize(): + for i in len(targets): + var n := targets[i] + original_positions[i] = n.global_position + original_scales[i] = n.scale + original_rotations[i] = n.global_rotation + original_gh_p = gizmo_holder.global_position diff --git a/test.tscn b/test.tscn new file mode 100644 index 0000000..24fdde8 --- /dev/null +++ b/test.tscn @@ -0,0 +1,90 @@ +[gd_scene load_steps=12 format=3 uid="uid://rdw1tgxqv6l1"] + +[ext_resource type="Script" path="res://test.gd" id="1_yg00y"] +[ext_resource type="PackedScene" uid="uid://d2recqdx4hj38" path="res://addons/@bendn/gizmo3d/translate/translate.tscn" id="2_nyr7l"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_q35d8"] +albedo_color = Color(2, 1, 2, 1) + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_38wvv"] +albedo_color = Color(2, 3, 3, 1) + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_k2mgk"] +albedo_color = Color(1, 1.5, 1, 1) +roughness = 0.61 + +[sub_resource type="Gradient" id="Gradient_1n4v5"] +offsets = PackedFloat32Array(0.0962963, 0.762963) + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_og18u"] +gradient = SubResource("Gradient_1n4v5") + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_7o86r"] +sky_top_color = Color(0.266667, 0.454902, 0.698039, 1) +sky_horizon_color = Color(0.572549, 0.67451, 0.709804, 1) +ground_bottom_color = Color(0.572549, 0.67451, 0.709804, 1) +ground_horizon_color = Color(0.572549, 0.67451, 0.709804, 1) + +[sub_resource type="Sky" id="Sky_8nx2j"] +sky_material = SubResource("ProceduralSkyMaterial_7o86r") + +[sub_resource type="Environment" id="Environment_k6esw"] +background_mode = 2 +sky = SubResource("Sky_8nx2j") +ambient_light_source = 3 +ssao_intensity = 6.88 +ssao_power = 1.60766 +glow_enabled = true +glow_levels/2 = 3.6 +glow_levels/3 = 0.0 +volumetric_fog_enabled = true +volumetric_fog_density = 0.0184 +volumetric_fog_sky_affect = 0.263 +adjustment_enabled = true +adjustment_contrast = 1.1 +adjustment_saturation = 1.1 +adjustment_color_correction = SubResource("GradientTexture1D_og18u") + +[sub_resource type="CameraAttributesPractical" id="CameraAttributesPractical_iq4p8"] +dof_blur_far_enabled = true +dof_blur_far_distance = 64.44 + +[node name="test" type="Node3D" node_paths=PackedStringArray("target")] +script = ExtResource("1_yg00y") +target = NodePath("box") +gizmo = ExtResource("2_nyr7l") + +[node name="box" type="Node3D" parent="."] + +[node name="CSGBox3D" type="CSGBox3D" parent="box"] +transform = Transform3D(0.707107, 0.5, -0.5, -0.707107, 0.5, -0.5, 0, 0.707107, 0.707107, 0, 0, 0) +size = Vector3(10, 10, 10) +material = SubResource("StandardMaterial3D_q35d8") + +[node name="CSGBox3D2" type="CSGBox3D" parent="box"] +transform = Transform3D(1, 0, 0, 0, 0.707107, -0.707107, 0, 0.707107, 0.707107, 0, 0, 0) +size = Vector3(10, 10, 10) +material = SubResource("StandardMaterial3D_38wvv") + +[node name="CSGSphere3D" type="CSGSphere3D" parent="box"] +radius = 7.167 +radial_segments = 64 +rings = 32 +material = SubResource("StandardMaterial3D_k2mgk") + +[node name="cam" type="Camera3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 15.8429) + +[node name="sun" type="DirectionalLight3D" parent="."] +transform = Transform3D(-0.258819, -0.965926, 7.19671e-09, 0.482963, -0.129409, 0.866025, -0.836516, 0.224144, 0.5, 10, -2, 2) +light_energy = 0.5 +shadow_enabled = true +directional_shadow_blend_splits = true + +[node name="CSGBox3D" type="CSGBox3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -16, 0) +size = Vector3(500, 1, 500) + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_k6esw") +camera_attributes = SubResource("CameraAttributesPractical_iq4p8") |