• Hi Guest!

    We are extremely excited to announce the release of our first Beta1.1 and the first release of our Public AddonKit!
    To participate in the Beta, a subscription to the Entertainer or Creator Tier is required. For access to the Public AddonKit you must be a Creator tier member. Once subscribed, download instructions can be found here.

    Click here for information and guides regarding the VaM2 beta. Join our Discord server for more announcements and community discussion about VaM2.
  • Hi Guest!

    VaM2 Resource Categories have now been added to the Hub! For information on posting VaM2 resources and details about VaM2 related changes to our Community Forums, please see our official announcement here.
Decal Maker

Plugins + Scripts Decal Maker

Download [3 MB]
Chokaphi updated Decal Maker with a new update entry:

Roses are red, Violets are red, Bushes are red...shit I broke the colorpicker again

Update the ColorPicker UI and fix reported bugs.

Fix: Adds check to skip Genital texture clipping when a male character is selected.
Fix: Color Picker will correctly sync with selected textures values.
Fix: Color Picker slider now has the texture path and value entry box.
Fix: Set DynamicStorables to not save to JSON

Read the rest of this update entry...
 
A fantastic plugin that addresses one of the biggest shortcomings of VAM's native skin functionality.

However, I have a suggestion:

SuperController.LogError is conventionally used for reporting actual errors. For messages indicating successful plugin loading, unloading, or other informational events, it might be better to use an info-level log instead.

The red error messages can be distracting and may even cause unnecessary confusion—especially for regular players.

Moreover, VAM pops up a UI window every time LogError is triggered, which can be quite unnecessary in these cases.
 
A fantastic plugin that addresses one of the biggest shortcomings of VAM's native skin functionality.

However, I have a suggestion:

SuperController.LogError is conventionally used for reporting actual errors. For messages indicating successful plugin loading, unloading, or other informational events, it might be better to use an info-level log instead.

The red error messages can be distracting and may even cause unnecessary confusion—especially for regular players.

Moreover, VAM pops up a UI window every time LogError is triggered, which can be quite unnecessary in these cases.

I try to use SuperController.LogError for user facing errors I want reported even if it does not crash the plugin, and Debug.Log/Error/warning for internal logs.

I did find a few that should be changed Please Add any others you think should not be alerted on.
Next release these will not be on or use internal logs:
  • Decal Maker assetbundle loaded and ready " + DateTime.Now
  • Decal Maker assetbundle unloaded " + DateTime.Now)
  • A JSON printout when old saves were loaded/converted
 
I try to use SuperController.LogError for user facing errors I want reported even if it does not crash the plugin, and Debug.Log/Error/warning for internal logs.

I did find a few that should be changed Please Add any others you think should not be alerted on.
Next release these will not be on or use internal logs:
  • Decal Maker assetbundle loaded and ready " + DateTime.Now
  • Decal Maker assetbundle unloaded " + DateTime.Now)
  • A JSON printout when old saves were loaded/converted

Thank you for your response. I think these would make more sense in an info-level log rather than an error log. In fact, aside from errors caused by the failure of a specific operation or function, it might be worth considering moving most error logs to info logs, as people who truly care about this information usually know how to find and interpret it. For most casual users, error logs only cause unnecessary alarm. :ROFLMAO:

JSON:
        void CharacterEvents(object o, CharEventArgs e)
        {
            SuperController.LogError(DateTime.Now +" PluginState CharacterEvent " + e.eventName);
            switch (e.eventName)
            {
                case "GpuTextureData":
                    //texture data for character has been stored
                    Data.InitRenderers(CharacterState);
                    break;

                case "_isMale":
                    PluginSettings.IsMale = e._isMale;
                    break;

                case "_uvSetName":
                    PluginSettings.UVSetName = e._uvSetName;
                    break;
            }
        }

JSON:
            this.request = request;
            loaded = true;
            SuperController.LogError("Decal Maker assetbundle loaded and ready " +DateTime.Now);
        }

