Пример #1
0
        /// <summary>
        /// Method called after the schema set has been loaded and the DomNodeTypes have been created, but
        /// before the DomNodeTypes have been frozen. This means that DomNodeType.SetIdAttribute, for example, has
        /// not been called on the DomNodeTypes. Is called shortly before OnDomNodeTypesFrozen.
        /// Create property descriptors for types.</summary>
        /// <param name="schemaSet">XML schema sets being loaded</param>
        protected override void OnSchemaSetLoaded(XmlSchemaSet schemaSet)
        {
            foreach (XmlSchemaTypeCollection typeCollection in GetTypeCollections())
            {
                m_namespace      = typeCollection.TargetNamespace;
                m_typeCollection = typeCollection;
                Schema.Initialize(typeCollection);


                // register extensions
                Schema.gameType.Type.Define(new ExtensionInfo <GameEditingContext>());
                Schema.gameType.Type.Define(new ExtensionInfo <UniqueIdValidator>());


                // Add required property descriptors to GameObject and OrcType so it can be edited
                // with two column PropertyGrid.

                // Note: this is programmatic approach: Decorate DomNode types with
                //       property descriptors.
                //       Alternatively schema annotations can used.
                //       However, programmatic approach is recommend because of type safety.


                // Descriptors for armorType.
                string general          = "General".Localize();
                var    armorDescriptors = new PropertyDescriptorCollection(null);
                armorDescriptors.Add(new AttributePropertyDescriptor(
                                         "Name".Localize(),
                                         Schema.armorType.nameAttribute,
                                         general,
                                         "Armor name".Localize(),
                                         false
                                         ));

                armorDescriptors.Add(new AttributePropertyDescriptor(
                                         "Defense".Localize(),
                                         Schema.armorType.defenseAttribute,
                                         general,
                                         "Armor defense".Localize(),
                                         false,
                                         new NumericEditor(typeof(int))
                                         ));

                armorDescriptors.Add(new AttributePropertyDescriptor(
                                         "Price".Localize(),
                                         Schema.armorType.priceAttribute,
                                         general,
                                         "Armor price in gold".Localize(),
                                         false,
                                         new NumericEditor(typeof(int))
                                         ));

                Schema.armorType.Type.SetTag(armorDescriptors);

                // club type property descriptors.
                var clubDescriptors = new PropertyDescriptorCollection(null);
                clubDescriptors.Add(new AttributePropertyDescriptor(
                                        "Spike".Localize(),
                                        Schema.clubType.spikesAttribute,
                                        general,
                                        "Club Has Spikes".Localize(),
                                        false,
                                        new BoolEditor()
                                        ));


                clubDescriptors.Add(new AttributePropertyDescriptor(
                                        "Damage".Localize(),
                                        Schema.clubType.DamageAttribute,
                                        general,
                                        "Amount of damage per strike".Localize(),
                                        false,
                                        new NumericEditor(typeof(int))
                                        ));

                clubDescriptors.Add(new AttributePropertyDescriptor(
                                        "Weight".Localize(),
                                        Schema.clubType.wieghtAttribute,
                                        general,
                                        "Weight of the club".Localize(),
                                        false,
                                        new NumericEditor(typeof(float))
                                        ));

                Schema.clubType.Type.SetTag(clubDescriptors);

                var gobDescriptors = new PropertyDescriptorCollection(null);
                gobDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Name".Localize(),
                        Schema.gameObjectType.nameAttribute,
                        null,
                        "Object name".Localize(),
                        false
                        ));

                // bool editor:  shows checkBox instead of textual (true,false).
                gobDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Visible".Localize(),
                        Schema.gameObjectType.visibleAttribute,
                        null,
                        "Show/Hide object in editor".Localize(),
                        false,
                        new BoolEditor()
                        ));

                // NumericTupleEditor can be used for vector values.
                string xformCategory = "Transformation".Localize();
                var    transEditor   =
                    new NumericTupleEditor(typeof(float), new string[] { "Tx", "Ty", "Tz" });

                gobDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Translate".Localize(),
                        Schema.gameObjectType.translateAttribute,
                        xformCategory,
                        "Object's position".Localize(),
                        false,
                        transEditor
                        ));

                var scaleEditor =
                    new NumericTupleEditor(typeof(float), new string[] { "Sx", "Sy", "Sz" });
                gobDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Scale".Localize(),
                        Schema.gameObjectType.scaleAttribute,
                        xformCategory,
                        "Object's scale".Localize(),
                        false,
                        scaleEditor
                        ));

                var rotationEditor =
                    new NumericTupleEditor(typeof(float), new string[] { "Rx", "Ry", "Rz" });
                rotationEditor.ScaleFactor = 360.0f / (2.0f * (float)Math.PI); // Radians to Degrees
                gobDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Rotation".Localize(),
                        Schema.gameObjectType.rotateAttribute,
                        xformCategory,
                        "Object's orientation".Localize(),
                        false,
                        rotationEditor
                        ));

                Schema.gameObjectType.Type.SetTag(gobDescriptors);

                // Defines property descriptors for orcType.
                var    orcDescriptors = new PropertyDescriptorCollection(null);
                string chCategory     = "Character attributes".Localize();

                // Bounded int editor: used for editing bounded int properties.
                orcDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Skill".Localize(),
                        Schema.orcType.skillAttribute,
                        chCategory,
                        "Skill".Localize(),
                        false,
                        new BoundedIntEditor(1, 120)
                        ));

                // Bounded float editor: similar to bounded int editor
                // but it operates on float instead.
                orcDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Weight".Localize(),
                        Schema.orcType.weightAttribute,
                        chCategory,
                        "Weight".Localize(),
                        false,
                        new BoundedFloatEditor(80, 400)
                        ));


                // Enum can be stored as string or as int.
                //  OrcLevel is stored as int
                //  OrcEmotion is stored as string.
                //  please see the schema.


                // Create image for showing character level.
                var     levVals   = Enum.GetValues(typeof(OrcLevel));
                Image[] levImages = new Image[levVals.Length];
                foreach (var en in levVals)
                {
                    levImages[(int)en] = new Bitmap(this.GetType(),
                                                    "Resources." + en + ".png");
                }


                // show usage for enum stored as int.
                // Shows how to edit enum that is stored as string.
                var lvEnumEditor    = new LongEnumEditor(typeof(OrcLevel), levImages);
                var lvTypeConverter = new IntEnumTypeConverter(typeof(OrcLevel));

                orcDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Level".Localize(),
                        Schema.orcType.levelAttribute,
                        chCategory,
                        "Character level".Localize(),
                        false,
                        lvEnumEditor,
                        lvTypeConverter
                        ));

                // create images used for showing emotion
                // for enum OrcEmotion
                var     emoVals   = Enum.GetValues(typeof(OrcEmotion));
                Image[] emoImages = new Image[emoVals.Length];
                foreach (var en in emoVals)
                {
                    emoImages[(int)en] = new Bitmap(this.GetType(),
                                                    "Resources." + en + ".png");
                }
                // Shows how to edit enum that is stored as string.
                var emotionEditor = new LongEnumEditor(typeof(OrcEmotion), emoImages);
                orcDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Emotion".Localize(),
                        Schema.orcType.emotionAttribute,
                        chCategory,
                        "Emotion".Localize(),
                        false,
                        emotionEditor
                        ));


                // FlagsUITypeEditor store flags as int.
                // doesn't implement IPropertyEditor

                FlagsUITypeEditor  goalsEditor    = new FlagsUITypeEditor(Enum.GetNames(typeof(OrcGoals)));
                FlagsTypeConverter goalsConverter = new FlagsTypeConverter(Enum.GetNames(typeof(OrcGoals)));
                orcDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Goals".Localize(),
                        Schema.orcType.goalsAttribute,
                        chCategory,
                        "Goals".Localize(),
                        false,
                        goalsEditor,
                        goalsConverter
                        ));


                orcDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Health".Localize(),
                        Schema.orcType.healthAttribute,
                        chCategory,
                        "Orc's health".Localize(),
                        false,
                        new NumericEditor(typeof(int))
                        ));


                //EmbeddedCollectionEditor edit children (edit, add, remove, move).
                // note: EmbeddedCollectionEditor needs some work (efficiency and implementation issues).
                var collectionEditor = new EmbeddedCollectionEditor();

                // the following  lambda's handles (add, remove, move ) items.
                collectionEditor.GetItemInsertersFunc = (context) =>
                {
                    var insertors
                        = new EmbeddedCollectionEditor.ItemInserter[1];

                    var list = context.GetValue() as IList <DomNode>;
                    if (list != null)
                    {
                        var childDescriptor
                            = context.Descriptor as ChildPropertyDescriptor;
                        if (childDescriptor != null)
                        {
                            insertors[0] = new EmbeddedCollectionEditor.ItemInserter(childDescriptor.ChildInfo.Type.Name,
                                                                                     delegate
                            {
                                DomNode node = new DomNode(childDescriptor.ChildInfo.Type);
                                if (node.Type.IdAttribute != null)
                                {
                                    node.SetAttribute(node.Type.IdAttribute, node.Type.Name);
                                }
                                list.Add(node);
                                return(node);
                            });
                            return(insertors);
                        }
                    }
                    return(EmptyArray <EmbeddedCollectionEditor.ItemInserter> .Instance);
                };


                collectionEditor.RemoveItemFunc = (context, item) =>
                {
                    var list = context.GetValue() as IList <DomNode>;
                    if (list != null)
                    {
                        list.Remove(item.Cast <DomNode>());
                    }
                };


                collectionEditor.MoveItemFunc = (context, item, delta) =>
                {
                    var list = context.GetValue() as IList <DomNode>;
                    if (list != null)
                    {
                        DomNode node        = item.Cast <DomNode>();
                        int     index       = list.IndexOf(node);
                        int     insertIndex = index + delta;
                        if (insertIndex < 0 || insertIndex >= list.Count)
                        {
                            return;
                        }
                        list.RemoveAt(index);
                        list.Insert(insertIndex, node);
                    }
                };

                string weaponCategory = "Weapons and Defense".Localize();
                orcDescriptors.Add(
                    new ChildPropertyDescriptor(
                        "Armor".Localize(),
                        Schema.orcType.armorChild,
                        weaponCategory,
                        "Armors".Localize(),
                        false,
                        collectionEditor
                        ));

                orcDescriptors.Add(
                    new ChildPropertyDescriptor(
                        "Club".Localize(),
                        Schema.orcType.clubChild,
                        weaponCategory,
                        "Club".Localize(),
                        false,
                        collectionEditor
                        ));

                orcDescriptors.Add(
                    new ChildPropertyDescriptor(
                        "Orcs".Localize(),
                        Schema.orcType.orcChild,
                        "Children".Localize(),
                        "Orc children".Localize(),
                        false,
                        collectionEditor
                        ));



                string renderingCategory = "Rendering".Localize();

                // color picker.
                // note: ColorPickerEditor doesn't implement IPropertyEditor
                orcDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Skin".Localize(),
                        Schema.orcType.skinColorAttribute,
                        renderingCategory,
                        "Skin color".Localize(),
                        false,
                        new ColorPickerEditor(),
                        new IntColorConverter()
                        ));


                // file picker.
                orcDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Texture file".Localize(),
                        Schema.orcType.textureFileAttribute,
                        renderingCategory,
                        "Texture file".Localize(),
                        false,
                        new FileUriEditor("Texture file (*.dds)|*.dds")
                        ));

                // Edit matrix.
                //NumericMatrixEditor
                orcDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Texture Transform".Localize(),
                        Schema.orcType.textureTransformAttribute,
                        renderingCategory,
                        "Texture Transform".Localize(),
                        false,
                        new NumericMatrixEditor()
                        ));


                // Edit array.
                // ArrayEditor, need some work, it has some efficiency and implementation issues.
                orcDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Texture Array".Localize(),
                        Schema.orcType.textureArrayAttribute,
                        renderingCategory,
                        "Texture Array".Localize(),
                        false,
                        new ArrayEditor()
                        ));


                // readonly property,
                // show datetime as readonly.
                orcDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Revision data".Localize(),
                        Schema.orcType.TextureRevDateAttribute,
                        renderingCategory,
                        "Texture revision data and time".Localize(),
                        true
                        ));

                // folder picker.
                // FolderUriEditor and FolderBrowserDialogUITypeEditor
                orcDescriptors.Add(
                    new AttributePropertyDescriptor(
                        "Resource Folder".Localize(),
                        Schema.orcType.resourceFolderAttribute,
                        renderingCategory,
                        "Resource folder".Localize(),
                        false,
                        new FolderUriEditor()
                        ));

                Schema.orcType.Type.SetTag(orcDescriptors);

                // only one namespace
                break;
            }
        }
        /// <summary>
        /// Creates an array of property descriptors that are associated with the adapted DomNode's
        /// DomNodeType. No duplicates will be in the array (based on the property descriptor's Name
        /// property).</summary>
        /// <returns>Array of property descriptors</returns>
        protected override System.ComponentModel.PropertyDescriptor[] GetPropertyDescriptors()
        {
            // Initialize property desciptors with the ones from the base class
            // If this is not done, the new property descriptors would be used instead of
            // rather than in addition to the ones defined in the schema
            List <System.ComponentModel.PropertyDescriptor> descriptors =
                new List <System.ComponentModel.PropertyDescriptor>(base.GetPropertyDescriptors());

            // Add ITransformable properties:
            // Translation, Rotation, Scale, RotatePivot, ScalePivot (if supported by this object)

            ITransformable      node          = this.Cast <ITransformable>();
            TransformationTypes transformType = node.TransformationType;

            NumericTupleEditor tupleEditor =
                new NumericTupleEditor(typeof(float), new string[] { "x", "y", "z" });
            NumericTupleEditor rotationTupleEditor =
                new NumericTupleEditor(typeof(float), new string[] { "x", "y", "z" });

            rotationTupleEditor.ScaleFactor = 360 / (2 * Math.PI); // Radians to Degrees

            FloatArrayConverter converter         = new FloatArrayConverter();
            FloatArrayConverter rotationConverter = new FloatArrayConverter();

            rotationConverter.ScaleFactor = 360 / (2 * Math.PI); // Radians to Degrees


            string category = "Transform".Localize();

            // Check for transform types
            if ((transformType & TransformationTypes.Translation) != 0)
            {
                descriptors.Add(
                    new AttributePropertyDescriptor(
                        "Translation", Schema.gameObjectType.translateAttribute, category, "Translation of Game Object along X, Y, and Z axes".Localize(),
                        false, tupleEditor, converter));
            }

            if ((transformType & TransformationTypes.Rotation) != 0)
            {
                descriptors.Add(new AttributePropertyDescriptor(
                                    "Rotation".Localize(), Schema.gameObjectType.rotateAttribute, category,
                                    "Origin of Rotation transform relative to Game Object Translation".Localize(),
                                    false, rotationTupleEditor, rotationConverter));
            }

            if ((transformType & TransformationTypes.Scale) != 0)
            {
                if ((transformType & TransformationTypes.UniformScale) == 0)
                {
                    descriptors.Add(
                        new AttributePropertyDescriptor(
                            "Scale".Localize(),
                            Schema.gameObjectType.scaleAttribute, category,
                            "Scale of Game Object along X, Y, and Z axes".Localize(),
                            false, tupleEditor, converter));
                }
                else
                {
                    descriptors.Add(
                        new AttributePropertyDescriptor(
                            "Scale".Localize(), Schema.gameObjectType.scaleAttribute,
                            category,
                            "Scale of Game Object along X, Y, and Z axes".Localize(),
                            false, new UniformArrayEditor <Single>(), new UniformFloatArrayConverter()));
                }
            }

            if ((transformType & TransformationTypes.Pivot) != 0)
            {
                descriptors.Add(
                    new AttributePropertyDescriptor(
                        "Pivot".Localize(), Schema.gameObjectType.pivotAttribute, category,
                        "Origin of Rotation and scale transform relative to Game Object Translation".Localize(),
                        false, tupleEditor, converter));
            }


            // remove hidden properties
            HashSet <string> hiddenProps = (HashSet <string>) this.DomNode.Type.GetTag(SchemaLoader.HiddenProperties);

            if (hiddenProps != null)
            {
                List <PropertyDescriptor> removeList = new List <PropertyDescriptor>();
                foreach (AttributePropertyDescriptor propdescr in descriptors.AsIEnumerable <AttributePropertyDescriptor>())
                {
                    if (hiddenProps.Contains(propdescr.AttributeInfo.Name))
                    {
                        removeList.Add(propdescr);
                    }
                }

                foreach (PropertyDescriptor propDescr in removeList)
                {
                    descriptors.Remove(propDescr);
                }
            }


            return(descriptors.ToArray());
        }