Esempio n. 1
0
        /// <summary>
        /// Dependency check
        /// Checks if all of the dependencies of the mesh are available in Unity
        /// </summary>
        public static bool DependencyCheck(MaterialDefinitionData materialDefinitionData)
        {
            // Check if we have textures available
            var currentReadPtr    = materialDefinitionData.parameters;
            var parameterDataSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(MaterialDefinitionParameterData));

            for (var i = 0; i < materialDefinitionData.parameterCount; ++i)
            {
                // Marshal parameter data
                MaterialDefinitionParameterData parameterData = (MaterialDefinitionParameterData)System.Runtime.InteropServices.Marshal.PtrToStructure(currentReadPtr, typeof(MaterialDefinitionParameterData));
                currentReadPtr = MarshalData.AddToIntPtr(currentReadPtr, parameterDataSize);

                // Get the parameter type
                ParamType type = (ParamType)parameterData.type;

                if (type == ParamType.Texture)
                {
                    // Check if we have a texture ready for this material definition
                    if (!PackageMapper.GetTexture2DFromToken(parameterData.textureToken))
                    {
                        // TODO: messages slow down the recieve mechanism and spam the log
                        //Debug.LogWarningFormat("Texture '{0}' for '{1}' material has not yet been created!",
                        //                         parameterData.textureToken,
                        //                         materialDefinitionData.entityToken);

                        return(false);
                    }
                }
            }

            return(true);
        }
