public override ActionResult DoAction()
        {
            if (MeshSelection.selectedObjectCount < 1)
            {
                return(ActionResult.NoSelection);
            }

            int subdivisions = m_SubdivisionCount;

            UndoUtility.RecordSelection("Subdivide Edges");

            ActionResult result = ActionResult.NoSelection;

            foreach (ProBuilderMesh pb in MeshSelection.topInternal)
            {
                List <Edge> newEdgeSelection = AppendElements.AppendVerticesToEdge(pb, pb.selectedEdges, subdivisions);

                if (newEdgeSelection != null)
                {
                    pb.SetSelectedEdges(newEdgeSelection);
                    pb.ToMesh();
                    pb.Refresh();
                    pb.Optimize();
                    result = new ActionResult(ActionResult.Status.Success, "Subdivide Edge");
                }
                else
                {
                    result = new ActionResult(ActionResult.Status.Failure, "Failed Subdivide Edge");
                }
            }

            ProBuilderEditor.Refresh();

            return(result);
        }
Beispiel #2
0
        /// <summary>
        /// Return a pb_ActionResult indicating the success/failure of action.
        /// </summary>
        /// <returns></returns>
        public override ActionResult DoAction()
        {
            var selection = MeshSelection.top.ToArray();

            Undo.RecordObjects(selection, "Make Double-Sided Faces");

            foreach (var mesh in selection)
            {
                AppendElements.DuplicateAndFlip(mesh, mesh.GetSelectedFaces());

                mesh.ToMesh();
                mesh.Refresh();
                mesh.Optimize();
            }

            // Rebuild the pb_Editor caches
            ProBuilderEditor.Refresh();

            return(new ActionResult(ActionResult.Status.Success, "Make Faces Double-Sided"));
        }
