public static GameObject CreateMeshInstance(MeshInstanceData meshInstanceData)
        {
            Debug.LogFormat("Mesh Instance - Token:{0}, Name:{1} Parent:{2}, Mesh:{3}", meshInstanceData.entityToken, meshInstanceData.displayName, meshInstanceData.entityParentToken, meshInstanceData.originalMesh);

            var transform = MarshalData.GetXFormFromUnmanagedArray(meshInstanceData.xform);

            // Find mesh prefab
            Object meshPrefabObj = PackageMapper.GetObjectFromToken(meshInstanceData.originalMesh);

            // Create a new game object
            GameObject meshInst = Object.Instantiate(meshPrefabObj as GameObject);

            // Remove the "(Clone)" string from name that Unity automatically adds when instantiating
            // and apply the actual display name of the instance
            meshInst.name = meshInstanceData.displayName;

            // Find instance parent
            Object parentObj = PackageMapper.GetObjectFromToken(meshInstanceData.entityParentToken);

            SceneTransmissionProtocolUtilities.UpdateObjectHierarchy(meshInst, parentObj as GameObject, transform);

            // Add token store
            PackageMapper.AddUniqueTokenStore(meshInst, meshInstanceData.entityToken);

            return(meshInst);
        }
        public static void ParseMaterialDefinitionData(MaterialDefinitionData materialDefinitionData)
        {
            // Check if the object already exists in the package mapper
            if (PackageMapper.TokenExistsInCache(materialDefinitionData.entityToken))
            {
                // If object exists skip update
                // TODO: At some point decide how we handle material updates.
                // Important note to consider is that we will be adding already existing
                // materials in Unity that STP didn't create to the material map and how to handle those updates.
                Debug.LogWarning("Material Definition Update not supported yet! Discarding material data!!");
                return;
            }
            else
            {
                // Create a new GameObject in the hierarchy
                Object newMaterial = MaterialDefinitionHandler.CreateMaterial(materialDefinitionData);

                if (newMaterial)
                {
                    PackageMapper.MapTokenToObject(materialDefinitionData.entityToken, newMaterial);

                    // If a new material has been created go through the stored list of meshes
                    // to see if we can create a new one with this material available
                    IterateMeshStore();
                }
            }
        }
Beispiel #3
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);
        }
        /// <summary>
        /// Get mesh materials
        /// Function checks for mesh materials by unique tokens and adds them to a list.
        /// </summary>
        private static Material[] GetMeshMaterials(int numFacesets, StringCollection materialNames, string entityToken)
        {
            // specify how to render it, one material per faceset
            var materials = new Material[numFacesets];

            for (var i = 0; i < numFacesets; ++i)
            {
                Material material = null;
                if (!System.String.IsNullOrEmpty(materialNames[i]))
                {
                    material = PackageMapper.GetMaterialFromToken(materialNames[i]);
                    if (!material)
                    {
                        throw new System.Exception(
                                  System.String.Format("Material '{0}' for '{1}' has not yet been created!",
                                                       materialNames[i],
                                                       entityToken));
                    }
                }
                else
                {
                    material = DefaultAssets.DiffuseMaterial;
                }
                materials[i] = material;
            }

            return(materials);
        }
Beispiel #5
0
        public static GameObject CreateCamera(CameraData cameraData)
        {
            CameraProjectionType camType = (CameraProjectionType)cameraData.type;

            Debug.LogFormat("Camera - Token:{0}, Name:{1}, Projection Type:{2}, VerticalFov:{3}, AspectRatio:{4}, HorizontalMag:{5}, NearClip:{6}, FarClip:{7}", cameraData.entityToken, cameraData.displayName, camType, cameraData.verticalFov, cameraData.aspectRatio, cameraData.horizontalMag, cameraData.nearClip, cameraData.farClip);

            // Get transformation data
            var transform = MarshalData.GetXFormFromUnmanagedArray(cameraData.xform);

            // Create a new game object
            GameObject cameraInst = new GameObject(cameraData.displayName);

            // Set transformation
            SceneTransmissionProtocolUtilities.UpdateObjectHierarchy(cameraInst, null, transform);

            // Add camera component
            Camera camera = cameraInst.AddComponent <Camera>();

            SetCameraData(camera, cameraData);

            // Add token store
            PackageMapper.AddUniqueTokenStore(cameraInst, cameraData.entityToken);

            return(cameraInst);
        }
        private static void StopClient()
        {
            Debug.Log("Foundry Bridge: Stopping client thread");
            stpUnityStopClient();

            // Stopping client clears package maps
            PackageMapper.ClearTokenMaps();
        }
