Наследование: MonoBehaviour, ISliceable
Пример #1
0
    private void CreateTravelerClone(PortalTraveler portalTraveler, bool enteredFromBack)
    {
        lstPortalTravelers.Add(portalTraveler);
        TransformToTarget(portalTraveler.transform, out Vector3 newPos, out Quaternion newRot);
        PortalTraveler travelerCopy = Instantiate(portalTraveler, newPos, newRot);

        travelerCopy.enabled = false;

        SimpleMove simpleMoveComponent = travelerCopy.GetComponent <SimpleMove>();

        if (simpleMoveComponent)
        {
            simpleMoveComponent.enabled = false;
        }

        Sliceable sliceable = portalTraveler.GetComponent <Sliceable>();

        sliceable.SlicePosition = transform.position;
        sliceable.SliceNormal   = transform.forward;
        sliceable.IsSliceable   = true;
        sliceable.Flip          = !enteredFromBack;
        sliceable.UpdateMaterialSlice();

        if (target)
        {
            sliceable = travelerCopy.GetComponent <Sliceable>();
            sliceable.SlicePosition = target.transform.position;
            sliceable.SliceNormal   = target.transform.forward;
            sliceable.IsSliceable   = true;
            sliceable.Flip          = enteredFromBack;
            sliceable.UpdateMaterialSlice();
        }

        travelerCopies.Add(portalTraveler, travelerCopy.gameObject);
    }
Пример #2
0
    public void OnTriggerExit(Collider other)
    {
        PortalTraveler portalTraveler = other.GetComponent <PortalTraveler>();

        if (portalTraveler != null)
        {
            if (other.CompareTag("Player"))
            {
                playerTraveler = null;
                var originalPosition = new Vector3(0, portalDisplay.transform.localPosition.y, 0);

                PortalAdjustment(originalPosition, originalPortalScale);
                target.PortalAdjustment(originalPosition, originalPortalScale);
            }
            else
            {
                Sliceable sliceable = portalTraveler.GetComponent <Sliceable>();
                sliceable.IsSliceable = false;
                sliceable.UpdateMaterialSlice();
                TransformToTarget(portalTraveler.transform);
                lstPortalTravelers.Remove(portalTraveler);
                DestroyTravelerCopy(portalTraveler);
                travelerCopies.Remove(portalTraveler);
            }
        }
    }
    //Add different components to the game objects depending on if they're staying or not
    void AddComponent(GameObject obj, bool stay)
    {
        obj.gameObject.layer = 8;
        obj.AddComponent <BoxCollider>();
        obj.GetComponent <BoxCollider>().size   = new Vector3(obj.GetComponent <BoxCollider>().size.x, 0, obj.GetComponent <BoxCollider>().size.z);
        obj.GetComponent <BoxCollider>().center = new Vector3(obj.GetComponent <BoxCollider>().center.x, 0, obj.GetComponent <BoxCollider>().center.z);
        BoxCollider bcol = obj.AddComponent <BoxCollider>();

        bcol.isTrigger = true;

        if (!stay)
        {
            obj.AddComponent <Rigidbody>();
            obj.GetComponent <Rigidbody>().interpolation = RigidbodyInterpolation.Interpolate;
            obj.GetComponent <Rigidbody>().AddExplosionForce(100, obj.transform.position, 20);
            Destroy(obj, 3f);
        }
        else
        {
            obj.AddComponent <Sliceable>();
            Sliceable temp = obj.GetComponent <Sliceable>();
            temp.SetMaster(this);
            temp.SetGameStarted(true);
            _gm.SetSliceable(temp);
        }
    }
Пример #4
0
    // Use this for initialization
    void Start()
    {
        if (_instance != null)
        {
            Debug.LogWarning("There may be multiple TurboSlice components in scene " + Application.loadedLevelName + ". Please review this!");
        }

        _instance = this;

        if (meshCaching)
        {
            meshCaches = new Dictionary <Mesh, MeshCache>();

            foreach (GameObject go in preload)
            {
                Sliceable s = ensureSliceable(go);

                MeshCache c = cacheFromGameObject(s, false);
                c.wasPreloaded = true;

                MeshFilter filter = getMeshFilter(s);

                if (filter == null)
                {
                    Mesh m = filter.sharedMesh;

                    meshCaches[m] = c;
                }
                else
                {
                    Debug.LogWarning("Turbo Slicer cannot preload object '" + go.name + "'; cannot find mesh filter.");
                }
            }
        }
    }
Пример #5
0
        /// <summary>
        /// Slice the object by the plane
        /// </summary>
        /// <param name="plane"></param>
        /// <param name="objectToCut"></param>
        /// <returns></returns>
        public static GameObject[] Slice(Plane plane, GameObject objectToCut)
        {
            //Get the current mesh and its verts and tris
            Mesh      mesh      = objectToCut.GetComponent <MeshFilter>().mesh;
            var       a         = mesh.GetSubMesh(0);
            Sliceable sliceable = objectToCut.GetComponent <Sliceable>();

            if (sliceable == null)
            {
                throw new NotSupportedException("Cannot slice non sliceable object, add the sliceable script to the object or inherit from sliceable to support slicing");
            }

            //Create left and right slice of hollow object
            SlicesMetadata slicesMeta = new SlicesMetadata(plane, mesh, sliceable.IsSolid, sliceable.ReverseWireTriangles, sliceable.ShareVertices, sliceable.SmoothVertices);

            GameObject positiveObject = CreateMeshGameObject(objectToCut);

            positiveObject.name = string.Format("{0}_positive", objectToCut.name);

            GameObject negativeObject = CreateMeshGameObject(objectToCut);

            negativeObject.name = string.Format("{0}_negative", objectToCut.name);

            var positiveSideMeshData = slicesMeta.PositiveSideMesh;
            var negativeSideMeshData = slicesMeta.NegativeSideMesh;

            positiveObject.GetComponent <MeshFilter>().mesh = positiveSideMeshData;
            negativeObject.GetComponent <MeshFilter>().mesh = negativeSideMeshData;

            SetupCollidersAndRigidBodys(ref positiveObject, positiveSideMeshData, sliceable.UseGravity);
            SetupCollidersAndRigidBodys(ref negativeObject, negativeSideMeshData, sliceable.UseGravity);

            return(new GameObject[] { positiveObject, negativeObject });
        }
Пример #6
0
 private void SliceThis(Sliceable otherSliceable)
 {
     if (otherSliceable != null && !justSliced.Contains(otherSliceable) && !pendingSlices.Contains(otherSliceable))
     {
         pendingSlices.Add(otherSliceable);
     }
 }
    public GameObject[] shatter(GameObject go, int steps)
    {
        Sliceable priorSliceable = go.GetComponent <Sliceable>();

        List <GameObject> l = new List <GameObject>();

        l.Add(go);

        List <GameObject> l2 = l;

        for (int i = 0; i < steps; i++)
        {
            l2 = new List <GameObject>(l.Count * 2);

            Vector4 shatterPlane = (Vector4)Random.insideUnitSphere;

            foreach (GameObject go2 in l)
            {
                l2.AddRange(_splitByPlane(go2, shatterPlane, true, false));
            }

            l = l2;
        }

        GameObject[] results = l2.ToArray();

        if (priorSliceable != null)
        {
            priorSliceable.handleSlice(results);
        }

        return(results);
    }
Пример #8
0
        /// <summary>
        /// Creates the default mesh game object.
        /// </summary>
        /// <param name="originalObject">The original object.</param>
        /// <returns></returns>
        private static GameObject CreateMeshGameObject(GameObject originalObject)
        {
            var originalMaterial = originalObject.GetComponent <MeshRenderer>().materials;

            GameObject meshGameObject    = new GameObject();
            Sliceable  originalSliceable = originalObject.GetComponent <Sliceable>();

            meshGameObject.AddComponent <MeshFilter>();
            meshGameObject.AddComponent <MeshRenderer>();
            Sliceable sliceable = meshGameObject.AddComponent <Sliceable>();

            sliceable.IsSolid = originalSliceable.IsSolid;
            sliceable.ReverseWireTriangles = originalSliceable.ReverseWireTriangles;
            sliceable.UseGravity           = originalSliceable.UseGravity;

            meshGameObject.GetComponent <MeshRenderer>().materials = originalMaterial;

            meshGameObject.transform.localScale = originalObject.transform.localScale;
            meshGameObject.transform.rotation   = originalObject.transform.rotation;
            meshGameObject.transform.position   = originalObject.transform.position;

            meshGameObject.tag = originalObject.tag;

            return(meshGameObject);
        }
