Question How to set clothing textures from current skin face textures?

Origin69

Well-known member
Wiki Contributor
Messages
521
Reactions
1,447
Points
93
I made Klingon head ridges as a clothing Item. They currently only work with the Custom Base Female face set, with a decal added over the top to add a bit of shading.

Does anyone know if a clothing plugin could find which textures/parameters are set on the person's face (including the built in textures) and update the clothing items material?

1731623762.jpg
 
In theory yes. In practice, I don't know of such a plugin - it may exist but probably not. It might be best to simply provide different versions of the clothing item to be used with different skins?
 
Upvote 0
In theory yes. In practice, I don't know of such a plugin - it may exist but probably not. It might be best to simply provide different versions of the clothing item to be used with different skins?
I can get it to work with any custom face textures (I might even be able to do that with a trigger within vam without a plugin), but the built in textures are a no go. The texture path doesn't show anything in game, so I'm assuming vam summons them from the void.
 
Upvote 0
You could look at the skin setting in the atom. The texture itself is tied to the material, hence why you don't see it in the fields : )
You could grab the texture reference from the material itself, but you would need a plugin.
 
Upvote 0
Please help, I feel like I'm drowning. I've spent so long trying to look up how this all works, but when It comes to scripting I literally don't speak the language.
I've read through Chokaphi's DecalMaker script, and Wardrobe by VamDazzler. I can see most parts of the puzzle, but I'm still lost.

I know this would be really useful. Not just for this item, but for grafting extra geometry as clothing to other area's of the body too.

I basically need a person plugin that has one list to select Face/torso/limbs/gens to copy the current textures/material properties from, and a second that lists the equipped clothing's material slots to copy them to.

I'm just pixels and verts. If someone who get's this side of things could write the code, or explain it to me like I'm 5, I would love them forever.
 
Upvote 0
The built-in skin textures cannot be extracted and used for other purposes. You could have matching custom skin presets and clothing presets for the ridges based on a specific texture set. I think that would be easier than writing some plugin, if you're not an expert at coding plugins.
 
Upvote 0
The built-in skin textures cannot be extracted and used for other purposes. You could have matching custom skin presets and clothing presets for the ridges based on a specific texture set. I think that would be easier than writing some plugin, if you're not an expert at coding plugins.

I think you're lost in translation here due to your lack of knowledge in code ;)
Origin asks for the way to read the property of materials. Not "copy" the textures as "physical assets".


I'm just pixels and verts. If someone who get's this side of things could write the code, or explain it to me like I'm 5, I would love them forever.

I can't look at the code right now, but I can give you the base idea, it's quite easy.
The process is this:
  • Identify what renders the material
  • Grab the renderer and the material instance
  • Read/Set the property

C#:
var myObjectContainingMat = ...; // find the object that has the mat ref

Material MySourceMat = myObjectContainingMat.material; // generally goes this way
Texture2D MySourceText = MySourceMat.GetTexture("_textureProperty"); // you'll have to find the exact name

MyTargetMaterial.SetTexture("_textureProperty", MySourceText);

Roughly the idea ^^
Look at Embody, it does manipulate the character shaders/materials quite extensively.
 
Upvote 0
Day 3 of feeling stupid. :cry:

Spud. I'm not trying to save the textures, just redirect the material used in game to a clothing item. That way extra geometry like this can be grafted onto any model. Saving a preset limits its use, It would be cool to make stuff like this that could be used on any existing look.

Adding extra geometry that grafts onto the skin could be useful for a lot of things other than just this, like horns and spines that have raised skin surrounding them to make them look more like a part of the model, raised moles or scars, cybernetic implants that effect the skin around them, detailed ear or nose prosthetic. All sorts of fantasy and sci-fi weirdness.


Hazmhox. Thanks for the idea's, but I'm still lost.
I 'read' through the code for Embody. Is this a pointy metal thing with a hole in?