Beispiel #7
0
        public static void UpdateTexture(TextureData textureData)
        {
            ImgFormat imgFormat = (ImgFormat)textureData.imgFormat;

            Debug.LogFormat("Texture Update - Token:{0}, {1} width {2} height {3} image type", textureData.entityToken, textureData.width, textureData.height, imgFormat);

            Texture2D texture = PackageMapper.GetTexture2DFromToken(textureData.entityToken);

            UpdateTextureData(texture, textureData, imgFormat);
        }
        CreateSimpleMeshAsset(
            string entityToken,
            string parentToken,
            string displayName,
            int numFacesets,
            StringCollection materialNames,
            Mesh mesh)
        {
            Material[] materials = GetMeshMaterials(numFacesets, materialNames, entityToken);

            // Add mesh name
            mesh.name = displayName;

            // Create asset folders if they are non existant
            PackageMapper.CreateAssetFolders(MeshHandler.assetPath);

            GameObject meshPrefab = new GameObject();

            meshPrefab.AddComponent <MeshFilter>();
            var meshRenderer = meshPrefab.AddComponent <MeshRenderer>();

            meshRenderer.materials = materials;
            var meshTokenComp = meshPrefab.AddComponent <FoundryUniqueToken>();

            meshTokenComp.uniqueToken = entityToken;

            // Create the mesh asset prefab
            var    localPath = System.String.Format("{0}/{1}/{2}", PackageMapper.rootPath, MeshHandler.assetPath, displayName);
            string prefabPath;

            PackageMapper.GenUniquePrefabAssetPath(localPath, out prefabPath);
#if UNITY_2018_3_OR_NEWER
            GameObject prefab = PrefabUtility.SaveAsPrefabAsset(meshPrefab, prefabPath);
#else
            GameObject prefab = PrefabUtility.CreatePrefab(prefabPath, meshPrefab);
#endif

            // Add the mesh object to the prefab
            AssetDatabase.AddObjectToAsset(mesh, prefab);

            // Need to add mesh after being added to the asset or it will disappear in the prefab
            prefab.GetComponent <MeshFilter>().mesh = mesh;

            AssetDatabase.SaveAssets();

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

            // Map the mesh prefab to unique token
            PackageMapper.MapTokenToObject(entityToken, prefab);
            PackageMapper.MapMeshToPrefab(mesh, prefab);

            return(true);
        }