Пример #9
0
    private MeshCache cacheFromGameObject(Sliceable sliceable, bool includeRoomForGrowth)
    {
        Renderer renderer = getMeshRenderer(sliceable);

        Mesh m = getMesh(sliceable);

        int initialCapacity = includeRoomForGrowth ? Mathf.RoundToInt((float)m.vertexCount * factorOfSafetyGeometry) : m.vertexCount;

        MeshCache c = new MeshCache();

        c.vertices = new TurboList <Vector3>(initialCapacity);
        if (sliceable.channelNormals)
        {
            c.normals = new TurboList <Vector3>(initialCapacity);
        }
        c.coords = new TurboList <Vector2>(initialCapacity);
        if (sliceable.channelUV2)
        {
            c.coords2 = new TurboList <Vector2>(initialCapacity);
        }

        c.indices = new int[m.subMeshCount][];

        for (int i = 0; i < m.subMeshCount; i++)
        {
            c.indices[i] = m.GetTriangles(i);
        }

        c.vertices.AddArray(m.vertices);
        if (sliceable.channelNormals)
        {
            c.normals.AddArray(m.normals);
        }
        c.coords.AddArray(m.uv);
        if (sliceable.channelUV2)
        {
            c.coords2.AddArray(m.uv2);
        }

        if (renderer != null)
        {
            if (renderer.sharedMaterials == null)
            {
                c.mats    = new Material[1];
                c.mats[0] = renderer.sharedMaterial;
            }
            else
            {
                c.mats = renderer.sharedMaterials;
            }
        }
        else
        {
            Debug.LogError("Object '" + sliceable.name + "' has no renderer");
        }

        return(c);
    }
Пример #10
0
    private void createResultObjects(GameObject go, Sliceable sliceable, bool forceCloning, Vector4 plane, out GameObject frontObject, out GameObject backObject)
    {
        Transform goTransform = go.transform;

        Dictionary <string, Transform> transformByName;
        Dictionary <string, bool>      frontPresence, backPresence;

        determinePresence(goTransform, plane, out transformByName, out frontPresence, out backPresence);

        bool useAlternateForFront, useAlternateForBack;

        if (sliceable.alternatePrefab == null)
        {
            useAlternateForFront = false;
            useAlternateForBack  = false;
        }
        else if (sliceable.alwaysCloneFromAlternate)
        {
            useAlternateForFront = true;
            useAlternateForBack  = true;
        }
        else
        {
            useAlternateForFront = sliceable.cloneAlternate(frontPresence);
            useAlternateForBack  = sliceable.cloneAlternate(backPresence);
        }

        Object frontSource = useAlternateForFront ? sliceable.alternatePrefab : go;
        Object backSource  = useAlternateForBack ? sliceable.alternatePrefab : go;

        frontObject = (GameObject)GameObject.Instantiate(frontSource);
        backObject  = (GameObject)GameObject.Instantiate(backSource);

        handleHierarchy(frontObject.transform, frontPresence, transformByName);
        handleHierarchy(backObject.transform, backPresence, transformByName);

        Transform parent = goTransform.parent;

        Vector3 position = goTransform.localPosition;
        Vector3 scale    = goTransform.localScale;

        Quaternion rotation = goTransform.localRotation;

        frontObject.transform.parent        = parent;
        frontObject.transform.localPosition = position;
        frontObject.transform.localScale    = scale;

        backObject.transform.parent        = parent;
        backObject.transform.localPosition = position;
        backObject.transform.localScale    = scale;

        frontObject.transform.localRotation = rotation;
        backObject.transform.localRotation  = rotation;

        frontObject.layer = go.layer;
        backObject.layer  = go.layer;
    }
Пример #11
0
    private void createResultObjects(GameObject go, Sliceable sliceable, bool forceCloning, Vector4 plane, out GameObject frontObject, out GameObject backObject)
    {
        Transform goTransform = go.transform;

        Dictionary<string,Transform> transformByName;
        Dictionary<string,bool> frontPresence, backPresence;

        determinePresence(goTransform, plane, out transformByName, out frontPresence, out backPresence);

        bool useAlternateForFront, useAlternateForBack;

        if(sliceable.alternatePrefab == null)
        {
            useAlternateForFront = false;
            useAlternateForBack = false;
        }
        else if(sliceable.alwaysCloneFromAlternate)
        {
            useAlternateForFront = true;
            useAlternateForBack = true;
        }
        else
        {
            useAlternateForFront = sliceable.cloneAlternate(frontPresence);
            useAlternateForBack = sliceable.cloneAlternate(backPresence);
        }

        Object frontSource = useAlternateForFront ? sliceable.alternatePrefab : go;
        Object backSource = useAlternateForBack ? sliceable.alternatePrefab : go;

        frontObject = (GameObject) GameObject.Instantiate(frontSource);
        backObject = (GameObject) GameObject.Instantiate(backSource);

        handleHierarchy(frontObject.transform, frontPresence, transformByName);
        handleHierarchy(backObject.transform, backPresence, transformByName);

        Transform parent = goTransform.parent;

        Vector3 position = goTransform.localPosition;
        Vector3 scale = goTransform.localScale;

        Quaternion rotation = goTransform.localRotation;

        frontObject.transform.parent = parent;
        frontObject.transform.localPosition = position;
        frontObject.transform.localScale = scale;

        backObject.transform.parent = parent;
        backObject.transform.localPosition = position;
        backObject.transform.localScale = scale;

        frontObject.transform.localRotation = rotation;
        backObject.transform.localRotation = rotation;

        frontObject.layer = go.layer;
        backObject.layer = go.layer;
    }
Пример #12
0
    private static Renderer getMeshRenderer(Sliceable s)
    {
        GameObject holder = getMeshHolder(s);

        if(holder != null)
        {
            return holder.GetComponent(typeof(Renderer)) as Renderer;
        }
        else
        {
            return null;
        }
    }
Пример #13
0
    private static Renderer getMeshRenderer(Sliceable s)
    {
        GameObject holder = getMeshHolder(s);

        if (holder != null)
        {
            return(holder.GetComponent(typeof(Renderer)) as Renderer);
        }
        else
        {
            return(null);
        }
    }
Пример #14
0
    private MeshFilter getMeshFilter(Sliceable s)
    {
        GameObject holder = getMeshHolder(s);

        if (holder != null)
        {
            return(holder.GetComponent <MeshFilter>());
        }
        else
        {
            return(null);
        }
    }
Пример #15
0
    private static Sliceable ensureSliceable(GameObject go)
    {
        Sliceable sliceable = go.GetComponent <Sliceable>();

        if (sliceable == null)
        {
            Debug.LogWarning("Turbo Slicer was given an object (" + go.name + ") with no Sliceable; improvising.");

            sliceable = go.AddComponent <Sliceable>();
            sliceable.currentlySliceable = true;
            sliceable.refreshColliders   = true;
        }

        return(sliceable);
    }
Пример #16
0
    private void FixChunk(GameObject chunk, Sliceable victim, Vector3 offsetDirection)
    {
        // Resets collider to adjust for current mesh
        Destroy(chunk.GetComponent <Collider>());
        var collider = chunk.AddComponent <MeshCollider>();

        collider.convex = true;

        var sliceable  = chunk.GetOrAddComponent <Sliceable>();
        var rigidbody  = chunk.GetOrAddComponent <Rigidbody>();
        var meshFilter = chunk.GetOrAddComponent <MeshFilter>();

        sliceable.CutMaterial     = victim.CutMaterial;
        sliceable.MaterialDensity = victim.MaterialDensity;
        rigidbody.mass            = meshFilter.mesh.Volume() * sliceable.MaterialDensity;
        rigidbody.MovePosition(chunk.transform.position + offsetDirection * .01f);
    }
