• Hi Guest!

    We are extremely excited to announce the release of our first Beta for VaM2, the next generation of Virt-A-Mate which is currently in development.
    To participate in the Beta, a subscription to the Entertainer or Creator Tier is required. 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.

Question Do we need to use JSONStorable?

henshin

Member
Joined
Dec 29, 2023
Messages
157
Reactions
23
I'm a bit confused about these classes extending JSONStorable, I see they are usually used in UI components (Utils from MacGruber for example)
But are they only required if we need to persiste the state of those components?
I mean if I'm creating components dynamically and use components from MacGruber they will make a mess in the final json creating when saving the scene?

Example:
I'm saving in my plugin the current active morphs in a List (to save keyframe of different facial expressions)
In my UI the user can then select any of those keyframes, the morphs are applied and I want to show a slider for those morphs too so the user can edit them
But I don't need to persist these sliders (or maybe yes, I don't know how to save the state of my plugin with the list of morphs and their settings yet)

I'm doing something like this now:

Code:
private void UpdateCurrentKeyframeMorphs()
        {
            List<DAZMorph> activeExpressionMorphs = GetAllActiveMorphs(true);
            MorphKeyFrame frame = morphFrames[currentKeyframeIndexActive];
            frame.morphsAndValues = new List<MorphUidAndValue>();
            foreach (var morph in activeExpressionMorphs)
            {
                frame.AddMorphAndValue(new MorphUidAndValue(morph.uid, morph.appliedValue, morph.morphName));
            }
        }
        private UIDynamicSlider CreateMorphSlider(DAZMorph morph)
        {
            string morphName = morph.morphName;
            float defaultValue = morph.jsonFloat.defaultVal;
            float min = morph.jsonFloat.min;
            float max = morph.jsonFloat.max;
            JSONStorableFloat storable = new JSONStorableFloat(morphName, defaultValue, min, max, true, true);
            storable.storeType = JSONStorableParam.StoreType.Full;
            UIDynamicSlider slider = this.CreateSlider(storable, true);
            this.RegisterFloat(storable);
            storable.valNoCallback = morph.morphValue;
            // storable.val = morph.morphValue;
            storable.setCallbackFunction += (float newVal) =>
                        {
                            morph.morphValue = newVal;
                            // appliedValue ??
                            UpdateCurrentKeyframeMorphs();
                        };
            return slider;
        }

And when a new Keyframe is selected I remove all the sliders and create new ones:

Code:
private void RefreshMorphSlidersForKeyframe(int selectedKeyframe)
        {
            Utils.RemoveUIElements(this, morphSliders.Cast<object>().ToList());
            morphSliders = new List<UIDynamicSlider>();
            if(selectedKeyframe >= 0 && morphFrames.Count() > selectedKeyframe)
            {
                foreach (MorphUidAndValue muv in morphFrames[selectedKeyframe].morphsAndValues)
                {
                    DAZMorph morph = GetMorphByUid(muv.uid);
                    morphSliders.Add(CreateMorphSlider(morph));
                }
            }
        }

It works fine, but I'm not sure if this is the correct way to work in VAM
 
Classes extending JSONStorables? Wut?

I don't see anything extending a JSONStorable in your code. Only custom sliders which are UI components updating values for a specific JSONStorableFloat.

I actually have trouble understanding your question/issue here. You want to save the data or you don't want to save the data?

Actually, it would be better if you could break down your goal, like :
  1. Update morphs for a character
  2. Save appearance/data
  3. ...etc
... because not knowing your exact goal doesn't help telling you if it's the ideal choice.

Beyong that... did you test your plugin? does it work? do you get the intended result? In local AND .var mode? If the answer is yes, then you're good. Maybe optimizations are possible, but there are dozens of way to do things... result matters, the rest does not. You'll get better and more optimal over time.
 
Upvote 0
Back
Top Bottom