Пример #1
0
        /// <summary>
        /// Update the current brush object and weights with the current mouse position.
        /// </summary>
        /// <param name="mousePosition">current mouse position (from Event)</param>
        /// <param name="isDrag">optional, is dragging the mouse cursor</param>
        /// <param name="overridenGO">optional, provides an already selected gameobject (used in unit tests only)</param>
        /// <param name="overridenRay"> optional, provides a ray already created (used in unit tests only)</param>
        internal void UpdateBrush(Vector2 mousePosition, bool isUserHoldingControl = false, bool isUserHoldingShift = false, bool isDrag = false, GameObject overridenGO = null, Ray?overridenRay = null)
        {
            MirrorSettings mirrorSettings = m_BrushMirrorEditor.settings;

            // NOTE: Quick fix for the lockBrushToFirst feature, probably need to refactor
            // some code in order to be able to do it properly
            if (firstGameObject != null && s_LockBrushToFirst)
            {
                Ray mouseRay2 = overridenRay != null ? (Ray)overridenRay : HandleUtility.GUIPointToWorldRay(mousePosition);
                DoMeshRaycast(mouseRay2, brushTarget, mirrorSettings);
                OnBrushMove();
                SceneView.RepaintAll();
                this.Repaint();
                return;
            }

            // Must check HandleUtility.PickGameObject only during MouseMoveEvents or errors will rain.
            GameObject go = null;

            brushTarget = null;

            if (isDrag && s_LockBrushToFirst && m_LastHoveredGameObject != null)
            {
                go          = m_LastHoveredGameObject;
                brushTarget = GetBrushTarget(go);
            }
            else if (s_IgnoreUnselected || isDrag)
            {
                GameObject cur = null;
                int        max = 0;             // safeguard against unforeseen while loop errors crashing unity

                do
                {
                    int tmp;
                    // overloaded PickGameObject ignores array of GameObjects, this is used
                    // when there are non-selected gameObjects between the mouse and selected
                    // gameObjects.
                    cur = overridenGO;
                    if (cur == null)
                    {
                        m_IgnoreDrag.RemoveAll(x => x == null);
                        cur = HandleUtility.PickGameObject(mousePosition, m_IgnoreDrag.ToArray(), out tmp);
                    }

                    if (cur != null)
                    {
                        if (!PolyEditorUtility.InSelection(cur))
                        {
                            if (!m_IgnoreDrag.Contains(cur))
                            {
                                m_IgnoreDrag.Add(cur);
                            }
                        }
                        else
                        {
                            brushTarget = GetBrushTarget(cur);

                            if (brushTarget != null)
                            {
                                go = cur;
                            }
                            else
                            {
                                m_IgnoreDrag.Add(cur);
                            }
                        }
                    }
                } while(go == null && cur != null && max++ < 128);
            }
            else
            {
                go = overridenGO;
                if (go == null)
                {
                    go = HandleUtility.PickGameObject(mousePosition, false);
                }

                if (go != null && PolyEditorUtility.InSelection(go))
                {
                    brushTarget = GetBrushTarget(go);
                }
                else
                {
                    go = null;
                }
            }

            bool mouseHoverTargetChanged = false;
            Ray  mouseRay = overridenRay != null ? (Ray)overridenRay :  HandleUtility.GUIPointToWorldRay(mousePosition);

            // if the mouse hover picked up a valid editable, raycast against that.  otherwise
            // raycast all meshes in selection
            if (go == null)
            {
                foreach (var kvp in m_Hovering)
                {
                    BrushTarget t = kvp.Value;

                    if (Util.IsValid(t) && DoMeshRaycast(mouseRay, t, mirrorSettings))
                    {
                        brushTarget = t;
                        go          = t.gameObject;
                        break;
                    }
                }
            }
            else
            {
                if (!DoMeshRaycast(mouseRay, brushTarget, mirrorSettings))
                {
                    if (!isDrag || !s_LockBrushToFirst)
                    {
                        go          = null;
                        brushTarget = null;
                    }

                    return;
                }
            }

            // if m_Hovering off another gameobject, call OnBrushExit on that last one and mark the
            // target as having been changed
            if (go != m_LastHoveredGameObject)
            {
                OnBrushExit(m_LastHoveredGameObject);
                mouseHoverTargetChanged = true;
                m_LastHoveredGameObject = go;
            }

            SceneView.RepaintAll();
            this.Repaint();

            if (brushTarget == null)
            {
                return;
            }

            if (mouseHoverTargetChanged)
            {
                brushSettings.isUserHoldingControl = isUserHoldingControl;
                brushSettings.isUserHoldingShift   = isUserHoldingShift;

                OnBrushEnter(brushTarget, brushSettings);

                // brush is in use, adding a new object to the undo
                if (m_ApplyingBrush && !m_UndoQueue.Contains(go))
                {
                    int curGroup = Undo.GetCurrentGroup();
                    brushTarget.editableObject.isDirty = true;
                    OnBrushBeginApply(brushTarget, brushSettings);
                    Undo.CollapseUndoOperations(curGroup);
                }
            }

            OnBrushMove();

            SceneView.RepaintAll();
            this.Repaint();
        }
