示例#1
0
文件: TestEntity.cs 项目: xen2/stride
        public void TestMultipleComponents()
        {
            // Check that TransformComponent cannot be added multiple times
            Assert.False(EntityComponentAttributes.Get <TransformComponent>().AllowMultipleComponents);

            // Check that CustomEntityComponent can be added multiple times
            Assert.True(EntityComponentAttributes.Get <CustomEntityComponent>().AllowMultipleComponents);

            // Check that DerivedEntityComponentBase can be added multiple times
            Assert.True(EntityComponentAttributes.Get <DerivedEntityComponent>().AllowMultipleComponents);

            var entity = new Entity();

            var transform = entity.Get <TransformComponent>();

            Assert.NotNull(transform);
            Assert.Equal(entity.Transform, transform);

            var custom = entity.GetOrCreate <CustomEntityComponent>();

            Assert.NotNull(custom);

            var custom2 = new CustomEntityComponent();

            entity.Components.Add(custom2);
            Assert.Equal(custom, entity.Get <CustomEntityComponent>());

            var allComponents = entity.GetAll <CustomEntityComponent>().ToList();

            Assert.Equal(new List <EntityComponent>()
            {
                custom, custom2
            }, allComponents);
        }
示例#2
0
        /// <inheritdoc/>
        protected override bool CanReplaceItem(IObjectNode collection, NodeIndex index, object newItem)
        {
            if (collection.Type != typeof(EntityComponentCollection))
            {
                return(base.CanReplaceItem(collection, index, newItem));
            }

            if (newItem == null)
            {
                return(false);
            }

            var componentType = newItem.GetType();

            // Cannot replace the transform component by another type of component
            if (collection.IndexedTarget(index).Type == typeof(TransformComponent) && componentType != typeof(TransformComponent))
            {
                return(false);
            }

            if (!EntityComponentAttributes.Get(componentType).AllowMultipleComponents)
            {
                // Cannot replace components that disallow multiple components, unless it is that specific component we're replacing
                var components = (EntityComponentCollection)collection.Retrieve();
                if (components.Where((x, i) => x.GetType() == componentType && i != index.Int).Any())
                {
                    return(false);
                }
            }
            return(base.CanReplaceItem(collection, index, newItem));
        }
示例#3
0
        /// <inheritdoc/>
        protected override bool CanInsertItem(IObjectNode collection, NodeIndex index, object newItem)
        {
            if (collection.Type != typeof(EntityComponentCollection))
            {
                return(base.CanInsertItem(collection, index, newItem));
            }

            if (newItem == null)
            {
                return(false);
            }

            var componentType = newItem.GetType();

            if (!EntityComponentAttributes.Get(componentType).AllowMultipleComponents)
            {
                // Cannot insert components that disallow multiple components
                var components = (EntityComponentCollection)collection.Retrieve();
                if (components.Any(x => x.GetType() == componentType))
                {
                    return(false);
                }
            }
            return(base.CanInsertItem(collection, index, newItem));
        }
        /// <inheritdoc/>
        protected override bool CanUpdate(IAssetNode node, ContentChangeType changeType, NodeIndex index, object value)
        {
            // Check if we are in the component collection of an entity (where we actually add new components)
            if (IsComponentForComponentCollection(node, value) && changeType == ContentChangeType.CollectionAdd)
            {
                var componentType       = value.GetType();
                var attributes          = EntityComponentAttributes.Get(componentType);
                var onlySingleComponent = !attributes.AllowMultipleComponents;
                var collection          = (EntityComponentCollection)node.Retrieve();

                foreach (var existingItem in collection)
                {
                    if (ReferenceEquals(existingItem, value))
                    {
                        return(false);
                    }

                    if (onlySingleComponent && componentType == existingItem.GetType())
                    {
                        return(false);
                    }
                }
            }

            return(base.CanUpdate(node, changeType, index, value));
        }