JSON:
        public void Destroy()
        {
            AssetLoader.DoneWithAssetBundleFromFile(path);
            //request = null;
            loaded = false;
            SuperController.LogError("Decal Maker assetbundle unloaded " + DateTime.Now);
           
            foreach (GameObject obj in InstancedObjects)
            {
                GameObject.Destroy(obj);
            }
            InstancedObjects = new List<GameObject>();
        }

JSON:
        void CharacterEvents(object o, CharEventArgs e)
        {
            SuperController.LogError(DateTime.Now + " BaseREnderer CharacterEvent " + e.eventName);
            switch (e.eventName)
            {
                case "GpuTextureData":
                    //texture data for character has been stored
                    //Debug.LogError(DateTime.Now+" BaseRender GpuTextureData " + e.daskin?.name + " " + e.dAZCharacter?.name);
                    IsDirty = true;
                    break;

                case "_uvSetName":
                    SetClipAction();
                    break;
            }
        }

JSON:
        public void Update()
        {
            SuperController.LogError("OnLateUpdate()");
            if (IsDirty)
            {
                SuperController.LogError("IS DIRTY!" + _MaterialSlot + " " + _TextureSlot);
                if (!Processing)
                {
                    dirtyTimeStart = dirtyTime;
                    Processing = true;
                    StartCoroutine(ApplyChanges());
                }
            }
        }
 
Last edited:
Thank you for your response. I think these would make more sense in an info-level log rather than an error log. In fact, aside from errors caused by the failure of a specific operation or function, it might be worth considering moving most error logs to info logs, as people who truly care about this information usually know how to find and interpret it. For most casual users, error logs only cause unnecessary alarm. :ROFLMAO:

JSON:
        void CharacterEvents(object o, CharEventArgs e)
        {
            SuperController.LogError(DateTime.Now +" PluginState CharacterEvent " + e.eventName);
            switch (e.eventName)
            {
                case "GpuTextureData":
                    //texture data for character has been stored
                    Data.InitRenderers(CharacterState);
                    break;

                case "_isMale":
                    PluginSettings.IsMale = e._isMale;
                    break;

                case "_uvSetName":
                    PluginSettings.UVSetName = e._uvSetName;
                    break;
            }
        }
Not active in Beta 2.5

JSON:
            this.request = request;
            loaded = true;
            SuperController.LogError("Decal Maker assetbundle loaded and ready " +DateTime.Now);
        }

JSON:
        public void Destroy()
        {
            AssetLoader.DoneWithAssetBundleFromFile(path);
            //request = null;
            loaded = false;
            SuperController.LogError("Decal Maker assetbundle unloaded " + DateTime.Now);
          
            foreach (GameObject obj in InstancedObjects)
            {
                GameObject.Destroy(obj);
            }
            InstancedObjects = new List<GameObject>();
        }

JSON:
        void CharacterEvents(object o, CharEventArgs e)
        {
            SuperController.LogError(DateTime.Now + " BaseREnderer CharacterEvent " + e.eventName);
            switch (e.eventName)
            {
                case "GpuTextureData":
                    //texture data for character has been stored
                    //Debug.LogError(DateTime.Now+" BaseRender GpuTextureData " + e.daskin?.name + " " + e.dAZCharacter?.name);
                    IsDirty = true;
                    break;

                case "_uvSetName":
                    SetClipAction();
                    break;
            }
        }
These asset load/unloads were using SuperController log by mistake and will be fixed next release.

JSON:
        public void Update()
        {
            SuperController.LogError("OnLateUpdate()");
            if (IsDirty)
            {
                SuperController.LogError("IS DIRTY!" + _MaterialSlot + " " + _TextureSlot);
                if (!Processing)
                {
                    dirtyTimeStart = dirtyTime;
                    Processing = true;
                    StartCoroutine(ApplyChanges());
                }
            }
        }
Also not active in Beta2.5
 
Hi.
tried yesterday a little bit. I noticed one thing.
When I scale a "normal" texture, it doesn't work. You can move and rotate the "normal" texture, but the scaling doesn't work.
thanks and keep up the good work.
 
Hi.
tried yesterday a little bit. I noticed one thing.
When I scale a "normal" texture, it doesn't work. You can move and rotate the "normal" texture, but the scaling doesn't work.
thanks and keep up the good work.



