value (lx_value.hpp)

From The Foundry MODO SDK wiki
(Redirected from TextValueHints)
Jump to: navigation, search


Contents

Value Global Service

This COM interface provides some useful functions for dealing with values.

(1) SDK: LXu_VALUESERVICE, etc. defines
 #define LXu_VALUESERVICE        "DD2C3059-2CD0-4c7d-860C-CF353CFB2F92"
 #define LXa_VALUESERVICE        "valueservice"
 
 #define LXe_OK_INEXACT_MATCH    LXxGOODCODE (LXeSYS_VALUE, 1)
 #define LXe_OK_NO_CHOICES       LXxGOODCODE (LXeSYS_VALUE, 2)

As with all globals, the first method gets the ILxScriptQueryID interface for the system.

(2) SDK: ValueService::ScriptQuery
         LXxMETHOD(  LxResult,
 ScriptQuery) (
         LXtObjectID              self,
         void                   **ppvObj);

Text Value Hint Encoding and Decoding

This encodes a numeric value as a string. If the 'buf' pointer is null, then a rolling buffer will be allocated and returned. If the hint pointer is null then the value is written as a plain signed integer.

This will return LXe_OK_INEXACT_MATCH when an integer is provided that does not exactly map to one of the choices. This is only returned if there are choices. LXe_OK_NO_CHOICES is returned if there are no choices at all. In both cases, the raw integer is encoded into the string buffer. Both codes are "OK" codes, and do not signify an error, but rather provide hints about the content of the encoded string, and may help instruct an code path if you do need an exact match or were expecting choices.

(3) SDK: ValueService::TextHintEncode
         LXxMETHOD(  LxResult,
 TextHintEncode) (
         LXtObjectID              self,
         int                      value,
         const LXtTextValueHint  *hint,
         char                    *buf,
         unsigned                 len);

Safer version for C++.

(4) SDK: CLxUser_ValueService::sgs_GetString method
 class Tmp_Sgs {
     public:
         CLxLoc_ValueService     *vsrv;
         const LXtTextValueHint  *hint;
         int                      value;
 
         LxResult sgs_GetString (char *buf, unsigned int len)
         {
                 return vsrv->TextHintEncode (value, hint, buf, len);
         }
 };
 
         bool
 EncodeHint (
         int                      value,
         const LXtTextValueHint  *hint,
         std::string             &text)
 {
         Tmp_Sgs                          tmp;
         CLxSafeGetString<Tmp_Sgs>        sgs;
 
         tmp.vsrv  = this;
         tmp.value = value;
         tmp.hint  = hint;
         return sgs.GetStringBool (tmp, text);
 }

This method decodes a string using the hint array. If the string is a number it will be returned directly after being clamped to min or max limits. If nothing is recognized then the function end-of-list will be returned.

