using System; using System.Collections; using System.Collections.Generic; using BITFALL.Placement; using BITFALL.Player.Movement; using BITKit; using BITKit.Entities; using BITKit.StateMachine; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Interactions; namespace BITFALL.Player.Equip { public interface IPlacementState:IState{} public sealed class PlacementController : BITEquipBase { [SerializeField] private Material material; [SerializeField] private LayerMask layerMask; [Header(Constant.Header.Input)] [SerializeField] private InputActionReference craftAction; [SerializeField] private InputActionReference snapAction; [Inject] private IEntityMovement _movement; [Inject] private IPlayerEquipSelector _equipSelector; private readonly Optional allowCraft = new(); private ScriptablePlacement ScriptablePlacement=>Item.GetAssetable() as ScriptablePlacement; private bool _snap; public override bool IsSupportItem(IBasicItem item) { if (item is null) return false; var assetable = item.GetAssetable(); return assetable is IPlacementObject; } public override void Entry() { base.Entry(); inputActionGroup.RegisterCallback(craftAction, OnCraft); inputActionGroup.RegisterCallback(snapAction, OnSnap); } private void OnSnap(InputAction.CallbackContext obj) { if(obj.interaction is not PressInteraction) return; _snap = obj.performed; } public override void Exit() { base.Exit(); inputActionGroup.UnRegisterCallback(craftAction, OnCraft); inputActionGroup.UnRegisterCallback(snapAction, OnSnap); } private void OnCraft(InputAction.CallbackContext obj) { if (BITAppForUnity.AllowCursor.Allow) return; if (obj is not { interaction: PressInteraction, performed: true }) return; if (!allowCraft.Allow) return; if (_inventory.Remove(Item)) { var instance = ScriptablePlacement.Clone() as UnityPlacementObject; instance!.transform.SetPositionAndRotation(allowCraft.Value, allowCraft.Value); if (instance.TryGetComponent(out var worldItemObject)) { worldItemObject.Item = Item; } } _equipSelector.Cancel(); } public override void OnUpdate(float deltaTime) { var startPosition = Camera.main.transform.position; var direction = Camera.main.transform.forward; var distance = 3.2f; var position = _movement.Position; var rotation = _movement.Rotation; // ReSharper disable once AssignmentInConditionalExpression if (allowCraft.Allow = Physics.Raycast(startPosition, direction, out var hit, distance, layerMask)) { position = hit.point; Debug.DrawLine(hit.point, hit.point + hit.normal, Color.magenta); rotation = _movement.Rotation * Quaternion.Euler(0, 180, 0); if (_snap) { position = hit.point + hit.normal * 0.32f; position = MathV.AlignToGrid(position, ScriptablePlacement.PositionIncrement); rotation = MathQ.AlignRotation(rotation, ScriptablePlacement.RotationIncrement); } foreach (var x in ScriptablePlacement.Object.As().GetComponentsInChildren()) { Graphics.DrawMesh(x.sharedMesh,position+rotation*x.transform.localPosition,rotation * x.transform.localRotation,material,LayerMask.NameToLayer("Default")); } allowCraft.Value = new Location(position, rotation); } else { Debug.DrawLine(startPosition, startPosition + direction * distance, Color.red); } } } }