VEX: choose between operators (+ - * /) in the interface

   485   6   0
User Avatar
Member
1160 posts
Joined: April 2017
Offline
I have 4 float masks on points. I'd like to make a wrangle with a dropdown menu to decide what operation to use for each mask (add, subtract, multiply or divide). Will I have to make a bunch of if statements or is there an easier way?

-Olivier
User Avatar
Member
9326 posts
Joined: July 2007
Offline
1. I'd consider if statements pretty clean and very readable for this purpose, you can make a function that combines masks and use it in for loop for each mask or whatever you are doing

float combine_masks( float mask0, mask1; int op){
    float out = mask0;
    if ( op == 0 ) out += mask1;
    if ( op == 1 ) out -= mask1;
    if ( op == 2 ) out *= mask1;
    if ( op == 3 ) out /= mask1;
    return out;
}

2. you can also inject Hscript expression into VEX snippet using `` which can for example be used to evaluate a parameter containing an operator string, this is pretty ugly though, not the most intuitive and if your injected expression is time dependent it will force the VEX code to recompile all the time so you need to be careful what you use this for

3. there is also Attribute Combine SOP which has all the options for combining multiple attributes using various operations and processing, so you can potentially wrap that into your HDA instead if it does what you require
Edited by tamte - Oct. 28, 2025 20:18:34
Tomas Slancik
CG Supervisor
Framestore, NY
User Avatar
Staff
650 posts
Joined: Aug. 2019
Offline
tamte
you can make a function that combines masks and use it in for loop for each mask or whatever you are doing
If the number of loop iterations is high, you may get better performance by putting the conditional outside of multiple loops.

e.g., instead of:
for (int i = 0; i < 10000, i++)
{
if ( op == 0 ) out += mask1;
else if ( op == 1 ) out -= mask1;
else if ( op == 2 ) out *= mask1;
else if ( op == 3 ) out /= mask1;
}

It may be faster to do:
if (op == 0)
{
for (int i = 0; i < 10000, i++)
out += mask1;
}
else if (op == 1)
{
for (int i = 0; i < 10000, i++)
out -= mask1;
}
... etc

This reduces the number of conditions that need to be checked per iteration and can help the compiler optimize.

Note that I also replaced the if chain with an else-if chain. This allows the code to short-circuit, meaning that if one of the upper conditions is true, it doesn't need to check any of the lower conditions. e.g., if op == 0 is true, it doesn't need to check op == 1, op == 2 or op == 3, as op can only have a single value.
User Avatar
Member
1160 posts
Joined: April 2017
Offline
Thanks for both replies, I apreciate!

@tamte : What is that line about? I've done vex for many years and never came across this before:
float combine_masks( float mask0, mask1; int op){

Bonus question: if I want a toggle for +-*/ so any click on one toggle will de-click the other options?
Edited by olivierth - Oct. 29, 2025 09:22:36

Attachments:
Houdini_Operations_toggles_01.jpg (18.7 KB)

User Avatar
Member
9326 posts
Joined: July 2007
Offline
olivierth
@tamte : What is that line about? I've done vex for many years and never came across this before:
float combine_masks( float mask0, mask1; int op){
it defines a function [www.sidefx.com] so that you can use it later instead of typing the whole thing again, so later you can just do

f@maskA = combine_masks( f@maskA, f@maskB, 0 ); // does f@maskA + f@maskB 
f@maskC = combine_masks( f@maskA, chf("scale") , 2 ); // does f@maskA * chf("scale")
f@maskD = combine_masks( f@maskA, f@maskB, chi("opD") ); // does f@maskA <opD> f@maskB
//...
Edited by tamte - Oct. 29, 2025 10:18:51
Tomas Slancik
CG Supervisor
Framestore, NY
User Avatar
Member
1160 posts
Joined: April 2017
Offline
AAAaaahhhhhh! Thanks!
User Avatar
Member
625 posts
Joined: March 2014
Offline
@olivierth:
To add to Tomas‘ answer:
The functions that you use and know in vex are all predefined functions (by SideFX devs).
But you can create your own user-defined function if you need one.

The user defined function needs a type (float, vector, void etc) and arguments (as „inputs“), similar to any function you know from VEX already. And will output a result of the defined type.

Also, you can overload functions (the multiple „versions“ some VEX functions have in the documentation) to output a different data type.

In your example above, this exact function you need is not available in VEX, therefore you create your „own version“ of it. Hence making it available for reuse.

Hope this helps
Edited by fuat - Oct. 30, 2025 12:55:45
Fuat Yüksel
  • Quick Links