DD::Image::Knob Class Referenceabstract

Inherits DD::Image::ValueStuffI.

Inherited by DD::Image::ShapeKnob, and DummyKnob.

Classes

class  cstring
 
class  Script_List
 

Public Types

enum  CallbackReason { kDestroying, kIsVisible, kUpdateWidgets, kChanged }
 
enum  HandleType {
  INVALID, POSITION, SELECTABLE, DISTANCE_FROM_POINT,
  DISTANCE_WITH_SNAP, ANYWHERE, ANYWHERE_MOUSEMOVES, ANYWHERE_KEY_PRESSED,
  SELECTED_BY_THIS
}
 
enum  HandleFlags { HOVER, USE_CURRENT_COLOR, LOW_PRIORITY, DO_HANDLE_CALLBACK_ON_SHIFT_SELECT }
 
typedef std::vector< int > SelectedIndexVector
 
typedef U64 FlagMask
 
typedef int(* Callback) (void *closure, CallbackReason)
 
typedef std::vector< int > TKnobIndices
 
typedef bool( HandleBatch) (ViewerContext *ctx, Knob *, const int focusIndex, const TKnobIndices &indices)
 
typedef bool( Handle) (ViewerContext *ctx, Knob *, int index)
 

Public Member Functions

void setClaimedName (const std::string &claimedName)
 
const std::string & claimedName ()
 
void setDefaultName (const std::string &defaultName)
 
void setDrawHandleTypes (DrawHandleTypeMask drawHandleTypes)
 
DrawHandleTypeMask drawHandleTypes () const
 
const std::string & defaultName () const
 
 Knob (Knob_Closure *c, const char *name, const char *label=nullptr)
 
virtual const char * Class () const =0
 
virtual int ClassID () const
 
virtual ArrayKnobI * arrayKnob ()
 
virtual ResizableArrayKnobI * resizableArrayKnob ()
 
virtual StringKnobI * stringKnob ()
 
virtual ScriptKnobI * scriptKnob ()
 
virtual Enumeration_KnobIenumerationKnob ()
 
virtual Colorspace_KnobIcolorspaceKnob ()
 
virtual SceneView_KnobIsceneViewKnob ()
 
virtual MultiArray_KnobImultiArrayKnob ()
 
virtual List_KnobI * listKnob ()
 
virtual Table_KnobI * tableKnob ()
 
virtual Geo_KnobI * geoKnob ()
 
virtual Axis_KnobI * axisKnob ()
 
virtual PositionVector_KnobIpositionVectorKnob ()
 
virtual PluginPython_KnobI * pluginPythonKnob ()
 
virtual GeoSelect_KnobI * geoSelectKnob ()
 
virtual ControlPointCollection_KnobI * controlPointCollectionKnob ()
 
virtual MetaKeyFrame_KnobI * metaKeyFrameKnob ()
 
virtual TransformJack_KnobI * transformJackKnob ()
 
virtual Transform2d_KnobI * transform2dKnob ()
 
virtual Ripple_KnobI * rippleKnob ()
 
virtual File_KnobIfileKnob ()
 
virtual LookupCurves_KnobIlookupCurvesKnob ()
 
virtual ColorKnobI * colorKnob ()
 
virtual AnimationHolderI * animationKnob ()
 
virtual LinkKnobI * linkKnob ()
 
VersionNumbers * version ()
 
VersionNumbers * version () const
 
Node * node () const
 
void set_node (Node *n)
 
Opop () const
 
const std::string & name () const
 
void name (const char *p)
 
bool is (const char *v) const
 
bool startsWith (const char *v) const
 
const std::string & label () const
 
const std::string & labelToUse () const
 
bool labelNotNull () const
 
void label (const char *)
 
bool canCopyValue () const
 
bool canSaveValueToPreset () const
 
std::string fullyQualifiedName (int idx=-1) const
 
const char * label_c_str () const
 
const char * name_c_str () const
 
const std::string & tooltip () const
 
void tooltip (const std::string &p)
 
void flags (FlagMask f) noexcept
 
void set_flag (FlagMask f) noexcept
 
void clear_flag (FlagMask f) noexcept
 
void invert_flag (FlagMask f) noexcept
 
void set_flag (FlagMask f, bool b) noexcept
 
FlagMask flags () const noexcept
 
bool flag (FlagMask f) const noexcept
 
bool any_of (FlagMask f) const noexcept
 
bool all_of (FlagMask f) const noexcept
 
virtual bool priority_undo () const
 
virtual WidgetPointer make_widget (const WidgetContext &context)
 this is the new version for 7.0 onwards More...
 
virtual WidgetPointer make_secondary_widget (const WidgetContext &context)
 
virtual void updateUI (const OutputContext &)
 
void addCallback (Callback cb, void *closure)
 
void removeCallback (Callback cb, void *closure)
 
bool isCallbackRegistered (Callback cb, void *closure) const
 
bool isEnabled () const
 
void enable ()
 
void disable ()
 
virtual void enable (bool)
 
virtual bool disabledDueToLicensing () const
 
virtual bool isReadOnly () const
 
void setReadOnly (bool value)
 
bool isReadOnlyInScripts () const
 
void setReadOnlyInScripts ()
 
bool isVisible () const
 
bool isHandleVisible () const
 
int openLinkCount () const
 the number of panels open which contain a link knob pointing at this knob
 
virtual void openLink ()
 increase the openLinkCount
 
virtual void closeLink ()
 decrease the openLinkCount
 
void hide ()
 
void show ()
 
void visible (bool)
 
bool isOpen () const
 
void open ()
 
void close ()
 
void open (bool)
 
bool isPushed () const
 
void pushed (bool p)
 
Knobknob (const char *) const
 
Knobknob (int) const
 
bool node_disabled () const
 
bool panel_visible () const
 
bool node_selected () const
 
unsigned node_gl_color () const
 
bool script_command (const char *command, bool py=true, bool eval=true) const
 
bool script_expand (const char *str, int what=1) const
 
virtual void reset_to_default ()
 
virtual bool build_handle (ViewerContext *)
 
void add_draw_handle (ViewerContext *)
 
virtual void draw_handle (ViewerContext *)
 
void begin_handle (HandleContext command, ViewerContext *ctx, Handle *cb, int index, const DD::Image::Vector3 &pos, ViewerContext::Cursor cursor=ViewerContext::kNoCursor)
 