Beispiel #9
0
        public static Object CreateTexture(TextureData textureData)
        {
            ImgFormat     imgFormat = (ImgFormat)textureData.imgFormat;
            TextureFormat texFormat = GetTextureFormat(imgFormat, textureData.entityToken);

            Debug.LogFormat("Texture - Token:{0}, {1} width {2} height {3} image type", textureData.entityToken, textureData.width, textureData.height, imgFormat);

            // Create a new Unity texture
            Texture2D newTexture = new Texture2D(textureData.width, textureData.height, texFormat, true);

            UpdateTextureData(newTexture, textureData, imgFormat);

            // Create texture folders if they don't exist
            PackageMapper.CreateAssetFolders(TextureHandler.assetPath);

            // Generate a unique texture name
            string texturePath = Application.dataPath + "/" + TextureHandler.assetPath;
            string uniqueTextureName;

            GenUniqueTextureAssetName(texturePath, textureData.displayName, out uniqueTextureName);

            // Set the unique texture name as the display name
            newTexture.name = uniqueTextureName;

            // Create a GameObject prefab object and use it as a database item of STP used textures
            GameObject texturePrefab = new GameObject(textureData.displayName);

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

            tokenStorage.uniqueToken = textureData.entityToken;

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

            PackageMapper.GenUniquePrefabAssetPath(localPrefabPath, out prefabPath);

#if UNITY_2018_3_OR_NEWER
            Object prefabAsset = PrefabUtility.SaveAsPrefabAsset(texturePrefab, prefabPath);
#else
            Object prefabAsset = PrefabUtility.CreatePrefab(prefabPath, texturePrefab);
#endif
            AssetDatabase.AddObjectToAsset(newTexture, prefabAsset);
            AssetDatabase.SaveAssets();

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

            return(prefabAsset);
        }
        static void Update()
        {
            if (startup)
            {
                AssociateManagedDelegatesWithNativePlugin();
                DefaultAssets.Instance.Create();
                startup = false;

                // Added the regenerate object maps on startup due to
                // Unity recompilation ( reimport and code change ) of scrips losing map data
                PackageMapper.RegenerateTokenToObjectMaps();
            }
            stpUnityIdleUpdate();
        }
        private static void PushMesh(GameObject obj)
        {
            // Get the mesh from object
            Mesh mesh = obj.GetComponent <MeshFilter>().sharedMesh;

            // Get the prefab and extract material data and get or generate a mesh token
            var prefab = PackageMapper.GetPrefabFromMesh(mesh);

            string uniqueToken;

            if (!prefab)
            {
                // Create unique mesh token
                uniqueToken = GenerateMeshToken(mesh);
            }
            else
            {
                // Grab existing token or generate a new one
                uniqueToken = GetTokenFromStorage(prefab);
                if (System.String.IsNullOrEmpty(uniqueToken))
                {
                    uniqueToken = GenerateMeshToken(mesh);
                }
            }

            // Gather material unique tokens
            List <string> materialTokens = new List <string>();
            var           meshRenderer   = obj.GetComponent <MeshRenderer>();

            if (meshRenderer)
            {
                for (var i = 0; i < meshRenderer.sharedMaterials.Length; i++)
                {
                    var materialPrefab = PackageMapper.GetPrefabFromMaterial(meshRenderer.sharedMaterials[i]);

                    var tokenStore = materialPrefab.GetComponent <FoundryUniqueToken>();
                    if (tokenStore && !System.String.IsNullOrEmpty(tokenStore.uniqueToken))
                    {
                        materialTokens.Add(tokenStore.uniqueToken);
                    }
                    else
                    {
                        materialTokens.Add("");
                    }
                }
            }

            // Send the mesh package to the server
            MeshHandler.CreateAndSendMeshRequest(mesh, materialTokens, uniqueToken);
        }
        private static void StartClient()
        {
            if (stpUnityIsClientRunning())
            {
                Debug.LogWarning("Client already running!");
                return;
            }

            ClientOptions.Instance.broadcast();

            PackageMapper.RegenerateTokenToObjectMaps();

            Debug.Log("Foundry Bridge: Starting client thread");
            stpUnityStartClient();
        }
