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_Span.h>
24 #include <UT/UT_StringHolder.h>
25 #include <UT/UT_StringView.h>
26 #include <UT/UT_Tracing.h>
27 #include <UT/UT_Tuple.h>
28 #include <UT/UT_WorkBuffer.h>
29 
30 #include <SYS/SYS_Math.h>
31 #include <SYS/SYS_Types.h>
32 
33 #include <algorithm>
34 #include <iterator>
35 #include <string>
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  NOOP, /// Do nothing; ignored after compilation.
413 
414  NORMAL, /// Normal callback which is unconditionally executed
415 
416  /// @{ flow control
417 
418  IF_BEGIN, /// Callback is used as an IF_BEGIN: expects the signature to be exactly a Bool called
419  /// condition + scope/spare
420  IF_END, /// Callback marks the end of an if block: expects the signature to be exactly
421  /// scope/spare.
422 
423  LOOP_BEGIN, /// Marks the start of an arbitrary loop, expects RunData to be an iterator
424  LOOP_END /// Marks the end of an arbitrary loop, expects RunData to be an iterator and shares
425  /// that rundata with the corresponding LOOP_BEGIN.
426 
427  /// @}
428 };
429 
431 
433 {
434 public:
435  virtual ~APEX_FunctionBase() = default;
436 
437  virtual const UT_StringHolder &getName() const = 0;
438  virtual void compile(
439  const APEX_Graph *graph,
440  APEX_NodeID node_id,
441  APEX_Program *prog,
443  {
444  }
445  virtual void execute(APEX_ArgPtrs &arg_ptrs) const {}
446 
447  /// What kind of function is this? Informs things like scopes & conditions
449 
450  virtual const APEX_Signature &signature() const = 0;
451 
452  virtual const APEX_TypeDefinitionBase *runDataTypeDef() const { return nullptr; }
453 
454  /// Earliest Houdini version that this callback is allowed in "X.Y.Z" format
455  virtual const char *minProductVersion() const { return nullptr; }
456 
457  /// Determines whether the callback should be hidden from the UI
458  virtual bool isHidden() const { return false; }
459 
460  /// Whether the callback requires its input geometry CE caches to be flushed.
461  virtual bool requiresCEFlush() const { return true; }
462 
463  /// Whether the callback leaves CE caches in its output geometry.
464  virtual bool usesCE() const { return false; }
465 
466  /// Called for any type with rundata with a reference to the rundata so it can be initialized.
467  virtual void runDataCompileHook(
468  APEX_Argument *rundata_instance,
469  const APEX_Graph *in_graph,
470  APEX_NodeID for_node,
471  APEX_Program *bind_to) const
472  {
473  }
474 
475  /// Does this node open a scope?
476  bool opensScope() const
477  {
478  auto t = callbackType();
480  }
481 
482  /// Does this node close a scope?
483  bool closesScope() const
484  {
485  auto t = callbackType();
487  }
488 
489  /// Name of the fake wire which is used to denote scope relationships.
490  virtual UT_StringHolder scopeConnection() const { return ""; }
491 
492  virtual bool hasSubnetTemplate() const { return false; }
493 
494  virtual const Dict &parmDefaults() const
495  {
496  return Dict::getAPEXStaticEmpty();
497  }
498 };
499 
500 template <typename C, typename... Ts, size_t... Index>
501 inline void
502 applyArgs(const C &callback, APEX_ArgPtrs &arg_ptrs, std::index_sequence<Index...>)
503 {
504  callback(*reinterpret_cast<std::remove_pointer_t<std::remove_const_t<Ts>> *>(arg_ptrs[Index])...);
505 }
506 
507 /// Invoke the callback with the provided arguments, which are casted to type Ts...
508 template <typename C, typename... Ts>
509 inline void
510 applyArgs(const C &callback, APEX_ArgPtrs &arg_ptrs)
511 {
512  applyArgs<C, Ts...>(callback, arg_ptrs, std::index_sequence_for<Ts...>{});
513 }
514 
515 template <typename T>
516 void
518 {
519  const APEX_TypeDefinitionBase *t_defn = findTypeDef<std::remove_const_t<T>>();
520 
521  if constexpr (std::is_const_v<T>)
522  {
523  sig.myInputs.emplace_back(name, t_defn);
524  if (name.startsWith(theSparePortPrefix))
525  sig.myOutputs.emplace_back(name, t_defn);
526  }
527  else
528  {
529  sig.myOutputs.emplace_back(name, t_defn);
530  if (name.startsWith(theInplacePortPrefix)
531  || name.startsWith(theConditionalInplacePortPrefix))
532  sig.myInputs.emplace_back(name, t_defn);
533  }
534 }
535 
536 template <typename... Ts, size_t... Index>
537 APEX_Signature
539  UT_Span<const char* const, sizeof...(Ts)> argnames,
540  std::index_sequence<Index...>)
541 {
543  ((addToSignature<Ts>(result, argnames[Index])), ...);
544  return result;
545 }
546 
547 template <typename... Ts>
548 APEX_Signature
549 makeSignature(UT_Span<const char* const, sizeof...(Ts)> argnames)
550 {
551  if constexpr (sizeof...(Ts) == 0)
552  return APEX_Signature();
553 
554  return makeSignature<Ts...>(argnames, std::index_sequence_for<Ts...>{});
555 }
556 
557 /// NB: This overload is here for backward compatibility. It was used to handle
558 /// callbacks declaring an empty argnames member (since const char*[0] is a
559 /// non-standard c++ type). The rare callbacks which do have an empty argnames
560 /// member should instead use a std::array<T, 0>:
561 /// `static constexpr std::array<const char*, 0> argnames = {};`
562 template <typename... Ts>
563 APEX_Signature
564 makeSignature(std::nullptr_t)
565 {
566  return APEX_Signature();
567 }
568 
569 template <typename C, typename... Ts>
571 {
572 public:
574  {
575  if constexpr (!std::is_null_pointer_v<decltype(C::argnames)>)
576  {
577  static_assert(
578  sizeof...(Ts) == std::size(C::argnames),
579  "Callback argnames size does not match template argument size");
580  }
581 
582  myName = C::funcname.asHolder();
583  mySignature = makeSignature<Ts...>(C::argnames);
584 
585  UT_Options defaults;
586  defaults.setFromPyDictionary(C::parm_defaults);
587  myDefaults->mergeUtOptions(&defaults, false, true, true, &mySignature);
588  }
589 
590  ~APEX_GenericFunction() override {}
591 
592  const UT_StringHolder &getName() const override { return myName; }
593 
594  static constexpr const char *parm_defaults = "";
595 
596  const APEX_Signature &signature() const override { return mySignature; };
597 
599 
600  const Dict &parmDefaults() const override { return myDefaults; }
601 
602  void addSparePort(const UT_StringRef &name = "", exint index = -1)
603  {
604  mySignature.addSparePort(name, index);
605  }
606 
607  bool addInputAlias(const UT_StringRef &name, const UT_StringRef &alias)
608  {
609  return mySignature.addInputAlias(name, alias);
610  }
611 
612  bool addOutputAlias(const UT_StringRef &name, const UT_StringRef &alias)
613  {
614  return mySignature.addOutputAlias(name, alias);
615  }
616 
617  void execute(APEX_ArgPtrs &arg_ptrs) const override
618  {
619  utZoneScopedN(C::funcname);
620  const auto &derived = static_cast<const C &>(*this);
621  applyArgs<C, Ts...>(derived, arg_ptrs);
622  }
623 
624 protected:
626 
627 private:
628  APEX_Signature mySignature;
629  Dict myDefaults;
630 };
631 
632 /// Splits the namespace version of @a fullname into a name and version pair.
633 /// For example, "string::Build::3.0" is split as {"string::Build", "3.0"}.
634 inline std::pair<UT_StringHolder, UT_StringHolder>
635 APEXsplitNameAndVersion(const char *fullname)
636 {
637  UT_WorkBuffer scope, name_space, core_name, version;
639  fullname, &scope, &name_space, &core_name, &version);
640 
642  if (!name_space.isEmpty())
643  {
644  name.append(name_space);
645  name.append("::");
646  }
647  name.append(core_name);
648 
649  return {std::move(name), std::move(version)};
650 }
651 
652 /// Filters the @p callbacks array by removing the callbacks whose signatures
653 /// do not contain all parms present in the @p filter signature. Returns the
654 /// number of removed callbacks.
655 ///
656 /// The filter signature represents a sparse set of required parms.
657 /// Callbacks with additional parms are not removed as long as all parms in the
658 /// filter signature are present in the callback signature.
659 template <typename T>
660 exint
662 {
663  exint removed_count = 0;
664  for (auto it = callbacks.rbegin(); it != callbacks.rend(); ++it)
665  {
666  const T *ptr = *it;
667  const APEX_Signature &sig = ptr->signature();
668 
669  // Compare input signatures
670  bool input_matches = true;
671  for (const APEX_Parm &filter_i : filter.inputs())
672  {
673  const APEX_Parm &cb_sig_i = sig.findInput(filter_i.name());
674  if (!cb_sig_i.isValid() || cb_sig_i.myTypeDefn != filter_i.myTypeDefn)
675  {
676  input_matches = false;
677  break;
678  }
679  }
680  if (!input_matches)
681  {
682  callbacks.removeItem(it);
683  removed_count++;
684  continue;
685  }
686 
687  // Compare output signatures
688  bool output_matches = true;
689  for (const APEX_Parm &filter_o : filter.outputs())
690  {
691  const APEX_Parm &sig_o = sig.findOutput(filter_o.name());
692  if (!sig_o.isValid() || sig_o.myTypeDefn != filter_o.myTypeDefn)
693  {
694  output_matches = false;
695  break;
696  }
697  }
698  if (!output_matches)
699  {
700  callbacks.removeItem(it);
701  removed_count++;
702  }
703  }
704 
705  return removed_count;
706 }
707 
708 } // end namespace apex
709 
710 #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
constexpr size_t size(const OIIO::span< T, E > &c)
Definition: span.h:381
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)
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
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
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:222
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:1064
exint emplace_back(S &&...s)
Definition: UT_ArrayImpl.h:781
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
void applyArgs(const C &callback, APEX_ArgPtrs &arg_ptrs, std::index_sequence< Index...>)
bool operator()(APEX_Parm const &p)
exint numOutputs() const
reverse_iterator rend()
End reverse iterator.
Definition: UT_Array.h:1070
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:87
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 ptr(T p) -> const void *
Definition: format.h:4331
condition + scope/spare
**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:1097
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:177
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:1953
virtual bool usesCE() const
Whether the callback leaves CE caches in its output geometry.
UN_NodeID APEX_NodeID
Definition: APEX_Include.h:233
void execute(APEX_ArgPtrs &arg_ptrs) const override
bool isInplace() const
Definition: APEX_Callback.h:90
APEX_Signature makeSignature(UT_Span< const char *const, sizeof...(Ts)> argnames, std::index_sequence< Index...>)
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
const APEX_TypeDefinitionBase * myTypeDefn
Definition: APEX_Callback.h:59