Exemple #1
0
        public static bool FindTriangle(this SpriteMeshData spriteMeshData, Vector2 point, out Vector3Int indices, out Vector3 barycentricCoords)
        {
            indices           = Vector3Int.zero;
            barycentricCoords = Vector3.zero;

            if (spriteMeshData.indices.Count < 3)
            {
                return(false);
            }

            int triangleCount = spriteMeshData.indices.Count / 3;

            for (int i = 0; i < triangleCount; ++i)
            {
                indices.x = spriteMeshData.indices[i * 3];
                indices.y = spriteMeshData.indices[i * 3 + 1];
                indices.z = spriteMeshData.indices[i * 3 + 2];

                MeshModuleUtility.Barycentric(
                    point,
                    spriteMeshData.vertices[indices.x].position,
                    spriteMeshData.vertices[indices.y].position,
                    spriteMeshData.vertices[indices.z].position,
                    out barycentricCoords);

                if (barycentricCoords.x >= 0f && barycentricCoords.y >= 0f && barycentricCoords.z >= 0f)
                {
                    return(true);
                }
            }

            return(false);
        }
Exemple #2
0
        private bool SegmentIntersectsEdge(Vector2 p1, Vector2 p2, int ignoreIndex, ref Vector2 point, out int intersectingEdgeIndex)
        {
            intersectingEdgeIndex = -1;

            float sqrDistance = float.MaxValue;

            for (int i = 0; i < spriteMeshData.edges.Count; i++)
            {
                Edge    edge     = spriteMeshData.edges[i];
                Vector2 v1       = spriteMeshData.vertices[edge.index1].position;
                Vector2 v2       = spriteMeshData.vertices[edge.index2].position;
                Vector2 pointTmp = Vector2.zero;

                if (!edge.Contains(ignoreIndex) && MeshModuleUtility.SegmentIntersection(p1, p2, v1, v2, ref pointTmp))
                {
                    float sqrMagnitude = (pointTmp - p1).sqrMagnitude;
                    if (sqrMagnitude < sqrDistance)
                    {
                        sqrDistance           = sqrMagnitude;
                        intersectingEdgeIndex = i;
                        point = pointTmp;
                    }
                }
            }

            return(intersectingEdgeIndex != -1);
        }
