HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
VOP_CustomContext.C
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018
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 #include <UT/UT_DSOVersion.h>
27 #include "VOP_CustomContext.h"
28 
29 #include <VOP/VOP_Operator.h>
30 #include <OP/OP_OperatorTable.h>
31 #include <OP/OP_Input.h>
32 #include <PRM/PRM_Include.h>
33 #include <PRM/PRM_SpareData.h>
34 #include <CH/CH_Manager.h>
35 #include <UT/UT_Assert.h>
36 #include <UT/UT_WorkBuffer.h>
37 #include <SYS/SYS_Types.h>
38 
39 #include <stdint.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 
44 using namespace HDK_Sample;
45 
46 
47 //////////////////////////////////////////////////////////////////////////////
48 //
49 // SOP_CustomVop Node Registration
50 //
51 
52 void
54 {
55  OP_Operator * op;
56 
57  op = new OP_Operator(
58  "hdk_customvop", // internal name
59  "Custom VOP", // UI label
60  SOP_CustomVop::myConstructor, // class factory
61  SOP_CustomVop::myTemplateList, // parm definitions
63  0, // min # of inputs
64  0 // max # of inputs
65  );
66  table->addOperator(op);
67 }
68 
70 
71 ///////////////////////////////////////////////////////////////////////////////
72 //
73 // SOP_CustomVop Implementation
74 //
75 
76 OP_Node *
78  OP_Network *net, const char *name, OP_Operator *entry)
79 {
80  return new SOP_CustomVop(net, name, entry);
81 }
82 
85 {
86  PRM_Template() // List terminator
87 };
88 
90  OP_Network *net, const char *name, OP_Operator *entry)
91  : SOP_Node(net, name, entry)
92 {
93  createAndGetOperatorTable();
94 }
95 
97 {
98 }
99 
100 const char *
102 {
103  return VOP_OPTYPE_NAME;
104 }
105 
108 {
109  return VOP_OPTYPE_ID;
110 }
111 
112 // Create dummy VOP_Operator subclass so that we can tag it as operators
113 // created by us by type. We also take this chance to conveniently simplify
114 // it's construction as well. Notice that besides the large range of inputs
115 // that we give it, we also give it an "invalid" vopnet mask so that it won't
116 // appear in any of the other VOP context networks.
118 {
119 public:
120  sop_CustomVopOperator(const char *name, const char *label)
121  : VOP_Operator(
122  name, // internal name
123  label, // UI label
124  VOP_CustomVop::myConstructor, // How to create one
125  VOP_CustomVop::myTemplateList, // parm definitions
126  SOP_CustomVop::theChildTableName,
127  0, // Min # of inputs
128  VOP_VARIABLE_INOUT_MAX, // Max # of inputs
129  "invalid", // vopnet mask
130  NULL, // Local variables
131  OP_FLAG_UNORDERED, // Special flags
132  VOP_VARIABLE_INOUT_MAX) // # of outputs
133  {
134  }
135 };
136 
138 SOP_CustomVop::createAndGetOperatorTable()
139 {
140  // We chain our custom VOP operators onto the default VOP operator table.
142 
143  // Procedurally create some simple operator types for illustrative purposes.
144  table.addOperator(new sop_CustomVopOperator("hdk_inout11_", "In-Out 1-1"));
145  table.addOperator(new sop_CustomVopOperator("hdk_inout21_", "In-Out 2-1"));
146  table.addOperator(new sop_CustomVopOperator("hdk_inout12_", "In-Out 1-2"));
147  table.addOperator(new sop_CustomVopOperator("hdk_inout22_", "In-Out 2-2"));
148 
149  // Notify observers of the operator table that it has been changed.
151 
152  return &table;
153 }
154 
155 OP_ERROR
157 {
158  // Do evaluation of the custom VOP network here.
159  return error();
160 }
161 
162 ///////////////////////////////////////////////////////////////////////////////
163 //
164 // VOP_CustomVop
165 //
166 
167 OP_Node *
169  OP_Network *net, const char *name, OP_Operator *entry)
170 {
171  return new VOP_CustomVop(net, name, entry);
172 }
173 
174 static PRM_Name vopPlugInputs("inputs", "Inputs");
175 static PRM_Name vopPlugInpName("inpplug#", "Input Name #");
176 static PRM_Default vopPlugInpDefault(0, "input1");
177 static PRM_Name vopPlugOutputs("outputs", "Outputs");
178 static PRM_Name vopPlugOutName("outplug#", "Output Name #");
179 static PRM_Default vopPlugOutDefault(0, "output1");
180 
181 static PRM_Template
182 vopPlugInpTemplate[] =
183 {
184  PRM_Template(PRM_ALPHASTRING, 1, &vopPlugInpName, &vopPlugInpDefault),
185  PRM_Template() // List terminator
186 };
187 static PRM_Template
188 vopPlugOutTemplate[] =
189 {
190  PRM_Template(PRM_ALPHASTRING, 1, &vopPlugOutName, &vopPlugOutDefault),
191  PRM_Template() // List terminator
192 };
193 
196 {
197  PRM_Template(PRM_MULTITYPE_LIST, vopPlugInpTemplate, 0, &vopPlugInputs,
199 
200  PRM_Template(PRM_MULTITYPE_LIST, vopPlugOutTemplate, 0, &vopPlugOutputs,
202 
203  PRM_Template() // List terminator
204 };
205 
207  OP_Network *parent, const char *name, OP_Operator *entry)
208  : VOP_Node(parent, name, entry)
209 {
210  // Add our event handler.
211  addOpInterest(this, &VOP_CustomVop::nodeEventHandler);
212 }
213 
215 {
216  // Failing to remove our event handler can cause Houdini to crash so make
217  // sure we do it.
218  removeOpInterest(this, &VOP_CustomVop::nodeEventHandler);
219 }
220 
221 // This function is called to run the creation script (if there is one).
222 // The return value is false if the node was deleted while running the
223 // script. In this case obviously the node pointer becomes invalid and
224 // should not be used any more. It returns true if the node still exists.
225 //
226 // We override this in order to perform initial creation we are created
227 // created for the first time in a .hip file. This function is NOT called
228 // when being loaded from .hip files.
229 bool
231 {
233  return false;
234 
235  fpreal t = CHgetEvalTime();
236  UT_WorkBuffer plugname;
237 
238  // For simplicity, we just initialize our number of inputs/outputs based
239  // upon our node type name.
240  const UT_StringHolder& type_name = getOperator()->getName();
241  int n = type_name.c_str()[type_name.length() - 3] - '0';
242  setInt(vopPlugInputs.getToken(), 0, t, n);
243  for (int i = 0; i < n; i++)
244  {
245  plugname.sprintf("input%d", i + 1);
247  vopPlugInpName.getToken(), &i, 0, t);
248  }
249 
250  n = type_name.c_str()[type_name.length() - 2] - '0';
251  setInt(vopPlugOutputs.getToken(), 0, t, n);
252  for (int i = 0; i < n; i++)
253  {
254  plugname.sprintf("output%d", i + 1);
256  vopPlugOutName.getToken(), &i, 0, t);
257  }
258 
259  return true;
260 }
261 
262 const char *
263 VOP_CustomVop::inputLabel(unsigned idx) const
264 {
265  static UT_WorkBuffer theLabel;
266  fpreal t = CHgetEvalTime();
267  int i = idx;
269 
270  // Evaluate our label from the corresponding parameter.
271  evalStringInst(vopPlugInpName.getToken(), &i, label, 0, t);
272  if (label.isstring())
273  theLabel.strcpy(label);
274  else
275  theLabel.strcpy("<unnamed>");
276 
277  return theLabel.buffer();
278 }
279 
280 const char *
281 VOP_CustomVop::outputLabel(unsigned idx) const
282 {
283  static UT_WorkBuffer theLabel;
284  fpreal t = CHgetEvalTime();
285  int i = idx;
287 
288  // Evaluate our label from the corresponding parameter.
289  evalStringInst(vopPlugOutName.getToken(), &i, label, 0, t);
290  if (label.isstring())
291  theLabel.strcpy(label);
292  else
293  theLabel.strcpy("<unnamed>");
294 
295  return theLabel.buffer();
296 }
297 
298 unsigned
300 {
301  /// For simplicity, we just use the user specified parameter.
302  return evalInt("inputs", 0, CHgetEvalTime());
303 }
304 
305 unsigned
307 {
308  /// For simplicity, we just use the user specified parameter.
309  return evalInt("outputs", 0, CHgetEvalTime());
310 }
311 
312 void
314 {
315  // For simplicity, we just do the same thing as our input/output labels.
316  name.harden(inputLabel(idx));
317 }
318 
319 int
321 {
322  // There are more efficient ways to do this, but just do a dumb reverse
323  // lookup here.
324  for (int i = 0; i < getNumVisibleInputs(); i++)
325  {
326  if (name == inputLabel(i))
327  return i;
328  }
329  return -1;
330 }
331 
332 void
334 {
335  // For simplicity, just assume everything is a float
336  type_info.setType(VOP_TYPE_FLOAT);
337 }
338 
339 void
341  VOP_VopTypeInfoArray &type_infos)
342 {
343  // For simplicity, just assume everything is a float
344  type_infos.append( VOP_TypeInfo( VOP_TYPE_FLOAT ));
345 }
346 
347 void
349 {
350  // For simplicity, we just do the same thing as our input/output labels.
351  name.harden(outputLabel(idx));
352 }
353 
354 void
356 {
357  // For simplicity, just assume everything is a float
358  type_info.setType(VOP_TYPE_FLOAT);
359 }
360 
361 void
362 VOP_CustomVop::nodeEventHandler(
363  OP_Node *caller, void *callee, OP_EventType type, void *data)
364 {
365  switch (type)
366  {
367  case OP_PARM_CHANGED:
368  static_cast<VOP_CustomVop*>(callee)->handleParmChanged((int)(intptr_t)data);
369  break;
370  default:
371  break;
372  }
373 }
374 
375 void
376 VOP_CustomVop::handleParmChanged(int parm_index)
377 {
378  // On any parameter change for us, trigger a notification that the node's
379  // UI needs to update so that the Network Pane will redraw with the changed
380  // inputs/outputs.
382 }
383 
384 
385 ///////////////////////////////////////////////////////////////////////////////
386 //
387 // SOP_CustomVopOperatorFilter Implementation
388 //
389 
390 bool
392 {
393  return (dynamic_cast<sop_CustomVopOperator *>(op) != NULL);
394 }
395 
396 
PRM_API PRM_Default PRMzeroDefaults[]
static const char * theChildTableName
sop_CustomVopOperator(const char *name, const char *label)
GLuint GLsizei const GLchar * label
Definition: glcorearb.h:2544
virtual OP_ERROR error()
The input/output connections have changed.
Definition: OP_DataTypes.h:97
void triggerUIChanged(OP_UIChangeType type=OP_UICHANGE_ANY)
OP_OperatorTable * getOperatorTable() const
Definition: OP_Network.h:595
#define VOP_VARIABLE_INOUT_MAX
Definition: VOP_Node.h:59
virtual OP_ERROR cookMySop(OP_Context &context)
Override this to do VOP network evaluation.
SYS_FORCE_INLINE const char * buffer() const
UT_ErrorSeverity
Definition: UT_Error.h:25
SYS_FORCE_INLINE void strcpy(const char *src)
virtual void getOutputNameSubclass(UT_String &out, int idx) const
void setType(VOP_Type type, VOP_Type raw_type=VOP_TYPE_UNDEF, const char *type_name=NULL)
virtual const char * getChildType() const
We override these to specify that our child network type is VOPs.
bool addOperator(OP_Operator *op, std::ostream *err=nullptr)
virtual unsigned getNumVisibleOutputs() const
png_uint_32 i
Definition: png.h:2877
C++ VOP node to select one of its inputs and feed it into the output.
static OP_Node * myConstructor(OP_Network *net, const char *name, OP_Operator *entry)
const UT_StringHolder & getName() const
Definition: OP_Operator.h:212
void addOpInterest(void *data, OP_EventMethod m)
Definition: OP_Node.h:1352
virtual const char * inputLabel(unsigned idx) const
Provides the labels to appear on input and output buttons.
void notifyUpdateTableSinksOfUpdate()
GLdouble n
Definition: glcorearb.h:2007
virtual void getOutputTypeInfoSubclass(VOP_TypeInfo &type_info, int idx)
Fills out the info about data type of each output connector.
static OP_Node * myConstructor(OP_Network *net, const char *name, OP_Operator *entry)
virtual OP_OpTypeId getChildTypeID() const
We override these to specify that our child network type is VOPs.
exint length() const
static PRM_Template myTemplateList[]
Our parameter templates.
VOP_CustomVop(OP_Network *net, const char *name, OP_Operator *entry)
void harden()
Take shallow copy and make it deep.
Definition: UT_String.h:213
SYS_FORCE_INLINE const char * c_str() const
OP_OpTypeId
Definition: OP_OpTypeId.h:15
GLboolean * data
Definition: glcorearb.h:130
fpreal CHgetEvalTime()
Definition: CH_Manager.h:1716
GLuint const GLchar * name
Definition: glcorearb.h:785
static PRM_SpareData multiStartOffsetZero
virtual void getAllowedInputTypeInfosSubclass(unsigned idx, VOP_VopTypeInfoArray &type_infos)
virtual unsigned getNumVisibleInputs() const
Controls the number of input/output buttons visible on the node tile.
PRM_API const PRM_Type PRM_ALPHASTRING
int sprintf(const char *fmt,...) SYS_PRINTF_CHECK_ATTRIBUTE(2
virtual void getInputTypeInfoSubclass(VOP_TypeInfo &type_info, int idx)
Fills in the info about the vop type connected to the idx-th input.
double fpreal
Definition: SYS_Types.h:270
void newSopOperator(OP_OperatorTable *table)
void evalStringInst(const UT_StringRef &name, const int *inst, UT_String &val, int vi, fpreal t, int nestlevel=1) const
#define VOP_TABLE_NAME
Definition: OP_Node.h:208
virtual const char * outputLabel(unsigned idx) const
Provides the labels to appear on input and output buttons.
#define OP_FLAG_UNORDERED
Definition: OP_Operator.h:69
void setInt(int parmi, int vectori, fpreal t, exint value)
#define VOP_OPTYPE_NAME
Definition: OP_Node.h:254
static PRM_Template myTemplateList[]
Our parameter templates.
SOP_CustomVop(OP_Network *net, const char *name, OP_Operator *entry)
OP_EventType
Definition: OP_Value.h:22
virtual bool runCreateScript()
exint append(void)
Definition: UT_Array.h:95
virtual int getInputFromNameSubclass(const UT_String &name) const
Reverse mapping of internal input names to an input index.
virtual void getInputNameSubclass(UT_String &name, int idx) const
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:107
void setStringInst(const UT_StringRef &value, CH_StringMeaning meaning, const char *parmname, const int *inst, int vectori, fpreal t, int nestlevel=1)
C++ SOP node to provide the custom VOP context.
exint evalInt(int pi, int vi, fpreal t) const
virtual bool allowOperatorAsChild(OP_Operator *op)
OP_Operator * getOperator() const
void removeOpInterest(void *data, OP_EventMethod m)
Definition: OP_Node.h:1354
const char * getToken() const
Definition: PRM_Name.h:83