123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400 |
- #if UNITY_EDITOR
- using UnityEngine;
- using UnityEditor;
- namespace O3DWB
- {
- [ExecuteInEditMode]
- public class ObjectPlacementGuide : MonoBehaviour, IMessageListener
- {
- #region Private Static Variables
- private static string _nameSuffix = "Active Prefab";
- private static ObjectPlacementGuide _instance;
- #endregion
- #region Private Variables
- [SerializeField]
- private Prefab _sourcePrefab;
- [SerializeField]
- private Transform _transform;
- private ObjectMouseUniformScaleSession _mouseUniformScaleSession = new ObjectMouseUniformScaleSession();
- private ObjectMouseRotationSession _mouseRotationSession = new ObjectMouseRotationSession();
- private ObjectMouseMoveAlongDirectionSession _mouseMoveAlongDirectionSession = new ObjectMouseMoveAlongDirectionSession();
- #endregion
- #region Public Static Properties
- public static ObjectPlacementGuide Instance
- {
- get
- {
- if (_instance == null) InstantiateFromActivePrefabIfPossible();
- return _instance;
- }
- }
- public static GameObject SceneObject { get { return ExistsInScene ? Instance.gameObject : null; } }
- public static bool ExistsInScene { get { return _instance != null; } }
- public static bool ExistsInSceneAndIsActive { get { return ExistsInScene && Instance.gameObject.activeSelf; } }
- public static bool Active { set { if (ExistsInScene) Instance.gameObject.SetActive(value); } }
- #endregion
- #region Public Properties
- public Prefab SourcePrefab { get { return _sourcePrefab; } }
- public bool IsSourcePrefabAvailable { get { return SourcePrefab != null && SourcePrefab.UnityPrefab != null; } }
- public Vector3 WorldPosition { get { return _transform.position; } }
- public Quaternion WorldRotation { get { return _transform.rotation; } }
- public Vector3 WorldScale { get { return _transform.lossyScale; } set { gameObject.SetWorldScale(value); } }
- public bool IsMouseMoveAlongDirectionSessionActive { get { return _mouseMoveAlongDirectionSession.IsActive; } }
- public bool IsMouseUniformScaleSessionActive { get { return _mouseUniformScaleSession.IsActive; } }
- public bool IsMouseRotationSessionActive { get { return _mouseRotationSession.IsActive; } }
- public bool IsMouseRotationSessionForCustomAxis { get { return _mouseRotationSession.RotatingAroundCustomAxis; } }
- public TransformAxis MouseRotationSessionAxis { get { return _mouseRotationSession.RotationAxis; } }
- public bool IsAnyMouseSessionActive { get { return IsMouseRotationSessionActive || IsMouseUniformScaleSessionActive || IsMouseMoveAlongDirectionSessionActive; } }
- #endregion
- #region Public Static Functions
- public static bool ContainsChild(Transform potentialChild)
- {
- if (ExistsInScene) return potentialChild != null && potentialChild.IsChildOf(Instance._transform);
- return false;
- }
- public static bool Equals(GameObject gameObject)
- {
- if (ExistsInScene) return gameObject == Instance.gameObject;
- return false;
- }
- public static void CreateFromActivePrefabIfNotExists()
- {
- if (!ExistsInScene) InstantiateFromActivePrefabIfPossible();
- }
- public static void DestroyIfExists()
- {
- if (ExistsInScene) Octave3DWorldBuilder.DestroyImmediate(ObjectPlacementGuide.Instance.gameObject);
- }
- #endregion
- #region Public Methods
- public void BeginMouseMoveAlongDirectionSession(Vector3 moveDirection)
- {
- if (!IsAnyMouseSessionActive) _mouseMoveAlongDirectionSession.Begin(gameObject, moveDirection, ObjectPlacementGuideSettings.Get().MouseOffsetFromPlacementSurfaceSettings);
- }
- public void EndMouseMoveAlongDirectionSession()
- {
- _mouseMoveAlongDirectionSession.End();
- }
- public void BeginMouseScaleSession(Vector3 scalePivotPoint)
- {
- if (!IsAnyMouseSessionActive)
- {
- _mouseUniformScaleSession.PivotPoint = scalePivotPoint;
- _mouseUniformScaleSession.Begin(gameObject, ObjectPlacementSettings.Get().ObjectPlacementGuideSettings.MouseUniformScaleSettings);
- }
- }
- public void EndMouseScaleSession()
- {
- _mouseUniformScaleSession.End();
- }
- public void BeginMouseRotationSession(TransformAxis rotationAxis)
- {
- if (!IsAnyMouseSessionActive)
- _mouseRotationSession.BeginRotationAroundAxis(gameObject, ObjectPlacementSettings.Get().ObjectPlacementGuideSettings.MouseRotationSettings, rotationAxis);
- }
- public void BeginMouseRotationSession(Vector3 customRotationAxis)
- {
- if (!IsAnyMouseSessionActive)
- _mouseRotationSession.BeginRotationAroundCustomAxis(gameObject, ObjectPlacementSettings.Get().ObjectPlacementGuideSettings.MouseRotationSettings, customRotationAxis);
- }
- public void EndMouseRotationSession()
- {
- _mouseRotationSession.End();
- }
- public void UpdateActiveMouseSessionsForMouseMovement(Event e)
- {
- if(IsMouseMoveAlongDirectionSessionActive) _mouseMoveAlongDirectionSession.UpdateForMouseMovement(e);
- else
- if(IsMouseUniformScaleSessionActive)
- {
- _mouseUniformScaleSession.UpdateForMouseMovement(e);
- UndoEx.RecordForToolAction(_sourcePrefab.ActivationSettings);
- _sourcePrefab.ActivationSettings.WorldScale = _transform.lossyScale;
- }
- else
- if(IsMouseRotationSessionActive)
- {
- _mouseRotationSession.UpdateForMouseMovement(e);
- UndoEx.RecordForToolAction(_sourcePrefab.ActivationSettings);
- _sourcePrefab.ActivationSettings.WorldRotation = _transform.rotation;
- }
- }
- public void SetHierarchyWorldRotationAndPreserveHierarchyCenter(Quaternion rotation)
- {
- if (IsAnyMouseSessionActive) return;
- UndoEx.RecordForToolAction(_transform);
- gameObject.SetHierarchyWorldRotationAndPreserveHierarchyCenter(rotation);
- UndoEx.RecordForToolAction(_sourcePrefab.ActivationSettings);
- _sourcePrefab.ActivationSettings.WorldRotation = _transform.rotation;
- }
- public void SetHierarchyWorldScaleByPivotPoint(float scale, Vector3 pivotPoint)
- {
- if (IsAnyMouseSessionActive) return;
- UndoEx.RecordForToolAction(_transform);
- gameObject.SetHierarchyWorldScaleByPivotPoint(scale, pivotPoint);
- UndoEx.RecordForToolAction(_sourcePrefab.ActivationSettings);
- _sourcePrefab.ActivationSettings.WorldScale = _transform.lossyScale;
- }
- public void SetHierarchyWorldScaleByPivotPoint(Vector3 scale, Vector3 pivotPoint)
- {
- if (IsAnyMouseSessionActive) return;
- UndoEx.RecordForToolAction(_transform);
- gameObject.SetHierarchyWorldScaleByPivotPoint(scale, pivotPoint);
- UndoEx.RecordForToolAction(_sourcePrefab.ActivationSettings);
- _sourcePrefab.ActivationSettings.WorldScale = _transform.lossyScale;
- }
- public void Snap()
- {
- float offsetFromSurface = SourcePrefab.OffsetFromGridSurface;
- if (ObjectSnapping.Get().SnapSurfaceType != SnapSurfaceType.GridCell) offsetFromSurface = SourcePrefab.OffsetFromObjectSurface;
- if (AllShortcutCombos.Instance.PlaceGuideBehindSurfacePlane.IsActive()) offsetFromSurface *= -1.0f;
- if (AllShortcutCombos.Instance.SnapCenterToCenter.IsActive()) ObjectSnapping.Get().SnapObjectHierarchyToCenterOfSnapSurface(gameObject, ObjectPlacement.Get().CenterProjectedGuidePivotPoint, ObjectPlacement.Get().ProjectedGuidePivotPoints, offsetFromSurface);
- else ObjectSnapping.Get().SnapObjectHierarchy(gameObject, ObjectPlacement.Get().ProjectedGuidePivotPoints, offsetFromSurface);
- PersistentObjectPlacementGuideData.Get().LastUsedWorldPosition = _transform.position;
- }
- public void SetWorldPosition(Vector3 position)
- {
- _transform.position = position;
- PersistentObjectPlacementGuideData.Get().LastUsedWorldPosition = _transform.position;
- }
- public void SetWorldScale(Vector3 worldScale)
- {
- UndoEx.RecordForToolAction(_transform);
- _transform.SetWorldScale(worldScale);
- UndoEx.RecordForToolAction(_sourcePrefab.ActivationSettings);
- _sourcePrefab.ActivationSettings.WorldScale = worldScale;
- }
- public void RegisterCurrentPosition()
- {
- PersistentObjectPlacementGuideData.Get().LastUsedWorldPosition = _transform.position;
- }
- public void SetWorldRotation(Quaternion rotation)
- {
- _transform.rotation = rotation;
- //_sourcePrefab.ActivationSettings.WorldRotation = _transform.rotation;
- }
- public void RotateUsingKeyboardSettings(Vector3 customRotationAxis)
- {
- if (IsAnyMouseSessionActive) return;
- UndoEx.RecordForToolAction(_transform);
- ObjectKeyboardRotationSettings keyboardRotationSettings = ObjectPlacementGuideSettings.Get().KeyboardRotationSettings;
- gameObject.RotateHierarchyBoxAroundPoint(keyboardRotationSettings.CustomAxisRotationSettings.RotationAmountInDegrees,
- customRotationAxis, gameObject.GetHierarchyWorldOrientedBox().Center);
- UndoEx.RecordForToolAction(_sourcePrefab.ActivationSettings);
- _sourcePrefab.ActivationSettings.WorldRotation = _transform.rotation;
- }
- public void RotateUsingKeyboardSettings(TransformAxis rotationAxis)
- {
- if (IsAnyMouseSessionActive) return;
- ObjectKeyboardRotationSettings keyboardRotationSettings = ObjectPlacementGuideSettings.Get().KeyboardRotationSettings;
- UndoEx.RecordForToolAction(_transform);
- AxisKeyboardRotationSettings axisKeyboardRotationSettings = keyboardRotationSettings.XAxisRotationSettings;
- if (rotationAxis == TransformAxis.Y) axisKeyboardRotationSettings = keyboardRotationSettings.YAxisRotationSettings;
- else if (rotationAxis == TransformAxis.Z) axisKeyboardRotationSettings = keyboardRotationSettings.XAxisRotationSettings;
- gameObject.RotateHierarchyBoxAroundPoint(axisKeyboardRotationSettings.RotationAmountInDegrees,
- TransformAxes.GetVector(rotationAxis, TransformSpace.Global, _transform),
- gameObject.GetHierarchyWorldOrientedBox().Center);
- UndoEx.RecordForToolAction(_sourcePrefab.ActivationSettings);
- _sourcePrefab.ActivationSettings.WorldRotation = _transform.rotation;
- }
- #endregion
- #region Private Methods
- private void Awake()
- {
- if (!IsGuideInstanceAllowedToExist()) { DestroyImmediate(this); return; }
- Initialize();
- }
- private void OnEnable()
- {
- if (!IsGuideInstanceAllowedToExist()) { DestroyImmediate(this); return; }
- Initialize();
- }
- private void Initialize()
- {
- MessageListenerRegistration.PerformRegistrationForObjectPlacementGuide(this);
- _instance = this;
- _transform = transform;
- EditorApplication.update -= OnEditorUpdate;
- EditorApplication.update += OnEditorUpdate;
- }
- private bool IsGuideInstanceAllowedToExist()
- {
- if (_instance != null && _instance != this) return false;
- return true;
- }
- private void Start()
- {
- // Note: We will always ensure that the guide is placed in the last position which it had before
- // it was destroyed. Although not strictly necessary, it is more pleasent than to see it
- // suddenly snap to position <0, 0, 0> every time an Undo/Redo operation is performed or
- // when the scripts are recompiled.
- // Note: This has to be done from the 'Start' function because here we can be sure that the object
- // which holds the persistent guide data has been created.
- gameObject.transform.position = PersistentObjectPlacementGuideData.Get().LastUsedWorldPosition;
- }
- private void OnDestroy()
- {
- if (_instance == this)
- {
- MessageListenerDatabase.Instance.UnregisterListener(this);
- _instance = null;
- EditorApplication.update -= OnEditorUpdate;
- }
- }
- private void OnEditorUpdate()
- {
- if (!EditorApplication.isPlaying)
- {
- if (Octave3DWorldBuilder.ActiveInstance == null) UndoEx.DestroyObjectImmediate(gameObject);
- else
- if (!Selection.Contains(Octave3DWorldBuilder.ActiveInstance.gameObject)) ObjectPlacement.Get().DestroyPlacementGuide();
- }
- }
- #endregion
- #region Message Handlers
- public void RespondToMessage(Message message)
- {
- switch(message.Type)
- {
- case MessageType.NewPrefabWasActivated:
- RespondToMessage(message as NewPrefabWasActivatedMessage);
- break;
- case MessageType.NewPrefabCategoryWasActivated:
- RespondToMessage(message as NewPrefabCategoryWasActivatedMessage);
- break;
- case MessageType.PrefabWasRemovedFromCategory:
- RespondToMessage(message as PrefabWasRemovedFromCategoryMessage);
- break;
- case MessageType.PrefabCategoryWasRemovedFromDatabase:
- RespondToMessage(message as PrefabCategoryWasRemovedFromDatabaseMessage);
- break;
- case MessageType.UndoRedoWasPerformed:
- RespondToMessage(message as UndoRedoWasPerformedMessage);
- break;
- }
- }
- private void RespondToMessage(NewPrefabWasActivatedMessage message)
- {
- if (Inspector.Get().ActiveInspectorGUIIdentifier == InspectorGUIIdentifier.ObjectSnapping ||
- Inspector.Get().ActiveInspectorGUIIdentifier == InspectorGUIIdentifier.ObjectPlacement)
- {
- DestroyIfExists();
- CreateFromActivePrefabIfNotExists();
- }
- }
- private void RespondToMessage(NewPrefabCategoryWasActivatedMessage message)
- {
- if(Inspector.Get().ActiveInspectorGUIIdentifier == InspectorGUIIdentifier.ObjectSnapping ||
- Inspector.Get().ActiveInspectorGUIIdentifier == InspectorGUIIdentifier.ObjectPlacement)
- {
- DestroyIfExists();
- CreateFromActivePrefabIfNotExists();
- }
- }
- private void RespondToMessage(PrefabWasRemovedFromCategoryMessage message)
- {
- DestroyIfExists();
- CreateFromActivePrefabIfNotExists();
- }
- private void RespondToMessage(PrefabCategoryWasRemovedFromDatabaseMessage message)
- {
- DestroyIfExists();
- CreateFromActivePrefabIfNotExists();
- }
- private void RespondToMessage(UndoRedoWasPerformedMessage message)
- {
- if(_sourcePrefab != PrefabCategoryDatabase.Get().ActivePrefabCategory.ActivePrefab)
- {
- DestroyIfExists();
- CreateFromActivePrefabIfNotExists();
- }
- }
- #endregion
- #region Private Static Functions
- private static void InstantiateFromActivePrefabIfPossible()
- {
- Prefab activePrefab = PrefabQueries.GetActivePrefab();
- if (activePrefab != null) InstantiateFromPrefab(activePrefab);
- }
- private static void InstantiateFromPrefab(Prefab prefab)
- {
- _instance = ObjectInstantiation.InstantiateObjectPlacementGuide(prefab, prefab.Name + "(" + _nameSuffix + ")");
- _instance._sourcePrefab = prefab;
- _instance.transform.rotation = prefab.ActivationSettings.WorldRotation;
- _instance.gameObject.SetWorldScale(prefab.ActivationSettings.WorldScale);
- ObjectPlacementGuideWasInstantiatedMessage.SendToInterestedListeners();
- }
- #endregion
- }
- }
- #endif
|