/// <summary> /// Sets the shader and properties to the input material /// </summary> /// <param name="material"></param> public void apply(Material material) { material.shader = TexturesUnlimitedLoader.getShader(shader); TextureSet.updateMaterialProperties(material, shaderProperties); TextureSet.fillEmptyStockTextureSlots(material); material.renderQueue = TexturesUnlimitedLoader.isTransparentMaterial(material) ? TexturesUnlimitedLoader.transparentTextureRenderQueue : TexturesUnlimitedLoader.diffuseTextureRenderQueue; }
/// <summary> /// Apply the current recoloring selections to the input transform. Does not recreate material, but simply applies the properties to the current material. /// </summary> /// <param name="root"></param> /// <param name="userColors"></param> public void applyRecoloring(Transform root, RecoloringData[] userColors) { TextureSet set = currentTextureSet; if (set == null) { return; } set.applyRecoloring(root, userColors); }
public Material createMaterial(string name) { string shdName = string.IsNullOrEmpty(this.shader) ? "KSP/Diffuse" : this.shader; Shader shd = KSPShaderLoader.getShader(shdName); Material mat = new Material(shd); mat.name = name; TextureSet.updateMaterialProperties(mat, props); return(mat); }
/// <summary> /// Applies any 'KSP_MODEL_SHADER' definitions to models in the GameDatabase.loadedModels list. /// </summary> private static void applyToModelDatabase() { ConfigNode[] modelShaderNodes = GameDatabase.Instance.GetConfigNodes("KSP_MODEL_SHADER"); TextureSet set = null; ConfigNode textureNode; string setName = ""; int len = modelShaderNodes.Length; string[] modelNames; GameObject model; for (int i = 0; i < len; i++) { textureNode = modelShaderNodes[i]; if (textureNode.HasNode("MATERIAL")) { set = new TextureSet(textureNode, "update"); setName = set.name; } else if (textureNode.HasNode("TEXTURE"))//legacy style definitions { set = new TextureSet(textureNode, "update"); setName = set.name; } else if (textureNode.HasValue("textureSet")) { setName = textureNode.GetStringValue("textureSet"); set = getTextureSet(setName); if (set == null) { Log.exception("ERROR: Did not locate texture set from global cache for input name: " + setName + " while applying KSP_MODEL_SHADER with name of: " + modelShaderNodes[i].GetStringValue("name", "UNKNOWN")); continue; } } if (!string.IsNullOrEmpty(setName) && !loadedModelShaderSets.ContainsKey(setName)) { loadedModelShaderSets.Add(setName, set); } modelNames = textureNode.GetStringValues("model"); int len2 = modelNames.Length; for (int k = 0; k < len2; k++) { model = GameDatabase.Instance.GetModelPrefab(modelNames[k]); if (model != null) { Log.replacement("TexturesUnlimited -- Replacing textures on database model: " + modelNames[k]); set.enable(model.transform, set.maskColors); } else { Log.exception("ERROR: Could not locate model: " + modelNames[k] + " while applying KSP_MODEL_SHADER with name of: " + modelShaderNodes[i].GetStringValue("name", "UNKNOWN")); } } } }
/// <summary> /// Return an array of texture sets for the values from within the input string array. Returns an empty array if none are found. /// </summary> /// <param name="setNodes"></param> /// <returns></returns> public static TextureSet[] getTextureSets(string[] setNames) { int len = setNames.Length; TextureSet[] sets = new TextureSet[len]; for (int i = 0; i < len; i++) { sets[i] = getTextureSet(setNames[i]); } return(sets); }
/// <summary> /// Public utility method to parse texture set instances from config nodes. /// </summary> /// <param name="nodes"></param> /// <returns></returns> public static TextureSet[] parse(ConfigNode[] nodes) { int len = nodes.Length; TextureSet[] sets = new TextureSet[len]; for (int i = 0; i < len; i++) { sets[i] = new TextureSet(nodes[i]); } return(sets); }
private static void loadTextureSets() { ConfigNode[] setNodes = GameDatabase.Instance.GetConfigNodes("KSP_TEXTURE_SET"); TextureSet[] sets = TextureSet.parse(setNodes); int len = sets.Length; for (int i = 0; i < len; i++) { loadedTextureSets.Add(sets[i].name, sets[i]); } }
public static TextureSet getTextureSet(string name) { TextureSet s = null; if (loadedTextureSets.TryGetValue(name, out s)) { return(s); } MonoBehaviour.print("ERROR: Could not locate texture set for name: " + name); return(null); }
public static TextureSet[] getTextureSets(ConfigNode[] setNodes) { int len = setNodes.Length; TextureSet[] sets = new TextureSet[len]; for (int i = 0; i < len; i++) { sets[i] = getTextureSet(setNodes[i].GetStringValue("name")); } return(sets); }
/// <summary> /// Find a global texture set from database with a name that matches the input name. Returns null if not found. /// </summary> /// <param name="name"></param> /// <returns></returns> public static TextureSet getTextureSet(string name) { TextureSet s = null; if (loadedTextureSets.TryGetValue(name, out s)) { return(s); } Log.exception("ERROR: Could not locate TextureSet from global cache for the input name of: " + name); return(null); }
/// <summary> /// Return a new material instances instatiated with the shader and properties for this material data. /// Does not include applying any recoloring data -- that needs to be handled externally. /// </summary> /// <returns></returns> public Material createMaterial() { if (string.IsNullOrEmpty(this.shader)) { //TODO -- include texture set name somehow... throw new NullReferenceException("ERROR: No shader specified for texture set."); } Shader shader = TexturesUnlimitedLoader.getShader(this.shader); Material material = new Material(shader); TextureSet.updateMaterialProperties(material, shaderProperties); material.renderQueue = TexturesUnlimitedLoader.isTransparentMaterial(material) ? TexturesUnlimitedLoader.transparentTextureRenderQueue : TexturesUnlimitedLoader.diffuseTextureRenderQueue; return(material); }
/// <summary> /// Applies this texture set to the input root transform, using the specified inclusions/exclusions from config. /// Does not update any recoloring data. Must also call 'applyRecoloring' in order to update recoloring properties. /// </summary> /// <param name="root"></param> /// <param name="userColors"></param> public void enable(Transform root, bool isIcon = false) { bool updateMode = string.Equals(mode, "update", StringComparison.CurrentCultureIgnoreCase); Transform[] trs = TextureSet.findApplicableTransforms(root, meshNames, excludedMeshes); int len = trs.Length; Renderer render; Log.debug("enabling TSMD.." + root + " updateMode: " + updateMode); if (updateMode) { Material material; for (int i = 0; i < len; i++) { render = trs[i].GetComponent <Renderer>(); if (render != null) { material = render.material; apply(material, isIcon); render.material = material; } } } else//create mode - creates new materials for renders to use, applying only those properties specified in the texture set, with optional inheritance of properties from the old material { Material newMaterial = createMaterial();//create a new material for this TSMD Material origMaterial = null; for (int i = 0; i < len; i++) { render = trs[i].GetComponent <Renderer>(); if (render != null) { //only inherit properties a single time, from the first render/transform/material found if (origMaterial == null) { origMaterial = render.sharedMaterial; if (origMaterial != null) { //if there was no shared material, this will be null; //TODO -- use std material ref if no shared mat exists? newMaterial.name = origMaterial.name; inheritProperties(newMaterial, origMaterial); } } render.sharedMaterial = newMaterial; Log.replacement("Updated material properties on transform: " + trs[i].name + "\n" + Debug.getMaterialPropertiesDebug(newMaterial)); } } } }
private void applyConfig(Transform root, TextureSet set, bool useSetColors, bool useIconShaders = false) { if (set == null) { return; } RecoloringData[] colors = useSetColors? set.maskColors : customColors; if (useSetColors) { customColors = set.maskColors; saveColors(customColors); } //apply the texture set to the base model (and trusses?) set.enable(root, colors, useIconShaders); if (stockFairing) { TextureSetMaterialData tsmd = set.textureData[0]; //adjust the already existing fairing materials and fairing panels ModuleProceduralFairing mpf = part.GetComponent <ModuleProceduralFairing>(); if (mpf != null) { Material mat; if (mpf.FairingMaterial != null && mpf.FairingConeMaterial != null) { mat = mpf.FairingMaterial; tsmd.apply(mat, useIconShaders); tsmd.applyRecoloring(mat, colors); mat = mpf.FairingConeMaterial; tsmd.apply(mat, useIconShaders); tsmd.applyRecoloring(mat, colors); } if (mpf.Panels != null && mpf.Panels.Count > 0)//cones are included in regular panels { int len = mpf.Panels.Count; for (int i = 0; i < len; i++) { mat = mpf.Panels[i].mat; tsmd.apply(mat, useIconShaders); tsmd.applyRecoloring(mat, colors); mat = mpf.Panels[i].go.GetComponent <Renderer>().material; tsmd.apply(mat, useIconShaders); tsmd.applyRecoloring(mat, colors); } } } } }
//really, could probably just move this back to the base class, possibly with a config bool for toggling enable of the secondary updates public void Start() { TextureSet ts = TexturesUnlimitedLoader.getTextureSet(textureSet); if (ts != null) { //apply the textur set to the base model, use set-specified mask colors (does not support user recoloring) ts.enable(part.transform.FindRecursive("model"), ts.maskColors); TextureSetMaterialData tsmd = ts.textureData[materialIndex]; //adjust the already existing fairing materials and fairing panels ModuleProceduralFairing mpf = part.GetComponent <ModuleProceduralFairing>(); if (mpf != null) { if (mpf.FairingMaterial != null && mpf.FairingConeMaterial != null) { tsmd.apply(mpf.FairingMaterial); tsmd.apply(mpf.FairingConeMaterial); } if (mpf.Panels != null && mpf.Panels.Count > 0)//cones are included in regular panels { int len = mpf.Panels.Count; for (int i = 0; i < len; i++) { tsmd.apply(mpf.Panels[i].mat); tsmd.apply(mpf.Panels[i].go.GetComponent <Renderer>().material); } } } } //prev shader-only code... //Shader shader = TexturesUnlimitedLoader.getShader(this.shader); //if (mpf != null && shader != null && mpf.FairingMaterial != null) //{ // mpf.FairingMaterial.shader = shader; // if (mpf.FairingConeMaterial != null) { mpf.FairingConeMaterial.shader = shader; } // MonoBehaviour.print("Adjusted MPF materials!"); // if (mpf.Panels != null && mpf.Panels.Count > 0)//cones are included in regular panels // { // int len = mpf.Panels.Count; // for (int i = 0; i < len; i++) // { // mpf.Panels[i].mat.shader = shader; // mpf.Panels[i].go.GetComponent<Renderer>().material.shader = shader; // } // } //} }
/// <summary> /// Sets the shader and properties to the input material /// </summary> /// <param name="material"></param> public void apply(Material material, bool isIcon = false) { if (isIcon) { material.shader = TexturesUnlimitedLoader.iconShaders[shader].iconShader; } else { material.shader = TexturesUnlimitedLoader.getShader(shader); } TextureSet.updateMaterialProperties(material, shaderProperties); TextureSet.fillEmptyStockTextureSlots(material); material.renderQueue = renderQueue; material.mainTextureOffset = textureOffset; material.mainTextureScale = textureScale; Log.replacement("Updated material properties\n" + Debug.getMaterialPropertiesDebug(material)); }
/// <summary> /// Applies any 'KSP_MODEL_SHADER' definitions to models in the GameDatabase.loadedModels list. /// </summary> private static void applyToModelDatabase() { ConfigNode[] modelShaderNodes = GameDatabase.Instance.GetConfigNodes("KSP_MODEL_SHADER"); TextureSet set = null; ConfigNode textureNode; string setName; int len = modelShaderNodes.Length; string[] modelNames; GameObject model; for (int i = 0; i < len; i++) { textureNode = modelShaderNodes[i]; if (textureNode.HasNode("MATERIAL")) { set = new TextureSet(textureNode); setName = set.name; } else if (textureNode.HasNode("TEXTURE"))//legacy style definitions { set = new TextureSet(textureNode); setName = set.name; } else if (textureNode.HasValue("textureSet")) { setName = textureNode.GetStringValue("textureSet"); set = getTextureSet(setName); } modelNames = textureNode.GetStringValues("model"); int len2 = modelNames.Length; for (int k = 0; k < len2; k++) { model = GameDatabase.Instance.GetModelPrefab(modelNames[k]); if (model != null) { if (logReplacements) { MonoBehaviour.print("TexturesUnlimited -- Replacing textures on database model: " + modelNames[k]); } set.enable(model.transform, set.maskColors); } } } }
/// <summary> /// Apply the current texture to the input transform. The texture sets include/exclude settings will be used to determine what children of the input transforms should be adjusted. /// </summary> /// <param name="root"></param> public void enableCurrentSet(Transform root) { TextureSet set = currentTextureSet; if (set == null) { MonoBehaviour.print("ERROR: KSPTextureSwitch could not locate texture set for name: " + currentTextureSetName); } if (customColors == null || customColors.Length == 0) { customColors = new RecoloringData[3]; customColors[0] = set.maskColors[0]; customColors[1] = set.maskColors[1]; customColors[2] = set.maskColors[2]; } set.enable(root, customColors); saveColors(customColors); }
public readonly string mode;//ghetto enum - 'update' or 'create' are the only valid values public TextureSetMaterialData(TextureSet owner, ConfigNode node, string defaultMode) { this.owner = owner; shader = node.GetStringValue("shader"); meshNames = node.GetStringValues("mesh"); excludedMeshes = node.GetStringValues("excludeMesh"); shaderProperties = ShaderProperty.parse(node); inheritedTex = node.GetStringValues("inheritTexture"); inheritedFloat = node.GetStringValues("inheritFloat"); inheritedColor = node.GetStringValues("inheritColor"); if (!node.HasValue("mode")) { Log.error("TextureSet: " + owner.name + " did not have definition for mode (create/update). Using default value of: " + defaultMode + ". This may not function as desired, and may need to be corrected in the configuration file."); } mode = node.GetStringValue("mode", defaultMode); renderQueue = node.GetIntValue("renderQueue", (TexturesUnlimitedLoader.isTransparentShader(shader)? (int)RenderQueue.Transparent : (int)RenderQueue.Geometry)); textureScale = node.GetVector2("textureScale", Vector2.one); textureOffset = node.GetVector2("textureOffset", Vector2.zero); }
private void init() { if (initialized) { return; } initialized = true; loadPersistentData(persistentData); if (applied == null) { //TODO only subscribe based on scene? GameEvents.onVariantApplied.Add(applied = new EventData <Part, PartVariant> .OnEvent(variantApplied)); GameEvents.onEditorVariantApplied.Add(editorApplied = new EventData <Part, PartVariant> .OnEvent(editorVariantApplied)); GameEvents.onEditorDefaultVariantChanged.Add(editorDefaultApplied = new EventData <AvailablePart, PartVariant> .OnEvent(editorDefaultVariantApplied)); } //application of the initial/default texture set should be handled by onVariantApplied being called when the base variant is applied? //.... but apparently is not //so find the last used or default set and apply it TextureSet set = null; //check 'last used set' names if (string.IsNullOrEmpty(textureSet) && string.IsNullOrEmpty(modelShaderSet)) { //if both are empty, module is uninitialized; query part for base variant, find extra-info, and find texture set from there set = getSet(part.baseVariant); } else { //else module previously had a texture set used, restore the texture-set instance from that value set = getSet(); } if (set != null) { //TODO -- will icon shaders ever be needed here? applyConfig(part.transform.FindRecursive("model"), set, false, false); } else { MonoBehaviour.print("ERROR: TUPartVariant could not locate default or stored texture set data"); } }
/// <summary> /// Applies this texture set to the input root transform, using the specified inclusions/exclusions from config. /// Does not update any recoloring data. Must also call 'applyRecoloring' in order to update recoloring properties. /// </summary> /// <param name="root"></param> /// <param name="userColors"></param> public void enable(Transform root) { bool updateMode = string.Equals(mode, "update", StringComparison.CurrentCultureIgnoreCase); Transform[] trs = TextureSet.findApplicableTransforms(root, meshNames, excludedMeshes); int len = trs.Length; Renderer render; if (updateMode) { Material material; for (int i = 0; i < len; i++) { render = trs[i].GetComponent <Renderer>(); if (render != null) { material = render.material; apply(material); render.material = material; } } } else//create mode - creates new materials for renders to use, applying only those properties specified in the texture set, with optional inheritance of properties from the old material { Material newMaterial = createMaterial();//create a new material for this TSMD Material origMaterial = null; for (int i = 0; i < len; i++) { render = trs[i].GetComponent <Renderer>(); if (render != null) { //only inherit properties a single time, from the first render/transform/material found if (origMaterial == null) { origMaterial = render.sharedMaterial; inheritProperties(newMaterial, origMaterial); } render.sharedMaterial = newMaterial; } } } }
/// <summary> /// Restores texture set data and either loads default texture set or saved texture set (if any) /// </summary> private void initialize() { if (textureSets != null) { //already initialized from OnLoad (prefab, some in-editor parts) return; } ConfigNode node = Utils.parseConfigNode(configNodeData); string[] setNames = node.GetStringValues("textureSet", false); string modelShaderName = node.GetStringValue("modelShader"); List <TextureSet> allSets = new List <TextureSet>(); if (!string.IsNullOrEmpty(modelShaderName)) { TextureSet set = TexturesUnlimitedLoader.getModelShaderTextureSet(modelShaderName); if (set != null) { allSets.Add(set); } } TextureSet[] sets = TexturesUnlimitedLoader.getTextureSets(setNames); for (int i = 0; i < sets.Length; i++) { allSets.Add(sets[i]); } ConfigNode[] fullNodeSets = node.GetNodes("KSP_TEXTURE_SET"); for (int i = 0; i < fullNodeSets.Length; i++) { allSets.Add(new TextureSet(fullNodeSets[i], "create")); } textureSets = new TextureSetContainer(this, Fields[nameof(currentTextureSet)], Fields[nameof(persistentData)], allSets); if (string.IsNullOrEmpty(currentTextureSet)) { currentTextureSet = allSets[0].name; } this.updateUIChooseOptionControl(nameof(currentTextureSet), textureSets.getTextureSetNames(), textureSets.getTextureSetTitles(), true, currentTextureSet); textureSets.enableCurrentSet(getModelTransforms(), false); Fields[nameof(currentTextureSet)].guiName = sectionName; }
private static void loadTextureSets() { loadedTextureSets.Clear(); ConfigNode[] setNodes = GameDatabase.Instance.GetConfigNodes("KSP_TEXTURE_SET"); TextureSet[] sets = TextureSet.parse(setNodes, "create"); int len = sets.Length; for (int i = 0; i < len; i++) { if (loadedTextureSets.ContainsKey(sets[i].name)) { Log.exception("ERROR: Duplicate texture set definition found for name: " + sets[i].name + " This is a major configuration error that should be corrected. Correct operation cannot be ensured."); } else { loadedTextureSets.Add(sets[i].name, sets[i]); } } }
public SectionRecolorData(IRecolorable owner, string name, RecoloringData[] colors, TextureSet set) { this.owner = owner; this.sectionName = name; this.colors = colors; this.sectionTexture = set; if (colors == null) { //owners may return null for set and/or colors if recoloring is unsupported set = sectionTexture = null; } //MonoBehaviour.print("Created section recolor data with texture set: " + set+" for section: "+name); if (set != null) { //MonoBehaviour.print("Set name: " + set.name + " :: " + set.title + " recolorable: " + set.supportsRecoloring); } else { MonoBehaviour.print("Set was null"); } }
private void editorVariantApplied(Part part, PartVariant variant) { if (part != this.part) { return; } bool resetColors = variant.Name != variantName; variantName = variant.Name; MonoBehaviour.print("EditorVariant applied: " + variant.Name); TextureSet set = getSet(variant); if (set != null) { applyConfig(part.transform.FindRecursive("model"), set, resetColors); } else { MonoBehaviour.print("ERROR: Set was null for variant: " + variant.Name); } }
private TextureSet getSet() { TextureSet set = null; if (!string.IsNullOrEmpty(textureSet) && (set = TexturesUnlimitedLoader.getTextureSet(textureSet)) != null) { modelShaderSet = string.Empty; return(set); } else if (!string.IsNullOrEmpty(modelShaderSet) && (set = TexturesUnlimitedLoader.getModelShaderTextureSet(modelShaderSet)) != null) { textureSet = string.Empty; return(set); } else if ((set = getSet(part.baseVariant)) != null) { return(set); } //if nothing found, clear out references modelShaderSet = textureSet = string.Empty; return(null); }
public void enableCurrentSet(Transform[] roots) { TextureSet set = Array.Find(textureSets, m => m.name == currentTextureSet); if (set == null) { MonoBehaviour.print("ERROR: KSPTextureSwitch could not locate texture set for name: " + currentTextureSet); } if (customColors == null || customColors.Length == 0) { customColors = new RecoloringData[3]; customColors[0] = set.maskColors[0]; customColors[1] = set.maskColors[1]; customColors[2] = set.maskColors[2]; } int len = roots.Length; for (int i = 0; i < len; i++) { set.enable(roots[i].gameObject, customColors); } saveColors(customColors); }
/// <summary> /// Apply the current texture to the input transforms. The texture sets include/exclude settings will be used to determine what children of the input transforms should be adjusted. /// </summary> /// <param name="roots"></param> public void enableCurrentSet(Transform[] roots, bool userInput) { TextureSet set = currentTextureSet; if (set == null) { return; } if (userInput || customColors == null || customColors.Length == 0) { customColors = new RecoloringData[3]; customColors[0] = set.maskColors[0]; customColors[1] = set.maskColors[1]; customColors[2] = set.maskColors[2]; } int len = roots.Length; for (int i = 0; i < len; i++) { set.enable(roots[i], customColors); } saveColors(customColors); }
public void applyRecoloring(Material mat, RecoloringData[] userColors) { TextureSet.updateMaterialProperties(mat, TextureSet.getRecolorProperties(userColors, shaderProperties)); }
/// <summary> /// Update the current recoloring data for this texture set. Does not adjust any other material properties. /// </summary> /// <param name="mat"></param> /// <param name="userColors"></param> public void applyRecoloring(Transform root, RecoloringData[] userColors) { TextureSet.updateMaterialProperties(root, meshNames, excludedMeshes, TextureSet.getRecolorProperties(userColors, shaderProperties)); }
/// <summary> /// Apply the current recoloring selections to the input transform. Does not recreate material, but simply applies the properties to the current material. /// </summary> /// <param name="root"></param> /// <param name="userColors"></param> public void applyRecoloring(Transform root, RecoloringData[] userColors) { TextureSet set = currentTextureSet; set.applyRecoloring(root, userColors); }