示例#1
0
 internal abstract void RegisterUndo(BrushTarget brushTarget);
 internal override void OnBrushSettingsChanged(BrushTarget target, BrushSettings settings)
 {
     base.OnBrushSettingsChanged(target, settings);
     RebuildColorTargets(brushColor, settings.strength);
 }
示例#3
0
 // Called whenever the brush is moved.  Note that @target may have a null editableObject.
 internal override void OnBrushMove(BrushTarget target, BrushSettings settings)
 {
     base.OnBrushMove(target, settings);
 }
示例#4
0
 void OnBrushEnter(BrushTarget target, BrushSettings settings)
 {
     mode.OnBrushEnter(target.editableObject, settings);
 }
示例#5
0
        /// <summary>
        /// Draw gizmos taking into account handling of normal by smooth brush mode.
        /// </summary>
        /// <param name="target">Current target Object</param>
        ///// <param name="settings">Current brush settings</param>
        internal override void DrawGizmos(BrushTarget target, BrushSettings settings)
        {
            UpdateBrushGizmosColor();
            Vector3 normal = s_SmoothDirection.value.ToVector3();

            int      rayCount    = target.raycastHits.Count;
            PolyMesh mesh        = target.editableObject.editMesh;
            int      vertexCount = mesh.vertexCount;

            Vector3[] normals = (s_SmoothDirection == PolyDirection.BrushNormal) ? mesh.normals : null;

            // don't use target.GetAllWeights because brush normal needs
            // to know which ray to use for normal
            for (int ri = 0; ri < rayCount; ri++)
            {
                PolyRaycastHit hit = target.raycastHits[ri];

                if (hit.weights == null || hit.weights.Length < vertexCount)
                {
                    continue;
                }

                if (s_SmoothDirection == PolyDirection.BrushNormal)
                {
                    if (s_UseFirstNormalVector && brushNormalOnBeginApply.Count > ri)
                    {
                        normal = brushNormalOnBeginApply[ri];
                    }
                    else
                    {
                        // get the highest weighted vertex to use its direction computation
                        float highestWeight = .0001f;
                        int   highestIndex  = -1;
                        for (int i = 0; i < commonVertexCount; i++)
                        {
                            int index = commonVertices[i][0];
                            if (hit.weights[index] < .0001f || (s_IgnoreOpenEdges && nonManifoldIndices.Contains(index)))
                            {
                                continue;
                            }

                            if (hit.weights[index] > highestWeight)
                            {
                                highestIndex = index;
                            }
                        }

                        if (highestIndex != -1)
                        {
                            normal = Math.WeightedAverage(normals, neighborLookup[highestIndex], hit.weights).normalized;
                        }
                        else
                        {
                            normal = hit.normal;
                        }
                    }
                }
                else if (s_SmoothDirection == PolyDirection.VertexNormal)
                {
                    normal = hit.normal;
                }

                PolyHandles.DrawBrush(hit.position, normal, settings, target.localToWorldMatrix, innerColor, outerColor);
            }
        }