Пример #2
0
        /// <summary>
        /// Update the current brush object and weights with the current mouse position.
        /// </summary>
        /// <param name="mousePosition">current mouse position (from Event)</param>
        /// <param name="isDrag">optional, is dragging the mouse cursor</param>
        /// <param name="overridenGO">optional, provides an already selected gameobject (used in unit tests only)</param>
        /// <param name="overridenRay"> optional, provides a ray already created (used in unit tests only)</param>
        internal void UpdateBrush(Vector2 mousePosition, bool isUserHoldingControl = false, bool isUserHoldingShift = false, bool isDrag = false, GameObject overridenGO = null, Ray?overridenRay = null)
        {
            MirrorSettings mirrorSettings = m_BrushMirrorEditor.settings;

            // Must check HandleUtility.PickGameObject only during MouseMoveEvents or errors will rain.
            GameObject go = null;

            brushTarget = null;
            GameObject cur = null;

#if UNITY_2021_1_OR_NEWER
            int materialIndex;
            cur = HandleUtility.PickGameObject(mousePosition, false, null, Selection.gameObjects, out materialIndex);
            if (cur != null)
            {
                brushTarget = GetOrCreateBrushTarget(cur);
            }

            if (brushTarget != null)
            {
                go = cur;
            }
#else
            int max = 0;                // safeguard against unforeseen while loop errors crashing unity

            do
            {
                int tmp;
                // overloaded PickGameObject ignores array of GameObjects, this is used
                // when there are non-selected gameObjects between the mouse and selected
                // gameObjects.
                cur = overridenGO;
                if (cur == null)
                {
                    m_IgnoreDrag.RemoveAll(x => x == null);
                    cur = HandleUtility.PickGameObject(mousePosition, m_IgnoreDrag.ToArray(), out tmp);
                }

                if (cur != null)
                {
                    if (!PolyEditorUtility.InSelection(cur))
                    {
                        if (!m_IgnoreDrag.Contains(cur))
                        {
                            m_IgnoreDrag.Add(cur);
                        }
                    }
                    else
                    {
                        brushTarget = GetOrCreateBrushTarget(cur);

                        if (brushTarget != null)
                        {
                            go = cur;
                        }
                        else
                        {
                            m_IgnoreDrag.Add(cur);
                        }
                    }
                }
            } while(go == null && cur != null && max++ < 128);
#endif

            bool mouseHoverTargetChanged = false;
            Ray  mouseRay = overridenRay != null ? (Ray)overridenRay :  HandleUtility.GUIPointToWorldRay(mousePosition);
            // if the mouse hover picked up a valid editable, raycast against that.  otherwise
            // raycast all meshes in selection
            if (go == null)
            {
                foreach (var kvp in m_Hovering)
                {
                    BrushTarget t = kvp.Value;

                    if (Util.IsValid(t) && DoMeshRaycast(mouseRay, t, mirrorSettings))
                    {
                        brushTarget = t;
                        go          = t.gameObject;
                        break;
                    }
                }
            }
            else
            {
                if (!DoMeshRaycast(mouseRay, brushTarget, mirrorSettings))
                {
                    brushTarget = null;
                    return;
                }
            }

            // if m_Hovering off another gameobject, call OnBrushExit on that last one and mark the
            // target as having been changed
            if (go != m_LastHoveredGameObject)
            {
                if (m_LastHoveredGameObject)
                {
                    OnBrushExit(m_LastHoveredGameObject);
                }

                if (m_ApplyingBrush)
                {
                    mode.OnBrushFinishApply(brushTarget, brushSettings);
                }

                mouseHoverTargetChanged = true;
                m_LastHoveredGameObject = go;

                foreach (var secondaryTarget in m_LastSecondaryBrushTargets)
                {
                    if (!m_SecondaryBrushTargets.Contains(secondaryTarget))
                    {
                        OnBrushExit(secondaryTarget.gameObject);
                        if (m_ApplyingBrush)
                        {
                            mode.OnBrushFinishApply(brushTarget, brushSettings);
                        }
                    }
                }
            }

            if (brushTarget == null)
            {
                SceneView.RepaintAll();
                DoRepaint();

                m_LastSecondaryBrushTargets.Clear();
                m_SecondaryBrushTargets.Clear();

                return;
            }

            brushSettings.isUserHoldingControl = isUserHoldingControl;
            brushSettings.isUserHoldingShift   = isUserHoldingShift;

            if (mouseHoverTargetChanged)
            {
                foreach (var secondaryTarget in m_SecondaryBrushTargets)
                {
                    if (!m_LastSecondaryBrushTargets.Contains(secondaryTarget))
                    {
                        OnBrushEnter(secondaryTarget, brushSettings);
                        if (m_ApplyingBrush)
                        {
                            mode.OnBrushBeginApply(secondaryTarget, brushSettings);
                        }
                    }
                }

                //The active brushtarget is the last one to notify the brush
                OnBrushEnter(brushTarget, brushSettings);

                // brush is in use, adding a new object to the undo
                if (m_ApplyingBrush)
                {
                    if (!m_UndoQueue.Contains(go))
                    {
                        int curGroup = Undo.GetCurrentGroup();
                        brushTarget.editableObject.isDirty = true;
                        OnBrushBeginApply(brushTarget, brushSettings);
                        Undo.CollapseUndoOperations(curGroup);
                    }
                    else
                    {
                        mode.OnBrushBeginApply(brushTarget, brushSettings);
                    }
                }
            }

            m_LastSecondaryBrushTargets.Clear();
            m_LastSecondaryBrushTargets.AddRange(m_SecondaryBrushTargets);

            OnBrushMove();

            SceneView.RepaintAll();
            DoRepaint();
        }