This will return LXe_NOTFOUND when the string does not exactly match any text hints and cannot be converted into an integer (i.e., it doesn't start with a number). LXe_OK_NO_CHOICES is returned when the string was sucessfully converted from a number into an integer and may have been constrained to any min/max hints present, but the hints contain no actual choices. This may occur in the case of a hints array that is used only for min/max or similar properties, and is not meant to have a list of choices.

(5) SDK: ValueService::TextHintDecode
         LXxMETHOD(  LxResult,
 TextHintDecode) (
         LXtObjectID              self,
         const char              *buf,
         const LXtTextValueHint  *hint,
         int                     *value);

Creating ILxValue Objects

This method creates a new value object of the given type.

(6) SDK: ValueService::CreateValue
         LXxMETHOD(  LxResult,
 CreateValue) (
         LXtObjectID              self,
         const char              *type,
         void                   **ppvObj);

(7) SDK: CLxUser_ValueService::NewValue method
         bool
 NewValue (
         CLxLocalizedObject      &value,
         const char              *type)
 {
         LXtObjectID              obj;
 
         if (LXx_FAIL (CreateValue (type, &obj)))
                 return false;
 
         return value.take (obj);
 }

This gets the intrinsic type for a given value type, as one of the LXi_TYPE_* choices.

(8) SDK: ValueService::ValueType
         LXxMETHOD(  LxResult,
 ValueType) (
         LXtObjectID              self,
         const char              *type,
         unsigned                *valType);

Empty value service Python user class.

(9) PY: empty Service.Value user class
 pass

Nexus 701 SP4

There are cases where it is useful to copy a text hints array. These methods can be used to do just that, and to free it when it is no longer needed. These functions will safely handle NULL arrays, and will simply fail.

(10) SDK: ValueService::TextHintDuplicate
         LXxMETHOD(  LxResult,
 TextHintDuplicate) (
         LXtObjectID               self,
         const LXtTextValueHint   *hint,
         LXtTextValueHint        **copy);

(11) SDK: ValueService::TextHintFreeDuplicate
         LXxMETHOD(  LxResult,
 TextHintFreeDuplicate) (
         LXtObjectID               self,
         LXtTextValueHint         *copy);

Nexus 801

Check a float for NaN or infinity. A zero return value is OK.

(12) SDK: ValueService::FloatType
         LXxMETHOD(  int,
 FloatType) (
         LXtObjectID              self,
         float                    val);

(13) SDK: LXiFLOATTYPE_NUMBER, etc. defines

Nexus 901

Returns the global Frames Per Second.

(14) SDK: ValueService::GetFPS
         LXxMETHOD(  double,
 GetFPS) (
         LXtObjectID              self);

Given a time and using the global Frames Per Second, returns an equivalent frame.

(15) SDK: ValueService::TimeToFrame
         LXxMETHOD(  double,
 TimeToFrame) (
         LXtObjectID              self,
         double                   time);

Given a frame and using the global Frames Per Second, returns an equivalent time.

(16) SDK: ValueService::FrameToTime
         LXxMETHOD(  double,
 FrameToTime) (
         LXtObjectID              self,
         double                   frame);

Given a time and a Frames Per Second, returns an equivalent frame.

(17) SDK: ValueService::TimeToFrameFPS
         LXxMETHOD(  double,
 TimeToFrameFPS) (
         LXtObjectID              self,
         double                   time,
         double                   fps);

Given a frame and a Frames Per Second, returns an equivalent time.

(18) SDK: ValueService::FrameToTimeFPS
         LXxMETHOD(  double,
 FrameToTimeFPS) (
         LXtObjectID              self,
         double                   frame,
         double                   fps);

Integer Hints

Internal numeric codes are sometimes stored in files: data files, config files, and even macros. Since these numeric codes are subject to change as algorithms and systems get updated, we provide a system of hints to use when storing these values to files so that we can cope with changes when reading old ones. Right now the system is simple, but it can be expanded as required to cope with more sophisticated conversions.

The hints come in the form of a null-terminated array of hint structs, each one linking a numeric value to a text token. Tokens that start with "+" indicate bit masks, and other values represent choices. The tokens should not start with numeric or punctuation characters, and should not contain spaces.

(19) SDK: LXtTextValueHint struct
 int                      value;
 const char              *text;

The hints allow encoding choices, bitmasks, or combinations of the two. This example takes the value to be composed of individually meaningful bits at 9, 10 and 11. The remaining bits in the number are taken in aggregate as a choice. The value 0x502 would be encoded as "two+xz", and the string "one+jy" would be decoded as 0x201, ignoring the superfluous "j". If there is an error, then -1 (the NULL entry) will be returned.

(20) Hint Example: Text Encoding
 static LXtTextValueHint  hint[] = {
         0,      "zero",
         1,      "one",
         2,      "two",
         3,      "three",
         0x100,  "+x",
         0x200,  "+y",
         0x400,  "+z",
         -1,     NULL
 };

Range Hints

Hints also support min and max for numbers that are not just choices. Either can be present and will be enforced when values are encoded or decoded from strings. The follwing hint example would limit an integer value to a range of zero to twelve.

(21) Hint Example: Integer min/max
 static LXtTextValueHint  hint[] = {
         0,      "&min",
         12,     "&max",
         -1,     NULL
 };

Floating point values can also support range limits. These can be specified using the same integer format above, in which case the value is clamped into an integer range. Non-integral limits can also be specified using a "%" format, in which case the actual value is divided by 10000. This example would limit the value to a max of 3.25 and a min of -1.

(22) Hint Example: Float min/max
 static LXtTextValueHint  hint[] = {
         -1,     "&min",
          32500, "%max",
          0,      NULL
 };

Angles are a special case. Min/max can be defined in radians using the hints above, but due to the impercision of %min/%max, you can't accurately hit angles like 45 degrees. To alleviate this, text hints can be stored as degrees instead. In this example, the minimum is set to -45 degrees and the maximum to set to 45 degrees

(23) Hint Example: Angle min/max
 static LXtTextValueHint  hint[] = {
         -450000,        "%minDegrees",
          450000,        "%maxDegrees",
          0,              NULL
 };

Choice & Type Hints

Text hints can implicitly define choices which suggest a certain type of value. This example shows three possible choices of type "choir-size", with usernames looked up through the CommandHelp ArgumentType config entries.

(24) Hint Example: Choice with Type
 static LXtTextValueHint  hint[] = {
         2,      "duet",
         4,      "quartet",
         8,      "octet",
         0,      "=choir-size"
         -1,     NULL
 };

If two adjacent hints have the same value but different strings, only one the first one is considered a valid choice and the duplicate is skipped. This is useful if the hint needed to be renamed and the new version should be used going forward, but the old hint

Note that the two hints with the same value must be adjacent for this to work -- inserting another value between them will result in both choices being displayed in a popup, although only the first one will ever be considered chosen by the user.

(25) Hint Example: Renamed/Duplicate Hint
 static LXtTextValueHint  hint[] = {
         1,      "newName",
         1,      "oldName",
         2,      "string",
         -1,     NULL
 };

Other Hints

Text hints can also support a file format type. This is used when examining the type of a "filepath" exo-type. The prefix is '@', but there can be an optional '>' to indicate a file that will only be written, and an optional "[]" to indicate that the filename is a pattern. This is all used when resolving links to external assets, remapping patterns to patterns and skipping output paths.

(26) Hint Example: File Format
 static LXtTextValueHint  imageHint[] = {
         0,      "@image",
         0,      NULL
 };
 static LXtTextValueHint  imageWriteOnlyHint[] = {
         0,      "@>image",
         0,      NULL
 };
 static LXtTextValueHint  imageSequenceHint[] = {
         0,      "@[]image",
         0,      NULL
 };

It is also possible to encode a username in a text hint. This is done through the '#' prefix. It is primarily used to encude usernames for User Channels, and can include a message table lookup. This functionality is otherwise rarely used.

(27) Hint Example: File Format
 static LXtTextValueHint  usernameHint[] = {
         0,      "#@table@message@",
         0,      NULL
 };

Value Interface

Anything that has a state could potentially provide this basic value interface. Clone returns a new duplicate of the object, Copy reads the value of one into the value of the other, and Compare returns a ranking of two values along some metric. Type is the intrinsic type ala attributes.

(28) SDK: Value::Clone, etc.
         LXxMETHOD( LxResult,
 Clone) (
         LXtObjectID              self,
         void                   **ppvObj);
 
         LXxMETHOD( LxResult,
 Copy) (
         LXtObjectID              self,
         LXtObjectID              from);
 
         LXxMETHOD( LxResult,
 Compare) (
         LXtObjectID              self,
         LXtObjectID              other,
         int                     *diff);
 
         LXxMETHOD( unsigned int,
 Type) (
         LXtObjectID              self);

(29) SDK: CLxUser_Value::Compare method
         int
 Compare (
         ILxUnknownID             other)
 {
         int                      diff;
 
         if (LXx_FAIL (CLxLoc_Value::Compare (other, &diff)))
                 return -1;
 
         return diff;
 }

The actual value of the value can be read and optionally set several different ways.

(30) SDK: Value::GetInt, etc.
         LXxMETHOD(  LxResult,
 GetInt) (
         LXtObjectID              self,
         int                     *val);
 
         LXxMETHOD(  LxResult,
 SetInt) (
         LXtObjectID              self,
         int                      val);
 
         LXxMETHOD(  LxResult,
 GetFlt) (
         LXtObjectID              self,
         double                  *val);
 
         LXxMETHOD(  LxResult,
 SetFlt) (
         LXtObjectID              self,
         double                   val);
 
         LXxMETHOD(  LxResult,
 GetString) (
         LXtObjectID              self,
         char                    *buf,
         unsigned                 len);
 
         LXxMETHOD(  LxResult,
 SetString) (
         LXtObjectID              self,
         const char              *val);

(31) SDK: CLxUser_Value::sgs_GetString method
         LxResult
 sgs_GetString (char *buf, unsigned len)
 {
         return GetString (buf, len);
 }
 
         bool
 String (
         std::string             &text)
 {
         CLxSafeGetString<CLxUser_Value>  sgs;
 
         return sgs.GetStringBool (*this, text);
 }

For setting at least we can infer the type from the argument.

(32) SDK: CLxUser_Value::Set method
         void
 Set (
         int                      value)
 {
         SetInt (value);
 }
 
         void
 Set (
         double                   value)
 {
         SetFlt (value);
 }
 
         void
 Set (
         const char              *value)
 {
         SetString (value);
 }

The Python user class add Get() and Set() methods that try to hide type conversions.

(33) PY: Value.Get method
 def Get(self):
     tp = self.Type()
     if tp == lx.symbol.i_TYPE_INTEGER:
         return self.GetInt()
     if tp == lx.symbol.i_TYPE_FLOAT:
         return self.GetFlt()
     if tp == lx.symbol.i_TYPE_STRING:
         return self.GetString()
 
     raise TypeError("can't get object values")
 
 def __str__(self):
     return str(self.Get())
 
 def Set(self, value):
     tp = self.Type()
     if tp == lx.symbol.i_TYPE_INTEGER:
         self.SetInt(int(value))
     elif tp == lx.symbol.i_TYPE_FLOAT:
         self.SetFlt(float(value))
     elif tp == lx.symbol.i_TYPE_STRING:
         self.SetString(str(value))
     else:
         raise TypeError("can't set object values");

A somewhat more raw method can give generic access to the intrinsic types. For integer types this is a pointer to int; for float types it's a pointer to double; for string types it's a pointer to char. Other value types may return null.

(34) SDK: Value::Intrinsic
         LXxMETHOD(  void *,
 Intrinsic) (
         LXtObjectID              self);

(35) SDK: LXu_VALUE, etc. defines
 #define LXu_VALUE       "62E1DBE9-2FFE-4B5C-B286-E54E79415303"
 #define LXa_VALUE       "value"

This interface allows simple string equivalence for COM objects. The Encode() function writes the value of the object to a string with the given number of available bytes (including null termination), and the Decode() parses a string setting the value of the object to match.

(36) SDK: StringConversion::Encode, etc.
         LXxMETHOD( LxResult,
 Encode) (
         LXtObjectID              self,
         char                    *buf,
         unsigned                 len);
 
         LXxMETHOD( LxResult,
 Decode) (
         LXtObjectID              self,
         const char              *buf);

There are actually two variants of this interfaces that an object can provide. The "raw" version writes values in a native format, most suitable for scripting of file I/O. The "nice" version writes the value in a format suitable for human reading, and parses a more extensive range of possible human input.

(37) SDK: LXu_STRINGCONVERSION, etc. defines
 #define LXu_STRINGCONVERSION            "5CB3EEDB-E4E0-499E-B0BA-A7FB51BABE3C" 
 #define LXu_STRINGCONVERSIONNICE        "5407328B-DE99-4F15-866F-F6E214FFA412"

Nice is the same as raw. Too bad there's no reasonable way to use the same interface with different GUIDs.

(38) SDK: StringConversionNice::Encode, etc.
         LXxMETHOD( LxResult,
 Encode) (
         LXtObjectID              self,
         char                    *buf,
         unsigned                 len);
 
         LXxMETHOD( LxResult,
 Decode) (
         LXtObjectID              self,
         const char              *buf);

Empty StringConversion Python user class.

(39) PY: empty StringConversion user class
 pass

Empty StringConversionNice Python user class.

(40) PY: empty StringConversionNice user class
 pass

Numeric or quasi-numeric values can be modified through the value-math interface.

(41) SDK: ValueMath::Step, etc.
         LXxMETHOD( LxResult,
 Step) (
         LXtObjectID              self,
         int                      direction);
 
         LXxMETHOD( int,
 Detent) (
         LXtObjectID              self);
 
         LXxMETHOD( LxResult,
 Add) (
         LXtObjectID              self,
         double                   delta);
 
         LXxMETHOD( LxResult,
 Multiply) (
         LXtObjectID              self,
         double                   factor);
 
         LXxMETHOD( LxResult,
 Blend) (
         LXtObjectID              self,
         LXtObjectID              other,
         double                   blend);

(42) SDK: LXiDETENT_NONE, etc. defines
 #define LXiDETENT_NONE   0
 #define LXiDETENT_MINOR  1
 #define LXiDETENT_MAJOR  2

(43) SDK: LXu_VALUEMATH define
 #define LXu_VALUEMATH   "752B4D2E-6F13-4B2C-B0B3-0BA8CA6B0692"

(44) SDK: empty ValueMath User Class

Empty ValueMath Python user class.

(45) PY: empty ValueMath user class
 pass

Some values are references to other object types. This interface allows access to the referenced object, as well as a query for knowing if a reference is set.

(46) SDK: ValueReference::IsSet, etc.
         LXxMETHOD( LxResult,
 IsSet) (
         LXtObjectID              self);
 
         LXxMETHOD( LxResult,
 GetObject) (
         LXtObjectID              self,
         void                   **ppvObj);
 
         LXxMETHOD( LxResult,
 SetObject) (
         LXtObjectID              self,
         LXtObjectID              obj);

(47) SDK: CLxUser_ValueReference::Get method
         bool
 Get (
         CLxLocalizedObject      &loc)
 {
         return GetObject (loc);
 }
 
         bool
 TakeObject (
         ILxUnknownID             obj)
 {
         if (LXx_FAIL (SetObject (obj)))
                 return false;
 
         lx::UnkRelease (obj);
         return true;
 }

(48) SDK: LXu_VALUEREFERENCE define
 #define LXu_VALUEREFERENCE      "0567BC88-F782-426E-98C5-8302FD52D9E4"

Empty ValueReference Python user class.

(49) PY: empty ValueReference user class
 pass

Attributes

The ILxAttributes interface provides a broadly useful way for objects to present themselves as sets of named values. The object can be queried to find out what attributes are present and what type they are.

Interface

The attributes interface typically does not stand on its own. Instead it's one of an object's polymorphic features, which packages the internal state of the object into a common format.

(50) SDK: LXu_ATTRIBUTES define
 #define LXu_ATTRIBUTES  "117957D0-5A13-11D7-A18C-000A95765C9E"

Return the number of attributes.

(51) SDK: Attributes::Count
         LXxMETHOD(  unsigned int,
 Count) (
         LXtObjectID              self);

Return the name of the attribute at given index, or LXe_OUTOFBOUNDS for bad index choices.

(52) SDK: Attributes::Name
         LXxMETHOD(  LxResult,
 Name) (
         LXtObjectID              self,
         unsigned int             index,
         const char             **name);

Return the index given the name, or LXe_NOTFOUND.

(53) SDK: Attributes::Lookup
         LXxMETHOD(  LxResult,
 Lookup) (
         LXtObjectID              self,
         const char              *name,
         unsigned int            *index);

Return the basic attribute type which indicates what intrinsic data type is used to store it. That is given by one of the types below.

(54) SDK: Attributes::Type
         LXxMETHOD(  LxResult,
 Type) (
         LXtObjectID              self,
         unsigned int             index,
         unsigned int            *type);

The intrinsic type returned by Type() is one of the following codes:

LXi_TYPE_INTEGER, LXi_TYPE_FLOAT The attribute is number, either an integer (int) of a floating point number (double). Booleans and axes are considered integers for this purpose.
LXi_TYPE_STRING The attribute is a string, and can be read or set as a null-terminated array of bytes.
LXi_TYPE_OBJECT The attribute is a complex object, and is accessed as an ILxValue interface.
(55) SDK: LXi_TYPE_OBJECT, etc. defines
 #define LXi_TYPE_OBJECT         0
 #define LXi_TYPE_INTEGER        1
 #define LXi_TYPE_FLOAT          2
 #define LXi_TYPE_STRING         3

Return the attribute type name. This is the name of any of the available value types.

(56) SDK: Attributes::TypeName
         LXxMETHOD(  LxResult,
 TypeName) (
         LXtObjectID              self,
         unsigned int             index,
         const char             **tname);

The type name can be one of the nexus intrinsic types here, or it can be a value type implemented by a plug-in server of the "value" class.

(57) SDK: LXsTYPE_INTEGER, etc. defines
 #define LXsTYPE_INTEGER         "integer"
 #define LXsTYPE_FLOAT           "float"
 #define LXsTYPE_DISTANCE        "distance"
 #define LXsTYPE_PERCENT         "percent"
 #define LXsTYPE_ANGLE           "angle"
 #define LXsTYPE_FLOAT3          "float3"
 #define LXsTYPE_DISTANCE3       "distance3"
 #define LXsTYPE_PERCENT3        "percent3"
 #define LXsTYPE_ANGLE3          "angle3"
 #define LXsTYPE_TIME            "time"
 #define LXsTYPE_LIGHT           "light"
 #define LXsTYPE_STRING          "string"
 #define LXsTYPE_FILEPATH        "filepath"
 #define LXsTYPE_UVCOORD         "uvcoord"
 #define LXsTYPE_BOOLEAN         "boolean"
 #define LXsTYPE_AXIS            "axis"
 #define LXsTYPE_MEMORY          "memory"
 #define LXsTYPE_PIXEL           "pixel"
 #define LXsTYPE_FPIXEL          "fpixel"
 #define LXsTYPE_COLOR           "color"
 #define LXsTYPE_COLOR1          "color1"
 #define LXsTYPE_MATRIX3         "matrix3"
 #define LXsTYPE_MATRIX4         "matrix4"
 #define LXsTYPE_DATETIME        "datetime"
 #define LXsTYPE_TOD             "timeofday"
 #define LXsTYPE_DATE            "date"
 #define LXsTYPE_OBJREF          "objref"
 #define LXsTYPE_VERTMAPNAME     "vertmapname"
 #define LXsTYPE_FORCE           "force"
 #define LXsTYPE_ACCELERATION    "acceleration"
 #define LXsTYPE_SPEED           "speed"
 #define LXsTYPE_MASS            "mass"
 #define LXsTYPE_QUATERNION      "quaternion"
 #define LXsTYPE_FOCALLENGTH     "focallength"
 #define LXsTYPE_NONE            "none"

Return a read-only array of text value hints for the given attribute. This may return null if there are none or if there is any other failure. Note that this array may be volatile and should not be stored.

(58) SDK: Attributes::Hints
         LXxMETHOD(  const LXtTextValueHint *,
 Hints) (
         LXtObjectID              self,
         unsigned int             index);

Once the list of attributes and their types has been determined, the following methods can be used to read and write their values given their index (from 0 to Count-1).

Value This gets the ILxValue associated with the attribute. The interface has been acquired for the calling client and needs to be released when done. If 'writeOK' is true the object will be writable, and changes to the value should be done using the appropriate object interface.
GetInt, SetInt These get and set the value of integer attributes.
GetFlt, SetFlt These get and set the value of floating-point attributes.
GetString, SetString These get and set the value of string attributes. Note that GetString() returns a "raw" string when used with non-string datatypes. "Nice" strings can be obtained by passing the result of Value() through an appropriate StringConversion.
(59) SDK: Attributes::Value, etc.
         LXxMETHOD(  LxResult,
 Value) (
         LXtObjectID              self,
         unsigned int             index,
         void                   **ppvObj,
         int                      writeOK);
 
         LXxMETHOD(  LxResult,
 GetInt) (
         LXtObjectID              self,
         unsigned int             index,
         int                     *val);
 
         LXxMETHOD(  LxResult,
 SetInt) (
         LXtObjectID              self,
         unsigned int             index,
         int                      val);
 
         LXxMETHOD(  LxResult,
 GetFlt) (
         LXtObjectID              self,
         unsigned int             index,
         double                  *val);
 
         LXxMETHOD(  LxResult,
 SetFlt) (
         LXtObjectID              self,
         unsigned int             index,
         double                   val);
 
         LXxMETHOD(  LxResult,
 GetString) (
         LXtObjectID              self,
         unsigned int             index,
         char                    *buf,
         unsigned                 len);
 
         LXxMETHOD(  LxResult,
 SetString) (
         LXtObjectID              self,
         unsigned int             index,
         const char              *val);

Attributes User Class

FindIndex() is an analogue of Lookup(), but returns the attribute index or -1 for none.

(60) SDK: CLxUser_Attributes::FindIndex method
         int
 FindIndex (
         const std::string       &name)
 {
         unsigned                 index;
 
         if (LXx_OK (Lookup (name.c_str (), &index)))
                 return index;
         else
                 return -1;
 }
 
         int
 FindIndex (
         const char              *name)
 {
         unsigned                 index;
 
         if (LXx_OK (Lookup (name, &index)))
                 return index;
         else
                 return -1;
 }
 
         int
 Type (
         unsigned                 index)
 {
         unsigned                 type;
 
         if (LXx_OK (CLxLoc_Attributes::Type (index, &type))) {
                 return type;
         }
         else {
                 return -1;
         }
 }
 
         bool
 Name (
         unsigned                 index,
         std::string             &name)
 {
         const char      *nameChars;
         bool             foundName;
 
         foundName = LXx_OK (CLxLoc_Attributes::Name (index, &nameChars));
         if (foundName) {
                 name = std::string (nameChars);
                 foundName = true;
         }
         else {
                 name = "";
         }
 
         return foundName;
 }

In Python we can get all the attribute names in a list.

(61) PY: Attributes.NameList method
 def NameList(self):
     return [ self.Name(i) for i in range(self.Count()) ]

There are a few alternate methods defined in the C++ user class for handling some of the type conversions.

(62) SDK: CLxUser_Attributes::Set method
         bool
 Set (
         unsigned                 index,
         bool                     val)
 {
         return LXx_OK (SetInt (index, val ? 1 : 0));
 }
 
         bool
 Set (
         unsigned                 index,
         int                      val)
 {
         return LXx_OK (SetInt (index, val));
 }
 
         bool
 Set (
         unsigned                 index,
         double                   val)
 {
         return LXx_OK (SetFlt (index, val));
 }
 
         bool
 Set (
         unsigned                 index,
         const char              *val)
 {
         return LXx_OK (SetString (index, val));
 }

Simpler get methods return the value without error checking.

(63) SDK: CLxUser_Attributes::Bool method
         bool
 Bool (
         unsigned                 index,
         bool                     preset = false)
 {
         int                      val;
 
         if (LXx_FAIL (GetInt (index, &val)))
                 return preset;
 
         return val ? true : false;
 }
 
         int
 Int (
         unsigned                 index,
         int                      preset = 0)
 {
         int                      val;
 
         if (LXx_FAIL (GetInt (index, &val)))
                 return preset;
 
         return val;
 }
 
         double
 Float (
         unsigned                 index,
         double                   preset = 0.0)
 {
         double                   val;
 
         if (LXx_FAIL (GetFlt (index, &val)))
                 return preset;
 
         return val;
 }

Strings can be set and read using the STL string class.

(64) SDK: CLxUser_Attributes::Set method
         bool
 Set (
         unsigned                 index,
         const std::string       &text)
 {
         return LXx_OK (SetString (index, text.c_str ()));
 }
 
 class Tmp_Sgs {
     public:
         CLxLoc_Attributes       *attr;
         unsigned                 index;
 
         LxResult sgs_GetString (char *buf, unsigned int len)
         {
                 return attr->GetString (index, buf, len);
         }
 };
 
         bool
 String (
         unsigned                 index,
         std::string             &text)
 {
         Tmp_Sgs                          tmp;
         CLxSafeGetString<Tmp_Sgs>        sgs;
 
         tmp.attr  = this;
         tmp.index = index;
         return sgs.GetStringBool (tmp, text);
 }

Object values can be read into any interface localization, for read-only access or for read-write.

(65) SDK: CLxUser_Attributes::ObjectRO method
         bool
 ObjectRO (
         unsigned                 index,
         CLxLocalizedObject      &loc)
 {
         LXtObjectID              obj;
 
         if (LXx_FAIL (Value (index, &obj, 0)))
                 return false;
 
         return loc.take (obj);
 }
 
         bool
 ObjectRW (
         unsigned                 index,
         CLxLocalizedObject      &loc)
 {
         LXtObjectID              obj;
 
         if (LXx_FAIL (Value (index, &obj, 1)))
                 return false;
 
         return loc.take (obj);
 }

If the object is of the OBJREF type, then it's actually a container for another object. These methods allow the content to be accessed directly.

(66) SDK: CLxUser_Attributes::GetRef method
         LxResult
 GetRef (
         unsigned                 index,
         void                   **ppvObj)
 {
         CLxLoc_ValueReference    ref;
         LxResult                 rc;
 
         rc = Value (index, ref, 0);
         if (LXx_FAIL (rc))
                 return rc;
 
         return ref.GetObject (ppvObj);
 }
 
         bool
 GetRef (
         unsigned                 index,
         CLxLocalizedObject      &loc)
 {
         LXtObjectID              obj;
 
         return LXx_OK (GetRef (index, &obj)) && loc.take (obj);
 }
 
         LxResult
 SetRef (
         unsigned                 index,
         ILxUnknownID             obj)
 {
         CLxLoc_ValueReference    ref;
         LxResult                 rc;
 
         rc = Value (index, ref, 1);
         if (LXx_FAIL (rc))
                 return rc;
 
         return ref.SetObject (obj);
 }
 
         bool
 TakeRef (
         unsigned                 index,
         ILxUnknownID             obj)
 {
         if (LXx_FAIL (SetRef (index, obj)))
                 return false;
 
         lx::UnkRelease (obj);
         return true;
 }

The Python user class adds Get() and Set() methods that infer the type of the attribute. The index can also be given as the name of the attribute.

(67) PY: Attributes.Get method
 def Get(self, index):
     if isinstance(index, str):
         index = self.Lookup(index)
 
     tp = self.Type(index)
     if tp == lx.symbol.i_TYPE_INTEGER:
         return self.GetInt(index)
     if tp == lx.symbol.i_TYPE_FLOAT:
         return self.GetFlt(index)
     if tp == lx.symbol.i_TYPE_STRING:
         return self.GetString(index)
 
     return self.Value(index, 0)
 
 def Set(self, index, value):
     if isinstance(index, str):
         index = self.Lookup(index)
 
     tp = self.Type(index)
     if tp == lx.symbol.i_TYPE_INTEGER:
         self.SetInt(index, value)
     elif tp == lx.symbol.i_TYPE_FLOAT:
         self.SetFlt(index, value)
     elif tp == lx.symbol.i_TYPE_STRING:
         self.SetString(index, value)
     else:
         raise TypeError("can't set object type values")

We also allow 'val = attr[index]' and 'attr[index] = val'.

(68) PY: Attributes.__getitem__ method
 def __getitem__(self, index):
     return self.Get(index)
 
 def __setitem__(self, index, value):
     self.Set(index, value)

Message

Error messages can be managed through the use of the ILxMessage interface. These objects contain the result code, a message, and values for each of the arguments in the message string.

(69) SDK: LXu_MESSAGE, etc. defines
 #define LXu_MESSAGE             "DDDBF46A-0865-4AB7-9962-72E7B477FD22"
 #define LXa_MESSAGE             "message"

Gross Features

This returns the code, which can be an error, info (success) or warning LxResult.

(70) SDK: Message::Code
         LXxMETHOD(  LxResult,
 Code) (
         LXtObjectID               self );

This sets that code.

(71) SDK: Message::SetCode
         LXxMETHOD(  LxResult,
 SetCode) (
         LXtObjectID               self,
         LxResult                  code );

Composing Messages Strings

To set the message, the client provides a message table name and either a message name or numeric ID representing the message. If the text name is NULL, the ID is converted to text and used instead. Setting a message clears any existing message.

(72) SDK: Message::SetMessage
         LXxMETHOD(  LxResult,
 SetMessage) (
         LXtObjectID               self,
         const char               *table,
         const char               *name,
         unsigned                  id);

Messages in message tables may have arguments marked in the form of %1, %2, etc. One of the SetArgument...() functions should be called for each to provide a meaningful dynamic value to the user.

Note that these argument indices match the numbers in the message string itself; if you want to set %1, use argument index 1. Technically, you can have a %0 and use arg index 0, but that is discouraged.

(73) SDK: Message::SetArgumentInt
         LXxMETHOD(  LxResult,
 SetArgumentInt) (
         LXtObjectID               self,
         unsigned                  arg,
         int                       value);

(74) SDK: Message::SetArgumentFloat
         LXxMETHOD(  LxResult,
 SetArgumentFloat) (
         LXtObjectID               self,
         unsigned                  arg,
         double                    value);

(75) SDK: Message::SetArgumentString
         LXxMETHOD(  LxResult,
 SetArgumentString) (
         LXtObjectID               self,
         unsigned                  arg,
         const char               *string);

(76) SDK: Message::SetArgumentObject
         LXxMETHOD(  LxResult,
 SetArgumentObject) (
         LXtObjectID               self,
         unsigned                  arg,
         LXtObjectID               object);

Other Methods

This resets a message object to LXe_OK and clears the string to NULL.

(77) SDK: Message::Reset
         LXxMETHOD(  LxResult,
 Reset) (
         LXtObjectID               self);

Some clients need access to the table and message name.

(78) SDK: Message::Table
         LXxMETHOD(  LxResult,
 Table) (
         LXtObjectID               self,
         const char              **table);

(79) SDK: Message::Name
         LXxMETHOD(  LxResult,
 Name) (
         LXtObjectID               self,
         const char              **name);

Composing Messages Strings

To set the message from a result code, the client provides the numeric ID representing the message. Setting a message clears any existing message. This also sets the result code itself by treating the numeric ID as an LxResult.

(80) SDK: Message::SetMessageResult
         LXxMETHOD(  LxResult,
 SetMessageResult) (
         LXtObjectID               self,
         unsigned                  id);

C++ User Class

The user class has alternate methods for setting the argument based on different types.

(81) SDK: CLxUser_Message::SetArg method
         bool
 SetArg (
         unsigned                 arg,
         int                      val)
 {
         return LXx_OK (SetArgumentInt (arg, val));
 }
 
         bool
 SetArg (
         unsigned                 arg,
         double                   val)
 {
         return LXx_OK (SetArgumentFloat (arg, val));
 }
 
         bool
 SetArg (
         unsigned                 arg,
         const char              *val)
 {
         return LXx_OK (SetArgumentString (arg, val));
 }

The Python SetArg() method passes every value as a string using repr(). We also allow 'msg[1] = "Hello"'.

(82) PY: Message.SetArg method
 def SetArg(self, arg, value):
     self.SetArgumentString(arg, repr(value))
 
 def __setitem__(self, arg, value):
     self.SetArgumentString(arg, repr(value))

It also has some alternates for setting the message itself using either dictionary string or message ID. If you pass just a string it will use common message 99 which just displays argument 1. This is not recommended for commercial plug-ins, but it lets you use literal text for quick hacks.

(83) SDK: CLxUser_Message::SetMsg method
         bool
 SetMsg (
         const char              *table,
         unsigned                 id)
 {
         return LXx_OK (SetMessage (table, 0, id));
 }
 
         bool
 SetMsg (
         const char              *table,
         const char              *name)
 {
         return LXx_OK (SetMessage (table, name, 0));
 }
 
         bool
 SetMsg (
         const char              *string)
 {
         return SetMsg ("common", 99) && SetArg (1, string);
 }

Query

Querying values through scripting can be done based on an array interface and the script query interface.

Value Container

The ILxValueArray interface is a container for multiple values of the same type. There can be zero or more values of any given type in the container, and the object has methods for setting and getting individual values. Generally an empty container will be passed to a source which will fill in all the values, and then the container will be passed along to a destination which will read out the values.

(84) SDK: LXu_VALUEARRAY, etc. defines
 #define LXu_VALUEARRAY          "A964962F-9028-4CA3-9612-17D360DF92BA"
 #define LXa_VALUEARRAY          "valuearray"

These returns the type of the values stored in the container. Type is an LXi_TYPE_* identifier, while TypeName is the ExoType's actual name string.

(85) SDK: ValueArray::Type, etc.
         LXxMETHOD(  LxResult,
 Type) (
         LXtObjectID               self,
         unsigned int             *type );
 
         LXxMETHOD(  LxResult,
 TypeName) (
         LXtObjectID               self,
         const char              **name );

This returns the number of values currently in the container.

(86) SDK: ValueArray::Count
         LXxMETHOD(  unsigned int,
 Count) (
         LXtObjectID               self );

This adds an uninitialized value to the container, optionally returning it to the caller. This is useful if you just need a dummy value to fill a gap. Another common use is to the returned value object to decode a string.

(87) SDK: ValueArray::AddEmptyValue
         LXxMETHOD(  LxResult,
 AddEmptyValue) (
         LXtObjectID              self,
         void                   **ppvObj );

These add new values to the container. Note that the original value is still owned by the client.

Also note that these only work on matching datatypes -- notably, AddString() will only work if the value array is itself representing a string. If you want have a string decoded as a value to add to the array, use AddEmptyValue() to add an empty value object to the array, then call that object's SetString() method to decode the string into it.

(88) SDK: ValueArray::AddValue, etc.
         LXxMETHOD(  LxResult,
 AddValue) (
         LXtObjectID               self,
         LXtObjectID               value );
 
         LXxMETHOD(  LxResult,
 AddInt) (
         LXtObjectID               self,
         int                       value );
 
         LXxMETHOD(  LxResult,
 AddFloat) (
         LXtObjectID               self,
         double                    value );
 
         LXxMETHOD(  LxResult,
 AddString) (
         LXtObjectID               self,
         const char               *value );

These get values out of the container. Note that the ILxValueID provided from GetValue() must be released by the caller.

Also note that GetString() can be used on non-string datatypes, and will return a "raw" string. "Nice" strings can be obtained by passing the result of Value() through an appropriate StringConversion.

(89) SDK: ValueArray::GetValue, etc.
         LXxMETHOD(  LxResult,
 GetValue) (
         LXtObjectID               self,
         unsigned int              index,
         void                   **ppvObj );
 
         LXxMETHOD(  LxResult,
 GetInt) (
         LXtObjectID               self,
         unsigned int              index,
         int                      *value );
 
         LXxMETHOD(  LxResult,
 GetFloat) (
         LXtObjectID               self,
         unsigned int              index,
         double                   *value );
 
         LXxMETHOD(  LxResult,
 GetString) (
         LXtObjectID               self,
         unsigned int              index,
         char                     *buf,
         unsigned                  len );

This returns the index of the first unique value found that is different from the 0th index, or -1 if all the values are identical. This is useful for creating mixed argument lists for user interfaces.

(90) SDK: ValueArray::FirstUnique
         LXxMETHOD(  LxResult,
 FirstUnique) (
         LXtObjectID               self,
         unsigned int             *uniqueIndex );

This empties the container, freeing all values within.

(91) SDK: ValueArray::Reset
         LXxMETHOD(  LxResult,
 Reset) (
         LXtObjectID               self );

There are a few alternate methods in the user class for varying arg types.

(92) SDK: CLxUser_ValueArray::AddEmpty method
         bool
 AddEmpty (
         CLxLocalizedObject      &val)
 {
         LXtObjectID              obj;
 
         if (LXx_FAIL (AddEmptyValue (&obj)))
                 return false;
 
         return val.take (obj);
 }
 
         bool
 Add (
         CLxLoc_Value            &val)
 {
         return LXx_OK (AddValue (val));
 }
 
         bool
 Add (
         bool                     val)
 {
         return LXx_OK (AddInt (val ? 1 : 0));
 }
 
         bool
 Add (
         int                      val)
 {
         return LXx_OK (AddInt (val));
 }
 
         bool
 Add (
         double                   val)
 {
         return LXx_OK (AddFloat (val));
 }
 
         bool
 Add (
         const char              *val)
 {
         return LXx_OK (AddString (val));
 }

(93) SDK: CLxUser_ValueArray::sgs_GetString method
 class Tmp_Sgs {
     public:
         CLxLoc_ValueArray       *vary;
         unsigned                 index;
 
         LxResult sgs_GetString (char *buf, unsigned int len)
         {
                 return vary->GetString (index, buf, len);
         }
 };
 
         bool
 String (
         unsigned                 index,
         std::string             &text)
 {
         Tmp_Sgs                          tmp;
         CLxSafeGetString<Tmp_Sgs>        sgs;
 
         tmp.vary  = this;
         tmp.index = index;
         return sgs.GetStringBool (tmp, text);
 }

In Python we support 'x = array[i]', and 'array + x' for appending atomic value types.

(94) PY: ValueArray.__getitem__ method
 def __getitem__(self, index):
     tp = self.Type()
     if tp == lx.symbol.i_TYPE_INTEGER:
         return self.GetInt(index)
     if tp == lx.symbol.i_TYPE_FLOAT:
         return self.GetFloat(index)
     if tp == lx.symbol.i_TYPE_STRING:
         return self.GetString(index)
     else:
         return self.GetValue(index)
 
 def __add__(self, value):
     tp = self.Type()
     if tp == lx.symbol.i_TYPE_INTEGER:
         self.AddInt(value)
     elif tp == lx.symbol.i_TYPE_FLOAT:
         self.AddFloat(value)
     elif tp == lx.symbol.i_TYPE_STRING:
         self.AddString(value)
     else:
         self.AddValue(value)

We also support iteration to allow the "for" syntax.

(95) PY: ValueArray.__iter__ method
 def __iter__(self):
     for i in range(self.Count()):
         yield self[i]

ILxArray

There is also this simple read-only list construct. The elements are COM objects that must be queried for their interface by the caller. As usually, any returned objects must be released by the caller.

(96) SDK: LXu_ARRAY, etc. defines
 #define LXu_ARRAY               "d1e1ba61-700e-48ad-aada-6865148fcc40"
 #define LXa_ARRAY               "array"

(97) SDK: Array::Count, etc.
         LXxMETHOD(  unsigned int,
 Count) (
         LXtObjectID               self );
 
         LXxMETHOD(  LxResult,
 ByIndex) (
         LXtObjectID               self,
         unsigned int              index,
         void                    **ppvObj );

Script Query

The ILxScriptQuery interface allows scripts and other clients to easily and generically access values from the internal systems.

(98) SDK: LXu_SCRIPTQUERY, etc. defines
 #define LXu_SCRIPTQUERY         "0434F07E-AD4A-492f-AD43-3249BD16994D"
 #define LXa_SCRIPTQUERY         "scriptquery"

These error codes can be returned by the interface on error.

(99) SDK: LXe_QUERY_UNKNOWN_SERVICE, etc. defines

LXe_QUERY_UNKNOWN_SERVICE Unknown service, usually used by those looking up a script service by name.
LXe_QUERY_UNKNOWN_SERVICE Service exists, but does not have an ILxScriptQuery inteface, usually because the ScriptQuery() method of the service returned LXe_NOTIMPL.
LXe_QUERY_UNKNOWN_ATTRIBUTE The attribute being queried is not known by the service.
LXe_QUERY_MISMATCHED_TYPE The attribute expects a type that is different from the type in the ILxValueArray object.
LXe_QUERY_SELECT_FAILED Attempt to select an item failed, possibly because it doesn't exist, is of the wrong type of the attribute, or the attribute doesn't require a selection.
LXe_QUERY_NEED_SELECTION The attribute requires a selection to operation on.
LXe_QUERY_MISMATCHED_SELECTION Although something is selected, it doesn't match the attribute being queried.
LXe_QUERY_NOT_APPLICABLE_TO_SELECTED The attribute is not applicable to the current selection, such as when the selected item does not have the property being queried.
LXe_QUERY_ERROR General error querying the selection.

This selects what a query will obtain values for. The attribute is the class that we're querying, which might be "command.username" for the name of a command; only the first part is looked at for the class, so "command" is fine. which is the thing we're getting the data from. The which argument depends on the kind of attribute; for commands, it might be the name of the command to get information for.

(100) SDK: ScriptQuery::Select
         LXxMETHOD(  LxResult,
 Select) (
         LXtObjectID              self,
         const char              *attribute,
         const char              *which);

Once selected, we can query the selected item for it's values by providing an attribute and an ILxValueArray object. For a list of all possible attributes, use NULL or an empty string for the attribute string. Note that both NULL and the empty string "" must be supported, as it can be difficult to provide NULL from a script.

(101) SDK: ScriptQuery::Query
         LXxMETHOD(  LxResult,
 Query) (
         LXtObjectID              self,
         const char              *attribute,
         LXtObjectID              query);

The type (LXi_TYPE_*) of the attribute can be obtained with this method. The ILxValueArrayID passed to Query() must be of this type.

(102) SDK: ScriptQuery::Type
         LXxMETHOD(  LxResult,
 Type) (
         LXtObjectID              self,
         const char              *attribute,
         int                     *type);

The specific ExoType name can be read with this method.

(103) SDK: ScriptQuery::TypeName
         LXxMETHOD(  LxResult,
 TypeName) (
         LXtObjectID               self,
         const char               *attribute,
         const char              **type);

The script query C++ user class has a method that allows it to init from any global. This is done by *casting* to the ILxValueService interface, which we know is defined, and calling the ScriptQuery() method. Any well-formed global will have this as their first method, but there is some danger here in casting.

(104) SDK: CLxUser_ScriptQuery::fromGlobal method
         bool
 fromGlobal (
         LXtObjectID              obj)
 {
         ILxValueServiceID        srv = reinterpret_cast<ILxValueServiceID> (obj);
 
         if (LXx_OK (srv[0]->ScriptQuery (srv, &obj)))
                 return take (obj);
 
         clear ();
         return false;
 }

Empty ScriptQuery Python user class.

(105) PY: empty ScriptQuery user class
 pass

Tags

Many object types support tags, which are an opened-ended list of strings indexed by numeric IDs. Tags can be accessed using this interface.

(106) SDK: LXu_STRINGTAG define
 #define LXu_STRINGTAG           "C2004BC7-6A90-4BD3-BDF7-B375C790DB70"

The ID is an LXtID4, which can be generated with the LXxID4() macro. This method gets the tag string for an ID, or returns NOTFOUND if none.

(107) SDK: StringTag::Get
         LXxMETHOD( LxResult,
 Get) (
         LXtObjectID              self,
         LXtID4                   type,
         const char             **tag);

This sets the value of a tag, overwriting the one for the given ID. Passing null for the string pointer will clear the tag.

(108) SDK: StringTag::Set
         LXxMETHOD( LxResult,
 Set) (
         LXtObjectID              self,
         LXtID4                   type,
         const char              *tag);

This methods gets the total number of tags.

(109) SDK: StringTag::Count
         LXxMETHOD( LxResult,
 Count) (
         LXtObjectID              self,
         unsigned int            *count);

This method returns the type and value of a tag by index.

(110) SDK: StringTag::ByIndex
         LXxMETHOD( LxResult,
 ByIndex) (
         LXtObjectID              self,
         unsigned int             index,
         LXtID4                  *type,
         const char             **tag);

User class method gets the string from the tag, or null if not found.

(111) SDK: CLxUser_StringTag::Value method
         const char *
 Value (
         LXtID4                   type)
 {
         const char              *tag;
 
         if (LXx_OK (Get (type, &tag)))
                 return tag;
         else
                 return 0;
 }

User class method returns true if the tag matches the string.

(112) SDK: CLxUser_StringTag::Match method
         bool
 Match (
         LXtID4                   type,
         const char              *str)
 {
         const char              *tag;
 
         return LXx_OK (Get (type, &tag)) && (strcmp (str, tag) == 0);
 }

User class method returns true if the tag contains the string.

(113) SDK: CLxUser_StringTag::Contains method
         bool
 Contains (
         LXtID4                   type,
         const char              *str)
 {
         const char              *tag = NULL;
 
         if (str && LXx_OK (Get (type, &tag)) && tag)
         {
                 std::string              tagStr (tag);
 
                 return (tagStr.find (std::string (str)) != std::string::npos);
         }
 
         return false;
 }

Some very common tags are defined here.

(114) SDK: LXiTAG_COMMENT, etc. defines
 #define LXiTAG_COMMENT           LXxID4('C','M','M','T')
 #define LXiTAG_DESCRIPTION       LXxID4('D','E','S','C')
 #define LXiTAG_CUE               LXxID4('C','U','E',' ')
 #define LXiTAG_LOCK              LXxID4('L','O','C','K')

Empty StringTag Python user class.

(115) PY: empty StringTag user class
 pass

Matrices

Matrices are one of the more common complex types, so we provide an interface (polymorphic with ILxValue-type objects) to access them more directly.

These functions allow 3x3 and 4x4 transformation matrices to be read.

(116) SDK: Matrix::Get3, etc.
         LXxMETHOD( LxResult,
 Get3) (
         LXtObjectID              self,
         LXtMatrix                mat3);
 
         LXxMETHOD( LxResult,
 Get4) (
         LXtObjectID              self,
         LXtMatrix4               mat4);
 
         LXxMETHOD( LxResult,
 GetOffset) (
         LXtObjectID              self,
         LXtVector                offset);

As a convenience, this method composes a vector with the matrix.

(117) SDK: Matrix::MultiplyVector
         LXxMETHOD( LxResult,
 MultiplyVector) (
         LXtObjectID              self,
         const LXtVector          vector,
         LXtVector                result);

Writable matrices have some operations to change them. First directly:

(118) SDK: Matrix::Set3, etc.
         LXxMETHOD( LxResult,
 Set3) (
         LXtObjectID              self,
         const LXtMatrix          mat3);
 
         LXxMETHOD( LxResult,
 Set4) (
         LXtObjectID              self,
         const LXtMatrix4         mat4);
 
         LXxMETHOD( LxResult,
 SetOffset) (
         LXtObjectID              self,
         const LXtVector          offset);

Then indirectly:

(119) SDK: Matrix::SetIdentity, etc.
         LXxMETHOD( LxResult,
 SetIdentity) (
         LXtObjectID              self);
 
         LXxMETHOD( LxResult,
 Multiply3) (
         LXtObjectID              self,
         const LXtMatrix          mat3);
 
         LXxMETHOD( LxResult,
 Multiply4) (
         LXtObjectID              self,
         const LXtMatrix4         mat4);
 
         LXxMETHOD( LxResult,
 Invert) (
         LXtObjectID              self);
 
         LXxMETHOD( LxResult,
 Transpose) (
         LXtObjectID              self);

(120) SDK: empty Matrix User Class

Empty Matrix Python user class.

(121) PY: empty Matrix user class
 pass

(122) SDK: LXu_MATRIX define
 #define LXu_MATRIX              "EF9FDE7B-E7FA-48B2-838E-A5A8F7D5C254"

Quaternions

Quaternions are often useful when working with rotations, however they are a rather complex data type, so we provide an interface (polymorphic ILxValue-type object) to access them more directly.

These functions allow the quaternion to be read. Either as a direct quaternion, a 3x3 matrix, or as an angle + axis.

(123) SDK: Quaternion::GetQuaternion, etc.
         LXxMETHOD( LxResult,
 GetQuaternion) (
         LXtObjectID              self,
         LXtQuaternion            q);
 
         LXxMETHOD( LxResult,
 GetMatrix) (
         LXtObjectID              self,
         LXtMatrix                mat3);
 
         LXxMETHOD( LxResult,
 GetAngleAxis) (
         LXtObjectID              self,
         double                  *ang,
         LXtVector                axis);

Writable quaternions have some operations to change them.

(124) SDK: Quaternion::SetQuaternion, etc.
         LXxMETHOD( LxResult,
 SetQuaternion) (
         LXtObjectID              self,
         const LXtQuaternion      q);
 
         LXxMETHOD( LxResult,
 SetMatrix) (
         LXtObjectID              self,
         const LXtMatrix          mat3);
 
         LXxMETHOD( LxResult,
 SetAngleAxis) (
         LXtObjectID              self,
         double                   ang,
         const LXtVector          axis);

(125) SDK: empty Quaternion User Class

Empty Quaternion Python user class.

(126) PY: empty Quaternion user class
 pass

(127) SDK: LXu_QUATERNION define
 #define LXu_QUATERNION          "B8697DEB-DCD0-4C86-B822-702D5EDEFA76"

Visitors

A visitor is a general-purpose object created by SDK clients when they want to perform some action from inside the app. The single Evaluate() method can be called for each element in a database, for example, or just when the client wants to do something in a specific context. If this method returns a value other than LXe_OK, the enumeration will stop and the enumerate method will return the result code.

(128) SDK: Visitor::Evaluate
         LXxMETHOD(  LxResult,
 Evaluate) (
         LXtObjectID              self);

(129) SDK: LXa_VISITOR, etc. defines
 #define LXa_VISITOR     "visitor"
 #define LXu_VISITOR     "C8FCAD70-DDDF-499E-A03B-A08B906D3E53"

Empty Visitor Python user class.

(130) PY: empty Visitor user class
 pass

Text Encoding Conversion

Text encoding converts text encoding of multi-bytes international between UTF-8 and other encodings.

LXiTEXT_ENCODING_DEFAULT System default encoding. UTF-8 is for Linux, one of others are for Windows and OSX and it is depended on the current locale setting.
LXiTEXT_ENCODING_ANSI ANSI character set for Latin.
LXiTEXT_ENCODING_UTF8 UTF8
LXiTEXT_ENCODING_SHIFTJIS Shift-JIS (Japanese)
LXiTEXT_ENCODING_EUCJP EUC-JP (Japanese)
LXiTEXT_ENCODING_EUCKR EUC-KR (Korea KS C 5601)
LXiTEXT_ENCODING_GB2312 GB2312 (Simplified Chinese)
LXiTEXT_ENCODING_BIG5 BIG5 (Traditonal Chinese)
(131) SDK: LXiTEXT_ENCODING_DEFAULT, etc. defines

Default Return the system default text encoding. It returns UTF-8 for OSX and Linux and others for Windows.
Source Return the current text encoding for source text.
Target Return the current text encoding for source text.
SetSource Set a text encoding for source text. The initial source encoding is set by "Default" method.
SetTarget Set a text encoding for target text to convert to.
Convert Convert a string encoded by source to a given buffer with target encoding.
NumChar Returns the length of a string in logical characters. If 'target' is true, the string is handled by target encoding, otherwise source encoding is used.
PullChar Gets the first character's numeric value in the current code page, and returns a pointer to the next character, or null if the the string was empty. If 'target' is true, the string is handled by target encoding, otherwise source encoding is used.
(132) SDK: TextEncoding::Default, etc.
         LXxMETHOD(  unsigned,
 Default) (
         LXtObjectID              self);
 
         LXxMETHOD(  unsigned,
 Source) (
         LXtObjectID              self);
 
         LXxMETHOD(  unsigned,
 Target) (
         LXtObjectID              self);
 
         LXxMETHOD(  LxResult,
 SetSource) (
         LXtObjectID              self,
         unsigned                 encoding);
 
         LXxMETHOD(  LxResult,
 SetTarget) (
         LXtObjectID              self,
         unsigned                 encoding);
 
         LXxMETHOD(  LxResult,
 Convert) (
         LXtObjectID              self,
         const char              *src,
         char                    *buf,
         unsigned                 max);

(133) SDK: TextEncoding::NumChar, etc.
         LXxMETHOD(  int,
 NumChar) (
         LXtObjectID              self,
         const char              *string,
         int                      target);
 
         LXxMETHOD(  const char *,
 PullChar) (
         LXtObjectID              self,
         const char              *string,
         int                     *code,
         int                     *len,
         int                      target);

(134) SDK: LXu_TEXTENCODING, etc. defines
 #define LXu_TEXTENCODING        "EE4989E5-F1E5-43D4-80CC-16F506EFD632"
 #define LXa_TEXTENCODING        "textencoding"

(135) SDK: CLxUser_TextEncoding::ConvertString method
         bool
 ConvertString (
         const std::string       &src,
         std::string             &dst)
 {
         char                    *tmp;
         unsigned                 max;
 
         if (CLxLoc_TextEncoding::Source () == CLxLoc_TextEncoding::Target ())
                 return false;
 
         max = (unsigned)src.length () * 2 + 1;
         tmp = new char[max];
         if (LXx_OK (CLxLoc_TextEncoding::Convert (src.c_str (), tmp, max)))
                 dst = tmp;
         delete [] tmp;
         return !dst.empty ();
 }

Empty TextEncoding Python user class.

(136) PY: empty TextEncoding user class
 pass

(137) SDK: LXu_TEXTENCODINGSERVICE, etc. defines
 #define LXu_TEXTENCODINGSERVICE "7753B6E4-CF23-491E-89C1-2CA26BE5C89F"
 #define LXa_TEXTENCODINGSERVICE "textencodingservice"

(138) SDK: TextEncodingService::Allocate
         LXxMETHOD(  LxResult,
 Allocate) (
         LXtObjectID              self,
         void                   **ppvObj);

(139) SDK: CLxUser_TextEncodingService::NewTextEncoding method
         bool
 NewTextEncoding (
         CLxLoc_TextEncoding      &txe)
 {
         LXtObjectID               obj;
         LxResult                  rc;
 
         rc = Allocate (&obj);
         if (LXx_FAIL (rc))
                 return false;
 
         return txe.take (obj);
 }

Empty textencoding service Python user class.

(140) PY: empty Service.TextEncoding user class
 pass