@DrJustice just been taking a look at your preset manager (only code, not played with it yet )
for discussion purposes i.e. its not criticism, its just great to have someone playing in this area, so can discuss these things. ... also I'm interested if my understanding is correct
I notice your using PExch, Im assuming this is fully populated on the patch (I've not checked, but explains how your PM works)
as such, I think this is not really saving presets, but saving a full set of current parameters values. presets are stored value in 'p' (i know not best name!) and are a subset of the parameters. so 'theoretically' it should only save those, and also I think it should populate 'p', since otherwise if a user does a recall of a preset later, they will not pick up the values that they earlier loaded.
I raised, this as potentially, there is going to be confusion, between the interplay of presetmanger and recall/storing of presets ... and frankly, I think presets already confuse many (including me )
also... and this may not matter... Id assume PExch changes as your patch changes... so does any patch change invalidate the preset stored?
of course my understanding may be incorrect, as I took a different approach on Push (as I wasn't storing the data), I used the global object parameter table (ObjectKvpRoot) , and just presented this to the user.
however, this also has 'issues' as its only the underlying parameters, so it doesn't have any knowledge of a parameter being on a 'subpatch', no issue for storage, but means from a UI perspective, you cannot show parameters that have been 'placed on the parent'
of course, the advantage for display, was also it has details about max/min , which aren't in PExch... unfortunately I dont think there is a relationship between PExch and the main object table (as far as i remember when playing with this)
here kind of illustrates where the two worlds divide:
parent->PExch[PARAM_INDEX_square__3_pitch].pfunction = pfun_signed_clamp;
SetKVP_IPVP(&KVP_instancesquare__3_pitch,ObjectKvpRoot, "square_3" ,&parent->PExch[PARAM_INDEX_square__3_pitch], -1<<27, 1<<27);
KVP_RegisterObject(&KVP_instancesquare__3_pitch);
thats this shows, is the global table knows about the parameters and all its attributes but only knows at PExch instance, it has no knowledge of where it comes from e.g. parent/Pexch idx , similarly parent->pExch has no understanding of the actually parameter that is created in the global parameter table.
anyway, this is a bit fyi and discussion only... alot of this matter only when building controllers which want to expose the parameters in a sensible way to the user. but I think some of it is 'interesting' to storing patch state.
note: the global parameter table has the object name, which is what I kind of referred to above, this name only changes if the user changes object names, rather than patch structure.
I fear PExch and the index in ObjectKvpRoot are both based on the order things are built in a patch, which in turn is position on the patch canvas vs other objects. (though Ive not verified this)
anyway, perhaps this should be a separate topic, but i thought Id start here... as may not interest you at all