示例#6
0
        /// <summary>
        /// Calculates the per-vertex weight for each raycast hit and fills in brush target weights.
        /// </summary>
        /// <param name="target"></param>
        /// <param name="settings"></param>
        /// <param name="tool"></param>
        /// <param name="bMode"></param>
        internal static void CalculateWeightedVertices(BrushTarget target, BrushSettings settings, BrushTool tool = BrushTool.None, BrushMode bMode = null)
        {
            //null checks
            if (target == null || settings == null)
            {
                return;
            }

            if (target.editableObject == null)
            {
                return;
            }

            bool  uniformScale = PolyMath.VectorIsUniform(target.transform.lossyScale);
            float scale        = uniformScale ? 1f / target.transform.lossyScale.x : 1f;

            PolyMesh mesh = target.editableObject.visualMesh;

            if (tool == BrushTool.Texture && mesh.subMeshCount > 1)
            {
                var   mode           = bMode as BrushModeTexture;
                int[] submeshIndices = mesh.subMeshes[mode.currentMeshACIndex].indexes;

                //List<List<int>> common = PolyMeshUtility.GetCommonVertices(mesh);

                Transform transform   = target.transform;
                int       vertexCount = mesh.vertexCount;
                Vector3[] vertices    = mesh.vertices;

                if (!uniformScale)
                {
                    Vector3[] world = new Vector3[vertexCount];
                    for (int i = 0; i < vertexCount; i++)
                    {
                        world[i] = transform.TransformPoint(vertices[i]);
                    }
                    vertices = world;
                }

                AnimationCurve curve = settings.falloffCurve;
                float          radius = settings.radius * scale, falloff_mag = Mathf.Max((radius - radius * settings.falloff), 0.00001f);

                Vector3        hitPosition = Vector3.zero;
                PolyRaycastHit hit;

                for (int n = 0; n < target.raycastHits.Count; n++)
                {
                    hit = target.raycastHits[n];
                    hit.SetVertexCount(vertexCount);

                    for (int i = 0; i < vertexCount; i++)
                    {
                        hit.weights[i] = 0f;
                    }

                    hitPosition = uniformScale ? hit.position : transform.TransformPoint(hit.position);

                    for (int i = 0; i < submeshIndices.Length; i++)
                    {
                        int   currentIndex = submeshIndices[i];
                        float dist         = (hitPosition - vertices[currentIndex]).magnitude;
                        float delta        = radius - dist;

                        if (delta >= 0)
                        {
                            float weight = Mathf.Clamp(curve.Evaluate(1f - Mathf.Clamp(delta / falloff_mag, 0f, 1f)), 0f, 1f);

                            hit.weights[currentIndex] = weight;
                        }
                    }
                }
            }
            else
            {
                List <List <int> > common = PolyMeshUtility.GetCommonVertices(mesh);

                Transform transform   = target.transform;
                int       vertexCount = mesh.vertexCount;
                Vector3[] vertices    = mesh.vertices;

                if (!uniformScale)
                {
                    Vector3[] world = new Vector3[vertexCount];
                    for (int i = 0; i < vertexCount; i++)
                    {
                        world[i] = transform.TransformPoint(vertices[i]);
                    }
                    vertices = world;
                }

                AnimationCurve curve = settings.falloffCurve;
                float          radius = settings.radius * scale, falloff_mag = Mathf.Max((radius - radius * settings.falloff), 0.00001f);

                Vector3        hitPosition = Vector3.zero;
                PolyRaycastHit hit;

                for (int n = 0; n < target.raycastHits.Count; n++)
                {
                    hit = target.raycastHits[n];
                    hit.SetVertexCount(vertexCount);

                    hitPosition = uniformScale ? hit.position : transform.TransformPoint(hit.position);

                    for (int i = 0; i < common.Count; i++)
                    {
                        int   commonArrayCount = common[i].Count;
                        float sqrDist          = (hitPosition - vertices[common[i][0]]).sqrMagnitude;

                        if (sqrDist > radius * radius)
                        {
                            for (int j = 0; j < commonArrayCount; j++)
                            {
                                hit.weights[common[i][j]] = 0f;
                            }
                        }
                        else
                        {
                            float weight = Mathf.Clamp(curve.Evaluate(1f - Mathf.Clamp((radius - Mathf.Sqrt(sqrDist)) / falloff_mag, 0f, 1f)), 0f, 1f);

                            for (int j = 0; j < commonArrayCount; j++)
                            {
                                hit.weights[common[i][j]] = weight;
                            }
                        }
                    }
                }
            }
            target.GetAllWeights(true);
        }
        /// <summary>
        /// Calculates the per-vertex weight for each raycast hit and fills in brush target weights.
        /// </summary>
        /// <param name="target"></param>
        /// <param name="settings"></param>
        /// <param name="tool"></param>
        /// <param name="bMode"></param>
        internal static void CalculateWeightedVertices(BrushTarget target, BrushSettings settings, BrushTool tool = BrushTool.None, BrushMode bMode = null)
        {
            if (target == null || settings == null)
            {
                return;
            }

            if (target.editableObject == null)
            {
                return;
            }

            bool  uniformScale = Math.VectorIsUniform(target.transform.lossyScale);
            float scale        = uniformScale ? 1f / target.transform.lossyScale.x : 1f;

            PolyMesh mesh = target.editableObject.visualMesh;

            Transform transform   = target.transform;
            int       vertexCount = mesh.vertexCount;

            Vector3[] vertices = mesh.vertices;

            if (!uniformScale)
            {
                // As we only increase size only when it's needed, always make sure to
                // use the vertexCount variable in loop statements and not the buffer length.
                if (s_WorldBuffer.Length < vertexCount)
                {
                    System.Array.Resize <Vector3>(ref s_WorldBuffer, vertexCount);
                }

                for (int i = 0; i < vertexCount; i++)
                {
                    s_WorldBuffer[i] = transform.TransformPoint(vertices[i]);
                }
                vertices = s_WorldBuffer;
            }

            AnimationCurve curve = settings.falloffCurve;
            float          radius = settings.radius * scale, falloff_mag = Mathf.Max((radius - radius * settings.falloff), 0.00001f);

            Vector3        hitPosition = Vector3.zero;
            PolyRaycastHit hit;

            if (tool == BrushTool.Texture && mesh.subMeshCount > 1)
            {
                var   mode           = bMode as BrushModeTexture;
                int[] submeshIndices = mesh.subMeshes[mode.currentMeshACIndex].indexes;

                for (int n = 0; n < target.raycastHits.Count; n++)
                {
                    hit = target.raycastHits[n];
                    hit.SetVertexCount(vertexCount);

                    for (int i = 0; i < vertexCount; i++)
                    {
                        hit.weights[i] = 0f;
                    }

                    hitPosition = uniformScale ? hit.position : transform.TransformPoint(hit.position);

                    for (int i = 0; i < submeshIndices.Length; i++)
                    {
                        int   currentIndex = submeshIndices[i];
                        float dist         = (hitPosition - vertices[currentIndex]).magnitude;
                        float delta        = radius - dist;

                        if (delta >= 0)
                        {
                            float weight = Mathf.Clamp(curve.Evaluate(1f - Mathf.Clamp(delta / falloff_mag, 0f, 1f)), 0f, 1f);

                            hit.weights[currentIndex] = weight;
                        }
                    }
                }
            }
            else
            {
                int[][] common = PolyMeshUtility.GetCommonVertices(mesh);

                Vector3 buf = Vector3.zero;

                for (int n = 0; n < target.raycastHits.Count; n++)
                {
                    hit = target.raycastHits[n];
                    hit.SetVertexCount(vertexCount);

                    hitPosition = uniformScale ? hit.position : transform.TransformPoint(hit.position);

                    for (int i = 0; i < common.Length; i++)
                    {
                        int[] commonItem       = common[i];
                        int   commonArrayCount = commonItem.Length;

                        Math.Subtract(vertices[commonItem[0]], hitPosition, ref buf);

                        float sqrDist = buf.sqrMagnitude;

                        if (sqrDist > radius * radius)
                        {
                            for (int j = 0; j < commonArrayCount; j++)
                            {
                                hit.weights[commonItem[j]] = 0f;
                            }
                        }
                        else
                        {
                            float weight = Mathf.Clamp(curve.Evaluate(1f - Mathf.Clamp((radius - Mathf.Sqrt(sqrDist)) / falloff_mag, 0f, 1f)), 0f, 1f);

                            for (int j = 0; j < commonArrayCount; j++)
                            {
                                hit.weights[commonItem[j]] = weight;
                            }
                        }
                    }
                }
            }

            target.GetAllWeights(true);
        }
 /// <summary>
 /// Handle Undo locally since it doesn't follow the same pattern as mesh modifications.
 /// </summary>
 /// <param name="brushTarget"></param>
 internal override void RegisterUndo(BrushTarget brushTarget)
 {
 }
