value (lx_value.hpp)

From The Foundry MODO SDK wiki
(Redirected from ILxAttributesID (index))
Jump to: navigation, search
There are security restrictions on this page


Contents

Value Global Service

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

(1) SDK: Declarations
 #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: ILxValueService interface
         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: ILxValueService interface
         LXxMETHOD(  LxResult,
 TextHintEncode) (
         LXtObjectID              self,
         int                      value,
         const LXtTextValueHint  *hint,
         char                    *buf,
         unsigned                 len);

Safer version for C++.

(4) User Service Class: ValueService 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: ILxValueService interface
         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: ILxValueService interface
         LXxMETHOD(  LxResult,
 CreateValue) (
         LXtObjectID              self,
         const char              *type,
         void                   **ppvObj);

(7) User Service Class: ValueService 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: ILxValueService interface
         LXxMETHOD(  LxResult,
 ValueType) (
         LXtObjectID              self,
         const char              *type,
         unsigned                *valType);

Empty value service Python user class.

(9) PY: ValueService method
 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: ILxValueService interface
         LXxMETHOD(  LxResult,
 TextHintDuplicate) (
         LXtObjectID               self,
         const LXtTextValueHint   *hint,
         LXtTextValueHint        **copy);

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

Nexus 801

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

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

(13) SDK: Declarations

Nexus 901

Returns the global Frames Per Second.

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

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

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

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

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

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

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

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

(18) SDK: ILxValueService interface
         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. This is useful when resolving links to external assets, since we don't want to remap output paths.

(26) Hint Example: File Format
 static LXtTextValueHint  imageHint[] = {
         0,      "@image",
         0,      NULL
 };
 static LXtTextValueHint  imageWriteOnlyHint[] = {
         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: ILxValue interface
         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) User Class: Value 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: ILxValue interface
         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) User Class: Value 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) User Class: Value 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 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: ILxValue interface
         LXxMETHOD(  void *,
 Intrinsic) (
         LXtObjectID              self);

(35) SDK: Declarations
 #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: ILxStringConversion interface
         LXxMETHOD( LxResult,
 Encode) (
         LXtObjectID              self,
         char                    *buf,
         unsigned                 len);
 
         LXxMETHOD( LxResult,
 Decode) (
         LXtObjectID              self,
         const char              *buf);

Same encode functionality, safer than before.

(37) Conv $$ user class method
 class Tmp_Sgs {
     public:
         CLxLoc_$$               *conv;
 
         LxResult sgs_GetString (char *buf, unsigned int len)
         {
                 return conv->Encode (buf, len);
         }
 };
 
         LxResult
 EncodeStr (
         std::string             &text)
 {
         Tmp_Sgs                          tmp;
         CLxSafeGetString<Tmp_Sgs>        sgs;
 
         tmp.conv = this;
         return sgs.GetString (tmp, text);
 }

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.

(38) SDK: Declarations
 #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.

(39) SDK: ILxStringConversionNice interface
         LXxMETHOD( LxResult,
 Encode) (
         LXtObjectID              self,
         char                    *buf,
         unsigned                 len);
 
         LXxMETHOD( LxResult,
 Decode) (
         LXtObjectID              self,
         const char              *buf);

