Warning: Can't synchronize with the repository (Couldn't open Subversion repository /home/crystal/scm/crystal: SubversionException: ("Expected FS format between '1' and '3'; found format '4'", 160043)). Look in the Trac log for more information.

The new iModifiable interface is to be implemented by all objects willing to be modified automatically. It provide access to the parameters of the CS objects, and to their type, description and constraints.

File CS/include/iutil/pluginconfig.h:

// Extension to csVariant with the following types:
enum csVariantType
{
  BOOL,
  INT32?,
  UINT32/64?,
  INT64,
  FLOAT,
  DOUBLE,
  STRING,
  COLOR,
  COLOR4,
  VECTOR2,
  VECTOR3,
  VECTOR4,
  KEYVAL,
  KEYVALLIST?, // ie ARRAY?
  QUATERNION, // or constraint of vector4?
  TRANSFORM?,
  IBASE,
  ARRAY?
};

File CS/include/iutil/modifiable.h:

struct iModifiable : public virtual iBase
{
  const csStringID GetID () const;

  csPtr<iModifiableDescription> GetDescription () const;

  void GetParameterValue (csStringID id, const csVariant& value) const;
  bool SetParameterValue (csStringID id, const csVariant& value);

  // TODO: add callback when some value is changed: through the CS event
  // system or through callbacks? The event system probably...
};

struct iModifiableDescription : public virtual iBase
{
  size_t GetParameterCount () const;

  const iModifiableParameter* GetParameter (csStringID id) const;
  const iModifiableParameter* GetParameterByIndex (size_t index) const;
};

struct iModifiableParameter : public virtual iBase
{
  const csStringID GetID () const;

  // The returned char* are actually entries to be processed by the translator.
  // Or: both the name and the description can already be found from the ID of the parameter,
  // therefore no need for for explicit methods to get them?
  const char* GetName () const;
  const char* GetDescription () const;
  csVariantType GetType () const;
  // return nullptr if no constraint
  const iModifiableConstraint* GetConstraint () const;
};

enum iModifiableConstraintType
{
  MODIFIABLE_CONSTRAINT_BOUNDED = 0, // only applicable for int, float, vector?, color?, quaternion?
  MODIFIABLE_CONSTRAINT_ENUM,        // applicable to all types?
  MODIFIABLE_CONSTRAINT_VFS_FILE,    // only applicable for string
  MODIFIABLE_CONSTRAINT_VFS_DIR,     // only applicable for string
  MODIFIABLE_CONSTRAINT_VFS_PATH,    // only applicable for string
  MODIFIABLE_CONSTRAINT_TEXT_ENTRY,  // only applicable for string
  MODIFIABLE_CONSTRAINT_TEXT_BLOB,   // only applicable for string
  MODIFIABLE_CONSTRAINT_BITMASK,     // only applicable for int?
  // TODO: constraints on iBase? eg SCF interfaces? or dynamic enum of the possible values?
};

struct iModifiableConstraint : public virtual iBase
{
  iModifiableConstraintType GetType () const;
  // TODO: callback/events when changes?
};

struct iModifiableConstraintBounded : public virtual iModifiableConstraint
{
  bool HasMinimum () const;
  csVariant& GetMinimum () const;
  bool HasMaximum () const;
  csVariant& GetMaximum () const;
};

struct iModifiableConstraintEnum : public virtual iModifiableConstraint
{
  size_t GetValueCount () const;
  csVariant& GetValue (size_t index) const;
};

Example:

static csColor manualColor;

class csGenmeshMeshObject
: public scfImplementation3<csGenmeshMeshObject, 
  iMeshObject,
  iGeneralMeshState,
  iModifiable>
{
  ...
};

const csStringID csGenmeshMeshObject::GetID () const
{
  return id_meshobject;
}

csPtr<iModifiableDescription> csGenmeshMeshObject::GetDescription () const
{
  csRef<iModifiableDescription> ref;
  ref.AttachNew (new csGenmeshMeshObjectDescription ());
  return ref;
}

void csGenmeshMeshObject::GetParameterValue (csStringID id, const csVariant& value) const
{
  ...
  else if (id == id_manualColor)
    value.SetColor (manualColor);
  ...
}

bool csGenmeshMeshObject::SetParameterValue (csStringID id, const csVariant& value)
{
  ...
  else if (id == id_manualColor)
#ifdef CS_DEBUG
    if (value.GetType () != CSVAR_COLOR)
      return ReportError
	("Invalid type while setting parameter %s. Got %s instead of %s.",
	 CS::Quote::Single (id),
	 CS::Quote::Single (value.GetType ()),
	 CS::Quote::Single (CSVAR_COLOR),
	  );
#endif // CS_DEBUG
    
  manualColor = value.GetColor ();
  ...
}

class csGenmeshMeshObjectDescription : public iModifiableDescription
{
  // Would need tool classes in order to help defining descriptions, parameters
  // and constraints
};

class csGenmeshMeshObject : public iModifiableParameter
{
  ManualColors ()
    : iModifiableParameter ("manualColors", "whether this mesh uses manual colors", iVariant::Type::Bool)
  {}
};

void ManualColors::GetValue (csVariant& value) const
{
  value.Set (...);
}

void ManualColors::SetValue (const iVariant& value) 
{
  ... = value.GetValue ();
}