示例#9
0
        internal override void OnBrushSettingsChanged(BrushTarget target, BrushSettings settings)
        {
            base.OnBrushSettingsChanged(target, settings);

            m_MeshVertexColors.RebuildColorTargets(m_BrushColor, settings.strength, mask);
        }
示例#10
0
        // Called whenever the brush is moved.  Note that @target may have a null editableObject.
        internal override void OnBrushMove(BrushTarget target, BrushSettings settings)
        {
            base.OnBrushMove(target, settings);

            if (!Util.IsValid(target))
            {
                return;
            }

            bool invert = settings.isUserHoldingControl;

            PolyMesh mesh        = target.editableObject.editMesh;
            int      vertexCount = mesh.vertexCount;

            float[] weights = target.GetAllWeights();

            switch (paintMode)
            {
            case PaintMode.Flood:
                for (int i = 0; i < vertexCount; i++)
                {
                    m_MeshVertexColors.Colors[i] = invert? s_WhiteColor : m_MeshVertexColors.TargetColors[i];
                }
                break;

            case PaintMode.Fill:

                System.Array.Copy(m_MeshVertexColors.OriginalColors, m_MeshVertexColors.Colors, vertexCount);
                int[] indices = target.editableObject.editMesh.GetTriangles();
                int   index   = 0;

                foreach (PolyRaycastHit hit in target.raycastHits)
                {
                    if (hit.triangle > -1)
                    {
                        index = hit.triangle * 3;

                        m_MeshVertexColors.Colors[indices[index + 0]] = invert ? s_WhiteColor : m_MeshVertexColors.TargetColors[indices[index + 0]];
                        m_MeshVertexColors.Colors[indices[index + 1]] = invert ? s_WhiteColor : m_MeshVertexColors.TargetColors[indices[index + 1]];
                        m_MeshVertexColors.Colors[indices[index + 2]] = invert ? s_WhiteColor : m_MeshVertexColors.TargetColors[indices[index + 2]];

                        m_FillModeEdges[0].x = indices[index + 0];
                        m_FillModeEdges[0].y = indices[index + 1];

                        m_FillModeEdges[1].x = indices[index + 1];
                        m_FillModeEdges[1].y = indices[index + 2];

                        m_FillModeEdges[2].x = indices[index + 2];
                        m_FillModeEdges[2].y = indices[index + 0];

                        for (int i = 0; i < 3; i++)
                        {
                            if (m_TriangleLookup.TryGetValue(m_FillModeEdges[i], out m_FillModeAdjacentTriangles))
                            {
                                for (int n = 0; n < m_FillModeAdjacentTriangles.Count; n++)
                                {
                                    index = m_FillModeAdjacentTriangles[n] * 3;

                                    m_MeshVertexColors.Colors[indices[index + 0]] = invert ? s_WhiteColor : m_MeshVertexColors.TargetColors[indices[index + 0]];
                                    m_MeshVertexColors.Colors[indices[index + 1]] = invert ? s_WhiteColor : m_MeshVertexColors.TargetColors[indices[index + 1]];
                                    m_MeshVertexColors.Colors[indices[index + 2]] = invert ? s_WhiteColor : m_MeshVertexColors.TargetColors[indices[index + 2]];
                                }
                            }
                        }
                    }
                }

                break;

            default:
            {
                for (int i = 0; i < vertexCount; i++)
                {
                    m_MeshVertexColors.Colors[i] = Util.Lerp(m_MeshVertexColors.OriginalColors[i],
                                                             invert ? m_MeshVertexColors.EraseColors[i] : m_MeshVertexColors.TargetColors[i],
                                                             mask,
                                                             weights[i]);
                }

                break;
            }
            }

            target.editableObject.editMesh.colors = m_MeshVertexColors.Colors;
            target.editableObject.ApplyMeshAttributes(MeshChannel.Color);
        }