Пример #17
0
    public void Cut(Vector3 contact, Sliceable victim, float velocity)
    {
        if (velocity > cutVelocityThreshold && previousCuts.Contains(victim))
        {
            previousCuts.Remove(victim);

            var cutNormal = transform.right;

            var cuts = MeshCut
                       .Cut(victim.gameObject, contact, cutNormal, victim.CutMaterial)
                       .OrderByDescending(c => c.GetComponent <MeshFilter>().mesh.Volume())
                       .ToList();

            FixChunk(cuts[0], victim, cutNormal);
            FixChunk(cuts[1], victim, -cutNormal);
        }
    }
Пример #18
0
    // Update is called once per frame
    void LateUpdate()
    {
        justSliced.Clear();

        if (pendingSlices.Count > 0)
        {
            slicePlane[0] = planeDefiner1.position;
            slicePlane[1] = planeDefiner2.position;
            slicePlane[2] = planeDefiner3.position;
        }

        while (pendingSlices.Count > 0)
        {
            Sliceable other = pendingSlices[0];
            pendingSlices.RemoveAt(0);

            if (other != null && other.gameObject != null && other.currentlySliceable)
            {
                bool stillSlice = false;

                if (onlySlicesCategories.Length > 0 && other.category.Length > 0)
                {
                    foreach (string s in onlySlicesCategories)
                    {
                        stillSlice |= s == other.category;
                    }
                }
                else
                {
                    stillSlice = true;
                }

                if (stillSlice)
                {
                    GameObject[] results = turboSlice.splitByTriangle(other.gameObject, slicePlane, false);

                    if (results[0] != other.gameObject)
                    {
                        GameObject.Destroy(other.gameObject);
                    }

                    justSliced.Add(other);
                }
            }
        }
    }
Пример #19
0
    private Mesh getMesh(Sliceable s)
    {
        GameObject holder   = getMeshHolder(s);
        Renderer   renderer = holder.GetComponent <Renderer>();
        Mesh       mesh     = null;

        if (renderer is MeshRenderer)
        {
            mesh = holder.GetComponent <MeshFilter>().mesh;
        }
        else if (renderer is SkinnedMeshRenderer)
        {
            SkinnedMeshRenderer smr = renderer as SkinnedMeshRenderer;
            mesh = new Mesh();
            smr.BakeMesh(mesh);
            meshDeletionQueue.Enqueue(mesh);
        }
        return(mesh);
    }
Пример #20
0
    private static GameObject getMeshHolder(Sliceable s)
    {
        if (s.explicitlySelectedMeshHolder != null)
        {
            return(s.explicitlySelectedMeshHolder);
        }
        else
        {
            MeshFilter[] allFilters = s.GetComponentsInChildren <MeshFilter>(true);

            if (allFilters.Length > 0)
            {
                return(allFilters[0].gameObject);
            }
            else
            {
                return(null);
            }
        }
    }
Пример #21
0
 private static void setMesh(Sliceable s, Mesh mesh)
 {
     GameObject holder = getMeshHolder(s);
     Renderer renderer = holder.GetComponent<Renderer>();
     MeshFilter filter = null;
     if(renderer is MeshRenderer)
     {
         filter = holder.GetComponent<MeshFilter>();
     }
     else if(renderer is SkinnedMeshRenderer)
     {
         holder = s.explicitlySelectedMeshHolder = s.gameObject;
         Material[] allMats = renderer.sharedMaterials;
         GameObject.DestroyImmediate(renderer);
         renderer = holder.AddComponent<MeshRenderer>();
         renderer.sharedMaterials = allMats;
         filter = holder.AddComponent<MeshFilter>();
     }
     if(filter != null) filter.mesh = mesh;
 }
Пример #22
0
    private static GameObject getMeshHolder(Sliceable s)
    {
        if(s.explicitlySelectedMeshHolder != null)
        {
            return s.explicitlySelectedMeshHolder;
        }
        else
        {
            MeshFilter[] allFilters = s.GetComponentsInChildren<MeshFilter>(true);

            if(allFilters.Length > 0)
            {
                return allFilters[0].gameObject;
            }
            else
            {
                return null;
            }
        }
    }
Пример #23
0
    private static void setMesh(Sliceable s, Mesh mesh)
    {
        GameObject holder   = getMeshHolder(s);
        Renderer   renderer = holder.GetComponent <Renderer>();
        MeshFilter filter   = null;

        if (renderer is MeshRenderer)
        {
            filter = holder.GetComponent <MeshFilter>();
        }
        else if (renderer is SkinnedMeshRenderer)
        {
            holder = s.explicitlySelectedMeshHolder = s.gameObject;
            Material[] allMats = renderer.sharedMaterials;
            GameObject.DestroyImmediate(renderer);
            renderer = holder.AddComponent <MeshRenderer>();
            renderer.sharedMaterials = allMats;
            filter = holder.AddComponent <MeshFilter>();
        }
        if (filter != null)
        {
            filter.mesh = mesh;
        }
    }
Пример #24
0
    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButton(0))
        {
            Ray cuttingRay = mainCamera.ScreenPointToRay(Input.mousePosition);

            Vector3 point = cuttingRay.GetPoint(3f);

            if (!cutting)
            {
                cutting = true;

                startPoint = point;
                endPoint   = point;

                cameraStartPoint = Input.mousePosition;
                cameraEndPoint   = Input.mousePosition;
            }
            else
            {
                if (point != startPoint)
                {
                    foundCut = true;

                    endPoint       = point;
                    cameraEndPoint = Input.mousePosition;

                    positions[0] = startPoint;
                    positions[1] = point;

                    lineRenderer.gameObject.SetActive(true);
                    lineRenderer.SetPositions(positions);
                }
                else
                {
                    lineRenderer.gameObject.SetActive(false);
                    foundCut = false;
                }
            }
        }
        else
        {
            if (cutting)
            {
                lineRenderer.gameObject.SetActive(false);
                cutting = false;

                if (foundCut)
                {
                    //Vector3 worldNormal = Vector3.Cross(endPoint - startPoint, startPoint - mainCamera.transform.position);
                    foreach (GameObject cutObject in objectsToCut)
                    {
                        // cut the mesh
                        Sliceable sliceable = cutObject.GetComponent <Sliceable>();

                        if (sliceable)
                        {
                            //sliceable.Slice(startPoint, worldNormal);
                            sliceable.SliceByLine(mainCamera, cameraStartPoint, cameraEndPoint);
                        }
                    }
                }

                foundCut = false;
            }
        }

        if (Input.GetMouseButton(1) && !cutting)
        {
            Vector3 targetPos = mainCamera.ScreenPointToRay(Input.mousePosition).GetPoint(5f);

            foreach (GameObject cutObject in objectsToCut)
            {
                Rigidbody rb = cutObject.GetComponent <Rigidbody>();

                rb.AddForce((targetPos - cutObject.transform.position) * 3f);
            }
        }
    }
Пример #25
0
    private MeshCache cacheFromGameObject(Sliceable sliceable, bool includeRoomForGrowth)
    {
        Renderer renderer = getMeshRenderer(sliceable);

        Mesh m = getMesh(sliceable);

        int initialCapacity = includeRoomForGrowth ? Mathf.RoundToInt((float) m.vertexCount * factorOfSafetyGeometry) : m.vertexCount;

        MeshCache c = new MeshCache();

        c.vertices = new TurboList<Vector3>(initialCapacity);
        if(sliceable.channelNormals) c.normals = new TurboList<Vector3>(initialCapacity);
        c.coords = new TurboList<Vector2>(initialCapacity);
        if(sliceable.channelUV2) c.coords2 = new TurboList<Vector2>(initialCapacity);

        c.indices = new int[m.subMeshCount][];

        for(int i = 0; i < m.subMeshCount; i++)
        {
            c.indices[i] = m.GetTriangles(i);
        }

        c.vertices.AddArray(m.vertices);
        if(sliceable.channelNormals) c.normals.AddArray(m.normals);
        c.coords.AddArray(m.uv);
        if(sliceable.channelUV2) c.coords2.AddArray(m.uv2);

        if(renderer != null)
        {
            if(renderer.sharedMaterials == null)
            {
                c.mats = new Material[1];
                c.mats[0] = renderer.sharedMaterial;
            }
            else
            {
                c.mats = renderer.sharedMaterials;
            }
        }
        else
        {
            Debug.LogError("Object '" + sliceable.name + "' has no renderer");
        }

        return c;
    }
Пример #26
0
    void OnTriggerEnter(Collider other)
    {
        Sliceable otherSliceable = other.GetComponent <Sliceable>();

        SliceThis(otherSliceable);
    }