(40) User Class: StringConversion method
 ''[[#C37|Conv StringConversion user class method]]''

(41) User Class: StringConversionNice method
 ''[[#C37|Conv StringConversionNice user class method]]''

Empty StringConversion Python user class.

(42) PY: StringConversion method
 pass

Empty StringConversionNice Python user class.

(43) PY: StringConversionNice method
 pass

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

(44) SDK: ILxValueMath interface
         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);

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

(46) User Class: ValueMath method

Empty ValueMath Python user class.

(47) PY: ValueMath method
 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.

(48) SDK: ILxValueReference interface
         LXxMETHOD( LxResult,
 IsSet) (
         LXtObjectID              self);
 
         LXxMETHOD( LxResult,
 GetObject) (
         LXtObjectID              self,
         void                   **ppvObj);
 
         LXxMETHOD( LxResult,
 SetObject) (
         LXtObjectID              self,
         LXtObjectID              obj);

(49) User Class: ValueReference method
         bool
 Get (
         CLxLocalizedObject      &loc)
 {
         return GetObject (loc);
 }
 
         bool
 TakeObject (
         ILxUnknownID             obj)
 {
         if (LXx_FAIL (SetObject (obj)))
                 return false;
 
         lx::UnkRelease (obj);
         return true;
 }

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

Empty ValueReference Python user class.

(51) PY: ValueReference method
 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.

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

Count
Return the number of attributes.
Name
Return the name of the attribute at given index, or LXe_OUTOFBOUNDS for bad index choices.
Lookup
Return the index given the name, or LXe_NOTFOUND.
Type
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.
TypeName
Return the attribute type name. This is the name of any of the available value types.
Hints
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.

(53) SDK: ILxAttributes interface
         LXxMETHOD(  unsigned int,
 Count) (
         LXtObjectID              self);
 
         LXxMETHOD(  LxResult,
 Name) (
         LXtObjectID              self,
         unsigned int             index,
         const char             **name);
 
         LXxMETHOD(  LxResult,
 Lookup) (
         LXtObjectID              self,
         const char              *name,
         unsigned int            *index);
 
         LXxMETHOD(  LxResult,
 Type) (
         LXtObjectID              self,
         unsigned int             index,
         unsigned int            *type);
 
         LXxMETHOD(  LxResult,
 TypeName) (
         LXtObjectID              self,
         unsigned int             index,
         const char             **tname);
 
         LXxMETHOD(  const LXtTextValueHint *,
 Hints) (
         LXtObjectID              self,
         unsigned int             index);

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.

(54) SDK: Declarations
 #define LXi_TYPE_OBJECT         0
 #define LXi_TYPE_INTEGER        1
 #define LXi_TYPE_FLOAT          2
 #define LXi_TYPE_STRING         3

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.

(55) SDK: Declarations
 #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"

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.

(56) SDK: ILxAttributes interface
         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.

(57) User Class: Attributes 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.

(58) PY: Attributes 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.

(59) User Class: Attributes 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.

(60) User Class: Attributes 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.

(61) User Class: Attributes 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.

(62) User Class: Attributes 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.

(63) User Class: Attributes 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.

(64) PY: Attributes 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'.

(65) PY: Attributes 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.

(66) SDK: Declarations
 #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.

(67) SDK: ILxMessage interface
         LXxMETHOD(  LxResult,
 Code) (
         LXtObjectID               self );

This sets that code.

(68) SDK: ILxMessage interface
         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.

(69) SDK: ILxMessage interface
         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.

(70) SDK: ILxMessage interface
         LXxMETHOD(  LxResult,
 SetArgumentInt) (
         LXtObjectID               self,
         unsigned                  arg,
         int                       value);

(71) SDK: ILxMessage interface
         LXxMETHOD(  LxResult,
 SetArgumentFloat) (
         LXtObjectID               self,
         unsigned                  arg,
         double                    value);

(72) SDK: ILxMessage interface
         LXxMETHOD(  LxResult,
 SetArgumentString) (
         LXtObjectID               self,
         unsigned                  arg,
         const char               *string);

(73) SDK: ILxMessage interface
         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.

(74) SDK: ILxMessage interface
         LXxMETHOD(  LxResult,
 Reset) (
         LXtObjectID               self);

Some clients need access to the table and message name.

(75) SDK: ILxMessage interface
         LXxMETHOD(  LxResult,
 Table) (
         LXtObjectID               self,
         const char              **table);

(76) SDK: ILxMessage interface
         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.

(77) SDK: ILxMessage interface
         LXxMETHOD(  LxResult,
 SetMessageResult) (
         LXtObjectID               self,
         unsigned                  id);

C++ User Class

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

(78) User Class: Message 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"'.

(79) PY: Message 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.

(80) User Class: Message 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.

(81) SDK: Declarations
 #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.

(82) SDK: ILxValueArray interface
         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.

(83) SDK: ILxValueArray interface
         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.

(84) SDK: ILxValueArray interface
         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.

(85) SDK: ILxValueArray interface
         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.

(86) SDK: ILxValueArray interface
         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.

(87) SDK: ILxValueArray interface
         LXxMETHOD(  LxResult,
 FirstUnique) (
         LXtObjectID               self,
         unsigned int             *uniqueIndex );

This empties the container, freeing all values within.

(88) SDK: ILxValueArray interface
         LXxMETHOD(  LxResult,
 Reset) (
         LXtObjectID               self );

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

(89) User Class: ValueArray 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));
 }

