Exemple #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="EditorNavigationViewModel"/> class.
        /// </summary>
        /// <param name="editor"></param>
        /// <param name="serviceProvider">The service provider for this view model.</param>
        /// <param name="controller">The controller object for the related editor game.</param>
        public EditorNavigationViewModel([NotNull] IViewModelServiceProvider serviceProvider, [NotNull] IEditorGameController controller, [NotNull] EntityHierarchyEditorViewModel editor)
            : base(serviceProvider)
        {
            if (controller == null)
            {
                throw new ArgumentNullException(nameof(controller));
            }
            this.editor     = editor;
            this.controller = controller;

            ToggleAllGroupsCommand = new AnonymousCommand <bool>(ServiceProvider, value => Visuals.ForEach(x => x.IsVisible = value));

            gameSettingsAsset = editor.Session.AllAssets.FirstOrDefault(x => x.AssetType == typeof(GameSettingsAsset));
            if (gameSettingsAsset != null)
            {
                gameSettingsAsset.PropertyGraph.ItemChanged += GameSettingsPropertyGraphOnItemChanged;
                gameSettingsAsset.PropertyGraph.Changed     += GameSettingsPropertyGraphOnChanged;
                UpdateNavigationMeshLayers();
            }

            editor.Dispatcher.InvokeTask(async() =>
            {
                await controller.GameContentLoaded;
                service = controller.GetService <EditorGameNavigationMeshService>();
                UpdateNavigationMeshLayers();
            });
        }
 public EntityFolderViewModel([NotNull] EntityHierarchyEditorViewModel editor, [NotNull] EntityHierarchyViewModel asset, string name, [NotNull] IEnumerable <EntityDesign> entities)
     : base(editor, asset, entities)
 {
     this.name     = name;
     Id            = new AbsoluteId(Asset.Id, Guid.NewGuid());
     RenameCommand = new AnonymousCommand(ServiceProvider, () => IsEditing = true);
 }
