Storm Keeper Posted March 16, 2015 Share Posted March 16, 2015 Hello, guys. While developing some complex operators in HDK I realized that defining lots of parameters becomes a bit tedious and routine task. So I decided to simplify this using C++ templates, and that's what I want to share. All you need is to define these parameters inside newSopOperator() function. Here's how it looks like: void newSopOperator(OP_OperatorTable *table) { PRM_LIST_START(myTemplateList); PRM_FLT(flt, "FLT", 0.01); PRM_INT(integer, "INT", 3); PRM_TOGGLE(toggle, "TOGGLE", ON); PRM_STRING(string, "STRING", "Hello, World!"); PRM_FLT2(flt2, "FLT2", 0.01, 0.02); PRM_FLT3(flt3, "FLT3", 0.01, 0.02, 0.03); PRM_XYZ(xyz, "XYZ", 0.01, 0.02, 0.03); PRM_RGB(rgb, "RGB", 0.3, 0.15, 0.85); PRM_UVW(uvw, "UVW", 1, 0.5, 0); PRM_BUTTON(btn, "Button", callback); PRM_LIST_END(); table->addOperator( new OP_Operator("hdkParmsDemo", "HDK Parms Demo", SOP_HDKParmsDemo::myConstructor, myTemplateList, 0, // Min # of sources 0, // Max # of sources 0) ); } The same easy thing is about reading: // Automatically create variables with parameter names READ_FLT(flt); // double flt; READ_INT(integer); // int integer; READ_TOGGLE(toggle); // bool toggle; READ_STRING(string); // UT_String string; READ_VEC2(flt2); // UT_Vector2 flt2; READ_VEC3(flt3); // UT_Vector3 flt3; Header and sample SOP are attached in the archive. Would appreciate your feedback HDK_Parms.zip Quote Link to comment Share on other sites More sharing options...
Guest mantragora Posted March 16, 2015 Share Posted March 16, 2015 (edited) So I decided to simplify this using C++ templates, and that's what I want to share. Macros NOT templates. Idea is old. I'm using it for more than parameters. For example to define selector for my SOP I have two lines of code. One is definition and second implementation. REUSABLESELECTOR_DECLARATION(PointGroup) REUSABLESELECTOR_IMPLEMENTATION(PointGroup, SELECTOR_FOO_CLASSNAME, SOP_FOO_OPERATOR_SMALLNAME, SOP_PARMS_NAMESPACE_NAME(____unique_sop_title____)::UI::input0PointGroup_Parameter, false) As for parameters, I'm building them as a piramid. Example: #define ____default_toggle_data____(smallname, bigname, defaultstate, varname)\ static auto varname##ToggleParm_Name = PRM_Name(smallname, bigname);\ static auto varname##ToggleParm_Default = PRM_Default(defaultstate); #define DEFAULT_TOOGLE_NO_JOIN(smallname, bigname, defaultstate, varname)\ ____default_toggle_data____(smallname, bigname, defaultstate, varname)\ auto varname##Toggle_Parameter = PRM_Template(PRM_TOGGLE, 1, &varname##ToggleParm_Name, &varname##ToggleParm_Default); #define DEFAULT_TOOGLE_JOIN(smallname, bigname, defaultstate, varname)\ ____default_toggle_data____(smallname, bigname, defaultstate, varname)\ auto varname##Toggle_Parameter = PRM_Template(PRM_TOGGLE | PRM_TYPE_JOIN_NEXT, 1, &varname##ToggleParm_Name, &varname##ToggleParm_Default); #define CUSTOM_TOOGLE_ON_PARAMETER(smallname, bigname, varname) DEFAULT_TOOGLE_NO_JOIN(smallname, bigname, 1, varname) #define CUSTOM_TOOGLE_OFF_PARAMETER(smallname, bigname, varname) DEFAULT_TOOGLE_NO_JOIN(smallname, bigname, 0, varname) #define CUSTOM_TOOGLE_ON_JOIN_PARAMETER(smallname, bigname, varname) DEFAULT_TOOGLE_JOIN(smallname, bigname, 1, varname) #define CUSTOM_TOOGLE_OFF_JOIN_PARAMETER(smallname, bigname, varname) DEFAULT_TOOGLE_JOIN(smallname, bigname, 0, varname) #define DEFAULT_FLIP_NORMALS_PARAMETER() CUSTOM_TOOGLE_OFF_PARAMETER("flipnormals", "Flip Normals", flipNormals) ____default_toggle_data____ is a base macro. I'm using ____foo____ notation to mark all things that shouldn't be used directly or shouldn't be used outside of the file they are defined in. So in this example base macro is used as a starting point for other macros.Then you got macros that start as DEFAULT_TOOGLE_NO_JOIN and DEFAULT_TOOGLE_JOIN in which you can modify all data, including variable name in which they will be stored. Then you have CUSTOM_TOOGLE_ON_PARAMETER etc... which are the most common presets I use for toggle parameter. And the last one is DEFAULT_FLIP_NORMALS_PARAMETER in which you cannot change anything, including variable name. This forces consistency in all my operators, they all use exactly the same small and big name for Flip normals + variable is always called the same, so I don't have to search to much WTF I was thinking when I defined it. Another example with Int prameter: #define ____custom_integer_rangemintype_t_rangemaxtype_t_parameter____(smallname, bigname, rangemin, rangemax, rangemintype, rangemaxtype, defaultvalue, varname)\ static auto varname##IntegerParm_Name = PRM_Name(smallname, bigname);\ static auto varname##IntegerParm_Default = PRM_Default(defaultvalue);\ static auto varname##IntegerParm_Range = PRM_Range(rangemintype, rangemin, rangemaxtype, rangemax);\ auto varname##Integer_Parameter = PRM_Template(PRM_INT, 1, &varname##IntegerParm_Name, &varname##IntegerParm_Default, 0, &varname##IntegerParm_Range); #define CUSTOM_INTEGER_0R_TO_MAXU_PARAMETER(smallname, bigname, rangemax, defaultvalue, varname) ____custom_integer_rangemintype_t_rangemaxtype_t_parameter____(smallname, bigname, 0, rangemax, PRM_RANGE_RESTRICTED, PRM_RANGE_UI, defaultvalue, varname) #define CUSTOM_INTEGER_0R_TO_MAXR_PARAMETER(smallname, bigname, rangemax, defaultvalue, varname) ____custom_integer_rangemintype_t_rangemaxtype_t_parameter____(smallname, bigname, 0, rangemax, PRM_RANGE_RESTRICTED, PRM_RANGE_RESTRICTED, defaultvalue, varname) #define CUSTOM_INTEGER_MINU_TO_MAXU_PARAMETER(smallname, bigname, rangemin, rangemax, defaultvalue, varname) ____custom_integer_rangemintype_t_rangemaxtype_t_parameter____(smallname, bigname, rangemin, rangemax, PRM_RANGE_UI, PRM_RANGE_UI, defaultvalue, varname) #define CUSTOM_INTEGER_MINR_TO_MAXU_PARAMETER(smallname, bigname, rangemin, rangemax, defaultvalue, varname) ____custom_integer_rangemintype_t_rangemaxtype_t_parameter____(smallname, bigname, rangemin, rangemax, PRM_RANGE_RESTRICTED, PRM_RANGE_UI, defaultvalue, varname) #define CUSTOM_INTEGER_MINR_TO_MINR_PARAMETER(smallname, bigname, rangemin, rangemax, defaultvalue, varname) ____custom_integer_rangemintype_t_rangemaxtype_t_parameter____(smallname, bigname, rangemin, rangemax, PRM_RANGE_RESTRICTED, PRM_RANGE_RESTRICTED, defaultvalue, varname) I have similar thing for defining list of parameters, but it's a little more extended to help manging visibility of parameters later on in UpdateParmsFlags() SOP_START_PARAMETERLIST() // all parameters SWITCH_VISIBILITY() // those that should be turned OFF if input is not connected SWITCH_INVERT_VISIBILITY() // those that should be turned ON if input is not connected SWITCH_BUTDONTFORCE_VISIBILITY() // those that should be turned off if input is not connected, but don't have to be turned on if is connected because they are managed by some other variable SOP_END_PARAMETERLIST() Lastly, a word of warning. MAKE SURE THAT YOU TEST THOSE MACROS PROPERLY, otherwise you may end up with REALLY fucked up errors that will make no sense, and you will end up chasing errors that are not the reason of your problems. Edited March 16, 2015 by mantragora Quote Link to comment Share on other sites More sharing options...
ayidi Posted March 17, 2015 Share Posted March 17, 2015 The OpenVDB team wrote a nice wrapper class for creating parameters called ParmFactory. https://github.com/dreamworksanimation/openvdb/blob/master/openvdb_houdini/houdini/ParmFactory.cc Using it looks like this: hutil::ParmList parms; // Define a string-valued group name pattern parameter and add it to the list. parms.add(hutil::ParmFactory(PRM_STRING, "group", "Group") .setHelpText("Specify a subset of the input VDB grids to be processed.") .setChoiceList(&hutil::PrimGroupMenuInput1)); // amplitude parms.add(hutil::ParmFactory(PRM_FLT_J, "amp", "Amplitude") .setDefault(PRMoneDefaults) .setRange(PRM_RANGE_RESTRICTED, 0.0, PRM_RANGE_FREE, 10.0)); // Register this operator. (OpFactory) hvdb::MyOpFactory("My Operator", My_Opertor::myConstructor, parms, *table) .addAlias("OpenVDB LevelSet Noise") .addInput("VDB grids to noise") .addOptionalInput("Optional VDB grid to use as mask"); 4 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.