Beispiel #3
0
        public override void FillHoles()
        {
            int filled = 0;

            foreach (ProBuilderMesh mesh in m_edgeSelection.Meshes)
            {
                //MeshSelection selection = new MeshSelection();
                //selection.SelectedEdges.Add(mesh, m_edgeSelection.GetEdges(mesh));
                //selection.EdgesToVertices(false);

                HashSet <int> indexes = new HashSet <int>();
                for (int i = 0; i < mesh.vertexCount; ++i)
                {
                    indexes.Add(i);
                }
                List <List <Edge> > holes = PBElementSelection.FindHoles(mesh, indexes);

                mesh.ToMesh();

                List <WingedEdge> wings         = WingedEdge.GetWingedEdges(mesh);
                HashSet <Face>    appendedFaces = new HashSet <Face>();

                // const bool wholePath = false;

                foreach (List <Edge> hole in holes)
                {
                    List <int> holeIndexes;
                    Face       face;

                    if (!hole.All(e => m_edgeSelection.IsSelected(mesh, e)))
                    {
                        continue;
                    }

                    //if (wholePath)
                    //{
                    //    // if selecting whole path and in edge mode, make sure the path contains
                    //    // at least one complete edge from the selection.
                    //    if (!hole.Any(x => common.Contains(x.edge.common.a) &&
                    //            common.Contains(x.edge.common.b)))
                    //        continue;

                    //    holeIndexes = hole.Select(x => x.edge.local.a).ToList();
                    //    face = AppendElements.CreatePolygon(mesh, holeIndexes, false);
                    //}
                    //else
                    {
                        //IEnumerable<WingedEdge> selected = hole.Where(x => common.Contains(x.edge.common.a));
                        //holeIndexes = selected.Select(x => x.edge.local.a).ToList();

                        //holeIndexes = hole.Select(x => x.edge.local.a).ToList();
                        //face = AppendElements.CreatePolygon(mesh, holeIndexes, true);

                        holeIndexes = hole.Select(x => x.a).ToList();
                        face        = AppendElements.CreatePolygon(mesh, holeIndexes, true);
                    }

                    if (face != null)
                    {
                        filled++;
                        appendedFaces.Add(face);
                    }
                }

                mesh.SetSelectedFaces(appendedFaces);

                wings = WingedEdge.GetWingedEdges(mesh);

                // make sure the appended faces match the first adjacent face found
                // both in winding and face properties
                foreach (var appendedFace in appendedFaces)
                {
                    var wing = wings.FirstOrDefault(x => x.face == appendedFace);

                    if (wing == null)
                    {
                        continue;
                    }

                    using (var it = new WingedEdgeEnumerator(wing))
                    {
                        while (it.MoveNext())
                        {
                            if (it.Current == null)
                            {
                                continue;
                            }

                            var currentWing  = it.Current;
                            var oppositeFace = it.Current.opposite != null ? it.Current.opposite.face : null;

                            if (oppositeFace != null && !appendedFaces.Contains(oppositeFace))
                            {
                                currentWing.face.submeshIndex = oppositeFace.submeshIndex;
                                currentWing.face.uv           = new AutoUnwrapSettings(oppositeFace.uv);
                                PBSurfaceTopology.ConformOppositeNormal(currentWing.opposite);
                                break;
                            }
                        }
                    }
                }

                mesh.ToMesh();
                mesh.Refresh();
                //mesh.Optimize();
            }
        }
        protected override ActionResult PerformActionImplementation()
        {
            if (MeshSelection.selectedObjectCount < 1)
            {
                return(ActionResult.NoSelection);
            }

            UndoUtility.RecordSelection("Fill Hole");

            ActionResult res       = new ActionResult(ActionResult.Status.NoChange, "No Holes Found");
            int          filled    = 0;
            bool         wholePath = m_SelectEntirePath;

            foreach (ProBuilderMesh mesh in MeshSelection.topInternal)
            {
                bool selectAll            = mesh.selectedIndexesInternal == null || mesh.selectedIndexesInternal.Length < 1;
                IEnumerable <int> indexes = selectAll ? mesh.facesInternal.SelectMany(x => x.indexes) : mesh.selectedIndexesInternal;

                mesh.ToMesh();

                List <WingedEdge>         wings  = WingedEdge.GetWingedEdges(mesh);
                HashSet <int>             common = mesh.GetSharedVertexHandles(indexes);
                List <List <WingedEdge> > holes  = ElementSelection.FindHoles(wings, common);

                HashSet <Face> appendedFaces = new HashSet <Face>();

                foreach (List <WingedEdge> hole in holes)
                {
                    List <int> holeIndexes;
                    Face       face;

                    if (wholePath)
                    {
                        // if selecting whole path and in edge mode, make sure the path contains
                        // at least one complete edge from the selection.
                        if (ProBuilderEditor.selectMode == SelectMode.Edge &&
                            !hole.Any(x => common.Contains(x.edge.common.a) &&
                                      common.Contains(x.edge.common.b)))
                        {
                            continue;
                        }

                        holeIndexes = hole.Select(x => x.edge.local.a).ToList();
                        face        = AppendElements.CreatePolygon(mesh, holeIndexes, false);
                    }
                    else
                    {
                        IEnumerable <WingedEdge> selected = hole.Where(x => common.Contains(x.edge.common.a));
                        holeIndexes = selected.Select(x => x.edge.local.a).ToList();
                        face        = AppendElements.CreatePolygon(mesh, holeIndexes, true);
                    }

                    if (face != null)
                    {
                        filled++;
                        appendedFaces.Add(face);
                    }
                }

                mesh.SetSelectedFaces(appendedFaces);

                wings = WingedEdge.GetWingedEdges(mesh);

                // make sure the appended faces match the first adjacent face found
                // both in winding and face properties
                foreach (var appendedFace in appendedFaces)
                {
                    var wing = wings.FirstOrDefault(x => x.face == appendedFace);

                    if (wing == null)
                    {
                        continue;
                    }

                    using (var it = new WingedEdgeEnumerator(wing))
                    {
                        while (it.MoveNext())
                        {
                            if (it.Current == null)
                            {
                                continue;
                            }

                            var currentWing  = it.Current;
                            var oppositeFace = it.Current.opposite != null ? it.Current.opposite.face : null;

                            if (oppositeFace != null && !appendedFaces.Contains(oppositeFace))
                            {
                                currentWing.face.submeshIndex = oppositeFace.submeshIndex;
                                currentWing.face.uv           = new AutoUnwrapSettings(oppositeFace.uv);
                                SurfaceTopology.ConformOppositeNormal(currentWing.opposite);
                                break;
                            }
                        }
                    }
                }

                mesh.ToMesh();
                mesh.Refresh();
                mesh.Optimize();
            }

            ProBuilderEditor.Refresh();

            if (filled > 0)
            {
                res = new ActionResult(ActionResult.Status.Success, filled > 1 ? string.Format("Filled {0} Holes", filled) : "Fill Hole");
            }
            return(res);
        }
