Пример #1
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);
        }
    }
Пример #2
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);
         *              }
         *      }
         * }*/
    }
Пример #3
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.PropertyField(shatterProperty, new GUIContent("Process shatter"));

        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);
                }
            }
        }*/
    }
Пример #4
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);
        }
    }