#nullable enable using Godot; using System; using System.Globalization; using System.IO; using System.Linq; using Godot.Collections; public partial class Main : Control { public static Random Random = Random.Shared; 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; [Export] private Gradient _gradient; private PlanetHelper.VertexData? _vertex = null; private PlanetHelper.PlateData? _plate = null; private int _resolution = 512; private PlanetHelper _planetHelper; [Export] private Curve _remapCurve; public override void _Ready() { _planetHelper = new PlanetHelper(_meshInstance, _textureRect, _remapCurve); UpdateStats(); Projector.GatherPoints(_planetHelper, int.Parse(GetNode("%Resolution").Text)); AxialTiltChanged(GetNode("%AxialTilt").Text); UpdateTime(); } Vector3 _pointerPosition = Vector3.Zero; private const float RayLength = 1000.0f; private bool _rotateable = false; public void MouseInViewport() { _rotateable = true; } public void MouseLeftViewport() { _rotateable = false; } public override void _Input(InputEvent @event) { if (@event is InputEventMouseButton mouseEvent) { if (mouseEvent.ButtonIndex == MouseButton.Left) { _moving = mouseEvent.Pressed && _rotateable; } 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, _resolution); _textureRect.Texture = Projector.Render(_planetHelper); } } public override void _Process(double delta) { if (Input.IsActionJustPressed("mouse_secondary")) { var from = _cameraNode.ProjectRayOrigin(_cameraNode.GetViewport().GetMousePosition()); var to = from + _cameraNode.ProjectRayNormal(_cameraNode.GetViewport().GetMousePosition()) * RayLength; var result = World.GetWorld3D().DirectSpaceState.IntersectRay(PhysicsRayQueryParameters3D.Create(from, to)); if (result.Count > 0) { Vector3 pos = result["position"].AsVector3(); GD.Print($"Hit: '{pos}'"); pos *= _meshInstance.Transform.Basis.Orthonormalized(); var closest = _planetHelper.Octree.SearchNearest(pos)?.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(); Vector3 vertexPos = _planetHelper.Mdt.GetVertex(_vertex.Id) * 0.01f; vertexPos *= _meshInstance.Transform.Basis.Inverse().Orthonormalized(); _pointerPosition = (Vector3)vertexPos + (vertexPos * (_vertex.Height + 0.01f) * 0.03f); // vertexPos * 1.01f; GetNode("%Pointer").GlobalPosition = _pointerPosition; UpdateTime(); } } } if (Input.IsActionJustPressed("spacebar")) { _planetHelper.Advance = true; } if (Input.IsActionJustPressed("enter")) { _planetHelper.AutoRun = true; } _planetHelper.Process(); if (_sunRotating) { _sunRotation = (double)(GetNode("%SunAngle").Value / 365.0); GetNode("%Sun").Rotation -= GetNode("%Sun").Rotation; GetNode("%Sun").Rotation += new Vector3(0, Mathf.DegToRad((float)_sunRotation * 360f), 0); UpdateTime(); } if (_planetRotating) { _planetRotation = (double)(GetNode("%PlanetAngle").Value / 24.0); _meshInstance.Rotation = Vector3.Zero; _meshInstance.RotateY((float)Mathf.DegToRad(_planetRotation * 360.0)); _meshInstance.RotateZ(Mathf.DegToRad(_axialTilt)); UpdateTime(); } } public void UpdateTime() { double hours = GetLocalTime(GetNode("%Pointer").GlobalPosition, GetNode("%Sun").GlobalTransform.Basis.Z, _meshInstance); GetNode