<|start_filename|>Unity3D/Assets/RosSharp/Editor/UrdfImporter/UrdfRobotExtensions.cs<|end_filename|>
﻿/*
© Siemens AG, 2017
Author: Dr. <NAME> (<EMAIL>)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

<http://www.apache.org/licenses/LICENSE-2.0>.

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using UnityEngine;
using UnityEditor;

namespace RosSharp.UrdfImporter
{
    public static class RobotCreator
    {
        public static GameObject Create(string filename)
        {
            Robot robot = new Robot(filename);
            return robot.Create();
        }
    }

    public static class UrdfRobotExtensions
    {
        public static GameObject Create(this Robot robot)
        {
            if (UrdfAssetDatabase.GetAssetPath(robot.filename) == null)
            { 
                Debug.LogError("URDF file and ressources must be placed in Assets Folder:\n" + Application.dataPath);
                return null;
            }

            UrdfAssetDatabase.Initialize(robot);

            GameObject gameObject = new GameObject(robot.name);
            robot.root.Create(gameObject);

            GameObjectUtility.SetParentAndAlign(gameObject, Selection.activeObject as GameObject);
            Undo.RegisterCreatedObjectUndo(gameObject, "Create " + gameObject.name);
            Selection.activeObject = gameObject;

            setKinematic(gameObject, true);

            return gameObject;
        }

        public static void setKinematic(GameObject robot, bool isKinematic)
        {
            Rigidbody[] rigidbodies = robot.GetComponentsInChildren<Rigidbody>();
            foreach (Rigidbody rigidbody in rigidbodies)
                rigidbody.isKinematic = isKinematic;
        }
    }
}


<|start_filename|>Unity3D/Assets/RosSharp/Editor/UrdfImporter/UrdfLinkGeometryBoxExtensions.cs<|end_filename|>
﻿/*
© Siemens AG, 2017
Author: Dr. <NAME> (<EMAIL>)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

<http://www.apache.org/licenses/LICENSE-2.0>.

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using UnityEngine;

namespace RosSharp.UrdfImporter
{
    public static class UrdfLinkGeometryBoxExtensions
    {
        public static GameObject CreateVisual(this Link.Geometry.Box box, GameObject parent)
        {
            GameObject gameObject = new GameObject("Box");
            gameObject.transform.SetParentAndAlign(parent.transform);

            MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();
            meshFilter.mesh = box.GetMesh();
            gameObject.AddComponent<MeshRenderer>();

            return gameObject;
        }

        public static GameObject CreateCollider(this Link.Geometry.Box box, GameObject parent)
        {
            GameObject gameObject = new GameObject("Box");
            gameObject.transform.SetParentAndAlign(parent.transform);

            BoxCollider boxCollider = gameObject.AddComponent<BoxCollider>();
            boxCollider.size = new Vector3((float)box.size[1], (float)box.size[2], (float)box.size[0]);

            return gameObject;
        }

        private static Mesh GetMesh(this Link.Geometry.Box box)
        {
            float length = (float)box.size[1];
            float width = (float)box.size[2];
            float height = (float)box.size[0];

            #region Vertices
            Vector3 p0 = new Vector3(-length * .5f, -width * .5f, height * .5f);
            Vector3 p1 = new Vector3(length * .5f, -width * .5f, height * .5f);
            Vector3 p2 = new Vector3(length * .5f, -width * .5f, -height * .5f);
            Vector3 p3 = new Vector3(-length * .5f, -width * .5f, -height * .5f);

            Vector3 p4 = new Vector3(-length * .5f, width * .5f, height * .5f);
            Vector3 p5 = new Vector3(length * .5f, width * .5f, height * .5f);
            Vector3 p6 = new Vector3(length * .5f, width * .5f, -height * .5f);
            Vector3 p7 = new Vector3(-length * .5f, width * .5f, -height * .5f);

            Vector3[] vertices = new Vector3[]
            {
                p0, p1, p2, p3, // Bottom                
                p7, p4, p0, p3, // Left             
                p4, p5, p1, p0, // Front                
                p6, p7, p3, p2, // Back
                p5, p6, p2, p1, // Right
                p7, p6, p5, p4 // Top
            };
            #endregion

            #region Normales
            Vector3 up = Vector3.up;
            Vector3 down = Vector3.down;
            Vector3 front = Vector3.forward;
            Vector3 back = Vector3.back;
            Vector3 left = Vector3.left;
            Vector3 right = Vector3.right;

            Vector3[] normales = new Vector3[]
            {
                down, down, down, down, // Bottom
                left, left, left, left, // Left
                front, front, front, front, // Front
                back, back, back, back, // Back
                right, right, right, right, // Right
                up, up, up, up // Top
            };
            #endregion

            #region UVs
            Vector2 _00 = new Vector2(0f, 0f);
            Vector2 _10 = new Vector2(1f, 0f);
            Vector2 _01 = new Vector2(0f, 1f);
            Vector2 _11 = new Vector2(1f, 1f);

            Vector2[] uvs = new Vector2[]
            {
                _11, _01, _00, _10, // Bottom 
                _11, _01, _00, _10, // Left
                _11, _01, _00, _10, // Front
                _11, _01, _00, _10, // Back
                _11, _01, _00, _10, // Right
                _11, _01, _00, _10, // Top
            };
            #endregion

            #region Triangles
            int[] triangles = new int[]
            {
                3, 1, 0, // Bottom
                3, 2, 1,
                3 + 4 * 1, 1 + 4 * 1, 0 + 4 * 1, // Left
                3 + 4 * 1, 2 + 4 * 1, 1 + 4 * 1,
                3 + 4 * 2, 1 + 4 * 2, 0 + 4 * 2, // Front
                3 + 4 * 2, 2 + 4 * 2, 1 + 4 * 2,
                3 + 4 * 3, 1 + 4 * 3, 0 + 4 * 3, // Back
                3 + 4 * 3, 2 + 4 * 3, 1 + 4 * 3,
                3 + 4 * 4, 1 + 4 * 4, 0 + 4 * 4, // Right
                3 + 4 * 4, 2 + 4 * 4, 1 + 4 * 4,
                3 + 4 * 5, 1 + 4 * 5, 0 + 4 * 5, // Top
                3 + 4 * 5, 2 + 4 * 5, 1 + 4 * 5,
            };
            #endregion

            Mesh mesh = new Mesh();

            mesh.vertices = vertices;
            mesh.normals = normales;
            mesh.uv = uvs;
            mesh.triangles = triangles;

            mesh.RecalculateBounds();
            return mesh;
        }
    }
}

<|start_filename|>Unity3D/Assets/RosSharp/Editor/CustomEditor/JointLimitsManagerEditor.cs<|end_filename|>
﻿/*
© Siemens AG, 2017
Author: Dr. <NAME> (<EMAIL>)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

<http://www.apache.org/licenses/LICENSE-2.0>.

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using UnityEngine;
using UnityEditor;

namespace RosSharp
{
    
    [CustomEditor(typeof(JointLimitsManager))]
    public class JointLimitsManagerEditor : Editor
    {
        private const float toleranceThreshold = 10;

        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();

            JointLimitsManager jointLimitsManager = (JointLimitsManager)target;
            //if (EditorGUILayout.Foldout(true, "Angles"))

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Actual Angle:", jointLimitsManager.AngleActual.ToString());
            EditorGUILayout.LabelField("Actual Rotation No.:", jointLimitsManager.RotationNumberActual.ToString());
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Min Angle:", jointLimitsManager.AngleLimitMin.ToString());
            EditorGUILayout.LabelField("Min. No. of Rotations:", jointLimitsManager.RotationLimitMin.ToString());
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Max Angle:", jointLimitsManager.AngleLimitMax.ToString());
            EditorGUILayout.LabelField("Max. No. of Rotations:", jointLimitsManager.RotationLimitMax.ToString());
            EditorGUILayout.EndHorizontal();

            if (180-jointLimitsManager.AngleLimitMin< toleranceThreshold)
                EditorGUILayout.HelpBox("Min. Angle is close to +180° where this fix will not work properly. Please increase tolerance.", MessageType.Warning);

            if (180 - jointLimitsManager.AngleLimitMin < toleranceThreshold)
                EditorGUILayout.HelpBox("Max. Angle is close to -180° where this fix will not work properly. Please increase tolerance.", MessageType.Warning);

        }
    }
}

<|start_filename|>Unity3D/Assets/RosSharp/Editor/UrdfImporter/UrdfLinkGeometryCylinderExtensions.cs<|end_filename|>
﻿/*
© Siemens AG, 2017
Author: Dr. <NAME> (<EMAIL>)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

<http://www.apache.org/licenses/LICENSE-2.0>.

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using UnityEngine;

namespace RosSharp.UrdfImporter
{
    public static class UrdfLinkGeometryCylinderExtensions
    {
        public static GameObject CreateVisual(this Link.Geometry.Cylinder cylinder, GameObject parent)
        {
            GameObject gameObject = new GameObject("Cylinder");
            gameObject.transform.SetParentAndAlign(parent.transform);

            MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();
            meshFilter.mesh = cylinder.getMesh();
            gameObject.AddComponent<MeshRenderer>();

            return gameObject;
        }

        public static GameObject CreateCollider(this Link.Geometry.Cylinder cylinder, GameObject parent)
        {
            GameObject gameObject = new GameObject("Cylinder");
            gameObject.transform.SetParentAndAlign(parent.transform);

            MeshCollider meshCollider = gameObject.AddComponent<MeshCollider>();
            meshCollider.sharedMesh = cylinder.getMesh();
            meshCollider.convex = true;

            return gameObject;
        }

        private static Mesh getMesh(this Link.Geometry.Cylinder cylinder)
        {
            float height = (float)cylinder.length;
            float bottomRadius = (float)cylinder.radius;
            float topRadius = (float)cylinder.radius;
            int nbSides = 30;
            int nbHeightSeg = 30;

            int nbVerticesCap = nbSides + 1;
            #region Vertices

            // bottom + top + sides
            Vector3[] vertices = new Vector3[nbVerticesCap + nbVerticesCap + nbSides * nbHeightSeg * 2 + 2];
            int vert = 0;
            float _2pi = Mathf.PI * 2f;

            // Bottom cap
            float top = 0.5f * height;
            float bottom = -0.5f * height;
            vertices[vert++] = new Vector3(0f, bottom, 0f);
            while (vert <= nbSides)
            {
                float rad = (float)vert / nbSides * _2pi;
                vertices[vert] = new Vector3(Mathf.Cos(rad) * bottomRadius, bottom, Mathf.Sin(rad) * bottomRadius);
                vert++;
            }

            // Top cap
            vertices[vert++] = new Vector3(0f, top, 0f);
            while (vert <= nbSides * 2 + 1)
            {
                float rad = (float)(vert - nbSides - 1) / nbSides * _2pi;
                vertices[vert] = new Vector3(Mathf.Cos(rad) * topRadius, top, Mathf.Sin(rad) * topRadius);
                vert++;
            }

            // Sides
            int v = 0;
            while (vert <= vertices.Length - 4)
            {
                float rad = (float)v / nbSides * _2pi;
                vertices[vert] = new Vector3(Mathf.Cos(rad) * topRadius, top, Mathf.Sin(rad) * topRadius);
                vertices[vert + 1] = new Vector3(Mathf.Cos(rad) * bottomRadius, bottom, Mathf.Sin(rad) * bottomRadius);
                vert += 2;
                v++;
            }
            vertices[vert] = vertices[nbSides * 2 + 2];
            vertices[vert + 1] = vertices[nbSides * 2 + 3];
            #endregion

            #region Normales

            // bottom + top + sides
            Vector3[] normales = new Vector3[vertices.Length];
            vert = 0;

            // Bottom cap
            while (vert <= nbSides)
            {
                normales[vert++] = Vector3.down;
            }

            // Top cap
            while (vert <= nbSides * 2 + 1)
            {
                normales[vert++] = Vector3.up;
            }

            // Sides
            v = 0;
            while (vert <= vertices.Length - 4)
            {
                float rad = (float)v / nbSides * _2pi;
                float cos = Mathf.Cos(rad);
                float sin = Mathf.Sin(rad);

                normales[vert] = new Vector3(cos, 0f, sin);
                normales[vert + 1] = normales[vert];

                vert += 2;
                v++;
            }
            normales[vert] = normales[nbSides * 2 + 2];
            normales[vert + 1] = normales[nbSides * 2 + 3];
            #endregion

            #region UVs
            Vector2[] uvs = new Vector2[vertices.Length];

            // Bottom cap
            int u = 0;
            uvs[u++] = new Vector2(0.5f, 0.5f);
            while (u <= nbSides)
            {
                float rad = (float)u / nbSides * _2pi;
                uvs[u] = new Vector2(Mathf.Cos(rad) * .5f + .5f, Mathf.Sin(rad) * .5f + .5f);
                u++;
            }

            // Top cap
            uvs[u++] = new Vector2(0.5f, 0.5f);
            while (u <= nbSides * 2 + 1)
            {
                float rad = (float)u / nbSides * _2pi;
                uvs[u] = new Vector2(Mathf.Cos(rad) * .5f + .5f, Mathf.Sin(rad) * .5f + .5f);
                u++;
            }

            // Sides
            int u_sides = 0;
            while (u <= uvs.Length - 4)
            {
                float t = (float)u_sides / nbSides;
                uvs[u] = new Vector3(t, 1f);
                uvs[u + 1] = new Vector3(t, 0f);
                u += 2;
                u_sides++;
            }
            uvs[u] = new Vector2(1f, 1f);
            uvs[u + 1] = new Vector2(1f, 0f);
            #endregion

            #region Triangles
            int nbTriangles = nbSides + nbSides + nbSides * 2;
            int[] triangles = new int[nbTriangles * 3 + 3];

            // Bottom cap
            int tri = 0;
            int i = 0;
            while (tri < nbSides - 1)
            {
                triangles[i] = 0;
                triangles[i + 1] = tri + 1;
                triangles[i + 2] = tri + 2;
                tri++;
                i += 3;
            }
            triangles[i] = 0;
            triangles[i + 1] = tri + 1;
            triangles[i + 2] = 1;
            tri++;
            i += 3;

            // Top cap
            //tri++;
            while (tri < nbSides * 2)
            {
                triangles[i] = tri + 2;
                triangles[i + 1] = tri + 1;
                triangles[i + 2] = nbVerticesCap;
                tri++;
                i += 3;
            }

            triangles[i] = nbVerticesCap + 1;
            triangles[i + 1] = tri + 1;
            triangles[i + 2] = nbVerticesCap;
            tri++;
            i += 3;
            tri++;

            // Sides
            while (tri <= nbTriangles)
            {
                triangles[i] = tri + 2;
                triangles[i + 1] = tri + 1;
                triangles[i + 2] = tri + 0;
                tri++;
                i += 3;

                triangles[i] = tri + 1;
                triangles[i + 1] = tri + 2;
                triangles[i + 2] = tri + 0;
                tri++;
                i += 3;
            }
            #endregion

            Mesh mesh = new Mesh();

            mesh.vertices = vertices;
            mesh.normals = normales;
            mesh.uv = uvs;
            mesh.triangles = triangles;

            mesh.RecalculateBounds();

            return mesh;
        }
    }
}

<|start_filename|>Unity3D/Assets/RosSharp/Editor/UrdfImporter/UrdfOriginExtensions.cs<|end_filename|>
﻿/*
© Siemens AG, 2017
Author: Dr. <NAME> (<EMAIL>)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

<http://www.apache.org/licenses/LICENSE-2.0>.

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using UnityEngine;

namespace RosSharp.UrdfImporter
{
    public static class UrdfOriginExtensions
    {
        public static void SetTransform(this Origin origin, GameObject gameObject)
        {
            gameObject.transform.Translate(origin.GetPosition());
            gameObject.transform.Rotate(origin.GetRotation());
        }
        public static Vector3 GetPosition(this Origin origin)
        {
            if (origin.Xyz != null)
                return new Vector3(
                    (float)-origin.Xyz[1],
                    (float)+origin.Xyz[2],
                    (float)+origin.Xyz[0]);
            else
                return Vector3.zero;
        }
        public static Vector3 GetRotation(this Origin origin)
        {
            if (origin.Rpy != null)
                return new Vector3(
                    (float)+origin.Rpy[1] * Mathf.Rad2Deg,
                    (float)-origin.Rpy[2] * Mathf.Rad2Deg,
                    (float)-origin.Rpy[0] * Mathf.Rad2Deg);
            else
                return Vector3.zero;
        }
    }
}

<|start_filename|>Unity3D/Assets/RosSharp/Editor/UrdfImporter/UrdfLinkGeometryExtensions.cs<|end_filename|>
﻿/*
© Siemens AG, 2017
Author: Dr. <NAME> (<EMAIL>)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

<http://www.apache.org/licenses/LICENSE-2.0>.

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using UnityEngine;

namespace RosSharp.UrdfImporter
{
    public static class UrdfLinkGeometryExtensions
    {
        public static GameObject CreateVisual(this Link.Geometry geometry, GameObject gameObject)
        {
            if (geometry.box != null)
                return geometry.box.CreateVisual(gameObject);
            else if (geometry.cylinder != null)
                return geometry.cylinder.CreateVisual(gameObject);
            else if (geometry.sphere != null)
                return geometry.sphere.CreateVisual(gameObject);
            else if (geometry.mesh != null)
                return geometry.mesh.CreateVisual(gameObject);
            else
                return null;
        }

        public static GameObject CreateCollider(this Link.Geometry geometry, GameObject gameObject)
        {
            if (geometry.box != null)
                return geometry.box.CreateCollider(gameObject);
            else if (geometry.cylinder != null)
                return geometry.cylinder.CreateCollider(gameObject);
            else if (geometry.sphere != null)
                return geometry.sphere.CreateCollider(gameObject);
            else if (geometry.mesh != null)
                return geometry.mesh.CreateCollider(gameObject);
            else
                return null;
        }
    }
}

<|start_filename|>Unity3D/Assets/RosSharp/Editor/UrdfImporter/UrdfAssetDatabase.cs<|end_filename|>
﻿/*
© Siemens AG, 2017
Author: Dr. <NAME> (<EMAIL>)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

<http://www.apache.org/licenses/LICENSE-2.0>.

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using System.IO;
using UnityEngine;
using UnityEditor;

namespace RosSharp.UrdfImporter
{
    public static class UrdfAssetDatabase
    {
        private const string defaultMaterialName = "Default";
        private const string materialFolderName = "Materials";
        private static string assetPath;

        public static void Initialize(Robot robot)
        {
            assetPath = GetAssetPath(robot.filename);

            if (!AssetDatabase.IsValidFolder(Path.Combine(assetPath, materialFolderName)))
                AssetDatabase.CreateFolder(assetPath, materialFolderName);

            createDefaultMaterialAsset();
            foreach (Link.Visual.Material material in robot.materials)
                createMaterialAsset(material);
        }

        #region SetAssetPath
        public static string GetAssetPath(this string urdfFile)
        {
            string absolutePath = Path.GetDirectoryName(urdfFile);
            string absolutePathUnityFormat = absolutePath.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
            if (absolutePathUnityFormat.StartsWith(Application.dataPath))
            {
                string assetPath = "Assets" + absolutePath.Substring(Application.dataPath.Length);
                return assetPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
            }
            return null;
        }
        #endregion

        #region GetAssetPath
        public static string GetAssetPathFromPackagePath(string packagePath)
        {
            string path = packagePath.Substring(10).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);

            if (path.Substring(path.Length - 3, 3).ToLowerInvariant() == "stl")
                path = path.Substring(0, path.Length - 3) + "prefab";

            return Path.Combine(assetPath, path);
        }

        private static string getMaterialAssetPath(string materialName)
        {
            string path = Path.Combine(materialFolderName, Path.GetFileName(materialName) + ".mat");
            return Path.Combine(assetPath,path);
        }
        #endregion

        #region CreateMaterialAssets
        private static Material initializeMaterial()        {
            Material material = new Material(Shader.Find("Standard"));
            material.SetFloat("_Metallic", 0.75f);
            material.SetFloat("_Glossiness", 0.75f);
            return material;
        }

        private static Material createMaterialAsset(this Link.Visual.Material urdfMaterial)
        {
            Material material = initializeMaterial();

            if (urdfMaterial.color != null)
                material.color = urdfMaterial.color.CreateColor();
            else if (urdfMaterial.texture != null)
                material.mainTexture = LoadTexture(urdfMaterial.texture.filename);

            AssetDatabase.CreateAsset(material, getMaterialAssetPath(urdfMaterial.name));
            return material;
        }

        private static Texture LoadTexture(string filename)
        {
            string path = Path.Combine(assetPath, filename).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
            if (path == null)
                return null;
            return AssetDatabase.LoadAssetAtPath<Texture>(path);
        }

        private static Material createDefaultMaterialAsset()
        {
            Material material = initializeMaterial();
            material.color = new Color(0.33f, 0.33f, 0.33f, 0.0f);

            AssetDatabase.CreateAsset(material, getMaterialAssetPath(defaultMaterialName));
            return material;
        }
        #endregion CreateMaterialAssets

        #region SetMaterial
        public static void SetMaterial(GameObject gameObject, string materialName)
        {
            Material material = AssetDatabase.LoadAssetAtPath<Material>(getMaterialAssetPath(materialName));
            Renderer[] renderers = gameObject.GetComponentsInChildren<Renderer>();
            foreach (Renderer renderer in renderers)
                renderer.sharedMaterial = material;
        }

        public static void SetDefaultMaterial(GameObject gameObject)
        {
            SetMaterial(gameObject, defaultMaterialName);
        }
        #endregion

    }
}