Beispiel #13
0
        /// <summary>
        /// CreateNonSTPMaterialPrefab
        /// Create a prefab for materials not created by STP to store token information
        /// and connect the token to the material
        /// </summary>
        public static GameObject CreateNonSTPMaterialPrefab(Material material)
        {
            // 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, material.name, out 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 = ExportUtilities.GenerateMaterialToken(material);

            // Add Foundry material storage component, store non STP material
            var materialStorage = materialPrefab.AddComponent <FoundryMaterialStore>();

            materialStorage.material = material;

            // 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
            // Add the prefab object to package mapper
            PackageMapper.AddUniqueTokenStore(prefabAsset as GameObject, tokenStorage.uniqueToken);
            PackageMapper.MapMaterialToPrefab(material, prefabAsset);

            AssetDatabase.SaveAssets();

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

            return(prefabAsset as GameObject);
        }
        public static string GenerateMaterialToken(Material material)
        {
            // If it doesn't exist generate a new one
            string uniqueMaterialToken;
            var    scene = SceneManager.GetActiveScene();

            uniqueMaterialToken  = "/";
            uniqueMaterialToken += (System.String.IsNullOrEmpty(scene.name)) ? "Untitled" : scene.name;
            uniqueMaterialToken += "/materials/";
            uniqueMaterialToken += material.name;

            if (PackageMapper.TokenExistsInCache(uniqueMaterialToken))
            {
                appendUniqueSuffix(ref uniqueMaterialToken);
            }

            return(uniqueMaterialToken);
        }
        public static bool UpdateMeshInstance(MeshInstanceData meshInstanceData)
        {
            Debug.LogFormat("Mesh Instance Update - Token:{0}, Parent:{1}, Mesh:{2}", meshInstanceData.entityToken, meshInstanceData.entityParentToken, meshInstanceData.originalMesh);

            Object meshInstObj = PackageMapper.GetObjectFromToken(meshInstanceData.entityToken);
            var    meshInst    = meshInstObj as GameObject;

            var transform = MarshalData.GetXFormFromUnmanagedArray(meshInstanceData.xform);

            // Update the transformation of the item, ignore hierarchy updates for now
            // TODO: Work on hierarchy control systems
            Transform  parentTrs = meshInst.transform.parent;
            GameObject parent    = null;

            if (parentTrs)
            {
                parent = parentTrs.gameObject;
            }

            SceneTransmissionProtocolUtilities.UpdateObjectHierarchy(meshInst, parent, transform);

            // Update mesh filter
            Mesh mesh = PackageMapper.GetMeshFromToken(meshInstanceData.originalMesh);

            var meshFilter = meshInst.GetComponent <MeshFilter>();

            if (meshFilter)
            {
                meshFilter.sharedMesh = mesh;
            }

            // Update mesh renderer
            GameObject meshPrefab       = PackageMapper.GetObjectFromToken(meshInstanceData.originalMesh) as GameObject;
            var        meshRenderer     = meshPrefab.GetComponent <MeshRenderer>();
            var        meshInstRenderer = meshInst.GetComponent <MeshRenderer>();

            if (meshRenderer && meshInstRenderer)
            {
                meshInstRenderer.sharedMaterials = meshRenderer.sharedMaterials;
            }

            return(true);
        }
        private static void ParseCameraData(CameraData cameraData)
        {
            // Check if the camera already exists in the package mapper
            if (PackageMapper.TokenExistsInCache(cameraData.entityToken))
            {
                // If mesh exists try to update it
                CameraHandler.UpdateCamera(cameraData);
            }
            else
            {
                // Create a new camera object in Unity
                var cameraInst = CameraHandler.CreateCamera(cameraData);

                if (cameraInst)
                {
                    PackageMapper.MapTokenToObject(cameraData.entityToken, cameraInst);
                }
            }
        }
        private static void appendUniqueSuffix(ref string token)
        {
            string tokenStore;

            tokenStore = token;
            int  suffixNum = 1;
            bool exists    = true;

            while (exists)
            {
                tokenStore  = token;
                tokenStore += "_";
                tokenStore += suffixNum;
                suffixNum++;

                exists = PackageMapper.TokenExistsInCache(tokenStore);
            }

            token = tokenStore;
        }
        public static bool DependencyCheck(MeshInstanceData meshInstanceData)
        {
            if (!PackageMapper.TokenExistsInCache(meshInstanceData.originalMesh))
            {
                // TODO: messages slow down the recieve mechanism and spam the log
                //Debug.LogWarningFormat("Mesh Instance '{0}' Dependancy failed! Missing mesh item {1}!", meshInstanceData.entityToken, meshInstanceData.originalMesh);
                return(false);
            }

            if (!System.String.IsNullOrEmpty(meshInstanceData.entityParentToken))
            {
                if (!PackageMapper.TokenExistsInCache(meshInstanceData.entityParentToken))
                {
                    // TODO: messages slow down the recieve mechanism and spam the log
                    //Debug.LogWarningFormat("Mesh Instance '{0}' Dependancy failed! Missing parent item {1}!", meshInstanceData.entityToken, meshInstanceData.entityParentToken);
                    return(false);
                }
            }

            return(true);
        }
        private static void ParseMeshInstanceData(MeshInstanceData meshInstData, out bool newItemCreated)
        {
            newItemCreated = false;
            // Check if the object already exists in the package mapper
            if (PackageMapper.TokenExistsInCache(meshInstData.entityToken))
            {
                // If object exists try to update it
                MeshInstanceHandler.UpdateMeshInstance(meshInstData);
            }
            else
            {
                // Create a new GameObject in the hierarchy
                GameObject meshInst = MeshInstanceHandler.CreateMeshInstance(meshInstData);

                if (meshInst)
                {
                    PackageMapper.MapTokenToObject(meshInstData.entityToken, meshInst);
                    newItemCreated = true;
                }
            }
        }
        /// <summary>
        /// Dependency check
        /// Checks if all of the dependencies of the mesh are available in Unity
        /// </summary>
        public static bool DependencyCheck(ManagedMeshData meshData, string entityToken)
        {
            // Check if we have materials available
            for (var i = 0; i < meshData.facesetNum; ++i)
            {
                if (!System.String.IsNullOrEmpty(meshData.materials[i]))
                {
                    // Check if we have a material instance or material definition ready for this mesh
                    if (!PackageMapper.GetMaterialFromToken(meshData.materials[i]))
                    {
                        // TODO: messages slow down the recieve mechanism and spam the log
                        //Debug.LogWarningFormat("Material '{0}' for '{1}' has not yet been created!",
                        //                         meshData.materials[i],
                        //                         entityToken);

                        return(false);
                    }
                }
            }

            return(true);
        }
        private static void PushMeshInstance(GameObject obj)
        {
            // Get the mesh from object
            Mesh mesh = obj.GetComponent <MeshFilter>().sharedMesh;

            // Get the prefab and extract material data and get or generate a mesh token
            var prefab = PackageMapper.GetPrefabFromMesh(mesh);

            // Get or generate unique mesh token
            string meshToken;

            if (!prefab)
            {
                // Create unique mesh token
                meshToken = GenerateMeshToken(mesh);
            }
            else
            {
                // Grab existing token or generate a new one
                meshToken = GetTokenFromStorage(prefab);
                if (System.String.IsNullOrEmpty(meshToken))
                {
                    meshToken = GenerateMeshToken(mesh);
                }
            }

            // Grab existing instance token or generate a new one
            string instanceToken = GetTokenFromStorage(obj);

            if (System.String.IsNullOrEmpty(instanceToken))
            {
                // Create unique instance token
                instanceToken = GenerateMeshInstanceToken(obj);
            }

            // Send the mesh instance package to the server
            MeshInstanceHandler.CreateAndSendMeshInstanceRequest(obj, instanceToken, meshToken, "");
        }
