HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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  const UT_String & type_name = getOperator()->getName();
236  fpreal t = CHgetEvalTime();
237  UT_WorkBuffer plugname;
238  int n;
239 
240  // For simplicity, we just initialize our number of inputs/outputs based
241  // upon our node type name.
242  n = type_name(type_name.length() - 3) - '0';
243  setInt(vopPlugInputs.getToken(), 0, t, n);
244  for (int i = 0; i < n; i++)
245  {
246  plugname.sprintf("input%d", i + 1);
248  vopPlugInpName.getToken(), &i, 0, t);
249  }
250 
251  n = type_name(type_name.length() - 2) - '0';
252  setInt(vopPlugOutputs.getToken(), 0, t, n);
253  for (int i = 0; i < n; i++)
254  {
255  plugname.sprintf("output%d", i + 1);
257  vopPlugOutName.getToken(), &i, 0, t);
258  }
259 
260  return true;
261 }
262 
263 const char *
264 VOP_CustomVop::inputLabel(unsigned idx) const
265 {
266  static UT_WorkBuffer theLabel;
267  fpreal t = CHgetEvalTime();
268  int i = idx;
270 
271  // Evaluate our label from the corresponding parameter.
272  evalStringInst(vopPlugInpName.getToken(), &i, label, 0, t);
273  if (label.isstring())
274  theLabel.strcpy(label);
275  else
276  theLabel.strcpy("<unnamed>");
277 
278  return theLabel.buffer();
279 }
280 
281 const char *
282 VOP_CustomVop::outputLabel(unsigned idx) const
283 {
284  static UT_WorkBuffer theLabel;
285  fpreal t = CHgetEvalTime();
286  int i = idx;
288 
289  // Evaluate our label from the corresponding parameter.
290  evalStringInst(vopPlugOutName.getToken(), &i, label, 0, t);
291  if (label.isstring())
292  theLabel.strcpy(label);
293  else
294  theLabel.strcpy("<unnamed>");
295 
296  return theLabel.buffer();
297 }
298 
299 unsigned
301 {
302  /// For simplicity, we just use the user specified parameter.
303  return evalInt("inputs", 0, CHgetEvalTime());
304 }
305 
306 unsigned
308 {
309  /// For simplicity, we just use the user specified parameter.
310  return evalInt("outputs", 0, CHgetEvalTime());
311 }
312 
313 void
315 {
316  // For simplicity, we just do the same thing as our input/output labels.
317  name.harden(inputLabel(idx));
318 }
319 
320 int
322 {
323  // There are more efficient ways to do this, but just do a dumb reverse
324  // lookup here.
325  for (int i = 0; i < getNumVisibleInputs(); i++)
326  {
327  if (name == inputLabel(i))
328  return i;
329  }
330  return -1;
331 }
332 
333 void
335 {
336  // For simplicity, just assume everything is a float
337  type_info.setType(VOP_TYPE_FLOAT);
338 }
339 
340 void
342  VOP_VopTypeInfoArray &type_infos)
343 {
344  // For simplicity, just assume everything is a float
345  type_infos.append( VOP_TypeInfo( VOP_TYPE_FLOAT ));
346 }
347 
348 void
350 {
351  // For simplicity, we just do the same thing as our input/output labels.
352  name.harden(outputLabel(idx));
353 }
354 
355 void
357 {
358  // For simplicity, just assume everything is a float
359  type_info.setType(VOP_TYPE_FLOAT);
360 }
361 
362 void
363 VOP_CustomVop::nodeEventHandler(
364  OP_Node *caller, void *callee, OP_EventType type, void *data)
365 {
366  switch (type)
367  {
368  case OP_PARM_CHANGED:
369  static_cast<VOP_CustomVop*>(callee)->handleParmChanged((int)(intptr_t)data);
370  break;
371  default:
372  break;
373  }
374 }
375 
376 void
377 VOP_CustomVop::handleParmChanged(int parm_index)
378 {
379  // On any parameter change for us, trigger a notification that the node's
380  // UI needs to update so that the Network Pane will redraw with the changed
381  // inputs/outputs.
383 }
384 
385 
386 ///////////////////////////////////////////////////////////////////////////////
387 //
388 // SOP_CustomVopOperatorFilter Implementation
389 //
390 
391 bool
393 {
394  return (dynamic_cast<sop_CustomVopOperator *>(op) != NULL);
395 }
396 
397 
static const char * theChildTableName
void setStringInst(const UT_String &value, CH_StringMeaning meaning, const char *parmname, const int *inst, int vectori, fpreal t, int nestlevel=1)
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:96
unsigned length(void) const
Return length of string.
Definition: UT_String.h:539
void triggerUIChanged(OP_UIChangeType type=OP_UICHANGE_ANY)
void strcpy(const char *src)
OP_OperatorTable * getOperatorTable() const
Definition: OP_Network.h:592
#define VOP_VARIABLE_INOUT_MAX
Definition: VOP_Node.h:57
virtual OP_ERROR cookMySop(OP_Context &context)
Override this to do VOP network evaluation.
UT_ErrorSeverity
Definition: UT_Error.h:25
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)
void addOpInterest(void *data, OP_EventMethod m)
Definition: OP_Node.h:1336
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.
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
GLboolean * data
Definition: glcorearb.h:130
fpreal CHgetEvalTime()
Definition: CH_Manager.h:1605
void evalStringInst(const char *name, const int *inst, UT_String &val, int vi, fpreal t, int nestlevel=1) const
GLuint const GLchar * name
Definition: glcorearb.h:785
static PRM_SpareData multiStartOffsetZero
virtual void getAllowedInputTypeInfosSubclass(unsigned idx, VOP_VopTypeInfoArray &type_infos)
OP_OpTypeId
Definition: OP_Node.h:263
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:263
void newSopOperator(OP_OperatorTable *table)
#define VOP_TABLE_NAME
Definition: OP_Node.h:210
const UT_String & getName() const
Definition: OP_Operator.h:202
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:68
void setInt(int parmi, int vectori, fpreal t, exint value)
#define VOP_OPTYPE_NAME
Definition: OP_Node.h:252
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
const char * buffer() const
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:107
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
PRM_API PRM_Default PRMzeroDefaults[]
void removeOpInterest(void *data, OP_EventMethod m)
Definition: OP_Node.h:1338
const char * getToken() const
Definition: PRM_Name.h:40