Ejemplo n.º 1
0
        public override void Module_Start(XFur_System owner)
        {
            systemOwner = owner;
            if (!fxTexture0)
            {
                fxTexture0            = systemOwner.XFur_CreateVertexData("FUR_VERTICES");
                fxTexture0.filterMode = FilterMode.Point;
                fxTexture0.wrapMode   = TextureWrapMode.Clamp;
                cols = new Color[fxTexture0.width * fxTexture0.height];
                mesh = new Mesh();

                if (systemOwner.GetComponent <SkinnedMeshRenderer>())
                {
                    systemOwner.GetComponent <SkinnedMeshRenderer>().BakeMesh(mesh);
                }

                norms = systemOwner.GetComponent <SkinnedMeshRenderer>()?mesh.normals:systemOwner.Mesh.normals;

                if (systemOwner.manualMeshIndex < 0)
                {
                    fVert = systemOwner.database.meshData[systemOwner.database.XFur_ContainsMeshData(systemOwner.OriginalMesh)].furVertices;
                }
                else
                {
                    fVert = systemOwner.database.meshData[systemOwner.database.XFur_ContainsMeshData(systemOwner.manualMeshIndex)].furVertices;
                }
            }

            timerFX = Time.timeSinceLevelLoad;
            systemOwner.XFur_UpdateFurMaterials();
        }
Ejemplo n.º 2
0
        public override void Module_Start(XFur_System owner)
        {
            systemOwner = owner;

            if (!systemOwner || !systemOwner.database)
            {
                return;
            }

            if (coatingSettings.Length != systemOwner.materialProfiles.Length)
            {
                coatingSettings = new XFur_CoatingSettings[systemOwner.materialProfiles.Length];
                for (int i = 0; i < coatingSettings.Length; i++)
                {
                    coatingSettings[i] = new XFur_CoatingSettings();
                    systemOwner.materialProfiles[i].CopyTo(ref coatingSettings[i].originalP);
                }
            }

            for (int i = 0; i < coatingSettings.Length; i++)
            {
                if (coatingSettings[i].originalP == null)
                {
                    coatingSettings[i].originalP = new XFur_MaterialProperties();
                }
                systemOwner.materialProfiles[i].CopyTo(ref coatingSettings[i].originalP);
                coatingSettings[i].originalP.originalMat = systemOwner.materialProfiles[i].originalMat;
            }


            if (Application.isPlaying && State == XFurModuleState.Enabled)
            {
                RandomizeFur();
            }
        }
Ejemplo n.º 3
0
        public override void Module_UI(XFur_System owner)
        {
            base.Module_UI(owner);

            if (State == XFurModuleState.Enabled)
            {
                lodMode     = (XFur_LODMode)UpperCaseEnumField(new GUIContent("LOD MODE", "The way the lod of this object will be managed and calculated. Quality switches to lower sample counts at a further distance (around 70% of the max distance) while Performance mode uses lower sample counts unless in a heavy close up (around 10-20% of the max. distance)"), lodMode);
                maxDistance = SliderField(new GUIContent("MAX. DISTANCE", "As the character approaches the max distance it will start reducing the amount of samples of the fur and to use simpler algorithms for physics, effects, etc."), maxDistance, 0.01f, 250.0f);
            }
        }
Ejemplo n.º 4
0
        public override void Module_Start(XFur_System owner)
        {
            systemOwner = owner;


            for (int i = 0; i < owner.materialProfiles.Length; i++)
            {
                furRenders[i] = (int)owner.materialProfiles[i].fullShadowLayers;
            }
        }
Ejemplo n.º 5
0
        public override void Module_UI(XFur_System owner)
        {
            base.Module_UI(owner);
            GUILayout.Space(8);

            if (State == XFurModuleState.Enabled)
            {
                for (int i = 0; i < coatingSettings.Length; i++)
                {
                    systemOwner.CopyFurProperties(systemOwner.materialProfiles[i], ref coatingSettings[i].originalP);

                    if (systemOwner.materialProfiles[i].furmatType == 2)
                    {
                        SmallGroup(coatingSettings[i].originalP.originalMat.name);

                        GUILayout.Space(8);
                        randomizeAllParameters = EnableDisableToggle(new GUIContent("RANDOMIZED PARAMETERSN", "Picks two randomly selected profiles from the profiles list and randomly lerps each fur parameter between them to produce more varied results"), randomizeAllParameters);
                        GUILayout.Space(8);

                        for (int c = 0; c < coatingSettings[i].coatingProfiles.Length; c++)
                        {
                            GUILayout.BeginHorizontal();
                            coatingSettings[i].coatingProfiles[c] = ObjectField <XFur_CoatingProfile>(new GUIContent("FUR PROFILE " + c, "The fur profile to use as a random option for this module"), coatingSettings[i].coatingProfiles[c], false);

                            if (StandardButton("REMOVE", 100))
                            {
                                var l = new List <XFur_CoatingProfile>(coatingSettings[i].coatingProfiles);
                                l.RemoveAt(c);
                                coatingSettings[i].coatingProfiles = l.ToArray();
                            }
                            GUILayout.Space(8); GUILayout.EndHorizontal();
                        }

                        GUILayout.Space(8);

                        if (CenteredButton("ADD NEW PROFILE", 200))
                        {
                            var l = new List <XFur_CoatingProfile>(coatingSettings[i].coatingProfiles);
                            l.Add(null);
                            coatingSettings[i].coatingProfiles = l.ToArray();
                        }


                        EndSmallGroup();

                        GUILayout.Space(12);
                    }
                }
            }
        }
        void OnEnable()
        {
            mTarget = (XFur_System)target;

            if (!Application.isPlaying)
            {
                mTarget.XFur_Start();
            }
            if (folds == null || folds.Length < 12 + (mTarget.customModules == null?0:mTarget.customModules.Length))
            {
                folds = new AnimBool[12 + (mTarget.customModules == null?0:mTarget.customModules.Length)];
                for (int i = 0; i < folds.Length; i++)
                {
                    folds[i] = new AnimBool();
                    folds[i].valueChanged.AddListener(Repaint);
                }
            }

            if (!pidiSkin)
            {
                PDEditor_GetCustomGUI(  );
            }

            if (mTarget.coatingModule != null)
            {
                mTarget.coatingModule.Module_StartUI(pidiSkin);
            }


            if (mTarget.lodModule != null)
            {
                mTarget.lodModule.Module_StartUI(pidiSkin);
            }


            if (mTarget.physicsModule != null)
            {
                mTarget.physicsModule.Module_StartUI(pidiSkin);
            }


            if (mTarget.fxModule != null)
            {
                mTarget.fxModule.Module_StartUI(pidiSkin);
            }
        }