Beispiel #22
0
        public static bool UpdateCamera(CameraData cameraData)
        {
            CameraProjectionType camType = (CameraProjectionType)cameraData.type;

            Debug.LogFormat("Camera Update - Token:{0}, Name:{1}, Projection Type:{2}, VerticalFov:{3}, AspectRatio:{4}, HorizontalMag:{5}, NearClip:{6}, FarClip:{7}", cameraData.entityToken, cameraData.displayName, camType, cameraData.verticalFov, cameraData.aspectRatio, cameraData.horizontalMag, cameraData.nearClip, cameraData.farClip);

            // Get transformation data
            var transform = MarshalData.GetXFormFromUnmanagedArray(cameraData.xform);

            // Get camera game object
            GameObject cameraInst = PackageMapper.GetObjectFromToken(cameraData.entityToken) as GameObject;

            if (cameraInst)
            {
                // Set transformation
                SceneTransmissionProtocolUtilities.UpdateObjectHierarchy(cameraInst, null, transform);

                // Get camera component
                Camera camera = cameraInst.GetComponent <Camera>();

                if (camera)
                {
                    SetCameraData(camera, cameraData);
                }
                else
                {
                    Debug.LogErrorFormat("Camera Update error! Camera component not found! Token:{0}");
                    return(false);
                }
            }
            else
            {
                Debug.LogErrorFormat("Camera Update error! Camera game object not found! Token:{0}");
                return(false);
            }

            return(true);
        }
        private static void ParseMeshData(MeshData meshData, ManagedMeshData managedMeshData)
        {
            // Check if the mesh already exists in the package mapper
            if (PackageMapper.TokenExistsInCache(meshData.entityToken))
            {
                // If mesh exists try to update it
                MeshHandler.UpdateMesh(meshData, managedMeshData);
            }
            else
            {
                // Create a new mesh object in Unity
                MeshHandler.CreateMesh(meshData, managedMeshData);

                // This loop starts over if we created a parent and a child is waiting in the store
                bool newItemCreated = true;
                while (newItemCreated)
                {
                    // Iterate through mesh instance store and try to create or update
                    // mesh instances that this mesh is a dependent of
                    IterateMeshInstanceStore(out newItemCreated);
                }
            }
        }
        private static bool PushMaterial(Material material)
        {
            var materialPrefab = PackageMapper.GetPrefabFromMaterial(material);

            // If material prefab doesn't exist it means this material is new to STP and we need
            // to add it to the database and generate a prefab for it
            if (!materialPrefab)
            {
                materialPrefab = MaterialDefinitionHandler.CreateNonSTPMaterialPrefab(material);
            }

            var tokenStore = materialPrefab.GetComponent <FoundryUniqueToken>();

            // If the token store is non existant bail out
            if (!tokenStore || System.String.IsNullOrEmpty(tokenStore.uniqueToken))
            {
                Debug.LogWarningFormat("Material '{0}' push failed! No available unique token!", material.name);
                return(false);
            }

            MaterialDefinitionHandler.CreateAndSendMaterialDefinitionRequest(material, tokenStore.uniqueToken);
            return(true);
        }
        public static void ParseTextureData(TextureData textureData)
        {
            // Check if the object already exists in the package mapper
            if (PackageMapper.TokenExistsInCache(textureData.entityToken))
            {
                // If object exists try to update it
                TextureHandler.UpdateTexture(textureData);
            }
            else
            {
                // Create a new GameObject in the hierarchy
                Object texture = TextureHandler.CreateTexture(textureData);

                if (texture)
                {
                    PackageMapper.MapTokenToObject(textureData.entityToken, texture);

                    // Iterate through material store and try to create or update
                    // materials that this texture is a dependent of
                    IterateMaterialDefinitionStore();
                }
            }
        }
        private static string GenerateMeshInstanceToken(GameObject obj)
        {
            // If it doesn't exist generate a new one
            string uniqueMeshInstanceToken;
            var    scene = SceneManager.GetActiveScene();

            uniqueMeshInstanceToken  = "/";
            uniqueMeshInstanceToken += (System.String.IsNullOrEmpty(scene.name)) ? "Untitled" : scene.name;
            uniqueMeshInstanceToken += "/instances/";
            uniqueMeshInstanceToken += obj.name;
            uniqueMeshInstanceToken += "_inst";

            if (PackageMapper.TokenExistsInCache(uniqueMeshInstanceToken))
            {
                appendUniqueSuffix(ref uniqueMeshInstanceToken);
            }

            // Add unique token store to the GameObject and add the token to the mapper
            // so we can reuse and update the mesh instance with STP
            PackageMapper.AddUniqueTokenStore(obj, uniqueMeshInstanceToken);
            PackageMapper.MapTokenToObject(uniqueMeshInstanceToken, obj);

            return(uniqueMeshInstanceToken);
        }