Пример #27
0
    private MeshRenderer getMeshRenderer(Sliceable s)
    {
        GameObject holder = getMeshHolder(s);

        if(holder != null)
        {
            return holder.GetComponent<MeshRenderer>();
        }
        else
        {
            return null;
        }
    }
Пример #28
0
    void OnCollisionEnter(Collision other)
    {
        Sliceable otherSliceable = other.collider.GetComponent <Sliceable>();

        SliceThis(otherSliceable);
    }
Пример #29
0
 private Mesh getMesh(Sliceable s)
 {
     GameObject holder = getMeshHolder(s);
     Renderer renderer = holder.GetComponent<Renderer>();
     Mesh mesh = null;
     if(renderer is MeshRenderer)
     {
         mesh = holder.GetComponent<MeshFilter>().mesh;
     }
     else if(renderer is SkinnedMeshRenderer)
     {
         SkinnedMeshRenderer smr = renderer as SkinnedMeshRenderer;
         mesh = new Mesh();
         smr.BakeMesh(mesh);
         meshDeletionQueue.Enqueue(mesh);
     }
     return mesh;
 }
Пример #30
0
    public GameObject[] splitByPlane(GameObject go, Vector4 plane, bool destroyOriginal)
    {
        if (go.GetComponentInChildren <SkinnedMeshRenderer>() != null)
        {
            return(splitByPlaneRD(go, plane, destroyOriginal));
        }

        Sliceable sliceable = ensureSliceable(go);

        if (!sliceable.currentlySliceable)
        {
            GameObject[] result = { go };

            return(result);
        }

        InfillConfiguration[] ourInfills = sliceable.infillers.Length > 0 ? sliceable.infillers : infills;

        MeshCache c = null;

        do
        {
            MeshFilter filter = getMeshFilter(sliceable);

            Mesh m = filter.sharedMesh;

            if (m == null)
            {
                break;
            }

            if (meshCaches != null && meshCaches.ContainsKey(m))
            {
                c = meshCaches[m];

                //The mesh cache will be directly modified under the assumption that this will be discarded shortly
                //and thus picked up by the GC. It will grow in size; it will not shrink. Thus we do not want to
                //operate on the original, semi-persistent mesh caches that were preloaded on boot. Instead, we want
                //to make a clone.

                if (c.wasPreloaded)
                {
                    c = c.clone();
                }
            }
            else
            {
                c = cacheFromGameObject(sliceable, true);
            }
        }while(false);
        if (c == null)
        {
            Debug.LogWarning("Turbo Slicer cannot find mesh filter in object '" + go.name + "' in scene '" + Application.loadedLevelName + "'! Only objects featuring a mesh filter can be sliced.");

            GameObject[] result = { go };

            return(result);
        }

        int submeshCount = c.indices.Length;

        //We're going to create two new tentative meshes which contain ALL original vertices in order,
        //plus room for new vertices. Not all of these copied vertices will be addressed, but copying them
        //over eliminates the need to remove doubles and do an On^2 search.

        TurboList <int>[] _frontIndices = new TurboList <int> [submeshCount];
        TurboList <int>[] _backIndices  = new TurboList <int> [submeshCount];

        PlaneTriResult[] sidePlanes = new PlaneTriResult[c.vertices.Count];
        {
            Vector3[] vertices = c.vertices.array;

            for (int i = 0; i < sidePlanes.Length; i++)
            {
                sidePlanes[i] = getSidePlane(ref vertices[i], ref plane);
            }
        }

        for (int j = 0; j < submeshCount; j++)
        {
            int initialCapacityIndices = Mathf.RoundToInt((float)c.indices[j].Length * factorOfSafetyIndices);

            _frontIndices[j] = new TurboList <int>(initialCapacityIndices);
            _backIndices[j]  = new TurboList <int>(initialCapacityIndices);

            int[] _indices = c.indices[j];

            TurboList <int> frontIndices = _frontIndices[j];
            TurboList <int> backIndices  = _backIndices[j];
            TurboList <int> splitPending = new TurboList <int>(initialCapacityIndices);

            int[] indices = new int[3];

            for (int i = 0; i < _indices.Length;)
            {
                indices[0] = _indices[i++];
                indices[1] = _indices[i++];
                indices[2] = _indices[i++];

                // compute the side of the plane each vertex is on
                PlaneTriResult r1 = sidePlanes[indices[0]];
                PlaneTriResult r2 = sidePlanes[indices[1]];
                PlaneTriResult r3 = sidePlanes[indices[2]];

                if (r1 == r2 && r1 == r3)                   // if all three vertices are on the same side of the plane.
                {
                    if (r1 == PlaneTriResult.PTR_FRONT)     // if all three are in front of the plane, then copy to the 'front' output triangle.
                    {
                        frontIndices.AddArray(indices);
                    }
                    else
                    {
                        backIndices.AddArray(indices);
                    }
                }
                else
                {
                    splitPending.AddArray(indices);
                }
            }

            InfillConfiguration ifc = null;

            if (j < c.mats.Length)
            {
                Material mat = c.mats[j];

                foreach (InfillConfiguration _ifc in ourInfills)
                {
                    if (_ifc.material == mat)
                    {
                        ifc = _ifc;
                    }
                }
            }

            splitTriangles(plane, splitPending.ToArray(), c, ifc, frontIndices, backIndices);
        }

        GameObject[] results;

        bool onlyHaveOne = true;

        for (int i = 0; i < c.indices.Length; i++)
        {
            onlyHaveOne &= _frontIndices[i].Count == 0 || _backIndices[i].Count == 0;
        }

        if (onlyHaveOne)
        {
            //Do nothing
            results    = new GameObject[1];
            results[0] = go;
        }
        else
        {
            MeshCache frontCache = new MeshCache();
            frontCache.vertices = c.vertices;
            if (sliceable.channelNormals)
            {
                frontCache.normals = c.normals;
            }
            frontCache.UVs  = c.UVs;
            frontCache.mats = c.mats;

            MeshCache backCache = new MeshCache();
            backCache.vertices = c.vertices;
            if (sliceable.channelNormals)
            {
                backCache.normals = c.normals;
            }
            backCache.UVs  = c.UVs;
            backCache.mats = c.mats;

            frontCache.indices = new int[submeshCount][];
            backCache.indices  = new int[submeshCount][];
            for (int i = 0; i < submeshCount; i++)
            {
                frontCache.indices[i] = _frontIndices[i].ToArray();
                backCache.indices[i]  = _backIndices[i].ToArray();
            }

            Vector3[] geoSubsetOne, geoSubsetTwo;
            Vector3[] normalsSubsetOne = null, normalsSubsetTwo = null;
            Vector2[] uvSubsetOne, uvSubsetTwo;
            int[][]   indexSubsetOne, indexSubsetTwo;

            indexSubsetOne = new int[submeshCount][];
            indexSubsetTwo = new int[submeshCount][];

            //Perfect subset will inflate the array list size if needed to the exact figure. So if we estimate 0,
            //and there is 1 submesh, than we will have 1 allocation, and this is optimal. Estimation can only help
            //if we have THREE or more submeshes, which is a silly scenario for anyone concerned about performance.
            int estimateOne = 0, estimateTwo = 0;

            TurboList <Vector3>
            _geoSubsetOne = null, _geoSubsetTwo = null,
                _normalSubsetOne = null, _normalSubsetTwo = null;

            TurboList <Vector2>
            _uvSubsetOne = null, _uvSubsetTwo = null;

            _geoSubsetOne = new TurboList <Vector3>(estimateOne);
            _geoSubsetTwo = new TurboList <Vector3>(estimateTwo);

            if (sliceable.channelNormals)
            {
                _normalSubsetOne = new TurboList <Vector3>(estimateOne);
                _normalSubsetTwo = new TurboList <Vector3>(estimateTwo);
            }

            _uvSubsetOne = new TurboList <Vector2>(estimateOne);
            _uvSubsetTwo = new TurboList <Vector2>(estimateTwo);

            int transferTableMaximumKey = c.vertices.Count;

            int[] transferTableOne = new int[transferTableMaximumKey];
            int[] transferTableTwo = new int[transferTableMaximumKey];

            for (int i = 0; i < transferTableOne.Length; i++)
            {
                transferTableOne[i] = -1;
            }
            for (int i = 0; i < transferTableTwo.Length; i++)
            {
                transferTableTwo[i] = -1;
            }

            for (int i = 0; i < submeshCount; i++)
            {
                perfectSubset(_frontIndices[i], c.vertices, c.normals, c.UVs, out indexSubsetOne[i], _geoSubsetOne, _normalSubsetOne, _uvSubsetOne, ref transferTableOne);
            }

            for (int i = 0; i < submeshCount; i++)
            {
                perfectSubset(_backIndices[i], c.vertices, c.normals, c.UVs, out indexSubsetTwo[i], _geoSubsetTwo, _normalSubsetTwo, _uvSubsetTwo, ref transferTableTwo);
            }

            geoSubsetOne = _geoSubsetOne.ToArray();
            geoSubsetTwo = _geoSubsetTwo.ToArray();
            if (sliceable.channelNormals)
            {
                normalsSubsetOne = _normalSubsetOne.ToArray();
                normalsSubsetTwo = _normalSubsetTwo.ToArray();
            }
            uvSubsetOne = _uvSubsetOne.ToArray();
            uvSubsetTwo = _uvSubsetTwo.ToArray();

            //Note that we do not explicitly call recalculate bounds because (as per the manual) this is implicit in an
            //assignment to vertices whenever the vertex count changes from zero to non-zero.

            Mesh frontMesh = new Mesh();
            Mesh backMesh  = new Mesh();

            GameObject frontObject, backObject;

            createResultObjects(go, sliceable, false, plane, out frontObject, out backObject);

            getMeshFilter(frontObject.GetComponent <Sliceable>()).mesh = frontMesh;
            getMeshFilter(backObject.GetComponent <Sliceable>()).mesh  = backMesh;

            frontMesh.vertices = geoSubsetOne;
            backMesh.vertices  = geoSubsetTwo;

            if (sliceable.channelNormals)
            {
                frontMesh.normals = normalsSubsetOne;
                backMesh.normals  = normalsSubsetTwo;
            }
            frontMesh.uv = uvSubsetOne;
            backMesh.uv  = uvSubsetTwo;

            frontMesh.subMeshCount = submeshCount;
            backMesh.subMeshCount  = submeshCount;

            for (int i = 0; i < submeshCount; i++)
            {
                frontMesh.SetTriangles(indexSubsetOne[i], i);
                backMesh.SetTriangles(indexSubsetTwo[i], i);
            }

            if (meshCaches != null)
            {
                if (go.GetComponent <DeletionCallback>() == null)
                {
                    frontObject.AddComponent <DeletionCallback>();
                    backObject.AddComponent <DeletionCallback>();
                }

                DeletionCallback frontCallback = frontObject.GetComponent <DeletionCallback>();
                DeletionCallback backCallback  = backObject.GetComponent <DeletionCallback>();

                frontCallback.deletionListener = new DeletionOccurred(this.releaseCacheByMesh);
                backCallback.deletionListener  = new DeletionOccurred(this.releaseCacheByMesh);

                frontCallback.mesh = frontMesh;
                backCallback.mesh  = backMesh;

                meshCaches[frontMesh] = frontCache;
                meshCaches[backMesh]  = backCache;
            }
            else
            {
                DeletionCallback frontCallback = frontObject.GetComponent <DeletionCallback>();
                DeletionCallback backCallback  = backObject.GetComponent <DeletionCallback>();

                if (frontCallback != null)
                {
                    GameObject.DestroyImmediate(frontCallback);
                }

                if (backCallback != null)
                {
                    GameObject.DestroyImmediate(backCallback);
                }
            }

            if (destroyOriginal)
            {
                GameObject.Destroy(go);
            }

            results    = new GameObject[2];
            results[0] = frontObject;
            results[1] = backObject;

            if (sliceable != null && sliceable.refreshColliders)
            {
                foreach (GameObject r in results)
                {
                    Collider collider = r.collider;

                    if (collider != null)
                    {
                        if (collider is BoxCollider)
                        {
                            GameObject.DestroyImmediate(collider);
                            r.AddComponent <BoxCollider>();
                        }
                        else if (collider is SphereCollider)
                        {
                            GameObject.DestroyImmediate(collider);
                            r.AddComponent <SphereCollider>();
                        }
                        else if (collider is MeshCollider)
                        {
                            MeshCollider mc = (MeshCollider)collider;

                            bool isFront = r == frontObject;

                            Mesh mesh = isFront ? frontMesh : backMesh;

                            mc.sharedMesh = mesh;
                        }
                    }
                }
            }

            if (sliceable != null)
            {
                sliceable.handleSlice(results);
            }
        }

        return(results);
    }
