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(); } } }
/// <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); }
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(); }
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); }
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(); }
/// <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, ""); }
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); }
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); }