Fixed, Will be in the next release.

material.SetTextureScale("_BumpMap" + count, frame.Scale);

Was never added to the normal Renderer
 
Chokaphi updated Decal Maker with a new update entry:

Hey..hey man.. I.I..I need my fix, like now man!

Fix: Normal Maps will now change in the render when scaled in the UI
Fix: Correct some debug messages to log internally instead of SuperController.LogError.
Fix: Selection Panel description will change to match what it is being used for. LINKING or EXPORTING
Fix: Export browser should now show existing textures when saving.
Fix: Exporting textures will not try and start if no selection is made.
Fix: Use the Blend Texture if available in the export selection Thumbnail.
Fix: Exporting textures...

Read the rest of this update entry...
 
btw one question, i dont know if i already mentioned this as nice to have.


the normal texture is the height texture.. That means, e.g. a scar has two textures if you want it to look realistic
Is one of the Blend functions a normal/height texture? e.g. if i am adding a scar decal and his scar normal as the blend texture to get the height map as if i would load it in the normal texture section?
Actually i would place the scar decal and then scale, move, rotate etc. After that, i have to do the same with his normal texture manually. Thats not that easy as it sounds, especially if the decal texture is placed freely somewhere on the body and is scaled etc.
A super comfortable function would be, if i have e.g. a complete set of decal with his 4 texture parts (decal, spec, gloss, normal, all the same size etc), then link those 4 textures together and move, scale, rotate them together. Maybe also need more digits after the decimal point.
 
Hi Chokaphi, thanks again for your hard work and the effort you put into this plugin, it cannot be overrated for the potential if brings to VaM!

I am currently updating the links in my plugins (Realistic Foreskin & Erection) to use your new version and noticed that on alt futa (with Stopper's plugin), DM loads female settings (of course, because they are females). I think the female base is correct for altfuta too in terms of all other slots, but we would need the male genitals slot instead of the female one. Sounds easy, but I am sure there are complications... However, would you consider it possible to add a special detection rule for alt futa, to load the male genitals slot? I think there would be a small community you made very happy :)

Detection of altfuta "gender" can be done quite easily on plugin load (however, with some delay to await Stoppers plugin) based on being female and having penis colliders: isFemale = geometry.gender == DAZCharacterSelector.Gender.Female; and e.g. detecting "AutoColliderGen3bHard".

I know you have lots of other stuff to do, and do not feed pushed, just allow me to ask please. Thanks and keep up your fantastic work!!
 
Hi Chokaphi, thanks again for your hard work and the effort you put into this plugin, it cannot be overrated for the potential if brings to VaM!

I am currently updating the links in my plugins (Realistic Foreskin & Erection) to use your new version and noticed that on alt futa (with Stopper's plugin), DM loads female settings (of course, because they are females). I think the female base is correct for altfuta too in terms of all other slots, but we would need the male genitals slot instead of the female one. Sounds easy, but I am sure there are complications... However, would you consider it possible to add a special detection rule for alt futa, to load the male genitals slot? I think there would be a small community you made very happy :)

Detection of altfuta "gender" can be done quite easily on plugin load (however, with some delay to await Stoppers plugin) based on being female and having penis colliders: isFemale = geometry.gender == DAZCharacterSelector.Gender.Female; and e.g. detecting "AutoColliderGen3bHard".

I know you have lots of other stuff to do, and do not feed pushed, just allow me to ask please. Thanks and keep up your fantastic work!!

why trying to detecting it? Let it switch on/off manually by user. Then you dont have to play around with delayed triggering etc. Its only a pragmatic idea for faster realisation.
 
Hi Chokaphi, thanks again for your hard work and the effort you put into this plugin, it cannot be overrated for the potential if brings to VaM!

I am currently updating the links in my plugins (Realistic Foreskin & Erection) to use your new version and noticed that on alt futa (with Stopper's plugin), DM loads female settings (of course, because they are females). I think the female base is correct for altfuta too in terms of all other slots, but we would need the male genitals slot instead of the female one. Sounds easy, but I am sure there are complications... However, would you consider it possible to add a special detection rule for alt futa, to load the male genitals slot? I think there would be a small community you made very happy :)

Detection of altfuta "gender" can be done quite easily on plugin load (however, with some delay to await Stoppers plugin) based on being female and having penis colliders: isFemale = geometry.gender == DAZCharacterSelector.Gender.Female; and e.g. detecting "AutoColliderGen3bHard".

I know you have lots of other stuff to do, and do not feed pushed, just allow me to ask please. Thanks and keep up your fantastic work!!
I will have to look at what the textureID used for AltFutas are using. VAM renders using mesh regions rather than 1 mesh per texture. Example the Face texture has 3 ID's, one renders the face, one the lips, and one inside the nostrils. ID 2, 5, 11 and these ID's are not the same between Male and Female characters, they differ on the Torso, limbs and Genitals.

females = Torso, new int[]{15,18,19,20,21,27,29}},
Limbs, new int[]{0,12,14,16,17,22,23}},
Genitals, new int[]{28}},

