HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DOP_GroupAndApply.C
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024
3  * Side Effects Software Inc. All rights reserved.
4  *
5  * Redistribution and use of Houdini Development Kit samples in source and
6  * binary forms, with or without modification, are permitted provided that the
7  * following conditions are met:
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. The name of Side Effects Software may not be used to endorse or
11  * promote products derived from this software without specific prior
12  * written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17  * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
20  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  *----------------------------------------------------------------------------
26  */
27 
28 #include "DOP_GroupAndApply.h"
29 #include <UT/UT_DSOVersion.h>
30 #include <SIM/SIM_DataFilter.h>
31 #include <SIM/SIM_Relationship.h>
33 #include <OP/OP_OperatorTable.h>
34 #include <DOP/DOP_PRMShared.h>
35 #include <DOP/DOP_InOutInfo.h>
36 #include <DOP/DOP_Operator.h>
37 #include <DOP/DOP_Engine.h>
38 
39 using namespace HDK_Sample;
40 
41 void
43 {
44  OP_Operator *op;
45 
46  // Create a new DOP_Operator which describes the operator we are
47  // building. The parameters to this function are similar to the
48  // OP_Operator constructor except for the last parameter, which
49  // specifies the number of outputs (up to 4) from this operator.
50  op = new DOP_Operator("hdk_groupandapply", "Group and Apply",
53  0, 1);
54  table->addOperator(op);
55 }
56 
57 static PRM_Name theInputIndexName("inputindex", "Input Index");
58 
61  // Standard activation parameter.
64  // Standard group parameter with group menu.
66  &DOPgroupMenu),
67  // The input index that determines which data will be attached to
68  // each object.
69  PRM_Template(PRM_INT_J, 1, &theInputIndexName, PRMzeroDefaults),
70  PRM_Template()
71 };
72 
73 OP_Node *
75  OP_Operator *op)
76 {
77  return new DOP_GroupAndApply(net, name, op);
78 }
79 
81  OP_Operator *op)
82  : DOP_Node(net, name, op)
83 {
84 }
85 
87 {
88 }
89 
90 void
92  const SIM_ObjectArray &objects,
93  DOP_Engine &engine)
94 {
95  SIM_ObjectArray filtered;
96  UT_String group;
97  int i, inputindex;
98 
99  // Grab the group string and filter our incoming objects using that
100  // string. This narrows down the set of objects that we actually want
101  // to operate on. The filtered array will contain only those objects
102  // from the original objects array that match the supplied string.
103  GROUP(group, time);
105  objects.filter(filter, filtered);
106 
107  // Loop through all the objects that passed the filter.
108  for( i = 0; i < filtered.entries(); i++ )
109  {
110  // Set information about the object we are going to process.
111  // The first argument is the index of the current object within the
112  // full list of objects we are going to process. The second
113  // argument is the total number of objects we are going to process.
114  // The last argument is a pointer to the actual object we are
115  // processing.
116  setCurrentObject(i, filtered.entries(), filtered(i));
117 
118  // The isActive function checks both the bypass flag and the
119  // activation parameter on the node (if there is one, which there
120  // is in this case). We call this function after calling
121  // setCurrentObject and we call it for each object in case the
122  // activation parameter uses some object-specific variables
123  // like OBJID in an expression.
124  if( isActive(time) )
125  {
126  // Evaluate the input index. Also called after setCurrentObject
127  // to properly evaluate objects specific local variables. Then
128  // make sure there is something connected to the requested input.
129  // We add one to the returned value to skip over the object
130  // input.
131  inputindex = INPUTINDEX(time) + 1;
132  if( inputindex != 0 && getInput(inputindex) )
133  {
134  SIM_Relationship *relationship;
135  UT_String addtogroup;
136  char numstr[UT_NUMBUF];
137 
138  // This function attaches the data connected to input
139  // number inputindex to the current object.
140  applyDataFromInput(time, inputindex, inputindex,
141  *filtered(i),
142  0, engine, 0, true);
143  // Create a group name based on the input index.
144  UT_String::itoa(numstr, inputindex);
145  addtogroup = "applygroup_";
146  addtogroup += numstr;
147 
148  // Create the relationship if it doesn't already exist,
149  // and add the object to the group.
150  relationship = engine.addRelationship(addtogroup,
152  if( relationship )
153  {
154  relationship->addGroup(filtered(i));
155  SIM_DATA_CREATE(*relationship, SIM_RELGROUP_DATANAME,
158  }
159  else
161  }
162  }
163  }
164 }
165 
166 void
168  DOP_InOutInfo &info) const
169 {
170  // Our first input is an object input.
171  // Our remaining inputs are data inputs.
172  if( inputidx == 0 )
173  info = DOP_InOutInfo(DOP_INOUT_OBJECTS, false);
174  else
175  info = DOP_InOutInfo(DOP_INOUT_DATA, true);
176 }
177 
178 void
180  DOP_InOutInfo &info) const
181 {
182  // Our single output is an object output.
183  info = DOP_InOutInfo(DOP_INOUT_OBJECTS, false);
184 }
185 
186 void
187 DOP_GroupAndApply::GROUP(UT_String &str, fpreal t)
188 {
189  evalString(str, DOPgroupName, 0, t);
190 }
191 
192 int
193 DOP_GroupAndApply::INPUTINDEX(fpreal t)
194 {
195  return evalInt(theInputIndexName, 0, t);
196 }
197 
void processObjectsSubclass(fpreal time, int foroutputidx, const SIM_ObjectArray &objects, DOP_Engine &engine) override
This default implementation does not affect incoming objects.
exint entries() const
DOP_API PRM_ChoiceList DOPgroupMenu
PRM_API const PRM_Type PRM_STRING
bool isActive(fpreal time)
GT_API const UT_StringHolder time
void filter(const SIM_DataFilter &filter, SIM_ObjectArray &filtered) const
DOP_API PRM_Name DOPgroupName
DOP_API PRM_Name DOPactivationName
bool addOperator(OP_Operator *op, std::ostream *err=nullptr)
PRM_API const PRM_Type PRM_INT_J
#define SIM_RELGROUP_DATANAME
Definition: SIM_Names.h:63
void newDopOperator(OP_OperatorTable *table)
This declaration allows HDK users to write custom DOP operators.
void evalString(UT_String &val, int pi, int vi, fpreal t) const
Holds pointers to a number of SIM_Object objects.
DOP_GroupAndApply(OP_Network *net, const char *name, OP_Operator *op)
OP_Node * getInput(unsigned idx, bool mark_used=false) const
Returns the node connected to a particular input (may be null).
void setCurrentObject(int objectindex, int objectcount, const SIM_Object *object)
#define SIM_DATA_RETURN_EXISTING
Definition: SIM_Data.h:90
GLuint const GLchar * name
Definition: glcorearb.h:786
GLenum GLenum GLsizei void * table
Definition: glad.h:5129
static int itoa(char *str, int64 i)
GLdouble t
Definition: glad.h:2397
fpreal64 fpreal
Definition: SYS_Types.h:277
#define UT_NUMBUF
Definition: UT_Defines.h:24
static PRM_Template myTemplateList[]
void getOutputInfoSubclass(int inputidx, DOP_InOutInfo &info) const override
This default implementation specifies the output sends out objects.
void applyDataFromInput(fpreal time, int inputidx, int inputidxforsuffix, SIM_RootData &rootdata, const char *parentdataname, DOP_Engine &engine, UT_StringArray *datanames, bool changeuniquenamesuffix)
static OP_Node * myConstructor(OP_Network *net, const char *name, OP_Operator *op)
This is the base class for all DOP nodes.
Definition: DOP_Node.h:77
DOP_API PRM_Default DOPgroupDefault
exint evalInt(int pi, int vi, fpreal t) const
void addGroup(const SIM_ObjectArray &objects)
Adds a number of objects to the object group.
void addError(int code, const char *msg=0)
Adds an error from the DOP error file.
Definition: DOP_Node.h:149
PRM_API PRM_Default PRMzeroDefaults[]
#define SIM_DATA_CREATE(Parent, DataName, DataClass, Flags)
Definition: SIM_Utils.h:63
DOP_API PRM_Default DOPactivationDefault
SIM_Relationship * addRelationship(const char *name, int creationflags)
void getInputInfoSubclass(int inputidx, DOP_InOutInfo &info) const override
This default implementation specifies the input accepts objects.
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glcorearb.h:1297