• 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.
CustomShaderLoaderAlt

Plugins + Scripts CustomShaderLoaderAlt

Download [3.82 MB]
CustomShaderLoaderAlt
Improvements over Regguise/CustomShaderLoader v1.72



✦ New Features



1. Material Slot Limit: 10 → 50

The original plugin hardcoded a limit of 10 material slots for Clothing/CUA mode. Any CUA or clothing item with more than 10 materials could not have its extra slots controlled.

The improved version raises the limit to 50 Clothing/CUA slots (skin slots remain at 30), supporting large CUAs and high-material-count clothing items.



2. New Property Type: vector4

The original only supported 3D vectors (vector = XYZ).
The improved version adds vector4, providing four sliders (X/Y/Z/W) for shader properties that require a Vector4 parameter (e.g. packed tiling+offset, custom parameter groups).

JSON:
{
  "name": "_TilingOffset",
  "displayName": "Tiling & Offset",
  "type": "vector4",
  "defaultVector4": { "x": 1.0, "y": 1.0, "z": 0.0, "w": 0.0 },
  "minVector4":     { "x": 0.1, "y": 0.1, "z": -2.0, "w": -2.0 },
  "maxVector4":     { "x": 10.0, "y": 10.0, "z": 2.0, "w": 2.0 }
}



3. New Property Type: label — Section Headers