(90) User Class: ValueArray 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.

(91) PY: ValueArray 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.

(92) PY: ValueArray 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.

(93) SDK: Declarations
 #define LXu_ARRAY               "d1e1ba61-700e-48ad-aada-6865148fcc40"
 #define LXa_ARRAY               "array"

(94) SDK: ILxArray interface
         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.

(95) SDK: Declarations
 #define LXu_SCRIPTQUERY         "0434F07E-AD4A-492f-AD43-3249BD16994D"
 #define LXa_SCRIPTQUERY         "scriptquery"

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

(96) SDK: Declarations

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.

(97) SDK: ILxScriptQuery interface
         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.

(98) SDK: ILxScriptQuery interface
         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.

(99) SDK: ILxScriptQuery interface
         LXxMETHOD(  LxResult,
 Type) (
         LXtObjectID              self,
         const char              *attribute,
         int                     *type);

The specific ExoType name can be read with this method.

(100) SDK: ILxScriptQuery interface
         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.

(101) User Class: ScriptQuery 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.

(102) PY: ScriptQuery method
 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. 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.

(103) SDK: ILxStringTag interface
         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.

(104) SDK: ILxStringTag interface
         LXxMETHOD( LxResult,
 Set) (
         LXtObjectID              self,
         LXtID4                   type,
         const char              *tag);

These methods allow the tag list to be walked.

(105) SDK: ILxStringTag interface
         LXxMETHOD( LxResult,
 Count) (
         LXtObjectID              self,
         unsigned int            *count);
 
         LXxMETHOD( LxResult,
 ByIndex) (
         LXtObjectID              self,
         unsigned int             index,
         LXtID4                  *type,
         const char             **tag);

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

(107) User Class: StringTag method
         const char *
 Value (
         LXtID4                   type)
 {
         const char              *tag;
 
         if (LXx_OK (Get (type, &tag)))
                 return tag;
         else
                 return 0;
 }

Empty StringTag Python user class.

(108) PY: StringTag method
 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.

(109) SDK: ILxMatrix interface
         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.

(110) SDK: ILxMatrix interface
         LXxMETHOD( LxResult,
 MultiplyVector) (
         LXtObjectID              self,
         const LXtVector          vector,
         LXtVector                result);

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

(111) SDK: ILxMatrix interface
         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:

(112) SDK: ILxMatrix interface
         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);

(113) User Class: Matrix method

Empty Matrix Python user class.

(114) PY: Matrix method
 pass

(115) SDK: Declarations
 #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.

(116) SDK: ILxQuaternion interface
         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.

(117) SDK: ILxQuaternion interface
         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);

(118) User Class: Quaternion method

Empty Quaternion Python user class.

(119) PY: Quaternion method
 pass

(120) SDK: Declarations
 #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.

(121) SDK: ILxVisitor interface
         LXxMETHOD(  LxResult,
 Evaluate) (
         LXtObjectID              self);

(122) SDK: Declarations
 #define LXa_VISITOR     "visitor"
 #define LXu_VISITOR     "C8FCAD70-DDDF-499E-A03B-A08B906D3E53"

Empty Visitor Python user class.

(123) PY: Visitor method
 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)

(124) SDK: Declarations

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.

(125) SDK: ILxTextEncoding interface
         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);

(126) SDK: ILxTextEncoding interface
         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);

(127) SDK: Declarations
 #define LXu_TEXTENCODING        "EE4989E5-F1E5-43D4-80CC-16F506EFD632"
 #define LXa_TEXTENCODING        "textencoding"

(128) User Class: TextEncoding 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.

(129) PY: TextEncoding method
 pass

(130) SDK: Declarations
 #define LXu_TEXTENCODINGSERVICE "7753B6E4-CF23-491E-89C1-2CA26BE5C89F"
 #define LXa_TEXTENCODINGSERVICE "textencodingservice"

(131) SDK: ILxTextEncodingService interface
         LXxMETHOD(  LxResult,
 Allocate) (
         LXtObjectID              self,
         void                   **ppvObj);

(132) User Service Class: TextEncodingService 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.

(133) PY: TextEncodingService method
 pass