Пример #31
0
    private void SliceThis(Sliceable otherSliceable)
    {
        if(!childSliced.Contains(otherSliceable) && otherSliceable != null && !justSliced.Contains(otherSliceable) && !pendingSlices.Contains(otherSliceable))
        {
            pendingSlices.Add(otherSliceable);
            Debug.Log("slicing: "+otherSliceable.gameObject.name);
        //			this.GetComponent<Collider>().enabled=false;

        }
    }
 void Awake()
 {
     //We assume this will work because, with the RequireComponent attribute, we asked the Unity editor
     //to ensure the presence of a Sliceable component on the same object.
     sliceable = gameObject.GetComponent <Sliceable>();
 }
Пример #33
0
 //Setter getters
 public void SetSliceable(Sliceable slice)
 {
     this._sliceable = slice;
 }
Пример #34
0
    private void createResultObjects(GameObject go, Sliceable sliceable, bool forceCloning, Vector4 plane, out GameObject frontObject, out GameObject backObject)
    {
        Transform goTransform = go.transform;

        Dictionary<string,Transform> transformByName;
        Dictionary<string,bool> frontPresence, backPresence;

        determinePresence(goTransform, plane, out transformByName, out frontPresence, out backPresence);

        bool useAlternateForFront, useAlternateForBack;

        if(sliceable.alternatePrefab == null)
        {
            useAlternateForFront = false;
            useAlternateForBack = false;
        }
        else if(sliceable.alwaysCloneFromAlternate)
        {
            useAlternateForFront = true;
            useAlternateForBack = true;
        }
        else
        {
            useAlternateForFront = sliceable.cloneAlternate(frontPresence);
            useAlternateForBack = sliceable.cloneAlternate(backPresence);
        }

        Object frontSource = useAlternateForFront ? sliceable.alternatePrefab : go;
        Object backSource = useAlternateForBack ? sliceable.alternatePrefab : go;

        frontObject = (GameObject) GameObject.Instantiate(frontSource);
        backObject = (GameObject) GameObject.Instantiate(backSource);

        handleHierarchy(frontObject.transform, frontPresence, transformByName);
        handleHierarchy(backObject.transform, backPresence, transformByName);

        Transform parent = goTransform.parent;

        Vector3 position = goTransform.localPosition;
        Vector3 scale = goTransform.localScale;

        Quaternion rotation = goTransform.localRotation;

        frontObject.transform.parent = parent;
        frontObject.transform.localPosition = position;
        frontObject.transform.localScale = scale;

        backObject.transform.parent = parent;
        backObject.transform.localPosition = position;
        backObject.transform.localScale = scale;

        frontObject.transform.localRotation = rotation;
        backObject.transform.localRotation = rotation;

        frontObject.layer = go.layer;
        backObject.layer = go.layer;

        Rigidbody originalRigidBody = go.GetComponent<Rigidbody>();

        if(originalRigidBody != null)
        {
            Rigidbody frontRigidBody = frontObject.GetComponent<Rigidbody>();
            Rigidbody backRigidBody = backObject.GetComponent<Rigidbody>();

            if(frontRigidBody != null)
            {
                frontRigidBody.angularVelocity = originalRigidBody.angularVelocity;
                frontRigidBody.velocity = originalRigidBody.velocity;
                frontRigidBody.useGravity = true;
            }

            if(backRigidBody != null)
            {
                backRigidBody.angularVelocity = originalRigidBody.angularVelocity;
                backRigidBody.velocity = originalRigidBody.velocity;
                backRigidBody.useGravity = true;
            }
        }

        //		if( frontObject.tag == "TargetClone" )
        //		{
        //			frontObject.GetComponent<Collider> ().enabled = false;
        //			backObject.GetComponent<Collider> ().enabled = false;
        //		}
        //		else
        //		{
        frontObject.GetComponent<Collider> ().isTrigger = false;
        backObject.GetComponent<Collider> ().isTrigger = false;
        //		}

        if( frontObject.tag == "Target" )
            frontObject.tag = backObject.tag = "TargetClone";
    }
