Beispiel #1
0
            private IEnumerable <Tuple <string, string, string> > SortHierarchyLevels(IEnumerable <IViewModelNode> hierarchyLevelNodes)
            {
                List <Tuple <string, string, string> > list = new List <Tuple <string, string, string> >();

                foreach (IViewModelNode node in hierarchyLevelNodes)
                {
                    list.Add(new Tuple <string, string, string>(ViewModelNode.GetTopAncestor(node).Text, node.ParentNode.Text, node.Text));
                }
                return(list);
            }
Beispiel #2
0
 private async Task RefreshAsync(ViewModelNode node)
 {
     if (!node.CanReload)
     {
         // Try reloading parent instead.
         await RefreshAsync(node.Parent)
         .ConfigureAwait(true);
     }
     else
     {
         // Force-reload children and discard result.
         await node.GetFilteredNodesAsync(true)
         .ConfigureAwait(true);
     }
 }
        private IViewModelNode CreateProperty(object obj)
        {
            var context   = new ViewModelContext();
            var contextUI = new ViewModelContext();

            context.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator());
            // add some more here...

            var testModel = new ViewModelNode("Root", obj);

            var view = ObservableViewModelNode.CreateObservableViewModel(contextUI, testModel);

            ObservableViewModelNode.Refresh(contextUI, context, new ViewModelState());

            return(view);
        }
        private IViewModelNode CreateProperty(object obj)
        {
            var context = new ViewModelContext();
            var contextUI = new ViewModelContext();

            context.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator());
            // add some more here...

            var testModel = new ViewModelNode("Root", obj);

            var view = ObservableViewModelNode.CreateObservableViewModel(contextUI, testModel);

            ObservableViewModelNode.Refresh(contextUI, context, new ViewModelState());

            return view;
        }
        private IViewModelNode CreateSampleTree()
        {
            MyDateTime now = MyDateTime.FromDateTime(DateTime.Now);

            var context   = new ViewModelContext(new ViewModelGlobalContext());
            var contextUI = new ViewModelContext(new ViewModelGlobalContext());

            context.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator());
            // add some more here...

            var testModel = new ViewModelNode("Root", now);

            var view = ObservableViewModelNode.CreateObservableViewModel(contextUI, testModel);

            ObservableViewModelNode.Refresh(contextUI, context, new ViewModelState());

            return(view);
        }
        private IViewModelNode CreateSampleTree()
        {
            MyDateTime now = MyDateTime.FromDateTime(DateTime.Now);

            var context = new ViewModelContext(new ViewModelGlobalContext());
            var contextUI = new ViewModelContext(new ViewModelGlobalContext());

            context.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator());
            // add some more here...

            var testModel = new ViewModelNode("Root", now);

            var view = ObservableViewModelNode.CreateObservableViewModel(contextUI, testModel);

            ObservableViewModelNode.Refresh(contextUI, context, new ViewModelState());

            return view;
        }
        protected void OnNewViewModel(object sender, EventArgs args)
        {
            var dlg = new NewFrm();

            if (dlg.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            var newName = dlg.GetName();
            if (string.IsNullOrWhiteSpace(newName))
            {
                MessageBox.Show("名称不能为空");
                return;
            }

            var fileName = System.IO.Path.Combine(this.Path, newName) + Dict.Extenstions.ViewModel_Extension;
            if (File.Exists(fileName))
            {
                MessageBox.Show("文件已经存在");
                return;
            }

            var writer = File.CreateText(fileName);
            writer.Flush();
            writer.Close();

            var dataModel = new ViewModelNode();

            dataModel.Parent = this;

            dataModel.FileName = System.IO.Path.GetFileNameWithoutExtension(fileName);
            dataModel.Name = dataModel.Text = System.IO.Path.GetFileNameWithoutExtension(fileName);
            dataModel.FullName = fileName;

            this.TreeNode.Expand();

            var cmd = CommandHostManager.Instance().Get<NewViewModelCommand>
                (CommandHostManager.HostType.ViewModel, Dict.Commands.NewViewModel);

            cmd.File = dataModel.FullName;

            cmd.Execute();

            //cmdHost.RunCommand(Dict.Commands.NewXmlModel);
        }
        protected override void LoadFile()
        {
            //var dir = new DirectoryInfo(this.Path);

            //foreach (var f in dir.GetFiles())
            //{
            //    if (f.Extension == Dict.Extenstion.XmlModel_Extension)
            //    {
            //        var file_node = NodeFactory.Create(Dict.NodeType.XmlModel, f.Name, f.Name);
            //        file_node.Parent = this;
            //    }
            //}

            var directory = new DirectoryInfo(Path);

            foreach (var dm in directory.GetFiles("*" + Dict.Extenstions.ViewModel_Extension))
            {
                var dmNode = new ViewModelNode();
                dmNode.FullName = dm.FullName;
                dmNode.Parent = this;
            }
        }
        public void GenerateChildren(ViewModelContext context, IViewModelNode viewModelNode, ref bool handled)
        {
            bool handleValueType = false;

            if (viewModelNode.NodeValue is MicroThread)
            {
                var microThread = (MicroThread)viewModelNode.NodeValue;
                var script      = microThread.Get(ScriptManager.ScriptProperty);

                viewModelNode.Content = new EnumerableViewModelContent <ViewModelReference>(() => new[] { new ViewModelReference(script, true) });

                handled = true;
            }
            else if (viewModelNode.NodeValue is IScript)
            {
                var script = (IScript)viewModelNode.NodeValue;

                // Expose all variables of IScript (defined by user)
                foreach (var property in script.GetType().GetProperties())
                {
                    if (property.PropertyType != typeof(int) && property.PropertyType != typeof(float))
                    {
                        continue;
                    }

                    viewModelNode.Children.Add(new ViewModelNode(property.Name, new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), property)));
                }
                handled = true;
            }
            else if (viewModelNode.NodeValue is Entity)
            {
                ViewModelNode componentsViewModelNode;

                viewModelNode.Children.Add(new ViewModelNode("Name", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(Entity).GetProperty("Name"))));
                viewModelNode.Children.Add(new ViewModelNode("Guid", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(Entity).GetProperty("Guid"))));
                viewModelNode.Children.Add(componentsViewModelNode = new ViewModelNode("Components", EnumerableViewModelContent.FromUnaryLambda <ViewModelReference, Entity>(new ParentNodeValueViewModelContent(),
                                                                                                                                                                             (entity) => entity.Properties
                                                                                                                                                                             .Select(x => x.Value)
                                                                                                                                                                             .OfType <EntityComponent>()
                                                                                                                                                                             .Select(x => new ViewModelReference(x, true)))));

                var availableKeysContent = new RootViewModelContent(null, typeof(string[]));
                componentsViewModelNode.Children.Add(new ViewModelNode("AvailableKeys", availableKeysContent));

                componentsViewModelNode.Children.Add(new ViewModelNode("RequestKeys", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                {
                    var availableComponentKeys = new List <string>();

                    // TODO: Improve component keys enumeration (maybe need a registry?)
                    // For now, scan assemblies for all types inheriting from EntityComponent
                    foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
                    {
                        foreach (var type in assembly.GetTypes())
                        {
                            if (type.IsSubclassOf(typeof(EntityComponent)) &&
                                type.GetField("Key", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy) != null)
                            {
                                availableComponentKeys.Add(type.AssemblyQualifiedName);
                            }
                        }
                    }

                    availableKeysContent.Value = availableComponentKeys.ToArray();
                }))));

                componentsViewModelNode.Children.Add(new ViewModelNode("Add", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                {
                    var entity = (Entity)viewModel2.Parent.Parent.NodeValue;
                    var componentType = Type.GetType((string)parameter);

                    // For now, assume it will be stored in a PropertyKey inside the actual component named "Key"
                    var componentKeyField = componentType.GetField("Key", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
                    entity.SetObject((PropertyKey)componentKeyField.GetValue(null), Activator.CreateInstance(componentType));
                }))));

                handled = true;
            }
            else if (viewModelNode.NodeValue is EntityComponent)
            {
                viewModelNode.PropertyName = "EntityComponent";
                var component = (EntityComponent)viewModelNode.NodeValue;
                // Would be better higher in the hierarchy, but it would complicate model
                var propertyKey     = component.Entity.Properties.First(x => x.Value == component).Key;
                var propertyKeyName = propertyKey.OwnerType.Name;
                viewModelNode.Children.Add(new ViewModelNode("PropertyKeyName", new RootViewModelContent(propertyKeyName)));
                viewModelNode.Children.Add(new ViewModelNode("Remove", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                {
                    component.Entity.SetObject(propertyKey, null);
                }))));

                var componentViewModel = new ViewModelNode("Component", component);
                viewModelNode.Children.Add(componentViewModel);
                if (component is TransformationComponent)
                {
                    componentViewModel.Children.Add(new ViewModelNode("WorldMatrix", new FieldInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(TransformationComponent).GetField("WorldMatrix"))).GenerateChildren(context));

                    // TODO: How to switch view model depending on TransformationComponent.Values type? Or should we always expose everything?
                    componentViewModel.Children.Add(new ViewModelNode("LocalMatrix", new FieldInfoViewModelContent(new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(TransformationComponent).GetProperty("Value")), typeof(TransformationValue).GetField("LocalMatrix"))).GenerateChildren(context));

                    //if (((TransformationComponent)component).Values is TransformationTRS)
                    {
                        componentViewModel.Children.Add(new ViewModelNode("Translation", new FieldInfoViewModelContent(new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(TransformationComponent).GetProperty("Value")), typeof(TransformationTRS).GetField("Translation"))).GenerateChildren(context));
                        componentViewModel.Children.Add(new ViewModelNode("Rotation", new FieldInfoViewModelContent(new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(TransformationComponent).GetProperty("Value")), typeof(TransformationTRS).GetField("Rotation"))).GenerateChildren(context));
                        componentViewModel.Children.Add(new ViewModelNode("Scaling", new FieldInfoViewModelContent(new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(TransformationComponent).GetProperty("Value")), typeof(TransformationTRS).GetField("Scaling"))).GenerateChildren(context));
                    }

                    componentViewModel.Children.Add(new ViewModelNode("Parent", LambdaViewModelContent <ViewModelReference> .FromOperand <EntityComponent>(new ParentNodeValueViewModelContent(), x => new ViewModelReference(x.Entity, false))));
                    componentViewModel.Children.Last().Children.Add(new ViewModelNode("SetAsRoot", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                    {
                        context.ViewModelByGuid.Clear();
                        context.Root = context.GetModelView(((TransformationComponent)component).Parent.Entity).Children.First(x => x.PropertyName == "Components");
                    }))));
                }
                if (component is ModelComponent)
                {
                    componentViewModel.Children.Add(new ViewModelNode("Parameters", ((ModelComponent)component).MeshParameters).GenerateChildren(context));
                    //componentViewModel.Children.Add(new ViewModelNode(
                    //    "MeshParameters",
                    //    EnumerableViewModelContent.FromUnaryLambda<ViewModelReference, ModelComponent>(
                    //        new ParentNodeValueViewModelContent(),
                    //        (ModelComponent) => ModelComponent.MeshParameters.Keys.Select(key => new ViewModelReference(Tuple.Create(ModelComponent.MeshParameters, key), true)))));
                }
                if (component is LightComponent)
                {
                    componentViewModel.Children.Add(new ViewModelNode("Type", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightComponent).GetProperty("Type"))).GenerateChildren(context));
                    componentViewModel.Children.Add(new ViewModelNode("ShadowMap", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightComponent).GetProperty("ShadowMap"))).GenerateChildren(context));
                    componentViewModel.Children.Add(new ViewModelNode("Deferred", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightComponent).GetProperty("Deferred"))).GenerateChildren(context));
                    componentViewModel.Children.Add(new ViewModelNode("Intensity", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightComponent).GetProperty("Intensity"))).GenerateChildren(context));
                    componentViewModel.Children.Add(new ViewModelNode("DecayStart", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightComponent).GetProperty("DecayStart"))).GenerateChildren(context));
                    componentViewModel.Children.Add(new ViewModelNode("Color", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightComponent).GetProperty("Color"))).GenerateChildren(context));
                    componentViewModel.Children.Add(new ViewModelNode("LightDirection", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightComponent).GetProperty("LightDirection"))).GenerateChildren(context));
                }
                if (component is LightShaftsComponent)
                {
                    componentViewModel.Children.Add(new ViewModelNode("Color", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightShaftsComponent).GetProperty("Color"))).GenerateChildren(context));
                    //componentViewModel.Children.Add(new ViewModelNode("LightShaftsBoundingBoxes", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightShaftsComponent).GetProperty("LightShaftsBoundingBoxes"))).GenerateChildren(context));
                }

                // Else try to display it using auto-display
                AutoDisplayComponent(context, viewModelNode, component);

                handled = true;
            }
            else if (viewModelNode.NodeValue is ParameterCollection)
            {
                viewModelNode.Content = EnumerableViewModelContent.FromUnaryLambda <ViewModelReference, ParameterCollection>(new NodeValueViewModelContent(), (parameterCollection) =>
                                                                                                                             parameterCollection.Keys.Where(key => key.PropertyType.IsValueType).Select(key =>
                {
                    if (key.PropertyType.IsValueType)
                    {
                        // For value type, generated tree won't change so make value based on key only.
                        return(new ViewModelReference(Tuple.Create(parameterCollection, key), true));
                    }
                    else
                    {
                        // TODO: resources currently ignored (until fixed)

                        // For reference type, make value dependent on actual value reference and source.
                        // This will trigger a regeneration for reference change (i.e. new texture bound).
                        // Useful since asset type/state might be different.
                        var value       = parameterCollection.GetObject(key);
                        var valueSource = engineContext.AssetManager.Url.Get(value);
                        return(new ViewModelReference(Tuple.Create(parameterCollection, key, valueSource), true));
                    }
                }));

                var availableKeysContent = new RootViewModelContent(null, typeof(string[]));
                viewModelNode.Children.Add(new ViewModelNode("AvailableKeys", availableKeysContent));

                viewModelNode.Children.Add(new ViewModelNode("RequestKeys", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                {
                    var parameterCollection = (ParameterCollection)viewModel2.Parent.NodeValue;
                    var effectMesh = viewModel2.Parent.Parent.NodeValue as EffectMesh;
                    if (effectMesh != null)
                    {
                        var availableKeys = effectMesh.Effect.Passes.SelectMany(x => x.DefaultParameters.Parameters.Select(y => y.Key)).Distinct().Where(x => !parameterCollection.IsValueOwner(x)).Select(x => x.Name).ToArray();
                        availableKeysContent.Value = availableKeys;
                    }
                }))));

                viewModelNode.Children.Add(new ViewModelNode("Add", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                {
                    var effectMesh = viewModel2.Parent.Parent.NodeValue as EffectMesh;
                    if (effectMesh != null)
                    {
                        var key = effectMesh.Effect.Passes.SelectMany(x => x.DefaultParameters.Parameters.Select(y => y.Key)).FirstOrDefault(x => x.Name == (string)parameter);
                        if (key != null)
                        {
                            effectMesh.Parameters.SetDefault(key);
                        }
                    }
                }))));
            }
            else if (viewModelNode.NodeValue is EffectMesh)
            {
                viewModelNode.PropertyName = "Mesh";
                viewModelNode.Children.Add(new ViewModelNode("Effect", LambdaViewModelContent <string> .FromParent <EffectMesh>(x => x.EffectMeshData.EffectData.Name, (x, effectName) => x.EffectMeshData.EffectData.Name = effectName)));
                viewModelNode.Children.Add(new ViewModelNode("Parameters", ((EffectMesh)viewModelNode.NodeValue).Parameters).GenerateChildren(context));
                //viewModelNode.Children.Add(new ViewModelNode("MeshData", LambdaViewModelContent<ViewModelReference>.FromParent<MeshData>(effectMeshData => new ViewModelReference(effectMeshData.MeshData, true))));
                handled = true;
            }
            else if (viewModelNode.NodeValue is ContentData || typeof(ContentData).IsAssignableFrom(viewModelNode.Type))
            {
                if (viewModelNode.NodeValue is ContentData)
                {
                    viewModelNode.Content = new NodeValueViewModelContent();
                }

                if (viewModelNode.Value != null)
                {
                    viewModelNode.Children.Add(new ViewModelNode("Url", new LambdaViewModelContent <string>(new ParentValueViewModelContent(),
                                                                                                            x => engineContext.AssetManager.Url.Get((x.Value)),
                                                                                                            (x, y) =>
                    {
                        var nodeValue = x.OwnerNode.Parent.NodeValue;
                    })));

                    viewModelNode.Children.Add(new ViewModelNode("ChangeUrl", new RootViewModelContent((ExecuteCommand)(async(viewModel2, parameter) =>
                    {
                        var dropParameters = (DropCommandParameters)parameter;
                        var parameterInfo = (Tuple <ParameterCollection, ParameterKey, ContentData>)viewModel2.Parent.Parent.NodeValue;

                        var parameterCollection = parameterInfo.Item1;

                        var textureData = await engineContext.AssetManager.LoadAsync <Image>((string)dropParameters.Data);
                        //parameter.Item1.SetObject(parameter.Item2, );
                        //parameterCollection.Remove(parameterInfo.Item2);

                        //var texture = engineContext.ContentManager.Convert<ITexture, Image>(textureData);
                        Texture texture;
                        throw new NotImplementedException();

                        parameterCollection.SetObject(parameterInfo.Item2, texture);
                    }))));

                    if (viewModelNode.Type == typeof(Image))
                    {
                        Image        thumbnail   = null;
                        Task <Image> textureData = null;

                        viewModelNode.Children.Add(new ViewModelNode("Thumbnail", new LambdaViewModelContent <Image>(new ParentValueViewModelContent(), (viewModelContent) =>
                        {
                            if (textureData == null)
                            {
                                var textureDataNew = viewModelContent.Value as Image;
                                if (engineContext.AssetManager.Url.Get(textureDataNew) != null)
                                {
                                    textureData = engineContext.AssetManager.LoadAsync <Image>(engineContext.AssetManager.Url.Get(textureDataNew));
                                    textureData.ContinueWith(task =>
                                    {
                                        thumbnail = task.Result;
                                        viewModelContent.OwnerNode.Content.SerializeFlags |= ViewModelContentSerializeFlags.Static;
                                    });
                                }
                            }
                            return(thumbnail);
                        })));
                    }
                }

                handled = true;
            }
            else if (viewModelNode.NodeValue is MeshData)
            {
                handled = true;
            }
            else if (viewModelNode.NodeValue is Tuple <ParameterCollection, ParameterKey, ContentData> )
            {
                var value = (Tuple <ParameterCollection, ParameterKey, ContentData>)viewModelNode.NodeValue;

                // Ignore namespace and class name for key name
                viewModelNode.PropertyName = value.Item2.Name;
                if (viewModelNode.PropertyName.Contains('.'))
                {
                    viewModelNode.PropertyName = viewModelNode.PropertyName.Substring(viewModelNode.PropertyName.LastIndexOf('.') + 1);
                }

                viewModelNode.Content = new NullViewModelContent(typeof(Image));
                if (value.Item3 != null)
                {
                    viewModelNode.Children.Add(new ViewModelNode("ObjectRef", new RootViewModelContent(value.Item3)
                    {
                        SerializeFlags = ViewModelContentSerializeFlags.None
                    }).GenerateChildren(context));
                }
                handled = true;
            }
            else if (viewModelNode.NodeValue is Tuple <ParameterCollection, ParameterKey> )
            {
                var value = (Tuple <ParameterCollection, ParameterKey>)viewModelNode.NodeValue;

                // Ignore namespace and class name for key name
                viewModelNode.PropertyName = value.Item2.Name;
                if (viewModelNode.PropertyName.Contains('.'))
                {
                    viewModelNode.PropertyName = viewModelNode.PropertyName.Substring(viewModelNode.PropertyName.LastIndexOf('.') + 1);
                }

                if (value.Item2.PropertyType.IsValueType)
                {
                    viewModelNode.Content =
                        new LambdaViewModelContent <object>(() => value.Item1.GetObject(value.Item2), newValue => value.Item1.SetObject(value.Item2, newValue))
                    {
                        Type = value.Item2.PropertyType
                    };

                    handleValueType = true;
                }
                handled = true;
            }
            else if (viewModelNode.Type == typeof(Matrix) || viewModelNode.Type == typeof(Vector3) || viewModelNode.Type == typeof(Color))
            {
                handled = true;
            }
            else if (viewModelNode.Type.IsValueType)
            {
                handleValueType = true;
            }

            if (handleValueType)
            {
                if (!(viewModelNode.Type == typeof(Matrix) || viewModelNode.Type == typeof(Vector3) || viewModelNode.Type == typeof(Color) || viewModelNode.Type == typeof(Color3)))
                {
                    if (viewModelNode.Type.IsValueType && !viewModelNode.Type.IsPrimitive && !viewModelNode.Type.IsEnum)
                    {
                        viewModelNode.Content.SerializeFlags = ViewModelContentSerializeFlags.None;
                        // Use default for those types
                        foreach (var fieldinfo in viewModelNode.Type.GetFields(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance))
                        {
                            IViewModelContent viewModelContent = new FieldInfoViewModelContent(new ParentValueViewModelContent(viewModelNode.Type), fieldinfo);
                            //if (fieldinfo.FieldType.IsValueType && !fieldinfo.FieldType.IsPrimitive && !fieldinfo.FieldType.IsEnum)
                            //    viewModelContent.Flags = ViewModelFlags.None;
                            // Doesn't support array
                            if (fieldinfo.FieldType.IsArray)
                            {
                                continue;
                            }
                            viewModelNode.Children.Add(new ViewModelNode(fieldinfo.Name, viewModelContent).GenerateChildren(context));
                        }
                        handled = true;
                    }
                }
            }
        }
        public void GenerateChildren(ViewModelContext context, IViewModelNode viewModelNode, ref bool handled)
        {
            bool handleValueType = false;

            if (viewModelNode.NodeValue is MicroThread)
            {
                var microThread = (MicroThread)viewModelNode.NodeValue;
                var script = microThread.Get(ScriptManager.ScriptProperty);

                viewModelNode.Content = new EnumerableViewModelContent<ViewModelReference>(() => new[] { new ViewModelReference(script, true) });

                handled = true;
            }
            else if (viewModelNode.NodeValue is IScript)
            {
                var script = (IScript)viewModelNode.NodeValue;

                // Expose all variables of IScript (defined by user)
                foreach (var property in script.GetType().GetProperties())
                {
                    if (property.PropertyType != typeof(int) && property.PropertyType != typeof(float))
                        continue;

                    viewModelNode.Children.Add(new ViewModelNode(property.Name, new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), property)));
                }
                handled = true;
            }
            else if (viewModelNode.NodeValue is Entity)
            {
                ViewModelNode componentsViewModelNode;

                viewModelNode.Children.Add(new ViewModelNode("Name", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(Entity).GetProperty("Name"))));
                viewModelNode.Children.Add(new ViewModelNode("Guid", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(Entity).GetProperty("Guid"))));
                viewModelNode.Children.Add(componentsViewModelNode = new ViewModelNode("Components", EnumerableViewModelContent.FromUnaryLambda<ViewModelReference, Entity>(new ParentNodeValueViewModelContent(), 
                    (entity) => entity.Properties
                                        .Select(x => x.Value)
                                        .OfType<EntityComponent>()
                                        .Select(x => new ViewModelReference(x, true)))));

                var availableKeysContent = new RootViewModelContent(null, typeof(string[]));
                componentsViewModelNode.Children.Add(new ViewModelNode("AvailableKeys", availableKeysContent));

                componentsViewModelNode.Children.Add(new ViewModelNode("RequestKeys", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                    {
                        var availableComponentKeys = new List<string>();

                        // TODO: Improve component keys enumeration (maybe need a registry?)
                        // For now, scan assemblies for all types inheriting from EntityComponent
                        foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
                        {
                            foreach (var type in assembly.GetTypes())
                            {
                                if (type.IsSubclassOf(typeof(EntityComponent))
                                    && type.GetField("Key", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy) != null)
                                {
                                    availableComponentKeys.Add(type.AssemblyQualifiedName);
                                }
                            }
                        }

                        availableKeysContent.Value = availableComponentKeys.ToArray();
                    }))));

                componentsViewModelNode.Children.Add(new ViewModelNode("Add", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                    {
                        var entity = (Entity)viewModel2.Parent.Parent.NodeValue;
                        var componentType = Type.GetType((string)parameter);
                        
                        // For now, assume it will be stored in a PropertyKey inside the actual component named "Key"
                        var componentKeyField = componentType.GetField("Key", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
                        entity.SetObject((PropertyKey)componentKeyField.GetValue(null), Activator.CreateInstance(componentType));
                    }))));

                handled = true;
            }
            else if (viewModelNode.NodeValue is EntityComponent)
            {
                viewModelNode.PropertyName = "EntityComponent";
                var component = (EntityComponent)viewModelNode.NodeValue;
                // Would be better higher in the hierarchy, but it would complicate model
                var propertyKey = component.Entity.Properties.First(x => x.Value == component).Key;
                var propertyKeyName = propertyKey.OwnerType.Name;
                viewModelNode.Children.Add(new ViewModelNode("PropertyKeyName", new RootViewModelContent(propertyKeyName)));
                viewModelNode.Children.Add(new ViewModelNode("Remove", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                {
                    component.Entity.SetObject(propertyKey, null);
                }))));

                var componentViewModel = new ViewModelNode("Component", component);
                viewModelNode.Children.Add(componentViewModel);
                if (component is TransformationComponent)
                {
                    componentViewModel.Children.Add(new ViewModelNode("WorldMatrix", new FieldInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(TransformationComponent).GetField("WorldMatrix"))).GenerateChildren(context));

                    // TODO: How to switch view model depending on TransformationComponent.Values type? Or should we always expose everything?
                    componentViewModel.Children.Add(new ViewModelNode("LocalMatrix", new FieldInfoViewModelContent(new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(TransformationComponent).GetProperty("Value")), typeof(TransformationValue).GetField("LocalMatrix"))).GenerateChildren(context));

                    //if (((TransformationComponent)component).Values is TransformationTRS)
                    {
                        componentViewModel.Children.Add(new ViewModelNode("Translation", new FieldInfoViewModelContent(new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(TransformationComponent).GetProperty("Value")), typeof(TransformationTRS).GetField("Translation"))).GenerateChildren(context));
                        componentViewModel.Children.Add(new ViewModelNode("Rotation", new FieldInfoViewModelContent(new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(TransformationComponent).GetProperty("Value")), typeof(TransformationTRS).GetField("Rotation"))).GenerateChildren(context));
                        componentViewModel.Children.Add(new ViewModelNode("Scaling", new FieldInfoViewModelContent(new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(TransformationComponent).GetProperty("Value")), typeof(TransformationTRS).GetField("Scaling"))).GenerateChildren(context));
                    }

                    componentViewModel.Children.Add(new ViewModelNode("Parent", LambdaViewModelContent<ViewModelReference>.FromOperand<EntityComponent>(new ParentNodeValueViewModelContent(), x => new ViewModelReference(x.Entity, false))));
                    componentViewModel.Children.Last().Children.Add(new ViewModelNode("SetAsRoot", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                        {
                            context.ViewModelByGuid.Clear();
                            context.Root = context.GetModelView(((TransformationComponent)component).Parent.Entity).Children.First(x => x.PropertyName == "Components");
                        }))));
                }
                if (component is ModelComponent)
                {
                    componentViewModel.Children.Add(new ViewModelNode("Parameters", ((ModelComponent)component).MeshParameters).GenerateChildren(context));
                    //componentViewModel.Children.Add(new ViewModelNode(
                    //    "MeshParameters",
                    //    EnumerableViewModelContent.FromUnaryLambda<ViewModelReference, ModelComponent>(
                    //        new ParentNodeValueViewModelContent(),
                    //        (ModelComponent) => ModelComponent.MeshParameters.Keys.Select(key => new ViewModelReference(Tuple.Create(ModelComponent.MeshParameters, key), true)))));
                }
                if (component is LightComponent)
                {
                    componentViewModel.Children.Add(new ViewModelNode("Type", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightComponent).GetProperty("Type"))).GenerateChildren(context));
                    componentViewModel.Children.Add(new ViewModelNode("ShadowMap", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightComponent).GetProperty("ShadowMap"))).GenerateChildren(context));
                    componentViewModel.Children.Add(new ViewModelNode("Deferred", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightComponent).GetProperty("Deferred"))).GenerateChildren(context));
                    componentViewModel.Children.Add(new ViewModelNode("Intensity", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightComponent).GetProperty("Intensity"))).GenerateChildren(context));
                    componentViewModel.Children.Add(new ViewModelNode("DecayStart", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightComponent).GetProperty("DecayStart"))).GenerateChildren(context));
                    componentViewModel.Children.Add(new ViewModelNode("Color", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightComponent).GetProperty("Color"))).GenerateChildren(context));
                    componentViewModel.Children.Add(new ViewModelNode("LightDirection", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightComponent).GetProperty("LightDirection"))).GenerateChildren(context));
                }
                if (component is LightShaftsComponent)
                {
                    componentViewModel.Children.Add(new ViewModelNode("Color", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightShaftsComponent).GetProperty("Color"))).GenerateChildren(context));
                    //componentViewModel.Children.Add(new ViewModelNode("LightShaftsBoundingBoxes", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(LightShaftsComponent).GetProperty("LightShaftsBoundingBoxes"))).GenerateChildren(context));
                }

                // Else try to display it using auto-display
                AutoDisplayComponent(context, viewModelNode, component);

                handled = true;
            }
            else if (viewModelNode.NodeValue is ParameterCollection)
            {
                viewModelNode.Content = EnumerableViewModelContent.FromUnaryLambda<ViewModelReference, ParameterCollection>(new NodeValueViewModelContent(), (parameterCollection) =>
                    parameterCollection.Keys.Where(key => key.PropertyType.IsValueType).Select(key =>
                    {
                        if (key.PropertyType.IsValueType)
                        {
                            // For value type, generated tree won't change so make value based on key only.
                            return new ViewModelReference(Tuple.Create(parameterCollection, key), true);
                        }
                        else
                        {
                            // TODO: resources currently ignored (until fixed)

                            // For reference type, make value dependent on actual value reference and source.
                            // This will trigger a regeneration for reference change (i.e. new texture bound).
                            // Useful since asset type/state might be different.
                            var value = parameterCollection.GetObject(key);
                            var valueSource = engineContext.AssetManager.Url.Get(value);
                            return new ViewModelReference(Tuple.Create(parameterCollection, key, valueSource), true);
                        }
                    }));

                var availableKeysContent = new RootViewModelContent(null, typeof(string[]));
                viewModelNode.Children.Add(new ViewModelNode("AvailableKeys", availableKeysContent));

                viewModelNode.Children.Add(new ViewModelNode("RequestKeys", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                    {
                        var parameterCollection = (ParameterCollection)viewModel2.Parent.NodeValue;
                        var effectMesh = viewModel2.Parent.Parent.NodeValue as EffectMesh;
                        if (effectMesh != null)
                        {
                            var availableKeys = effectMesh.Effect.Passes.SelectMany(x => x.DefaultParameters.Parameters.Select(y => y.Key)).Distinct().Where(x => !parameterCollection.IsValueOwner(x)).Select(x => x.Name).ToArray();
                            availableKeysContent.Value = availableKeys;
                        }
                    }))));

                viewModelNode.Children.Add(new ViewModelNode("Add", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                    {
                        var effectMesh = viewModel2.Parent.Parent.NodeValue as EffectMesh;
                        if (effectMesh != null)
                        {
                            var key = effectMesh.Effect.Passes.SelectMany(x => x.DefaultParameters.Parameters.Select(y => y.Key)).FirstOrDefault(x => x.Name == (string)parameter);
                            if (key != null)
                            {
                                effectMesh.Parameters.SetDefault(key);
                            }
                        }
                    }))));
            }
            else if (viewModelNode.NodeValue is EffectMesh)
            {
                viewModelNode.PropertyName = "Mesh";
                viewModelNode.Children.Add(new ViewModelNode("Effect", LambdaViewModelContent<string>.FromParent<EffectMesh>(x => x.EffectMeshData.EffectData.Name, (x, effectName) => x.EffectMeshData.EffectData.Name = effectName)));
                viewModelNode.Children.Add(new ViewModelNode("Parameters", ((EffectMesh)viewModelNode.NodeValue).Parameters).GenerateChildren(context));
                //viewModelNode.Children.Add(new ViewModelNode("MeshData", LambdaViewModelContent<ViewModelReference>.FromParent<MeshData>(effectMeshData => new ViewModelReference(effectMeshData.MeshData, true))));
                handled = true;
            }
            else if (viewModelNode.NodeValue is ContentData || typeof(ContentData).IsAssignableFrom(viewModelNode.Type))
            {
                if (viewModelNode.NodeValue is ContentData)
                    viewModelNode.Content = new NodeValueViewModelContent();

                if (viewModelNode.Value != null)
                {
                    viewModelNode.Children.Add(new ViewModelNode("Url", new LambdaViewModelContent<string>(new ParentValueViewModelContent(),
                        x => engineContext.AssetManager.Url.Get((x.Value)),
                        (x, y) =>
                        {
                            var nodeValue = x.OwnerNode.Parent.NodeValue;
                        })));

                    viewModelNode.Children.Add(new ViewModelNode("ChangeUrl", new RootViewModelContent((ExecuteCommand)(async (viewModel2, parameter) =>
                        {
                            var dropParameters = (DropCommandParameters)parameter;
                            var parameterInfo = (Tuple<ParameterCollection, ParameterKey, ContentData>)viewModel2.Parent.Parent.NodeValue;

                            var parameterCollection = parameterInfo.Item1;

                            var textureData = await engineContext.AssetManager.LoadAsync<Image>((string)dropParameters.Data);
                            //parameter.Item1.SetObject(parameter.Item2, );
                            //parameterCollection.Remove(parameterInfo.Item2);

                            //var texture = engineContext.ContentManager.Convert<ITexture, Image>(textureData);
                            Texture texture;
                            throw new NotImplementedException();

                            parameterCollection.SetObject(parameterInfo.Item2, texture);
                        }))));

                    if (viewModelNode.Type == typeof(Image))
                    {
                        Image thumbnail = null;
                        Task<Image> textureData = null;

                        viewModelNode.Children.Add(new ViewModelNode("Thumbnail", new LambdaViewModelContent<Image>(new ParentValueViewModelContent(), (viewModelContent) =>
                            {
                                if (textureData == null)
                                {
                                    var textureDataNew = viewModelContent.Value as Image;
                                    if (engineContext.AssetManager.Url.Get(textureDataNew) != null)
                                    {
                                        textureData = engineContext.AssetManager.LoadAsync<Image>(engineContext.AssetManager.Url.Get(textureDataNew));
                                        textureData.ContinueWith(task =>
                                            {
                                                thumbnail = task.Result;
                                                viewModelContent.OwnerNode.Content.SerializeFlags |= ViewModelContentSerializeFlags.Static;
                                            });
                                    }
                                }
                                return thumbnail;
                            })));
                    }
                }

                handled = true;
            }
            else if (viewModelNode.NodeValue is MeshData)
            {
                handled = true;
            }
            else if (viewModelNode.NodeValue is Tuple<ParameterCollection, ParameterKey, ContentData>)
            {
                var value = (Tuple<ParameterCollection, ParameterKey, ContentData>)viewModelNode.NodeValue;

                // Ignore namespace and class name for key name
                viewModelNode.PropertyName = value.Item2.Name;
                if (viewModelNode.PropertyName.Contains('.'))
                    viewModelNode.PropertyName = viewModelNode.PropertyName.Substring(viewModelNode.PropertyName.LastIndexOf('.') + 1);

                viewModelNode.Content = new NullViewModelContent(typeof(Image));
                if (value.Item3 != null)
                    viewModelNode.Children.Add(new ViewModelNode("ObjectRef", new RootViewModelContent(value.Item3) { SerializeFlags = ViewModelContentSerializeFlags.None }).GenerateChildren(context));
                handled = true;
            }
            else if (viewModelNode.NodeValue is Tuple<ParameterCollection, ParameterKey>)
            {
                var value = (Tuple<ParameterCollection, ParameterKey>)viewModelNode.NodeValue;

                // Ignore namespace and class name for key name
                viewModelNode.PropertyName = value.Item2.Name;
                if (viewModelNode.PropertyName.Contains('.'))
                    viewModelNode.PropertyName = viewModelNode.PropertyName.Substring(viewModelNode.PropertyName.LastIndexOf('.') + 1);

                if (value.Item2.PropertyType.IsValueType)
                {
                    viewModelNode.Content =
                        new LambdaViewModelContent<object>(() => value.Item1.GetObject(value.Item2), newValue => value.Item1.SetObject(value.Item2, newValue))
                        {
                            Type = value.Item2.PropertyType
                        };

                    handleValueType = true;
                }
                handled = true;
            }
            else if (viewModelNode.Type == typeof(Matrix) || viewModelNode.Type == typeof(Vector3) || viewModelNode.Type == typeof(Color))
            {
                handled = true;
            }
            else if (viewModelNode.Type.IsValueType)
            {
                handleValueType = true;
            }

            if (handleValueType)
            {
                if (!(viewModelNode.Type == typeof(Matrix) || viewModelNode.Type == typeof(Vector3) || viewModelNode.Type == typeof(Color) || viewModelNode.Type == typeof(Color3)))
                {
                    if (viewModelNode.Type.IsValueType && !viewModelNode.Type.IsPrimitive && !viewModelNode.Type.IsEnum)
                    {
                        viewModelNode.Content.SerializeFlags = ViewModelContentSerializeFlags.None;
                        // Use default for those types
                        foreach (var fieldinfo in viewModelNode.Type.GetFields(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance))
                        {

                            IViewModelContent viewModelContent = new FieldInfoViewModelContent(new ParentValueViewModelContent(viewModelNode.Type), fieldinfo);
                            //if (fieldinfo.FieldType.IsValueType && !fieldinfo.FieldType.IsPrimitive && !fieldinfo.FieldType.IsEnum)
                            //    viewModelContent.Flags = ViewModelFlags.None;
                            // Doesn't support array
                            if (fieldinfo.FieldType.IsArray)
                                continue;
                            viewModelNode.Children.Add(new ViewModelNode(fieldinfo.Name, viewModelContent).GenerateChildren(context));
                        }
                        handled = true;
                    }
                }
            }
        }