Exemple #3
0
        public EntityViewModel([NotNull] EntityHierarchyEditorViewModel editor, [NotNull] EntityHierarchyViewModel asset, [NotNull] EntityDesign entityDesign)
            : base(editor, asset, GetOrCreateChildPartDesigns((EntityHierarchyAssetBase)asset.Asset, entityDesign), entityDesign.Entity)
        {
            if (entityDesign.Entity == null)
            {
                throw new ArgumentException(@"entity must contain a non-null asset entity.", nameof(entityDesign));
            }

            EntityDesign = entityDesign;

            var assetNode = Editor.NodeContainer.GetOrCreateNode(entityDesign.Entity);

            nameNodeBinding       = new MemberGraphNodeBinding <string>(assetNode[nameof(Entity.Name)], nameof(Name), OnPropertyChanging, OnPropertyChanged, Editor.UndoRedoService);
            componentsNodeBinding = new ObjectGraphNodeBinding <EntityComponentCollection>(assetNode[nameof(Entity.Components)].Target, nameof(Components), OnPropertyChanging, OnPropertyChanged, Editor.UndoRedoService, false);

            modelComponent     = new ModelComponentViewModel(ServiceProvider, this);
            particleComponent  = new ParticleSystemComponentViewModel(ServiceProvider, this);
            cameraComponent    = new CameraComponentViewModel(ServiceProvider, this);
            transformationNode = Editor.NodeContainer.GetNode(AssetSideEntity.Transform)[nameof(TransformComponent.Children)].Target;
            transformationNode.ItemChanging += TransformChildrenChanging;
            transformationNode.ItemChanged  += TransformChildrenChanged;
            RenameCommand        = new AnonymousCommand(ServiceProvider, () => IsEditing = true);
            FocusOnEntityCommand = new AnonymousCommand(ServiceProvider, FocusOnEntity);

            UpdateSourcePrefab();
            var basePrefabNode = Editor.NodeContainer.GetNode(EntityDesign)[nameof(EntityDesign.Base)];

            basePrefabNode.ValueChanged += BasePrefabChanged;
        }
 protected EntityHierarchyRootViewModel([NotNull] EntityHierarchyEditorViewModel editor, [NotNull] EntityHierarchyViewModel asset, [NotNull] string name)
     : base(editor, asset, asset.Asset.Hierarchy.EnumerateRootPartDesigns(), null)
 {
     this.name        = name ?? throw new ArgumentNullException(nameof(name));
     rootEntitiesNode = Editor.Session.AssetNodeContainer.GetNode(EntityHierarchy.Hierarchy)[nameof(AssetCompositeHierarchyData <EntityDesign, Entity> .RootParts)].Target;
     rootEntitiesNode.ItemChanging += RootEntitiesChanging;
     rootEntitiesNode.ItemChanged  += RootEntitiesChanged;
     entitiesNode              = Editor.Session.AssetNodeContainer.GetNode(EntityHierarchy.Hierarchy)[nameof(AssetCompositeHierarchyData <EntityDesign, Entity> .Parts)].Target;
     entitiesNode.ItemChanged += EntitiesChanged;
 }
        protected EntityHierarchyElementViewModel([NotNull] EntityHierarchyEditorViewModel editor, [NotNull] EntityHierarchyViewModel asset, [NotNull] IEnumerable <EntityDesign> childEntities, object assetSideInstance)
            : base(editor, asset, childEntities)
        {
            this.assetSideInstance = assetSideInstance;
            LoadCommand            = new AnonymousTaskCommand <bool>(ServiceProvider, recursive => RequestLoading(!IsLoaded, recursive));
            LockCommand            = new AnonymousTaskCommand <bool>(ServiceProvider, recursive => RequestLocking(!IsLocked, recursive));

            DependentProperties.Add(nameof(IsLoaded), new[] { nameof(IsSelectable) });
            DependentProperties.Add(nameof(IsLocked), new[] { nameof(IsSelectable) });
        }
        protected EntityHierarchyItemViewModel([NotNull] EntityHierarchyEditorViewModel editor, [NotNull] EntityHierarchyViewModel asset, [NotNull] IEnumerable <EntityDesign> childEntities)
            : base(editor, asset)
        {
            if (childEntities == null)
            {
                throw new ArgumentNullException(nameof(childEntities));
            }

            // note: we want to ignore case and diacritics (e.g. accentuation) when sorting the folders
            Folders = new AutoUpdatingSortedObservableCollection <EntityFolderViewModel>((x, y) => string.Compare(x.Name, y.Name, StringComparison.InvariantCultureIgnoreCase));

            // Note: we make sure that empty folders and null folders are grouped together
            // TODO: implement a more robust folder grouping method that trims, etc.
            // TODO: also ensure that empty folder are serialized as null (or vice-versa) to avoid this kind of issue
            foreach (var folderGroup in childEntities.GroupBy(x => !string.IsNullOrWhiteSpace(x.Folder) ? x.Folder : null).OrderBy(x => x.Key))
            {
                if (!EntityFolderViewModel.GenerateFolder(this, folderGroup.Key, folderGroup))
                {
                    foreach (var child in folderGroup)
                    {
                        var viewModel = (EntityViewModel)Editor.CreatePartViewModel(Asset, child);
                        subEntities.Add(viewModel);
                    }
                }
            }

            AddItems(Folders);
            AddItems(subEntities);

            // We register the collection changed handler after having added already-existing children
            Folders.CollectionChanged     += FolderCollectionChanged;
            subEntities.CollectionChanged += SubEntityCollectionChanged;

            // Add policies for adding/inserting assets
            // TODO: make it work with plugins (discovery, registration, override...)
            addAssetPolicies = new List <IAddAssetPolicy>
            {
                new AddModelAssetPolicy <ModelAsset>(),
                new AddModelAssetPolicy <PrefabModelAsset>(),
                new AddModelAssetPolicy <ProceduralModelAsset>(),
                new AddPrefabAssetPolicy(),
                new AddSceneAssetPolicy(),
                new AddScriptSourceFileAssetPolicy(),
                new AddSpriteSheetAssetPolicy(),
                new AddSpriteStudioModelAssetPolicy(),
                new AddTextureAssetPolicy(),
                new AddVideoAssetPolicy(),
                new AddUIPageAssetPolicy(),
            };
        }