void begin_handle (ViewerContext *ctx, Handle *cb, int index, const DD::Image::Vector3 &pos, ViewerContext::Cursor cursor=ViewerContext::kNoCursor)
 
void begin_handle (HandleContext command, ViewerContext *ctx, Handle *cb, int index, float x=0, float y=0, float z=0, ViewerContext::Cursor cursor=ViewerContext::kNoCursor)
 
void begin_handle (ViewerContext *ctx, Handle *cb, int index, float x=0, float y=0, float z=0, ViewerContext::Cursor cursor=ViewerContext::kNoCursor)
 
void end_handle (ViewerContext *ctx)
 
void make_handle (HandleContext command, ViewerContext *ctx, Handle *cb, const int index, const DD::Image::Vector3 &pos, const ViewerContext::Cursor cursor=ViewerContext::kNoCursor)
 
void make_handle (ViewerContext *ctx, Handle *cb, const int index, const DD::Image::Vector3 &pos, const ViewerContext::Cursor cursor=ViewerContext::kNoCursor)
 
void make_handle (HandleContext command, ViewerContext *ctx, Handle *cb, const int index, const float x, const float y, const float z=0.0f, const ViewerContext::Cursor cursor=ViewerContext::kNoCursor)
 
void make_handle (ViewerContext *ctx, Handle *cb, const int index, const float x, const float y, const float z=0.0f, const ViewerContext::Cursor cursor=ViewerContext::kNoCursor)
 
bool is_selected (ViewerContext *ctx, Handle *cb, int index) const
 
virtual bool is_selected (ViewerContext *ctx, int index) const
 
void get_selected_indices (Handle *cb, SelectedIndexVector &allIndices) const
 
bool clear_selected (ViewerContext *)
 
bool toggle_selected (ViewerContext *ctx, Handle *cb, int index)
 
virtual bool toggle_selected (ViewerContext *ctx, int index)
 
bool is_focused (ViewerContext *, Handle *cb, int index)
 
int selection_size (ViewerContext *)
 
void add_to_undo ()
 
void stop_add_to_undo ()
 
void new_undo (const char *name=nullptr)
 
void force_new_undo (const char *name=nullptr)
 
void extra_undo ()
 
void new_undo (const void *controller)
 
bool doingUndoRedo ()
 
virtual Knobundoer ()
 
void setUndoer (Knob *undoer)
 
void new_nudge_undo ()
 
void undo ()
 
void redo ()
 
virtual void changed ()
 
void updateWidgets ()
 
void asapUpdate ()
 
void asapUpdate (const Box &box, int direction=0)
 
void redraw ()
 
void undoless (bool undoless)
 
const OutputContextuiContext () const
 
const Formatinput_format () const
 
virtual void store (StoreType, void *p, Hash &hash, const OutputContext &context)
 
virtual void append (Hash &hash, const OutputContext *context)
 
virtual int get_key_list (std::set< int > &keylist) const
 
virtual int get_key_list (std::set< int > &keylist, int index) const
 
virtual bool splitForViews () const
 
virtual ViewSet storedViews () const
 
virtual bool keyframesDisplayed () const
 
virtual bool from_script (const char *v)
 
bool set_text (const char *v)
 
bool to_double (const char *, double &result)
 
bool to_int (const char *, int &result)
 
bool to_bool (const char *, bool &result)
 
virtual const char * get_text (const OutputContext *=nullptr) const
 
virtual void to_script (std::ostream &, const OutputContext *, bool quote) const
 
virtual void to_script_prefix (std::ostream &) const
 
virtual void to_script_userknob (std::ostream &) const
 
virtual bool not_default () const
 
void * pyObject ()
 
void setPyObject (void *s)
 
KnobImpl * pImpl ()
 
- Public Member Functions inherited from DD::Image::ValueStuffI
virtual int value_stuff (int what, ValueStuffArg *user=nullptr) const
 
bool set_value (double v, int channel=-1)
 
bool set_value_at (double v, double time, int channel=-1)
 
bool set_value_at_view (double v, double time, int view, int channel=-1)
 
bool set_key (int channel=-1, int view=-1)
 
bool set_key_at (double time, int channel=-1, int view=-1)
 
bool set_values (const double *array, int n)
 
bool set_values_at (const double *array, int n, double time)
 
bool set_values (const float *array, int n)
 
bool set_values_at (const float *array, int n, double time)
 
bool set_values (const int *array, int n)
 
bool set_values_at (const int *array, int n, double time)
 
bool set_values (const U64 *array, int n)
 
bool set_values_at (const U64 *array, int n, double time)
 
bool remove_key (int channel=-1)
 
bool remove_key_at (double time, int channel=-1, int view=-1)
 
void set_range (double a, double b, bool force=false)
 
void set_animation (const char *a, int channel=-1)
 
bool is_key_at (double time, int channel=-1, int view=-1) const
 
bool is_key (int channel=-1) const
 
double get_value (int channel=0) const
 
double get_value_at (double time, int channel=0) const
 
double get_value_at_view (double time, int view, int channel=0) const
 
double get_value_at (const OutputContext &oc, int channel=0) const
 
bool set_expression (const char *v, int channel, int view=-1)
 
int getNumKeys (int channel=-1, int view=-1) const
 
int getKeyIndex (double &time, int channel=-1, int view=-1) const
 
bool split_view (int view)
 
bool unsplit_view (int view)
 
void getKeyFrame (int keyindex, double &x, double &y, double &lslope, double &rslope, double &la, double &ra, unsigned char &interp, unsigned char &extrap, int channel, int view=-1) const
 
void setKeyFrame (int keyindex, double x, double y, double lslope, double rslope, double la, double ra, unsigned char interp, unsigned char extrap, int channel, int view=-1) const
 
void addKeyFrame (double x, double y, double lslope, double rslope, double la, double ra, unsigned char interp, unsigned char extrap, int channel, int view=-1) const
 
void get_expression (std::string &expr, int channel=-1, int view=-1)
 
double getKeyTime (int keyindex, int channel=-1, int view=-1) const
 
double getDerivative (double time, int channel=0, int view=-1) const
 
double getNthDerivative (int n, double time, int channel=0, int view=-1) const
 
double getIntegral (double t1, double t2, int channel=0, int view=-1) const
 
double getInverse (double value, int channel=0, int view=-1) const
 
double getInverseGeneral (double value, int channel=0, int view=-1) const
 
bool set_animated (int channel=-1) const
 
bool is_animated (int channel=-1)
 