Exemple #3
0
        public static List <SpriteBoneData> CreateSpriteBoneData(List <SpriteBone> spriteBoneList, Matrix4x4 rootMatrix)
        {
            List <SpriteBoneData> spriteBoneDataList = new List <SpriteBoneData>(spriteBoneList.Count);

            foreach (var spriteBone in spriteBoneList)
            {
                spriteBoneDataList.Add(new SpriteBoneData()
                {
                    name          = spriteBone.name,
                    parentId      = spriteBone.parentId,
                    localPosition = spriteBone.position,
                    localRotation = spriteBone.rotation,
                    depth         = spriteBone.position.z,
                    length        = spriteBone.length
                });
            }

            Matrix4x4[] localToWorldMatrices = null;
            MeshModuleUtility.UpdateLocalToWorldMatrices(spriteBoneDataList, rootMatrix, ref localToWorldMatrices);

            for (int i = 0; i < spriteBoneDataList.Count; ++i)
            {
                var spriteBoneData = spriteBoneDataList[i];
                spriteBoneData.position    = localToWorldMatrices[i].MultiplyPoint(Vector2.zero);
                spriteBoneData.endPosition = localToWorldMatrices[i].MultiplyPoint(Vector2.right * spriteBoneData.length);
            }

            return(spriteBoneDataList);
        }
        public void LayoutEdge(Vector2 startPosition, Vector2 endPosition, int index)
        {
            int controlID = guiWrapper.GetControlID(m_EdgeHashCode, FocusType.Passive);

            float distance = guiWrapper.DistanceToSegment(startPosition, endPosition);

            guiWrapper.LayoutControl(controlID, distance);

            if (guiWrapper.eventType == EventType.Layout)
            {
                if (guiWrapper.IsControlNearest(controlID))
                {
                    m_HoveredEdge          = index;
                    m_HoveredEdgeControlID = controlID;
                }

                distance = HandleUtility.DistancePointToLineSegment(MeshModuleUtility.ClampPositionToRect(mouseWorldPosition, frame), startPosition, endPosition);

                if (distance < m_MinDistance)
                {
                    m_MinDistance      = distance;
                    m_ClosestEdgeIndex = index;
                }
            }
        }
        private void HandleRotateBone()
        {
            if (bindPoseView.IsActionTriggering(BindPoseAction.RotateBone))
            {
                m_PreviewChanged = false;
                undoObject.RegisterCompleteObjectUndo("Rotate Bone");
                UpdateBones();
            }

            if (bindPoseView.IsActionFinishing(BindPoseAction.RotateBone))
            {
                m_PreviewChanged = true;
                undoObject.RevertAllInCurrentGroup();
                UpdateBones();
            }

            Vector2 lookAtPosition;

            if (bindPoseView.DoRotateBone(out lookAtPosition))
            {
                if (selection.single == -1)
                {
                    throw new ArgumentException("no bone or multiple bone selected");
                }

                var spriteBoneData      = spriteMeshData.bones[selection.single];
                var localLookAtPosition = localToWorldMatrices[selection.single].inverse.MultiplyPoint3x4(lookAtPosition);
                spriteBoneData.localRotation = MeshModuleUtility.NormalizeQuaternion(spriteBoneData.localRotation * Quaternion.FromToRotation(Vector2.right, localLookAtPosition));
                m_PreviewChanged             = true;
                UpdateBones();
            }
        }
        private void UpdateBindPose()
        {
            MeshModuleUtility.UpdateLocalToWorldMatrices(spriteMeshData.bones, spriteMeshData.CalculateRootMatrix(), ref m_BindPose);

            for (int i = 0; i < m_BindPose.Length; ++i)
            {
                m_BindPose[i] = m_BindPose[i].inverse;
            }
        }
        private void UpdateBones()
        {
            MeshModuleUtility.UpdateLocalToWorldMatrices(spriteMeshData.bones, spriteMeshData.CalculateRootMatrix(), ref m_LocalToWorldMatrices);
            spriteMeshData.UpdateSpriteBoneDataWorldPosition(m_LocalToWorldMatrices);

            if (onSkinPreviewChanged != null)
            {
                onSkinPreviewChanged.Invoke();
            }
        }
        public override void DoMainGUI()
        {
            HandleSpriteRectSelectionChange();
            DrawGizmos();

            SetupElements();

            if (m_CachedSpriteMeshData != null)
            {
                m_MeshPreview.Prepare();

                if (m_SpriteMeshCache.mode == Mode.Weights)
                {
                    MeshModuleUtility.DrawMesh(m_MeshPreview.mesh, m_MeshPreview.meterial);
                }

                m_MeshPreview.DrawTriangles();

                if (!m_BindPoseController.inSkinningPreview)
                {
                    EditorGUI.BeginChangeCheck();

                    m_SpriteMeshController.OnGUI();

                    if (EditorGUI.EndChangeCheck())
                    {
                        m_MeshPreview.SetVerticesDirty();
                        m_MeshPreview.SetIndicesDirty();
                        spriteEditor.SetDataModified();
                    }
                }

                if (m_SpriteMeshCache.mode == Mode.Weights)
                {
                    m_BindPoseController.DoBoneGUI();
                }

                m_RectSelectionTool.OnGUI();
                m_UnselectTool.OnGUI();

                if (m_SpriteMeshCache.mode == Mode.Weights && m_SpriteMeshCache.selectedWeightTool == WeightTool.Brush && m_BindPoseView.hoveredBone == -1)
                {
                    EditorGUI.BeginChangeCheck();

                    m_BrushWeightTool.OnGUI();

                    if (EditorGUI.EndChangeCheck())
                    {
                        m_MeshPreview.SetWeightsDirty();
                        spriteEditor.SetDataModified();
                    }
                }
            }
        }
