HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
APEX_Callback.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: APEX_Callback.h (APEX Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __APEX_CALLBACK_H__
12 #define __APEX_CALLBACK_H__
13 
14 #include "APEX_API.h"
15 #include "APEX_ParmDict.h"
16 #include "APEX_Include.h"
17 #include "APEX_Types.h"
18 
19 #include <UT/UT_Array.h>
20 #include <UT/UT_Options.h>
21 #include <UT/UT_OpUtils.h>
22 #include <UT/UT_SharedPtr.h>
23 #include <UT/UT_StringHolder.h>
24 #include <UT/UT_StringView.h>
25 #include <UT/UT_Tracing.h>
26 #include <UT/UT_Tuple.h>
27 #include <UT/UT_WorkBuffer.h>
28 
29 #include <SYS/SYS_Math.h>
30 #include <SYS/SYS_Types.h>
31 
32 #include <algorithm>
33 #include <iterator>
34 #include <string>
35 #include <tuple>
36 #include <type_traits>
37 #include <utility>
38 
39 #include <cstddef>
40 //#include <stddef.h>
41 
42 namespace apex
43 {
44 
45 class APEX_Program;
46 class APEX_Argument;
47 class APEX_Graph;
48 
49 struct APEX_Parm
50 {
51  APEX_Parm() = default;
52 
54  : myName(name), myTypeDefn(typedefn)
55  {
56  }
57 
61 
62  // Used for py bindings
64  tuple_t asTuple() const
65  {
66  return {myName.toStdString(), myTypeDefn ? myTypeDefn->repr().toStdString() : ""};
67  }
68 
69  bool operator==(const APEX_Parm &other) const
70  {
71  return myName == other.myName && myTypeDefn == other.myTypeDefn;
72  }
73 
74  bool operator!=(const APEX_Parm &other) const
75  {
76  return myName != other.myName || myTypeDefn != other.myTypeDefn;
77  }
78 
79  const UT_StringHolder &name() const { return myName; }
81  const UT_StringRef &typeName() const
82  {
83  if (!myTypeDefn)
84  return theUndefTypeName.asRef();
85  return myTypeDefn->repr();
86  }
87 
88  bool isValid() const { return !myName.isEmpty() && myName != "__invalid__"; }
89  bool isSpare() const { return myName.startsWith(theSparePortPrefix); }
90  bool isInplace() const { return myName.startsWith(theInplacePortPrefix); }
91  bool isConditionalInplace() const { return myName.startsWith(theConditionalInplacePortPrefix); }
92 };
93 
94 static const APEX_Parm theInvalidParm = {"__invalid__", nullptr};
95 
98 
100 {
102 
103  bool operator()(APEX_Parm const &p)
104  {
105  if (myStr == p.myName)
106  return true;
107 
108  UT_StringView name_view(p.myName);
109  name_view = name_view.trimLeft("*");
110  name_view = name_view.trimLeft("+");
111  name_view = name_view.trimLeft("-");
112  if (UT_StringView(myStr) == name_view)
113  return true;
114 
115  return !p.myAlias.isEmpty() && myStr == p.myAlias;
116  }
117 
119 };
120 
122 {
123  using iterator_category = std::forward_iterator_tag;
124  using difference_type = std::ptrdiff_t;
126  using pointer = APEX_Parm *; // or also value_type*
127  using reference = APEX_Parm &; // or also value_type&
128 };
129 
131 {
132 public:
133  const APEX_ParmList &inputs() const { return myInputs; }
134  const APEX_ParmList &outputs() const { return myOutputs; }
135 
138 
139  bool operator==(const APEX_Signature &other) const
140  {
141  return myInputs == other.myInputs && myOutputs == other.myOutputs;
142  }
143 
144  bool operator!=(const APEX_Signature &other) const
145  {
146  return !(myInputs == other.myInputs && myOutputs == other.myOutputs);
147  }
148 
150  {
151  auto it = std::find_if (myInputs.begin(), myInputs.end(), ParmNameComp(name));
152  return it != myInputs.end() ? std::distance(myInputs.begin(), it) : -1;
153  }
154 
156  {
157  auto it = std::find_if (myOutputs.begin(), myOutputs.end(), ParmNameComp(name));
158  return it != myOutputs.end() ? std::distance(myOutputs.begin(), it) : -1;
159  }
160 
161  const APEX_Parm &findInput(const UT_StringRef &name) const
162  {
163  auto it = std::find_if (myInputs.begin(), myInputs.end(), ParmNameComp(name));
164  if (it == myInputs.end())
165  return theInvalidParm;
166  return *it;
167  }
168 
169  const APEX_Parm &findOutput(const UT_StringRef &name) const
170  {
171  auto it = std::find_if (myOutputs.begin(), myOutputs.end(), ParmNameComp(name));
172  if (it == myOutputs.end())
173  return theInvalidParm;
174  return *it;
175  }
176 
178  {
179  exint index = findInputIndex(name);
180  if (index != -1)
181  *parm = &myInputs[index];
182 
183  return index;
184  }
185 
187  {
188  exint index = findOutputIndex(name);
189  if (index != -1)
190  *parm = &myOutputs[index];
191 
192  return index;
193  }
194 
195  exint numInputs() const { return myInputs.size(); }
196 
197  exint numOutputs() const { return myOutputs.size(); }
198 
199  exint size() const { return numInputs() + numOutputs(); }
200 
201  APEX_Parm &addInput(int idx, const APEX_Parm &parm)
202  {
203  if (idx < 0)
204  idx = myInputs.append(parm);
205  else
206  {
207  if (myInputs.isEmpty())
208  {
209  idx = myInputs.append(parm);
210  }
211  else
212  myInputs.insertAt(parm, idx);
213  }
214  return myInputs[idx];
215  }
216 
217  APEX_Parm &addOutput(int idx, const APEX_Parm &parm)
218  {
219  if (idx < 0)
220  idx = myOutputs.append(parm);
221  else
222  {
223  if (myOutputs.isEmpty())
224  {
225  idx = myOutputs.append(parm);
226  }
227  else
228  idx = myOutputs.insertAt(parm, idx);
229  }
230  return myOutputs[idx];
231  }
232 
233  void addSparePort(const UT_StringRef &name="", exint index = -1)
234  {
235  if (name.isEmpty())
236  {
237  addInput(-1, {theSparePortName.asRef(), nullptr});
238  addOutput(-1, {theSparePortName.asRef(), nullptr});
239  }
240  else
241  {
242  UT_StringHolder full_name;
243  full_name.format("+{}", name);
244  addInput(SYSmin(index, myInputs.size()), {full_name, nullptr});
245  addOutput(SYSmin(index, myOutputs.size()), {full_name, nullptr});
246  }
247  }
248 
249  bool addInputAlias(const UT_StringRef &name, const UT_StringRef &alias)
250  {
251  exint index = findInputIndex(name);
252  if (index < 0)
253  return false;
254 
255  UT_StringView alias_view(alias);
256  alias_view = alias_view.trimLeft("*");
257  alias_view = alias_view.trimLeft("+");
258  alias_view = alias_view.trimLeft("-");
259  if (findInputIndex(alias_view) >= 0)
260  return false;
261 
262  myInputs[index].myAlias = alias_view;
263  return true;
264  }
265 
266  bool addOutputAlias(const UT_StringRef &name, const UT_StringRef &alias)
267  {
268  exint index = findOutputIndex(name);
269  if (index < 0)
270  return false;
271 
272  UT_StringView alias_view(alias);
273  alias_view = alias_view.trimLeft("*");
274  alias_view = alias_view.trimLeft("+");
275  alias_view = alias_view.trimLeft("-");
276  if (findOutputIndex(alias_view) >= 0)
277  return false;
278 
279  myOutputs[index].myAlias = alias_view;
280  return true;
281  }
282 
283  // FIXME: this is broken until the removal of type enums is complete
284  bool isGeneric() const { return false; }
285 
286 #if 0
287  void serialize(UT_String &str)
288  {
289  // UT_OptionsHolder inputs_opt;
290  // UT_OptionsHolder outputs_opt;
291  // UT_Options sig_opt;
292  // for (auto &[name, _t] : inputs)
293  // inputs_opt.setOptionI(name,static_cast<int>(_t));
294  // for (auto &[name, _t] : outputs)
295  // outputs_opt.setOptionI(name,static_cast<int>(_t));
296  // sig_opt.setOptionDict("inputs", inputs_opt);
297  // sig_opt.setOptionDict("outputs", outputs_opt);
298  // sig_opt.dump();
299  }
300 #endif
301 
303 };
304 
306 
308 {
309 public:
310  APEX_ParmHandleRef(APEX_Parm *parm) : myParmPtr(parm) {};
311  APEX_ParmHandleRef(APEX_SignaturePtr &sig, APEX_Parm *parm) : myParmPtr(parm), myOwner(sig)
312  {
313  myOwns = false;
314  };
316  {
317  if (myOwns)
318  delete myParmPtr;
319  }
320  APEX_Parm *ptr() { return myParmPtr; }
321 
322  bool isOwner() { return myOwns; }
323 
324  bool isValid()
325  {
326  if (!myOwns && !myOwner)
327  return false;
328  else
329  return !!myParmPtr;
330  }
331 
332  void setPtr(APEX_Parm *ptr, bool owns)
333  {
334  myParmPtr = ptr;
335  myOwns = owns;
336  }
337  void incref() { myRefCount++; }
338  void decref()
339  {
340  myRefCount--;
341  if (myRefCount == 0)
342  delete this;
343  }
344 
345 private:
346  bool myOwns = false;
347  exint myRefCount = 0;
349  APEX_Parm *myParmPtr = nullptr;
350 };
351 
353 {
354 public:
356  {
357  myHandle = new APEX_ParmHandleRef(sig, parm);
358  myHandle->incref();
359  }
361  {
362  myHandle = new APEX_ParmHandleRef(nullptr);
363  auto *copy = new APEX_Parm(parm);
364 
365  myHandle->setPtr(copy, true);
366  myHandle->incref();
367  }
368  APEX_ParmHandle(const APEX_ParmHandle &other): myHandle(other.myHandle)
369  {
370  myHandle->incref();
371  }
372 
374  {
375  myHandle->decref();
376  }
377 
378  bool isOwner() const { return myHandle->isOwner(); }
379 
380  bool isValid() const { return !!myHandle && myHandle->isValid(); }
381 
382  bool isSpare() const { return isValid() && get()->isSpare(); }
383  bool isInplace() const { return isValid() && get()->isInplace(); }
384  bool isConditionalInplace() const { return isValid() && get()->isConditionalInplace(); }
385 
386  UT_StringHolder &name() { return get()->myName; }
387  const UT_StringRef &typeName() { return get()->typeName(); }
389 
391  {
392  const APEX_Parm *parm = get();
393  return APEX_ParmHandle({parm->myName, parm->myTypeDefn});
394  }
395 
397  {
398  if (isValid())
399  return *get();
400  return {"invalid", nullptr};
401  }
402 
403  APEX_Parm *get() { return myHandle->ptr(); }
404  const APEX_Parm *get() const { return myHandle->ptr(); }
405 
406 private:
407  APEX_ParmHandleRef *myHandle;
408 };
409 
411 {
412 public:
413  virtual ~APEX_FunctionBase() = default;
414 
415  virtual const UT_StringHolder &getName() const = 0;
416  virtual void compile(
417  const APEX_Graph *graph,
418  APEX_NodeID node_id,
419  APEX_Program *prog,
421  {
422  }
423  virtual void execute(APEX_ArgPtrs &arg_ptrs) const {}
424 
425  /// What kind of function is this? Informs things like scopes & conditions
427 
428  virtual const APEX_Signature &signature() const = 0;
429 
430  virtual const APEX_TypeDefinitionBase *runDataTypeDef() const { return nullptr; }
431 
432  /// Earliest Houdini version that this callback is allowed in "X.Y.Z" format
433  virtual const char *minProductVersion() const { return nullptr; }
434 
435  /// Determines whether the callback should be hidden from the UI
436  virtual bool isHidden() const { return false; }
437 
438  /// Whether the callback requires its input geometry CE caches to be flushed.
439  virtual bool requiresCEFlush() const { return true; }
440 
441  /// Whether the callback leaves CE caches in its output geometry.
442  virtual bool usesCE() const { return false; }
443 
444  /// Called for any type with rundata with a reference to the rundata so it can be initialized.
445  virtual void runDataCompileHook(
446  APEX_Argument *rundata_instance,
447  const APEX_Graph *in_graph,
448  APEX_NodeID for_node,
449  APEX_Program *bind_to) const
450  {
451  }
452 
453  /// Does this node open a scope?
454  bool opensScope() const
455  {
456  auto t = callbackType();
458  }
459 
460  /// Does this node close a scope?
461  bool closesScope() const
462  {
463  auto t = callbackType();
465  }
466 
467  /// Name of the fake wire which is used to denote scope relationships.
468  virtual UT_StringHolder scopeConnection() const { return ""; }
469 
470  virtual bool hasSubnetTemplate() const { return false; }
471 
472  virtual const Dict &parmDefaults() const
473  {
474  return Dict::getAPEXStaticEmpty();
475  }
476 };
477 
478 template <typename... T, size_t... Index>
479 UT_Tuple<T *...>
480 castArgs(APEX_ArgPtrs &arg_ptrs, std::index_sequence<Index...>)
481 {
482  return UT_Tuple<T*...>((
483  [&]()
484  {
485  T *result = reinterpret_cast<std::remove_pointer_t<T> *>(arg_ptrs[Index]);
486  return result;
487  }()
488  )...);
489 }
490 
491 template <typename... T>
492 UT_Tuple<T *...>
494 {
495  return castArgs<T...>(arg_ptrs, std::index_sequence_for<T...>{});
496 }
497 
498 template <typename T>
499 void
501 {
502  const APEX_TypeDefinitionBase *t_defn = findTypeDef<std::remove_const_t<T>>();
503 
504  if constexpr (std::is_const_v<T>)
505  {
506  sig.myInputs.emplace_back(name, t_defn);
507  if (name.startsWith(theSparePortPrefix))
508  sig.myOutputs.emplace_back(name, t_defn);
509  }
510  else
511  {
512  sig.myOutputs.emplace_back(name, t_defn);
513  if (name.startsWith(theInplacePortPrefix)
514  || name.startsWith(theConditionalInplacePortPrefix))
515  sig.myInputs.emplace_back(name, t_defn);
516  }
517 }
518 
519 template <typename... Ts, size_t... Index>
520 auto
522  const char *const argnames[sizeof...(Ts)],
523  std::index_sequence<Index...>)
524 {
526  ((addToSignature<Ts>(result, argnames[Index])), ...);
527  return result;
528 }
529 
530 template <typename... Ts>
531 auto
533  // this nonsense is to allow empty argnames[] = {} (or indeed, just an argnames = nullptr
534  // would work too) the extra (seemingly redundant) sizeof...(Ts) > 0 ternary is because we
535  // need substitution of the parameters to conditional_t to succeed, even if passed
536  // sizeof...(Ts) == 0 and a size-0 array is nonstandard
538  (sizeof...(Ts) > 0),
539  const char *const[(sizeof...(Ts) > 0 ? sizeof...(Ts) : 1)],
540  std::nullptr_t> argnames)
541 {
542  if constexpr (sizeof...(Ts) > 0)
543  return makeSignature<Ts...>(argnames, std::index_sequence_for<Ts...>{});
544  else
545  return APEX_Signature();
546 }
547 
548 template <typename C, typename... Ts>
550 {
551 public:
553  {
554  myName = C::funcname.asHolder();
555  mySignature = makeSignature<Ts...>(C::argnames);
556 
557  UT_Options defaults;
558  defaults.setFromPyDictionary(C::parm_defaults);
559  myDefaults->mergeUtOptions(&defaults, false, true, true, &mySignature);
560  };
561 
562  ~APEX_GenericFunction() override {}
563 
564  const UT_StringHolder &getName() const override { return myName; }
565 
566  static constexpr const char *parm_defaults = "";
567 
568  const APEX_Signature &signature() const override { return mySignature; };
569 
571 
572  const Dict &parmDefaults() const override { return myDefaults; }
573 
574  void addSparePort(const UT_StringRef &name = "", exint index = -1)
575  {
576  mySignature.addSparePort(name, index);
577  }
578 
579  bool addInputAlias(const UT_StringRef &name, const UT_StringRef &alias)
580  {
581  return mySignature.addInputAlias(name, alias);
582  }
583 
584  bool addOutputAlias(const UT_StringRef &name, const UT_StringRef &alias)
585  {
586  return mySignature.addOutputAlias(name, alias);
587  }
588 
589  void execute(APEX_ArgPtrs &arg_ptrs) const override
590  {
591  utZoneScopedN(C::funcname);
592  auto cast_args = castArgs<std::remove_const_t<Ts>...>(arg_ptrs);
593  auto ref_args = makerefs(cast_args);
594 
595  const auto &derived = static_cast<const C &>(*this);
596 
597  std::apply(derived, ref_args);
598  }
599 
600 protected:
602 
603 private:
604  APEX_Signature mySignature;
605  Dict myDefaults;
606 };
607 
608 /// Splits the namespace version of @a fullname into a name and version pair.
609 /// For example, "string::Build::3.0" is split as {"string::Build", "3.0"}.
610 inline std::pair<UT_StringHolder, UT_StringHolder>
611 APEXsplitNameAndVersion(const char *fullname)
612 {
613  UT_WorkBuffer scope, name_space, core_name, version;
615  fullname, &scope, &name_space, &core_name, &version);
616 
618  if (!name_space.isEmpty())
619  {
620  name.append(name_space);
621  name.append("::");
622  }
623  name.append(core_name);
624 
625  return {std::move(name), std::move(version)};
626 }
627 
628 /// Filters the @p callbacks array by removing the callbacks whose signatures
629 /// do not contain all parms present in the @p filter signature. Returns the
630 /// number of removed callbacks.
631 ///
632 /// The filter signature represents a sparse set of required parms.
633 /// Callbacks with additional parms are not removed as long as all parms in the
634 /// filter signature are present in the callback signature.
635 template <typename T>
636 exint
638 {
639  exint removed_count = 0;
640  for (auto it = callbacks.rbegin(); it != callbacks.rend(); ++it)
641  {
642  const T *ptr = *it;
643  const APEX_Signature &sig = ptr->signature();
644 
645  // Compare input signatures
646  bool input_matches = true;
647  for (const APEX_Parm &filter_i : filter.inputs())
648  {
649  const APEX_Parm &cb_sig_i = sig.findInput(filter_i.name());
650  if (!cb_sig_i.isValid() || cb_sig_i.myTypeDefn != filter_i.myTypeDefn)
651  {
652  input_matches = false;
653  break;
654  }
655  }
656  if (!input_matches)
657  {
658  callbacks.removeItem(it);
659  removed_count++;
660  continue;
661  }
662 
663  // Compare output signatures
664  bool output_matches = true;
665  for (const APEX_Parm &filter_o : filter.outputs())
666  {
667  const APEX_Parm &sig_o = sig.findOutput(filter_o.name());
668  if (!sig_o.isValid() || sig_o.myTypeDefn != filter_o.myTypeDefn)
669  {
670  output_matches = false;
671  break;
672  }
673  }
674  if (!output_matches)
675  {
676  callbacks.removeItem(it);
677  removed_count++;
678  }
679  }
680 
681  return removed_count;
682 }
683 
684 } // end namespace apex
685 
686 #endif
std::string toStdString() const
const APEX_TypeDefinitionBase * typeDefinition()
exint APEXfilterCallbacksBySignature(UT_Array< const T * > &callbacks, const APEX_Signature &filter)
const UT_StringHolder & getName() const override
Normal callback which is unconditionally executed.
exint findOutputIndex(const UT_StringView &name) const
virtual bool hasSubnetTemplate() const
bool operator!=(const APEX_Signature &other) const
bool isSpare() const
Definition: APEX_Callback.h:89
APEX_Parm duplicateParm() const
APEX_ParmHandle(APEX_SignaturePtr &sig, APEX_Parm *parm)
typename std::conditional< B, T, F >::type conditional_t
Definition: core.h:266
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
UT_Tuple< std::string, std::string > tuple_t
Definition: APEX_Callback.h:63
APEX_ParmHandle(const APEX_ParmHandle &other)
const UT_StringHolder & name() const
Definition: APEX_Callback.h:79
UT_StringHolder myStr
exint findOutput(const UT_StringRef &name, APEX_Parm **parm)
virtual void runDataCompileHook(APEX_Argument *rundata_instance, const APEX_Graph *in_graph, APEX_NodeID for_node, APEX_Program *bind_to) const
Called for any type with rundata with a reference to the rundata so it can be initialized.
SYS_NO_DISCARD_RESULT SYS_FORCE_INLINE UT_StringView trimLeft(const char *c=" \t\n\r") const
bool opensScope() const
Does this node open a scope?
virtual bool requiresCEFlush() const
Whether the callback requires its input geometry CE caches to be flushed.
#define APEX_API
Definition: APEX_API.h:21
bool isEmpty() const
Same as !isstring()
UT_SharedPtr< APEX_Parm > APEX_ParmPtr
Definition: APEX_Callback.h:96
auto makerefs(UT_Tuple< T...> &t)
Definition: APEX_Include.h:253
int64 exint
Definition: SYS_Types.h:125
virtual void compile(const APEX_Graph *graph, APEX_NodeID node_id, APEX_Program *prog, UT_Array< APEX_Argument > &args) const
bool closesScope() const
Does this node close a scope?
GLdouble s
Definition: glad.h:3009
bool isValid() const
Definition: APEX_Callback.h:88
static void getComponentsFromFullName(const char *full_name, UT_WorkBuffer *scope_opname, UT_WorkBuffer *namespace_name, UT_WorkBuffer *op_name, UT_WorkBuffer *version)
void addToSignature(APEX_Signature &sig, const UT_StringHolder &name)
std::tuple< Types...> UT_Tuple
Definition: UT_Tuple.h:53
exint numInputs() const
**But if you need a result
Definition: thread.h:622
bool isConditionalInplace() const
Definition: APEX_Callback.h:91
std::ptrdiff_t difference_type
UT_StringHolder & name()
APEX_CallbackType callbackType() const override
What kind of function is this? Informs things like scopes & conditions.
APEX_Parm(const UT_StringHolder &name, const APEX_TypeDefinitionBase *typedefn)
Definition: APEX_Callback.h:53
void addSparePort(const UT_StringRef &name="", exint index=-1)
APEX_ParmHandle freeze() const
Marks the start of an arbitrary loop, expects RunData to be an iterator.
const APEX_ParmList & inputs() const
APEX_ParmList myInputs
APEX_CallbackType
Definition: APEX_Include.h:224
bool isOwner() const
A utility class to do read-only operations on a subset of an existing string.
Definition: UT_StringView.h:40
#define utZoneScopedN(name)
Definition: UT_Tracing.h:212
bool isInplace() const
bool isGeneric() const
bool setFromPyDictionary(const char *dict)
reverse_iterator rbegin()
Begin iterating over the array in reverse.
Definition: UT_Array.h:1038
exint emplace_back(S &&...s)
Definition: UT_ArrayImpl.h:769
virtual void execute(APEX_ArgPtrs &arg_ptrs) const
bool addOutputAlias(const UT_StringRef &name, const UT_StringRef &alias)
APEX_ParmList myOutputs
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:36
PXL_API const char * getName(const ColorSpace *space)
Return the name of the color space.
virtual const UT_StringRef & repr() const =0
Return a human-readable string representing the type.
virtual APEX_CallbackType callbackType() const
What kind of function is this? Informs things like scopes & conditions.
tuple_t asTuple() const
Definition: APEX_Callback.h:64
virtual const Dict & parmDefaults() const
const APEX_TypeDefinitionBase * typeDefinition() const
Definition: APEX_Callback.h:80
const Dict & parmDefaults() const override
bool addInputAlias(const UT_StringRef &name, const UT_StringRef &alias)
bool operator==(const APEX_Parm &other) const
Definition: APEX_Callback.h:69
SYS_FORCE_INLINE bool isEmpty() const
bool addInputAlias(const UT_StringRef &name, const UT_StringRef &alias)
APEX_Parm()=default
GLuint const GLchar * name
Definition: glcorearb.h:786
UT_StringHolder myName
Definition: APEX_Callback.h:58
size_t format(const char *fmt, const Args &...args)
Format a string using the same formatting codes as UTformat.
bool operator!=(const APEX_Parm &other) const
Definition: APEX_Callback.h:74
virtual const APEX_TypeDefinitionBase * runDataTypeDef() const
bool operator()(APEX_Parm const &p)
exint numOutputs() const
reverse_iterator rend()
End reverse iterator.
Definition: UT_Array.h:1044
bool addOutputAlias(const UT_StringRef &name, const UT_StringRef &alias)
APEX_Parm & addInput(int idx, const APEX_Parm &parm)
bool isConditionalInplace() const
const APEX_Signature & signature() const override
GLdouble t
Definition: glad.h:2397
std::forward_iterator_tag iterator_category
const UT_StringRef & typeName()
GT_API const UT_StringHolder version
const APEX_ParmList & outputs() const
A map of string to various well defined value types.
Definition: UT_Options.h:84
virtual const char * minProductVersion() const
Earliest Houdini version that this callback is allowed in "X.Y.Z" format.
bool isSpare() const
void setPtr(APEX_Parm *ptr, bool owns)
static const APEX_Signature theEmptySignature
APEX_ParmHandle(APEX_Parm &&parm)
virtual UT_StringHolder scopeConnection() const
Name of the fake wire which is used to denote scope relationships.
const UT_StringRef & typeName() const
Definition: APEX_Callback.h:81
exint findInputIndex(const UT_StringView &name) const
const APEX_Parm & findInput(const UT_StringRef &name) const
bool operator==(const APEX_Signature &other) const
GLuint index
Definition: glcorearb.h:786
SYS_FORCE_INLINE void append(char character)
exint size() const
auto makeSignature(const char *const argnames[sizeof...(Ts)], std::index_sequence< Index...>)
auto ptr(T p) -> const void *
Definition: format.h:4331
**If you just want to fire and args
Definition: thread.h:618
UT_StringHolder myAlias
Definition: APEX_Callback.h:60
void removeItem(const reverse_iterator &it)
Remove item specified by the reverse_iterator.
Definition: UT_Array.h:1071
APEX_Parm & addOutput(int idx, const APEX_Parm &parm)
const APEX_Parm & findOutput(const UT_StringRef &name) const
virtual bool isHidden() const
Determines whether the callback should be hidden from the UI.
APEX_ParmHandleRef(APEX_SignaturePtr &sig, APEX_Parm *parm)
void addSparePort(const UT_StringRef &name="", exint index=-1)
exint findInput(const UT_StringRef &name, APEX_Parm **parm)
static constexpr const char * parm_defaults
ParmNameComp(const UT_StringView &s)
APEX_ParmHandleRef(APEX_Parm *parm)
Represents a location for a single object inside of an APEX_Buffer.
Definition: APEX_Buffer.h:176
static const APEX_COWHandle< APEX_ParmDict > & getAPEXStaticEmpty()
Definition: APEX_COW.h:40
SIM_API const UT_StringHolder distance
bool isValid() const
std::pair< UT_StringHolder, UT_StringHolder > APEXsplitNameAndVersion(const char *fullname)
bool startsWith(const UT_StringView &pfx, bool case_sense=true) const
Imported from UT_String.
#define SYSmin(a, b)
Definition: SYS_Math.h:1583
virtual bool usesCE() const
Whether the callback leaves CE caches in its output geometry.
UN_NodeID APEX_NodeID
Definition: APEX_Include.h:332
void execute(APEX_ArgPtrs &arg_ptrs) const override
bool isInplace() const
Definition: APEX_Callback.h:90
UT_SharedPtr< APEX_Signature > APEX_SignaturePtr
Do nothing; ignored after compilation.
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glcorearb.h:1297
UT_Tuple< T *...> castArgs(APEX_ArgPtrs &arg_ptrs, std::index_sequence< Index...>)
const APEX_TypeDefinitionBase * myTypeDefn
Definition: APEX_Callback.h:59