bool clear_animated (int channel=-1)
 
bool clear_animated_view (int view, int channel=-1)
 
bool set_animated_view (int view, int channel=-1)
 
bool is_animated_view (int view, int channel=-1)
 
bool toggle ()
 
bool set_input (int input)
 

Static Public Member Functions

static void addTooltipOverride (const std::string &knob, const std::string &tooltip)
 
static const char * script_result (bool py=false)
 
static void script_unlock ()
 
static int message (char t, const char *,...)
 
static int vmessage (char t, const char *, va_list)
 
static Indent * indent ()
 
static void error (const char *lpFormat,...)
 
static void warning (const char *lpFormat,...)
 
static void critical (const char *lpFormat,...)
 
static void debug (const char *lpFormat,...)
 
static void error (Knob *lpKnob, const char *lpFormat,...)
 
static void warning (Knob *lpKnob, const char *lpFormat,...)
 
static void critical (Knob *lpKnob, const char *lpFormat,...)
 
static void debug (Knob *lpKnob, const char *lpFormat,...)
 

Static Public Attributes

static constexpr const FlagMask DISABLED
 Grey out and lock interface. Prevents copy/paste (see READ_ONLY to allow this).
 
static constexpr const FlagMask NO_ANIMATION
 Disable right click and button animation menu.
 
static constexpr const FlagMask DO_NOT_WRITE
 Disables calling to_script. No writing to script file or copy/paste.
 
static constexpr const FlagMask INVISIBLE
 Disables param and viewer widgets. Cannot be made visible again. See HIDDEN for this.
 
static constexpr const FlagMask RESIZABLE
 Allows more complex knobs to resize param panel to fill available space.
 
static constexpr const FlagMask STARTLINE
 Start a new line in the param panel before knob widget.
 
static constexpr const FlagMask ENDLINE
 Start a new line in the param panel after knob widget.
 
static constexpr const FlagMask NO_RERENDER
 Removes knob from Op hash calculation, preventing rerendering on value change.
 
static constexpr const FlagMask NO_HANDLES
 Disables viewer widget handles from drawing.
 
static constexpr const FlagMask KNOB_CHANGED_ALWAYS
 Always calls knob_changed, regardless of whether it has previously returned false.
 
static constexpr const FlagMask NO_KNOB_CHANGED
 Prevents knob_changed being called on value change. Set if prev knob_changed returned false.
 
static constexpr const FlagMask HIDDEN
 Disables param panel and viewer widgets. Can be managed dynamically with show/hide.
 
static constexpr const FlagMask NO_UNDO
 Disables laying down of undo/redo points.
 
static constexpr const FlagMask ALWAYS_SAVE
 Forces data to always be written regardless. Deprecated. Override not_default instead.
 
static constexpr const FlagMask NODE_KNOB
 For internal use only.
 
static constexpr const FlagMask HANDLES_ANYWAY
 Force viewer widgets to be visible regardless of current node tab.
 
static constexpr const FlagMask INDETERMINATE
 Presents a blacked out undefined value interface on supporting knobs.
 
static constexpr const FlagMask COLOURCHIP_HAS_UNSET
 Defines whether a color chip can be in the 'unset' state. Defaults to false.
 
static constexpr const FlagMask SMALL_UI
 Switches param panel widget to be more viewer Toolbar friendly in supported knobs (eg Button).
 
static constexpr const FlagMask NO_NUMERIC_FIELDS
 Disables numeric input box widget on supported knobs.
 
static constexpr const FlagMask KNOB_CHANGED_RECURSIVE
 Recursive knob_changed calls are prevented unless overriden using this flag.
 
static constexpr const FlagMask READ_ONLY
 As with DISABLED, except value can be copied from and expression linked against.
 
static constexpr const FlagMask NO_CURVE_EDITOR
 Disables curve editor.
 
static constexpr const FlagMask NO_MULTIVIEW
 Disables view menu and splitting when in a multiview script.
 
static constexpr const FlagMask EARLY_STORE
 Forces early synchronisation of data allowing usage in pre-op calls such as split_input().
 
static constexpr const FlagMask MODIFIES_GEOMETRY
 Should be set on all knobs which modify geometry or associated transforms.
 
static constexpr const FlagMask OUTPUT_ONLY
 Similar to READ_ONLY & NO_RERENDER together - data changes don't count as a script change.
 
static constexpr const FlagMask NO_KNOB_CHANGED_FINISHED
 Prevents knob_changed_finished being called on value change. Set if prev call returned false.
 
static constexpr const FlagMask SET_SIZE_POLICY
 Do not use.
 
static constexpr const FlagMask EXPAND_TO_WIDTH
 Force knob to expand to fill available space. - only for Enum knobs currently.
 
static constexpr const FlagMask NEVER_DRAW_HANDLES
 Disables viewer widget handles from drawing. Unlike the NO_HANDLES flag, the state of this flag will never change internally within Nuke.
 
static constexpr const FlagMask KNOB_CHANGED_RIGHTCONTEXT
 Always call knob_changed on a properly cooked Op, even if KNOB_CHANGED_ALWAYS is on.
 
static constexpr const FlagMask DONT_SAVE_TO_NODEPRESET
 This value of this knob should never be saved to a NodePreset. Can be used, for example, for data knobs.
 
static constexpr const FlagMask RESERVED_COLORCHIP_KNOB
 DO NOT USE. This value is used by the colorchip knob.
 
static constexpr const FlagMask READ_ONLY_IN_SCRIPTS
 Prevents knobs from being modified from Python/Tcl.
 
static constexpr const FlagMask ALWAYS_ALIGN_LABEL_TOP
 Label is always aligned to the top of the Knob.
 
static constexpr const FlagMask TINY_SLIDER
 Modifies SLIDER to be a tiny slider underneath lineedit. Should be a numeric knob flag but we've overrun the < 0x80 condition.
 
static constexpr const FlagMask HIDE_ANIMATION_AND_VIEWS
 Prevents Animation Curve_Knob and Views being shown. Animation is still possible, unless NO_ANIMATION is set of course.
 
static constexpr const FlagMask NO_COLOR_DROPDOWN
 Prevents Color Panel Dropdown from being available. Popup color panel will stil be available.
 
static constexpr const FlagMask NODEGRAPH_ONLY
 Indicate that this knob should only be displayed when using the NodeGraph, since the Timeline uses gpuEngine, which might not support all the same knobs.
 