Exemple #9
0
        private void MoveSelectedVertices(Vector2 delta)
        {
            delta = MeshModuleUtility.MoveRectInsideFrame(CalculateRectFromSelection(), spriteMeshData.frame, delta);

            undoObject.RegisterCompleteObjectUndo("Move Vertices");

            foreach (int index in selection)
            {
                Vector2 v = spriteMeshData.vertices[index].position;
                spriteMeshData.SetVertexPosition(index, ClampToFrame(v + delta));
            }

            spriteMeshData.Triangulate(triangulator);
        }
        private void WeightChannelDrawer(
            ref bool isChannelEnabled, ref BoneWeightData boneWeightData,
            bool isChannelEnabledMixed = false, bool isBoneIndexMixed = false, bool isWeightMixed = false)
        {
            EditorGUILayout.BeginHorizontal();

            EditorGUIUtility.fieldWidth = 1f;
            EditorGUIUtility.labelWidth = 1f;

            EditorGUI.showMixedValue = isChannelEnabledMixed;
            isChannelEnabled         = EditorGUILayout.Toggle(GUIContent.none, isChannelEnabled);

            EditorGUIUtility.fieldWidth = 30f;
            EditorGUIUtility.labelWidth = 30f;

            using (new EditorGUI.DisabledScope(!isChannelEnabled && !isChannelEnabledMixed))
            {
                int tempBoneIndex = GUI.enabled ? boneWeightData.boneIndex : -1;

                EditorGUI.BeginChangeCheck();

                EditorGUI.showMixedValue = GUI.enabled && isBoneIndexMixed;
                tempBoneIndex            = EditorGUILayout.Popup(tempBoneIndex, MeshModuleUtility.GetBoneNameList(spriteMeshData));

                if (EditorGUI.EndChangeCheck())
                {
                    boneWeightData.boneIndex = tempBoneIndex;
                }

                EditorGUIUtility.fieldWidth = 45f;

                EditorGUI.showMixedValue = isWeightMixed;
                boneWeightData.weight    = EditorGUILayout.Slider(GUIContent.none, boneWeightData.weight, 0f, 1f);
            }

            EditorGUILayout.EndHorizontal();

            EditorGUI.showMixedValue    = false;
            EditorGUIUtility.labelWidth = -1;
            EditorGUIUtility.fieldWidth = -1;
        }
Exemple #11
0
 private Vector2 ClampToFrame(Vector2 position)
 {
     return(MeshModuleUtility.ClampPositionToRect(position, spriteMeshData.frame));
 }
