using System; using Godot; using Godot.Collections; namespace Cirno.Scripts.Actors._3D; [Tool] public partial class Door3D : AnimatableBody3D, IActivable { [Export] public string GroupName { get; set; } [Export] public DoorState State { get; set; } = DoorState.Closed; [Signal] public delegate void OpeningEventHandler(); [Signal] public delegate void ClosingEventHandler(); [Signal] public delegate void SetClosedEventHandler(); [Signal] public delegate void SetOpenEventHandler(); // [Export] public AnimationPlayer AnimationPlayer { get; set; } // // [Export] public string OpenAnimationName { get; set; } = "Open"; // // [Export] public string CloseAnimationName { get; set; } = "Close"; // // [Export] public string OpenedAnimationName { get; set; } = "Opened"; // // [Export] public string ClosedAnimationName { get; set; } = "Closed"; private bool _isAnimating = false; private bool _isPlayerIncollider = false; private CollisionShape3D _collisionShape; public override void _Ready() { if (Engine.IsEditorHint()) return; if (!string.IsNullOrWhiteSpace(GroupName)) { this.AddToGroup(GroupName); } _collisionShape = GetNode("CollisionShape3D"); SyncAnimation(); // AnimationPlayer.AnimationFinished += AnimationPlayerOnAnimationFinished; } private void SyncAnimation() { if (State is DoorState.Closed) { EmitSignalSetClosed(); //AnimationPlayer.Play(ClosedAnimationName); } else { EmitSignalSetOpen(); //AnimationPlayer.Play(OpenedAnimationName); } } public void ClosedAnimationFinished() { State = DoorState.Closed; CallDeferred(MethodName.ToggleCollisionDeferred, true); _isAnimating = false; } public void OpenAnimationFinished() { State = DoorState.Open; CallDeferred(MethodName.ToggleCollisionDeferred, false); _isAnimating = false; } public void _func_godot_apply_properties(Dictionary props) { GroupName = (string)props["targetname"]; } public bool Activate(ActivationType activationType = ActivationType.Toggle) { if (_isAnimating) return false; switch (activationType) { case ActivationType.Toggle: case ActivationType.Use: if (State is DoorState.Open && _isPlayerIncollider) { return false; } Toggle(); break; case ActivationType.Enable: case ActivationType.Close: if (State is DoorState.Open && _isPlayerIncollider) { return false; } ChangeState(DoorState.Closed); break; case ActivationType.Disable: case ActivationType.Open: ChangeState(DoorState.Open); break; case ActivationType.Destroy: break; default: throw new ArgumentOutOfRangeException(nameof(activationType), activationType, null); } return true; } private void ChangeState(DoorState newState) { if (_isAnimating) return; if (State == newState) return; switch (newState) { case DoorState.Open: EmitSignalOpening(); break; case DoorState.Closed: EmitSignalClosing(); break; } //State = newState; _isAnimating = true; } private void ToggleCollisionDeferred(bool toggle) { _collisionShape.Disabled = !toggle; } public void Toggle() { if (_isAnimating) return; ChangeState(State is DoorState.Open ? DoorState.Closed : DoorState.Open); } public void OnPlayerDetected(Node3D body) { _isPlayerIncollider = true; // if (!_isAnimating) return; // if (State is DoorState.Open) // It means it's closing // { // AnimationPlayer.SetSpeedScale(-1); // } } public void OnPlayerUndetected(Node3D body) { _isPlayerIncollider = false; } // private bool IsPlayerInArea() // { // var spaceState = GetWorld3D().DirectSpaceState; // // var query = new PhysicsShapeQueryParameters3D() // { // CollideWithBodies = true, // // } // // // //query.CollideWithBodies = true; // } }