示例#11
0
        /// <summary>
        /// Calculate the weights for this ray.
        /// </summary>
        /// <param name="mouseRay">The ray used to calculate weights</param>
        /// <param name="target">The object on which to calculate the weights</param>
        /// <returns>true if mouseRay hits the target, false otherwise</returns>
        bool DoMeshRaycast(Ray mouseRay, BrushTarget target, MirrorSettings mirrorSettings)
        {
            m_SecondaryBrushTargets.Clear();
            if (!Util.IsValid(target))
            {
                return(false);
            }

            target.ClearRaycasts();

            EditableObject editable = target.editableObject;

            s_Rays.Clear();
            s_Rays.Add(mouseRay);

            if (mirrorSettings.Axes != BrushMirror.None)
            {
                for (int i = 0; i < 3; i++)
                {
                    if (((uint)mirrorSettings.Axes & (1u << i)) < 1)
                    {
                        continue;
                    }

                    int len = s_Rays.Count;

                    for (int n = 0; n < len; n++)
                    {
                        Vector3 flipVec = ((BrushMirror)(1u << i)).ToVector3();

                        if (mirrorSettings.Space == MirrorCoordinateSpace.World)
                        {
                            Vector3 cen = editable.gameObjectAttached.GetComponent <Renderer>().bounds.center;
                            s_Rays.Add(new Ray(Vector3.Scale(s_Rays[n].origin - cen, flipVec) + cen,
                                               Vector3.Scale(s_Rays[n].direction, flipVec)));
                        }
                        else
                        {
                            Transform t = SceneView.lastActiveSceneView.camera.transform;
                            Vector3   o = t.InverseTransformPoint(s_Rays[n].origin);
                            Vector3   d = t.InverseTransformDirection(s_Rays[n].direction);
                            s_Rays.Add(new Ray(t.TransformPoint(Vector3.Scale(o, flipVec)),
                                               t.TransformDirection(Vector3.Scale(d, flipVec))));
                        }
                    }
                }
            }

            bool hitMesh = false;

            int[] triangles = editable.editMesh.GetTriangles();
            foreach (Ray ray in s_Rays)
            {
                PolyRaycastHit hit;

                if (PolySceneUtility.WorldRaycast(ray, editable.transform, editable.visualMesh.vertices, triangles,
                                                  out hit))
                {
                    target.raycastHits.Add(hit);
                    hitMesh = true;
                }
            }

            PolySceneUtility.CalculateWeightedVertices(target, brushSettings, tool, mode);

            if (hitMesh)
            {
                Transform[] trs  = Selection.GetTransforms(SelectionMode.Unfiltered);
                var         hits = target.raycastHits;
                foreach (var selectedTransform in trs)
                {
                    bool isValid = false;
                    if (selectedTransform != editable.transform)
                    {
                        BrushTarget secondaryTarget = GetOrCreateBrushTarget(selectedTransform.gameObject);
                        isValid = Util.IsValid(secondaryTarget);
                        if (isValid)
                        {
                            m_SecondaryBrushTargets.Add(secondaryTarget);
                            secondaryTarget.ClearRaycasts();

                            foreach (var hit in hits)
                            {
                                PolyRaycastHit secondaryHit = new PolyRaycastHit(hit.distance,
                                                                                 secondaryTarget.transform.InverseTransformPoint(editable.transform.TransformPoint(hit.position)),
                                                                                 hit.normal,
                                                                                 -1);
                                secondaryTarget.raycastHits.Add(secondaryHit);
                            }
                        }
                        PolySceneUtility.CalculateWeightedVertices(secondaryTarget, brushSettings, tool, mode);
                    }
                }
            }

            return(hitMesh);
        }
