• 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

Active member
Joined
Dec 29, 2023
Messages
163
Reactions
54
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
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.

Tested only in local (I don't know how to create a VAR yet)
With classes extending JSONStorable I mean JSONStorableFloat, etc
And my question if it's ok to use that even when I don't want to preserve those sliders, they are dynamic, I'm creating them and destroying when user click some keyframe (this is what I need to preserve, keyframes, not sure how yet).

My problem is to understand the JSONStorable classes, becasue I don't want to store the sliders, but I don't know how to create sliders without JSONStorable, maybe it's not important, just asking to learn something new or to understand it better
 
Upvote 0
You're confusing the data (JSONStorable) and the UI component (Slider).
A slider is not stored, it's only giving a feedback of the JSONStorable data to the user.

You can create a JSONStorableFloat, set it's value, save it, without ever showing a slider to the user.
Check my plugins (for instance VAMStory or VAMMoan 2), you'll see different ways of creating/using JSONStorable.
You can also setup a JSONStorable to not save data like this :

C#:
new JSONStorableString("MyString", "Default"){isStorable=false,isRestorable=false};

One note: be very careful with UI/Sliders etc, having dozens (or more) UI components can kill the frametime. If you're planning on having a huge AI, you will need to make a dynamic UI.
 
Upvote 0
You're confusing the data (JSONStorable) and the UI component (Slider).
A slider is not stored, it's only giving a feedback of the JSONStorable data to the user.

You can create a JSONStorableFloat, set it's value, save it, without ever showing a slider to the user.
Check my plugins (for instance VAMStory or VAMMoan 2), you'll see different ways of creating/using JSONStorable.
You can also setup a JSONStorable to not save data like this :

C#:
new JSONStorableString("MyString", "Default"){isStorable=false,isRestorable=false};

One note: be very careful with UI/Sliders etc, having dozens (or more) UI components can kill the frametime. If you're planning on having a huge AI, you will need to make a dynamic UI.

Yes I know the slider won't be saved, but I thought every JSONStorableX created will be saved automatically (and then recovered too somehow? I don't know how to recover the state of my plugin)
Maybe this is the line:
Code:
this.RegisterFloat(storable);
If I comment that line the slider works fine anyway, and maybe only registered JSONStorableX objects are saved/loaded automatically?
 
Upvote 0
Yes I know the slider won't be saved, but I thought every JSONStorableX created will be saved automatically
My problem is to understand the JSONStorable classes, becasue I don't want to store the sliders, but I don't know how to create sliders without JSONStorable

Are you only starting (as a general concept) with code? Because you clearly stated "store sliders". It's not mean or anything... it's just better to understand each other and use the same terminology. Or maybe you're not a native english speaker?

Yes, a JSONStorable needs to be registered to be saved. You can also create your own save process in the plugin.
 
Upvote 0
Are you only starting (as a general concept) with code? Because you clearly stated "store sliders". It's not mean or anything... it's just better to understand each other and use the same terminology. Or maybe you're not a native english speaker?

Yes, a JSONStorable needs to be registered to be saved. You can also create your own save process in the plugin.
I'm not native english speaker
I just want to understand JSONStorable classes, why they exist in VAM, when we need them and when not

ALso, is there any tutorial to create my own save/load process in the plugin, would be nice if I can restore the state of my plugin with the normal "load/save plugin preset" from VAM (right now I'm creating custom buttons for save/load custom .json)
 
Upvote 0
I'm not native english speaker

Ok cool! :3


I just want to understand JSONStorable classes, why they exist in VAM, when we need them and when not

Don't overthink this. JSONStorable provides a way to store data, that's pretty much it. You can do whatever you want with this. But they can be the core of your plugin without having to dev your own save system.
Or you can go the hard way and code everything yourself. I think it's not hard to conclude what is the best way ;)


ALso, is there any tutorial to create my own save/load process in the plugin, would be nice if I can restore the state of my plugin with the normal "load/save plugin preset" from VAM (right now I'm creating custom buttons for save/load custom .json)

I wrote a CUA Editor a long time ago. This gives you a solid base to understand how to save data. (even if you don't need a CUA). I'm planning on releasing the "ideal" CUA tutorial as I finally (after years of iteration) found the best way possible to handle CUAs. But this old one already gives you enough information.

The presets are very tightly connected to JSONStorables of the target atom. If you prefer if you save a preset for an "Empty" or a "CUA", storing data through JSONStorables is way better as the are natively handled by the preset system.

But creating your own restore/save routine will work too, you just need to do it properly so that the presets stores the data correctly.
 
Upvote 0
Back
Top Bottom