static constexpr const FlagMask NO_SCRIPT_EXECUTE
 Prevents 'execute' being called on the knob.
 
static constexpr const FlagMask MODIFIES_TIME
 Should be set on all knobs which modify timing.
 
static constexpr const FlagMask TOOLBAR_BUTTON_DRAWSTYLE
 This knob must be drawn in the style of Viewer toolbar knobs.
 
static constexpr const FlagMask FLAGS_LOCKED
 Used to lock modifications to this knobs flags.
 
static constexpr const FlagMask MAGNITUDE
 Enables switchable numeric box & slider to multiple boxes (array knob derived numeric knobs).
 
static constexpr const FlagMask SLIDER
 Enables slider on single numeric knob, or array knob with MAGNITUDE set (numeric knobs).
 
static constexpr const FlagMask LOG_SLIDER
 Switches linear slider to log slider, or cubic depending on range (numeric knobs with SLIDER).
 
static constexpr const FlagMask STORE_INTEGER
 Stores and presents integer value rather than float (numeric knobs).
 
static constexpr const FlagMask FORCE_RANGE
 Forces stored and presented value to be clamped to range set (numeric knobs).
 
static constexpr const FlagMask ANGLE
 Switches widget for angle UI (single value numeric knobs).
 
static constexpr const FlagMask NO_PROXYSCALE
 Disables proxyscaling on knobs supporting it (XY_Knob & WH_Knob derivatives).
 
static constexpr const FlagMask GRANULAR_UNDO
 Disables concatenation of minor undo events (string knobs)
 
static constexpr const FlagMask NO_RECURSIVE_PATHS
 Badly named. Actually disables relative paths (string knobs).
 
static constexpr const FlagMask NO_TCL_ERROR
 For strings containing TCL expressions, don't replace with TCL error messages if an error occurs.
 
static constexpr const FlagMask SAVE_MENU
 Forces menu entries to be written to script. Used by dynamic menus (enumeration knobs).
 
static constexpr const FlagMask EXPAND_TO_CONTENTS
 Make Enumeration knobs adjust their width to the size of the largest munu item.
 
static constexpr const FlagMask EXACT_MATCH_ONLY
 invalid value, the knob will be put into an Error state. More...
 
static constexpr const FlagMask STRIP_CASCADE_PREFIX
 Make Cascading Enumeration knobs not serialise out cascading prefixes.
 
static constexpr const FlagMask SINGLE_SELECTION_ONLY
 Knob only allows one item to be selected at a time.
 
static constexpr const FlagMask SHOW_BUTTONS
 Show Add Layer/Delete Layer buttons.
 
static constexpr const FlagMask CLOSED
 Stores the open/closed state of group knobs (group knobs).
 
static constexpr const FlagMask TOOLBAR_GROUP
 Make the group into a viewer toolbar. General used via BeginToolbar (group knobs).
 
static constexpr const FlagMask TOOLBAR_LEFT
 Defines which side of viewer toolbar appears on. Pick one at toolbar construction time (toolbar).
 
static constexpr const FlagMask TOOLBAR_TOP
 Defines which side of viewer toolbar appears on. Pick one at toolbar construction time (toolbar).
 
static constexpr const FlagMask TOOLBAR_BOTTOM
 Defines which side of viewer toolbar appears on. Pick one at toolbar construction time (toolbar).
 
static constexpr const FlagMask TOOLBAR_RIGHT
 Defines which side of viewer toolbar appears on. Pick one at toolbar construction time (toolbar).
 
static constexpr const FlagMask TOOLBAR_POSITION
 A mask for the position part of the flags.
 
static constexpr const FlagMask NO_CHECKMARKS
 Disable individual channel checkbox widgets (channel/channelset knobs).
 
static constexpr const FlagMask NO_ALPHA_PULLDOWN
 Disable 4th channel pulldown widget (channel/channelset knobs).
 
static constexpr const FlagMask FULL_LAYER_ENABLED
 channel/channelset knobs will always consider every channel in a layer to be enabled.
 
static constexpr const FlagMask PROXY_DEFAULT
 Sets default knob value from script proxy format rather than full res (format knob).
 
static constexpr const FlagMask COLORCHIP_PRESERVE_ALPHA
 The ColorChip_knob discards alpha values by default. Set this flag to make it keep them, instead.
 
static constexpr const FlagMask ALLOW_NUKE_COLORSPACES
 Allows the knob to display Nuke's native colorspaces if Color Management is set to Nuke.
 
static int nudgeController
 
static KnobshowPanel
 passed to Op::knob_changed() when panel opened
 
static KnobhidePanel
 passed to Op::knob_changed() when panel closed
 
static KnobinputChange
 passed to Op::knob_changed() when inputs change
 
static bool undo_state
 true in Op::knob_changed() when called due to undo/redo
 
static void(* pMessageCallback )(const Knob *lpKnob, const OpMessage &lrMessage)
 Callback function for internal use.
 

Additional Inherited Members

- Protected Types inherited from DD::Image::ValueStuffI
enum  {
  W_SETVALUES_DBL, W_SETVALUE, W_SETRANGE, W_SETVALUESAT_DBL,
  W_SETVALUES_FLT, W_SETVALUES_INT, W_SETVALUES_INT64, W_SETANIMATION,
  W_SETVALUEAT, W_SETKEY, W_SETKEYAT, W_ISKEYAT,
  W_GETVALUE, W_SETEXPRESSION, W_SETVALUESAT_FLT, W_SETVALUESAT_INT,
  W_SETVALUESAT_INT64, W_GETVALUEAT, W_REMOVEKEY, W_REMOVEKEYAT,
  W_ISKEY, W_GETNUMKEYS, W_GETKEYINDEX, W_GETKEYTIME,
  W_GETDERIVATIVE, W_GETINTEGRAL, W_GETVALUEATVIEW, W_SET_ANIMATED,
  W_IS_ANIMATED, W_CLEAR_ANIMATED, W_TOGGLE, W_SET_INPUT,
  W_SETVALUEAT_VIEW, W_SPLIT_VIEW, W_UNSPLIT_VIEW, W_CLEAR_ANIMATED_VIEW,
  W_IS_ANIMATED_VIEW, W_SET_ANIMATED_VIEW, W_GETKEYFRAME, W_SETKEYFRAME,
  W_ADDKEYFRAME, W_GETEXPRESSION, W_GETINVERSE, W_GETINVERSE_GENERAL
}
 