示例#12
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();
        }
示例#13
0
        void OnGUI()
        {
            Profiler.BeginSample("Polybrush GUI");
            Event e = Event.current;

            GUILayout.Space(8);

            DoContextMenu();
            DrawToolbar();
            CheckForEscapeKey(e);

            // Call current mode GUI
            if (mode != null)
            {
                m_Scroll = EditorGUILayout.BeginScrollView(m_Scroll);

                DrawBrushSettings();
                m_BrushMirrorEditor.OnGUI();
                if (tool != BrushTool.None)
                {
                    DrawActiveToolmodeSettings();
                }

                EditorGUILayout.Space();

                if (EditorGUI.EndChangeCheck())
                {
                    mode.OnBrushSettingsChanged(brushTarget, brushSettings);
                }

                EditorGUILayout.EndScrollView();
            }

#if POLYBRUSH_DEBUG
            GUILayout.Label("DEBUG", EditorStyles.boldLabel);

            GUILayout.Label("target: " + (Util.IsValid(brushTarget) ? brushTarget.editableObject.gameObjectAttached.name : "null"));
            GUILayout.Label("vertex: " + (Util.IsValid(brushTarget) ? brushTarget.editableObject.vertexCount : 0));
            GUILayout.Label("applying: " + m_ApplyingBrush);
            GUILayout.Label("lockBrushToFirst: " + s_LockBrushToFirst);
            GUILayout.Label("lastHoveredGameObject: " + m_LastHoveredGameObject);

            GUILayout.Space(6);

            foreach (var kvp in m_Hovering)
            {
                BrushTarget    t            = kvp.Value;
                EditableObject dbg_editable = t.editableObject;
                GUILayout.Label("Vertex Streams: " + dbg_editable.usingVertexStreams);
                GUILayout.Label("Original: " + (dbg_editable.originalMesh == null ? "null" : dbg_editable.originalMesh.name));
                GUILayout.Label("Active: " + (dbg_editable.editMesh == null ? "null" : dbg_editable.editMesh.name));
                GUILayout.Label("Graphics: " + (dbg_editable.graphicsMesh == null ? "null" : dbg_editable.graphicsMesh.name));
            }
#endif

            if (m_WantsRepaint)
            {
                m_WantsRepaint = false;
                Repaint();
            }
            Profiler.EndSample();
        }
        // Called whenever the brush is moved.  Note that @target may have a null editableObject.
        internal override void OnBrushMove(BrushTarget target, BrushSettings settings)
        {
            base.OnBrushMove(target, settings);

            if (!Util.IsValid(target) || !m_LikelySupportsTextureBlending)
            {
                return;
            }

            bool invert = settings.isUserHoldingControl;

            float[] weights;

            if (paintMode == PaintMode.Brush)
            {
                weights = target.GetAllWeights();
            }
            else if (paintMode == PaintMode.Flood)
            {
                weights = new float[m_VertexCount];

                for (int i = 0; i < m_VertexCount; i++)
                {
                    weights[i] = 1f;
                }
            }
            else
            {
                weights = new float[m_VertexCount];
                int[] indices      = target.editableObject.editMesh.GetTriangles();
                int   index        = 0;
                float weightTarget = 1f;

                foreach (PolyRaycastHit hit in target.raycastHits)
                {
                    if (hit.triangle > -1)
                    {
                        index = hit.triangle * 3;

                        m_FillModeEdges[0].x = indices[index + 0];
                        m_FillModeEdges[0].y = indices[index + 1];

                        m_FillModeEdges[1].x = indices[index + 1];
                        m_FillModeEdges[1].y = indices[index + 2];

                        m_FillModeEdges[2].x = indices[index + 2];
                        m_FillModeEdges[2].y = indices[index + 0];

                        for (int i = 0; i < 3; i++)
                        {
                            if (m_TriangleLookup.TryGetValue(m_FillModeEdges[i], out m_FillModeAdjacentTriangles))
                            {
                                for (int n = 0; n < m_FillModeAdjacentTriangles.Count; n++)
                                {
                                    index = m_FillModeAdjacentTriangles[n] * 3;

                                    weights[indices[index]]     = weightTarget;
                                    weights[indices[index + 1]] = weightTarget;
                                    weights[indices[index + 2]] = weightTarget;
                                }
                            }
                        }
                    }
                }
            }

            if (m_SelectedAttributeIndex < 0 || m_SelectedAttributeIndex >= meshAttributes.Length)
            {
                SetBrushColorWithAttributeIndex(0);
            }

            int mask = meshAttributes[m_SelectedAttributeIndex].mask;

            splat_current.LerpWeights(splat_cache, invert ? splat_erase : splat_target, mask, weights);
            splat_current.Apply(target.editableObject.editMesh);
            target.editableObject.ApplyMeshAttributes();
        }