The original had no way to group properties visually — everything was stacked without structure.
The improved version introduces the label type, which inserts a colored banner to visually separate property groups.

  • defaultColor: Banner background color (supports #RRGGBB hex or named colors)
  • textColor: Text color; if omitted, black or white is chosen automatically based on background luminance
  • height, fontSize: Control banner dimensions

JSON:
{ "name": "", "displayName": "─── Base Colors ───", "type": "label", "defaultColor": "#1a2a4a", "height": 45, "fontSize": 26 },
{ "name": "", "displayName": "─── Lighting ───",    "type": "label", "defaultColor": "#2a1a1a", "textColor": "#ffcc88", "height": 45, "fontSize": 26 }



4. New Property Type: column — Left/Right Column Toggle

The original placed all shader properties in the right column only (hardcoded rightSide = true), leaving the left column completely empty.
The improved version adds the column type — inserting it switches all subsequent properties to the other column, enabling a balanced two-column layout.

JSON:
{ "name": "_Color",    "displayName": "Base Color", "type": "color", "defaultColor": "white" },
{ "name": "_Emission", "displayName": "Emission",   "type": "color", "defaultColor": "black" },
{ "name": "", "displayName": "", "type": "column" },
{ "name": "_Metallic", "displayName": "Metallic",   "type": "float", "defaultValue": 0.0, "minValue": 0.0, "maxValue": 1.0 },
{ "name": "_Gloss",    "displayName": "Smoothness", "type": "float", "defaultValue": 0.5, "minValue": 0.0, "maxValue": 1.0 }

The two color pickers appear in the right column; after column, the sliders switch to the left column.



5. New Property Type: tab — Tab-Based Layout

The original had no tab support — large property lists required endless scrolling.
The improved version integrates CustomTabUI: placing a tab entry in the JSON creates a tab button at the top of the plugin UI, and all subsequent properties are grouped under that tab.

JSON:
{ "name": "", "displayName": "Basic", "type": "tab", "tabWidth": 100 },
{ "name": "_Color",    "displayName": "Base Color", "type": "color", "defaultColor": "white" },
{ "name": "_Metallic", "displayName": "Metallic",   "type": "float", "defaultValue": 0.0, "minValue": 0.0, "maxValue": 1.0 },

{ "name": "", "displayName": "Textures", "type": "tab", "tabWidth": 100 },
{ "name": "_MainTex",  "displayName": "Albedo",     "type": "texture", "wrapMode": "Repeat" },
{ "name": "_BumpMap",  "displayName": "Normal Map", "type": "texture", "wrapMode": "Repeat" }



toggle: New keyword Field — Shader Keyword Control

The original toggle only set a shader property's float value (0/1), with no ability to control #pragma multi_compile keyword branches.

The improved version adds an optional keyword field — toggling the switch also calls EnableKeyword / DisableKeyword.

JSON:
{ "name": "_UseNormalMap", "displayName": "Enable Normal Map", "type": "toggle", "defaultValueBool": false, "keyword": "USE_NORMAL_MAP" },
{ "name": "_UseEmission",  "displayName": "Enable Emission",   "type": "toggle", "defaultValueBool": false, "keyword": "EMISSION_ON" }

Corresponding shader code:
Code:
#pragma multi_compile_local _ USE_NORMAL_MAP
#pragma multi_compile_local _ EMISSION_ON



texture: New wrapMode Field

The original applied the default wrap mode to all textures with no way to override it. The improved version lets you specify wrap mode per texture:

ValueBehavior
Repeat (default)Tile and repeat
Clamp
MirrorMirrored tiling
[TD]Stretch edges — ideal for masks/gradients[/TD]

JSON:
{ "name": "_MainTex", "displayName": "Albedo",    "type": "texture", "wrapMode": "Repeat" },
{ "name": "_MaskTex", "displayName": "Mask",      "type": "texture", "wrapMode": "Clamp" },
{ "name": "_FlowMap", "displayName": "Flow Map",  "type": "texture", "wrapMode": "Mirror" }



✦ Bug Fixes



8. WalkAndGetParentItems: No Longer Overwrites containingAtom

The original accidentally reassigned containingAtom while walking parent objects:

C#:
containingAtom = parent.GetComponent<Atom>(); // ← overwrites the plugin's own host reference!

In Clothing mode, this replaced containingAtom with the clothing's host Person Atom, breaking all downstream logic that relied on it.

Fix: A local variable walkedAtom is used for traversal comparison; containingAtom is never modified.



9. RestoreShaderPropertiesFromJSON: Person Mode Wait Condition Fixed

Original wait condition:
C#:
yield return new WaitUntil(() => shaderPropertyInitDone && (dazSkinWrap != null || pluginMode.val == "cua"));

In Person mode with no clothing selected, dazSkinWrap is null and the mode is not "cua", so the coroutine waits forever — skin shader properties never restore.

Fix: Added pluginMode.val == "person" branch:
C#:
yield return new WaitUntil(() => shaderPropertyInitDone && (dazSkinWrap != null || pluginMode.val == "cua" || pluginMode.val == "person"));



10. RestoreFromJSON: Removed Redundant ApplyShaderToMaterials Calls Inside Loop

The original called ApplyShaderToMaterials() on every loop iteration:
C#:
for (int i = 0; i < slots.Count ...) {
    materialSlotStorables[i].valNoCallback = slots[i].AsBool;
    ApplyShaderToMaterials(); // ← fires every iteration!
}

10 material slots = 10 redundant calls. Fix: Moved outside the loop — called once after all slots are restored.



11. Vector Properties: Fixed Order-Dependent Accumulation Logic

The original accumulated xValue/yValue and only submitted the vector upon encountering _Z, relying on Dictionary iteration in X→Y→Z order (not guaranteed):
C#:
if (propertyname.EndsWith("_Z")) {
    UpdateShaderProperty(baseName, new Vector3(xValue, yValue, val)); // wrong if order differs
}

Fix: Uses HashSet<string> processedVectorBases to track processed base names, reads all components at once before submitting, and correctly handles the W component of vector4.



12. Texture Callback: Fixed Passing Texture Name Instead of Path

The original passed tex.name (Unity's internal asset name) instead of the disk path:
C#:
(Texture2D tex) => TexturePropertyCallback(tex.name) // ← can't match a disk path

This caused the texture load callback to fail when trying to update the shader property. Fix: Passes the full file URL and applies complete texture settings (wrapMode, filterMode, anisoLevel).



13. Log Writing: Eliminated Linear I/O Growth

The original read the entire log file before every write:
C#:
string existingContent = FileManagerSecure.ReadAllText(_logFilePath); // reads entire file each time
FileManagerSecure.WriteAllText(_logFilePath, existingContent + message, ...);

Cost grew linearly with file size. Fix: Maintains _logFileContent in memory and appends directly before writing.



14. CUA Material Restore: Added defaultShaders Bounds Check

The original restore loop lacked a length check on defaultShaders, risking an index-out-of-bounds exception. Fix: Added && i < defaultShaders.Count.



✦ Full Configuration Example: Clothing Shader

Demonstrates label grouping / two-column layout / keyword / time animation / vector4

JSON:
[
  { "name": "", "displayName": "─── Colors ───", "type": "label", "defaultColor": "#1a1a2e", "height": 42 },
  { "name": "_Color",      "displayName": "Base Color",  "type": "color", "defaultColor": "#888888" },
  { "name": "", "displayName": "", "type": "column" },
  { "name": "_Metallic",   "displayName": "Metallic",    "type": "float", "defaultValue": 0.8, "minValue": 0.0, "maxValue": 1.0 },
  { "name": "_Smoothness", "displayName": "Smoothness",  "type": "float", "defaultValue": 0.6, "minValue": 0.0, "maxValue": 1.0 },
  { "name": "", "displayName": "─── Textures ───", "type": "label", "defaultColor": "#1a2e1a", "height": 42 },
  { "name": "_MainTex",    "displayName": "Albedo",      "type": "texture", "wrapMode": "Repeat" },
  { "name": "_BumpMap",    "displayName": "Normal Map",  "type": "texture", "wrapMode": "Repeat" },
  { "name": "_UseNormal",  "displayName": "Enable Normal", "type": "toggle", "defaultValueBool": true, "keyword": "USE_NORMAL_MAP" },
  { "name": "", "displayName": "─── Dynamic ───", "type": "label", "defaultColor": "#2e1a2e", "height": 42 },
  { "name": "_CustomTime", "displayName": "Time Animation", "type": "time" },
  { "name": "_TilingOffset", "displayName": "Tiling/Offset", "type": "vector4",
    "defaultVector4": { "x": 1.0, "y": 1.0, "z": 0.0, "w": 0.0 },
    "minVector4":     { "x": 0.1, "y": 0.1, "z": -2.0, "w": -2.0 },
    "maxVector4":     { "x": 10.0, "y": 10.0, "z": 2.0, "w": 2.0 } }
]

QQ20260307-231956.png
QQ20260303-221701.png
React to this content...

Share this resource

Back
Top Bottom