Detailed Description

Provides the user interface for a single named "control" of an Op.

The Op::knobs() function is called to create these and to list them in order to store() values into an instance of an Op.

The to_script() and from_script() methods are used to read and write the value as a text stream. This is used for saving scripts and also for implementing undo/redo.

The most common types of knobs produce a widget in the "control panel" of a Node in Nuke. However this functionality is private to Nuke. Plugins can only make knobs that are manipulated through the user clicking and dragging on the viewers. They can also create "child" knobs that display widgets.

Writing a new knob type is quite complex, though I hope it is not hopeless. It is recommended that you examine the source code to plugins that use it (DustBust, ...).

Member Enumeration Documentation

Commands passed to begin_handle

Enumerator
LOW_PRIORITY 

Indicates that this handle is low priority in terms of selecting. If multiple handles are contained within the pick area, normal priority handles are favoured over low priority ones.

DO_HANDLE_CALLBACK_ON_SHIFT_SELECT 

This flag is to get around the fact that, when shift-selectting, Nuke doesn't by default call handle callbacks. Setting this flag will ensure that it will.

Constructor & Destructor Documentation

Knob::Knob ( Knob_Closure *  c,
const char *  name,
const char *  label = nullptr 
)

The constructor for a knob adds it to the list being built for the current Node.

Member Function Documentation

const char * Knob::Class ( ) const
pure virtual

Return a string name for the type of knob. The base class returns "Knob". This is currently only used for messages.

int Knob::ClassID ( ) const
virtual

Return the enumeration value from Knobs.h that will create this knob. This is used to write instructions for creating this knob to a saved script. If no value creates this knob then return 0, and the user will not be able to clone the knob. The base class returns zero.

Op * Knob::op ( ) const

Return an Op that belongs to the control panel this Knob is on. You cannot make very many assumptions about this op except that it has been constructed. You could for instance get the Class() or help().

Referenced by DD::Image::PrintKnobChangedInValidateWarning().

bool DD::Image::Knob::is ( const char *  v) const
inline

fn bool Knob::is(const char* name) const Return true if the name matches the passed string. You should use this in Op::knob_changed() methods to figure out if the changed knob is the one you are interested in.

Referenced by DD::Image::Executable::frameRangeKnobsChanged(), DD::Image::DrawIop::knob_changed(), DD::Image::NukeWrapper::knob_changed(), and DD::Image::ReadGeo::knob_changed().

bool Knob::startsWith ( const char *  v) const

Return true if the name starts with the substring. Useful in Op::knob_changed() to detect a set of related knobs.

std::string Knob::fullyQualifiedName ( int  idx = -1) const

returns the fully-qualified name of the knob within the node. This can be useful for expression linking. "idx" specifies the optional channel number of the sub-knob, leave blank or set to -1 to get the qualified name of the knob only.

const std::string & Knob::tooltip ( ) const

Get the tooltip for the knob

void DD::Image::Knob::addTooltipOverride ( const std::string &  knob,
const std::string &  tooltip 
)
static

Add a tooltip override to the tooltip overrides table. 'knob' is expected to be in the form 'Blur.size', and tooltip is the text to be displayed instead of the default tooltip

WidgetPointer Knob::make_widget ( const WidgetContext &  context)
virtual

this is the new version for 7.0 onwards

Create the widget to put in a panel for the knob and return it. This can return null if no widget should be created, this is what the default version does.

addCallback() must be called to add some function that is called when the value changes or when the knob is destroyed, so that the widget can respond to it. Nuke source code currently wraps this in another function called add_widget_to_knob().

WidgetPointer Knob::make_secondary_widget ( const WidgetContext &  context)
virtual

Create the secondary widget. This widget is intended to be be displayed below the existing label, if the label exists. The default implementation returns a NULL widget.

return WidgetPointer, a pointer to the widget which is to be displayed in the label column, else, NULL if no secondary widget is to be displayed (in which case the label will display as usual)

void Knob::updateUI ( const OutputContext )
virtual

Cause any update to widgets due to the outputContext() being changed. The default version does nothing, but subclasses that display the animated value must do this.

void Knob::addCallback ( Callback  cb,
void *  closure 
)

Add a callback to a GUI widget. Changes to the knob's visibility, enable, the value, and the destruction of the knob all send messages to this.

References DD::Image::end().

Referenced by DD::Image::LUTInfo::updateColorspaceDefaultValue().

void Knob::removeCallback ( Callback  cb,
void *  closure 
)

Remove a callback added with addCallback(). You must not call this if your callback got the kDestroying message.

References DD::Image::end().

Referenced by DD::Image::LUTInfo::updateColorspaceDefaultValue().

bool Knob::isCallbackRegistered ( Callback  cb,
void *  closure 
) const

Check if a callback was registered.

References DD::Image::end().

bool DD::Image::Knob::isEnabled ( ) const
inline

Return true if enable() was called or false if disable() was called.

bool DD::Image::Knob::disable ( )
inline

Same as enable(false)

Referenced by DD::Image::ReadGeo::knob_changed().

void Knob::enable ( bool  e)
virtual

Enable or disable (gray out) the widget. For historical reasons this will also show/hide the handles in the viewer by setting the NO_HANDLES flag. If you don't want this, set the flag back to the way you want after calling this.

References DISABLED, and NO_HANDLES.

bool Knob::isReadOnly ( ) const
virtual

Return true if this knob is read only. The default implementation tests for the read-only flag. In read-only mode, values will be displayed and can be copied and viewed as usual, but no modifications through direct user input will be possible. Changes may still be made through Tcl/Python.

Not all knobs support this flag.

References READ_ONLY.

bool DD::Image::Knob::isReadOnlyInScripts ( ) const
inline

Return true if this knob is read-only in scripts. The default implementation tests for the READ_ONLY_IN_SCRIPTS flag. In this mode, attempts to modify a knob's values will be prevented with an error. Changes may still be possible through the Nuke user interface (see READ_ONLY flag to block this)

References READ_ONLY_IN_SCRIPTS.

bool Knob::isVisible ( ) const

Return true if the widget is visible (ie the control panel is open and switched to the tab that this knob is on). Knobs with no widgets return panel_visible().

References HIDDEN, INVISIBLE, and panel_visible().

void DD::Image::Knob::hide ( )
inline

Make the widget disappear. This only works if the widget exists, which means you have to defer this until Op::knob_callback() is called with the show-panel knob.