示例#15
0
 /// <summary>
 /// Called whenever the brush is moved. Note that @target may have a null editableObject.
 /// </summary>
 /// <param name="target">Current target of the brush</param>
 /// <param name="settings">Current brush settings</param>
 internal virtual void OnBrushMove(BrushTarget target, BrushSettings settings)
 {
     UpdateTempComponent(target, settings);
 }
        internal override void DrawGizmos(BrushTarget target, BrushSettings settings)
        {
            PolyMesh mesh = target.editableObject.editMesh;

            if (Util.IsValid(target) && paintMode == PaintMode.Fill)
            {
                Vector3[] vertices = mesh.vertices;
                int[]     indices  = mesh.GetTriangles();

                PolyHandles.PushMatrix();
                PolyHandles.PushHandleColor();

                Handles.matrix = target.transform.localToWorldMatrix;

                int index = 0;

                foreach (PolyRaycastHit hit in target.raycastHits)
                {
                    if (hit.triangle > -1)
                    {
                        Handles.color = Color.green;

                        index = hit.triangle * 3;

                        Handles.DrawLine(vertices[indices[index + 0]] + hit.normal * .1f, vertices[indices[index + 1]] + hit.normal * .1f);
                        Handles.DrawLine(vertices[indices[index + 1]] + hit.normal * .1f, vertices[indices[index + 2]] + hit.normal * .1f);
                        Handles.DrawLine(vertices[indices[index + 2]] + hit.normal * .1f, vertices[indices[index + 0]] + hit.normal * .1f);

                        m_FillModeEdges[0].x = indices[index + 0];
                        m_FillModeEdges[0].y = indices[index + 1];

                        m_FillModeEdges[1].x = indices[index + 1];
                        m_FillModeEdges[1].y = indices[index + 2];

                        m_FillModeEdges[2].x = indices[index + 2];
                        m_FillModeEdges[2].y = indices[index + 0];

                        for (int i = 0; i < 3; i++)
                        {
                            if (m_TriangleLookup.TryGetValue(m_FillModeEdges[i], out m_FillModeAdjacentTriangles))
                            {
                                for (int n = 0; n < m_FillModeAdjacentTriangles.Count; n++)
                                {
                                    index = m_FillModeAdjacentTriangles[n] * 3;

                                    Handles.DrawLine(vertices[indices[index + 0]] + hit.normal * .1f, vertices[indices[index + 1]] + hit.normal * .1f);
                                    Handles.DrawLine(vertices[indices[index + 1]] + hit.normal * .1f, vertices[indices[index + 2]] + hit.normal * .1f);
                                    Handles.DrawLine(vertices[indices[index + 2]] + hit.normal * .1f, vertices[indices[index + 0]] + hit.normal * .1f);
                                }
                            }
                        }
                    }
                }

                PolyHandles.PopHandleColor();
                PolyHandles.PopMatrix();
            }
            else
            {
                base.DrawGizmos(target, settings);
            }
        }
