/// <summary> /// Ajoute un rail et le définit comme sélection actuelle /// </summary> /// <param name="railIndex">Index du prefab à ajouter, depuis la palette de rails</param> private GameObject AddRail(int railIndex) { // Récupération de la sélection actuelle GameObject selected = Selection.activeGameObject; Rail selectedRail = null; if (selected) { selectedRail = selected.GetComponent <Rail>(); // null si l'objet sélectionné n'est pas un rail if (!selectedRail) { // Recherche parmi les parents selectedRail = selected.GetComponentInParent <Rail>(); } if (selectedRail != null) { // Can be null RailAnchor anchor = selectedRail.GetAnchorForEndpoint(Rail.Endpoint.Default); return(AddRail(railIndex, selectedRail, anchor)); } } return(AddRail(railIndex, null, null)); }
/// <summary> /// Ajoute un rail au circuit /// TODO : éviter la redondance toRail = anchor.Parent /// </summary> /// <param name="prefab"></param> /// <param name="toRail"></param> /// <param name="anchor"></param> /// <returns></returns> public Rail AddRail(Rail prefab, Rail toRail = null, RailAnchor anchor = null) { // Vérification si on ajoute à un rail existant if (toRail != null && anchor != null) { // Si le rail possède déjà un rail à cet endroit if (!toRail.CanAppendRail(anchor)) { return(null); } } Rail newRail; #if UNITY_EDITOR newRail = PrefabUtility.InstantiatePrefab(prefab) as Rail; // TODO tester le cast #else newRail = Instantiate(prefab); #endif // Créé à la suite d'un rail existant if (toRail) { toRail.AppendRail(newRail, anchor); } // Créé au centre du circuit (par défaut) else { newRail.transform.parent = transform; newRail.transform.localPosition = Vector3.zero; } return(newRail); }
/// <summary> /// Quitte le mode édition depuis la SceneView /// Rétablit l'outil précédement sélectionné et détruit l'éventuel Gismo de rail /// </summary> private void ExitSceneEditing() { SceneView.duringSceneGui -= OnSceneGUI; DestroyRailHandle(); _focusedAnchor = null; Tools.current = _lastTool; }
/// <summary> /// Ajoute un rail au circuit /// </summary> /// <param name="prefab"></param> /// <param name="toRail"></param> /// <param name="point"></param> /// <returns></returns> public Rail AddRail(Rail prefab, Rail toRail, Rail.Endpoint point) { if (toRail != null) { RailAnchor anchor = toRail.GetAnchorForEndpoint(point); if (anchor != null) { return(AddRail(prefab, toRail, anchor)); } } return(AddRail(prefab, null, null)); }
/// <summary> /// Connecte le RailAnchor à un autre /// </summary> /// <param name="withAnchor"></param> /// <param name="notifyOther"></param> public void Connect(RailAnchor withAnchor, bool notifyOther = true) { if (notifyOther) { withAnchor.NotifyConnection(this); } #if UNITY_EDITOR // https://answers.unity.com/questions/155370/edit-an-object-in-unityeditor-editorwindow.html // Nécessaire d'utiliser SerializedObject pour conserver la valeur après un play var serializedAnchor = new SerializedObject(this); var connectionProp = serializedAnchor.FindProperty("Connection"); connectionProp.objectReferenceValue = withAnchor; serializedAnchor.ApplyModifiedProperties(); #else Connection = withAnchor; #endif }
/// <summary> /// Ajoute un rail et le définit comme sélection actuelle /// </summary> /// <param name="railIndex"></param> /// <param name="toRail"></param> /// <param name="anchor"></param> /// <returns></returns> public GameObject AddRail(int railIndex, Rail toRail, RailAnchor anchor) { // TODO : changer le type GameObject newRail = Circuit.AddRail(_railPalette[railIndex].GetComponent <Rail>(), toRail, anchor).gameObject; if (newRail) { // Sélectionne le nouveau rail GameObject[] newSelection = { newRail }; Selection.objects = newSelection; Undo.RegisterCreatedObjectUndo(newRail, "Add Rail"); return(newRail); } else { Debug.LogError("Impossible d'ajouter un rail à cet endroit"); return(null); } }
/// <summary> /// Gestion des évènements dans la SceneView /// </summary> /// <param name="sceneView">SceneView courante</param> private void OnSceneGUI(SceneView sceneView) { if (_addModeIndex == 1) { if (Event.current.type == EventType.MouseMove) { // ----------------------------------------------------------------------------------- // Détection de la proximité du curseur avec une extrémité de rail libre float lowestDistance = _maxDistanceSnap; RailAnchor previouslySelectedAnchor = _focusedAnchor; _focusedAnchor = null; foreach (Rail rail in Circuit.GetRails()) { foreach (RailAnchor anchor in rail.GetFreeConnections()) { Vector2 guiPosition = HandleUtility.WorldToGUIPoint(anchor.Position); float distance = Vector2.Distance(Event.current.mousePosition, guiPosition); if (distance < lowestDistance) { _focusedAnchor = anchor; lowestDistance = distance; } } } // ----------------------------------------------------------------------------------- // La sélection a changé if (previouslySelectedAnchor != _focusedAnchor) { // Changement de la sélection d'anchor if (_focusedAnchor != null) { if (_railHandle == null) { _railHandle = Instantiate(_railPalette[_selectedRailIndex]); } // Placement de ce rail selon l'anchor _railHandle.transform.parent = _editorGameObject.transform; _railHandle.GetComponent <Rail>().SetTransformFromAnchor(_focusedAnchor); } // On est sorti de la zone de sqélection, suppression du handle else { DestroyRailHandle(); } } // Consomme l'Event Event.current.Use(); } else if (Event.current.type == EventType.MouseDown) { // Un rail est prêt à être placé if (_railHandle && _focusedAnchor) { // à bouger ------- GameObject newRail = AddRail(_selectedRailIndex, _focusedAnchor.Parent, _focusedAnchor); if (newRail) { // Consomme l'Event Event.current.Use(); _consumeNextMouseUp = true; DestroyRailHandle(); } } } else if (Event.current.type == EventType.MouseUp) { if (_consumeNextMouseUp) { // Consomme l'Event Event.current.Use(); _consumeNextMouseUp = false; } } } }
// Update is called once per frame void Update() { // Initialisation de la caméra à l'ajout du premier rail if (!_cameraInitialized) { if (_circuitEditor.Circuit.RailsCount > 0) { ResetCamera(); _cameraInitialized = true; } } // Inputs \\ // Évènements à la souris restreint à l'extérieur de l'UI if (!EventSystem.current.IsPointerOverGameObject()) { Vector2 mousePos = Input.mousePosition; // Mouse move if (mousePos != _lastMousePos) { if (_circuitEditor.AddMode == CircuitEditor.AddingMode.Scene && !editorCamera.IsMovingView) { // ----------------------------------------------------------------------------------- // Détection de la proximité du curseur avec une extrémité de rail libre float lowestDistance = _maxDistanceSnap; RailAnchor previouslySelectedAnchor = _focusedAnchor; _focusedAnchor = null; foreach (Rail rail in _circuitEditor.Circuit.GetRails()) { foreach (RailAnchor anchor in rail.GetFreeConnections()) { Vector2 guiPosition = editorCamera.Camera.WorldToScreenPoint(anchor.Position); float distance = Vector2.Distance(mousePos, guiPosition); if (distance < lowestDistance) { _focusedAnchor = anchor; lowestDistance = distance; } } } // ----------------------------------------------------------------------------------- // La sélection a changé if (previouslySelectedAnchor != _focusedAnchor) { // Changement de la sélection d'anchor if (_focusedAnchor != null) { if (_railHandle == null) { _railHandle = Instantiate(_circuitEditor.SelectedRail); } // Placement de ce rail selon l'anchor _railHandle.transform.parent = _handlesRoot.transform; _railHandle.GetComponent <Rail>().SetTransformFromAnchor(_focusedAnchor); } // On est sorti de la zone de sqélection, suppression du handle else { DestroyRailHandle(); } } } _lastMousePos = mousePos; } // Clic gauche if (Input.GetMouseButtonDown(0)) { // En mode scène, le clic gauche sert à l'ajout de rail if (_circuitEditor.AddMode == CircuitEditor.AddingMode.Scene && !editorCamera.IsMovingView) { // Un rail est prêt à être placé if (_railHandle && _focusedAnchor) { Rail newRail = _circuitEditor.AddRail(_focusedAnchor.Parent, _focusedAnchor); if (newRail) { DestroyRailHandle(); } } } // En mode clic, le clic gauche sert à la sélection else if (_circuitEditor.AddMode == CircuitEditor.AddingMode.Click) { Ray ray = editorCamera.Camera.ScreenPointToRay(mousePos); int layerMask = 1 << CircuitEditor.railLayer; if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, layerMask)) { if (hit.collider.TryGetComponent(out Rail selectedRail)) { // Le rail devient la nouvelle sélection Selection = selectedRail; } } else { // Clic dans le vide => déselection Selection = null; } } } }
/// <summary> /// Réplique la connection sur l'autre RailAnchor /// </summary> /// <param name="withAnchor"></param> public void NotifyConnection(RailAnchor withAnchor) { Connect(withAnchor, false); }