Referenced by DD::Image::DrawIop::knob_changed(), DD::Image::NukeWrapper::knob_changed(), and DD::Image::InternalOCIOOp::nodePanelShown().

void DD::Image::Knob::show ( )
inline

Make the widget become visible, undoing a hide().

Referenced by DD::Image::DrawIop::knob_changed(), and DD::Image::NukeWrapper::knob_changed().

void Knob::visible ( bool  v)

Does show() if true, hide() if false.

References HIDDEN.

Referenced by DD::Image::DrawIop::knob_changed(), and DD::Image::Write::set_file_type().

bool DD::Image::Knob::isOpen ( ) const
inline

Returns true if this hierarchy title is open.

void DD::Image::Knob::open ( )
inline

Makes a hierarchy title open, showing all the child knobs.

References open().

Referenced by open().

void DD::Image::Knob::close ( )
inline

Makes a hierarchy title close, hiding all the child knobs.

void Knob::open ( bool  v)

Does open() if true, close() if false.

References CLOSED.

bool DD::Image::Knob::isPushed ( ) const
inline

Return true if this knob is "pushed". This means that the user is either holding down a slider in the control panel or is dragging a handle in the viewer. This can be used to decide whether to draw a texture map preview or not.

void DD::Image::Knob::pushed ( bool  p)
inline

Turn isPushed() on/off.

Knob * Knob::knob ( const char *  name) const

Return another knob on the same control panel as this knob, looked up by name.

Knob * Knob::knob ( int  n) const

Find a knob by index number. If the index number is larger than the number of knobs then null is returned. By starting at zero and incrementing until this returns null you will get every Knob known about. One of the return values will be this knob itself.

bool Knob::node_disabled ( ) const

Return true if the node this knob is in is disabled.

bool Knob::panel_visible ( ) const

Returns true if the control panel for this node is open. You may want to use visible(), which will return true only if the tab containing this knob is open.

Referenced by isVisible().

bool Knob::node_selected ( ) const

Returns true if the node is selected by the user. This can be used to turn a wireframe preview on/off.

unsigned Knob::node_gl_color ( ) const

Returns the color selected by the user to draw things in the viewer. The return value is of the form 0xrrggbb00.

bool Knob::script_command ( const char *  command,
bool  py = true,
bool  eval = true 
) const

Execute a string in Nuke's scripting language. You must call script_unlock() after calling this!

See also
Op::script_command
bool Knob::script_expand ( const char *  str,
int  what = 1 
) const
See also
Op::script_expand(). The integer argument is unused currently. Use 1 for future compatibility.
const char * Knob::script_result ( bool  py = false)
static
void Knob::script_unlock ( )
static
int Knob::message ( char  t,
const char *  format,
  ... 
)
static
See also
Op::message_f
int Knob::vmessage ( char  t,
const char *  format,
va_list  va 
)
static
See also
Op::message_f
bool Knob::build_handle ( ViewerContext ctx)
virtual

This call is used by viewers to search for objects that need to draw "handles" into the viewer. This will be called for all knobs on any opened control panel.

If you want to draw anything you should add a callback with ViewerContext::add_draw_handle(). Or you can return true and a callback that calls draw_handle() will be added for you.

Recommended you check that the viewer is in the correct mode (ctx->viewer_mode()!=0 indicates a 3D mode) and that visible() is true before you add the callbacks.

The default version returns false.

Referenced by DD::Image::Op::anyKnobHandles(), and DD::Image::Op::build_knob_handles().

void Knob::add_draw_handle ( ViewerContext ctx)

Convenience function to call ViewerContext::add_draw_handle() with a function that will call this->draw_handle().

References DD::Image::ViewerContext::add_draw_handle().

Referenced by DD::Image::Op::add_knob_handle(), and DD::Image::Op::build_knob_handles().

void Knob::draw_handle ( ViewerContext ctx)
virtual

If build_handle() returns true, then this will be called to actually draw the handle in OpenGL.

void Knob::begin_handle ( HandleContext  command,
ViewerContext ctx,
Handle cb,
int  index,
const DD::Image::Vector3 pos,
ViewerContext::Cursor  cursor = ViewerContext::kNoCursor 
)

Start drawing a handle. Any OpenGL you draw after this will be passed through hit-detection on a PUSH event and if selected then the cb will be called with events. draw_handle() should call this to indicate that the next thing to be drawn is something the user can click on, which we call a "handle".

The command describes the xyz that will be passed back to the handle callback. Current values are:

  • POSITION: The xyz passed in plus the distance the mouse dragged, with the numbers rounded somewhat to "nice" decimal numbers, and if the mouse has not moved very far or if shift is held down to restrict the axis, the passed-in xyz unchanged.
  • SELECTABLE: Same as POSITION except this is a selectable handle. It is selected by the user clicking on it, by the user dragging out a box, or by shift-clicking. When the user drags any selected handle then all of them get PUSH, DRAG, and RELEASE events and the first one gets the rounded position and all the others move in a locked formation with it. Any keystrokes are sent as KEY events to all the selected handles. If cb calls ctx->menu() then the menu only appears once, and all other calls return the same menu item, so the same action is done to all points.
  • DISTANCE_FROM_POINT: The difference between where the mouse is and the xyz position passed in this call (pass 0,0,0 if you want the absolute position in space). The xyz are not rounded so you probably don't want the numbers shown to the user, as they will have ugly extra digits of precision.
  • DISTANCE_WITH_SNAP: Same as DISTANCE_FROM_POINT except the delta values are rounded to "nice" numbers. Pass 0,0,0 to get "nice" rounded positions in space.
  • ANYWHERE, ANYWHERE_MOUSEMOVES, SELECTED_BY_THIS: these should only be passed to make_handle.

The cb function is called when the user causes an event that Nuke thinks should be sent to this handle. The function should return true if the event is consumed by this handle (returing false allows an ANYWHERE handle to get events). The context->event() says why this is being called:

  • PUSH - mouse was pushed down
  • DRAG - mouse was dragged after being pushed. The mouse position can be retrieved from context->x(), y(), and z(). These coordinates are in the same transformation that make_handle() was called in. You can also get the mouse position in pixels from context->mouse_x() and mouse_y(), though I'm not sure if you can do anything useful with that.
  • RELEASE - mouse was released after being dragged.
  • KEY - A keyboard key was pushed. You can get it from context->key().
  • KEYUP - A keyboard key was released. You can get it from context->key().
  • WHEEL - Mouse wheel (or other secondary manipulator) was moved. You can get the amount it was moved (in pixels) from context->wheel_dx() and wheel_dy().
  • MOVE - mouse is being dragged over window with no button pushed.
  • FIRST_MENU - You should use this as the first enumeration assigned to items in a Menu. If you call ctx->menu() and an item is picked the event is set to the picked item.
  • NO_EVENT - If you call ctx->menu() and either the user does not pick an item or they already picked an item from a different menu, then the event is set to this. You should not do anything in this case.

