public override void UpdateNode(INodePresenter node) { if (DictionaryDescriptor.IsDictionary(node.Type)) { if (node.Type.IsGenericType) { var genericArguments = node.Type.GetGenericArguments(); node.AttachedProperties.Add(DictionaryNodeKeyType, genericArguments[0]); } else { foreach (var typeInterface in node.Type.GetInterfaces()) { if (!typeInterface.IsGenericType || typeInterface.GetGenericTypeDefinition() != typeof(IDictionary <,>)) { continue; } var genericArguments = typeInterface.GetGenericArguments(); node.AttachedProperties.Add(DictionaryNodeKeyType, genericArguments[0]); break; } } } }
/// <inheritdoc/> public override bool CanAttach(INodePresenter nodePresenter) { // We are in a dictionary... var dictionaryDescriptor = nodePresenter.Descriptor as DictionaryDescriptor; if (dictionaryDescriptor == null) { return(false); } // ... that is not read-only... var memberCollection = (nodePresenter as MemberNodePresenter)?.MemberAttributes.OfType <MemberCollectionAttribute>().FirstOrDefault() ?? nodePresenter.Descriptor.Attributes.OfType <MemberCollectionAttribute>().FirstOrDefault(); if (memberCollection?.ReadOnly == true) { return(false); } // ... can construct key type... if (!AddNewItemCommand.CanConstruct(dictionaryDescriptor.KeyType)) { return(false); } // ... and can construct value type var elementType = dictionaryDescriptor.ValueType; return(AddNewItemCommand.CanAdd(elementType)); }
/// <inheritdoc/> protected override void ExecuteSync(INodePresenter nodePresenter, object parameter, object preExecuteResult) { var assetNodePresenter = nodePresenter as IAssetNodePresenter; var dictionaryDescriptor = (DictionaryDescriptor)nodePresenter.Descriptor; var value = nodePresenter.Value; NodeIndex newKey; if (dictionaryDescriptor.KeyType == typeof(string)) { newKey = GenerateStringKey(value, dictionaryDescriptor, parameter as string); } else if (dictionaryDescriptor.KeyType.IsEnum) { newKey = new NodeIndex(parameter); } else { newKey = new NodeIndex(Activator.CreateInstance(dictionaryDescriptor.KeyType)); } var newItem = dictionaryDescriptor.ValueType.Default(); var instance = CreateInstance(dictionaryDescriptor.ValueType); if (!AddNewItemCommand.IsReferenceType(dictionaryDescriptor.ValueType) && (assetNodePresenter == null || !assetNodePresenter.IsObjectReference(instance))) { newItem = instance; } nodePresenter.AddItem(newItem, newKey); }
/// <inheritdoc/> public override bool CanAttach(INodePresenter nodePresenter) { // We are in a collection or dictionary... var collectionNode = (nodePresenter as ItemNodePresenter)?.OwnerCollection; var collectionDescriptor = collectionNode?.Descriptor as CollectionDescriptor; var dictionaryDescriptor = collectionNode?.Descriptor as DictionaryDescriptor; if (collectionDescriptor == null && dictionaryDescriptor == null) return false; // ... that is not read-only... var memberCollection = (collectionNode as MemberNodePresenter)?.MemberAttributes.OfType<MemberCollectionAttribute>().FirstOrDefault() ?? collectionNode.Descriptor.Attributes.OfType<MemberCollectionAttribute>().FirstOrDefault(); if (memberCollection?.ReadOnly == true) return false; // ... and supports remove... if (collectionDescriptor != null) { var elementType = collectionDescriptor.ElementType; // We also add the same conditions that for AddNewItem return collectionDescriptor.HasRemoveAt && AddNewItemCommand.CanAdd(elementType); } // TODO: add a HasRemove in the dictionary descriptor and test it! return true; }
/// <inheritdoc /> public override bool CanAttach(INodePresenter nodePresenter) { var assetNodePresenter = nodePresenter as IAssetNodePresenter; var assetPropertyProvider = nodePresenter.PropertyProvider as IAssetPropertyProviderViewModel; return(assetNodePresenter != null& assetPropertyProvider?.RelatedAsset.ServiceProvider.TryGet <ICopyPasteService>() != null); }
/// <inheritdoc/> protected override void ExecuteSync(INodePresenter nodePresenter, object parameter, object preExecuteResult) { foreach (var item in nodePresenter.Children) { item.UpdateValue(parameter); } }
/// <summary> /// Gets the node that corresponds to the given category name, if it exists. Otherwise, returns <c>null</c>. /// </summary> /// <param name="node">The node that contains the category.</param> /// <param name="categoryName">The name of the category.</param> /// <returns>The node that corresponds to the given category name, or <c>null</c>.</returns> public static AssetVirtualNodePresenter GetCategory([NotNull] this INodePresenter node, string categoryName) { var categoryPropertyName = CategoryData.ComputeCategoryNodeName(categoryName); var category = node.Children.FirstOrDefault(x => x.Name == categoryPropertyName); return((AssetVirtualNodePresenter)category); }
/// <inheritdoc/> public override bool CanAttach(INodePresenter nodePresenter) { // We are in a dictionary if (!(nodePresenter.Descriptor is DictionaryDescriptor dictionaryDescriptor)) { return(false); } // It is not read-only var memberCollection = (nodePresenter as MemberNodePresenter)?.MemberAttributes .OfType <MemberCollectionAttribute>() .FirstOrDefault() ?? nodePresenter.Descriptor.Attributes .OfType <MemberCollectionAttribute>() .FirstOrDefault(); if (memberCollection?.ReadOnly == true) { return(false); } // It can construct the key type if (!AddNewItemCommand.CanConstruct(dictionaryDescriptor.KeyType)) { return(false); } // And it can construct the value type var elementType = dictionaryDescriptor.ValueType; return(AddNewItemCommand.CanAdd(elementType)); }
public ItemNodePresenter([NotNull] INodePresenterFactoryInternal factory, IPropertyProviderViewModel propertyProvider, [NotNull] INodePresenter parent, [NotNull] IObjectNode container, Index index) : base(factory, propertyProvider, parent) { if (factory == null) { throw new ArgumentNullException(nameof(factory)); } if (parent == null) { throw new ArgumentNullException(nameof(parent)); } Container = container ?? throw new ArgumentNullException(nameof(container)); Descriptor = TypeDescriptorFactory.Default.Find(container.Descriptor.GetInnerCollectionType()); OwnerCollection = parent; Type = (container.Descriptor as CollectionDescriptor)?.ElementType ?? (container.Descriptor as DictionaryDescriptor)?.ValueType; Index = index; Name = index.ToString(); Order = index.IsInt ? (int?)index.Int : null; // So items are sorted by index instead of string CombineKey = Name; DisplayName = Index.IsInt ? "Item " + Index : Index.ToString(); container.ItemChanging += OnItemChanging; container.ItemChanged += OnItemChanged; AttachCommands(); }
public override void FinalizeTree(INodePresenter root) { var node = root[Title]; var dependencyNode = GetDependencyNode(node.Root); node.AddDependency(dependencyNode, IsRecursive); }
public override void UpdateNode(INodePresenter node) { if (typeof(UPath).IsAssignableFrom(node.Type)) { node.AttachedProperties.Add(ReferenceData.Key, new UPathReferenceViewModel()); } }
/// <inheritdoc/> protected override async void ExecuteSync(INodePresenter nodePresenter, object parameter, object preExecuteResult) { if (!(nodePresenter is AssetMemberNodePresenter assetPresenter)) { return; } var undoRedoService = assetPresenter.Asset.UndoRedoService; var session = assetPresenter.Asset.Session; var serviceProvider = assetPresenter.Asset.ServiceProvider; var scriptSourceCodeProvider = serviceProvider.TryGet <IScriptSourceCodeResolver>(); if (scriptSourceCodeProvider == null) { return; } var template = ScriptTemplateGenerator.GetScriptTemplateAssetDescriptions(session.FindTemplates(TemplateScope.Asset)).FirstOrDefault(); if (template == null) { return; } var viewModel = new TemplateDescriptionViewModel(serviceProvider, template); var customParameters = ScriptTemplateGenerator.GetAssetOverrideParameters(parameter as string, true); var assetViewModel = (await session.ActiveAssetView.RunAssetTemplate(viewModel, null, customParameters)).FirstOrDefault(); if (assetViewModel == null) { return; } //TODO: Maybe situations where this asset/node are no longer valid. if (assetViewModel.IsDeleted) { return; } IEnumerable <Type> componentTypes = scriptSourceCodeProvider.GetTypesFromSourceFile(assetViewModel.AssetItem.FullPath); var componentType = componentTypes.FirstOrDefault(); if (componentType != null) { using (var transaction = session.UndoRedoService.CreateTransaction()) { object component = Activator.CreateInstance(componentType); var index = new NodeIndex(nodePresenter.Children.Count); nodePresenter.AddItem(component); session.UndoRedoService.PushOperation( new AnonymousDirtyingOperation( assetPresenter.Asset.Dirtiables, () => nodePresenter.RemoveItem(component, index), () => nodePresenter.AddItem(component))); session.UndoRedoService.SetName(transaction, "Add new script component."); } } }
public override void UpdateNode(INodePresenter node) { // Adjust Quality range depending on Dither mode // Note: other part of the behavior is in GraphicsCompositorViewModel.OnAssetPropertyChanged (clamp Quality based on Dither) var fxaaEffect = node.Value as FXAAEffect; if (fxaaEffect != null) { var ditherNode = node[nameof(FXAAEffect.Dither)]; // If dither type changes, we will need to update quality sliders again node.AddDependency(ditherNode, false); // Adjust quality range according to dither level var(minQuality, maxQuality) = FXAAEffect.GetQualityRange(fxaaEffect.Dither); node[nameof(FXAAEffect.Quality)].AttachedProperties[NumericData.MinimumKey] = minQuality; node[nameof(FXAAEffect.Quality)].AttachedProperties[NumericData.MaximumKey] = maxQuality; // FXAA: Hide Quality if Dither is set to None (only 9 is a valid value) if (fxaaEffect.Dither == FXAAEffect.DitherType.None) { node[nameof(FXAAEffect.Quality)].IsVisible = false; } } }
/// <inheritdoc/> protected override void ExecuteSync(INodePresenter nodePresenter, object parameter, object preExecuteResult) { var assetNodePresenter = nodePresenter as IAssetNodePresenter; var collectionDescriptor = (CollectionDescriptor)nodePresenter.Descriptor; object itemToAdd; // First, check if parameter is an AbstractNodeEntry var abstractNodeEntry = parameter as AbstractNodeEntry; if (abstractNodeEntry != null) { itemToAdd = abstractNodeEntry.GenerateValue(null); } // Otherwise, assume it's an object else { var elementType = collectionDescriptor.ElementType; itemToAdd = parameter; if (itemToAdd == null) { var instance = ObjectFactoryRegistry.NewInstance(elementType); if (!IsReferenceType(elementType) && (assetNodePresenter == null || !assetNodePresenter.IsObjectReference(instance))) { itemToAdd = instance; } } } nodePresenter.AddItem(itemToAdd); }
/// <inheritdoc/> public override bool CanAttach(INodePresenter nodePresenter) { // We are in a collection... var collectionDescriptor = nodePresenter.Descriptor as CollectionDescriptor; if (collectionDescriptor == null) { return(false); } // ... that is not read-only... var memberCollection = (nodePresenter as MemberNodePresenter)?.MemberAttributes.OfType <MemberCollectionAttribute>().FirstOrDefault() ?? nodePresenter.Descriptor.Attributes.OfType <MemberCollectionAttribute>().FirstOrDefault(); if (memberCollection?.ReadOnly == true) { return(false); } // ... supports add... if (!collectionDescriptor.HasAdd) { return(false); } // ... and can construct element var elementType = collectionDescriptor.ElementType; return(CanConstruct(elementType) || elementType.IsAbstract || elementType.IsNullable() || IsReferenceType(elementType)); }
/// <inheritdoc/> public override bool CanAttach(INodePresenter nodePresenter) { // We are in a dictionary... var collectionNode = (nodePresenter as ItemNodePresenter)?.OwnerCollection; var dictionaryDescriptor = collectionNode?.Descriptor as DictionaryDescriptor; if (dictionaryDescriptor == null) { return(false); } // ... that is not read-only... var memberCollection = (collectionNode as MemberNodePresenter)?.MemberAttributes.OfType <MemberCollectionAttribute>().FirstOrDefault() ?? collectionNode.Descriptor.Attributes.OfType <MemberCollectionAttribute>().FirstOrDefault(); if (memberCollection?.ReadOnly == true) { return(false); } // ... and is indexed by strings... if (dictionaryDescriptor.KeyType != typeof(string)) { return(false); } // ... and supports remove and insert // TODO: ... and can remove items - we don't have this information yet in DictionaryDescriptor return(true); }
private static void UpdateNavigationGroup([NotNull] INodePresenter node, [NotNull] object value) { var entry = (AbstractNodeValue)value; var group = entry.Value as NavigationMeshGroup; var guid = group?.Id ?? Guid.Empty; node.UpdateValue(guid); }
private static void TransferAttachedProperties(INodePresenter node) { if (TypeDescriptorFactory.Default.AttributeRegistry.GetAttribute <InlinePropertyAttribute>(node.Type) != null) { node.AttachedProperties.Set(InlineData.InlineMemberKey, true); } if (node.Value == null) { return; } // Hide the Enabled properties - they must be inlined in their parent node to be usable if (node.Name == "Enabled") { node.IsVisible = false; } var type = node.Value.GetType(); var properties = type.GetProperties(); string mainProperty = null; // Inner properties of a inlined node are usually never expanded, unless explicitly stated var expand = ExpandRule.Never; foreach (var property in properties) { var attribute = property.GetCustomAttribute <InlinePropertyAttribute>(); if (attribute != null) { if (mainProperty != null) { throw new InvalidOperationException("Multiple properties of the same node have the InlinePropertyAttribute."); } mainProperty = property.Name; expand = attribute.Expand; } } if (mainProperty != null) { node.AttachedProperties.Set(DisplayData.AutoExpandRuleKey, expand); node.AttachedProperties.Set(InlineData.InlineMemberKey, true); // If the updater has already been run, the property is already properly named. var mainPropertyNode = node.TryGetChild(InlineData.InlinedProperty) ?? node[mainProperty]; if (mainPropertyNode != null) { TransferAttachedProperty(NumericData.MinimumKey, node, mainPropertyNode); TransferAttachedProperty(NumericData.MaximumKey, node, mainPropertyNode); TransferAttachedProperty(NumericData.SmallStepKey, node, mainPropertyNode); TransferAttachedProperty(NumericData.LargeStepKey, node, mainPropertyNode); TransferAttachedProperty(NumericData.DecimalPlacesKey, node, mainPropertyNode); mainPropertyNode.Rename(InlineData.InlinedProperty); mainPropertyNode.IsVisible = false; node.AddDependency(mainPropertyNode, false); } } }
public void UpdateNode(INodePresenter node, MemberInfo memberInfo) { if (memberInfo == null) { throw new ArgumentNullException(nameof(memberInfo)); } var stepRange = TypeDescriptorFactory.Default.AttributeRegistry.GetAttribute <DataMemberRangeAttribute>(memberInfo); var isNumeric = node.Type.IsNumeric(); // If the type is integral numeric, we don't want decimal places if (node.Type.IsIntegral()) { node.AttachedProperties.Add(NumericData.DecimalPlacesKey, 0); } // If the type is just 8 bits, we want to display it with a slider so we attach small/large steps information if (node.Type == typeof(byte) || node.Type == typeof(sbyte)) { node.AttachedProperties.Add(NumericData.SmallStepKey, 1); node.AttachedProperties.Add(NumericData.LargeStepKey, 5); } // Get the min/max values from the type. if (isNumeric) { node.AttachedProperties.Add(NumericData.MinimumKey, GetMinimum(node.Type)); } if (isNumeric) { node.AttachedProperties.Add(NumericData.MaximumKey, GetMaximum(node.Type)); } if (stepRange != null) { // If we have the attribute, override the attached properties values with what it indicates if (stepRange.Minimum != null) { node.AttachedProperties.Set(NumericData.MinimumKey, stepRange.Minimum); } if (stepRange.Maximum != null) { node.AttachedProperties.Set(NumericData.MaximumKey, stepRange.Maximum); } if (stepRange.SmallStep != null) { node.AttachedProperties.Set(NumericData.SmallStepKey, stepRange.SmallStep); } if (stepRange.LargeStep != null) { node.AttachedProperties.Set(NumericData.LargeStepKey, stepRange.LargeStep); } if (stepRange.DecimalPlaces != null) { node.AttachedProperties.Set(NumericData.DecimalPlacesKey, stepRange.DecimalPlaces); } } }
internal void UpdateNodePresenter(INodePresenter node) { if (node.Value is ModelComponent && node.Parent?.Value is EntityComponentCollection) { // Make sure the materials get refreshed if we change the model. var materials = node[nameof(ModelComponent.Materials)]; var model = node[nameof(ModelComponent.Model)]; materials.AddDependency(model, false); } if (node.Value is IndexingDictionary <Material> && node.Parent?.Value is ModelComponent) { var materialsNode = (IAssetObjectNode)entity.Editor.NodeContainer.GetNode(node.Value); var materials = node; var model = GetReferencedModel(); if (model != null) { int i = 0; foreach (var child in materials.Children.ToList()) { child.IsVisible = false; } var factory = ((IAssetNodePresenter)node).Factory; foreach (var material in model.Materials.ToList()) { var modelMaterial = model.Materials.Count > i ? model.Materials[i] : null; var materialName = modelMaterial?.Name ?? $"(Material {i + 1})"; var index = new Index(i); var virtualMaterial = factory.CreateVirtualNodePresenter(node, material.Name + "___Virtual", typeof(Material), i, () => GetMaterial(materialsNode, index), x => SetMaterial(materialsNode, index, (Material)x), () => materialsNode.BaseNode != null, () => materialsNode.IsItemInherited(index), () => materialsNode.IsItemOverridden(index)); // Do not put the FetchAssetCommand, we need a custom implementation for this one. // Do not put the CreateNewInstanceCommand neither, otherwise it will display the "Clear reference" button which doesn't make sense here (null => disabled) virtualMaterial.Commands.RemoveWhere(x => x.Name == FetchAssetCommand.CommandName || x.Name == CreateNewInstanceCommand.CommandName); // Override the FetchAsset command to be able to fetch the model material when it is null in the component var fetchAsset = new AnonymousNodePresenterCommand(FetchAssetCommand.CommandName, (x, param) => FetchMaterial(materialsNode, index)); virtualMaterial.Commands.Add(fetchAsset); virtualMaterial.DisplayName = materialName; virtualMaterial.RegisterAssociatedNode(new NodeAccessor(materialsNode, index)); var enabledNode = factory.CreateVirtualNodePresenter(virtualMaterial, "Enabled", typeof(bool), 0, () => IsMaterialEnabled(materialsNode, index), x => SetMaterialEnabled(materialsNode, index, (bool)x), () => materialsNode.BaseNode != null, () => materialsNode.IsItemInherited(index), () => materialsNode.IsItemOverridden(index)); enabledNode.RegisterAssociatedNode(new NodeAccessor(materialsNode, index)); enabledNode.IsVisible = false; i++; } } } }
public override void UpdateNode(INodePresenter node) { if (node.Name == nameof(Types.DependentPropertyContainer.Title)) { var instance = (Types.DependentPropertyContainer)node.Root.Value; node.AttachedProperties.Set(TestData, instance.Instance.Name); node.AttachedProperties.Set(UpdateCount, count++); } }
public sealed override void FinalizeTree(INodePresenter root) { var assetNode = root as IAssetNodePresenter; if (assetNode != null) { FinalizeTree(assetNode); } }
public sealed override void UpdateNode(INodePresenter node) { var assetNode = node as IAssetNodePresenter; if (assetNode != null) { UpdateNode(assetNode); } }
protected override bool ShouldCreateMemberPresenter(INodePresenter parent, IMemberNode member, IPropertyProviderViewModel propertyProvider) { // Don't construct members of object references if (((IAssetNodePresenter)parent).IsObjectReference(parent.Value)) { return(false); } return(base.ShouldCreateMemberPresenter(parent, member, propertyProvider)); }
/// <inheritdoc/> protected override void ExecuteSync(INodePresenter nodePresenter, object parameter, object preExecuteResult) { var currentValue = nodePresenter.Value; if (currentValue != null) { // TODO: we should display the path instead of the name for the title session.ServiceProvider.Get <IEditorDialogService>().AssetEditorsManager.OpenCurveEditorWindow(currentValue, nodePresenter.Name); } }
/// <inheritdoc/> public override void UpdateNodePresenter([NotNull] INodePresenter node) { // TODO: make an interface for component view models so they present these methods if (node == null) { throw new ArgumentNullException(nameof(node)); } base.UpdateNodePresenter(node); modelComponent.UpdateNodePresenter(node); }
/// <inheritdoc/> protected override void ExecuteSync(INodePresenter nodePresenter, object parameter, object preExecuteResult) { var currentValue = nodePresenter.Value; var collectionNode = ((ItemNodePresenter)nodePresenter).OwnerCollection; collectionNode.RemoveItem(nodePresenter.Value, nodePresenter.Index); var newName = AddPrimitiveKeyCommand.GenerateStringKey(collectionNode.Value, collectionNode.Descriptor, (string)parameter); collectionNode.AddItem(currentValue, newName); }
public override void FinalizeTree(INodePresenter root) { // Note: this needs to be done in FinalizeTree, because if the inlined property itself is modified, UpdateNode won't be called again on the parent property, TransferAttachedProperties(root); foreach (var node in root.Children.SelectDeep(x => x.Children)) { TransferAttachedProperties(node); } base.FinalizeTree(root); }
public override void UpdateNode(INodePresenter node) { var settingsKey = node.Value as PackageSettingsWrapper.SettingsKeyWrapper; if (settingsKey != null) { var acceptableValues = settingsKey.Key.AcceptableValues.ToList(); node.AttachedProperties.Add(SettingsData.HasAcceptableValuesKey, acceptableValues.Count > 0); node.AttachedProperties.Add(SettingsData.AcceptableValuesKey, acceptableValues); } }
/// <inheritdoc/> protected override void ExecuteSync(INodePresenter nodePresenter, object parameter, object preExecuteResult) { var itemNode = (ItemNodePresenter)nodePresenter; var collectionNode = itemNode.OwnerCollection; var indices = (Tuple <int, int>)parameter; var sourceIndex = new NodeIndex(indices.Item1); var targetIndex = new NodeIndex(indices.Item2); var value = itemNode.Value; collectionNode.RemoveItem(value, sourceIndex); collectionNode.AddItem(value, targetIndex); }