Пример #35
0
    public override void OnInspectorGUI()
    {
        bool someTargetsAreUnvetted           = false;
        bool someTargetsHaveMultipleRenderers = false;

        List <Renderer> relevantRenderers = new List <Renderer>();
        List <Renderer> allRenderers      = new List <Renderer>();

        foreach (Object o in targets)
        {
            Sliceable s = (Sliceable)o;

            Component[] _allRenderersOnThisTarget = s.GetComponentsInChildren(typeof(Renderer), true);

            Renderer[] allRenderersOnThisTarget = new Renderer[_allRenderersOnThisTarget.Length];

            for (int i = 0; i < _allRenderersOnThisTarget.Length; i++)
            {
                allRenderersOnThisTarget[i] = _allRenderersOnThisTarget[i] as Renderer;
            }

            allRenderers.AddRange(allRenderersOnThisTarget);

            if (allRenderersOnThisTarget.Length == 1)
            {
                relevantRenderers.Add(allRenderersOnThisTarget[0]);
            }
            else if (s.explicitlySelectedMeshHolder != null)
            {
                relevantRenderers.Add(s.explicitlySelectedMeshHolder.GetComponent(typeof(Renderer)) as Renderer);
            }
            else
            {
                someTargetsAreUnvetted = true;
            }

            someTargetsHaveMultipleRenderers |= allRenderersOnThisTarget.Length > 1;
        }

        EditorGUILayout.PropertyField(refreshCollidersProperty, new GUIContent("Refresh colliders"));
        EditorGUILayout.PropertyField(alternatePrefabProperty, new GUIContent("Alternate prefab"));
        EditorGUILayout.PropertyField(shreddableProperty, new GUIContent("Shreddable"));

        bool atLeastSomeHaveAlternatePrefab = alternatePrefabProperty.hasMultipleDifferentValues || alternatePrefabProperty.objectReferenceValue != null;

        if (atLeastSomeHaveAlternatePrefab)
        {
            EditorGUILayout.PropertyField(alwaysCloneFromAlternateProperty, new GUIContent("Always clone from alternate"));
        }

        EditorGUILayout.PropertyField(channelNormalsProperty, new GUIContent("Process Normals"));
        EditorGUILayout.PropertyField(channelTangentsProperty, new GUIContent("Process Tangents"));
        EditorGUILayout.PropertyField(channelUV2Property, new GUIContent("Process UV2"));

        EditorGUILayout.Separator();

        //Ensure that all the targets are vetted and if they're not, we can only vet them one at a time
        //through the unity inspector.

        if (relevantRenderers.Count == 0)
        {
            EditorGUILayout.LabelField("No mesh renderers found!");
        }
        else if (someTargetsAreUnvetted && (targets.Length > 1))
        {
            EditorGUILayout.LabelField("Cannot multi-edit: Some objects have multiple");
            EditorGUILayout.LabelField("meshes. Please vet them individually.");
        }
        else if (someTargetsHaveMultipleRenderers && (targets.Length == 1))
        {
            EditorGUILayout.LabelField("This object has multiple meshes. Specify the primary.");

            int selectedRenderer = 0;

            GameObject explicitlySelectedMeshHolder = explicitlySelectedMeshHolderProperty.objectReferenceValue as GameObject;

            if (explicitlySelectedMeshHolder != null)
            {
                Renderer r = explicitlySelectedMeshHolder.GetComponent <Renderer>();
                if (r != null)
                {
                    selectedRenderer = allRenderers.IndexOf(r);
                }
            }

            string[] displayedOptions = new string[allRenderers.Count];
            for (int i = 0; i < displayedOptions.Length; i++)
            {
                displayedOptions[i] = allRenderers[i].name;
            }

            selectedRenderer = EditorGUILayout.Popup("Slice Mesh", selectedRenderer, displayedOptions);

            Renderer renderer = allRenderers[selectedRenderer];

            explicitlySelectedMeshHolderProperty.objectReferenceValue = renderer.gameObject;
        }

        serializedObject.ApplyModifiedProperties();

        //Assuming we're all legit, let's multi-edit the infillers.

        if (!someTargetsAreUnvetted)
        {
            List <Material> mats = new List <Material>();

            foreach (Renderer r in relevantRenderers)
            {
                Material[] _mats = r.sharedMaterials;
                foreach (Material mat in _mats)
                {
                    if (mats.Contains(mat) == false)
                    {
                        mats.Add(mat);
                    }
                }
            }

            if (mats.Count > 0)
            {
                EditorGUILayout.LabelField("For each material, define what region is used for infill.");
            }
        }

        if (!someTargetsAreUnvetted)
        {
            var mats = new List <Material>();
            var preexistingInfillers = new List <InfillConfiguration>();

            foreach (Object o in targets)
            {
                Sliceable s = o as Sliceable;

                Renderer renderer;

                if (s.explicitlySelectedMeshHolder != null)
                {
                    renderer = s.explicitlySelectedMeshHolder.GetComponent <Renderer>();
                }
                else
                {
                    renderer = s.gameObject.GetComponent <Renderer>();
                }

                if (renderer != null)
                {
                    Material[] _mats = renderer.sharedMaterials;

                    foreach (Material mat in _mats)
                    {
                        if (mats.Contains(mat) == false)
                        {
                            mats.Add(mat);
                        }
                    }
                }

                preexistingInfillers.AddRange(s.infillers);
            }

            InfillConfiguration[] infillers = new InfillConfiguration[mats.Count];

            var forceDirty = false;

            for (int i = 0; i < mats.Count; i++)
            {
                Material mat = mats[i];

                InfillConfiguration infiller = null;

                foreach (var _infiller in preexistingInfillers)
                {
                    if (_infiller.material == mat)
                    {
                        infiller = _infiller;
                        break;
                    }
                }

                //If there is no infiller, than the UI will create one. However, the GUI will not be seen as changed, and
                //therefore if we do not set some flag, than the code lower down will not recognize that it ought to
                //set the item as 'dirty'.

                if (infiller == null)
                {
                    infiller          = new InfillConfiguration();
                    infiller.material = mat;

                    infiller.regionForInfill = new Rect(0f, 0f, 1f, 1f);
                    forceDirty = true;
                }

                infillers[i] = infiller;
            }

            foreach (var infiller in infillers)
            {
                EditorGUILayout.Separator();

                EditorGUILayout.LabelField("Material: " + infiller.material.name);

                infiller.regionForInfill = EditorGUILayout.RectField("Region for infill", infiller.regionForInfill);
            }

            if (GUI.changed || forceDirty)
            {
                foreach (Object o in targets)
                {
                    Sliceable s = o as Sliceable;

                    s.infillers = new InfillConfiguration[infillers.Length];

                    System.Array.Copy(infillers, s.infillers, infillers.Length);

                    EditorUtility.SetDirty(o);
                }
            }
        }
    }