index is passed unchanged to the cb function. This can be used to select what part of a knob is being moved.

x and y (and z) indicate the initial position of the dragged object. Notice that it does not have to be the location you are drawing at.

void Knob::end_handle ( ViewerContext ctx)

draw_handle() should call this after calling begin_handle() and drawing the selectable items. It is harmless to call this extra times.

bool Knob::is_selected ( ViewerContext ctx,
Handle cb,
int  index 
) const

Return true if the cb was flagged as a SELECTABLE one and it is currently selected by the user.

More performant version of the other make_handle(). Accepts a function which takes an vector of handle indices which apply to that combination of (knob*, callback)

virtual bool DD::Image::Knob::is_selected ( ViewerContext ctx,
int  index 
) const
inlinevirtual

Return true if the main SELECTABLE callback is currently selected by the user.

void Knob::get_selected_indices ( Handle cb,
Knob::SelectedIndexVector &  allIndices 
) const

Return a vector of all selected indices for the given cb

bool Knob::clear_selected ( ViewerContext ctx)

Clear the selection list Return true if successful.

bool Knob::toggle_selected ( ViewerContext ctx,
Handle cb,
int  index 
)

Toggle the selection Return true if successful.

virtual bool DD::Image::Knob::toggle_selected ( ViewerContext ctx,
int  index 
)
inlinevirtual

Toggle the selection with the main SELECTABLE callback. Return true if successful.

bool Knob::is_focused ( ViewerContext ctx,
Handle cb,
int  index 
)

Returns true if the cb was flagged as HOVER, and it is currently in focus by the user

int Knob::selection_size ( ViewerContext ctx)

Return the selection size

void Knob::add_to_undo ( )

Add the current knob into the last undo event. This allows changes from different knobs to be grouped into a single event.

void Knob::stop_add_to_undo ( )

Stop adding to undo

void Knob::new_undo ( const char *  name = nullptr)

Same as new_undo(0). If this knob has not been recorded into the current Undo, start a new Undo and record the current state.

void Knob::force_new_undo ( const char *  name = nullptr)

Closes (possible) previous open undo event and starts a new one before recording the current state. This should be called by knobs instead of new_undo(...) when the action should not be merged with any previous open undo event.

void Knob::extra_undo ( )

Make changes to this knob be part of the current Undo.

Deprecated. You should not need to call this, Nuke merges undos for everything done by an Op::knob_changed() or other functions that should look like a single action to the user.

TODO : mark as deprecated

void Knob::new_undo ( const void *  controller)

Start a new Undo and remember the current state in that Undo, if either:

  • this knob has not been recorded in the current Undo
  • widget is non-zero and different than the previous call

The intention was for widget to be the widget being manipulated, though you can also pass pointers to static variables that indicate the "class" of widget, for instance if you want a set of checkmarks to all act like a single Undo.

You can call repeatedly with widget == NULL and subsequent calls are ignored. This makes it convienent to stuff this call into any method that is going to change the value.

See also
extra_undo
bool Knob::doingUndoRedo ( )

Check whether this knob changed event was invoked by an undo or redo

void DD::Image::Knob::new_nudge_undo ( )
inline

Call new_undo(widget) with a pointer to a constant that indicates a "nudge" modification, such as the numeric keypad keys. All adjacent nudge modifications for a knob are merged into a single undo.

void Knob::undo ( )

If possible this backs up to the last time new_undo() was called. However this may back up many other knobs to the same state, so only call this on one knob per panel!

See also
redo, new_undo, new_nudge_undo
void Knob::redo ( )

If possible this goes forward and undoes an undo. However this may back up many other knobs to the same state, so only call this on one knob per panel!

See also
undo, new_undo, new_nudge_undo
void Knob::changed ( )
virtual

This virtual function is called when the value of the knob changes. Subclasses can override this, they should not do anything very expensive (such as read a file) or Nuke will lock up! They must call the base class implementation, it calls UpdateWidgets(), sets the modified flag, and triggers the viewer to check to see if it needs to update, among other things.

References DD::Image::PrintKnobChangedInValidateWarning().

void Knob::updateWidgets ( )

Sometimes (especially in subclasses) you know that only the widget has to redraw and that the knob's value did not change. In this case you can call this function instead of changed(), to avoid triggering unnecessary recalculation.

void Knob::asapUpdate ( )

See Op::asapUpdate(). Indicate the output of the Ops controlled by this node are dynamically changing. This causes the viewer to update right away and disables disk caching of viewer images.

You must make the hash() of the Op change. If you are altering the knob's value, then this is probably enough to make the hash change.

void Knob::asapUpdate ( const Box box,
int  direction = 0 
)

See Op::asapUpdate(). Indicate the output of the Ops controlled by this node are dynamically changing and that the indicated area of the viewer should be drawn first. This causes the viewer to update right away and disables disk caching of viewer images. The direction indicates which way to draw the box, zero indicates you don't care. This is used by paint strokes, setting the direction to the same way the paint brush is moving makes the best feedback.

void Knob::redraw ( )

Make any handles in the viewer redraw, such as to show highlighting or previews, without the overhead or setting modified flags that changed() does.

const OutputContext & Knob::uiContext ( ) const

Return the "user interface context" from the node this knob belongs to. This is best thought of as "what frame/view the user thinks the Node is at". In reality, a node may produce several ops at different frames/views/proxy settings, one of these settings is returned by this.

const Format & Knob::input_format ( ) const

Same as Op::input_format(). A store() method can use this to scale uv coordinates to pixels or to take into account pixel aspect when storing width/height pairs.

void Knob::store ( StoreType  type,
void *  p,
Hash hash,
const OutputContext context 
)
virtual

Write over the passed location (which is in an Op) with the new data, and append that data to the Hash somehow. This is how data is stored into the pointed-to locations referred to by the knobs() function.

The context is used to figure out the current value from an animated knob, and to scale the stored values to the current proxy resolution. The hash should depend on these values.

