diff --git a/project/aircraft/aircraft.gd b/project/aircraft/aircraft.gd index 090e0fe..5e01092 100644 --- a/project/aircraft/aircraft.gd +++ b/project/aircraft/aircraft.gd @@ -1,15 +1,18 @@ extends Node3D signal use_fallback(active: bool) +signal fog_density_changed(new_density: float) ## Rotation of cyclic stick model for full control deflection, in degrees @export var range_cyclic: float = 30 ## Main rotor speed, in revolutions per minute @export var rotor_rpm: float = 500 @export var track_platform: bool = false +@export var fog_values: Array[float] = [0.0, -1.0, -2.0, -3.0, -4.0] ## Current angle of rotor rotation var _rotor_azimuth: float = 0 +var fog_index: int = 0 @onready var connector: MarshConnector = $MarshConnector @onready var skeleton: Skeleton3D = $"Mi-2/Armature/Skeleton3D" @@ -65,6 +68,14 @@ func _process(delta: float) -> void: xr_origin.transform = tracker_mount.transform * tracker.transform.affine_inverse() recent_tracking.start() +func _input(event): + if event.is_action_pressed("fog_cycle"): + var step = 1 + if event is InputEventWithModifiers and event.shift_pressed: + step = -1 + # The index is updated in the signal callback to handle parameter changes + connector.fog_density = fog_values[(fog_index + step) % len(fog_values)] + # Only reset the position when tracking is lost for some time func _on_recent_tracking_timeout() -> void: xr_origin.transform = Transform3D.IDENTITY @@ -72,3 +83,14 @@ func _on_recent_tracking_timeout() -> void: func _on_vr_setup_failed() -> void: xr_camera.current = false use_fallback.emit(true) + +func _on_marsh_connector_fog_density_changed(new_density: float) -> void: + # Forward to parent + fog_density_changed.emit(new_density) + + # Round down to nearest defined value or assign the last one (so it will disable on next cycle) + # Example: -1.5 should select -2 and on next cycle it will be -3 + var new_index = fog_values.find_custom(func (d): return d <= new_density) + if new_index == -1: + new_index = len(fog_values) - 1 + fog_index = new_index diff --git a/project/aircraft/aircraft.tscn b/project/aircraft/aircraft.tscn index 9b65e24..edd497e 100644 --- a/project/aircraft/aircraft.tscn +++ b/project/aircraft/aircraft.tscn @@ -71,5 +71,6 @@ transform = Transform3D(-0.5, -1.27582e-08, 7.43353e-08, 4.33325e-10, 0.4923, 0. [connection signal="use_fallback" from="." to="AttitudeRoot/PilotEyes" method="_on_aircraft_use_fallback"] [connection signal="timeout" from="AttitudeRoot/PilotEyes/PilotFloor/XROrigin3D/RecentTracking" to="." method="_on_recent_tracking_timeout"] +[connection signal="fog_density_changed" from="MarshConnector" to="." method="_on_marsh_connector_fog_density_changed"] [editable path="Mi-2"] diff --git a/project/fog_controller.gd b/project/fog_controller.gd new file mode 100644 index 0000000..248abf7 --- /dev/null +++ b/project/fog_controller.gd @@ -0,0 +1,8 @@ +extends WorldEnvironment + +func _on_fog_density_changed(new_density: float) -> void: + if new_density == 0.0 or not is_finite(new_density): + environment.fog_enabled = false + else: + environment.fog_enabled = true + environment.fog_density = 10 ** new_density diff --git a/project/fog_controller.gd.uid b/project/fog_controller.gd.uid new file mode 100644 index 0000000..285eeb8 --- /dev/null +++ b/project/fog_controller.gd.uid @@ -0,0 +1 @@ +uid://6g3b2ohwbkyv diff --git a/project/main.tscn b/project/main.tscn index 1f92149..364a3b0 100644 --- a/project/main.tscn +++ b/project/main.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=7 format=3 uid="uid://crq3o0eu4y8ya"] +[gd_scene load_steps=8 format=3 uid="uid://crq3o0eu4y8ya"] [ext_resource type="Script" uid="uid://dfcjdxesyn3l0" path="res://start_vr.gd" id="1_ig7tw"] [ext_resource type="PackedScene" uid="uid://bj1s0g7ixjw71" path="res://aircraft/aircraft.tscn" id="2_0xm2m"] +[ext_resource type="Script" uid="uid://6g3b2ohwbkyv" path="res://fog_controller.gd" id="3_1bvp3"] [ext_resource type="PackedScene" uid="uid://bchcr54i3piaw" path="res://ads33-terrain/Cones_scene_terrain.tscn" id="3_h2yge"] [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_7dm0k"] @@ -12,6 +13,10 @@ sky_material = SubResource("ProceduralSkyMaterial_7dm0k") [sub_resource type="Environment" id="Environment_0xm2m"] background_mode = 2 sky = SubResource("Sky_ig7tw") +fog_enabled = true +fog_sun_scatter = 0.5 +fog_density = 0.0 +fog_depth_end = 80.0 [node name="Main" type="Node3D"] @@ -21,6 +26,7 @@ sky = SubResource("Sky_ig7tw") [node name="WorldEnvironment" type="WorldEnvironment" parent="."] environment = SubResource("Environment_0xm2m") +script = ExtResource("3_1bvp3") [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] transform = Transform3D(0.866025, 0.433013, 0.25, 0, -0.5, 0.866025, 0.5, -0.75, -0.433013, -5, 5, -5) @@ -29,4 +35,5 @@ shadow_enabled = true [node name="StartVR" type="Node3D" parent="."] script = ExtResource("1_ig7tw") +[connection signal="fog_density_changed" from="Aircraft" to="WorldEnvironment" method="_on_fog_density_changed"] [connection signal="setup_failed" from="StartVR" to="Aircraft" method="_on_vr_setup_failed"] diff --git a/project/project.godot b/project/project.godot index 8180d9a..5f7adb8 100644 --- a/project/project.godot +++ b/project/project.godot @@ -62,6 +62,11 @@ pov_reset={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":113,"location":0,"echo":false,"script":null) ] } +fog_cycle={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null) +] +} [physics] diff --git a/src/marshconnector.cpp b/src/marshconnector.cpp index 591cf11..00edf56 100644 --- a/src/marshconnector.cpp +++ b/src/marshconnector.cpp @@ -53,6 +53,15 @@ void MarshConnector::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "hostname"), "set_hostname", "get_hostname"); + ClassDB::bind_method(D_METHOD("get_fog_density"), + &MarshConnector::get_fog_density); + ClassDB::bind_method(D_METHOD("set_fog_density", "p_fog_density"), + &MarshConnector::set_fog_density); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_density"), "set_fog_density", + "get_fog_density"); + ADD_SIGNAL(MethodInfo("fog_density_changed", + PropertyInfo(Variant::FLOAT, "new_density"))); + // Timer callbacks ClassDB::bind_method(D_METHOD("send_heartbeat"), &MarshConnector::send_heartbeat); @@ -262,6 +271,17 @@ Vector4 MarshConnector::get_controls() { return last_controls; } Vector4 MarshConnector::get_trim() { return last_trim; } +float MarshConnector::get_fog_density() { return parameters[FOG_DENSITY]; } + +void MarshConnector::set_fog_density(float density) { + if (density == parameters[FOG_DENSITY]) + return; + + parameters[FOG_DENSITY] = density; + emit_signal("fog_density_changed", density); + send_param(FOG_DENSITY); +} + bool MarshConnector::get_manager_connected() { return manager_connected; } bool MarshConnector::get_model_connected() { return model_connected; } @@ -417,7 +437,11 @@ void MarshConnector::handle_param(mavlink_message_t message) { if (param_value.has_value()) { // TODO: Verify the value before updating - parameters[i] = *param_value; + if (i == FOG_DENSITY) { + set_fog_density(*param_value); + } else { + parameters[i] = *param_value; + } } send_param(Parameter{i}); } diff --git a/src/marshconnector.h b/src/marshconnector.h index c136cb9..2de3a7d 100644 --- a/src/marshconnector.h +++ b/src/marshconnector.h @@ -51,6 +51,10 @@ public: // Get normalized trim position Vector4 get_trim(); + // Get current fog density as set in the parameter + float get_fog_density(); + void set_fog_density(float value); + // Is there a connection to MARSH Manager bool get_manager_connected(); // Is receiving data from flight model @@ -94,7 +98,7 @@ private: // Not an enum class on purpose, to make use more convenient, it's scoped // inside the class namespace anyway enum Parameter : uint16_t { - // FOG_DENSITY, + FOG_DENSITY, NAV_OFS_HDG, NAV_OFS_X, NAV_OFS_Y, @@ -102,11 +106,10 @@ private: LOCAL_FRAME_LON, PARAM_COUNT, }; - float parameters[PARAM_COUNT] = {0.0, 0.0, 0.0, 0.0, 0.0}; + float parameters[PARAM_COUNT] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; const String parameter_names[PARAM_COUNT] = { - // "FOG_DENSITY", - "NAV_OFS_HDG", "NAV_OFS_X", "NAV_OFS_Y", - "LOCAL_FRAME_LAT", "LOCAL_FRAME_LON", + "FOG_DENSITY", "NAV_OFS_HDG", "NAV_OFS_X", + "NAV_OFS_Y", "LOCAL_FRAME_LAT", "LOCAL_FRAME_LON", }; Error send_param(Parameter index); Error subscribe_message(uint8_t manager_system, uint8_t manager_component,