Hi everyone,
I’ve spent some time recently trying to implement expander modules (with bi-directional communication) for a project I’m working on. Thanks to the Module expanders tutorial thread and a fair amount of experimentation and reading others’ code, it’s working fine. Many thanks to @clone45, @CountModula, and @marc_boule!
Because things are somewhat buried in that thread, I wanted to share a simple example in the hopes that it can save somebody else some time. Here’s a little module that is an expander for itself - slide as many together as you like. Each displays its own position and the total number in the group.
The widget implements the beautiful seamless expander behaviour seen in MindMeld’s MixMaster & AuxSpander.
The module code is:
struct expMessage { // contains both directions
unsigned int numModulesSoFar = 0; // This will travel rightward
unsigned int numModulesTotal = 0; // This will travel leftward
};
struct TwoWayExpander : Module {
expMessage leftMessages[2][1]; // messages to & from left module
expMessage rightMessages[2][1]; // messages to & from right module
unsigned int numMe = 0;
unsigned int numModules = 0;
TwoWayExpander() {
leftExpander.producerMessage = leftMessages[0];
leftExpander.consumerMessage = leftMessages[1];
rightExpander.producerMessage = rightMessages[0];
rightExpander.consumerMessage = rightMessages[1];
} // module constructor
void process(const ProcessArgs &args) override {
bool expandsLeftward = leftExpander.module && leftExpander.module->model == modelTwoWayExpander;
bool expandsRightward = rightExpander.module && rightExpander.module->model == modelTwoWayExpander;
expMessage* leftSink = expandsLeftward ? (expMessage*)(leftExpander.module->rightExpander.producerMessage) : nullptr; // this is the left module's; I write to it and request flip
expMessage* leftSource = (expMessage*)(leftExpander.consumerMessage); // this is mine; my leftExpander.producer message is written by the left module, which requests flip
expMessage* rightSink = expandsRightward ? (expMessage*)(rightExpander.module->leftExpander.producerMessage) : nullptr; // this is the right module's; I write to it and request flip
expMessage* rightSource = (expMessage*)(rightExpander.consumerMessage); // this is mine; my rightExpander.producer message is written by the right module, which requests flip
if (expandsLeftward) { // Add to the number of modules
numMe = leftSource->numModulesSoFar + 1;
} else { // I'm the leftmost. Count myself.
numMe = 1;
}
if (expandsRightward) {
rightSink->numModulesSoFar = numMe; // current count
numModules = rightSource->numModulesTotal; // total from right
rightExpander.module->leftExpander.messageFlipRequested = true; // tell the right module to flip its leftExpander, putting the producer I wrote to into its consumer
} else { // I'm the rightmost. Close the count loop.
numModules = numMe;
}
if (expandsLeftward) {
leftSink->numModulesTotal = numModules; // total goes left
leftExpander.module->rightExpander.messageFlipRequested = true; // tell the left module to flip its rightExpander, putting the producer I wrote to into its consumer
}
} // process
}; // TwoWayExpander
The repo can be found at https://github.com/landgrvi/VGLabs-TwoWayExpander. Thanks again, and enjoy!