Пример #36
0
    public override void OnInspectorGUI()
    {
        bool someTargetsHaveMultipleRenderers = false;

        var allRenderers = new List <Renderer>();

        foreach (Object o in targets)
        {
            Sliceable s = (Sliceable)o;

            Component[] _allRenderersOnThisTarget = s.GetComponentsInChildren(typeof(Renderer), true);

            Renderer[] allRenderersOnThisTarget = new Renderer[_allRenderersOnThisTarget.Length];

            for (int i = 0; i < _allRenderersOnThisTarget.Length; i++)
            {
                allRenderersOnThisTarget[i] = _allRenderersOnThisTarget[i] as Renderer;
            }

            allRenderers.AddRange(allRenderersOnThisTarget);

            someTargetsHaveMultipleRenderers |= allRenderersOnThisTarget.Length > 1;
        }

        EditorGUILayout.PropertyField(refreshCollidersProperty, new GUIContent("Refresh colliders"));
        EditorGUILayout.PropertyField(alternatePrefabProperty, new GUIContent("Alternate prefab"));
        EditorGUILayout.PropertyField(shreddableProperty, new GUIContent("Shreddable"));

        bool atLeastSomeHaveAlternatePrefab = alternatePrefabProperty.hasMultipleDifferentValues || alternatePrefabProperty.objectReferenceValue != null;

        if (atLeastSomeHaveAlternatePrefab)
        {
            EditorGUILayout.PropertyField(alwaysCloneFromAlternateProperty, new GUIContent("Always clone from alternate"));
        }

        EditorGUILayout.PropertyField(channelNormalsProperty, new GUIContent("Process Normals"));
        EditorGUILayout.PropertyField(channelTangentsProperty, new GUIContent("Process Tangents"));
        EditorGUILayout.PropertyField(channelUV2Property, new GUIContent("Process UV2"));

        EditorGUILayout.Separator();

        //Ensure that all the targets are vetted and if they're not, we can only vet them one at a time
        //through the unity inspector.

        if (allRenderers.Count == 0)
        {
            EditorGUILayout.LabelField("No mesh renderers found!");
        }

        serializedObject.ApplyModifiedProperties();

        //Assuming we're all legit, let's multi-edit the infillers.

        var mats = new HashSet <Material>();

        foreach (var r in allRenderers)
        {
            Material[] _mats = r.sharedMaterials;
            foreach (Material mat in _mats)
            {
                mats.Add(mat);
            }
        }

        if (mats.Count > 0)
        {
            EditorGUILayout.LabelField("For each material, define what region is used for infill.");
        }

        var preexistingInfillers = new List <InfillConfiguration>();

        foreach (Object o in targets)
        {
            Sliceable s = o as Sliceable;

            Renderer renderer;

            renderer = s.gameObject.GetComponent <Renderer>();

            if (renderer != null)
            {
                Material[] _mats = renderer.sharedMaterials;

                foreach (Material mat in _mats)
                {
                    if (mats.Contains(mat) == false)
                    {
                        mats.Add(mat);
                    }
                }
            }

            preexistingInfillers.AddRange(s.infillers);
        }

        var infillersBuilder = new List <InfillConfiguration>();

        var forceDirty = false;

        foreach (var mat in mats)
        {
            InfillConfiguration infiller = null;

            foreach (var _infiller in preexistingInfillers)
            {
                if (_infiller.material == mat)
                {
                    infiller = _infiller;
                    break;
                }
            }

            //If there is no infiller, than the UI will create one. However, the GUI will not be seen as changed, and
            //therefore if we do not set some flag, than the code lower down will not recognize that it ought to
            //set the item as 'dirty'.

            if (infiller == null)
            {
                infiller          = new InfillConfiguration();
                infiller.material = mat;

                infiller.regionForInfill = new Rect(0f, 0f, 1f, 1f);
                forceDirty = true;
            }

            infillersBuilder.Add(infiller);
        }

        foreach (var infiller in infillersBuilder)
        {
            EditorGUILayout.Separator();

            var material     = infiller.material;
            var materialName = material == null ? "Null" : material.name;

            EditorGUILayout.LabelField("Material: " + materialName);

            infiller.regionForInfill = EditorGUILayout.RectField("Region for infill", infiller.regionForInfill);
        }

        if (GUI.changed || forceDirty)
        {
            var infillersArray = infillersBuilder.ToArray();

            foreach (Object o in targets)
            {
                Sliceable s = o as Sliceable;

                s.infillers = infillersArray;

                EditorUtility.SetDirty(o);
            }
        }
    }
Пример #37
0
    public override void OnInspectorGUI()
    {
        bool someTargetsAreUnvetted           = false;
        bool someTargetsHaveMultipleRenderers = false;

        List <Renderer> relevantRenderers = new List <Renderer>();
        List <Renderer> allRenderers      = new List <Renderer>();

        foreach (Object o in targets)
        {
            Sliceable s = (Sliceable)o;

            Component[] _allRenderersOnThisTarget = s.GetComponentsInChildren(typeof(Renderer), true);

            Renderer[] allRenderersOnThisTarget = new Renderer[_allRenderersOnThisTarget.Length];

            for (int i = 0; i < _allRenderersOnThisTarget.Length; i++)
            {
                allRenderersOnThisTarget[i] = _allRenderersOnThisTarget[i] as Renderer;
            }

            allRenderers.AddRange(allRenderersOnThisTarget);

            if (allRenderersOnThisTarget.Length == 1)
            {
                relevantRenderers.Add(allRenderersOnThisTarget[0]);
            }
            else if (s.explicitlySelectedMeshHolder != null)
            {
                relevantRenderers.Add(s.meshHolder.GetComponent(typeof(Renderer)) as Renderer);
            }
            else
            {
                someTargetsAreUnvetted = true;
            }

            someTargetsHaveMultipleRenderers |= allRenderersOnThisTarget.Length > 1;
        }

        EditorGUILayout.PropertyField(refreshCollidersProperty, new GUIContent("Refresh colliders"));
        EditorGUILayout.PropertyField(alternatePrefabProperty, new GUIContent("Alternate prefab"));

        bool atLeastSomeHaveAlternatePrefab = alternatePrefabProperty.hasMultipleDifferentValues || alternatePrefabProperty.objectReferenceValue != null;

        if (atLeastSomeHaveAlternatePrefab)
        {
            EditorGUILayout.PropertyField(alwaysCloneFromAlternateProperty, new GUIContent("Always clone from alternate"));
        }

        EditorGUILayout.PropertyField(channelNormalsProperty, new GUIContent("Process Normals"));
        EditorGUILayout.PropertyField(channelTangentsProperty, new GUIContent("Process Tangents"));
        EditorGUILayout.PropertyField(channelUV2Property, new GUIContent("Process UV2"));

        EditorGUILayout.Separator();

        //Ensure that all the targets are vetted and if they're not, we can only vet them one at a time
        //through the unity inspector.

        if (relevantRenderers.Count == 0)
        {
            EditorGUILayout.LabelField("No mesh renderers found!");
        }
        else if (someTargetsAreUnvetted && (targets.Length > 1))
        {
            EditorGUILayout.LabelField("Cannot multi-edit: Some objects have multiple");
            EditorGUILayout.LabelField("meshes. Please vet them individually.");
        }
        else if (someTargetsHaveMultipleRenderers && (targets.Length == 1))
        {
            EditorGUILayout.LabelField("This object has multiple meshes. Specify the primary.");

            int selectedRenderer = 0;

            GameObject explicitlySelectedMeshHolder = explicitlySelectedMeshHolderProperty.objectReferenceValue as GameObject;

            if (explicitlySelectedMeshHolder != null)
            {
                Renderer r = explicitlySelectedMeshHolder.GetComponent <Renderer>();
                if (r != null)
                {
                    selectedRenderer = allRenderers.IndexOf(r);
                }
            }

            string[] displayedOptions = new string[allRenderers.Count];
            for (int i = 0; i < displayedOptions.Length; i++)
            {
                displayedOptions[i] = allRenderers[i].name;
            }

            selectedRenderer = EditorGUILayout.Popup("Slice Mesh", selectedRenderer, displayedOptions);

            Renderer renderer = allRenderers[selectedRenderer];

            explicitlySelectedMeshHolderProperty.objectReferenceValue = renderer.gameObject;
        }

        serializedObject.ApplyModifiedProperties();

        //Assuming we're all legit, let's multi-edit the infillers.

        if (!someTargetsAreUnvetted)
        {
            List <Material> mats = new List <Material>();

            foreach (Renderer r in relevantRenderers)
            {
                Material[] _mats = r.sharedMaterials;
                foreach (Material mat in _mats)
                {
                    if (mats.Contains(mat) == false)
                    {
                        mats.Add(mat);
                    }
                }
            }

            if (mats.Count > 0)
            {
                EditorGUILayout.LabelField("For each material, define what region is used for infill.");
            }
        }

        if (!someTargetsAreUnvetted)
        {
            List <Material> mats = new List <Material>();
            List <TurboSlice.InfillConfiguration> preexistingInfillers = new List <TurboSlice.InfillConfiguration>();

            foreach (Object o in targets)
            {
                Sliceable s = o as Sliceable;

                Material[] _mats = s.meshHolder.GetComponent <Renderer>().sharedMaterials;

                foreach (Material mat in _mats)
                {
                    if (mats.Contains(mat) == false)
                    {
                        mats.Add(mat);
                    }
                }

                preexistingInfillers.AddRange(s.infillers);
            }

            TurboSlice.InfillConfiguration[] infillers = new TurboSlice.InfillConfiguration[mats.Count];

            for (int i = 0; i < mats.Count; i++)
            {
                Material mat = mats[i];

                TurboSlice.InfillConfiguration infiller = null;

                foreach (TurboSlice.InfillConfiguration _infiller in preexistingInfillers)
                {
                    if (_infiller.material == mat)
                    {
                        infiller = _infiller;
                        break;
                    }
                }

                if (infiller == null)
                {
                    infiller                 = new TurboSlice.InfillConfiguration();
                    infiller.material        = mat;
                    infiller.regionForInfill = new Rect(0f, 0f, 1f, 1f);
                }

                infillers[i] = infiller;
            }

            foreach (TurboSlice.InfillConfiguration infiller in infillers)
            {
                EditorGUILayout.Separator();

                EditorGUILayout.LabelField("Material: " + infiller.material.name);

                infiller.regionForInfill = EditorGUILayout.RectField("Region for infill", infiller.regionForInfill);
            }

            if (GUI.changed)
            {
                foreach (Object o in targets)
                {
                    Sliceable s = o as Sliceable;

                    s.infillers = new TurboSlice.InfillConfiguration[infillers.Length];

                    System.Array.Copy(infillers, s.infillers, infillers.Length);

                    EditorUtility.SetDirty(o);
                }
            }
        }

        /*if(!someTargetsAreUnvetted)
         * {
         *      List<Material> mats = new List<Material>();
         *
         *      foreach(Renderer r in relevantRenderers)
         *      {
         *              Material[] _mats = r.sharedMaterials;
         *              foreach(Material mat in _mats)
         *              {
         *                      if(mats.Contains(mat) == false) mats.Add(mat);
         *              }
         *      }
         *
         *      if(mats.Count > 0)
         *      {
         *              EditorGUILayout.LabelField("For each material, define what region is used for infill.");
         *      }
         *
         *      foreach(Material mat in mats)
         *      {
         *              //Is this material represented in our array?
         *
         *              EditorGUILayout.Separator();
         *
         *              SerializedProperty infiller = null;
         *
         *              for(int i = 0; i < infillersProperty.arraySize; i++)
         *              {
         *                      SerializedProperty _infiller = infillersProperty.GetArrayElementAtIndex(i);
         *                      _infiller.
         *                      SerializedProperty _mat = _infiller.FindPropertyRelative("material");
         *                      if(_mat != null)
         *                      {
         *                              Material thisMat = _mat.objectReferenceValue as Material;
         *                              if(thisMat == mat)
         *                              {
         *                                      infiller = _infiller;
         *                              }
         *                      }
         *              }
         *
         *              if(infiller == null)
         *              {
         *                      infillersProperty.InsertArrayElementAtIndex(0);
         *                      infiller = infillersProperty.GetArrayElementAtIndex(0);
         *
         *                      SerializedProperty _mat = infiller.FindPropertyRelative("material");
         *                      _mat.objectReferenceValue = mat;
         *              }
         *
         *              EditorGUILayout.LabelField("Material: " + mat.name);
         *
         *              SerializedProperty regionForInfillProperty = infiller.FindPropertyRelative("regionForInfill");
         *
         *              EditorGUILayout.PropertyField(regionForInfillProperty, new GUIContent("Region for infill"));
         *      }
         *
         *      {
         *              List<Material> observedMats = new List<Material>();
         *
         *              for(int i = 0; i < infillersProperty.arraySize; i++)
         *              {
         *                      SerializedProperty _infiller = infillersProperty.GetArrayElementAtIndex(i);
         *                      SerializedProperty _mat = _infiller.FindPropertyRelative("material");
         *                      Material mat = _mat.objectReferenceValue as Material;
         *                      bool delete = mat == null || observedMats.Contains(mat);
         *                      if(delete) infillersProperty.DeleteArrayElementAtIndex(i--);
         *                      else observedMats.Add(mat);
         *              }
         *      }
         * }*/
    }
