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

Plugins + Scripts HeelAdjust2

Download [3.84 MB]
CheesyFX submitted a new resource:

HeelAdjust2 - Adds configurable colliders to shoes



Read more about this resource...
Hey, first off, thanks for all your contributions to the community.
I have a question: why isn't there a ToeColOffset “y” option in the plugin?
You can see in my screenshot that her toes are pointing upward too much, and her shoes are clipping through the floor.
I looked into the Skynet high-heel plugin, “Stopper.shoeHelper,” and the toe collision range ultimately pinpointed the issue.
Would it be possible for you to add this option?
Thanks again for your contributions.
1.PNG
2.PNG
3.PNG
 
Hi @CheesyFX , I made a couple of bugfix in this script:
1) Linked Items menu does not appear
2) A constant bug when the script is attached/removed
3) Fast clothing items swap (applying a Clothing Preset) produces wrong delta values
The first one is simple to fix
Git:
@@ -597,7 +603,7 @@ namespace CheesyFX
 
         private void CreateAdditionalItemsUI()
         {
-            RemoveTextField(lockedInfo);
+            if(lockedInfo != null) RemoveTextField(lockedInfo);
             RemoveUIElements(UIElementsSliders);
             linkAdditionalButton.label = "Return";
             linkAdditionalButton.button.onClick.RemoveAllListeners();
You just forget it could be null.
The second fix is simple too and barely could break something:
Git:
@@ -411,7 +412,9 @@ namespace CheesyFX
             HandShakeWithFlexIt();
             for (int i = 0; i < clothes.childCount; i++)
             {
-                clothes.GetChild(i).gameObject.AddComponent<ClothingEquippedEventHandler>();
+                var obj = clothes.GetChild(i).gameObject;
+                if (obj.GetComponent<DAZClothingItem>() == null) continue;
+                obj.AddComponent<ClothingEquippedEventHandler>();
             }
Explanation: there is a strange Clothing Item without DAZClothinItem attached to it exists for me in the transform. I don't know what is that and if other users have similar problem.
Code:
private IEnumerator DeferredInit()
{
    ....
    int n = 10;
    for (int i = 0; i < clothes.childCount; i++)
    {
        var obj = clothes.GetChild(i).gameObject;
        var dci = obj.GetComponent<DAZClothingItem>();
        if (dci != null)
        {
            if (--n > 0)
                SuperController.LogMessage(GetGameObjectPath(obj.transform));
            obj.AddComponent<ClothingEquippedEventHandler>();  
        }
        else SuperController.LogMessage($"no dci obj[{i}].path={GetGameObjectPath(obj.transform)}");
    }
}
OUTPUT:-------------->
SceneAtoms/Girl/rescale2/geometry/FemaleClothes/ClothingCreator
no dci obj[1].path=SceneAtoms/Girl/rescale2/geometry/FemaleClothes/FemaleClothingPrefab(Clone) <--- source of problem
SceneAtoms/Girl/rescale2/geometry/FemaleClothes/CustomClothingItem
SceneAtoms/Girl/rescale2/geometry/FemaleClothes/CustomClothingItem
SceneAtoms/Girl/rescale2/geometry/FemaleClothes/CustomClothingItem
The third: your special case if (currentPreset != null) StartCoroutine(IECalculateDeltas()); never executed if I understand correctly so that I made a way to execute it.
diff --git a/HeelAdjust2Core.cs b/HeelAdjust2Core.cs
index 0aca527..49ad788 100644
--- a/HeelAdjust2Core.cs
+++ b/HeelAdjust2Core.cs
@@ -411,7 +412,9 @@ namespace CheesyFX
HandShakeWithFlexIt();
for (int i = 0; i < clothes.childCount; i++)
{
- clothes.GetChild(i).gameObject.AddComponent<ClothingEquippedEventHandler>();
+ var obj = clothes.GetChild(i).gameObject;
+ if (obj.GetComponent<DAZClothingItem>() == null) continue;
+ obj.AddComponent<ClothingEquippedEventHandler>();
}
if (sceneData != null)
{
@@ -444,7 +447,7 @@ namespace CheesyFX

private void OnDestroy()
{
- OnDisable();
+ // OnDisable(); // it is called by SuperController already
GPUCollidersManager.DeregisterLineSphereCollider(lHeelGPUCapsule);
GPUCollidersManager.DeregisterLineSphereCollider(lToeGPUCapsule);
GPUCollidersManager.DeregisterLineSphereCollider(rHeelGPUCapsule);
@@ -454,6 +457,8 @@ namespace CheesyFX
Destroy(lToeColliderBase.gameObject);
Destroy(lHeelColliderBase.gameObject);

+ // otherwise onClothingItemToggled(dci, false) are fired for every equipped clothing item
+ ClothingEquippedEventHandler.skip = true;
for (int i = 0; i < clothes.childCount; i++)
{
Destroy(clothes.GetChild(i).GetComponent<ClothingEquippedEventHandler>());
@@ -474,6 +479,7 @@ namespace CheesyFX
rfootCTRL.GetFloatJSONParam("jointDriveYTarget").setCallbackFunction -= OnJointDriveChanged;
rfootCTRL.GetFloatJSONParam("jointDriveZTarget").setCallbackFunction -= OnJointDriveChanged;
HandShakeWithFlexIt();
+ SuperController.LogMessage("HellAdjust after OnDestroy");
}

private void SwitchTab(int id)
@@ -597,7 +603,7 @@ namespace CheesyFX

private void CreateAdditionalItemsUI()
{
- RemoveTextField(lockedInfo);
+ if(lockedInfo != null) RemoveTextField(lockedInfo);
RemoveUIElements(UIElementsSliders);
linkAdditionalButton.label = "Return";
linkAdditionalButton.button.onClick.RemoveAllListeners();
@@ -977,6 +983,14 @@ namespace CheesyFX
toeColliderOffset.SetValToDefault();
toeColliderRotation.SetValToDefault();
toeColliderScale.SetValToDefault();
+ // SuperController.LogMessage(new StackTrace(true).ToString());
+ string msg = "Reset @"+Time.realtimeSinceStartup.ToString();
+ float rotation = lFoot.transform.localRotation.eulerAngles.x;
+ msg += $" right rot={rotation}";
+ rotation = rFoot.transform.localRotation.eulerAngles.x;
+ msg += $"left rot={rotation}";
+ SuperController.LogMessage(msg);
+
rToeGPUCapsule.enabled = lToeGPUCapsule.enabled = lHeelGPUCapsule.enabled = rHeelGPUCapsule.enabled = false;
reloadButton.label = reloadLabel = "<b>Toggle</b>: None";
if (!autoCalculateDeltas.val)
@@ -1299,6 +1313,7 @@ namespace CheesyFX
var col = collisionEnabled.val;
collisionEnabled.val = false;
SetFootPose(0f);
+ SuperController.LogMessage($"SetFootPose(0) @{Time.realtimeSinceStartup}");
yield return new WaitForSeconds(.5f);
CalculateDeltas();
OnFootPoseChanged();
@@ -1327,8 +1342,16 @@ namespace CheesyFX

private void CalculateDeltas()
{
- rFootSlopeDelta.val = rDelta = GetDelta(rFoot.transform.localRotation.eulerAngles.x);
- lFootSlopeDelta.val = lDelta = GetDelta(lFoot.transform.localRotation.eulerAngles.x);
+ string msg = "deltas @"+Time.realtimeSinceStartup.ToString();
+ // float rotation = lfootCTRL.transform.localRotation.eulerAngles.x;
+ float rotation = lFoot.transform.localRotation.eulerAngles.x;
+ msg += $" right rot={rotation}";
+ rFootSlopeDelta.val = rDelta = GetDelta(rotation);
+ rotation = rFoot.transform.localRotation.eulerAngles.x;
+ // rotation = rfootCTRL.transform.localRotation.eulerAngles.x;
+ msg += $"left rot={rotation}";
+ SuperController.LogMessage(msg);
+ lFootSlopeDelta.val = lDelta = GetDelta(rotation);
}

private float GetDelta(float rotation)
@@ -1389,12 +1412,14 @@ namespace CheesyFX
if (preset != null)
{
toggleItemButton.label = toggleItemLabel = $"<b>Toggle</b> {StripNonAlphaNum(GetItemNameFromCustomClothingUID(dci.uid))}";
+ itemToStore.val = itemName; // TODO: this caption is not red right after plugin starts
if(enabled)
{
+ SuperController.LogMessage($"equip @{Time.realtimeSinceStartup}:{preset}");
LoadFromPath(preset);
if(autoCalculateDeltas.val)
{
- if (currentPreset != null) StartCoroutine(IECalculateDeltas());
+ if (currentPreset != null || (Time.realtimeSinceStartup - lastClothingDisabled) < .2f) StartCoroutine(IECalculateDeltas());
else CalculateDeltas();
}
}
@@ -1406,19 +1431,27 @@ namespace CheesyFX
{
activeItems.Remove(itemName);
activeItemNames.Remove(itemName);
- if (currentPreset == null || currentPreset == preset)
+ if (currentPreset != null && currentPreset == preset)
{
+ SuperController.LogMessage($"remove @{Time.realtimeSinceStartup}:{currentPreset}");
+ // possibly the user make a preset with either the platform and the heel item, so we don't want to get here re╤Бursively
+ ClothingEquippedEventHandler.skip = true;
if(currentPreset != null) EquipLinkedItems(LoadJSON(currentPreset).AsObject, false);
+ ClothingEquippedEventHandler.skip = false;
currentPreset = null;
+ lastClothingDisabled = Time.realtimeSinceStartup;
// currentItem = null;
// toggleItemButtonUid.label = "Current item: None"
Reset();
+ itemToStore.val = "None";
}
}
itemToStore.choices = activeItemNames;
aditionalItemChooser.choices = activeItemNames;
}

+ float lastClothingDisabled = 0;
+
private void HandShakeWithFlexIt()
{
for (int i = 0; i < transform.parent.childCount; i++)
@@ -1938,6 +1971,7 @@ namespace CheesyFX

public class ClothingEquippedEventHandler : MonoBehaviour
{
+ public static bool skip;
private void OnEnable()
{
var dci = gameObject.GetComponent<DAZClothingItem>();
@@ -1947,6 +1981,7 @@ namespace CheesyFX

private void OnDisable()
{
+ if (skip) return;
var dci = gameObject.GetComponent<DAZClothingItem>();
HeelAdjust2.onClothingItemToggled(dci, false);
// $"{gameObject.GetComponent<DAZClothingItem>().uid} unequipped".Print();
There are some action to reduce unwanted callback also.
I wonder why do you use (DAZBone)lFoot but not (FreeControllerV3)lfootCTRL for calculating deltas? That way you can't start-up the script properly if it has been launched on a atom with feet already bent (you see the angles in the video below).
 

Attachments

  • HA-full.patch.txt
    15.1 KB · Views: 0
And another version with (FreeControllerV3)lfootCTRL usage as angles source for the deltas. It works better for me but I possibly miss some other circumstances.
UPD: now I see this way does not work because we need the shin-foot angle that is simpler to produce with DAZBone. So the other way is to save the addition you bring to DAZbone angle and reverse it before apply a new one. The same with HeightAdjust: saving the introduced difference rather than the original value could produce a better result.
 

Attachments

  • HA-2.patch.txt
    17.2 KB · Views: 0
Last edited:
Hi @CheesyFX , I made a couple of bugfix in this script:
1) Linked Items menu does not appear
2) A constant bug when the script is attached/removed
3) Fast clothing items swap (applying a Clothing Preset) produces wrong delta values
The first one is simple to fix
Git:
@@ -597,7 +603,7 @@ namespace CheesyFX
 
         private void CreateAdditionalItemsUI()
         {
-            RemoveTextField(lockedInfo);
+            if(lockedInfo != null) RemoveTextField(lockedInfo);
             RemoveUIElements(UIElementsSliders);
             linkAdditionalButton.label = "Return";
             linkAdditionalButton.button.onClick.RemoveAllListeners();
You just forget it could be null.
The second fix is simple too and barely could break something:
Git:
@@ -411,7 +412,9 @@ namespace CheesyFX
             HandShakeWithFlexIt();
             for (int i = 0; i < clothes.childCount; i++)
             {
-                clothes.GetChild(i).gameObject.AddComponent<ClothingEquippedEventHandler>();
+                var obj = clothes.GetChild(i).gameObject;
+                if (obj.GetComponent<DAZClothingItem>() == null) continue;
+                obj.AddComponent<ClothingEquippedEventHandler>();
             }
Explanation: there is a strange Clothing Item without DAZClothinItem attached to it exists for me in the transform. I don't know what is that and if other users have similar problem.
Code:
private IEnumerator DeferredInit()
{
    ....
    int n = 10;
    for (int i = 0; i < clothes.childCount; i++)
    {
        var obj = clothes.GetChild(i).gameObject;
        var dci = obj.GetComponent<DAZClothingItem>();
        if (dci != null)
        {
            if (--n > 0)
                SuperController.LogMessage(GetGameObjectPath(obj.transform));
            obj.AddComponent<ClothingEquippedEventHandler>();
        }
        else SuperController.LogMessage($"no dci obj[{i}].path={GetGameObjectPath(obj.transform)}");
    }
}
OUTPUT:-------------->
SceneAtoms/Girl/rescale2/geometry/FemaleClothes/ClothingCreator
no dci obj[1].path=SceneAtoms/Girl/rescale2/geometry/FemaleClothes/FemaleClothingPrefab(Clone) <--- source of problem
SceneAtoms/Girl/rescale2/geometry/FemaleClothes/CustomClothingItem
SceneAtoms/Girl/rescale2/geometry/FemaleClothes/CustomClothingItem
SceneAtoms/Girl/rescale2/geometry/FemaleClothes/CustomClothingItem
The third: your special case if (currentPreset != null) StartCoroutine(IECalculateDeltas()); never executed if I understand correctly so that I made a way to execute it.
diff --git a/HeelAdjust2Core.cs b/HeelAdjust2Core.cs
index 0aca527..49ad788 100644
--- a/HeelAdjust2Core.cs
+++ b/HeelAdjust2Core.cs
@@ -411,7 +412,9 @@ namespace CheesyFX
HandShakeWithFlexIt();
for (int i = 0; i < clothes.childCount; i++)
{
- clothes.GetChild(i).gameObject.AddComponent<ClothingEquippedEventHandler>();
+ var obj = clothes.GetChild(i).gameObject;
+ if (obj.GetComponent<DAZClothingItem>() == null) continue;
+ obj.AddComponent<ClothingEquippedEventHandler>();
}
if (sceneData != null)
{
@@ -444,7 +447,7 @@ namespace CheesyFX

private void OnDestroy()
{
- OnDisable();
+ // OnDisable(); // it is called by SuperController already
GPUCollidersManager.DeregisterLineSphereCollider(lHeelGPUCapsule);
GPUCollidersManager.DeregisterLineSphereCollider(lToeGPUCapsule);
GPUCollidersManager.DeregisterLineSphereCollider(rHeelGPUCapsule);
@@ -454,6 +457,8 @@ namespace CheesyFX
Destroy(lToeColliderBase.gameObject);
Destroy(lHeelColliderBase.gameObject);

+ // otherwise onClothingItemToggled(dci, false) are fired for every equipped clothing item
+ ClothingEquippedEventHandler.skip = true;
for (int i = 0; i < clothes.childCount; i++)
{
Destroy(clothes.GetChild(i).GetComponent<ClothingEquippedEventHandler>());
@@ -474,6 +479,7 @@ namespace CheesyFX
rfootCTRL.GetFloatJSONParam("jointDriveYTarget").setCallbackFunction -= OnJointDriveChanged;
rfootCTRL.GetFloatJSONParam("jointDriveZTarget").setCallbackFunction -= OnJointDriveChanged;
HandShakeWithFlexIt();
+ SuperController.LogMessage("HellAdjust after OnDestroy");
}

private void SwitchTab(int id)
@@ -597,7 +603,7 @@ namespace CheesyFX

private void CreateAdditionalItemsUI()
{
- RemoveTextField(lockedInfo);
+ if(lockedInfo != null) RemoveTextField(lockedInfo);
RemoveUIElements(UIElementsSliders);
linkAdditionalButton.label = "Return";
linkAdditionalButton.button.onClick.RemoveAllListeners();
@@ -977,6 +983,14 @@ namespace CheesyFX
toeColliderOffset.SetValToDefault();
toeColliderRotation.SetValToDefault();
toeColliderScale.SetValToDefault();
+ // SuperController.LogMessage(new StackTrace(true).ToString());
+ string msg = "Reset @"+Time.realtimeSinceStartup.ToString();
+ float rotation = lFoot.transform.localRotation.eulerAngles.x;
+ msg += $" right rot={rotation}";
+ rotation = rFoot.transform.localRotation.eulerAngles.x;
+ msg += $"left rot={rotation}";
+ SuperController.LogMessage(msg);
+
rToeGPUCapsule.enabled = lToeGPUCapsule.enabled = lHeelGPUCapsule.enabled = rHeelGPUCapsule.enabled = false;
reloadButton.label = reloadLabel = "<b>Toggle</b>: None";
if (!autoCalculateDeltas.val)
@@ -1299,6 +1313,7 @@ namespace CheesyFX
var col = collisionEnabled.val;
collisionEnabled.val = false;
SetFootPose(0f);
+ SuperController.LogMessage($"SetFootPose(0) @{Time.realtimeSinceStartup}");
yield return new WaitForSeconds(.5f);
CalculateDeltas();
OnFootPoseChanged();
@@ -1327,8 +1342,16 @@ namespace CheesyFX

private void CalculateDeltas()
{
- rFootSlopeDelta.val = rDelta = GetDelta(rFoot.transform.localRotation.eulerAngles.x);
- lFootSlopeDelta.val = lDelta = GetDelta(lFoot.transform.localRotation.eulerAngles.x);
+ string msg = "deltas @"+Time.realtimeSinceStartup.ToString();
+ // float rotation = lfootCTRL.transform.localRotation.eulerAngles.x;
+ float rotation = lFoot.transform.localRotation.eulerAngles.x;
+ msg += $" right rot={rotation}";
+ rFootSlopeDelta.val = rDelta = GetDelta(rotation);
+ rotation = rFoot.transform.localRotation.eulerAngles.x;
+ // rotation = rfootCTRL.transform.localRotation.eulerAngles.x;
+ msg += $"left rot={rotation}";
+ SuperController.LogMessage(msg);
+ lFootSlopeDelta.val = lDelta = GetDelta(rotation);
}

private float GetDelta(float rotation)
@@ -1389,12 +1412,14 @@ namespace CheesyFX
if (preset != null)
{
toggleItemButton.label = toggleItemLabel = $"<b>Toggle</b> {StripNonAlphaNum(GetItemNameFromCustomClothingUID(dci.uid))}";
+ itemToStore.val = itemName; // TODO: this caption is not red right after plugin starts
if(enabled)
{
+ SuperController.LogMessage($"equip @{Time.realtimeSinceStartup}:{preset}");
LoadFromPath(preset);
if(autoCalculateDeltas.val)
{
- if (currentPreset != null) StartCoroutine(IECalculateDeltas());
+ if (currentPreset != null || (Time.realtimeSinceStartup - lastClothingDisabled) < .2f) StartCoroutine(IECalculateDeltas());
else CalculateDeltas();
}
}
@@ -1406,19 +1431,27 @@ namespace CheesyFX
{
activeItems.Remove(itemName);
activeItemNames.Remove(itemName);
- if (currentPreset == null || currentPreset == preset)
+ if (currentPreset != null && currentPreset == preset)
{
+ SuperController.LogMessage($"remove @{Time.realtimeSinceStartup}:{currentPreset}");
+ // possibly the user make a preset with either the platform and the heel item, so we don't want to get here re╤Бursively
+ ClothingEquippedEventHandler.skip = true;
if(currentPreset != null) EquipLinkedItems(LoadJSON(currentPreset).AsObject, false);
+ ClothingEquippedEventHandler.skip = false;
currentPreset = null;
+ lastClothingDisabled = Time.realtimeSinceStartup;
// currentItem = null;
// toggleItemButtonUid.label = "Current item: None"
Reset();
+ itemToStore.val = "None";
}
}
itemToStore.choices = activeItemNames;
aditionalItemChooser.choices = activeItemNames;
}

+ float lastClothingDisabled = 0;
+
private void HandShakeWithFlexIt()
{
for (int i = 0; i < transform.parent.childCount; i++)
@@ -1938,6 +1971,7 @@ namespace CheesyFX

public class ClothingEquippedEventHandler : MonoBehaviour
{
+ public static bool skip;
private void OnEnable()
{
var dci = gameObject.GetComponent<DAZClothingItem>();
@@ -1947,6 +1981,7 @@ namespace CheesyFX

private void OnDisable()
{
+ if (skip) return;
var dci = gameObject.GetComponent<DAZClothingItem>();
HeelAdjust2.onClothingItemToggled(dci, false);
// $"{gameObject.GetComponent<DAZClothingItem>().uid} unequipped".Print();
There are some action to reduce unwanted callback also.
I wonder why do you use (DAZBone)lFoot but not (FreeControllerV3)lfootCTRL for calculating deltas? That way you can't start-up the script properly if it has been launched on a atom with feet already bent (you see the angles in the video below).
Hey! Thanks for the contribution and the detailed explanations. Really appreciated!
I'll implement them, although I only get error Nr. 3. This didn't bother me much though cause I usually just reaply the PoseMe pose to have it fixed.

Using the controller for the deltas is not a good idea in general. The controller isn't a good measurement for the ankle rotation when it is in "On" state or if joint drives are involved. It can only be used when in "Locked" state, which is very rarely the case in the average scene on the hub, sadly even for standing poses. Probably because Timeline does not support state switching (at least without big time hassle).

On another note: are you planing to release your girl? She really has a killer-body, especially the lower part 😳. If not, it's ok. I've never come to release mine either. Some bigger pictures would be nice though. :p
And what about the various clothing presets you seeme to have created? There are some really cool ones based on the small previews visible (Marciana, Skirt-Rave etc). I'd love to get them!
 
Last edited:
Thank you for your reply. Hope you can make it better as that your great creation I use all the time, thank you for that!
I attach a video explaining the bug#1: it just should start with "Lock Toe Joint" unchecked to reproduce it.
Also I attached a video with some another (better?) way to change feet angle when a preset applied: you wait for some time after the current shoe removed (0.2 sec for example) and if you see a new shoe equipped then you cancel unbending and apply a new bend right a way. That way is demonstrated in the video and the code is HA-2.patch but it uses FreeControllerV3 that as I understand already is not good idea. Later it could try to realize it with DAZBone.

About the girl: please look here and I attached a .vap file I just created (it is .zip file actually) for you but much of the clothes are unpacked for me too so there is no direct hub link but the titles are mostly unchanged so you can find them here easily. Some textures modified too (with Paint ;) ) so I don't include it. Please tell me if that share way is not working for you or if the video is not visible (I can not see them by myself mostly on the site because of blocking) then I will try some another sharing service (much of them are blocked too).
 

Attachments

  • cheesy_share.vap
    763.8 KB · Views: 0
  • HA_21-bug_1-expl-converted.mp4
    1.1 MB
  • HA_21-Remove-delay-way-converted.mp4
    2.4 MB
I made another version with DAZBone and feet unbend delay with few more bugfixes. But there are some unfinished thing and one bug I haven't fix yet. If you agree with my edition I will share the rest later. The patch is for the initial .cs version.
 

Attachments

  • HA-3.patch.txt
    25.5 KB · Views: 0
Back
Top Bottom