示例#17
0
 /// <summary>
 /// Called when the mouse begins a drag across a valid target.
 /// </summary>
 /// <param name="target"> The object the mouse is dragging on</param>
 /// <param name="settings">Current brush settings</param>
 internal virtual void OnBrushBeginApply(BrushTarget target, BrushSettings settings)
 {
 }
        void PlaceGameObject(PolyRaycastHit hit, PrefabAndSettings prefabAndSettings, BrushTarget target, BrushSettings settings)
        {
            if (prefabAndSettings == null)
            {
                return;
            }

            GameObject prefab = prefabAndSettings.gameObject;

            var worldPosition = target.transform.TransformPoint(hit.position);
            var worldNormal   = target.transform.TransformDirection(hit.normal);
            Ray ray           = RandomRay(worldPosition, worldNormal, settings.radius, settings.falloff, settings.falloffCurve);

            ray.origin    = target.transform.InverseTransformPoint(ray.origin);
            ray.direction = target.transform.InverseTransformDirection(ray.direction);

            PolyRaycastHit rand_hit;

            Vector3[] vertices  = target.editableObject.editMesh.vertices;
            int[]     triangles = target.editableObject.editMesh.GetTriangles();

            if (PolySceneUtility.MeshRaycast(ray, vertices, triangles, out rand_hit))
            {
                PlacementSettings placementSettings = prefabAndSettings.settings;
                Vector3           scaleSetting      = prefab.transform.localScale;
                if (placementSettings.uniformBool)
                {
                    float uniformScale = Random.Range(placementSettings.uniformScale.x, placementSettings.uniformScale.y);
                    scaleSetting *= uniformScale;
                }
                else
                {
                    if (placementSettings.xScaleBool)
                    {
                        scaleSetting.x = Random.Range(placementSettings.scaleRangeMin.x, placementSettings.scaleRangeMax.x);
                    }
                    if (placementSettings.yScaleBool)
                    {
                        scaleSetting.y = Random.Range(placementSettings.scaleRangeMin.y, placementSettings.scaleRangeMax.y);
                    }
                    if (placementSettings.zScaleBool)
                    {
                        scaleSetting.z = Random.Range(placementSettings.scaleRangeMin.z, placementSettings.scaleRangeMax.z);
                    }
                }

                Vector3 rotationSetting = Vector3.zero;
                if (placementSettings.xRotationBool)
                {
                    rotationSetting.x = Random.Range(placementSettings.rotationRangeMin.x, placementSettings.rotationRangeMax.x);
                }
                if (placementSettings.yRotationBool)
                {
                    rotationSetting.y = Random.Range(placementSettings.rotationRangeMin.y, placementSettings.rotationRangeMax.y);
                }
                if (placementSettings.xRotationBool)
                {
                    rotationSetting.z = Random.Range(placementSettings.rotationRangeMin.z, placementSettings.rotationRangeMax.z);
                }

                Quaternion rotation = SceneView.lastActiveSceneView.in2DMode ?
                                      Quaternion.FromToRotation(-Vector3.forward, target.transform.TransformDirection(rand_hit.normal)):
                                      Quaternion.FromToRotation(Vector3.up, target.transform.TransformDirection(rand_hit.normal));

                GameObject inst = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
                inst.transform.position   = target.transform.TransformPoint(rand_hit.position);
                inst.transform.rotation   = rotation;
                inst.transform.localScale = scaleSetting;

                float pivotOffset = s_UsePivotForPlacement ? 0f : GetPivotOffset(inst);

                inst.name = FormatInstanceName(prefab);

                inst.transform.position = inst.transform.position - (inst.transform.up * pivotOffset);
                inst.transform.rotation = inst.transform.rotation * Quaternion.Euler(rotationSetting);

                if (SceneView.lastActiveSceneView.in2DMode)
                {
                    inst.transform.position += Vector3.back * s_2DDepthOffset;
                }

                if (s_AvoidOverlappingGameObjects && TestIntersection(inst))
                {
                    Object.DestroyImmediate(inst);
                    return;
                }

                if (s_ParentObjectWithSurface)
                {
                    inst.transform.SetParent(target.transform);
                }

                m_PrefabsInstances.Add(inst);

                Undo.RegisterCreatedObjectUndo(inst, UndoMessage);
            }
        }
示例#19
0
 /// <summary>
 /// Called every time the brush should apply itself to a valid target.  Default is on mouse move.
 /// </summary>
 /// <param name="target">Object on which to apply the brush</param>
 /// <param name="settings">Current brush settings</param>
 internal abstract void OnBrushApply(BrushTarget target, BrushSettings settings);
示例#20
0
        internal override void OnBrushApply(BrushTarget target, BrushSettings settings)
        {
            if (!likelyToSupportVertexSculpt)
            {
                return;
            }

            int rayCount = target.raycastHits.Count;


            Vector3  v, t, avg, dirVec = s_SmoothDirection.value.ToVector3();
            Plane    plane = new Plane(Vector3.up, Vector3.zero);
            PolyMesh mesh  = target.editableObject.editMesh;

            Vector3[] normals     = (s_SmoothDirection == PolyDirection.BrushNormal) ? mesh.normals : null;
            int       vertexCount = mesh.vertexCount;

            // don't use target.GetAllWeights because brush normal needs
            // to know which ray to use for normal
            for (int ri = 0; ri < rayCount; ri++)
            {
                PolyRaycastHit hit = target.raycastHits[ri];

                if (hit.weights == null || hit.weights.Length < vertexCount)
                {
                    continue;
                }

                for (int i = 0; i < commonVertexCount; i++)
                {
                    int index = commonVertices[i][0];

                    if (hit.weights[index] < .0001f || (s_IgnoreOpenEdges && nonManifoldIndices.Contains(index)))
                    {
                        continue;
                    }

                    v = vertices[index];

                    if (s_SmoothDirection == PolyDirection.VertexNormal)
                    {
                        avg = Math.Average(vertices, neighborLookup[index]);
                    }
                    else
                    {
                        avg = Math.WeightedAverage(vertices, neighborLookup[index], hit.weights);

                        if (s_SmoothDirection == PolyDirection.BrushNormal)
                        {
                            if (s_UseFirstNormalVector)
                            {
                                dirVec = brushNormalOnBeginApply[ri].normalized;
                            }
                            else
                            {
                                dirVec = Math.WeightedAverage(normals, neighborLookup[index], hit.weights).normalized;
                            }
                        }

                        plane.SetNormalAndPosition(dirVec, avg);
                        avg = v - dirVec * plane.GetDistanceToPoint(v);
                    }

                    t = Vector3.Lerp(v, avg, hit.weights[index]);
                    int[] indices = commonVertices[i];

                    Vector3 pos = v + (t - v) * settings.strength * SMOOTH_STRENGTH_MODIFIER;

                    for (int n = 0; n < indices.Length; n++)
                    {
                        vertices[indices[n]] = pos;
                    }
                }
            }

            mesh.vertices = vertices;

            if (tempComponent != null)
            {
                tempComponent.OnVerticesMoved(mesh);
            }

            base.OnBrushApply(target, settings);
        }