Пример #38
0
    public override void OnInspectorGUI()
    {
        Sliceable s = (Sliceable)target;

        Renderer[] renderers = s.GetComponentsInChildren <Renderer>(true);

        bool isAnimated = false;

        foreach (Renderer r in renderers)
        {
            isAnimated |= r is SkinnedMeshRenderer;
        }

        //TurboSlice.supportsSkinned is a const that is overridden by the presence of Ragdoll Slicer
#pragma warning disable 0162
        if (isAnimated && !TurboSlice.supportsSkinned)
        {
            EditorGUILayout.LabelField("Error!");
            EditorGUILayout.LabelField("Skinned meshes are not supported.");
            return;
        }

        s.refreshColliders = EditorGUILayout.Toggle("Refresh colliders", s.refreshColliders);

        s.alternatePrefab = EditorGUILayout.ObjectField("Alternate prefab", (Object)s.alternatePrefab, typeof(GameObject), false);

        if (s.alternatePrefab != null)
        {
            s.alwaysCloneFromAlternate = EditorGUILayout.Toggle("Always clone from alternate", s.alwaysCloneFromAlternate);
        }

        s.currentlySliceable = EditorGUILayout.Toggle("Currently Sliceable", s.currentlySliceable);

        s.category = EditorGUILayout.TextField("Category", s.category);

        s.channelNormals  = EditorGUILayout.Toggle("Process Normals", s.channelNormals);
        s.channelTangents = EditorGUILayout.Toggle("Process Tangents", s.channelTangents);
        s.channelUV2      = EditorGUILayout.Toggle("Process UV2", s.channelUV2);

        Renderer renderer = null;

        if (renderers.Length == 0)
        {
            EditorGUILayout.LabelField("No mesh renderers found in this object!");
        }
        else if (renderers.Length > 1)
        {
            EditorGUILayout.LabelField("This object has multiple meshes. Specify the primary.");

            int selectedRenderer = 0;

            if (s.explicitlySelectedMeshHolder != null)
            {
                Renderer r = s.explicitlySelectedMeshHolder.GetComponent <Renderer>();
                if (r != null)
                {
                    selectedRenderer = System.Array.IndexOf <Renderer>(renderers, r);
                }
            }

            string[] displayedOptions = new string[renderers.Length];
            for (int i = 0; i < displayedOptions.Length; i++)
            {
                displayedOptions[i] = renderers[i].name;
            }

            selectedRenderer = EditorGUILayout.Popup("Slice Mesh", selectedRenderer, displayedOptions);

            renderer = renderers[selectedRenderer];
            s.explicitlySelectedMeshHolder = renderer.gameObject;
        }
        else if (renderers.Length == 1)
        {
            renderer = renderers[0];

            s.explicitlySelectedMeshHolder = renderer.gameObject;
        }

        if (renderer != null)
        {
            List <TurboSlice.InfillConfiguration> newInfillers = new List <TurboSlice.InfillConfiguration>();

            Material[] mats = renderer.sharedMaterials;

            if (mats.Length > 0)
            {
                EditorGUILayout.LabelField("For each material, define what region is used for infill.");
            }

            foreach (Material mat in mats)
            {
                //Is this material represented in our array?

                EditorGUILayout.Separator();

                if (s.infillers == null)
                {
                    s.infillers = new TurboSlice.InfillConfiguration[0];
                }

                TurboSlice.InfillConfiguration infiller = null;
                foreach (TurboSlice.InfillConfiguration ifc in s.infillers)
                {
                    if (ifc.material == mat)
                    {
                        infiller = ifc;
                        break;
                    }
                }

                EditorGUILayout.LabelField("Material: " + mat.name);

                bool hasIt = EditorGUILayout.Toggle("Infill this material", infiller != null);

                if (hasIt && infiller == null)
                {
                    infiller = new TurboSlice.InfillConfiguration();

                    infiller.material = mat;
                }
                else if (!hasIt)
                {
                    infiller = null;
                }

                if (infiller != null)
                {
                    newInfillers.Add(infiller);

                    infiller.regionForInfill = EditorGUILayout.RectField(infiller.regionForInfill);
                }
            }

            s.infillers = newInfillers.ToArray();
        }

        if (GUI.changed)
        {
            EditorUtility.SetDirty(target);
        }
    }
 void Awake()
 {
     sliceable = gameObject.GetComponent <Sliceable>();
 }