/// <summary> /// Prints relevant info about this node to the console including: /// <br/> /// /// </summary> /// <param name="node"></param> public static void PrintInfo(this UnityDisplayNode node) { var start = $"-------------Information about UnityDisplayNode {node.name}-------------"; MelonLogger.Msg(start); MelonLogger.Msg("Generic Renderers:"); for (var i = 0; i < node.genericRenderers.Count; i++) { var renderer = node.genericRenderers[i]; MelonLogger.Msg($" {i}. {renderer.name} ({renderer.GetIl2CppType().Name})"); } MelonLogger.Msg(""); MelonLogger.Msg("Generic Render Layers:"); for (var i = 0; i < node.genericRendererLayers.Count; i++) { var layer = node.genericRendererLayers[i]; MelonLogger.Msg($" {i}. {layer}"); } MelonLogger.Msg(""); MelonLogger.Msg("Component Hierarchy:"); node.gameObject.RecursivelyLog(); MelonLogger.Msg(new string('-', start.Length)); }
private static void SetupUDN(UnityDisplayNode udn, ModDisplay modDisplay, Action <UnityDisplayNode> onComplete) { udn.name = modDisplay.Id + "(Clone)"; udn.RecalculateGenericRenderers(); try { modDisplay.ModifyDisplayNode(udn); } catch (Exception e) { MelonLogger.Error($"Failed to modify DisplayNode for {modDisplay.Name}"); MelonLogger.Error(e); } try { if (modDisplay.Scale < 1f || modDisplay.Scale > 1f) { udn.transform.GetChild(0).transform.localScale = new Vector3(modDisplay.Scale, modDisplay.Scale, modDisplay.Scale); } } catch (Exception e) { MelonLogger.Error($"Failed to change scale for {modDisplay.Name}"); MelonLogger.Error(e); } udn.RecalculateGenericRenderers(); onComplete.Invoke(udn); ResourceHandler.Prefabs[modDisplay.Id] = udn; }
/// <summary> /// Gets all generic renderers of the specified type, recalculating the renderers if need be /// </summary> /// <param name="node">The UnityDisplayNode</param> /// <param name="recalculate">Whether to recalculate renderers</param> /// <typeparam name="T">The type of Renderer you're looking for</typeparam> /// <returns></returns> public static List <T> GetRenderers <T>(this UnityDisplayNode node, bool recalculate = true) where T : Renderer { if (node.genericRenderers == null) { return(new List <T>()); } if (recalculate && node.genericRenderers[0] == null) { node.RecalculateGenericRenderers(); } return(node.genericRenderers.GetItemsOfType <Renderer, T>().ToList()); }
/// <summary> /// Gets all renderers that are of type SkinnedMeshRenderer or MeshRenderer /// </summary> /// <param name="node"></param> /// <param name="recalculate"></param> /// <returns></returns> public static List <Renderer> GetMeshRenderers(this UnityDisplayNode node, bool recalculate = true) { if (node.genericRenderers == null) { return(new List <Renderer>()); } if (recalculate && node.genericRenderers[0] == null) { node.RecalculateGenericRenderers(); } return(node.genericRenderers.Where(nodeGenericRenderer => nodeGenericRenderer.IsType <SkinnedMeshRenderer>() || nodeGenericRenderer.IsType <MeshRenderer>()) .ToList()); }
/// <summary> /// Saves the texture used for this node's mesh renderer /// <br/> /// By default, this saves to local files, aka "C:\Users\...\AppData\LocalLow\Ninja Kiwi\BloonsTD6" /// </summary> /// <param name="node">The UnityDisplayNode</param> /// <param name="index"></param> /// <param name="path">Optional path to save to instead</param> public static void SaveMeshTexture(this UnityDisplayNode node, int index = 0, string path = null) { if (path == null) { path = FileIOUtil.GetSandboxPath() + node.name + index + ".png"; } var meshRenderers = node.GetMeshRenderers(); if (meshRenderers.Count == 0) { MelonLogger.Error("Can't save mesh texture because the node doesn't have any MeshRenderers or SkinnedMeshRenderers, you might want to call node.PrintInfo()"); } else if (meshRenderers.Count <= index) { MelonLogger.Error($"The node doesn't have {index} total mesh renderers, you might want to call node.PrintInfo()"); } else { meshRenderers[index].material.mainTexture.TrySaveToPNG(path); } }
public static void RemoveBone(this UnityDisplayNode unityDisplayNode, string boneName, bool alreadyUnbound = false) { var skinnedMeshRenderer = unityDisplayNode.GetRenderer <SkinnedMeshRenderer>(); if (!alreadyUnbound) { // Unbind the mesh so we can change it without affecting the original skinnedMeshRenderer.UnbindMesh(); } // Get the bone index that controls the Boomerang var boomerang = skinnedMeshRenderer.GetBoneIndex(boneName); // Get all vertices that the bone controls var badVertices = skinnedMeshRenderer.GetVerticesConnectedToBoneArray(boomerang); // Remove all triangles that contain any of those vertices var triangles = skinnedMeshRenderer.GetTrianglesAsArrays(); triangles.RemoveAll(triangle => triangle.Any(v => badVertices[v])); skinnedMeshRenderer.SetTriangles(triangles); }
/// <summary> /// Gets the first generic renderer of the specified type, recalculating the renderers if need be /// </summary> /// <param name="node">The UnityDisplayNode</param> /// <param name="recalculate">Whether to recalculate renderers</param> /// <typeparam name="T">The type of Renderer you're looking for</typeparam> public static T GetRenderer <T>(this UnityDisplayNode node, bool recalculate = true) where T : Renderer { return(node.GetRenderers <T>(recalculate) .OrderBy(renderer => renderer.name.StartsWith("FlatSkin") ? 0 : 1) .FirstOrDefault()); }
public static Transform GetBone(this UnityDisplayNode unityDisplayNode, string boneName) { return(unityDisplayNode.gameObject.GetComponentInChildrenByName <Transform>(boneName)); }
/// <summary> /// Alters the UnityDisplayNode that was copied from the one used by <see cref="ModDisplay.BaseDisplay"/> /// <br/> /// By default, this will change the main texture of the first SkinnedMeshRenderer of the node to that of a /// png with the same name as the class /// </summary> /// <param name="node">The UnityDisplayNode</param> public override void ModifyDisplayNode(UnityDisplayNode node) { SetMeshTexture(node, Name); }
public static void Process(string towername, UnityDisplayNode node) { var parent = node.transform; //make sure it only runs once if (parent.FindChild("processed") == null) { var proc = new GameObject("processed"); proc.transform.parent = parent; var towerlocation = towername + ".png"; var orig = filePath + "original/" + towerlocation; var custom = filePath + "custom/" + towerlocation; //Console.WriteLine("processing: " + towername); //create orig try { bool fileExists = true; if (!origFiles.TryGetValue(orig, out fileExists)) { origFiles.Add(orig, File.Exists(orig)); origFiles.TryGetValue(orig, out fileExists); } if (!fileExists) { //string counter = ""; foreach (Renderer renderer in node.genericRenderers) { try { var texture = renderer.material.mainTexture; File.WriteAllBytes(filePath + "original/" + towerlocation, ImageConversion.EncodeToPNG(makeReadable(texture))); break; } catch { } //counter += "_"; //renderer.material.mainTexture = FlipTexture(makeReadable(texture)); } //Console.WriteLine("dumped texture for: " + towername); } } catch (Exception e) { //Console.WriteLine("could not create orig: " + e.Message); } //read custom try { bool fileExists = true; if (!customFiles.TryGetValue(custom, out fileExists)) { customFiles.Add(custom, File.Exists(custom)); customFiles.TryGetValue(custom, out fileExists); } //Console.WriteLine("file for " + towername + "exists: " + fileExists); if (fileExists) { Texture2D tex; if (!customTexture.TryGetValue(custom, out tex)) { tex = new Texture2D(2, 2); //Console.WriteLine("loading custom texture for " + towername); ImageConversion.LoadImage(tex, File.ReadAllBytes(filePath + "custom/" + towerlocation)); //Console.WriteLine("adding to dict"); customTexture.Add(custom, tex); //Console.WriteLine("found custom texture for " + towername); } else { //Console.WriteLine("texture was cached"); } foreach (Renderer renderer in node.genericRenderers) { //Texture2D tex = new Texture2D(2, 2); //ImageConversion.LoadImage(tex, File.ReadAllBytes(filePath + "custom/" + towerlocation)); //Console.WriteLine("loaded custom texture for " + towername); renderer.material.mainTexture = tex; } } } catch (Exception e) { //Console.WriteLine("could not read custom texture: " + e.Message); } } }
/// <summary> /// (Cross-Game compatible) Get all 3D models attached to this UnityDisplayNode. /// </summary> /// <param name="unityDisplayNode"></param> /// <returns></returns> public static List <Transform> Get3DModels(this UnityDisplayNode unityDisplayNode) { return(unityDisplayNode.transform.parent.GetComponentsInChildren <Transform>().ToList()); }
/// <summary> /// Sets the sprite texture to that of a named png /// </summary> /// <param name="node">The UnityDisplayNode</param> /// <param name="textureName">The name of the texture, without .png</param> protected void Set2DTexture(UnityDisplayNode node, string textureName) { node.GetRenderer <SpriteRenderer>().sprite = GetSprite(textureName, PixelsPerUnit); }
/// <summary> /// Sets the mesh texture to that of a named png /// </summary> /// <param name="node">The UnityDisplayNode</param> /// <param name="textureName">The name of the texture, without .png</param> protected void SetMeshTexture(UnityDisplayNode node, string textureName, int index) { node.GetMeshRenderer(index).SetMainTexture(GetTexture(textureName)); }
/// <summary> /// Alters the UnityDisplayNode that was copied from the one used by <see cref="BaseDisplay"/> /// </summary> /// <param name="node"></param> public abstract void ModifyDisplayNode(UnityDisplayNode node);
/// <summary> /// Gets the first (or an indexed) SkinnedMeshRenderer/MeshRenderer /// </summary> /// <param name="node"></param> /// <param name="index"></param> /// <param name="recalculate"></param> /// <returns></returns> public static Renderer GetMeshRenderer(this UnityDisplayNode node, int index = 0, bool recalculate = true) { return(node.GetMeshRenderers()[index]); }
public override void ModifyDisplayNode(UnityDisplayNode node) { Set2DTexture(node, "boss"); }
/// <summary> /// Performs alterations to the unity display node when it is created /// </summary> /// <param name="node"></param> public override void ModifyDisplayNode(UnityDisplayNode node) { }