Exemple #12
0
        private void CreateVertex(Vector2 position, int edgeIndex)
        {
            position = MeshModuleUtility.ClampPositionToRect(position, spriteMeshData.frame);
            undoObject.RegisterCompleteObjectUndo("Create Vertex");

            BoneWeight boneWeight = new BoneWeight();

            Vector3Int indices;
            Vector3    barycentricCoords;

            if (spriteMeshData.FindTriangle(position, out indices, out barycentricCoords))
            {
                EditableBoneWeight bw1 = spriteMeshData.vertices[indices.x].editableBoneWeight;
                EditableBoneWeight bw2 = spriteMeshData.vertices[indices.y].editableBoneWeight;
                EditableBoneWeight bw3 = spriteMeshData.vertices[indices.z].editableBoneWeight;

                EditableBoneWeight result = new EditableBoneWeight();

                foreach (BoneWeightChannel channel in bw1)
                {
                    if (!channel.enabled)
                    {
                        continue;
                    }

                    BoneWeightData data = channel.boneWeightData;
                    data.weight *= barycentricCoords.x;

                    if (data.weight > 0f)
                    {
                        result.AddChannel(data, true);
                    }
                }

                foreach (BoneWeightChannel channel in bw2)
                {
                    if (!channel.enabled)
                    {
                        continue;
                    }

                    BoneWeightData data = channel.boneWeightData;
                    data.weight *= barycentricCoords.y;

                    if (data.weight > 0f)
                    {
                        result.AddChannel(data, true);
                    }
                }

                foreach (BoneWeightChannel channel in bw3)
                {
                    if (!channel.enabled)
                    {
                        continue;
                    }

                    BoneWeightData data = channel.boneWeightData;
                    data.weight *= barycentricCoords.z;

                    if (data.weight > 0f)
                    {
                        result.AddChannel(data, true);
                    }
                }

                result.UnifyChannelsWithSameBoneIndex();
                result.FilterChannels(0f);
                result.ClampChannels(4, true);

                boneWeight = result.ToBoneWeight(true);
            }
            else if (edgeIndex != -1)
            {
                Edge    edge = spriteMeshData.edges[edgeIndex];
                Vector2 pos1 = spriteMeshData.vertices[edge.index1].position;
                Vector2 pos2 = spriteMeshData.vertices[edge.index2].position;
                Vector2 dir1 = (position - pos1);
                Vector2 dir2 = (pos2 - pos1);
                float   t    = Vector2.Dot(dir1, dir2.normalized) / dir2.magnitude;
                t = Mathf.Clamp01(t);
                BoneWeight bw1 = spriteMeshData.vertices[edge.index1].editableBoneWeight.ToBoneWeight(true);
                BoneWeight bw2 = spriteMeshData.vertices[edge.index2].editableBoneWeight.ToBoneWeight(true);

                boneWeight = EditableBoneWeightUtility.Lerp(bw1, bw2, t);
            }

            spriteMeshData.CreateVertex(position, edgeIndex);
            spriteMeshData.vertices[spriteMeshData.vertices.Count - 1].editableBoneWeight.SetFromBoneWeight(boneWeight);
            spriteMeshData.Triangulate(triangulator);
        }
 public Vector3 GUIToWorld(Vector2 guiPosition, Vector3 planeNormal, Vector3 planePosition)
 {
     return(MeshModuleUtility.GUIToWorld(guiPosition, planeNormal, planePosition));
 }
 public Vector2 GUIToWorld(Vector2 guiPosition)
 {
     return(MeshModuleUtility.GUIToWorld(guiPosition));
 }
        public void OnInspectorGUI()
        {
            Debug.Assert(weightEditor != null);

            weightEditor.mode = (WeightEditorMode)EditorGUILayout.EnumPopup(Contents.mode, weightEditor.mode);

            if (weightEditor.mode != WeightEditorMode.Smooth)
            {
                weightEditor.boneIndex = EditorGUILayout.Popup(Contents.selectedBone, weightEditor.boneIndex, MeshModuleUtility.GetBoneNameList(weightEditor.spriteMeshData));
            }

            weightEditor.autoNormalize = EditorGUILayout.Toggle(Contents.autoNormalize, weightEditor.autoNormalize);

            radius = EditorGUILayout.FloatField(Contents.size, radius);
            radius = Mathf.Max(1f, radius);

            EditorGUIUtility.labelWidth = 70f;

            hardness = EditorGUILayout.Slider(Contents.hardness, hardness, 1f, 100f);
            step     = EditorGUILayout.Slider(Contents.step, step, 1f, 100f);

            EditorGUIUtility.labelWidth = 0f;

            if (weightEditor.boneIndex == -1 && weightEditor.mode != WeightEditorMode.Smooth)
            {
                EditorGUILayout.HelpBox(Contents.helpMessage.text, MessageType.Info, true);
            }
        }
        public void OnGUI()
        {
            m_ControlID = GUIUtility.GetControlID("BrushWeightEditor".GetHashCode(), FocusType.Passive);

            EventType eventType = Event.current.GetTypeForControl(controlID);

            weightEditor.selection = m_Selection;

            m_CircleVertexSelector.vertices = weightEditor.spriteMeshData.vertices;

            Vector2 position = MeshModuleUtility.GUIToWorld(Event.current.mousePosition);

            if (eventType == EventType.Layout && !Event.current.alt)
            {
                HandleUtility.AddControl(controlID, 0f);
            }

            if (GUIUtility.hotControl == 0 && HandleUtility.nearestControl == controlID &&
                eventType == EventType.MouseDown && Event.current.button == 0 && !Event.current.alt)
            {
                GUIUtility.hotControl = controlID;
                GUI.changed           = true;

                m_DeltaAcc     = 0f;
                m_LastPosition = position;

                weightEditor.OnEditStart(true);
                OnBrush(hardness / 100f, position);

                Event.current.Use();
            }

            if (GUIUtility.hotControl == controlID && eventType == EventType.MouseUp && Event.current.button == 0)
            {
                GUIUtility.hotControl = 0;

                weightEditor.OnEditEnd();

                GUI.changed = true;
                Event.current.Use();
            }

            if (HandleUtility.nearestControl == controlID && Event.current.shift && eventType == EventType.ScrollWheel)
            {
                float radiusDelta = HandleUtility.niceMouseDeltaZoom * k_WheelRadiusSpeed;
                radius = Mathf.Max(1f, radius + radiusDelta);

                UpdateSelection(position);

                Event.current.Use();
            }

            if (GUIUtility.hotControl == 0 && HandleUtility.nearestControl == controlID && eventType == EventType.MouseMove)
            {
                UpdateSelection(position);

                Event.current.Use();
            }

            if (GUIUtility.hotControl == controlID && eventType == EventType.MouseDrag)
            {
                step = Mathf.Max(step, 1f);

                Vector2 delta         = position - m_LastPosition;
                Vector2 direction     = delta.normalized;
                Vector2 startPosition = m_LastPosition - direction * m_DeltaAcc;
                float   magnitude     = delta.magnitude;

                m_DeltaAcc += magnitude;

                if (m_DeltaAcc >= step)
                {
                    Vector2 stepVector      = direction * step;
                    Vector2 currentPosition = startPosition;

                    while (m_DeltaAcc >= step)
                    {
                        currentPosition += stepVector;

                        OnBrush(hardness / 100f, currentPosition);

                        m_DeltaAcc -= step;
                    }
                }

                m_LastPosition = position;

                GUI.changed = true;
                Event.current.Use();
            }

            if ((GUIUtility.hotControl == controlID || (GUIUtility.hotControl == 0 && HandleUtility.nearestControl == controlID)) && eventType == EventType.Repaint)
            {
                Color oldColor = Handles.color;

                Handles.color = Color.white;

                if (isSecondaryAction)
                {
                    Handles.color = Color.red;
                }

                if (GUIUtility.hotControl == controlID)
                {
                    Handles.color = Color.yellow;
                }

                Handles.DrawWireDisc(position, Vector3.forward, radius);

                Handles.color = oldColor;
            }
        }
        public override void OnModuleActivate()
        {
            InitStyles();

            Undo.undoRedoPerformed           += UndoRedoPerformed;
            spriteEditor.enableMouseMoveEvent = true;

            IGUIWrapper guiWrapper = new GUIWrapper();

            m_SpriteMeshCache      = ScriptableObject.CreateInstance <SpriteMeshCache>();
            m_Triangulator         = new Triangulator();
            m_WeightGenerator      = new BoundedBiharmonicWeightsGenerator();
            m_OutlineGenerator     = new OutlineGenerator();
            m_UndoObject           = new UndoObject(m_SpriteMeshCache);
            m_SpriteMeshController = new SpriteMeshController();
            m_SpriteMeshView       = new SpriteMeshView(guiWrapper);
            m_BindPoseController   = new BindPoseController();
            m_BindPoseView         = new BindPoseView(guiWrapper);
            m_RectSelectionTool    = new RectSelectionTool(m_SpriteMeshCache);
            m_UnselectTool         = new UnselectTool(m_SpriteMeshCache);
            m_WeightEditor         = new WeightEditor();
            m_BrushWeightTool      = new BrushWeightTool();
            m_SliderWeightTool     = new SliderWeightTool();
            m_WeightInspector      = new WeightInspector(m_SpriteMeshCache);
            m_BoneInspector        = new BoneInspector(m_SpriteMeshCache);
            m_MeshPreview          = new MeshPreview();

            var dataProvider       = spriteEditor.GetDataProvider <ISpriteEditorDataProvider>();
            var boneProvider       = spriteEditor.GetDataProvider <ISpriteBoneDataProvider>();
            var spriteMeshProvider = spriteEditor.GetDataProvider <ISpriteMeshDataProvider>();
            var spriteRects        = dataProvider.GetSpriteRects();
            var textureProvider    = spriteEditor.GetDataProvider <ITextureDataProvider>();

            m_MeshPreview.textureDataProvider = textureProvider;

            for (var i = 0; i < spriteRects.Length; i++)
            {
                var spriteRect     = spriteRects[i];
                var spriteMeshData = new SpriteMeshData();
                spriteMeshData.spriteID = spriteRect.spriteID;
                spriteMeshData.frame    = spriteRect.rect;
                spriteMeshData.pivot    = spriteRect.rect.position + Vector2.Scale(spriteRect.rect.size, spriteRect.pivot);
                spriteMeshData.bones    = MeshModuleUtility.CreateSpriteBoneData(boneProvider.GetBones(spriteRect.spriteID), spriteMeshData.CalculateRootMatrix());

                var metaVertices = spriteMeshProvider.GetVertices(spriteRect.spriteID);
                foreach (var mv in metaVertices)
                {
                    var v = new Vertex2D(mv.position + spriteRect.rect.position, mv.boneWeight);
                    spriteMeshData.vertices.Add(v);
                }

                spriteMeshData.indices = new List <int>(spriteMeshProvider.GetIndices(spriteRect.spriteID));

                Vector2Int[] edges = spriteMeshProvider.GetEdges(spriteRect.spriteID);

                foreach (var e in edges)
                {
                    spriteMeshData.edges.Add(new Edge(e.x, e.y));
                }

                m_SpriteMeshCache.AddSpriteMeshData(spriteMeshData);
            }

            m_WeightEditorWindow = new ModuleWindow(Contents.weightEditor.text, new Rect(0f, 0f, 300f, 195f));
            m_WeightEditorWindow.windowGUICallback = WeightEditorInspector;

            m_InspectorWindow = new ModuleWindow(Contents.inspector.text, new Rect(0f, 0f, 300f, 95f));

            m_GenerateGeometryMenuContents.settings           = m_GenerateGeometrySettings;
            m_GenerateGeometryMenuContents.onGenerateGeometry = OnGenerateGeometry;

            m_BindPoseController.onSkinPreviewChanged += () =>
            {
                m_MeshPreview.SetSkinningDirty();
            };

            m_MeshPreview.SetMeshDirty();

            m_CachedSpriteMeshData = selectedSpriteMeshData;
        }