using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace Handlers
{
public class SkinHandler : IHandler
{
private readonly DAZSkinV2 _skin;
private readonly IEnumerable<string> _materialsToHide;
private readonly int _materialsToHideMax;
private List<SkinShaderMaterialSnapshot> _materialRefs;

public SkinHandler(DAZSkinV2 skin, IEnumerable<string> materialsToHide, int materialsToHideMax)
{
_skin = skin;
_materialsToHide = materialsToHide;
_materialsToHideMax = materialsToHideMax;
}

public bool Prepare()
{
_materialRefs = new List<SkinShaderMaterialSnapshot>();

foreach (var material in GetMaterialsToHide())
{
var materialInfo = SkinShaderMaterialSnapshot.FromMaterial(material);

Shader shader;
if (!ReplacementShaders.ShadersMap.TryGetValue(material.shader.name, out shader))
SuperController.LogError("Missing replacement shader: '" + material.shader.name + $"' ({material.name} will not be hidden)");

if (shader != null)
{
material.shader = shader;
materialInfo.alphaAdjustSupport = material.HasProperty("_AlphaAdjust");
materialInfo.alphaCutoffSupport = material.HasProperty("_Cutoff");
materialInfo.specColorSupport = material.HasProperty("_SpecColor");
}
else
{
materialInfo.alphaAdjustSupport = materialInfo.originalAlphaAdjustSupport;
materialInfo.alphaCutoffSupport = materialInfo.originalAlphaCutoffSupport;
materialInfo.specColorSupport = materialInfo.originalSpecColorSupport;
}

_materialRefs.Add(materialInfo);
}

// This is a hack to force a refresh of the shaders cache
_skin.BroadcastMessage("OnApplicationFocus", true);
return true;
}
 
Upvote 0
Yup! You seem to be at the right spot. This is where he flips the materials. It seems he's using the skin, so you should find the current materials there, and read the textures from the material :)
 
Upvote 0
So far I have this script that shows it can get the textures I need from the _dazSkin.GPUmaterials;
I just have it listing all of the textures from the skin materials in the error log right now.

using System; using UnityEngine; public class MaterialTextureDisplay : MVRScript { private DAZCharacter _dazCharacter; private DAZSkinV2 _dazSkin; private Atom _parentAtom; public override void Init() { base.Init(); try { // Ensure the script is attached to a valid PERSON atom if (containingAtom.mainController == null) { SuperController.LogError("Please add this plugin to a PERSON atom."); return; } _parentAtom = containingAtom; // Initialize _parentAtom with the containingAtom reference // Get the DAZ character _dazCharacter = _parentAtom.GetComponentInChildren<DAZCharacter>(); if (_dazCharacter == null) { SuperController.LogError("No DAZCharacter found in the parent atom."); return; } // Get the DAZ skin (merged skin) _dazSkin = _dazCharacter.skin as DAZSkinV2; if (_dazSkin == null) { SuperController.LogError("No DAZSkin found for the DAZCharacter."); return; } // Display the textures from the DAZSkin DisplayTextures(); } catch (Exception ex) { SuperController.LogError("Error initializing MaterialTextureDisplay: " + ex.Message); } } private void DisplayTextures() { if (_dazSkin != null) { // Retrieve materials from the DAZSkin Material[] materials = _dazSkin.GPUmaterials; // Iterate over each material in the skin for (int i = 0; i < materials.Length; i++) { Material material = materials[i]; SuperController.LogError("Material: " + material.name); // Log Diffuse texture (MainTex) if (material.HasProperty("_MainTex")) { Texture diffuseTexture = material.GetTexture("_MainTex"); SuperController.LogError(" Diffuse Texture: " + diffuseTexture?.name ?? "None"); } // Log Specular texture (SpecTex) if (material.HasProperty("_SpecTex")) { Texture specTexture = material.GetTexture("_SpecTex"); SuperController.LogError(" Specular Texture: " + specTexture?.name ?? "None"); } // Log Gloss texture (GlossTex) if (material.HasProperty("_GlossTex")) { Texture glossTexture = material.GetTexture("_GlossTex"); SuperController.LogError(" Gloss Texture: " + glossTexture?.name ?? "None"); } // Log Normal Map texture (BumpMap) if (material.HasProperty("_BumpMap")) { Texture normalTexture = material.GetTexture("_BumpMap"); SuperController.LogError(" Normal Map Texture: " + normalTexture?.name ?? "None"); } } } else { SuperController.LogError("No DAZSkin available on the DAZCharacter."); } } }


I also have this part that gets the active clothing items on the person. Again just listing them to the error log right now.

using System; using System.Linq; using System.Collections.Generic; using UnityEngine; public class ActiveClothingLister : MVRScript { private Atom _parentAtom; private List<DAZClothingItem> _activeClothingItems = new List<DAZClothingItem>(); public override void Init() { base.Init(); try { // Ensure the script is attached to a valid PERSON atom if (containingAtom.mainController == null) { SuperController.LogError("Please add this plugin to a PERSON atom."); return; } _parentAtom = containingAtom; // Initialize _parentAtom with the containingAtom reference // Log active clothing items on the person atom LogActiveClothingItems(); } catch (Exception e) { SuperController.LogError("Error in Init: " + e.Message); } } // This method logs the active clothing items on the person atom private void LogActiveClothingItems() { // Retrieve the active clothing items from the parent atom _activeClothingItems = FindActiveClothingItems(); // Check if there are active clothing items and log them if (_activeClothingItems.Any()) { SuperController.LogError("Active clothing items on " + _parentAtom.name + ":"); foreach (var clothingItem in _activeClothingItems) { SuperController.LogError(" - " + clothingItem.name); // Log each clothing item name } } else { SuperController.LogError("No active clothing items found on " + _parentAtom.name); } } // Find active clothing items on the parent atom private List<DAZClothingItem> FindActiveClothingItems() { // Get the list of clothing items based on the `containingAtom` and clothing references var clothingItems = _parentAtom.GetComponentsInChildren<DAZClothingItem>(); return clothingItems .Where(item => item.containingAtom == _parentAtom) // Ensure it's part of the current atom .Where(item => !string.IsNullOrEmpty(item.name)) // Make sure the item has a name .ToList(); } }


Anyone know how best to combine these, using the texture information to create a ui with selectable dropdowns, and a button to transfer the selected person textures to the selected clothing item?

1732145035759.png
 
Upvote 0
You want like a dynamic thing? That reloads upon scene load?
I think that's best. I don't know if applying textures to the clothing in this way would allow you to save a clothing preset, as the gpu texture information could be different next time you load the clothing.
 
Upvote 0
I think you simply need to save one thing then.
The material ID you're using for which clothing piece on the character.

The base technic is not hard, you can dig into most of my plugins you will find a comprehensive way of creating a dropdown.
But in your case, the most annoying part is creating the UI on the fly... because VAM is not very good at doing "non-arbitrary" UI inputs.

To make it simple: when you create an input in VAM like for instance, a slider. It needs to be created in Init. If you don't do this, this will fail to initialize properly and save/restore the data.

In your case, since you're waiting on the character to be ready and you don't know "out of the box" how much clothing elements there are, you need to initialize them manually.

The process is not hard tho, it's just tedious:
  • Wait for your data ( in your case, your character / scene finished loading )
  • Look at the clothes, create dropdowns accordingly
  • Register dropdowns
  • Restore json
  • Init clothes based on loaded data
You also would have to handle the situation where new clothes are added, or removed.

The way you can save the data to know which one is which is with the Json identifier. For instance, I'm doing prefixed/suffixed names like "Clothing_SuffixIdentifier".

So "Clothing_UberHat" JSONStorable would contain the material ID for the clothing UberHat.

Saving the data or creating the UI is not the complex part. It's the whole loading/initialization process that's gonna take you a while to do properly : )
 
Upvote 0
I think you simply need to save one thing then.
The material ID you're using for which clothing piece on the character.

The base technic is not hard, you can dig into most of my plugins you will find a comprehensive way of creating a dropdown.
But in your case, the most annoying part is creating the UI on the fly... because VAM is not very good at doing "non-arbitrary" UI inputs.

To make it simple: when you create an input in VAM like for instance, a slider. It needs to be created in Init. If you don't do this, this will fail to initialize properly and save/restore the data.

In your case, since you're waiting on the character to be ready and you don't know "out of the box" how much clothing elements there are, you need to initialize them manually.

The process is not hard tho, it's just tedious:
  • Wait for your data ( in your case, your character / scene finished loading )
  • Look at the clothes, create dropdowns accordingly
  • Register dropdowns
  • Restore json
  • Init clothes based on loaded data
You also would have to handle the situation where new clothes are added, or removed.

The way you can save the data to know which one is which is with the Json identifier. For instance, I'm doing prefixed/suffixed names like "Clothing_SuffixIdentifier".

So "Clothing_UberHat" JSONStorable would contain the material ID for the clothing UberHat.

Saving the data or creating the UI is not the complex part. It's the whole loading/initialization process that's gonna take you a while to do properly : )
Thanks for looking at this hazmhox, I appreciate all of your input, but unfortunately I think this project is now beyond my interests.

I like to create things for vam to make people happy, but I've really stressed myself out trying to understand coding and plugins. It's just not how my mind works, and I am getting zero enjoyment out of it at this point. I'm not even into Klingons, I just made it on a whim because Farger added the bird of prey, so I turned his Saiko into a Klingon to make him smile.

I do think there is something great behind this idea, using clothing skin grafts that match the uv's of the person textures to add more detailed geometry, It could have gotten around the issue you were chasing ages ago with height maps too, but I think it is beyond my skill level. Like I often say, I'm just pixels and verts, I know what I'm good at and what I enjoy doing.

Thanks anyway.
 
Upvote 0
You should do what you enjoy yes!
At least, you are aware enough of your motivation about that, which is better than starting it and failing to finish the project.

Keep up the great pixels and verts content coming ;)
 
Upvote 0
Thanks for looking at this hazmhox, I appreciate all of your input, but unfortunately I think this project is now beyond my interests.

I like to create things for vam to make people happy, but I've really stressed myself out trying to understand coding and plugins. It's just not how my mind works, and I am getting zero enjoyment out of it at this point. I'm not even into Klingons, I just made it on a whim because Farger added the bird of prey, so I turned his Saiko into a Klingon to make him smile.

I do think there is something great behind this idea, using clothing skin grafts that match the uv's of the person textures to add more detailed geometry, It could have gotten around the issue you were chasing ages ago with height maps too, but I think it is beyond my skill level. Like I often say, I'm just pixels and verts, I know what I'm good at and what I enjoy doing.

Thanks anyway.

I do greatly appreciate the testing with Saiko, it looks terrific.
 
Upvote 0
Back
Top Bottom