Game Development Community

Setting default values manually

by Scott Goodwin · in Torque X 2D · 07/14/2008 (8:36 am) · 2 replies

Suppose we have a component with property P having attribute [TorqueXmlSchemaType(DefaultValue = "100.0")].

If I attach the component to an object through TXB, the default value gets set (i.e., it's in the txscene file). But I want to add the component in code. The default value doesn't get automatically set. I know I could initialize the corresponding private member field _p to the default value, but I don't want to do it that way because of the possibility of the attribute default value being different (i.e., over time changing the attribute default and forgetting to make the corresponding change to the private member field).

The default value is recorded in the .txschema file. Is there an easy way to access these values and initialize the defaults in code.

Obviously, this is done somewhere in the scene loader. Before I go looking for the code, has anybody done this already or have a better solution?


Short version: I want adding a component in code to behave the same way as when it is added through TXB.

#1
07/14/2008 (12:33 pm)
Here's a first try at this. I'm not sure it correctly handles all the possibilities (since I don't know what the possiblities are! Only guessing based on the schema exporter). This seems to handle simple cases such as [TorqueXmlSchemaType(DefaultValue = "100.0")]. Not sure about if other attributes are handled correctly or if inheritance is a factor. If anyone has further insights, please let me know.

The idea is when you create a component in code, you can pass it to the Initialize method below and it will find and apply property DefaultValues declared in the attributes.

Doesn't check whether the property is public and doesn't distinguish fields versus properties. Not sure if that's important.

Anyway, here it is:

public void Initialize(object o)
        {
            Type t = o.GetType();
            // skip anthing that isn't an instantiable reference type
            if (!t.IsClass || t.IsInterface || t.IsAbstract)
                return;
 
            // skip it unless it has a TorqueXmlSchemaType attribute
            object[] attrs = t.GetCustomAttributes(false);
 
            bool hasSchemaAttr = false;
 
            foreach (object attr in attrs)
            {
                if (attr is TorqueXmlSchemaType)
                {
                    hasSchemaAttr = true;
                    break;
                }
            }
 
            if (!hasSchemaAttr)
                return;
 
            TypeInfo ti = TypeUtil.FindTypeInfo(t.FullName);
 
            if (ti.Type.IsSubclassOf(typeof(TorqueComponent)))
            {
                List<IFieldOrProperty> fieldsAndProperties = ti.FieldsAndProperties;
                foreach (IFieldOrProperty fieldOrProperty in fieldsAndProperties)
                {
                    // retrieve XML schema attribute, if any
                    TorqueXmlSchemaType xmlAttr = null;
 
                    object[] cAttrs = fieldOrProperty.GetCustomAttributes(true);
                    foreach (object cAttr in cAttrs)
                    {
                        if (cAttr is TorqueXmlSchemaType)
                        {
                            xmlAttr = cAttr as TorqueXmlSchemaType;
                            break;
                        }
                    }
 
                    if (xmlAttr != null)
                    {
                        if (xmlAttr.DefaultValue != null)
                        {
                            fieldOrProperty.SetValue(
                                o,
                                TypeUtil.GetPrimitiveValue(
                                    fieldOrProperty.DeclaredType,
                                    xmlAttr.DefaultValue));
                        }
                    }
                }
            }
#2
07/15/2008 (1:21 pm)
Whoa! thats pretty nifty scott, I'm going to check that out!

Will