Beispiel #27
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);
        }
        /// <summary>
        /// Update mesh
        /// Function that goes through the process of updating existing mesh item.
        /// Checking for unindexed or indexed meshes.
        /// </summary>
        public static bool UpdateMesh(MeshData meshData, ManagedMeshData managedMeshData)
        {
            Debug.LogFormat("Mesh Update - Token:{0}, Parent:{1}, {2} positions, {3} facesets", meshData.entityToken, meshData.entityParentToken, meshData.positionsNum, meshData.facesetsNum);

            // Find existing mesh
            Mesh mesh = PackageMapper.GetMeshFromToken(meshData.entityToken);

            if (!mesh)
            {
                return(false);
            }

            // Get the index format of the mesh
            UnityEngine.Rendering.IndexFormat indexFormat;
            int maxVertexLimitSplit;

            GetIndexBufferConfiguration(
                managedMeshData.positions.Length,
                out indexFormat,
                out maxVertexLimitSplit);

            // Get the prefab object
            GameObject prefab = PackageMapper.GetObjectFromToken(meshData.entityToken) as GameObject;

            // Check if we need to split the mesh
            if (maxVertexLimitSplit == 0)
            {
                // Update existing mesh
                UpdateMeshData(
                    managedMeshData.positions,
                    managedMeshData.normals,
                    managedMeshData.uvs,
                    managedMeshData.facesetNum,
                    managedMeshData.indices,
                    indexFormat,
                    ref mesh
                    );

                UpdateSimpleMeshAsset(
                    meshData.entityToken,
                    meshData.displayName,
                    managedMeshData,
                    mesh,
                    prefab
                    );
            }
            else
            {
                // Delete prefab first
                AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(prefab));

                // Create split mesh assets, create hierarchy of prefabs
                // and add the root prefab to the package mapper
                List <Mesh> meshList = CreateSplitMeshes(
                    meshData.entityToken,
                    meshData.displayName,
                    managedMeshData
                    );

                CreateSplitMeshAsset(
                    meshData.entityToken,
                    meshData.displayName,
                    meshData.entityParentToken,
                    managedMeshData.facesetNum,
                    managedMeshData.materials,
                    meshList);
            }

            mesh.UploadMeshData(false);

            return(true);
        }
        /// <summary>
        /// Create unindexed mesh asset
        /// Used to create the assets of a referenced Unity mesh item
        /// We create two asset parts, first a Unity mesh asset in the set path
        /// And second a prefab made from the temporary GameObject of the created mesh asset
        /// Mesh prefab is used to store unique token information for that mesh and other data
        /// as materials and other.
        ///
        /// Difference between simple and unindexed mesh assets is that the vertex data for unindexed meshes is completely unwelded.
        /// </summary>
        private static bool CreateSplitMeshAsset(
            string entityToken,
            string displayName,
            string parentToken,
            int numFacesets,
            StringCollection materialNames,
            List <Mesh> meshList)
        {
            // specify how to render it, one material per faceset
            var materials = GetMeshMaterials(numFacesets, materialNames, entityToken);

            // Create root GameObject and add child GameObjects for each mesh generated
            // Root
            // ---- Mesh_Split_1
            // ---- Mesh_Split_2
            // ---- etc...
            GameObject rootObj = new GameObject(displayName);

            Transform rootTrs        = rootObj.transform;
            var       rootTokenStore = rootObj.AddComponent <FoundryUniqueToken>();

            rootTokenStore.uniqueToken = entityToken;

            // Create asset folders if they are non existant
            PackageMapper.CreateAssetFolders(MeshHandler.assetPath);

            // Create GameObject hierarchy
            int splitNum = 1;

            foreach (var mesh in meshList)
            {
                // Create the mesh asset
                string     gameObjectDisplayName;
                GameObject meshPrefab;

                // If we split this mesh create a game object for each part
                // else just populate the root object
                if (meshList.Count > 1)
                {
                    gameObjectDisplayName = System.String.Format("{0}_Split{1}", displayName, splitNum);

                    // Create mesh game object
                    meshPrefab = new GameObject(gameObjectDisplayName);

                    //Parent to the root game object
                    meshPrefab.transform.SetParent(rootTrs);
                }
                else
                {
                    gameObjectDisplayName = displayName;
                    meshPrefab            = rootObj;
                }

                meshPrefab.AddComponent <MeshFilter>();
                var meshRenderer = meshPrefab.AddComponent <MeshRenderer>();
                meshRenderer.materials = materials;

                mesh.name = gameObjectDisplayName;

                splitNum++;
            }

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

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

            List <MeshFilter> results = new List <MeshFilter>();
            prefabAsset.GetComponentsInChildren <MeshFilter>(results);

            int i = 0;
            foreach (var mesh in meshList)
            {
                AssetDatabase.AddObjectToAsset(mesh, prefabAsset);
                results[i].mesh = mesh;
                i++;
            }

            AssetDatabase.SaveAssets();

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

            // Map the mesh prefab to unique token
            PackageMapper.MapTokenToObject(entityToken, prefabAsset);
            PackageMapper.MapMeshToPrefab(meshList[0], prefabAsset);

            return(true);
        }