Dynamic Array of Objects - mobj - an Abstraction
I'm working on an abstraction to create an array of objects that can be expanded or contracted on the fly. I call it "mobj" (multi-object, or, if you like, mob of objects). It's meant for you to have the patch saved in with the patch you want to use it in, then create an instance of it. If instantiated properly, you can treat the mobj just like you would treat the object that it is an array of, provided you prepend all input messages with a number from 0 to n-1 (which is treated like an index into the virtual array to route the input to the proper instance in the array) and acknowledge that all output messages will have the same prepended index.
This functionality is achieved by creating/deleting/patching the array of objects with scripting messages to a thispatcher object.
And the arguments for instantiation:
The first argument when you create an instance of the abstraction is the number of inlets for the mobj. This is meant to match the number of inlets of the type of object you want to create.
The second argument is the number of outlets of the mobj. Same idea, you match it to the number of outlets on the type of object in the array.
The third argument is the number of objects in the array.
The fourth argument is the name to use when creating objects, and all subsequent arguments will be the arguments of the objects created.
For example, you could create an array of 8 [line 0. 10] objects with:
[mobj 3 2 8 line 0. 10]
To change the number of objects in the array on the fly, simply pass any inlet of the object the message (num $1) or (number $1), and the correct number of objects is added or subtracted from the array. To change the number of inlets of the mobj. pass the message (inlets $1). All inlets are automatically routed to the corresponding inlet of each object in the array, provided that the object has enough inlets (if it doesn't, the inlet isn't routed to anything). The number of outlets can be changed in the same way (outlets $1). You can also change the objects themselves on the fly if you have the need, by passing (obj $1 $2 $3 ... $n) or (object $1 $2 $3 ... $n), in which $1 is the object name and all following terms are arguments to the object. Note that these object creation parameters will only apply to all subsequent objects that are created by sending a (num $1) increase message. Note that this means the array can actually contain different kinds of objects, or objects with different arguments. If you wish for all of the array objects to be recreated with the type you specify with (obj $1 $2 $3 ... $n), all you have to do is pass a (remake) message and all array objects will be deleted and remade.
- - -
So far, all of this is working properly, but there is one hitch: when you save and reload a patch using these mobj, all patch cords to and from the mobj are not recreated on reload. This is because each mobj begins with no inlets or outlets, then creates them as prompted by the patcherargs object in the mobj, and the parent patch always tries to create the patch connections before the inlets actually exist. So, as of right now, mobj only works if you connect up the inputs and outputs every time you load up a patch. I would love to hear some possible solutions to this problem, because right now, I am getting discouraged.
Here is the code. Save it in a folder as mobj.maxpat along with a new patch to use it in and see what I mean.
When mobj is done and working well, it's going to do so much for my Max workflow. I hope it can be of some use to others as well.
Oh, I should add that when you paste the above code, it will go ahead and create an array of 8 [i] objects based on the default arguments in patcherargs. In order for the patch to work correctly, YOU MUST delete ALL of the objects on the left side of the patch, including inlets and outlets. These will all be created according to arguments, and if they are there before instantiation, it will screw up the array that gets created.
list-accum: No such object
For the inlets/outlets, the usual solution offered is to include some hypothetical max number of in/outlets (99?) in the mobj abstraction and have the script delete the unused ones at instantiation.
I suppose I can give the maximum inlets/outlets thing a try. It seems reasonable enough.
And, whoops, I suppose I must have downloaded list-accum from some external repository. I can try to to reimplement the patch without it, if other people are interested in using mobj.
Okay, I've got this working using 100 inlets and outlets upon instantiation, then eliminating all but the needed ones.
My only problem now is that, because the abstraction instance begins with so many inlets and outlets, the patching rectangle always comes out huge - a width of 1355.5 (which is, I guess, the default patching rectangle width for an object with 100 inlets).
Is there a way for me to make the abstraction change the size of its own patching rectangle in the parent patch? (Or to make it always come up as a reasonable size and not have to go in to the inspector to change the number by hand every time I instantiate an mobj or try to change its arguments?)
[list-accum] can be replaced by [zl group].
any chance of a max4 patcher, or at least a .maxpat binary or a little jpg? i am interested.
-110
So, I should be able to send a (sendbox size 150 20) message to the abstraction to change the size, and I can actually send this message from the inside of the abstraction with the [thispatcher] object. The problem is that the whatever is connected to the first inlet on the inside of the abstraction receives the message and resizes it rectangle, rather than resizing the rectangle of the abstraction within the parent patch.
So, I'm still at a loss for how to resize the rectangle from within the abstraction.
Also, I'm not sure what it would entail for me to convert this to a max4 patcher or maxpat binary for you, Roman, but I can certainly look into it. I've been doing Pd/Max stuff for several years now, but I never really learned about how to properly share a maxpatch with others in a way that would be useful to them.
Maybe you could do something with js sending a message out to the parent patcher telling the abstraction box to resize?
not sure about the resizing, but for the Max4 stuff, you'd need to build the example patch in Max 4 and share that text code. Then anyone with Max 4 or 5 could open it, but Max 4 users can't open Max 5 code directly. (backwards compatible but not forwards)
if you can give me .maxpat file or a picture (with everything unlocked/visible) i should
be able to build a max 4 version from it and upload it when everything works.
we are getting lesser, but there are still many lots of people on max v4, which can not
open max5 code. but we can look at max5 patches using the runtime and copy stuff
manually.
-110
So, you want to port it to v4 from the v5 maxpat file?
Yeah, of course I can upload it. I'm just glad to hear that other people have use for this as well.
The maxpat is attached. I haven't changed [list-accum] to the more universal [zl group] yet, but you, being the one who suggested it, should have no trouble making that switch. Also, I hope the thispatcher scripting commands work the same for v4. Let me know if you have any trouble getting it to work correctly. It's kind of sensitive.
Also, the sizing problem makes it kind of awkward to use, so if you come up with any solutions now that you have the code, please let me know. It's the only thing standing in the way of this being a practical abstraction for everyday use.
thanks. i will be able to just change things as soon as i understand what it should do.
right now max 506 runtime does not display the message boxes. :D
@Roman - have you seen the supercollider code that converts from Max5 to Max 4?
I find it handy every now and again as I am still working across both versions. Of course you have to run supercollider to do the conversion but it is a lot easier than doing it manually. I can't remember exactly how you do the conversion but it is not too complicated. There are some other posts here on the forum about it if you get stuck.
You can get the code here:
HTH
A.
i know it but i dont have sc3 installed :)
Well, if you need any help from me with piecing things together, let me know.