#nullable enable using Godot; using System; using System.Globalization; using System.Linq; using Godot.Collections; public partial class Main : Control { private bool _moving = false; [Export] private Node3D _yawNode; [Export] private Node3D _pitchNode; [Export] private Camera3D _cameraNode; [Export] private float _moveSensitivity = 1f/500f; [Export] private float _zoomSensitivity = 1f; [Export] private MeshInstance3D _meshInstance; [Export] private Node3D World; [Export] private TextureRect _textureRect; private PlanetHelper.VertexData? _vertex = null; private PlanetHelper.PlateData? _plate = null; private PlanetHelper _planetHelper; public override void _Ready() { _planetHelper = new PlanetHelper(_meshInstance, _textureRect); UpdateStats(); } private const float RayLength = 1000.0f; public override void _Input(InputEvent @event) { if (@event is InputEventMouseButton mouseEvent) { if (mouseEvent.ButtonIndex == MouseButton.Left) { _moving = mouseEvent.Pressed; } if (mouseEvent.ButtonIndex == MouseButton.WheelUp) { _cameraNode.Position += new Vector3(0, 0, _zoomSensitivity); } if (mouseEvent.ButtonIndex == MouseButton.WheelDown) { _cameraNode.Position -= new Vector3(0, 0, _zoomSensitivity); } } else if (@event is InputEventMouseMotion motionEvent && _moving) { _yawNode.RotateY(-motionEvent.ScreenRelative.X * _moveSensitivity); _pitchNode.RotateX(-motionEvent.ScreenRelative.Y * _moveSensitivity); } } public void Tab(int tab) { if (tab == 1) { Projector.GatherPoints(_planetHelper); _textureRect.Texture = Projector.Render(_planetHelper); } } public override void _Process(double delta) { if (Input.IsActionJustPressed("mouse_secondary")) { var from = _cameraNode.ProjectRayOrigin(GetViewport().GetMousePosition()); var to = from + _cameraNode.ProjectRayNormal(GetViewport().GetMousePosition()) * RayLength; var result = World.GetWorld3D().DirectSpaceState.IntersectRay(PhysicsRayQueryParameters3D.Create(from, to)); if (result.Count > 0) { Vector3? pos = result["position"].AsVector3(); if (pos != null) { GD.Print($"Hit: '{pos}'"); var closest = _planetHelper.Octree.SearchNearest(pos ?? Vector3.Zero)?.Id; if (closest != null) { _vertex = _planetHelper.Vertices.Single(v => v.Id == closest); if (_planetHelper.Plates.Count > 0 && _vertex.PlateId != -1) _plate = _planetHelper.Plates[_vertex.PlateId]; else _plate = null; UpdateStats(); } } } } if (Input.IsActionJustPressed("spacebar")) { _planetHelper.Advance = true; } if (Input.IsActionJustPressed("enter")) { _planetHelper.AutoRun = true; } _planetHelper.Process(); } public void UpdateStats() { if (_vertex != null) { var height = -9000f * (0.5f - _vertex.Height) * 2f; GetNode