| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- using UnityEngine;
- using UnityEngine.InputSystem;
- using System.Collections.Generic;
- public class SelectionManager : MonoBehaviour
- {
- [Header("Selection Settings")]
- public LayerMask selectableLayerMask = -1;
- public Material ghostMaterial;
- private Villager selectedVillager;
- private GameObject selectedObject;
- private Camera playerCamera;
- // Drag and Drop
- private bool isDragging = false;
- private GameObject dragGhost;
- private Vector3 dragStartPosition;
- public Villager SelectedVillager => selectedVillager;
- public GameObject SelectedObject => selectedObject;
- void Start()
- {
- playerCamera = Camera.main;
- if (playerCamera == null)
- playerCamera = FindObjectOfType<Camera>();
- }
- void Update()
- {
- HandleInput();
- HandleDragAndDrop();
- }
- void HandleInput()
- {
- // Left click - selection
- var mouse = Mouse.current;
- if (mouse.leftButton.wasPressedThisFrame)
- {
- HandleSelection();
- }
- // Right click - cancel/deselect
- if (mouse.rightButton.wasPressedThisFrame)
- {
- CancelCurrentAction();
- }
- }
- void HandleSelection()
- {
- if (Mouse.current == null || playerCamera == null) return;
- Ray ray = playerCamera.ScreenPointToRay(Mouse.current.position.ReadValue());
- RaycastHit hit;
- if (Physics.Raycast(ray, out hit, Mathf.Infinity, selectableLayerMask))
- {
- GameObject hitObject = hit.collider.gameObject;
- // Check if we hit a villager
- Villager villager = hitObject.GetComponent<Villager>();
- if (villager != null)
- {
- SelectVillager(villager);
- return;
- }
- // Check for other selectable objects
- ISelectable selectable = hitObject.GetComponent<ISelectable>();
- if (selectable != null)
- {
- SelectObject(hitObject);
- return;
- }
- // If we hit something else, check parent objects
- Transform parent = hitObject.transform.parent;
- while (parent != null)
- {
- villager = parent.GetComponent<Villager>();
- if (villager != null)
- {
- SelectVillager(villager);
- return;
- }
- selectable = parent.GetComponent<ISelectable>();
- if (selectable != null)
- {
- SelectObject(parent.gameObject);
- return;
- }
- parent = parent.parent;
- }
- }
- // If we didn't hit anything selectable, deselect
- DeselectAll();
- }
- void HandleDragAndDrop()
- {
- if (Mouse.current == null) return;
- var mouse = Mouse.current;
- // Start dragging
- if (selectedVillager != null && mouse.leftButton.wasPressedThisFrame && !isDragging)
- {
- StartDrag();
- }
- // Update drag
- if (isDragging)
- {
- UpdateDrag();
- }
- // End dragging
- if (isDragging && mouse.leftButton.wasReleasedThisFrame)
- {
- EndDrag();
- }
- }
- void StartDrag()
- {
- isDragging = true;
- dragStartPosition = selectedVillager.transform.position;
- // Create ghost object
- CreateDragGhost();
- }
- void UpdateDrag()
- {
- if (dragGhost != null)
- {
- // Move ghost to mouse position
- Ray ray = playerCamera.ScreenPointToRay(Mouse.current.position.ReadValue());
- if (Physics.Raycast(ray, out RaycastHit hit))
- {
- dragGhost.transform.position = hit.point + Vector3.up * 0.1f;
- }
- }
- }
- void EndDrag()
- {
- isDragging = false;
- if (dragGhost != null)
- {
- Vector3 dropPosition = dragGhost.transform.position;
- // Check what we're dropping on
- Ray ray = playerCamera.ScreenPointToRay(Mouse.current.position.ReadValue());
- if (Physics.Raycast(ray, out RaycastHit hit))
- {
- HandleDrop(hit.collider.gameObject, dropPosition);
- }
- DestroyDragGhost();
- }
- }
- void CreateDragGhost()
- {
- if (selectedVillager != null)
- {
- dragGhost = Instantiate(selectedVillager.gameObject);
- // Make it a ghost (semi-transparent, no collisions)
- Collider ghostCollider = dragGhost.GetComponent<Collider>();
- if (ghostCollider != null)
- ghostCollider.enabled = false;
- // Remove any scripts that might interfere
- Villager ghostVillager = dragGhost.GetComponent<Villager>();
- if (ghostVillager != null)
- Destroy(ghostVillager);
- // Apply ghost material
- Renderer ghostRenderer = dragGhost.GetComponent<Renderer>();
- if (ghostRenderer != null && ghostMaterial != null)
- {
- ghostRenderer.material = ghostMaterial;
- }
- else if (ghostRenderer != null)
- {
- Color ghostColor = ghostRenderer.material.color;
- ghostColor.a = 0.5f;
- ghostRenderer.material.color = ghostColor;
- }
- }
- }
- void DestroyDragGhost()
- {
- if (dragGhost != null)
- {
- Destroy(dragGhost);
- dragGhost = null;
- }
- }
- void HandleDrop(GameObject dropTarget, Vector3 dropPosition)
- {
- if (selectedVillager == null) return;
- VillagerManager villagerManager = GameManager.Instance.villagerManager;
- // Determine what to do based on drop target
- string targetTag = dropTarget.tag;
- JobType newJob = targetTag switch
- {
- "Tree" => JobType.Woodcutter,
- "Stone" => JobType.Stonecutter,
- "Farm" => JobType.Farmer,
- "TownHall" => JobType.None, // Unemployed - return to town hall
- _ => selectedVillager.currentJob // Keep current job if dropped on something else
- };
- if (newJob != selectedVillager.currentJob || (newJob != JobType.None && selectedVillager.targetWorkplace != dropTarget))
- {
- // Assign job and specific workplace
- villagerManager.AssignVillagerToSpecificWorkplace(selectedVillager, newJob, dropTarget);
- Debug.Log($"Assigned {selectedVillager.villagerName} to {newJob} at specific {dropTarget.name}");
- }
- }
- public void SelectVillager(Villager villager)
- {
- // Deselect previous
- DeselectAll();
- selectedVillager = villager;
- selectedObject = villager.gameObject;
- villager.SetSelected(true);
- Debug.Log($"SelectionManager: Selected villager: {villager.villagerName}");
- Debug.Log($"SelectionManager: OnVillagerSelected event triggered");
- }
- public void SelectObject(GameObject obj)
- {
- // Deselect previous
- DeselectAll();
- selectedObject = obj;
- ISelectable selectable = obj.GetComponent<ISelectable>();
- selectable?.OnSelected();
- Debug.Log($"Selected object: {obj.name}");
- }
- public void DeselectAll()
- {
- if (selectedVillager != null)
- {
- selectedVillager.SetSelected(false);
- selectedVillager = null;
- }
- if (selectedObject != null)
- {
- ISelectable selectable = selectedObject.GetComponent<ISelectable>();
- selectable?.OnDeselected();
- selectedObject = null;
- }
- // Cancel any ongoing drag
- if (isDragging)
- {
- isDragging = false;
- DestroyDragGhost();
- }
- }
- void CancelCurrentAction()
- {
- if (isDragging)
- {
- isDragging = false;
- DestroyDragGhost();
- }
- else
- {
- DeselectAll();
- }
- Debug.Log("Cancelled current action");
- }
- }
- // Interface for selectable objects
- public interface ISelectable
- {
- void OnSelected();
- void OnDeselected();
- }
|