males = Torso, new int[]{15,16,19,20,21,22,30,32}},
Limbs, new int[]{0,12,14,17,18,23,24}},
Genitals, new int[]{28,29}},


That is why we have to be aware if characters "sex" when rendering.
 
btw one question, i dont know if i already mentioned this as nice to have.


the normal texture is the height texture.. That means, e.g. a scar has two textures if you want it to look realistic
Is one of the Blend functions a normal/height texture? e.g. if i am adding a scar decal and his scar normal as the blend texture to get the height map as if i would load it in the normal texture section?
Actually i would place the scar decal and then scale, move, rotate etc. After that, i have to do the same with his normal texture manually. Thats not that easy as it sounds, especially if the decal texture is placed freely somewhere on the body and is scaled etc.
A super comfortable function would be, if i have e.g. a complete set of decal with his 4 texture parts (decal, spec, gloss, normal, all the same size etc), then link those 4 textures together and move, scale, rotate them together. Maybe also need more digits after the decimal point.

Now that DecalMaker2 allows normal and specular/Gloss movement, linking the three layers movement together is something I have been considering. I just don't know what UI will work for it
 
I will have to look at what the textureID used for AltFutas are using. VAM renders using mesh regions rather than 1 mesh per texture. Example the Face texture has 3 ID's, one renders the face, one the lips, and one inside the nostrils. ID 2, 5, 11 and these ID's are not the same between Male and Female characters, they differ on the Torso, limbs and Genitals.

females = Torso, new int[]{15,18,19,20,21,27,29}},
Limbs, new int[]{0,12,14,16,17,22,23}},
Genitals, new int[]{28}},

males = Torso, new int[]{15,16,19,20,21,22,30,32}},
Limbs, new int[]{0,12,14,17,18,23,24}},
Genitals, new int[]{28,29}},


That is why we have to be aware if characters "sex" when rendering.
Thanks! I would expect the identical textureIDs from the male system to work on the (female) alt futas, because Stopper just adds male geometry. Just a guess though!
At least you can use the VaM male genital skin slots on alt futas.
 
Now that DecalMaker2 allows normal and specular/Gloss movement, linking the three layers movement together is something I have been considering. I just don't know what UI will work for it
that would be a really benefit for some 3 Dimensional decals. To place manually all the three layers exactly above each other is a little bit tricky. I thought something like grouping/linking together across the layers, like the actually already existing grouping method inside each layer, but even with the movement and scaling etc.
Actually i am backing such items, if i want to use it more that one time, as clothing. And even if i have to move the decal with all the textures, then i can move it at the dirty way in the clothing textures tab. At least I have everything on one page there, but i dont want to bake for every decal an own clothing item. :)
But anyway, decal maker 2 is a big step forward to the next level. I am happy about it, that you started the development for decal maker 2. Right now, it seems that the already existing features works as designed and you already fixed the bugs.
 
