Hi needs some help to complete a project. I have a script that loads an object into a scene, I am currently using MRTK this is for Hololens Development. The object that is loaded is made up of subparts. I wanted to color each sub part in a different color (randomizing the color to each subpart differently). I wanted to press a button and this would randomize the colors on the loaded object. Here is my code :
// tlordmarshall@gmail.com
using System;
using System.Collections;
using System.Linq;
using System.IO;
using UnityEngine;
using Microsoft.MixedReality.Toolkit.UI;
using Microsoft.MixedReality.Toolkit.Experimental.UI;
using Microsoft.MixedReality.Toolkit.Utilities;
using TMPro;
using TriLib;
#if ENABLE_WINMD_SUPPORT
using System.Threading.Tasks;
using Windows.Storage;
#endif
#if UNITY_EDITOR
using UnityEditor;
#endif
#pragma warning disable 0649
namespace HololensProject {
public class HModelLoader : SingletonBehaviour<HModelLoader> {
[Header("UI")]
[SerializeField] private Transform m_content;
[SerializeField] private ScrollingObjectCollection m_scrollingCollection;
[SerializeField] private GameObject m_textButtonPrefab;
[SerializeField] private TextMeshPro m_currentPathTMP;
[SerializeField] private TextMeshPro m_errorTMP;
[Header("Model Load")]
[SerializeField] private ClippingPrimitive[] m_clippingPrimitives;
[SerializeField] private Transform m_modelLoadArea;
[SerializeField] private RuntimeAnimatorController m_runtimeAnimatorController;
[SerializeField] private GameObject m_modelComponentPrefab;
[Header("Material")]
[SerializeField] private bool m_useDefaultMaterial = true;
[SerializeField] private Shader m_mrtkShader;
[SerializeField] private Color m_defaultMaterialColor = Color.gray;
[SerializeField] private Color m_clippingBorderColor = Color.blue;
[SerializeField, HideInInspector]
private byte[] m_defaultModelData;
private Material m_defaultMaterial;
private static GameObject m_lastLoadedModel;
private static string[] m_directoryFiles;
void Awake() {
m_defaultMaterial = new Material(m_mrtkShader);
m_errorTMP.text = "";
m_content.gameObject.GetChilds().Destroy();
m_modelLoadArea.gameObject.GetChilds().Destroy();
m_scrollingCollection.UpdateCollection();
StartCoroutine(ListModels());
}
IEnumerator ListModels() {
yield return ReadModelPaths();
if (m_directoryFiles.Length == 0)
yield break;
for (var i = 0; i < m_directoryFiles.Length; i++) {
var button = Instantiate(m_textButtonPrefab, m_content).GetComponent<Interactable>();
var tmp = button.transform.Find("IconAndText/TextMeshPro").GetComponent<TextMeshPro>();
var filePath = m_directoryFiles*;*
tmp.text = Path.GetFileName(m_directoryFiles*);*
button.OnClick.AddListener(() => {
#if ENABLE_WINMD_SUPPORT
try {
Task.Run(async () => {
if (await StorageFile.GetFileFromPathAsync(filePath) != null)
Dispatcher.Invoke(() => LoadModel(filePath));
});
}
catch (Exception ex) {
m_errorTMP.text = $“Phase 2 error: {ex.Message}”;
}
#else
if (File.Exists(filePath))
LoadModel(filePath);
#endif
});
}
m_scrollingCollection.UpdateCollection();
}
IEnumerator ReadModelPaths() {
var loaded = false;
#if ENABLE_WINMD_SUPPORT
try {
var modelData = m_defaultModelData;
Task.Run(async () => {
var objects3DPath = await ApplicationData.Current.LocalFolder.CreateFolderAsync(“3D Objects”);
if (modelData.Length > 0 && await KnownFolders.Objects3D.TryGetItemAsync(“molecule_default.fbx”) == null) {
var defaultModel = await objects3DPath.CreateFileAsync(“molecule_default.fbx”);
await FileIO.WriteBytesAsync(defaultModel, modelData);
}
var allModels = await KnownFolders.Objects3D.GetFilesAsync();
foreach (var file in allModels)
await file.CopyAsync(objects3DPath);
allModels = await objects3DPath.GetFilesAsync();
Dispatcher.Invoke(() => {
m_currentPathTMP.text = objects3DPath.Path.Replace(@"", “/”);
m_directoryFiles = allModels.Where(f => f.FileType.ToLower() == “.fbx”).Select(f => f.Path).ToArray();
});
});
}
catch (Exception ex) {
m_errorTMP.text = $“Phase 1 error: {ex.Message}”;
}
#else
var userPath = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)).Parent.Parent.FullName;
var objects3DPath = Path.Combine(userPath, “3D Objects”);
Directory.CreateDirectory(objects3DPath);
if (m_defaultModelData.Length > 0 && !File.Exists(objects3DPath + “/molecule_default.fbx”))
File.WriteAllBytes(objects3DPath + “/molecule_default.fbx”, m_defaultModelData);
m_currentPathTMP.text = objects3DPath.Replace(@"", “/”);
m_directoryFiles = new DirectoryInfo(objects3DPath).GetFiles().Where(f => f.Extension.ToLower() == “.fbx”).Select(f => f.FullName).ToArray();
loaded = true;
#endif
while (!loaded)
yield return null;
}
Material GetMaterial(Renderer renderer)
=> m_useDefaultMaterial && m_defaultMaterial ?
m_defaultMaterial :
new Material(m_mrtkShader) { mainTexture = renderer.material.mainTexture, color = renderer.material.color };
///
/// Load FBX model at specified path.
///
///
public static void LoadModel(string modelPath) {
try {
using (var assetLoaderAsync = new AssetLoaderAsync()) {
var assetLoaderOptions = AssetLoaderOptions.CreateInstance();
assetLoaderOptions.UseOriginalPositionRotationAndScale = true;
assetLoaderOptions.UseLegacyAnimations = false;
assetLoaderOptions.AnimatorController = Instance.m_runtimeAnimatorController;
var thread = assetLoaderAsync.LoadFromFile(modelPath, assetLoaderOptions, null, delegate (GameObject tempLoadedModel) {
if (m_lastLoadedModel)
Destroy(m_lastLoadedModel);
m_lastLoadedModel = Instantiate(Instance.m_modelComponentPrefab);
m_lastLoadedModel.name = Path.GetFileNameWithoutExtension(modelPath);
tempLoadedModel.transform.localEulerAngles = Vector3.zero;
var renderers = tempLoadedModel.GetComponentsInChildren();
foreach (var renderer in renderers) {
renderer.transform.SetParent(m_lastLoadedModel.transform);
renderer.material = Instance.GetMaterial(renderer);
if (!renderer.material)
continue;
renderer.material.SetFloat(“_ClippingBorder”, 1);
renderer.material.SetColor(“_ClippingBorderColor”, Instance.m_clippingBorderColor);
if (Instance.m_useDefaultMaterial)
renderer.material.color = Instance.m_defaultMaterialColor;
}
if (renderers.FirstOrDefault() is SkinnedMeshRenderer smr)
smr.bones[0].SetParent(m_lastLoadedModel.transform);
foreach (var clipping in Instance.m_clippingPrimitives) {
clipping.ClearRenderers();
foreach (var renderer in renderers)
clipping.AddRenderer(renderer);
}
ChildMeshToggler.ListMeshes(m_lastLoadedModel);
m_lastLoadedModel.transform.position = Instance.m_modelLoadArea.position;
m_lastLoadedModel.transform.SetParent(Instance.m_modelLoadArea);
m_lastLoadedModel.GetComponent().FitToChildren();
Destroy(tempLoadedModel.gameObject);
});
}
}
catch {
Debug.LogWarning("Unable to load fbx model at: " + modelPath);
}
}
#if UNITY_EDITOR
[Header(“Editor”)]
[SerializeField] private GameObject m_defaultTestModel;
void OnValidate() {
if (m_defaultTestModel && (null != m_defaultModelData || m_defaultModelData.Length == 0)) {
var modelPath = AssetDatabase.GetAssetPath(m_defaultTestModel);
if (!string.IsNullOrEmpty(modelPath))
m_defaultModelData = File.ReadAllBytes(modelPath);
}
if (!m_defaultTestModel && m_defaultModelData.Length > 0)
m_defaultModelData = null;
}
#endif
}
}