Ejemplo n.º 7
0
        public override void Module_Start(XFur_System owner)
        {
            systemOwner      = owner;
            buffPositions[0] = systemOwner.transform.position;
            buffRotations[0] = systemOwner.transform.rotation;

            if (systemOwner.GetComponent <SkinnedMeshRenderer>())
            {
                bones = systemOwner.GetComponent <SkinnedMeshRenderer>().bones;

                for (int i = 0; i < bones.Length; i++)
                {
                    buffPositions[i] = bones[i].position;
                    buffRotations[i] = bones[i].rotation;
                }
            }
        }
Ejemplo n.º 8
0
        public override void Module_Start(XFur_System owner)
        {
            systemOwner      = owner;
            buffPositions[0] = systemOwner.transform.position;
            buffRotations[0] = systemOwner.transform.rotation;

            if (systemOwner.GetComponent <SkinnedMeshRenderer>() && ((bones == null || bones.Length == 0) || autoDetectBones))
            {
                var bonesList = new List <Transform>(systemOwner.GetComponent <SkinnedMeshRenderer>().bones);

                bones = new Transform[Mathf.Min(bonesList.Count, 128)];

                for (int i = 0; i < bones.Length; i++)
                {
                    bones[i]         = bonesList[i];
                    buffPositions[i] = bones[i].position;
                    buffRotations[i] = bones[i].rotation;
                }
            }
        }
Ejemplo n.º 9
0
        // Use this for initialization
        IEnumerator Start()
        {
            yield return(new WaitForSeconds(1.0f));

            target = GameObject.FindObjectOfType <XFur_System>();
            if (target)
            {
                transform.forward = -target.transform.root.forward;
                orbitX            = transform.eulerAngles.y;
                origin            = target.transform.position;
                distance          = target.GetComponent <Renderer>().bounds.extents.magnitude + 1;


                if (!target.GetComponent <MeshCollider>())
                {
                    var tMesh = new Mesh();

                    if (target.GetComponent <SkinnedMeshRenderer>())
                    {
                        target.GetComponent <SkinnedMeshRenderer>().BakeMesh(tMesh);
                    }

                    target.gameObject.AddComponent <MeshCollider>();

                    target.GetComponent <MeshCollider>().sharedMesh = target.GetComponent <SkinnedMeshRenderer>()?tMesh:target.Mesh;
                }

                perMaterialData = new XFurPainter_PainterData[target.materialProfiles.Length];

                for (int i = 0; i < perMaterialData.Length; i++)
                {
                    if (target.materialProfiles[i].furmatType == 2)
                    {
                        PrepareMaterial(i);
                    }
                }
            }

            ready = true;
            yield break;
        }
Ejemplo n.º 10
0
        public override void Module_Start(XFur_System owner)
        {
            systemOwner = owner;
            if (Application.isPlaying && !fxTexture0)
            {
                fxTexture0            = systemOwner.XFur_CreateVertexData("FUR_VERTICES");
                fxTexture0.filterMode = FilterMode.Point;
                fxTexture0.wrapMode   = TextureWrapMode.Clamp;
                cols = fxTexture0.GetPixels();
                mesh = new Mesh();

                if (systemOwner.GetComponent <SkinnedMeshRenderer>())
                {
                    systemOwner.GetComponent <SkinnedMeshRenderer>().BakeMesh(mesh);
                }

                norms = systemOwner.GetComponent <SkinnedMeshRenderer>()?mesh.normals:systemOwner.Mesh.normals;

                fVert = systemOwner.database.meshData[systemOwner.database.XFur_ContainsMeshData(systemOwner.OriginalMesh)].furVertices;
            }

            timerFX = Time.timeSinceLevelLoad;
            systemOwner.XFur_UpdateFurMaterials();
        }
Ejemplo n.º 11
0
 public virtual void Module_Start(XFur_System owner)
 {
     systemOwner = owner;
 }