Esempio n. 2
0
        public static Object CreateMaterial(MaterialDefinitionData materialDefinitionData)
        {
            ShaderModel shaderModel = (ShaderModel)materialDefinitionData.shaderModel;
            BlendMode   blendMode   = (BlendMode)materialDefinitionData.blendMode;

            Debug.LogFormat("Material Definition - Token:{0} Display Name:{1}, {2} shader model {3} blend mode {4} parameter count", materialDefinitionData.entityToken, materialDefinitionData.displayName, shaderModel, blendMode, materialDefinitionData.parameterCount);

            // Create a new Unity material with "Standard" Unity shader
            // Shader string names are assumed to use the Unity Standard shader code
            Material newMaterial = new Material(Shader.Find("Standard"));

            // Set blend mode options
            switch (blendMode)
            {
            case BlendMode.ModeUnknown:
            case BlendMode.Opaque:
                // Default blend mode, skip modification
                break;

            case BlendMode.Translucent:
                // Code taken from https://answers.unity.com/questions/1004666/change-material-rendering-mode-in-runtime.html
                // Changes what options are available in Unity shader GUI
                newMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                newMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                newMaterial.SetInt("_ZWrite", 0);
                newMaterial.DisableKeyword("_ALPHATEST_ON");
                newMaterial.DisableKeyword("_ALPHABLEND_ON");
                newMaterial.EnableKeyword("_ALPHAPREMULTIPLY_ON");
                newMaterial.renderQueue = 3000;
                break;
            }

            var currentReadPtr    = materialDefinitionData.parameters;
            var parameterDataSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(MaterialDefinitionParameterData));

            for (var i = 0; i < materialDefinitionData.parameterCount; ++i)
            {
                // Marshal parameter data
                MaterialDefinitionParameterData parameterData = (MaterialDefinitionParameterData)System.Runtime.InteropServices.Marshal.PtrToStructure(currentReadPtr, typeof(MaterialDefinitionParameterData));
                currentReadPtr = MarshalData.AddToIntPtr(currentReadPtr, parameterDataSize);

                // Get the parameter type
                ParamType type = (ParamType)parameterData.type;

                Debug.LogFormat("Material Parameter - Name:{0} Type:{1} Target:{2}, {3} texture token", parameterData.name, type, parameterData.target, parameterData.textureToken);

                // Get the right shader input and connect parameter data
                string  shaderStringTarget;
                Vector4 vect;
                int     offset = 0;
                switch (type)
                {
                case ParamType.Float:
                    shaderStringTarget = FindScalarInput(parameterData.target);
                    if (System.String.IsNullOrEmpty(shaderStringTarget))
                    {
                        break;
                    }

                    newMaterial.SetFloat(shaderStringTarget, MarshalData.GetFloatFromUnmanagedArray(parameterData.floatData, offset));
                    break;

                case ParamType.Float2:
                    shaderStringTarget = FindVectorInput(parameterData.target);
                    if (System.String.IsNullOrEmpty(shaderStringTarget))
                    {
                        break;
                    }

                    vect.x  = MarshalData.GetFloatFromUnmanagedArray(parameterData.floatData, offset);
                    offset += MarshalData.sizeOfInt;
                    vect.y  = MarshalData.GetFloatFromUnmanagedArray(parameterData.floatData, offset);
                    vect.z  = 0.0f;
                    vect.w  = 0.0f;
                    newMaterial.SetVector(shaderStringTarget, vect);
                    break;

                case ParamType.Float3:
                    shaderStringTarget = FindVectorInput(parameterData.target);
                    if (System.String.IsNullOrEmpty(shaderStringTarget))
                    {
                        break;
                    }

                    vect.x  = MarshalData.GetFloatFromUnmanagedArray(parameterData.floatData, offset);
                    offset += MarshalData.sizeOfInt;
                    vect.y  = MarshalData.GetFloatFromUnmanagedArray(parameterData.floatData, offset);
                    offset += MarshalData.sizeOfInt;
                    vect.z  = MarshalData.GetFloatFromUnmanagedArray(parameterData.floatData, offset);
                    vect.w  = 0.0f;
                    newMaterial.SetVector(shaderStringTarget, vect);
                    break;

                case ParamType.Float4:
                case ParamType.RGBA8:
                    shaderStringTarget = FindVectorInput(parameterData.target);
                    if (System.String.IsNullOrEmpty(shaderStringTarget))
                    {
                        break;
                    }

                    vect.x  = MarshalData.GetFloatFromUnmanagedArray(parameterData.floatData, offset);
                    offset += MarshalData.sizeOfInt;
                    vect.y  = MarshalData.GetFloatFromUnmanagedArray(parameterData.floatData, offset);
                    offset += MarshalData.sizeOfInt;
                    vect.z  = MarshalData.GetFloatFromUnmanagedArray(parameterData.floatData, offset);
                    offset += MarshalData.sizeOfInt;
                    vect.w  = MarshalData.GetFloatFromUnmanagedArray(parameterData.floatData, offset);
                    newMaterial.SetVector(shaderStringTarget, vect);
                    break;

                case ParamType.Texture:
                    shaderStringTarget = FindTextureInput(parameterData.target);
                    if (System.String.IsNullOrEmpty(shaderStringTarget))
                    {
                        break;
                    }

                    Texture texture = PackageMapper.GetTexture2DFromToken(parameterData.textureToken);

                    newMaterial.SetTexture(shaderStringTarget, texture);

                    // TODO: Emission keyword doesn't work in Unity 2018.2.15f1 as it doesn't enable
                    // emission checkbox for some reason
                    // Special case for emission textures, enable the emission map on the shader
                    if (shaderStringTarget == ShaderEmissionTexture)
                    {
                        newMaterial.EnableKeyword("_EMISSION");
                    }
                    break;
                }
            }

            // Create material default STP folders if they don't exist
            PackageMapper.CreateAssetFolders(MaterialDefinitionHandler.assetPath);

            // Generate a unique material name
            string materialPath = Application.dataPath + "/" + MaterialDefinitionHandler.assetPath;
            string uniqueMaterialName;

            GenUniqueMaterialAssetName(materialPath, materialDefinitionData.displayName, out uniqueMaterialName);

            // Set the unique material name as the display name
            newMaterial.name = uniqueMaterialName;

            // Create a GameObject prefab object and use it as a database item of STP used materials
            GameObject materialPrefab = new GameObject(uniqueMaterialName);

            // Add Foundry unique token storage component, store unique material token
            var tokenStorage = materialPrefab.AddComponent <FoundryUniqueToken>();

            tokenStorage.uniqueToken = materialDefinitionData.entityToken;

            // Create the prefab asset
            var    localPrefabPath = System.String.Format("{0}/{1}/{2}", PackageMapper.rootPath, MaterialDefinitionHandler.assetPath, uniqueMaterialName);
            string prefabPath;

            PackageMapper.GenUniquePrefabAssetPath(localPrefabPath, out prefabPath);
#if UNITY_2018_3_OR_NEWER
            Object prefabAsset = PrefabUtility.SaveAsPrefabAsset(materialPrefab, prefabPath);
#else
            Object prefabAsset = PrefabUtility.CreatePrefab(prefabPath, materialPrefab);
#endif

            // Map the prefab to the material
            PackageMapper.MapMaterialToPrefab(newMaterial, prefabAsset);

            AssetDatabase.AddObjectToAsset(newMaterial, prefabAsset);
            AssetDatabase.SaveAssets();

            // Remove game object that's used for creating a prefab from scene hierarchy
            Object.DestroyImmediate(materialPrefab);

            return(prefabAsset);
        }