Beispiel #5
0
    public void Generate()
    {
        switch (ShapeType)
        {
        case ShapeTypes.Wythoff:
            var wythoff = new WythoffPoly(PolyType, PrismP, PrismQ);
            wythoff.BuildFaces();
            poly = new ConwayPoly(wythoff);
            break;

        case ShapeTypes.Johnson:
            poly = JohnsonPoly.Build(JohnsonPolyType, PrismP);
            break;

        case ShapeTypes.Grid:
            poly = Grids.Grids.MakeGrid(GridType, GridShape, PrismP, PrismQ);
            break;
        }

        if (ApplyOp)
        {
            var o1 = new OpParams {
                valueA = op1Amount1, valueB = op1Amount2, facesel = op1Facesel
            };
            poly = poly.ApplyOp(op1, o1);
        }

        if (PreCanonicalize)
        {
            poly = poly.Canonicalize(0.01, 0.01);
        }

        if (Canonicalize)
        {
            poly = poly.Canonicalize(0.01, 0.01);
        }

        if (ApplyOp)
        {
            var o2 = new OpParams {
                valueA = op2Amount1, valueB = op2Amount2, facesel = op2Facesel
            };
            poly = poly.ApplyOp(op2, o2);
            var o3 = new OpParams {
                valueA = op3Amount1, valueB = op3Amount2, facesel = op3Facesel
            };
            poly = poly.ApplyOp(op3, o3);
        }

        var points = poly.ListVerticesByPoints().ToList();

        if (JitterAmount > 0)
        {
            for (int i = 0; i < points.Count(); i++)
            {
                var point = points[i];
                points[i] = new Vector3(
                    point.x + Random.value * JitterAmount,
                    point.y + Random.value * JitterAmount,
                    point.z + Random.value * JitterAmount
                    );
            }
        }
        var faceIndices = poly.ListFacesByVertexIndices();

        // This whole mess is because I can't find a way to regenerate
        // a probuilder mesh and therefore have to continually create/destroy gameobjects
        // (which is a mess in edit mode)
        // If anyone can explain how to simply take an existing probuilder object clear it
        // and pass in a list of Vector3's and lists of ordered indexes for faces
        // then please do.

        if (pbmesh != null && pbmesh.gameObject != null)
        {
            if (Application.isPlaying)
            {
                Destroy(pbmesh.gameObject);
            }
            else
            {
                var go = pbmesh.gameObject;
                UnityEditor.EditorApplication.delayCall += () =>
                {
                    DestroyImmediate(go);
                };
            }
        }
        var colors = Enumerable.Range(0, 8).Select(x => Colors.Evaluate(((x / 8f) * ColorRange + ColorOffset) % 1)).ToArray();

        pbmesh = ProBuilderMesh.Create(points, new List <Face>());
        var faces = new List <PBFace>();

        for (var i = 0; i < faceIndices.Length; i++)
        {
            var face   = faceIndices[i];
            var result = AppendElements.CreatePolygon(pbmesh, face, false);
            if (result != null)
            {
                pbmesh.SetFaceColor(result, colors[(int)poly.FaceRoles[i]]);
                faces.Add(result);
            }
        }

        if (faces.Count < 1 || pbmesh == null)
        {
            return;
        }

        pbmesh.SetMaterial(faces, material);
        pbmesh.ToMesh();
        pbmesh.Refresh();
    }