public static void SelectEntity(IEnumerable <Entity> entities) { // Update property editor selection. if (selectedEntitiesContext != null) { selectedEntitiesContext.ViewModelByGuid.Clear(); var viewModels = entities .Where(entity => entity != null) .Select(entity => selectedEntitiesContext.GetModelView(entity).Children.First(x => x.PropertyName == "Components")) .ToArray(); if (viewModels.Count() > 1) { selectedEntitiesContext.Root = ViewModelController.Combine(selectedEntitiesContext, viewModels); } else { selectedEntitiesContext.Root = viewModels.FirstOrDefault(); } } // Update picking system (gizmo). // It will also update the remote selection in entity tree view. var entitiesArray = entities.ToArray(); if (!ArrayExtensions.ArraysEqual(pickingSystem.SelectedEntities, entitiesArray)) { pickingSystem.SelectedEntities = entitiesArray; } entitiesChangePacketEvent.Set(); }
public void GenerateChildren(ViewModelContext context, IViewModelNode viewModelNode, ref bool handled) { if (viewModelNode.NodeValue is EffectBuilder) { viewModelNode.Children.Add(new ViewModelNode("Name", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(EffectBuilder).GetProperty("Name")))); viewModelNode.Children.Add(new ViewModelNode("EventOpen", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) => { selectedEntitiesContext.ViewModelByGuid.Clear(); selectedEntitiesContext.Root = selectedEntitiesContext.GetModelView(viewModel2.Parent.NodeValue); })))); viewModelNode.Children.Add(new ViewModelNode("Definition", new AsyncViewModelContent <EffectDefinition>(new ParentNodeValueViewModelContent(), operand => new EffectDefinition { Plugins = ((EffectBuilder)operand.Value).Plugins.Select(x => { var pluginDefinition = new EffectPluginDefinition { PluginType = x.GetType().AssemblyQualifiedName, Parameters = new Dictionary <string, EffectParameterDefinition>() }; foreach (var property in x.GetType().GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance)) { if (property.GetCustomAttributes(typeof(EffectDefinitionPropertyAttribute), true).Length == 0) { continue; } // Check type and do some simple conversion var value = property.GetValue(x, null); if (typeof(RenderPassPlugin).IsAssignableFrom(property.PropertyType)) { value = Guid.NewGuid(); } else if (!typeof(ShaderSource).IsAssignableFrom(property.PropertyType) && !property.PropertyType.IsValueType) { throw new NotSupportedException(); } pluginDefinition.Parameters.Add(property.Name, new EffectParameterDefinition(property.PropertyType, value)); } return(pluginDefinition); }).ToList() }))); //new AsyncViewModelContent<EffectDefinition>(() => ) { LoadState = ViewModelContentState.NotLoaded, Flags = ViewModelFlags.Static | ViewModelFlags.Async | ViewModelFlags.Serialize }); } }
public void GenerateChildren(ViewModelContext context, IViewModelNode viewModelNode, ref bool handled) { if (viewModelNode.NodeValue is MicroThread) { viewModelNode.Children.Add(new ViewModelNode("Id", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(MicroThread).GetProperty("Id")))); viewModelNode.Children.Add(new ViewModelNode("Name", new PropertyInfoViewModelContent(new ParentNodeValueViewModelContent(), typeof(MicroThread).GetProperty("Name")))); viewModelNode.Children.Add(new ViewModelNode("ScriptName", LambdaViewModelContent <string> .FromParent <MicroThread>(x => x.Get(ScriptManager.ScriptEntryProperty).TypeName))); viewModelNode.Children.Add(new ViewModelNode("EventOpen", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) => { selectedEntitiesContext.ViewModelByGuid.Clear(); selectedEntitiesContext.Root = selectedEntitiesContext.GetModelView(viewModel2.Parent.NodeValue); })))); handled = true; } }
public async static Task ProcessClient(EngineContext engineContext, SocketContext socketContext, SocketContext socketContextAsync) { socketContext.AddPacketHandler <DownloadFileQuery>( async(packet) => { var stream = await VirtualFileSystem.OpenStreamAsync(packet.Url, VirtualFileMode.Open, VirtualFileAccess.Read); var data = new byte[stream.Length]; await stream.ReadAsync(data, 0, data.Length); stream.Close(); socketContext.Send(new DownloadFileAnswer { StreamId = packet.StreamId, Data = data }); }); socketContext.AddPacketHandler <UploadFilePacket>( async(packet) => { var stream = await VirtualFileSystem.OpenStreamAsync(packet.Url, VirtualFileMode.Create, VirtualFileAccess.Write); await stream.WriteAsync(packet.Data, 0, packet.Data.Length); stream.Close(); }); var viewModelGlobalContext = new ViewModelGlobalContext(); selectedEntitiesContext = new ViewModelContext(viewModelGlobalContext); selectedEntitiesContext.ChildrenPropertyEnumerators.Add(new EntityComponentEnumerator(engineContext)); selectedEntitiesContext.ChildrenPropertyEnumerators.Add(new RenderPassPluginEnumerator()); selectedEntitiesContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator()); //selectedEntitiesContext.ChildrenPropertyEnumerators.Add(new EffectPropertyEnumerator(engineContext)); var renderPassHierarchyContext = new ViewModelContext(viewModelGlobalContext); renderPassHierarchyContext.ChildrenPropertyEnumerators.Add(new RenderPassHierarchyEnumerator()); renderPassHierarchyContext.Root = new ViewModelNode("Root", engineContext.RenderContext.RootRenderPass).GenerateChildren(renderPassHierarchyContext); var renderPassPluginsContext = new ViewModelContext(viewModelGlobalContext); renderPassPluginsContext.ChildrenPropertyEnumerators.Add(new RenderPassPluginsEnumerator { SelectedRenderPassPluginContext = selectedEntitiesContext }); renderPassPluginsContext.Root = new ViewModelNode("Root", new EnumerableViewModelContent <ViewModelReference>( () => engineContext.RenderContext.RenderPassPlugins.Select(x => new ViewModelReference(x, true)))); var entityHierarchyEnumerator = new EntityHierarchyEnumerator(engineContext.EntityManager, selectedEntitiesContext); var entityHierarchyContext = new ViewModelContext(viewModelGlobalContext); entityHierarchyContext.ChildrenPropertyEnumerators.Add(entityHierarchyEnumerator); entityHierarchyContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator()); entityHierarchyContext.Root = new ViewModelNode("EntityHierarchyRoot", new EnumerableViewModelContent <ViewModelReference>( () => engineContext.EntityManager.Entities .Where(x => { var transformationComponent = x.Transformation; return(transformationComponent == null || transformationComponent.Parent == null); }) .Select(x => new ViewModelReference(x, true)))); entityHierarchyEnumerator.SelectedEntities.CollectionChanged += (sender, args) => { SelectEntity(entityHierarchyEnumerator.SelectedEntities); }; //entityHierarchyContext.Root.Children.Add(new ViewModelNode("SelectedItems", EnumerableViewModelContent.FromUnaryLambda<ViewModelReference, ViewModelReference>(new NullViewModelContent(), // (x) => { return new[] { new ViewModelReference(pickingSystem.SelectedEntity) }; }))); /*(value) => * { * var entityModelView = value != null ? entityHierarchyContext.GetModelView(value.Guid) : null; * var entity = entityModelView != null ? (Entity)entityModelView.NodeValue : null; * SelectEntity(entity); * })));*/ entityHierarchyContext.Root.Children.Add(new ViewModelNode("DropEntity", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) => { var dropParameters = (DropCommandParameters)parameter; var movedItem = dropParameters.Data is Guid ? entityHierarchyContext.GetModelView((Guid)dropParameters.Data) : null; var newParent = dropParameters.Parent is Guid ? entityHierarchyContext.GetModelView((Guid)dropParameters.Parent) : null; if (newParent == null || movedItem == null) { return; } var parent = ((Entity)newParent.NodeValue).Transformation; if (dropParameters.TargetIndex > parent.Children.Count) { return; } var transformationComponent = ((Entity)movedItem.NodeValue).Transformation; transformationComponent.Parent = null; parent.Children.Insert(dropParameters.TargetIndex, transformationComponent); })))); entityHierarchyContext.Root.Children.Add(new ViewModelNode("DropAsset", new RootViewModelContent((ExecuteCommand)(async(viewModel2, parameter) => { var dropParameters = (DropCommandParameters)parameter; var assetUrl = (string)dropParameters.Data; /*var newParent = entityHierarchyContext.GetModelView((Guid)dropParameters.Parent); * * if (newParent == null || assetUrl == null) * return; * * var parent = ((Entity)newParent.NodeValue).Transformation; * if (dropParameters.ItemIndex > parent.Children.Count) * return;*/ engineContext.Scheduler.Add(async() => { // Load prefab entity var loadedEntityPrefab = await engineContext.AssetManager.LoadAsync <Entity>(assetUrl + "#"); // Build another entity from prefab var loadedEntity = Prefab.Inherit(loadedEntityPrefab); // Add it to scene engineContext.EntityManager.AddEntity(loadedEntity); if (loadedEntity.ContainsKey(AnimationComponent.Key)) { Scheduler.Current.Add(() => AnimScript.AnimateFBXModel(engineContext, loadedEntity)); } }); })))); var scriptEngineContext = new ViewModelContext(viewModelGlobalContext); scriptEngineContext.ChildrenPropertyEnumerators.Add(new ScriptAssemblyEnumerator(engineContext)); scriptEngineContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator()); scriptEngineContext.Root = new ViewModelNode(new EnumerableViewModelContent <ViewModelReference>( () => engineContext.ScriptManager.ScriptAssemblies.Select(x => new ViewModelReference(x, true)))); scriptEngineContext.Root.Children.Add(new ViewModelNode("RunScript", new RootViewModelContent((ExecuteCommand)(async(viewModel2, parameter) => { var scriptName = (string)parameter; var matchingScript = engineContext.ScriptManager.Scripts.Where(x => x.TypeName + "." + x.MethodName == scriptName); if (matchingScript.Any()) { var scriptEntry = matchingScript.Single(); var microThread = engineContext.ScriptManager.RunScript(scriptEntry, null); } })))); var runningScriptsContext = new ViewModelContext(viewModelGlobalContext); runningScriptsContext.ChildrenPropertyEnumerators.Add(new MicroThreadEnumerator(selectedEntitiesContext)); runningScriptsContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator()); runningScriptsContext.Root = new ViewModelNode("MicroThreads", new EnumerableViewModelContent <ViewModelReference>( () => engineContext.Scheduler.MicroThreads.Select(x => new ViewModelReference(x, true)) )); var effectsContext = new ViewModelContext(viewModelGlobalContext); effectsContext.ChildrenPropertyEnumerators.Add(new EffectEnumerator(selectedEntitiesContext)); effectsContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator()); effectsContext.Root = new ViewModelNode("Effects", new EnumerableViewModelContent <ViewModelReference>( () => engineContext.RenderContext.Effects.Select(x => new ViewModelReference(x, true)) )); //effectsContext.Root.Children.Add(new ViewModelNode("PluginDefinitions", new RootViewModelContent())); var assetBrowserContext = new ViewModelContext(viewModelGlobalContext); assetBrowserContext.ChildrenPropertyEnumerators.Add(new AssetBrowserEnumerator(engineContext)); assetBrowserContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator()); assetBrowserContext.Root = new ViewModelNode("Root", "Root").GenerateChildren(assetBrowserContext); var editorContext = new ViewModelContext(viewModelGlobalContext); editorContext.Root = new ViewModelNode("Root"); editorContext.Root.Children.Add(new ViewModelNode("SwitchSelectionMode", new CommandViewModelContent((sender, parameters) => { pickingSystem.ActiveGizmoActionMode = PickingSystem.GizmoAction.None; }))); editorContext.Root.Children.Add(new ViewModelNode("SwitchTranslationMode", new CommandViewModelContent((sender, parameters) => { pickingSystem.ActiveGizmoActionMode = PickingSystem.GizmoAction.Translation; }))); editorContext.Root.Children.Add(new ViewModelNode("SwitchRotationMode", new CommandViewModelContent((sender, parameters) => { pickingSystem.ActiveGizmoActionMode = PickingSystem.GizmoAction.Rotation; }))); var contexts = new Dictionary <string, Tuple <ViewModelContext, ViewModelState> >(); contexts.Add("Editor", Tuple.Create(editorContext, new ViewModelState())); contexts.Add("RenderPassPlugins", Tuple.Create(renderPassPluginsContext, new ViewModelState())); contexts.Add("RenderPasses", Tuple.Create(renderPassHierarchyContext, new ViewModelState())); contexts.Add("SelectedEntities", Tuple.Create(selectedEntitiesContext, new ViewModelState())); contexts.Add("EntityHierarchy", Tuple.Create(entityHierarchyContext, new ViewModelState())); contexts.Add("ScriptEngine", Tuple.Create(scriptEngineContext, new ViewModelState())); contexts.Add("MicroThreads", Tuple.Create(runningScriptsContext, new ViewModelState())); contexts.Add("AssetBrowser", Tuple.Create(assetBrowserContext, new ViewModelState())); contexts.Add("Effects", Tuple.Create(effectsContext, new ViewModelState())); int lastAckPacket = 0; var entitiesChangePackets = new ConcurrentQueue <EntitiesChangePacket>(); socketContext.AddPacketHandler <EntitiesChangePacket>( (packet) => { entitiesChangePackets.Enqueue(packet); entitiesChangePacketEvent.Set(); }); Action asyncThreadStart = () => { while (true) { Thread.Sleep(100); foreach (var context in contexts) { // Process async data Guid[] path = null; object value = null; lock (context.Value.Item1) { var pendingNode = context.Value.Item1.GetNextPendingAsyncNode(); if (pendingNode != null) { value = pendingNode.Value; path = ViewModelController.BuildPath(pendingNode); } } if (path != null) { // Temporary encoding through our serializer (until our serializer are used for packets) var memoryStream = new MemoryStream(); var writer = new BinarySerializationWriter(memoryStream); writer.SerializeExtended(null, value, ArchiveMode.Serialize); var change = new NetworkChange { Path = path.ToArray(), Type = NetworkChangeType.ValueUpdateAsync, Value = memoryStream.ToArray() }; var packet = new EntitiesChangePacket { GroupKey = context.Key, Changes = new NetworkChange[] { change } }; socketContextAsync.Send(packet); break; } } } }; new Thread(new ThreadStart(asyncThreadStart)).Start(); // TODO: Move some of this code directly inside ViewModelContext/Controller classes while (true) { await TaskEx.WhenAny(TaskEx.Delay(250), entitiesChangePacketEvent.WaitAsync()); EntitiesChangePacket packet; while (entitiesChangePackets.TryDequeue(out packet)) { ViewModelController.NetworkApplyChanges(contexts[packet.GroupKey].Item1, packet.Changes); lastAckPacket = packet.Index; } // Wait a single frame so that network updates get applied properly by all rendering systems for next update await Scheduler.Current.NextFrame(); // If entity disappeared, try to replace it with new one (happen during file reload) // It's little bit cumbersome to test, need some simplification of this specific entity view model root. if (selectedEntitiesContext.Root != null && selectedEntitiesContext.Root.Parent != null && selectedEntitiesContext.Root.Parent.NodeValue is Entity) { var entity = (Entity)selectedEntitiesContext.Root.Parent.NodeValue; if (!engineContext.EntityManager.Entities.Contains(entity)) { entity = engineContext.EntityManager.Entities.FirstOrDefault(x => x.Guid == entity.Guid); if (entity != null) { selectedEntitiesContext.ViewModelByGuid.Clear(); selectedEntitiesContext.Root = selectedEntitiesContext.GetModelView(entity).Children.First(x => x.PropertyName == "Components"); } } } var data = new Dictionary <string, byte[]>(); foreach (var context in contexts) { lock (context.Value.Item1) { if (context.Value.Item1.Root != null) { context.Value.Item1.AddModelView(context.Value.Item1.Root); } ViewModelController.UpdateReferences(context.Value.Item1, true); data[context.Key] = ViewModelController.NetworkSerialize(context.Value.Item1, context.Value.Item2); } } viewModelGlobalContext.UpdateObjects(contexts.Select(x => x.Value.Item1)); //Console.WriteLine("DataSize: {0}", data.Sum(x => x.Value.Length)); await Task.Factory.StartNew(() => socketContext.Send(new EntitiesUpdatePacket { AckIndex = lastAckPacket, Data = data })); } }
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; } } } }
public async static Task ProcessClient(EngineContext engineContext, SocketContext socketContext, SocketContext socketContextAsync) { socketContext.AddPacketHandler<DownloadFileQuery>( async (packet) => { var stream = await VirtualFileSystem.OpenStreamAsync(packet.Url, VirtualFileMode.Open, VirtualFileAccess.Read); var data = new byte[stream.Length]; await stream.ReadAsync(data, 0, data.Length); stream.Close(); socketContext.Send(new DownloadFileAnswer { StreamId = packet.StreamId, Data = data }); }); socketContext.AddPacketHandler<UploadFilePacket>( async (packet) => { var stream = await VirtualFileSystem.OpenStreamAsync(packet.Url, VirtualFileMode.Create, VirtualFileAccess.Write); await stream.WriteAsync(packet.Data, 0, packet.Data.Length); stream.Close(); }); var viewModelGlobalContext = new ViewModelGlobalContext(); selectedEntitiesContext = new ViewModelContext(viewModelGlobalContext); selectedEntitiesContext.ChildrenPropertyEnumerators.Add(new EntityComponentEnumerator(engineContext)); selectedEntitiesContext.ChildrenPropertyEnumerators.Add(new RenderPassPluginEnumerator()); selectedEntitiesContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator()); //selectedEntitiesContext.ChildrenPropertyEnumerators.Add(new EffectPropertyEnumerator(engineContext)); var renderPassHierarchyContext = new ViewModelContext(viewModelGlobalContext); renderPassHierarchyContext.ChildrenPropertyEnumerators.Add(new RenderPassHierarchyEnumerator()); renderPassHierarchyContext.Root = new ViewModelNode("Root", engineContext.RenderContext.RootRenderPass).GenerateChildren(renderPassHierarchyContext); var renderPassPluginsContext = new ViewModelContext(viewModelGlobalContext); renderPassPluginsContext.ChildrenPropertyEnumerators.Add(new RenderPassPluginsEnumerator { SelectedRenderPassPluginContext = selectedEntitiesContext }); renderPassPluginsContext.Root = new ViewModelNode("Root", new EnumerableViewModelContent<ViewModelReference>( () => engineContext.RenderContext.RenderPassPlugins.Select(x => new ViewModelReference(x, true)))); var entityHierarchyEnumerator = new EntityHierarchyEnumerator(engineContext.EntityManager, selectedEntitiesContext); var entityHierarchyContext = new ViewModelContext(viewModelGlobalContext); entityHierarchyContext.ChildrenPropertyEnumerators.Add(entityHierarchyEnumerator); entityHierarchyContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator()); entityHierarchyContext.Root = new ViewModelNode("EntityHierarchyRoot", new EnumerableViewModelContent<ViewModelReference>( () => engineContext.EntityManager.Entities .Where(x => { var transformationComponent = x.Transformation; return (transformationComponent == null || transformationComponent.Parent == null); }) .Select(x => new ViewModelReference(x, true)))); entityHierarchyEnumerator.SelectedEntities.CollectionChanged += (sender, args) => { SelectEntity(entityHierarchyEnumerator.SelectedEntities); }; //entityHierarchyContext.Root.Children.Add(new ViewModelNode("SelectedItems", EnumerableViewModelContent.FromUnaryLambda<ViewModelReference, ViewModelReference>(new NullViewModelContent(), // (x) => { return new[] { new ViewModelReference(pickingSystem.SelectedEntity) }; }))); /*(value) => { var entityModelView = value != null ? entityHierarchyContext.GetModelView(value.Guid) : null; var entity = entityModelView != null ? (Entity)entityModelView.NodeValue : null; SelectEntity(entity); })));*/ entityHierarchyContext.Root.Children.Add(new ViewModelNode("DropEntity", new RootViewModelContent((ExecuteCommand)((viewModel2, parameter) => { var dropParameters = (DropCommandParameters)parameter; var movedItem = dropParameters.Data is Guid ? entityHierarchyContext.GetModelView((Guid)dropParameters.Data) : null; var newParent = dropParameters.Parent is Guid ? entityHierarchyContext.GetModelView((Guid)dropParameters.Parent) : null; if (newParent == null || movedItem == null) return; var parent = ((Entity)newParent.NodeValue).Transformation; if (dropParameters.TargetIndex > parent.Children.Count) return; var transformationComponent = ((Entity)movedItem.NodeValue).Transformation; transformationComponent.Parent = null; parent.Children.Insert(dropParameters.TargetIndex, transformationComponent); })))); entityHierarchyContext.Root.Children.Add(new ViewModelNode("DropAsset", new RootViewModelContent((ExecuteCommand)(async (viewModel2, parameter) => { var dropParameters = (DropCommandParameters)parameter; var assetUrl = (string)dropParameters.Data; /*var newParent = entityHierarchyContext.GetModelView((Guid)dropParameters.Parent); if (newParent == null || assetUrl == null) return; var parent = ((Entity)newParent.NodeValue).Transformation; if (dropParameters.ItemIndex > parent.Children.Count) return;*/ engineContext.Scheduler.Add(async () => { // Load prefab entity var loadedEntityPrefab = await engineContext.AssetManager.LoadAsync<Entity>(assetUrl + "#"); // Build another entity from prefab var loadedEntity = Prefab.Inherit(loadedEntityPrefab); // Add it to scene engineContext.EntityManager.AddEntity(loadedEntity); if (loadedEntity.ContainsKey(AnimationComponent.Key)) { Scheduler.Current.Add(() => AnimScript.AnimateFBXModel(engineContext, loadedEntity)); } }); })))); var scriptEngineContext = new ViewModelContext(viewModelGlobalContext); scriptEngineContext.ChildrenPropertyEnumerators.Add(new ScriptAssemblyEnumerator(engineContext)); scriptEngineContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator()); scriptEngineContext.Root = new ViewModelNode(new EnumerableViewModelContent<ViewModelReference>( () => engineContext.ScriptManager.ScriptAssemblies.Select(x => new ViewModelReference(x, true)))); scriptEngineContext.Root.Children.Add(new ViewModelNode("RunScript", new RootViewModelContent((ExecuteCommand)(async (viewModel2, parameter) => { var scriptName = (string)parameter; var matchingScript = engineContext.ScriptManager.Scripts.Where(x => x.TypeName + "." + x.MethodName == scriptName); if (matchingScript.Any()) { var scriptEntry = matchingScript.Single(); var microThread = engineContext.ScriptManager.RunScript(scriptEntry, null); } })))); var runningScriptsContext = new ViewModelContext(viewModelGlobalContext); runningScriptsContext.ChildrenPropertyEnumerators.Add(new MicroThreadEnumerator(selectedEntitiesContext)); runningScriptsContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator()); runningScriptsContext.Root = new ViewModelNode("MicroThreads", new EnumerableViewModelContent<ViewModelReference>( () => engineContext.Scheduler.MicroThreads.Select(x => new ViewModelReference(x, true)) )); var effectsContext = new ViewModelContext(viewModelGlobalContext); effectsContext.ChildrenPropertyEnumerators.Add(new EffectEnumerator(selectedEntitiesContext)); effectsContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator()); effectsContext.Root = new ViewModelNode("Effects", new EnumerableViewModelContent<ViewModelReference>( () => engineContext.RenderContext.Effects.Select(x => new ViewModelReference(x, true)) )); //effectsContext.Root.Children.Add(new ViewModelNode("PluginDefinitions", new RootViewModelContent())); var assetBrowserContext = new ViewModelContext(viewModelGlobalContext); assetBrowserContext.ChildrenPropertyEnumerators.Add(new AssetBrowserEnumerator(engineContext)); assetBrowserContext.ChildrenPropertyEnumerators.Add(new ChildrenPropertyInfoEnumerator()); assetBrowserContext.Root = new ViewModelNode("Root", "Root").GenerateChildren(assetBrowserContext); var editorContext = new ViewModelContext(viewModelGlobalContext); editorContext.Root = new ViewModelNode("Root"); editorContext.Root.Children.Add(new ViewModelNode("SwitchSelectionMode", new CommandViewModelContent((sender, parameters) => { pickingSystem.ActiveGizmoActionMode = PickingSystem.GizmoAction.None; }))); editorContext.Root.Children.Add(new ViewModelNode("SwitchTranslationMode", new CommandViewModelContent((sender, parameters) => { pickingSystem.ActiveGizmoActionMode = PickingSystem.GizmoAction.Translation; }))); editorContext.Root.Children.Add(new ViewModelNode("SwitchRotationMode", new CommandViewModelContent((sender, parameters) => { pickingSystem.ActiveGizmoActionMode = PickingSystem.GizmoAction.Rotation; }))); var contexts = new Dictionary<string, Tuple<ViewModelContext, ViewModelState>>(); contexts.Add("Editor", Tuple.Create(editorContext, new ViewModelState())); contexts.Add("RenderPassPlugins", Tuple.Create(renderPassPluginsContext, new ViewModelState())); contexts.Add("RenderPasses", Tuple.Create(renderPassHierarchyContext, new ViewModelState())); contexts.Add("SelectedEntities", Tuple.Create(selectedEntitiesContext, new ViewModelState())); contexts.Add("EntityHierarchy", Tuple.Create(entityHierarchyContext, new ViewModelState())); contexts.Add("ScriptEngine", Tuple.Create(scriptEngineContext, new ViewModelState())); contexts.Add("MicroThreads", Tuple.Create(runningScriptsContext, new ViewModelState())); contexts.Add("AssetBrowser", Tuple.Create(assetBrowserContext, new ViewModelState())); contexts.Add("Effects", Tuple.Create(effectsContext, new ViewModelState())); int lastAckPacket = 0; var entitiesChangePackets = new ConcurrentQueue<EntitiesChangePacket>(); socketContext.AddPacketHandler<EntitiesChangePacket>( (packet) => { entitiesChangePackets.Enqueue(packet); entitiesChangePacketEvent.Set(); }); Action asyncThreadStart = () => { while (true) { Thread.Sleep(100); foreach (var context in contexts) { // Process async data Guid[] path = null; object value = null; lock (context.Value.Item1) { var pendingNode = context.Value.Item1.GetNextPendingAsyncNode(); if (pendingNode != null) { value = pendingNode.Value; path = ViewModelController.BuildPath(pendingNode); } } if (path != null) { // Temporary encoding through our serializer (until our serializer are used for packets) var memoryStream = new MemoryStream(); var writer = new BinarySerializationWriter(memoryStream); writer.SerializeExtended(null, value, ArchiveMode.Serialize); var change = new NetworkChange { Path = path.ToArray(), Type = NetworkChangeType.ValueUpdateAsync, Value = memoryStream.ToArray() }; var packet = new EntitiesChangePacket { GroupKey = context.Key, Changes = new NetworkChange[] { change } }; socketContextAsync.Send(packet); break; } } } }; new Thread(new ThreadStart(asyncThreadStart)).Start(); // TODO: Move some of this code directly inside ViewModelContext/Controller classes while (true) { await TaskEx.WhenAny(TaskEx.Delay(250), entitiesChangePacketEvent.WaitAsync()); EntitiesChangePacket packet; while (entitiesChangePackets.TryDequeue(out packet)) { ViewModelController.NetworkApplyChanges(contexts[packet.GroupKey].Item1, packet.Changes); lastAckPacket = packet.Index; } // Wait a single frame so that network updates get applied properly by all rendering systems for next update await Scheduler.Current.NextFrame(); // If entity disappeared, try to replace it with new one (happen during file reload) // It's little bit cumbersome to test, need some simplification of this specific entity view model root. if (selectedEntitiesContext.Root != null && selectedEntitiesContext.Root.Parent != null && selectedEntitiesContext.Root.Parent.NodeValue is Entity) { var entity = (Entity)selectedEntitiesContext.Root.Parent.NodeValue; if (!engineContext.EntityManager.Entities.Contains(entity)) { entity = engineContext.EntityManager.Entities.FirstOrDefault(x => x.Guid == entity.Guid); if (entity != null) { selectedEntitiesContext.ViewModelByGuid.Clear(); selectedEntitiesContext.Root = selectedEntitiesContext.GetModelView(entity).Children.First(x => x.PropertyName == "Components"); } } } var data = new Dictionary<string, byte[]>(); foreach (var context in contexts) { lock (context.Value.Item1) { if (context.Value.Item1.Root != null) context.Value.Item1.AddModelView(context.Value.Item1.Root); ViewModelController.UpdateReferences(context.Value.Item1, true); data[context.Key] = ViewModelController.NetworkSerialize(context.Value.Item1, context.Value.Item2); } } viewModelGlobalContext.UpdateObjects(contexts.Select(x => x.Value.Item1)); //Console.WriteLine("DataSize: {0}", data.Sum(x => x.Value.Length)); await Task.Factory.StartNew(() => socketContext.Send(new EntitiesUpdatePacket { AckIndex = lastAckPacket, Data = data })); } }