diff --git a/asset_dev/hud_tools/sprayer.xcf b/asset_dev/hud_tools/sprayer.xcf
new file mode 100644
index 0000000..edac3a4
Binary files /dev/null and b/asset_dev/hud_tools/sprayer.xcf differ
diff --git a/assets/ui/hud/tools/point_sprayer.png b/assets/ui/hud/tools/point_sprayer.png
new file mode 100644
index 0000000..173da05
--- /dev/null
+++ b/assets/ui/hud/tools/point_sprayer.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d99d36cefa570f6c2b46ae3309a12cd002c3944beac351f55cc50e25b9d5889a
+size 1189
diff --git a/assets/ui/hud/tools/point_sprayer.png.import b/assets/ui/hud/tools/point_sprayer.png.import
new file mode 100644
index 0000000..0264fc0
--- /dev/null
+++ b/assets/ui/hud/tools/point_sprayer.png.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://brcxorcpe2g56"
+path="res://.godot/imported/point_sprayer.png-318d04609fd4015d1804430442998ec2.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/ui/hud/tools/point_sprayer.png"
+dest_files=["res://.godot/imported/point_sprayer.png-318d04609fd4015d1804430442998ec2.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/assets/ui/hud/tools/tall_sprayer.png b/assets/ui/hud/tools/tall_sprayer.png
new file mode 100644
index 0000000..ba4ee58
--- /dev/null
+++ b/assets/ui/hud/tools/tall_sprayer.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:83658aa38401bbccbb65271633228f5ecae1bfb1aadc8ca0cc1ef61afa1c7d81
+size 1259
diff --git a/assets/ui/hud/tools/tall_sprayer.png.import b/assets/ui/hud/tools/tall_sprayer.png.import
new file mode 100644
index 0000000..ad300f4
--- /dev/null
+++ b/assets/ui/hud/tools/tall_sprayer.png.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dmwey2qj77tm0"
+path="res://.godot/imported/tall_sprayer.png-afff96b79dd248903034c5c54431a377.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/ui/hud/tools/tall_sprayer.png"
+dest_files=["res://.godot/imported/tall_sprayer.png-afff96b79dd248903034c5c54431a377.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/assets/ui/hud/tools/wide_sprayer.png b/assets/ui/hud/tools/wide_sprayer.png
new file mode 100644
index 0000000..1bb7cd4
--- /dev/null
+++ b/assets/ui/hud/tools/wide_sprayer.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0b88955deadfbac0f760daec82c1cacaac9f52e03bb2e281a23a59f31eff01c1
+size 1219
diff --git a/assets/ui/hud/tools/wide_sprayer.png.import b/assets/ui/hud/tools/wide_sprayer.png.import
new file mode 100644
index 0000000..5e3be3c
--- /dev/null
+++ b/assets/ui/hud/tools/wide_sprayer.png.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dxjwpai3or1hw"
+path="res://.godot/imported/wide_sprayer.png-158adcbd34f972ea83f5b7ac10add881.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/ui/hud/tools/wide_sprayer.png"
+dest_files=["res://.godot/imported/wide_sprayer.png-158adcbd34f972ea83f5b7ac10add881.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/src/equipment/point_spray/point_spray.tscn b/src/equipment/point_spray/point_spray.tscn
index da47faa..af9e937 100644
--- a/src/equipment/point_spray/point_spray.tscn
+++ b/src/equipment/point_spray/point_spray.tscn
@@ -1,10 +1,12 @@
-[gd_scene load_steps=12 format=3 uid="uid://cc102xko0u6yj"]
+[gd_scene load_steps=14 format=3 uid="uid://cc102xko0u6yj"]
[ext_resource type="Script" uid="uid://dngia2ldbccv7" path="res://src/equipment/point_spray/point_spray.gd" id="1_2yl2v"]
[ext_resource type="Material" uid="uid://c00gndxoepuqh" path="res://assets/materials/laser_spray.tres" id="2_0pfy3"]
[ext_resource type="Texture2D" uid="uid://bn0gcsy37ahto" path="res://assets/ui/hud/reticle_large.png" id="2_qcl8j"]
[ext_resource type="PackedScene" uid="uid://b8vradbaw61ga" path="res://src/equipment/laser_cast/laser_cast.tscn" id="3_qmoff"]
[ext_resource type="Script" uid="uid://b274q7uvn0cvp" path="res://src/ui/rumbler_3d.gd" id="5_k4cg5"]
+[ext_resource type="Script" uid="uid://dj2x7x5qkbym1" path="res://src/ui/canvas_projector.gd" id="6_h2fjt"]
+[ext_resource type="Texture2D" uid="uid://brcxorcpe2g56" path="res://assets/ui/hud/tools/point_sprayer.png" id="6_otnek"]
[sub_resource type="CylinderMesh" id="CylinderMesh_j5thb"]
material = ExtResource("2_0pfy3")
@@ -61,7 +63,7 @@ parent_tool = NodePath("../..")
[node name="SprayEffect" type="MeshInstance3D" parent="Muzzle"]
unique_name_in_owner = true
-transform = Transform3D(1, 0, 0, 0, -4.47035e-08, -1, 0, 1, -4.47035e-08, 0, 0, -1)
+transform = Transform3D(1, 0, 0, 0, -4.47035e-08, -1, 0, 1, -4.47035e-08, 0, 0, -1.1)
layers = 2
sorting_offset = 3.0
mesh = SubResource("CylinderMesh_j5thb")
@@ -91,12 +93,39 @@ texture_albedo = ExtResource("2_qcl8j")
texture_emission = ExtResource("2_qcl8j")
cull_mask = 1048573
-[node name="Rumbler" type="Node3D" parent="."]
+[node name="HUDTool" type="Node3D" parent="."]
+unique_name_in_owner = true
+
+[node name="Rumbler" type="Node3D" parent="HUDTool"]
unique_name_in_owner = true
script = ExtResource("5_k4cg5")
-[node name="SprayNozzle" type="MeshInstance3D" parent="Rumbler"]
+[node name="SprayNozzle" type="MeshInstance3D" parent="HUDTool/Rumbler"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0)
+visible = false
layers = 2
mesh = SubResource("CapsuleMesh_k4cg5")
-skeleton = NodePath("../../..")
+skeleton = NodePath("../../../..")
+
+[node name="NozzleMarker" type="Marker3D" parent="HUDTool/Rumbler"]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.15)
+script = ExtResource("6_h2fjt")
+
+[node name="HUDElement" type="Control" parent="HUDTool/Rumbler/NozzleMarker"]
+layout_mode = 3
+anchors_preset = 8
+anchor_left = 0.5
+anchor_top = 0.5
+anchor_right = 0.5
+anchor_bottom = 0.5
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="NozzleTexture" type="TextureRect" parent="HUDTool/Rumbler/NozzleMarker/HUDElement"]
+texture_filter = 3
+offset_left = -256.0
+offset_top = -186.0
+offset_right = -192.0
+offset_bottom = -122.0
+scale = Vector2(10, 10)
+texture = ExtResource("6_otnek")
diff --git a/src/equipment/tool.gd b/src/equipment/tool.gd
index 0df1343..a1b7071 100644
--- a/src/equipment/tool.gd
+++ b/src/equipment/tool.gd
@@ -3,6 +3,10 @@ class_name Tool extends Node3D
var firing := false
+@onready var hud_tool: Node3D = %HUDTool
+
+@onready var _lagged_transform := global_transform
+
func _fire() -> void:
pass
@@ -28,3 +32,9 @@ func fire() -> void:
func idle() -> void:
firing = false
_idle()
+
+
+func _process(_delta: float) -> void:
+ if hud_tool:
+ hud_tool.global_transform = _lagged_transform
+ _lagged_transform = global_transform
diff --git a/src/equipment/wide_spray/wide_spray.tscn b/src/equipment/wide_spray/wide_spray.tscn
index e5714c9..be78f1c 100644
--- a/src/equipment/wide_spray/wide_spray.tscn
+++ b/src/equipment/wide_spray/wide_spray.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=17 format=3 uid="uid://d2hnxr5l6w2x4"]
+[gd_scene load_steps=20 format=3 uid="uid://d2hnxr5l6w2x4"]
[ext_resource type="Script" uid="uid://dv40fyim2g2fa" path="res://src/equipment/wide_spray/wide_spray.gd" id="1_ggkto"]
[ext_resource type="Material" uid="uid://c00gndxoepuqh" path="res://assets/materials/laser_spray.tres" id="2_26efp"]
@@ -7,6 +7,9 @@
[ext_resource type="Texture2D" uid="uid://carrggw6kp14w" path="res://assets/ui/hud/reticle_left.png" id="4_rotxf"]
[ext_resource type="Texture2D" uid="uid://wp03nuwt8hp5" path="res://assets/ui/hud/reticle_right.png" id="5_xo3vu"]
[ext_resource type="Script" uid="uid://b274q7uvn0cvp" path="res://src/ui/rumbler_3d.gd" id="7_ku0nd"]
+[ext_resource type="Script" uid="uid://dj2x7x5qkbym1" path="res://src/ui/canvas_projector.gd" id="8_j7ker"]
+[ext_resource type="Texture2D" uid="uid://dxjwpai3or1hw" path="res://assets/ui/hud/tools/wide_sprayer.png" id="9_8vo2h"]
+[ext_resource type="Texture2D" uid="uid://dmwey2qj77tm0" path="res://assets/ui/hud/tools/tall_sprayer.png" id="10_hv82w"]
[sub_resource type="CylinderMesh" id="CylinderMesh_48buk"]
material = ExtResource("2_26efp")
@@ -61,11 +64,47 @@ tracks/0/keys = {
"update": 0,
"values": [Vector3(0, 0, 0)]
}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("HUDTool:rotation")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Vector3(0, 0, 0)]
+}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("HUDTool/Rumbler/NozzleMarker/HUDElement/WideNozzle:visible")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [true]
+}
+tracks/3/type = "value"
+tracks/3/imported = false
+tracks/3/enabled = true
+tracks/3/path = NodePath("HUDTool/Rumbler/NozzleMarker/HUDElement/TallNozzle:visible")
+tracks/3/interp = 1
+tracks/3/loop_wrap = true
+tracks/3/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [false]
+}
[sub_resource type="Animation" id="Animation_ay2b7"]
resource_name = "rotate"
length = 0.1
-step = 0.0333
+step = 0.01
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
@@ -78,6 +117,42 @@ tracks/0/keys = {
"update": 0,
"values": [Vector3(0, 0, 0), Vector3(0, 0, 1.5708)]
}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("HUDTool:rotation")
+tracks/1/interp = 2
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0, 0.05, 0.1),
+"transitions": PackedFloat32Array(1, 1, 1),
+"update": 0,
+"values": [Vector3(0, 0, 0), Vector3(-1.5708, 0, 0), Vector3(0, 0, 0)]
+}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("HUDTool/Rumbler/NozzleMarker/HUDElement/WideNozzle:visible")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0, 0.04, 0.05, 0.1),
+"transitions": PackedFloat32Array(1, 1, 1, 1),
+"update": 1,
+"values": [true, true, false, false]
+}
+tracks/3/type = "value"
+tracks/3/imported = false
+tracks/3/enabled = true
+tracks/3/path = NodePath("HUDTool/Rumbler/NozzleMarker/HUDElement/TallNozzle:visible")
+tracks/3/interp = 1
+tracks/3/loop_wrap = true
+tracks/3/keys = {
+"times": PackedFloat32Array(0, 0.04, 0.05, 0.1),
+"transitions": PackedFloat32Array(1, 1, 1, 1),
+"update": 1,
+"values": [false, false, true, true]
+}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_fmqw2"]
_data = {
@@ -186,13 +261,50 @@ libraries = {
&"": SubResource("AnimationLibrary_fmqw2")
}
-[node name="Rumbler" type="Node3D" parent="."]
+[node name="HUDTool" type="Node3D" parent="."]
+unique_name_in_owner = true
+
+[node name="Rumbler" type="Node3D" parent="HUDTool"]
unique_name_in_owner = true
script = ExtResource("7_ku0nd")
-[node name="SprayNozzle" type="MeshInstance3D" parent="Rumbler"]
+[node name="SprayNozzle" type="MeshInstance3D" parent="HUDTool/Rumbler"]
+visible = false
layers = 2
mesh = SubResource("BoxMesh_fmqw2")
-skeleton = NodePath("../../..")
+skeleton = NodePath("../../../..")
+
+[node name="NozzleMarker" type="Marker3D" parent="HUDTool/Rumbler"]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.15)
+script = ExtResource("8_j7ker")
+
+[node name="HUDElement" type="Control" parent="HUDTool/Rumbler/NozzleMarker"]
+layout_mode = 3
+anchors_preset = 8
+anchor_left = 0.5
+anchor_top = 0.5
+anchor_right = 0.5
+anchor_bottom = 0.5
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="WideNozzle" type="TextureRect" parent="HUDTool/Rumbler/NozzleMarker/HUDElement"]
+texture_filter = 3
+offset_left = -256.0
+offset_top = -186.0
+offset_right = -192.0
+offset_bottom = -122.0
+scale = Vector2(10, 10)
+texture = ExtResource("9_8vo2h")
+
+[node name="TallNozzle" type="TextureRect" parent="HUDTool/Rumbler/NozzleMarker/HUDElement"]
+visible = false
+texture_filter = 3
+offset_left = -256.0
+offset_top = -186.0
+offset_right = -192.0
+offset_bottom = -122.0
+scale = Vector2(10, 10)
+texture = ExtResource("10_hv82w")
[connection signal="animation_finished" from="AnimationPlayer" to="." method="_on_animation_finished"]
diff --git a/src/ui/canvas_projector.gd b/src/ui/canvas_projector.gd
new file mode 100644
index 0000000..d1df335
--- /dev/null
+++ b/src/ui/canvas_projector.gd
@@ -0,0 +1,23 @@
+class_name CanvasProjector extends Node3D
+## 3D node which projects its children into 2D screen space.
+
+
+func _ready() -> void:
+ visibility_changed.connect(_on_visibility_changed)
+ _on_visibility_changed()
+
+
+func _process(_delta: float) -> void:
+ var camera := get_viewport().get_camera_3d()
+ var px_coord := camera.unproject_position(global_position)
+ for c: Node in get_children():
+ if c is Control:
+ (c as Control).global_position = px_coord
+ elif c is Node2D:
+ (c as Node2D).global_position = px_coord
+
+
+func _on_visibility_changed() -> void:
+ for c: Node in get_children():
+ if c is CanvasItem:
+ (c as CanvasItem).visible = is_visible_in_tree()
diff --git a/src/ui/canvas_projector.gd.uid b/src/ui/canvas_projector.gd.uid
new file mode 100644
index 0000000..78e05d0
--- /dev/null
+++ b/src/ui/canvas_projector.gd.uid
@@ -0,0 +1 @@
+uid://dj2x7x5qkbym1
diff --git a/vault/assets/color_palette.md b/vault/assets/color_palette.md
index 2b5b692..6de08c0 100644
--- a/vault/assets/color_palette.md
+++ b/vault/assets/color_palette.md
@@ -3,10 +3,12 @@
## Player Ship
(Color sampled from Metal Gear Solid)
-- `#050b10` Gunmetal Shadow SAMPLE
-- `#182124` Gunmetal Midtone 1 SAMPLE
-- `#212f35` Gunmetal Midtone 2 SAMPLE
-- `#70a5c1` Gunmetal Highlight SAMPLE
+- `#050b10` Gunmetal Shadow 1 SAMPLE
+- `#182124` Gunmetal Shadow 2 SAMPLE
+- `#212f35` Gunmetal Midtone 1 SAMPLE
+- `#9eadb4` Gunmetal Midtone 2 SAMPLE
+- `#d3e3e8` Gunmetal Highlight SAMPLE
+- `#70a5c1` Gunmetal Emission SAMPLE
- `#6586ab` Tech Emission Blue SAMPLE
## Grunk
@@ -23,6 +25,7 @@
- `#3c6b64` Tech Emissive Shadow SAMPLE
- `#60ae7b` Tech Emissive Midtone SAMPLE
- `#b6cf8e` Tech Emissive Highlight SAMPLE
+
## Props
- `#e8e1d1` Control White SAMPLE
- `#b4ac9e` Control Dark White SAMPLE