/// <summary> /// 移除Material Editor資料 /// </summary> /// <param name="targetChaCtrl"></param> /// <param name="targetSlot"></param> /// <param name="gameObject">對象GameObject</param> /// <param name="objectType">對象分類</param> public static void RemoveMaterialEditorData(ChaControl targetChaCtrl, int targetSlot, GameObject gameObject, ObjectType objectType) { if (GameObjectTypeCheck(gameObject, objectType)) { return; } if (targetChaCtrl != MaterialEditor_Support.targetChaCtrl) { GetControllerAndBackupData(targetChaCtrl: targetChaCtrl); } //是否有執行到 bool doFlag = false; for (int i = 0; i < storedValueInfos.Length; i++) { bool doFlag2 = false; StoredValueInfo storedValue = storedValueInfos[i]; object target = TargetMaterialBackup[storedValue.listName].ToListWithoutType(); //移除 object objRemoved = target.Where((x) => (int)x.GetField("ObjectType") == (int)objectType && (int)x.GetField("CoordinateIndex") == targetChaCtrl.fileStatus.coordinateType && (int)x.GetField("Slot") == targetSlot ).ForEach((x) => { if (null == x) { return; } doFlag2 = true; Renderer r = null; Material m = null; if (i == 1) { r = Extension.Extension.InvokeStatic(MaterialAPI, "GetRendererList", new object[] { gameObject })?.ToList <Renderer>().Where(y => y.name == (string)x.GetField("RendererName"))?.FirstOrDefault(); if (r == null) { doFlag2 = false; return; } } else { m = Extension.Extension.InvokeStatic(MaterialAPI, "GetMaterials", new object[] { gameObject, (string)x.GetField("MaterialName") })?.ToList <Material>()?.FirstOrDefault(); if (m == null) { doFlag2 = false; return; } } switch (i) { case 0: //MaterialShader TargetMaterialEditorController.Invoke(storedValue.removeFunctionName, new object[] { targetSlot, m, gameObject, true }); if (null != x.GetField("RenderQueueOriginal")) { TargetMaterialEditorController.Invoke("RemoveMaterialShaderRenderQueue", new object[] { targetSlot, m, gameObject, true }); } break; case 1: //RendererProperty TargetMaterialEditorController.Invoke(storedValue.removeFunctionName, new object[] { targetSlot, r, x.GetField("Property"), gameObject, true }); break; case 2: //MaterialFloatProperty case 3: //MaterialColorProperty TargetMaterialEditorController.Invoke(storedValue.removeFunctionName, new object[] { targetSlot, m, x.GetField("Property"), gameObject, true }); break; case 4: //MaterialTexture TargetMaterialEditorController.Invoke(storedValue.removeFunctionName, new object[] { targetSlot, m, x.GetField("Property"), gameObject, false }); break; } }); if (doFlag2) { if (objRemoved.Count() > 0) { GetExtDataFromController(targetChaCtrl, out TargetMaterialBackup, out TargetTextureDictionaryBackup); Logger.LogDebug($"--->Remove {objRemoved.Count()} {storedValue.className}"); } } doFlag |= doFlag2; } if (objectType == ObjectType.Accessory) { if (doFlag) { Logger.LogDebug($"-->Remove Material Editor Data: {targetChaCtrl.fileParam.fullname} Slot{targetSlot}"); } else { Logger.LogDebug($"-->No Material Editor Backup to remove: {targetChaCtrl.fileParam.fullname} Slot{targetSlot}"); } } else if (objectType == ObjectType.Clothing) { if (doFlag) { Logger.LogDebug($"-->Remove Material Editor Data: {targetChaCtrl.fileParam.fullname} {Enum.GetName(typeof(ChaFileDefine.ClothesKind), targetSlot)}"); } else { Logger.LogDebug($"-->No Material Editor Backup to remove: {targetChaCtrl.fileParam.fullname} {Enum.GetName(typeof(ChaFileDefine.ClothesKind), targetSlot)}"); } } }
/// <summary> /// 寫入Material Editor資料 /// </summary> /// <param name="sourceChaCtrl"></param> /// <param name="sourceSlot"></param> /// <param name="targetChaCtrl"></param> /// <param name="targetSlot"></param> /// <param name="gameObject">對象GameObject</param> /// <param name="objectType">對象分類</param> private static void SetMaterialEditorData(ChaControl sourceChaCtrl, int sourceSlot, ChaControl targetChaCtrl, int targetSlot, GameObject gameObject, ObjectType objectType) { if (sourceChaCtrl != MaterialEditor_Support.sourceChaCtrl || targetChaCtrl != MaterialEditor_Support.targetChaCtrl) { GetControllerAndBackupData(sourceChaCtrl, targetChaCtrl); } //是否有執行到 bool doFlag = false; for (int i = 0; i < storedValueInfos.Length; i++) { bool doFlag2 = false; StoredValueInfo storedValue = storedValueInfos[i]; object target = TargetMaterialBackup[storedValue.listName].ToListWithoutType(); //加入 object objAdded = SourceMaterialBackup[storedValue.listName].ToListWithoutType().Where(x => (int)x.GetField("ObjectType") == (int)objectType && (int)x.GetField("CoordinateIndex") == sourceChaCtrl.fileStatus.coordinateType && (int)x.GetField("Slot") == sourceSlot ).ForEach((x) => { doFlag2 = true; Renderer r = null; Material m = null; if (i == 1) { r = Extension.Extension.InvokeStatic(MaterialAPI, "GetRendererList", new object[] { gameObject })?.ToList <Renderer>().Where(y => y.name == (string)x.GetField("RendererName"))?.FirstOrDefault(); if (r == null) { Logger.LogWarning($"Missing Renderer: {(string)x.GetField("RendererName")}!"); doFlag2 = false; return; } } else { m = Extension.Extension.InvokeStatic(MaterialAPI, "GetMaterials", new object[] { gameObject, (string)x.GetField("MaterialName") })?.ToList <Material>()?.FirstOrDefault(); if (m == null) { Logger.LogWarning($"Missing Material: {(string)x.GetField("MaterialName")}!"); doFlag2 = false; return; } } switch (i) { case 0: //MaterialShader TargetMaterialEditorController.Invoke(storedValue.setFunctionName, new object[] { targetSlot, m, x.GetField("ShaderName"), gameObject, true }); if (null != x.GetField("RenderQueueOriginal")) { TargetMaterialEditorController.Invoke("SetMaterialShaderRenderQueue", new object[] { targetSlot, m, x.GetField("RenderQueue"), gameObject, true }); } break; case 1: //RendererProperty TargetMaterialEditorController.Invoke(storedValue.setFunctionName, new object[] { targetSlot, r, x.GetField("Property"), x.GetField("Value"), gameObject, true }); break; case 2: //MaterialFloatProperty TargetMaterialEditorController.Invoke(storedValue.setFunctionName, new object[] { targetSlot, m, x.GetField("Property"), (float)Convert.ToDouble(x.GetField("Value")), gameObject, true }); break; case 3: //MaterialColorProperty TargetMaterialEditorController.Invoke(storedValue.setFunctionName, new object[] { targetSlot, m, x.GetField("Property"), x.GetField("Value"), gameObject, true }); break; case 4: //MaterialTextureProperty //Texture int?texID = (int?)x.GetField("TexID"); if (texID.HasValue && SourceTextureDictionaryBackup.TryGetValue(texID.Value, out object textureHolder) && textureHolder.GetProperty("Data") is byte[] BA) { string tempPath = Path.Combine(CacheDirectory.FullName, DateTime.UtcNow.Ticks + "_" + texID); File.WriteAllBytes(tempPath, BA); TargetMaterialEditorController.Invoke("SetMaterialTextureFromFile", new object[] { targetSlot, m, x.GetField("Property"), tempPath, gameObject, false }); File.Delete(tempPath); //Offset if (null != x.GetField("OffsetOriginal")) { TargetMaterialEditorController.Invoke("SetMaterialTextureOffset", new object[] { targetSlot, m, x.GetField("Property"), x.GetField("Offset"), gameObject, true }); } //Scale if (null != x.GetField("ScaleOriginal")) { TargetMaterialEditorController.Invoke("SetMaterialTextureScale", new object[] { targetSlot, m, x.GetField("Property"), x.GetField("Scale"), gameObject, true }); } } break; } }); if (doFlag2) { if (objAdded.Count() > 0) { GetExtDataFromController(targetChaCtrl, out TargetMaterialBackup, out TargetTextureDictionaryBackup); Logger.LogDebug($"--->Change {objAdded.Count()} {storedValue.className}"); } } doFlag |= doFlag2; } if (objectType == ObjectType.Accessory) { if (doFlag) { Logger.LogDebug($"-->Set Material Editor Data: {sourceChaCtrl.fileParam.fullname} Slot{sourceSlot} -> {targetChaCtrl.fileParam.fullname} Slot{targetSlot}"); } else { Logger.LogDebug($"-->No Material Editor Backup to set: {sourceChaCtrl.fileParam.fullname} {sourceSlot}"); } } else if (objectType == ObjectType.Clothing) { if (doFlag) { Logger.LogDebug($"-->Set Material Editor Data: {sourceChaCtrl.fileParam.fullname} {Enum.GetName(typeof(ChaFileDefine.ClothesKind), sourceSlot)} -> {targetChaCtrl.fileParam.fullname} {Enum.GetName(typeof(ChaFileDefine.ClothesKind), targetSlot)}"); } else { Logger.LogDebug($"-->No Material Editor Backup to set: {sourceChaCtrl.fileParam.fullname} {Enum.GetName(typeof(ChaFileDefine.ClothesKind), sourceSlot)}"); } } }
/// <summary> /// 將給入的Material Data Backup儲存至ChaControl之Controller內 /// </summary> /// <param name="chaCtrl">目標ChaControl</param> /// <param name="objectType">類型</param> /// <param name="MaterialBackup">要存入的Material Data Backup</param> /// <param name="Slot">Coordinate ClothesKind 或 Accessory Slot</param> public static void SetToController(ChaControl chaCtrl, ObjectType objectType, Dictionary <string, object> MaterialBackup = null, int Slot = -1) { Predicate <object> predicate = new Predicate <object>(x => (int)x.GetField("ObjectType") == (int)objectType && (int)x.GetField("CoordinateIndex") == chaCtrl.fileStatus.coordinateType && //若Slot有給入,則加上檢查Slot的判斷 (Slot < 0) ? true : (int)x.GetField("Slot") == Slot ); //是否有執行到 bool doFlag = false; MonoBehaviour MaterialEditorController; if (null == MaterialBackup) { MaterialEditorController = GetExtDataFromController(chaCtrl, out Dictionary <string, object> m, out Dictionary <int, object> _); if (null == MaterialBackup) { MaterialBackup = m; } } else { MaterialEditorController = chaCtrl.GetComponents <MonoBehaviour>().FirstOrDefault(x => Equals(x.GetType().Name, "MaterialEditorCharaController")); } if (null != MaterialEditorController && null != MaterialBackup) { for (int i = 0; i < storedValueInfos.Length; i++) { StoredValueInfo storedValue = storedValueInfos[i]; bool doFlag2 = false; object target = MaterialEditorController.GetField(storedValue.listName).ToListWithoutType(); //移除 doFlag2 = target.RemoveAll(predicate) > 0; //加回 object obj2Add = MaterialBackup[storedValue.listName].Where(predicate); if (obj2Add.Count() > 0) { doFlag2 = true; target.AddRange(obj2Add); } if (doFlag2) { MaterialEditorController.SetField(storedValue.listName, target); GetExtDataFromController(chaCtrl, out Dictionary <string, object> m, out Dictionary <int, object> t); Logger.LogDebug($"--->{storedValue.className}: {m[storedValue.listName].Count()}"); } doFlag |= doFlag2; } if (doFlag) { if (objectType == ObjectType.Clothing) { Logger.LogDebug($"-->Material Set: Clothes " + ((Slot >= 0) ? $", {Patches.ClothesKindName[Slot]}" : ", All Clothes")); } else if (objectType == ObjectType.Accessory) { Logger.LogDebug($"-->Material Set: Accessory" + ((Slot >= 0) ? ", Slot " + Slot : ", All Slots")); } } } }