Beispiel #11
0
        public void GenerateChildren(ViewModelContext context, IViewModelNode viewModelNode, ref bool handled)
        {
            if ((viewModelNode.NodeValue as string) == "Root")
            {
                viewModelNode.Children.Add(new ViewModelNode("SearchResults", new EnumerableViewModelContent <ViewModelReference>(() =>
                                                                                                                                  searchResults != null && searchResults.IsCompleted ? searchResults.Result.Select(searchResult => new ViewModelReference(KeyValuePair.Create(UrlType.SearchResult, searchResult), true))
                                                                       : new ViewModelReference[] { })));
                viewModelNode.Children.Add(new ViewModelNode("SearchFilter",
                                                             new LambdaViewModelContent <string>(
                                                                 () => searchFilter,
                                                                 (newFilter) =>
                {
                    searchFilter = newFilter;
                    StartSearch();
                })));
                viewModelNode.Children.Add(new ViewModelNode("Packages",
                                                             new EnumerableViewModelContent <ViewModelReference>(() => engineContext.PackageManager.Packages.Select(package => new ViewModelReference(package, true)))));

                fileTracker = new FileTracker();
                fileTracker.Setup("/global_data");
                fileTracker.Setup("/global_data2");
                viewModelNode.Children.Add(new ViewModelNode("FileTracker", new RootViewModelContent(fileTracker)).GenerateChildren(context));
            }
            if (viewModelNode.Type == typeof(FileTracker))
            {
                viewModelNode.Content.SerializeFlags = ViewModelContentSerializeFlags.None;
                viewModelNode.Children.Add(new ViewModelNode("RootFolder", KeyValuePair.Create(UrlType.FileTracker, "/")).GenerateChildren(context));
                handled = true;
            }
            if (viewModelNode.NodeValue is Package)
            {
                viewModelNode.Children.Add(new ViewModelNode("Name", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(Package).GetProperty("Name"))));
                handled = true;
            }

            if (viewModelNode.NodeValue is Tuple <UrlType, string> )
            {
                var nodeValue = (Tuple <UrlType, string>)viewModelNode.NodeValue;
                var url       = nodeValue.Item2;

                if (nodeValue.Item1 == UrlType.SearchResult)
                {
                    // Load thumbnail (not cached yet)
                    if (url.EndsWith(".png") || url.EndsWith(".jpg"))
                    {
                        //var textureData = engineContext.ContentManager.LoadAsync<Image>(url);
                        var thumbnail = new ViewModelNode("Thumbnail",
                                                          new AsyncViewModelContent <Image>(new NullViewModelContent(), operand => engineContext.AssetManager.Load <Image>(url)));
                        viewModelNode.Children.Add(thumbnail);

                        /*textureData.ContinueWith(task =>
                         *  {
                         *      thumbnail.Value = task.Result;
                         *      thumbnail.Content.Flags |= ViewModelFlags.Static;
                         *  });*/
                    }

                    /*else
                     * {
                     *  throw new NotImplementedException();
                     * }*/

                    viewModelNode.Content = new RootViewModelContent(url);
                    viewModelNode.Content.SerializeFlags = ViewModelContentSerializeFlags.Serialize;
                }
                else if (nodeValue.Item1 == UrlType.FileTracker)
                {
                    viewModelNode.Content = new RootViewModelContent(url);
                    viewModelNode.Content.SerializeFlags = ViewModelContentSerializeFlags.Serialize;

                    viewModelNode.Children.Add(new ViewModelNode("SetAsSearchFilter", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                    {
                        searchRoot = url;
                        StartSearch();
                    }))));

                    if (url.EndsWith("/"))
                    {
                        viewModelNode.Children.Add(new ViewModelNode("Folders", new EnumerableViewModelContent <ViewModelReference>(() =>
                                                                                                                                    fileTracker.Files
                                                                                                                                    .Where(file => file.StartsWith(url))
                                                                                                                                    .GroupBy(file =>
                        {
                            var separatorIndex = file.IndexOf('/', url.Length + 1);
                            return(file.Substring(url.Length, separatorIndex != -1 ? separatorIndex - url.Length + 1 : file.Length - url.Length));
                        })
                                                                                                                                    .Where(x => x.Key.EndsWith("/") || x.Key.EndsWith(".dat") || x.Key.EndsWith(".xksl"))
                                                                                                                                    .Select(x => new ViewModelReference(KeyValuePair.Create(UrlType.FileTracker, url + x.Key), this))
                                                                                                                                    )));
                    }
                }

                handled = true;
            }
        }
        public void GenerateChildren(ViewModelContext context, IViewModelNode viewModelNode, ref bool handled)
        {
            if ((viewModelNode.NodeValue as string) == "Root")
            {
                viewModelNode.Children.Add(new ViewModelNode("SearchResults", new EnumerableViewModelContent<ViewModelReference>(() =>
                    searchResults != null && searchResults.IsCompleted ? searchResults.Result.Select(searchResult => new ViewModelReference(KeyValuePair.Create(UrlType.SearchResult, searchResult), true))
                                                                       : new ViewModelReference[] { })));
                viewModelNode.Children.Add(new ViewModelNode("SearchFilter",
                    new LambdaViewModelContent<string>(
                        () => searchFilter,
                        (newFilter) =>
                        {
                            searchFilter = newFilter;
                            StartSearch();
                        })));
                viewModelNode.Children.Add(new ViewModelNode("Packages",
                    new EnumerableViewModelContent<ViewModelReference>(() => engineContext.PackageManager.Packages.Select(package => new ViewModelReference(package, true)))));

                fileTracker = new FileTracker();
                fileTracker.Setup("/global_data");
                fileTracker.Setup("/global_data2");
                viewModelNode.Children.Add(new ViewModelNode("FileTracker", new RootViewModelContent(fileTracker)).GenerateChildren(context));
            }
            if (viewModelNode.Type == typeof(FileTracker))
            {
                viewModelNode.Content.SerializeFlags = ViewModelContentSerializeFlags.None;
                viewModelNode.Children.Add(new ViewModelNode("RootFolder", KeyValuePair.Create(UrlType.FileTracker, "/")).GenerateChildren(context));
                handled = true;
            }
            if (viewModelNode.NodeValue is Package)
            {
                viewModelNode.Children.Add(new ViewModelNode("Name", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(Package).GetProperty("Name"))));
                handled = true;
            }

            if (viewModelNode.NodeValue is Tuple<UrlType, string>)
            {
                var nodeValue = (Tuple<UrlType, string>)viewModelNode.NodeValue;
                var url = nodeValue.Item2;

                if (nodeValue.Item1 == UrlType.SearchResult)
                {
                    // Load thumbnail (not cached yet)
                    if (url.EndsWith(".png") || url.EndsWith(".jpg"))
                    {
                        //var textureData = engineContext.ContentManager.LoadAsync<Image>(url);
                        var thumbnail = new ViewModelNode("Thumbnail",
                            new AsyncViewModelContent<Image>(new NullViewModelContent(), operand => engineContext.AssetManager.Load<Image>(url)));
                        viewModelNode.Children.Add(thumbnail);
                        /*textureData.ContinueWith(task =>
                            {
                                thumbnail.Value = task.Result;
                                thumbnail.Content.Flags |= ViewModelFlags.Static;
                            });*/
                    }
                    /*else
                    {
                        throw new NotImplementedException();
                    }*/

                    viewModelNode.Content = new RootViewModelContent(url);
                    viewModelNode.Content.SerializeFlags = ViewModelContentSerializeFlags.Serialize;
                }
                else if (nodeValue.Item1 == UrlType.FileTracker)
                {
                    viewModelNode.Content = new RootViewModelContent(url);
                    viewModelNode.Content.SerializeFlags = ViewModelContentSerializeFlags.Serialize;

                    viewModelNode.Children.Add(new ViewModelNode("SetAsSearchFilter", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) =>
                        {
                            searchRoot = url;
                            StartSearch();
                        }))));

                    if (url.EndsWith("/"))
                    {
                        viewModelNode.Children.Add(new ViewModelNode("Folders", new EnumerableViewModelContent<ViewModelReference>(() =>
                                fileTracker.Files
                                    .Where(file => file.StartsWith(url))
                                    .GroupBy(file =>
                                        {
                                            var separatorIndex = file.IndexOf('/', url.Length + 1);
                                            return file.Substring(url.Length, separatorIndex != -1 ? separatorIndex - url.Length + 1 : file.Length - url.Length);
                                        })
                                    .Where(x => x.Key.EndsWith("/") || x.Key.EndsWith(".dat") || x.Key.EndsWith(".xksl"))
                                    .Select(x => new ViewModelReference(KeyValuePair.Create(UrlType.FileTracker, url + x.Key), this))
                            )));
                    }
                }

                handled = true;
            }
        }