Exemple #7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="EditorNavigationViewModel"/> class.
        /// </summary>
        /// <param name="serviceProvider">The service provider for this view model.</param>
        /// <param name="controller">The controller object for the related editor game.</param>
        public EditorLightingViewModel([NotNull] IViewModelServiceProvider serviceProvider, [NotNull] IEditorGameController controller, [NotNull] EntityHierarchyEditorViewModel editor)
            : base(serviceProvider)
        {
            if (controller == null)
            {
                throw new ArgumentNullException(nameof(controller));
            }
            if (editor == null)
            {
                throw new ArgumentNullException(nameof(editor));
            }

            this.controller = controller;
            this.editor     = editor;

            RequestLightProbesComputeCommand = new AnonymousTaskCommand(ServiceProvider, () => RebuildLightProbes(LightProbeBounces));
            RequestLightProbesResetCommand   = new AnonymousTaskCommand(ServiceProvider, () => RebuildLightProbes(0));

            CaptureCubemapCommand = new AnonymousTaskCommand(ServiceProvider, CaptureCubemap);
        }
 public EntityHierarchyElementChangePropagator([NotNull] EntityHierarchyEditorViewModel editor, [NotNull] EntityViewModel owner, [NotNull] Entity assetSidePart)
     : base(editor, owner, assetSidePart)
 {
 }
Exemple #9
0
        private async void TransformChildrenChanged(object sender, ItemChangeEventArgs e)
        {
            Entity childEntity;

            switch (e.ChangeType)
            {
            case ContentChangeType.CollectionAdd:
                childEntity = ((TransformComponent)e.NewValue).Entity;
                Editor.Logger.Verbose($"Add {childEntity.Name} ({childEntity.Id}) to the Entities collection");
                break;

            case ContentChangeType.CollectionRemove:
                childEntity = ((TransformComponent)e.OldValue).Entity;
                Editor.Logger.Verbose($"Remove {childEntity.Name} ({childEntity.Id}) from the Entities collection");
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            // Update view model
            if (e.ChangeType == ContentChangeType.CollectionAdd)
            {
                // TODO: can be factorized with what EntityHierarchyRootViewModel is doing, through a base method. There are a few differences though.
                var component = (TransformComponent)e.NewValue;
                var entity    = EntityHierarchy.Hierarchy.Parts[component.Entity.Id];
                var element   = (EntityViewModel)Editor.CreatePartViewModel(Asset, entity);
                var index     = e.Index.Int;
                var parent    = FindOrCreateFolder(entity.Folder);
                parent.InsertEntityViewModel(element, parent.FindIndexInParent(index, EntityDesign.Entity.Transform.Children.Select(x => EntityHierarchy.Hierarchy.Parts[x.Entity.Id])));

                // FIXME: when we allow loading/unloading single entities, this should be implemented in OnLoadingRequested. Then just call RequestLoading(true).
                // Check if the container root is loaded
                if (EntityHierarchyEditorViewModel.GetRoot(this).IsLoaded)
                {
                    var children = element.TransformChildren.BreadthFirst(x => x.TransformChildren).ToList();
                    // Set the new entity and its children as 'loading'
                    element.IsLoading = true;
                    foreach (var child in children)
                    {
                        child.IsLoading = true;
                    }
                    // Add the entity to the game (actually load the entity and its children)
                    await Editor.Controller.AddPart(this, element.AssetSideEntity);

                    // Set the new entity and its children as 'loaded'
                    element.IsLoaded = true;
                    foreach (var child in children)
                    {
                        child.IsLoaded = true;
                    }
                    // Manually notify the game-side scene
                    element.NotifyGameSidePartAdded().Forget();
                    foreach (var child in children)
                    {
                        child.NotifyGameSidePartAdded().Forget();
                    }
                }
            }
            else if (e.ChangeType == ContentChangeType.CollectionRemove)
            {
                var component = (TransformComponent)e.OldValue;
                var partId    = new AbsoluteId(Asset.Id, component.Entity.Id);
                var element   = (EntityViewModel)Editor.FindPartViewModel(partId);
                if (element == null)
                {
                    throw new InvalidOperationException($"{nameof(element)} cannot be null");
                }
                RemoveEntityViewModel(element);
                // FIXME: when we allow loading/unloading single entities, this should be implemented in OnLoadingRequested. Then just call RequestLoading(false).
                if (element.IsLoaded)
                {
                    element.IsLoading = true;
                    Editor.Controller.RemovePart(this, element.AssetSideEntity).Forget();
                    element.IsLoaded = false;
                }
            }
        }