Store Custom Class in ValueTree

Hi!
I’ve started using Value Trees and I am able to store and retrieve basic types like strings or floats, as they are easily cast to juce::var. My question is: how is it possible to pass custom classes into a Value Tree?

I have a custom class like this, very simple:

class Scale
{
public:
    Scale(int tonic, NotePattern scaleTemplatePattern, juce::String scaleType);
    virtual ~Scale();

    juce::String getName() const;
    juce::String getType() const;
    int getTonic() const;
    NotePattern getNotePattern() const;

    bool doesIncludePitch(int pitch) const;
    bool doesIncludePattern(NotePattern& notePattern) const;
    
private:
    juce::String _name;
    juce::String _scaleType;
    int _tonic;
    NotePattern _notePattern;

};

And now I want to store an instance of this class as a Value Tree property.
I’ve read about dynamic_casts and ReferenceCountedObjects, but I’m still unsure of how to go about this.

I’d really appreciate any guidance or help on this. :slight_smile:
Thanks!

I would do this as a ValueTree child. <Scale name="" type="" tonic="" notePattern="">. I have a base class called ValueTreeWrapper, which I derive domain specific classes from, which have setters/getters/callbacks… This is the basic idea. The wrapper is meant to only be used locally, not shared, in that it only has single callbacks, not lists. This is super useful in that I don’t have to think about the ValueTree specifics in the everyday code. :slight_smile:

class ScaleWrapper : public ValueTreeWrapper
{
public:
    void setName (String name);
    void setType (ScaleType type);

   String getName ();
   ScaleType getType ();

   std::function<void(String name) onNameChange;
   std::fucntion<void(ScaleType type) onTypeChange;

private:
}
1 Like

You can only really store basic types in the value tree. Under the hood it converts to XML, so if it’s not a type XML will support it won’t convert nicely.

This sometimes means arrays etc need to get a bit funky in there… I’ve tried store some JSON strings but that leads to weird formatting in the ValueTree if you look at the XML. I’ve settled on generating comma delimited strings for arrays, but in essence I’ll usually add to my class:

/* */
String getValueTreeID();

/* */
ValueTree toValueTree() {}

/* */
void updateFromValueTree(ValueTree& inTree) {}

Then use this for create serialization functions, and add the value tree for the specific object / class as a child tree / node in the parent ValueTree

then you can do something like:

ValueTree& child = parent_tree.getChildForID(class->getTreeID);
class->updateFromValueTree(child);
1 Like

Thank you @cpr2323 and @jakemumu for the ideas!
I’ll try some things :slight_smile:

I just watched this talk from ADC '17 that explains @cpr2323’s method of using a wrapper in more detail. Great stuff, really helpful for others wondering about the some problem :slight_smile:

3 Likes

This is the exact talk that gave me the ValueTree education required to not only start using them, but to really lean into them for data models.

2 Likes