示例#21
0
 /// <summary>
 /// Called when a brush application has finished.  Use this to clean up temporary resources or apply
 /// deferred actions to a mesh (rebuild UV2, tangents, whatever).
 /// </summary>
 /// <param name="target">The Object the brush was being applied on</param>
 /// <param name="settings">Current brush settings</param>
 internal virtual void OnBrushFinishApply(BrushTarget target, BrushSettings settings)
 {
     DestroyTempComponent();
 }
示例#22
0
 internal override void OnBrushSettingsChanged(BrushTarget target, BrushSettings settings)
 {
     base.OnBrushSettingsChanged(target, settings);
 }
示例#23
0
        /// <summary>
        /// Draw scene gizmos. Base implementation draws the brush preview.
        /// </summary>
        /// <param name="target">Current target Object</param>
        /// <param name="settings">Current brush settings</param>
        internal virtual void DrawGizmos(BrushTarget target, BrushSettings settings)
        {
            UpdateBrushGizmosColor();
            foreach (PolyRaycastHit hit in target.raycastHits)
            {
                PolyHandles.DrawBrush(hit.position, hit.normal, settings, target.localToWorldMatrix, innerColor, outerColor);
            }

#if Z_DEBUG
#if Z_DRAW_WEIGHTS || DRAW_PER_VERTEX_ATTRIBUTES
            float[] w = target.GetAllWeights();
#endif

#if Z_DRAW_WEIGHTS
            Mesh       m       = target.mesh;
            Vector3[]  v       = m.vertices;
            GUIContent content = new GUIContent("", "");

            Handles.BeginGUI();
            for (int i = 0; i < v.Length; i++)
            {
                if (w[i] < .0001f)
                {
                    continue;
                }

                content.text = w[i].ToString("F2");
                GUI.Label(HandleUtility.WorldPointToSizedRect(target.transform.TransformPoint(v[i]), content, EditorStyles.label), content);
            }
            Handles.EndGUI();
#endif

#if DRAW_PER_VERTEX_ATTRIBUTES
            Mesh           m        = target.editableObject.editMesh;
            Color32[]      colors   = m.colors;
            Vector4[]      tangents = m.tangents;
            List <Vector4> uv0      = m.uv0;
            List <Vector4> uv1      = m.uv1;
            List <Vector4> uv2      = m.uv2;
            List <Vector4> uv3      = m.uv3;

            int vertexCount = m.vertexCount;

            Vector3[]  verts = m.vertices;
            GUIContent gc    = new GUIContent("");

            List <List <int> >        common = MeshUtility.GetCommonVertices(m);
            System.Text.StringBuilder sb     = new System.Text.StringBuilder();

            Handles.BeginGUI();
            foreach (List <int> l in common)
            {
                if (w[l[0]] < .001)
                {
                    continue;
                }

                Vector3 v = target.transform.TransformPoint(verts[l[0]]);

                if (colors != null)
                {
                    sb.AppendLine("color: " + colors[l[0]].ToString("F2"));
                }
                if (tangents != null)
                {
                    sb.AppendLine("tangent: " + tangents[l[0]].ToString("F2"));
                }
                if (uv0 != null && uv0.Count == vertexCount)
                {
                    sb.AppendLine("uv0: " + uv0[l[0]].ToString("F2"));
                }
                if (uv1 != null && uv1.Count == vertexCount)
                {
                    sb.AppendLine("uv1: " + uv1[l[0]].ToString("F2"));
                }
                if (uv2 != null && uv2.Count == vertexCount)
                {
                    sb.AppendLine("uv2: " + uv2[l[0]].ToString("F2"));
                }
                if (uv3 != null && uv3.Count == vertexCount)
                {
                    sb.AppendLine("uv3: " + uv3[l[0]].ToString("F2"));
                }

                gc.text = sb.ToString();
                sb.Remove(0, sb.Length);                        // @todo .NET 4.0
                GUI.Label(HandleUtility.WorldPointToSizedRect(v, gc, EditorStyles.label), gc);
            }
            Handles.EndGUI();
#endif
#endif
        }
示例#24
0
 internal override void OnBrushBeginApply(BrushTarget target, BrushSettings settings)
 {
     base.OnBrushBeginApply(target, settings);
     m_PrefabsInstances = PolySceneUtility.FindInstancesInScene(prefabPalette.prefabs.Select(x => x.gameObject), FormatInstanceName).ToList();
 }
 internal override void OnBrushBeginApply(BrushTarget brushTarget, BrushSettings brushSettings)
 {
     base.OnBrushBeginApply(brushTarget, brushSettings);
 }