Ejemplo n.º 12
0
        public override void Module_UI(XFur_System owner)
        {
            //Undo.RecordObject(this,moduleName+"_"+GetInstanceID());
            base.Module_UI(owner);

            if (Enabled)
            {
                GUILayout.Space(16);

                affectedByLOD = EnableDisableToggle(new GUIContent("LOD INFLUENCED MODE", "If enabled, this module's functionality will be affected by the LOD module. At further distances, the functionality of this module will be adjusted for better performance"), affectedByLOD);
                GUILayout.Space(4);
                autoFixMeshTransform = EnableDisableToggle(new GUIContent("TRANSFORM AUTO-FIX", "Automatically Fix transform issues on your mesh (rotation is not 0,0,0. Fixes most cases of snow accumulating on wrong places/directions but it has a performance cost. It is recommended to fix the rotation on your modelling app and just use this option if you cannot modify the original mesh"), autoFixMeshTransform);
                forceUpdateNormals   = EnableDisableToggle(new GUIContent("DYNAMIC NORMALS UPDATE", "If enabled, the normals of the mesh are updated as it moves (on animated characters) to calculate the snow/rain coverage in a much more accurate way. Impacts performance"), forceUpdateNormals);
                GUILayout.Space(4);
                localWindStrength = SliderField(new GUIContent("LOCAL WIND STRENGTH", "A local multiplier for the global wind strength"), localWindStrength, 0.0f, 64.0f);
                maxIterations     = IntSliderField(new GUIContent("MAX. ITERATIONS", "Maximum amount of updates per second that the module makes to the effects before sending them to the mesh. Impacts performance"), maxIterations, 1, 10);
                vertexBuffer      = IntSliderField(new GUIContent("VERTICES BUFFER", "Maximum amount of vertex operations per frame that the module will perform. Lower values give better performance but reduce the smoothness of the effects' fading and melting"), vertexBuffer, 32, 2048);

                GUILayout.Space(16);

                SmallGroup("BLOOD FX SETTINGS");

                if (bloodSettings.fxMode != 0)
                {
                    bloodSettings.fxMode = 3;
                }

                bloodSettings.fxMode = PopupField(new GUIContent("BLOOD MODE", "The mode in which this effect will be calculated and applied"), bloodSettings.fxMode, new GUIContent[] { new GUIContent("Disabled"), new GUIContent("Global & On Demand", "Blood is added through both a global direction for the whole scene and upon demand by specific objects/function calls"), new GUIContent("Global Direction", "The blood comes from a global direction and is applied to every fur system that has it enabled"), new GUIContent("On Demand", "The blood is only applied by specific objects upon contact / function call") });

                if (bloodSettings.fxMode > 0)
                {
                    GUILayout.Space(8);

                    bloodSettings.fxColor        = ColorField(new GUIContent("FX COLOR"), bloodSettings.fxColor);
                    bloodSettings.normalFalloff  = SliderField(new GUIContent("EFFECT FALLOFF", "How will the blood effect falloff on the slopes of the model?"), bloodSettings.normalFalloff, 0.15f, 0.9f);
                    bloodSettings.vanishOverTime = EnableDisableToggle(new GUIContent("FADE OVER TIME", "Should the blood dry and fade over a certain period of time?"), bloodSettings.vanishOverTime);

                    GUILayout.Space(8);
                    if (bloodSettings.vanishOverTime)
                    {
                        bloodSettings.vanishingTime = FloatField(new GUIContent("FADING TIME (SECS)", "The amount of time it takes for the blood to dry and fade"), bloodSettings.vanishingTime);
                    }

                    bloodSettings.furPenetration = SliderField(new GUIContent("FX FUR PENETRATION", "How much the effect will penetrate the fur, from tips to roots"), bloodSettings.furPenetration, 0.0f, 1.0f);
                    bloodSettings.fxSpecSmooth   = ColorField(new GUIContent("FX SPEC/SMOOTHNESS", "The specular RGB and smoothness modifier of this effect"), bloodSettings.fxSpecSmooth);
                }
                GUILayout.Space(8);
                EndSmallGroup();

                GUILayout.Space(16);

                SmallGroup("SNOW FX SETTINGS");

                snowSettings.fxMode = PopupField(new GUIContent("SNOW MODE", "The mode in which this effect will be calculated and applied"), snowSettings.fxMode, new GUIContent[] { new GUIContent("Disabled"), new GUIContent("Global & On Demand", "Snow is added through both a global direction for the whole scene and upon demand by specific objects/function calls"), new GUIContent("Global Direction", "The snow comes from a global direction and is applied to every fur system that has it enabled"), new GUIContent("On Demand", "The snow is only applied by specific objects upon contact / function call") });

                if (snowSettings.fxMode > 0)
                {
                    GUILayout.Space(8);
                    snowSettings.fxColor        = ColorField(new GUIContent("FX COLOR"), snowSettings.fxColor);
                    snowSettings.normalFalloff  = SliderField(new GUIContent("EFFECT FALLOFF", "How will the snow effect falloff on the slopes of the model?"), snowSettings.normalFalloff, 0.15f, 0.9f);
                    snowSettings.vanishOverTime = EnableDisableToggle(new GUIContent("FADE OVER TIME", "Should the snow melt over a certain period of time?"), snowSettings.vanishOverTime);
                    GUILayout.Space(8);

                    if (snowSettings.vanishOverTime)
                    {
                        snowSettings.vanishingTime = FloatField(new GUIContent("MELTING TIME (SECS)", "The amount of time it takes for the snow to melt"), snowSettings.vanishingTime);
                    }
                    snowSettings.furPenetration = SliderField(new GUIContent("FX FUR PENETRATION", "How much the effect will penetrate the fur, from tips to roots"), snowSettings.furPenetration, 0.0f, 1.0f);
                    snowSettings.fxSpecSmooth   = ColorField(new GUIContent("FX SPEC/SMOOTHNESS", "The specular RGB and smoothness modifier of this effect"), snowSettings.fxSpecSmooth);
                    GUILayout.Space(8);
                }

                EndSmallGroup();

                GUILayout.Space(12);

                SmallGroup("WATER FX SETTINGS");

                waterSettings.fxMode = PopupField(new GUIContent("WATER MODE", "The mode in which this effect will be calculated and applied"), waterSettings.fxMode, new GUIContent[] { new GUIContent("Disabled"), new GUIContent("Global & On Demand", "Snow is added through both a global direction for the whole scene and upon demand by specific objects/function calls"), new GUIContent("Global Direction", "The water comes from a global direction and is applied to every fur system that has it enabled"), new GUIContent("On Demand", "The water is only applied by specific objects upon contact / function call") });

                if (waterSettings.fxMode > 0)
                {
                    GUILayout.Space(8);
                    waterSettings.fxColor        = ColorField(new GUIContent("FX Color"), waterSettings.fxColor);
                    waterSettings.normalFalloff  = SliderField(new GUIContent("EFFECT FALLOFF", "How will the water effect falloff on the slopes of the model?"), waterSettings.normalFalloff, 0.15f, 0.9f);
                    waterSettings.vanishOverTime = EnableDisableToggle(new GUIContent("FADE OVER TIME", "Should the water dry off over a certain period of time?"), waterSettings.vanishOverTime);

                    GUILayout.Space(8);

                    if (waterSettings.vanishOverTime)
                    {
                        waterSettings.vanishingTime = FloatField(new GUIContent("MELTING TIME (SECS)", "The amount of time it takes for the snow to melt"), waterSettings.vanishingTime);
                    }
                    waterSettings.furPenetration = SliderField(new GUIContent("FX FUR PENETRATION", "How much the effect will penetrate the fur, from tips to roots"), waterSettings.furPenetration, 0.0f, 1.0f);
                    waterSettings.fxSpecSmooth   = ColorField(new GUIContent("FX SPEC/SMOOTHNESS", "The specular RGB and smoothness modifier of this effect"), waterSettings.fxSpecSmooth);
                    GUILayout.Space(8);
                }
                GUILayout.Space(8);
                EndSmallGroup();

                GUILayout.Space(12);
            }

            GUILayout.Space(12);
        }
 public override void Module_Start(XFur_System owner)
 {
     systemOwner = owner;
 }
