public override void OnInspectorGUI()
    {
        EditorGUI.BeginChangeCheck();

        base.OnInspectorGUI();
        if (GUILayout.Button("Place"))
        {
            foreach (Object obj in targets)
            {
                MultiMaterialPlacer m         = obj as MultiMaterialPlacer;
                Material[]          materials = PlaceObjects(m);
                if (materials != null)
                {
                    foreach (Material mat in materials)
                    {
                        UnityEditor.Experimental.Rendering.HDPipeline.HDEditorUtils.ResetMaterialKeywords(mat);
                    }
                }
            }
        }

        if (EditorGUI.EndChangeCheck())
        {
            serializedObject.ApplyModifiedProperties();

            if (_materialEditor != null)
            {
                // Free the memory used by the previous MaterialEditor
                DestroyImmediate(_materialEditor);
            }

            if (!serializedObject.FindProperty("material").hasMultipleDifferentValues&& (serializedObject.FindProperty("material") != null))
            {
                // Create a new instance of the default MaterialEditor
                _materialEditor = (MaterialEditor)CreateEditor((Material)serializedObject.FindProperty("material").objectReferenceValue);
            }
        }


        if (_materialEditor != null)
        {
            // Draw the material's foldout and the material shader field
            // Required to call _materialEditor.OnInspectorGUI ();
            _materialEditor.DrawHeader();

            //  We need to prevent the user to edit Unity default materials
            bool isDefaultMaterial = !AssetDatabase.GetAssetPath((Material)serializedObject.FindProperty("material").objectReferenceValue).StartsWith("Assets");

            using (new EditorGUI.DisabledGroupScope(isDefaultMaterial))
            {
                // Draw the material properties
                // Works only if the foldout of _materialEditor.DrawHeader () is open
                _materialEditor.OnInspectorGUI();
            }
        }
    }
    Renderer CopyObject(Renderer _target, float _x, float _y, Transform _parent, MultiMaterialPlacer _placer)
    {
        Renderer o = Instantiate(_target.gameObject).GetComponent <Renderer>();

        o.sharedMaterial             = Instantiate(_target.sharedMaterial);
        o.transform.parent           = _parent;
        o.transform.localPosition    = new Vector3(_x, _y, 0f);
        o.transform.localRotation    = Quaternion.identity;
        o.transform.localScale       = Vector3.one * _placer.scale;
        o.transform.localEulerAngles = _placer.rotation;
        return(o);
    }
    public static void PlaceObjects(MultiMaterialPlacer _target)
    {
        //clear hierarchy
        for (int i = _target.transform.childCount - 1; i >= 0; --i)
        {
            //DestroyImmediate(_target.transform.GetChild(i).GetComponent<Renderer>().sharedMaterial);
            DestroyImmediate(_target.transform.GetChild(i).gameObject);
        }

        if (_target.prefabObject == null)
        {
            return;
        }

        List <Material> materials = new List <Material>();

        Renderer refObject = Instantiate(_target.prefabObject.gameObject).GetComponent <Renderer>();

        if (_target.material != null)
        {
            refObject.sharedMaterial = Instantiate(_target.material);
        }
        else
        {
            refObject.sharedMaterial = Instantiate(_target.prefabObject.sharedMaterial);
        }

        for (int i = 0; i < _target.commonParameters.Length; i++)
        {
            ApplyParameterToMaterial(refObject.sharedMaterial, _target.commonParameters[i]);
            if (_target.overideRenderQueue)
            {
                refObject.sharedMaterial.renderQueue = (int)_target.renderQueue;
            }
        }

        float x = 0f;
        float y = 0f;

        if (_target.is2D)
        {
            if (_target.instanceParameters.Length < 2)
            {
                return;
            }
            if (!(_target.instanceParameters[0].multi && _target.instanceParameters[1].multi))
            {
                return;
            }

            for (int i = 0; i < _target.instanceParameters[0].count; i++)
            {
                for (int j = 0; j < _target.instanceParameters[1].count; j++)
                {
                    Renderer tmp = CopyObject(refObject, x, y, _target.transform, _target);
                    tmp.gameObject.name  = _target.prefabObject.name + "_" + ApplyParameterToMaterial(tmp.sharedMaterial, _target.instanceParameters[0], i);
                    tmp.gameObject.name += "_" + ApplyParameterToMaterial(tmp.sharedMaterial, _target.instanceParameters[1], j);
                    materials.Add(tmp.sharedMaterial);
                    y -= _target.offset;
                }
                x += _target.offset;
                y  = 0f;
            }
        }
        else
        {
            for (int i = 0; i < _target.instanceParameters.Length; i++)
            {
                if (!string.IsNullOrEmpty(_target.instanceParameters[i].parameter))
                {
                    if (_target.instanceParameters[i].multi)
                    {
                        if (_target.instanceParameters[i].paramType == MaterialParameterVariation.ParamType.Texture)
                        {
                            Renderer tmp = CopyObject(refObject, x, y, _target.transform, _target);
                            tmp.gameObject.name = _target.prefabObject.name + "_" + ApplyParameterToMaterial(tmp.sharedMaterial, _target.instanceParameters[i]);
                            materials.Add(tmp.sharedMaterial);
                        }
                        else
                        {
                            for (int j = 0; j < _target.instanceParameters[i].count; j++)
                            {
                                if (j > 0)
                                {
                                    x += _target.offset;
                                }

                                Renderer tmp = CopyObject(refObject, x, y, _target.transform, _target);
                                tmp.gameObject.name = _target.prefabObject.name + "_" + ApplyParameterToMaterial(tmp.sharedMaterial, _target.instanceParameters[i], j);
                                materials.Add(tmp.sharedMaterial);
                            }
                        }
                    }
                    else
                    {
                        Renderer tmp = CopyObject(refObject, x, y, _target.transform, _target);
                        tmp.gameObject.name = _target.prefabObject.name + "_" + ApplyParameterToMaterial(tmp.sharedMaterial, _target.instanceParameters[i]);
                        materials.Add(tmp.sharedMaterial);
                    }
                }

                x += _target.offset;
            }
        }

        DestroyImmediate(refObject.gameObject);

        if (materials != null)
        {
            foreach (Material mat in materials)
            {
                UnityEditor.Rendering.HighDefinition.HDShaderUtils.ResetMaterialKeywords(mat);
            }
        }

        UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
    }
    public Material[] PlaceObjects(MultiMaterialPlacer _target)
    {
        //clear hierarchy
        for (int i = _target.transform.childCount - 1; i >= 0; --i)
        {
            //DestroyImmediate(_target.transform.GetChild(i).GetComponent<Renderer>().sharedMaterial);
            DestroyImmediate(_target.transform.GetChild(i).gameObject);
        }

        if (_target.prefabObject == null)
        {
            return(null);
        }

        List <Material> outMats = new List <Material>();;

        Renderer refObject = Instantiate(_target.prefabObject.gameObject).GetComponent <Renderer>();

        if (_target.material != null)
        {
            refObject.sharedMaterial = Instantiate(_target.material);
        }
        else
        {
            refObject.sharedMaterial = Instantiate(_target.prefabObject.sharedMaterial);
        }

        for (int i = 0; i < _target.commonParameters.Length; i++)
        {
            ApplyParameterToMaterial(refObject.sharedMaterial, _target.commonParameters[i]);
        }

        float x = 0f;
        float y = 0f;

        if (_target.is2D)
        {
            if (_target.instanceParameters.Length < 2)
            {
                return(null);
            }
            if (!(_target.instanceParameters[0].multi && _target.instanceParameters[1].multi))
            {
                return(null);
            }

            for (int i = 0; i < _target.instanceParameters[0].count; i++)
            {
                for (int j = 0; j < _target.instanceParameters[1].count; j++)
                {
                    Renderer tmp = CopyObject(refObject, x, y, _target.transform, _target);
                    tmp.gameObject.name  = _target.prefabObject.name + "_" + ApplyParameterToMaterial(tmp.sharedMaterial, _target.instanceParameters[0], i);
                    tmp.gameObject.name += "_" + ApplyParameterToMaterial(tmp.sharedMaterial, _target.instanceParameters[1], j);
                    outMats.Add(tmp.sharedMaterial);
                    y -= _target.offset;
                }
                x += _target.offset;
                y  = 0f;
            }
        }
        else
        {
            for (int i = 0; i < _target.instanceParameters.Length; i++)
            {
                if (!string.IsNullOrEmpty(_target.instanceParameters[i].parameter))
                {
                    if (_target.instanceParameters[i].multi)
                    {
                        if (_target.instanceParameters[i].paramType == MaterialParameterVariation.ParamType.Texture)
                        {
                            Renderer tmp = CopyObject(refObject, x, y, _target.transform, _target);
                            tmp.gameObject.name = _target.prefabObject.name + "_" + ApplyParameterToMaterial(tmp.sharedMaterial, _target.instanceParameters[i]);
                            outMats.Add(tmp.sharedMaterial);
                        }
                        else
                        {
                            for (int j = 0; j < _target.instanceParameters[i].count; j++)
                            {
                                if (j > 0)
                                {
                                    x += _target.offset;
                                }

                                Renderer tmp = CopyObject(refObject, x, y, _target.transform, _target);
                                tmp.gameObject.name = _target.prefabObject.name + "_" + ApplyParameterToMaterial(tmp.sharedMaterial, _target.instanceParameters[i], j);
                                outMats.Add(tmp.sharedMaterial);
                            }
                        }
                    }
                    else
                    {
                        Renderer tmp = CopyObject(refObject, x, y, _target.transform, _target);
                        tmp.gameObject.name = _target.prefabObject.name + "_" + ApplyParameterToMaterial(tmp.sharedMaterial, _target.instanceParameters[i]);
                        outMats.Add(tmp.sharedMaterial);
                    }
                }

                x += _target.offset;
            }
        }

        DestroyImmediate(refObject.gameObject);

        return(outMats.ToArray());
    }