示例#5
0
        /// <inheritdoc/>
        void IAddChildrenPropertiesProviderViewModel.AddChildren(IReadOnlyCollection <object> children, AddChildModifiers modifiers)
        {
            foreach (var asset in children.OfType <AssetViewModel>())
            {
                var component = CreateComponentFromAsset(asset);
                if (component != null)
                {
                    // 3 cases:
                    // - If AllowMultipleComponents is true, we add at the end
                    // - If AllowMultipleComponents is true and the component doesn't exist yet, we replace
                    // - If AllowMultipleComponents is false and the component already exists, we replace

                    // Retrieve list of components to check if we need to add or replace
                    var assetSideEntityNode = Editor.NodeContainer.GetNode(AssetSideEntity);
                    var componentsNode      = assetSideEntityNode[nameof(Entity.Components)].Target;
                    var components          = AssetSideEntity.Components;

                    int replaceIndex = -1;

                    // Only try to replace in case AllowMultipleComponents is not set
                    if (!EntityComponentAttributes.Get(component.GetType()).AllowMultipleComponents)
                    {
                        // Find the replace index (if a component of same type already exists)
                        replaceIndex = components.IndexOf(x => x.GetType() == component.GetType());
                    }

                    // Add or replace the component
                    using (var transaction = Editor.UndoRedoService.CreateTransaction())
                    {
                        if (replaceIndex == -1)
                        {
                            componentsNode.Add(component);
                            Editor.UndoRedoService.SetName(transaction, $"Add component {component.GetType().Name}");
                        }
                        else
                        {
                            componentsNode.Update(component, new NodeIndex(replaceIndex));
                            Editor.UndoRedoService.SetName(transaction, $"Replace component {component.GetType().Name}");
                        }
                    }
                }
            }
        }
        protected override void UpdateNode(IAssetNodePresenter node)
        {
            if (!(node.Asset?.Asset is EntityHierarchyAssetBase))
            {
                return;
            }

            if (node.Value is EntityComponent && node.Parent?.Type == typeof(EntityComponentCollection))
            {
                // Apply the display name of the component
                var displayAttribute = TypeDescriptorFactory.Default.AttributeRegistry.GetAttribute <DisplayAttribute>(node.Value.GetType());
                if (!string.IsNullOrEmpty(displayAttribute?.Name))
                {
                    node.DisplayName = displayAttribute.Name;
                }

                node.CombineKey = node.Value.GetType().Name;
                if (node.Value is TransformComponent)
                {
                    // Always put the transformation component in first.
                    node.Order = -1;
                    var removeCommand = node.Commands.FirstOrDefault(x => x.Name == RemoveItemCommand.CommandName);
                    node.Commands.Remove(removeCommand);

                    // Remove the Children property of the transformation component (it should be accessible via the scene graph)
                    node[nameof(TransformComponent.Children)].IsVisible = false;
                }
            }
            if (node.Type == typeof(EntityComponentCollection))
            {
                var types = typeof(EntityComponent).GetInheritedInstantiableTypes()
                            .Where(x => Attribute.GetCustomAttribute(x, typeof(NonInstantiableAttribute)) == null &&
                                   (EntityComponentAttributes.Get(x).AllowMultipleComponents ||
                                    ((EntityComponentCollection)node.Value).All(y => y.GetType() != x)))
                            .OrderBy(DisplayAttribute.GetDisplayName)
                            .Select(x => new AbstractNodeType(x)).ToArray();
                node.AttachedProperties.Add(EntityHierarchyData.EntityComponentAvailableTypesKey, types);

                //TODO: Choose a better grouping method.
                var typeGroups =
                    types.GroupBy(t => ComponentCategoryAttribute.GetCategory(t.Type))
                    .OrderBy(g => g.Key)
                    .Select(g => new AbstractNodeTypeGroup(g.Key, g.ToArray())).ToArray();

                node.AttachedProperties.Add(EntityHierarchyData.EntityComponentAvailableTypeGroupsKey, typeGroups);

                // Cannot replace entity component collection.
                var replaceCommandIndex = node.Commands.IndexOf(x => x.Name == ReplacePropertyCommand.CommandName);
                if (replaceCommandIndex >= 0)
                {
                    node.Commands.RemoveAt(replaceCommandIndex);
                }

                // Combine components by type, but also append a index in case multiple components of the same types exist in the same collection.
                var componentCount = new Dictionary <Type, int>();
                foreach (var componentNode in node.Children)
                {
                    var type = componentNode.Value.GetType();
                    int count;
                    componentCount.TryGetValue(type, out count);
                    componentNode.CombineKey = $"{type.Name}@{count}";
                    componentCount[type]     = ++count;
                }
            }
            if (typeof(EntityComponent).IsAssignableFrom(node.Type))
            {
                node.AttachedProperties.Add(ReferenceData.Key, new ComponentReferenceViewModel());
            }
            if (typeof(Entity) == node.Type)
            {
                node.AttachedProperties.Add(ReferenceData.Key, new EntityReferenceViewModel());
            }
        }