that would be a really benefit for some 3 Dimensional decals. To place manually all the three layers exactly above each other is a little bit tricky. I thought something like grouping/linking together across the layers, like the actually already existing grouping method inside each layer, but even with the movement and scaling etc.
Actually i am backing such items, if i want to use it more that one time, as clothing. And even if i have to move the decal with all the textures, then i can move it at the dirty way in the clothing textures tab. At least I have everything on one page there, but i dont want to bake for every decal an own clothing item. :)
But anyway, decal maker 2 is a big step forward to the next level. I am happy about it, that you started the development for decal maker 2. Right now, it seems that the already existing features works as designed and you already fixed the bugs.
It is not hard to implement on the backend, just remove the region filter that generate the list of selectable textures and add monitoring for the move, translate scale events in the Link Observer. Making the UI will be more effort because you do not want the same events for cross texture types links.

However Normal Maps do not rotate like you think. Since the are tangent space data of the angle light should reflect that breaks when you rotate the texture. The normal data would have to be recalculated in shader before generating the Normal for display.
This is an example of a Normal, specular and decal moving and rotating, note how the highlights appear on the opposite side when rotated.
 
ah ok. then the usecase is very special, more for symetric normals, maybe something like for a piercing hole, or eg. gunshot wounds for action scenes if you using VAM as a movie generator, whatever. etc. Some people build space battles with starships with vam for VR. ;)
 
Hello I love this plugin, however the newest updates have broken the way i used it, in the earlier .37 or .3x versions i used to just add your plugin to my looks, add different decals, then save my look apperance (without makeing a decalmaker save for each appearance), then when i had decal maker added as a plugin and loaded any look i made befire hand with your plugin included, it asked me "this look has decalmaker somethin somethin, would you like to load all clear all etc, and the new .40 versions every look i saved before it doesnt recongize i had custom decal maker settings for each one when i change a look, and i never made decalmaker saves for them, i just saved the apperance preset with decal maker loaded and it worked before, sorry if you cant understand english not main language. thanks for reading
 
i dont understand the issue exactly from pengpeng17, but maybe it is the same issue as in timeline? The name of decalmaker is different from Decal Maker 1, even the Plugin Slot is the same. Its not enought to import the former decal maker settings into Decalmaker 2.
btw. i didnt made to import from decal maker 1 to version 2 without manually reconstruct in timeline the decal triggers, because the Different plugin name. Decal Maker 2 has the Plugin Name "Decal Maker Core" or something like that.
I mean, if i am saying it exactly, the decal maker settings ARE imported INTO decal maker 2, but triggers and timeline dont recognize decal maker 2. as the former decal maker. I have to add it again everywhere, and then i have to do the settings in timeline or in the triggers.
I can liv with it, but i think, that would be a problem for an standard consumer, who already upgraded to version 2 and wanna use a scene with triggers/timeline, which one was made with decal maker 1. I dont know if every one can handy this, recognizie the "problem" and do a downgrade because a scene on to decalmaker 1. Normally it will work with the ingame store dependency downloading but i didnt tested it. Mutch pretty would be, to give in the plugin slot the same name for decal maker 2.
btw. there are 2 scritps in the package, i can only start the one which named "list" something. The other one does nothing, so i dont know what this second script does.
 
Hi @Chokaphi, I found that in the new version of DM the input accepted by "strength_normalmapx_genitals_BumpMap" is limited to 1.00, even though you can manually enter higher values in the field (see below). However, if I trigger a value of e.g. 2.5, the value is discarded.

Could you please check this and allow higher values again? Thank you!

1754814341976.png
 
Hi @Chokaphi, I found that in the new version of DM the input accepted by "strength_normalmapx_genitals_BumpMap" is limited to 1.00, even though you can manually enter higher values in the field (see below). However, if I trigger a value of e.g. 2.5, the value is discarded.

Could you please check this and allow higher values again? Thank you!

View attachment 514981
The slider currently maxes at one but you can enter higher values in the entry box. I may go back with the normal sliders having a -10 to +10 range or mimic VAM witha multiplier
 
The slider currently maxes at one but you can enter higher values in the entry box. I may go back with the normal sliders having a -10 to +10 range or mimic VAM witha multiplier
Please add this again, because you currently cannot trigger from externally more than -1/+1 (even if you can enter more inside your plugin!
 
Back
Top Bottom