Ejemplo n.º 14
0
        public override void OnInspectorGUI()
        {
            xFur = (XFur_System)target;



            if (xFur.coatingModule != null)
            {
                xFur.coatingModule.Module_StartUI(pidiSkin2);
            }


            if (xFur.lodModule != null)
            {
                xFur.lodModule.Module_StartUI(pidiSkin2);
            }


            if (xFur.physicsModule != null)
            {
                xFur.physicsModule.Module_StartUI(pidiSkin2);
            }


            if (xFur.fxModule != null)
            {
                xFur.fxModule.Module_StartUI(pidiSkin2);
            }

            Undo.RecordObject(xFur, "XFUR_" + xFur.GetInstanceID());



            var tSkin = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector);

            GUI.skin = pidiSkin;



            var buffDatabase = xFur.database;

            GUILayout.BeginHorizontal(); GUILayout.BeginVertical(pidiSkin2.box);
            AssetLogoAndVersion();
            GUILayout.Space(8);
            GUILayout.BeginHorizontal(); GUILayout.Space(12); GUILayout.BeginVertical();
            xFur.database = ObjectField <XFur_DatabaseModule>(new GUIContent("XFUR DATABASE ASSET", "The XFur Database asset, required for LOD management, mesh handling and most other internal features"), xFur.database, false);
            GUILayout.Space(8);

            if (buffDatabase != xFur.database && xFur.database != null)
            {
                xFur.XFur_UpdateMeshData();
                xFur.XFur_Start();
            }

            var tempTarget = xFur.manualMeshIndex;

            xFur.manualMeshIndex = EnableDisableToggle(new GUIContent("EXPLICIT MODEL INDEX", "Use an explicit index on the database to get the mesh data from instead of automatically linking XFur to the database through Mesh ID. In most cases, you should leave this toggle disabled"), xFur.manualMeshIndex != -1)?Mathf.Max(xFur.manualMeshIndex, 0):-1;

            if (xFur.manualMeshIndex != -1)
            {
                if (xFur.database.meshData.Length < 1)
                {
                    xFur.manualMeshIndex = -1;
                }
                xFur.manualMeshIndex = PopupField(new GUIContent("EXPLICIT DATABASE INDEX"), xFur.manualMeshIndex, xFur.database.GetMeshNames());
                xFur.manualMeshIndex = Mathf.Clamp(xFur.manualMeshIndex, 0, xFur.database.meshData.Length - 1);
            }

            if (tempTarget != xFur.manualMeshIndex)
            {
                xFur.XFur_UpdateMeshData();
            }

            if (!xFur.database)
            {
                GUILayout.BeginHorizontal(); GUILayout.Space(12);
                EditorGUILayout.HelpBox("Please assign the XFur Database Asset to this component. It is required for internal functions and its absence can make this software unstable", MessageType.Error);
                GUILayout.Space(12); GUILayout.EndHorizontal();
                GUILayout.Space(8);

                GUILayout.EndVertical(); GUILayout.Space(12);
                GUILayout.EndHorizontal();
            }
            else
            {
                if (xFur.database.XFur_ContainsMeshData(xFur.OriginalMesh) != -1)
                {
                    if (xFur.database.meshData[xFur.database.XFur_ContainsMeshData(xFur.OriginalMesh)].XFurVersion != xFur.Version)
                    {
                        GUILayout.BeginHorizontal(); GUILayout.Space(12);
                        EditorGUILayout.HelpBox("The current XFur version you are using does not match the version of the data stored in the database asset. You need to rebuild this data", MessageType.Error);
                        GUILayout.Space(12); GUILayout.EndHorizontal();
                        GUILayout.Space(8);

                        if (CenteredButton("REBUILD DATA", 200))
                        {
                            xFur.database.XFur_DeleteMeshData(xFur.database.XFur_ContainsMeshData(xFur.OriginalMesh));
                            xFur.XFur_UpdateMeshData();
                        }

                        GUILayout.Space(8);
                    }
                    else
                    {
                        GUILayout.Space(8);
                        if (CenteredButton("REBUILD DATA", 200))
                        {
                            xFur.database.XFur_DeleteMeshData(xFur.database.XFur_ContainsMeshData(xFur.OriginalMesh));
                            xFur.XFur_UpdateMeshData();
                        }

                        GUILayout.Space(8);
                    }
                }

                GUILayout.EndVertical(); GUILayout.Space(12);
                GUILayout.EndHorizontal();

                if (BeginCenteredGroup("XFUR - MAIN SETTINGS", ref xFur.folds[0]))
                {
                    GUILayout.Space(16);

                    xFur.updateDynamically = EnableDisableToggle(new GUIContent("DYNAMIC UPDATES", "Enable this if you plan on making dynamic changes to the fur at runtime. If you are using the FX or Physics module, disable it for better performance."), xFur.updateDynamically);

                    xFur.materialProfileIndex = PopupField(new GUIContent("MATERIAL SLOT", "The material we are currently editing"), xFur.materialProfileIndex, xFur.FurMatGUIS);

                    GUILayout.Space(8);
                    xFur.materialProfiles[xFur.materialProfileIndex].originalMat = ObjectField <Material>(new GUIContent("BASE FUR MATERIAL", "The fur material that will be used as a reference by this instance"), xFur.materialProfiles[xFur.materialProfileIndex].originalMat, false);
                    GUILayout.Space(8);

                    if (xFur.materialProfiles[xFur.materialProfileIndex].buffOriginalMat != xFur.materialProfiles[xFur.materialProfileIndex].originalMat || xFur.GetComponent <Renderer>().sharedMaterials[xFur.materialProfileIndex] == null || !xFur.GetComponent <Renderer>().sharedMaterials[xFur.materialProfileIndex].name.Contains(xFur.materialProfiles[xFur.materialProfileIndex].originalMat.name) || !xFur.GetComponent <Renderer>().sharedMaterials[xFur.materialProfileIndex].shader.name.Contains("XFUR"))
                    {
                        xFur.UpdateSharedData(xFur.materialProfiles[xFur.materialProfileIndex]);
                        xFur.materialProfiles[xFur.materialProfileIndex].SynchToOriginalMat();
                        xFur.XFur_UpdateMeshData();
                    }

                    GUILayout.Space(4);
                    if (xFur.materialProfiles[xFur.materialProfileIndex].originalMat && xFur.materialProfiles[xFur.materialProfileIndex].furmatType == 2)
                    {
                        if ((!Application.isPlaying || !xFur.instancedMode) && xFur.materialProfiles[xFur.materialProfileIndex].furmatShadowsMode == 0)
                        {
                            if (XFur_System.materialReferences.ContainsKey(xFur.materialProfiles[xFur.materialProfileIndex].originalMat))
                            {
                                var samples = new List <GUIContent>();


                                for (int i = 0; i < xFur.database.highQualityShaders.Length; i++)
                                {
                                    var shaderName = XFur_System.materialReferences[xFur.materialProfiles[xFur.materialProfileIndex].originalMat][i].shader.name.ToUpper();
                                    samples.Add(new GUIContent(shaderName.Split("/"[0])[shaderName.Split("/"[0]).Length - 1]));
                                }

                                if (xFur.lodModule.State == XFurModuleState.Enabled)
                                {
                                    samples.Clear();
                                    samples.Add(new GUIContent("LOD DRIVEN"));
                                    var n = 0;
                                    n = PopupField(new GUIContent("FUR SAMPLES", "The amount of samples to use on this shader"), n, new GUIContent[] { new GUIContent("LOD Driven") });

                                    if (!Application.isPlaying)
                                    {
                                        xFur.materialProfiles[xFur.materialProfileIndex].furmatSamples = 2;
                                    }
                                }
                                else
                                {
                                    xFur.materialProfiles[xFur.materialProfileIndex].furmatSamples = PopupField(new GUIContent("FUR SAMPLES", "The amount of samples to use on this shader"), xFur.materialProfiles[xFur.materialProfileIndex].furmatSamples, samples.ToArray());
                                }
                            }
                        }
                        else
                        {
                            if ((xFur.lodModule == null || (xFur.lodModule != null && xFur.lodModule.State != XFurModuleState.Enabled)) && xFur.runMaterialReferences.ContainsKey(xFur.materialProfiles[xFur.materialProfileIndex].originalMat))
                            {
                                var samples = new List <GUIContent>();


                                if (xFur.lodModule.State == XFurModuleState.Enabled)
                                {
                                    samples.Clear();
                                    samples.Add(new GUIContent("LOD DRIVEN"));
                                }

                                xFur.materialProfiles[xFur.materialProfileIndex].furmatSamples = PopupField(new GUIContent("FUR SAMPLES", "The amount of samples to use on this shader"), xFur.materialProfiles[xFur.materialProfileIndex].furmatSamples, samples.ToArray());
                            }
                            else
                            {
                                var n = 0;
                                n = PopupField(new GUIContent("FUR SAMPLES", "The amount of samples to use on this shader"), n, new GUIContent[] { new GUIContent("LOD Driven") });
                            }
                        }

                        var s = xFur.materialProfiles[xFur.materialProfileIndex].furmatShadowsMode;

                        xFur.materialProfiles[xFur.materialProfileIndex].furmatShadowsMode = PopupField(new GUIContent("SHADOWS MODE", "Switches between the different shadow modes for the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatShadowsMode, new GUIContent[] { new GUIContent("STANDARD SHADOWS", "Simple shadow casting on forward and deferred with full shadow reception enabled only for deferred rendering"), new GUIContent("(BETA) FULL SHADOWS", "Expensive method of full shadowing in forward and deferred that adds accurate shadows in casting and receiving mode based on each fur strand and layer") });

                        if (s == 1)
                        {
                            GUILayout.BeginHorizontal(); GUILayout.Space(12);
                            EditorGUILayout.HelpBox("Full shadows generate additional geometry and sub renderers, making it VERY expensive to compute. DO NOT use them on scenes with more than a couple characters nor in models with more than 6-10k polygons", MessageType.Warning);
                            GUILayout.Space(12); GUILayout.EndHorizontal();
                            GUILayout.Space(8);

                            var tempF = (int)xFur.materialProfiles[xFur.materialProfileIndex].fullShadowLayers;
                            tempF = IntSliderField(new GUIContent("FUR SAMPLES"), tempF, 6, 32);
                            xFur.materialProfiles[xFur.materialProfileIndex].fullShadowLayers = tempF;
                        }

                        if (s != xFur.materialProfiles[xFur.materialProfileIndex].furmatShadowsMode && xFur.materialProfiles[xFur.materialProfileIndex].furmatShadowsMode == 1)
                        {
                            xFur.XFur_GenerateShadowMesh(xFur.materialProfiles[xFur.materialProfileIndex]);
                        }


                        if (xFur.FurMaterials == 1
#if UNITY_2018_1_OR_NEWER
                            || true
#endif
                            )
                        {
                            GUILayout.Space(8);

                            //EnableDisableToggle( new GUIContent("Static Material", "If this fur material will not change its length, thickness, color, etc. at runtime it is recommended to toggle this value to handle the material as a static instance for better performance" ), ref xFur.instancedMode );
                            xFur.materialProfiles[xFur.materialProfileIndex].furmatCollision        = EnableDisableToggle(new GUIContent("BASIC SELF-COLLISION", "Performs a basic self-collision algorithm on the shader to avoid (with a low precision) the fur from going inside the mesh"), xFur.materialProfiles[xFur.materialProfileIndex].furmatCollision == 1) ? 1 : 0;
                            xFur.materialProfiles[xFur.materialProfileIndex].furmatRenderSkin       = EnableDisableToggle(new GUIContent("BASE SKIN PASS", "Render the skin layer under the fur for this material"), xFur.materialProfiles[xFur.materialProfileIndex].furmatRenderSkin == 1) ? 1 : 0;
                            xFur.materialProfiles[xFur.materialProfileIndex].furmatTriplanar        = EnableDisableToggle(new GUIContent("TRIPLANAR MODE", "Render fur using triplanar coordinates generated at runtime instead of the secondary UV channel of this mesh"), xFur.materialProfiles[xFur.materialProfileIndex].furmatTriplanar == 1) ? 1 : 0;
                            xFur.materialProfiles[xFur.materialProfileIndex].furmatForceUV2Grooming = EnableDisableToggle(new GUIContent("GROOM MAP ON UV2", "Forces triplanar coordinates to be used for fur projection, using the secondary UV map as coordinates for grooming instead"), xFur.materialProfiles[xFur.materialProfileIndex].furmatForceUV2Grooming == 1) ? 1 : 0;

                            if (xFur.materialProfiles[xFur.materialProfileIndex].furmatForceUV2Grooming == 1)
                            {
                                xFur.materialProfiles[xFur.materialProfileIndex].furmatTriplanar = 1;
                            }

                            GUILayout.Space(8);

                            if (xFur.materialProfiles[xFur.materialProfileIndex].furmatTriplanar == 1)
                            {
                                xFur.materialProfiles[xFur.materialProfileIndex].furmatTriplanarScale = SliderField(new GUIContent("TRIPLANAR SCALE", "The scale used for the triplanar projection of the fur, multiplied by the fur UV1 and UV2 channels' sizes"), xFur.materialProfiles[xFur.materialProfileIndex].furmatTriplanarScale, 0.0f, 1.0f);
                            }


                            GUILayout.Space(8);

                            xFur.materialProfiles[xFur.materialProfileIndex].furmatReadBaseSkin = PopupField(new GUIContent("BASE SKIN MODE", "The mode in which the skin color and specularity are controlled for this instance"), xFur.materialProfiles[xFur.materialProfileIndex].furmatReadBaseSkin, new GUIContent[] { new GUIContent("FROM MATERIAL"), new GUIContent("FROM INSTANCE") });
                            xFur.materialProfiles[xFur.materialProfileIndex].furmatReadBaseFur  = PopupField(new GUIContent("FUR SETTINGS MODE", "The mode in which the fur parameters are controlled for this instance"), xFur.materialProfiles[xFur.materialProfileIndex].furmatReadBaseFur, new GUIContent[] { new GUIContent("FROM MATERIAL"), new GUIContent("FROM INSTANCE") });
                            xFur.materialProfiles[xFur.materialProfileIndex].furmatReadFurNoise = PopupField(new GUIContent("FUR GEN MAP", "The mode in which the fur noise map is controlled for this instance"), xFur.materialProfiles[xFur.materialProfileIndex].furmatReadFurNoise, new GUIContent[] { new GUIContent("FROM MATERIAL"), new GUIContent("FROM INSTANCE") });

                            GUILayout.Space(8);

                            XFur_CoatingProfile t = null;
                            t = ObjectField <XFur_CoatingProfile>(new GUIContent("LOAD FUR PROFILE", "Allows you to assign a pre-made fur profile to easily load existing settings, colors, etc"), t, false);

                            if (t != null)
                            {
                                xFur.LoadXFurProfileAsset(t, xFur.materialProfileIndex);
                            }

                            GUILayout.Space(16);
                            if (CenteredButton("EXPORT FUR SETTINGS", 200))
                            {
                                var k = xFur.XFur_ExportMaterialProfile(xFur.materialProfiles[xFur.materialProfileIndex]);
                                if (k)
                                {
                                    var path = EditorUtility.SaveFilePanelInProject("Save Fur Profile", "New Fur Profile", "asset", "");
                                    AssetDatabase.CreateAsset(k, path);
                                    AssetDatabase.SaveAssets();
                                    AssetDatabase.Refresh();
                                }
                            }
                            GUILayout.Space(16);

                            if (xFur.materialProfiles[xFur.materialProfileIndex].furmatReadBaseSkin != 0)
                            {
                                GUILayout.Space(4);
                                SmallGroup("BASE SKIN");
                                xFur.materialProfiles[xFur.materialProfileIndex].furmatBaseColor = ColorField(new GUIContent("MAIN COLOR", "Final tint to be applied to the skin under the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatBaseColor);

                                if (!xFur.materialProfiles[xFur.materialProfileIndex].furmatGlossSpecular)
                                {
                                    xFur.materialProfiles[xFur.materialProfileIndex].furmatSpecular = ColorField(new GUIContent("SPECULAR COLOR", "Specular color to be applied to the skin under the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatSpecular);
                                }

                                xFur.materialProfiles[xFur.materialProfileIndex].furmatBaseTex = ObjectField <Texture2D>(new GUIContent("MAIN TEXTURE", "Texture to be applied to the mesh under the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatBaseTex, false);

                                xFur.materialProfiles[xFur.materialProfileIndex].furmatGlossSpecular = ObjectField <Texture2D>(new GUIContent("SPECULAR MAP", "Base Specular (RGB) and Smoothness (A) map to be used under the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatGlossSpecular, false);
                                GUILayout.Space(4);

                                if (!xFur.materialProfiles[xFur.materialProfileIndex].furmatGlossSpecular)
                                {
                                    xFur.materialProfiles[xFur.materialProfileIndex].furmatSmoothness = SliderField(new GUIContent("SMOOTHNESS", "Smoothness to be applied to the skin under the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatSmoothness, 0.0f, 1.0f);
                                }

                                GUILayout.Space(4);

                                xFur.materialProfiles[xFur.materialProfileIndex].furmatNormalmap = ObjectField <Texture2D>(new GUIContent("NORMALMAP", "The normalmap to be applied to the skin under the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatNormalmap, false);
                                xFur.materialProfiles[xFur.materialProfileIndex].furmatOcclusion = ObjectField <Texture2D>(new GUIContent("OCCLUSION MAP", "The occlusion map to be applied to the skin under the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatOcclusion, false);

                                GUILayout.Space(8);
                                EndSmallGroup();
                            }

                            GUILayout.Space(16);

                            if (xFur.materialProfiles[xFur.materialProfileIndex].furmatReadBaseFur != 0)
                            {
                                GUILayout.Space(4);
                                SmallGroup("FUR SETTINGS");
                                xFur.materialProfiles[xFur.materialProfileIndex].furmatFurColorA = ColorField(new GUIContent("FUR COLOR A", "Main tint to be applied to the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatFurColorA);
                                xFur.materialProfiles[xFur.materialProfileIndex].furmatFurColorB = ColorField(new GUIContent("FUR COLOR B", "Main tint to be applied to the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatFurColorB);
                                xFur.materialProfiles[xFur.materialProfileIndex].furmatFurRim    = ColorField(new GUIContent("FUR RIM COLOR", "Main tint to be applied to the fur's rim"), xFur.materialProfiles[xFur.materialProfileIndex].furmatFurRim);

                                xFur.materialProfiles[xFur.materialProfileIndex].furmatFurSpecular = ColorField(new GUIContent("SPECULAR COLOR", "Specular color to be applied to the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatFurSpecular);

                                xFur.materialProfiles[xFur.materialProfileIndex].furmatFurColorMap = ObjectField <Texture2D>(new GUIContent("FUR COLOR MAP", "Texture to be applied to the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatFurColorMap, false);
                                xFur.materialProfiles[xFur.materialProfileIndex].furmatData0       = ObjectField <Texture2D>(new GUIContent("FUR DATA 0", "Main fur Data map (fur mask, length, thickness and occlusion)"), xFur.materialProfiles[xFur.materialProfileIndex].furmatData0, false);
                                xFur.materialProfiles[xFur.materialProfileIndex].furmatData1       = ObjectField <Texture2D>(new GUIContent("FUR DATA 1", "Secondary fur Data map (grooming and stiffness)"), xFur.materialProfiles[xFur.materialProfileIndex].furmatData1, false);

                                if (xFur.materialProfiles[xFur.materialProfileIndex].furmatReadFurNoise > 0)
                                {
                                    xFur.materialProfiles[xFur.materialProfileIndex].furmatFurNoiseMap = ObjectField <Texture2D>(new GUIContent("FUR NOISE GEN", "Multi-layer noise map used as reference to generate the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatFurNoiseMap, false);
                                }
                                GUILayout.Space(4);

                                xFur.materialProfiles[xFur.materialProfileIndex].furmatFurOcclusion  = SliderField(new GUIContent("FUR OCCLUSION", "Shadowing and Occlusion to be applied to the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatFurOcclusion, 0.0f, 1.0f);
                                xFur.materialProfiles[xFur.materialProfileIndex].furmatFurSmoothness = SliderField(new GUIContent("FUR SMOOTHNESS", "Smoothness to be applied to the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatFurSmoothness, 0.0f, 1.0f);
                                xFur.materialProfiles[xFur.materialProfileIndex].furmatFurLength     = SliderField(new GUIContent("FUR LENGTH", "Length of the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatFurLength, 0.0f, 4.0f);
                                xFur.materialProfiles[xFur.materialProfileIndex].furmatFurThickness  = SliderField(new GUIContent("FUR THICKNESS", "Thickness of the fur"), xFur.materialProfiles[xFur.materialProfileIndex].furmatFurThickness, 0.0f, 1.0f);
                                xFur.materialProfiles[xFur.materialProfileIndex].furmatFurRimPower   = SliderField(new GUIContent("FUR RIM POWER", "The power of the rim lighting effect"), xFur.materialProfiles[xFur.materialProfileIndex].furmatFurRimPower, 0.0f, 1.0f);
                                GUILayout.Space(4);

                                xFur.materialProfiles[xFur.materialProfileIndex].furmatFurUV1 = FloatField(new GUIContent("FUR UV 0 SCALE", "Scale of the first fur specific UV channel"), xFur.materialProfiles[xFur.materialProfileIndex].furmatFurUV1);
                                xFur.materialProfiles[xFur.materialProfileIndex].furmatFurUV2 = FloatField(new GUIContent("FUR UV 1 SCALE", "Scale of the second fur specific UV channel"), xFur.materialProfiles[xFur.materialProfileIndex].furmatFurUV2);

                                Vector3 furDir         = xFur.materialProfiles[xFur.materialProfileIndex].furmatDirection;
                                int     groomAlgorithm = (int)xFur.materialProfiles[xFur.materialProfileIndex].furmatDirection.w;

                                groomAlgorithm = PopupField(new GUIContent("GROOMING ALGORITHM", "The grooming algorithm to use when adding fur direction to this model"), groomAlgorithm, new GUIContent[] { new GUIContent("Original", "The original grooming algorithm adds a bit of length to the fur as you groom allowing more creativity. Please use small fur direction values for best results"), new GUIContent("Accurate", "The new algorithm for grooming is more accurate, bending the fur without adding any length. It allows for a more controlled, predictable grooming. Please make sure to use high fur direction values for best results") });
                                furDir         = Vector3Field(new GUIContent("FUR DIRECTION"), furDir);

                                xFur.materialProfiles[xFur.materialProfileIndex].furmatDirection = new Vector4(furDir.x, furDir.y, furDir.z, groomAlgorithm);



                                GUILayout.Space(8);
                                EndSmallGroup();

                                GUILayout.Space(8);
                            }
                        }
                        else
                        {
                            GUILayout.Space(6);

                            GUILayout.BeginHorizontal(); GUILayout.Space(12);
                            EditorGUILayout.HelpBox("Per Instance parameters are not supported on models with more than 1 fur based material on Unity versions older than Unity 2018.1", MessageType.Warning);
                            GUILayout.Space(12); GUILayout.EndHorizontal();

                            GUILayout.Space(6);
                        }
                    }
                    else
                    {
                        GUILayout.BeginHorizontal(); GUILayout.Space(12);
                        EditorGUILayout.HelpBox("This material is not a fur enabled material, no settings will be available for it.", MessageType.Warning);
                        GUILayout.Space(12); GUILayout.EndHorizontal();
                    }
                    GUILayout.Space(16);
                }
                EndCenteredGroup();


                if (BeginCenteredGroup(xFur.coatingModule != null ? "XFUR - " + xFur.coatingModule.ModuleName : "XFur - Coating Module (ERROR)", ref xFur.folds[1]))
                {
                    GUILayout.Space(16);
                    xFur.coatingModule.Module_UI(xFur);
                    GUILayout.Space(16);
                }
                EndCenteredGroup();


                if (BeginCenteredGroup(xFur.lodModule != null ? "XFUR - " + xFur.lodModule.ModuleName : "XFur - Lod Module (ERROR)", ref xFur.folds[2]))
                {
                    GUILayout.Space(16);
                    xFur.lodModule.Module_UI(xFur);
                    GUILayout.Space(16);
                }
                EndCenteredGroup();


                if (BeginCenteredGroup(xFur.physicsModule != null ? "XFUR - " + xFur.physicsModule.ModuleName : "XFur - Physics Module (ERROR)", ref xFur.folds[3]))
                {
                    GUILayout.Space(16);
                    xFur.physicsModule.Module_UI(xFur);
                    GUILayout.Space(16);
                }
                EndCenteredGroup();


                if (BeginCenteredGroup(xFur.fxModule != null ? "XFUR - " + xFur.fxModule.ModuleName : "XFur - FX Module (ERROR)", ref xFur.folds[4]))
                {
                    GUILayout.Space(16);
                    xFur.fxModule.Module_UI(xFur);
                    GUILayout.Space(16);
                }
                EndCenteredGroup();

                if (BeginCenteredGroup("HELP & SUPPORT", ref xFur.folds[6]))
                {
                    GUILayout.Space(16);
                    CenteredLabel("SUPPORT AND ASSISTANCE");
                    GUILayout.Space(10);

                    EditorGUILayout.HelpBox("Please make sure to include the following information with your request :\n - Invoice number\n - Screenshots of the XFur_System component and its settings\n - Steps to reproduce the issue.\n\nOur support service usually takes 2-4 business days to reply, so please be patient. We always reply to all emails.", MessageType.Info);

                    GUILayout.Space(8);
                    GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace();
                    GUILayout.Label("For support, contact us at : [email protected]", pidiSkin2.label);
                    GUILayout.FlexibleSpace(); GUILayout.EndHorizontal();

                    GUILayout.Space(8);

                    GUILayout.Space(16);
                    CenteredLabel("ONLINE TUTORIALS");
                    GUILayout.Space(10);
                    if (CenteredButton("QUICK START GUIDE", 200))
                    {
                        Help.BrowseURL("https://pidiwiki.irreverent-software.com/wiki/doku.php?id=xfur_studio_legacy#quick_start_guide");
                    }
                    if (CenteredButton("PREPARING YOUR 3D MODELS", 200))
                    {
                        Help.BrowseURL("https://pidiwiki.irreverent-software.com/wiki/doku.php?id=xfur_studio_legacy#preparing_your_3d_models");
                    }
                    if (CenteredButton("XFUR PAINTER", 200))
                    {
                        Help.BrowseURL("https://pidiwiki.irreverent-software.com/wiki/doku.php?id=xfur_studio_legacy#xfur_painter");
                    }
                    if (CenteredButton("XFUR SYSTEM COMPONENTS", 200))
                    {
                        Help.BrowseURL("https://pidiwiki.irreverent-software.com/wiki/doku.php?id=xfur_studio_legacy#xfur_studio_-_components");
                    }
                    if (CenteredButton("XFUR SYSTEM MODULES", 200))
                    {
                        Help.BrowseURL("https://pidiwiki.irreverent-software.com/wiki/doku.php?id=xfur_studio_legacy#xfur_studio_-_system_modules");
                    }

                    if (CenteredButton("XFUR STUDIO API", 200))
                    {
                        Help.BrowseURL("https://pidiwiki.irreverent-software.com/wiki/doku.php?id=xfur_studio_legacy#xfur_studio_api");
                    }

                    GUILayout.Space(24);
                    CenteredLabel("ABOUT PIDI : XFUR STUDIO™");
                    GUILayout.Space(12);

                    EditorGUILayout.HelpBox("PIDI : XFur Studio™ has been integrated in dozens of projects by hundreds of users.\nYour use and support to this tool is what keeps it growing, evolving and adapting to better suit your needs and keep providing you with the best quality fur for Unity.\n\nIf this tool has been useful for your project, please consider taking a minute to rate and review it, to help us to continue its development for a long time.", MessageType.Info);

                    GUILayout.Space(8);
                    if (CenteredButton("REVIEW XFUR STUDIO™", 200))
                    {
                        Help.BrowseURL("https://assetstore.unity.com/packages/vfx/shaders/pidi-xfur-studio-113361");
                    }
                    GUILayout.Space(8);
                    if (CenteredButton("ABOUT THIS VERSION", 200))
                    {
                        Help.BrowseURL("https://assetstore.unity.com/packages/vfx/shaders/pidi-xfur-studio-113361");
                    }
                    GUILayout.Space(8);
                }
                EndCenteredGroup();
            }

            GUILayout.Space(16);

            var tempStyle = new GUIStyle();
            tempStyle.normal.textColor = new Color(0.75f, 0.75f, 0.75f);
            tempStyle.fontSize         = 9;
            tempStyle.fontStyle        = FontStyle.Italic;
            GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace();
            GUILayout.Label("Copyright© 2018-2019, Jorge Pinal N.", tempStyle);
            GUILayout.FlexibleSpace(); GUILayout.EndHorizontal();

            GUILayout.Space(16);
            GUILayout.EndVertical(); GUILayout.Space(8); GUILayout.EndHorizontal();


            GUI.skin = tSkin;
        }
Ejemplo n.º 15
0
 public virtual void Module_UI(XFur_System owner)
 {
     moduleState = EnableDisableToggle(new GUIContent("ENABLE MODULE FUNCTIONS"), moduleState == XFurModuleState.Enabled?true:false)?XFurModuleState.Enabled:XFurModuleState.Disabled;
     systemOwner = owner;
 }
Ejemplo n.º 16
0
        public override void Module_UI(XFur_System owner)
        {
            base.Module_UI(owner);

            if (State == XFurModuleState.Enabled)
            {
                GUILayout.Space(8);
                affectedByLOD = EnableDisableToggle(new GUIContent("LOD INFLUENCED MODE", "If enabled, this module's functionality will be affected by the LOD module. At further distances, the functionality of this module will be adjusted for better performance"), affectedByLOD);
                GUILayout.Space(8);
                useBasicPhysics   = EnableDisableToggle(new GUIContent("USE BASIC PHYSICS", "Use a less complex and less accurate physics algorithm. Improves performance"), useBasicPhysics);
                useAngularPhysics = EnableDisableToggle(new GUIContent("USE ANGULAR FORCES", "Calculate physics for angular movements (rotations). Affects performance"), useAngularPhysics);
                GUILayout.Space(16);

                iterations         = IntField(new GUIContent("PHYSICS ITERATIONS", "Amount of iterations per second that the physics simulation will perform. Impacts performance"), iterations);
                physicsSensitivity = SliderField(new GUIContent("PHYSICS SENSITIVITY", "The sensitivity of the fur to movement. The higher the sensitivity, the smaller the movements need to be to be tracked by the physics simulation"), physicsSensitivity, 0.0f, 1.0f);
                physicsStrength    = SliderField(new GUIContent("PHYSICS STRENGTH", "The strength of the physics to be applied to the fur"), physicsStrength, 0.0f, 1.0f);
                gravityStrength    = SliderField(new GUIContent("GRAVITY STRENGTH", "The strength of the gravity to be applied to the fur"), gravityStrength, 0.0f, 1.0f);
                inertia            = SliderField(new GUIContent("INERTIA STRENGTH", "The strength of the inertia to be applied to the fur"), inertia, 0.0f, 1.0f);
                GUILayout.Space(16);

                if (systemOwner.GetComponent <SkinnedMeshRenderer>())
                {
                    CenteredLabel("BONE SETTINGS (BETA)");

                    if (!autoDetectBones)
                    {
                        GUILayout.Space(8);
                        EditorGUILayout.HelpBox("WARNING : Assigning bones manually to the physics module requires you to re-generate the geometry. Please regenerate the patched geometry now by pressing the Rebuild Data button at the top of the XFur System UI if you haven't already.", MessageType.Warning);
                    }

                    GUILayout.Space(8);
                    autoDetectBones = EnableDisableToggle(new GUIContent("AUTO-TRACK BONES", "If enabled, XFur will automatically detect and track the first 128 bones of the model for the physics simulation"), autoDetectBones);

                    if (!autoDetectBones)
                    {
                        SmallGroup("TRACKED BONES");
                        GUILayout.Space(8);

                        for (int i = 0; i < bones.Length; i++)
                        {
                            GUILayout.BeginHorizontal();
                            bones[i] = ObjectField <Transform>(new GUIContent("TRACKED BONE " + i), bones[i], true);
                            GUILayout.Space(8);
                            if (StandardButton("X", 24))
                            {
                                ArrayUtility.RemoveAt <Transform>(ref bones, i);
                                GUILayout.EndHorizontal();
                                break;
                            }
                            GUILayout.Space(12);
                            GUILayout.EndHorizontal();
                        }

                        if (CenteredButton("ADD NEW BONE", 200))
                        {
                            ArrayUtility.Add <Transform>(ref bones, null);
                        }
                        GUILayout.Space(8);

                        EndSmallGroup();
                    }
                }
            }
            GUILayout.Space(16);
        }