If there is any problem storing the value you should call error() with a message to show the user. You should still put a legal value there and return the correct hash.

The base class does nothing.

Referenced by DD::Image::RenderScene::build_handles().

void Knob::append ( Hash hash,
const OutputContext context 
)
virtual

Append a representation of the current value() at the context to the hash. Nuke will use this to calculate the hash of any knob that does not have a pointer for the store() function but also does not have the NO_RERENDER flag on.

If the context is null, then you should instead append the entire animation of the knob to the hash. This is used to identify if any frame in a clip has changed.

The base class does nothing.

Referenced by DD::Image::LookupCurves::append(), and DD::Image::ParticleOp::appendSimulationCurve().

int Knob::get_key_list ( std::set< int > &  keylist) const
virtual

Turn on a flag in the bl array for each frame number between first and last that contains a key frame, and return the total number of keyframes. This is used to update the tick mark display in the Viewer frame slider. The base class returns zero.

virtual bool DD::Image::Knob::keyframesDisplayed ( ) const
inlinevirtual

Whether the viewer should display the tickmarks for me at the moment subclasses can override this to display tickmarks for invisible knobs

void Knob::error ( const char *  lpFormat,
  ... 
)
static

Use these to report once-off warning or error messages produced by a knob. They'll only be displayed as message boxes, and won't be stored. The versions that take a knob parameter use parameters from that knob they're called on, such as the pop-up scheme from any associated op.

bool Knob::from_script ( const char *  v)
virtual

Parse a string read from a saved script. The result should be a knob that is in exactly the same state as it was when to_script() was called to produce the string.

The return value is whether or not the value changed. If it did this must also call changed(). Note it should do this even if an error() is produced.

If any errors are encountered you should call error() to print a message.

Nuke provides a helper class Knob::String_List to split nested lists of words at spaces (this actually uses tcl to do the work), and the to_double() and to_bool() methods to turn words into values.

The default version produces an error. You don't need to implement this as long as not_default() is always false.

Reimplemented in DD::Image::ShapeKnob.

Referenced by DD::Image::LUTInfo::updateColorspaceDefaultValue().

bool Knob::to_double ( const char *  expr,
double &  result 
)

from_script() can call this to convert a word into a double. This will run the Nuke expression evaluator so that math expressions typed in by the user will be handled. If there is any problem a message is printed with error() and false is returned. If true is returned then the second argument is set to the resulting double value.

If you wish to write doubles in to_script(), using << works acceptably.

bool Knob::to_int ( const char *  expr,
int &  result 
)

from_script() can call this to convert a word into an integer value. The argument can be any legal expression. If it is not an integer then int(floor(x)) is returned.

bool Knob::to_bool ( const char *  expr,
bool &  result 
)

from_script() can call this to convert a word into a boolean value. The argument can be any legal expression that evaluates to 0, non-zero, or the words "false" or "true".

const char * Knob::get_text ( const OutputContext = nullptr) const
virtual

Return the null-terminated text that to_script(o, context, false) would write to the stream, or return null to indicate that this is not implemented.

The main purpose of this function is so a caller can avoid the overhead of creating a stringstream and extracting the result from there if they just want to copy the to_script value somewhere.

A caller can assume this is implemented for String_knob(). It is also implemented for Enumeration_knob and Bool_knob and most others that use keywords for their value, if a context is given or the knob is not animated.

The returned value is temporary and is only good until the next time this or any other knob is changed. However you are allowed to pass it once to a from_script() method on this or any knob.

The base class returns null. Notice that this means the base class to_script() always writes an empty string.

Referenced by DD::Image::ReadGeo::_validate(), DD::Image::WriteGeo::set_file_type_from_filename(), DD::Image::Write::set_file_type_from_filename(), and to_script().

void Knob::to_script ( std::ostream &  o,
const OutputContext context,
bool  quote 
) const
virtual

Write the text that describes the state of the knob to a stream. The resulting text must be able to be passed to from_script() to restore the current value.

If context is null, then you should write a description of all the animation of the knob. If context is not null, you should write the a description of the value that is stored for the given context (this string, if passed to from_script(), would then produce a non-animated value for the knob).

For speed this writes directly to the output file, so you must do the quoting if necessary. quote indicates that you should modify the output with the necessary quoting characters and delimiters so that the text results in exactly one word in a space-separated tcl list (generally this means you should add curly braces around it). If quote is false then you should output the text in the form it would be after it is extracted from the list.

The helper class Knob::cstring will correctly quote a string or null so that it is returned unchanged to from_script() or so it can be put into a space-separated Knob::Script_List.

The default version prints the result of get_text(), using Knob::cstring if necessary to quote it.

Reimplemented in DD::Image::ShapeKnob.

References get_text().

void Knob::to_script_prefix ( std::ostream &  o) const
virtual

Write commands that must be executed before the to_script() value can be parsed. This is used to write commands to declare Layers and Formats and other objects that are shared by knobs. Be sure to put a newline after the command. The default version writes nothing.

void Knob::to_script_userknob ( std::ostream &  o) const
virtual

Write the arguments to an addUserKnob command that will create this knob. Nuke will already have written the ClassID() and the name() (the way these are written may change in future versions). This should write keyword+value pairs separated by spaces with a leading space, and use cstring to quote values.

The base class writes " l \a label t \a tooltip ". label is not written if it is the same as name(). tooltip is not written if it is blank.

References DISABLED, HIDDEN, INVISIBLE, and STARTLINE.

bool Knob::not_default ( ) const
virtual

Return true if the knob is not at it's default value. This is used to avoid writing knobs which are set to the default to saved scripts. The base class returns false always.

static Indent* DD::Image::Knob::indent ( )
inlinestatic

DD::Image::Knob::Indent* DD::Image::Knob::indent() Writes the current indentation to the output stream. You use it by doing "o << indent()". This is used by Knob::to_script() to indent lines of text to match the surrounding braces. If you want more indentation, just print spaces after the indent, or feel free to mess with the "Indent::amount" variable, as long as you restore the value after you are done.

Member Data Documentation

constexpr const FlagMask DD::Image::Knob::EXACT_MATCH_ONLY
static

invalid value, the knob will be put into an Error state.

Make Enumeration knobs use exact match when setting a value. If an attempt is made to set an



©2020 The Foundry Visionmongers, Ltd. All Rights Reserved.
www.thefoundry.co.uk