using System; using System.Collections.Generic; using System.Linq; using System.Text; using Aiwaz.Contracts; using Aiwaz.Core; using Aiwaz.Resources.Attributes; using System.Collections.ObjectModel; using System.Collections.Specialized; namespace Aiwaz.Resources { [AiwazResource("RenderCommand Node", "Node to update and perform other nodes.")] public class RenderCommandNode : CommandUser, IUpdatable { #region IRenderCommandNode Members private ObservableCollection children; public CommandBuffer CommandBuffer { get; protected set; } public bool IsDirty { get; protected set;} public RenderCommandNode ParentRenderCommandNode { get; set; } public RenderCommandNode() { Console.WriteLine(string.Format("Creating RenderCommandNode..")); children = new ObservableCollection(); children.CollectionChanged += new NotifyCollectionChangedEventHandler(children_CollectionChanged); CommandBuffer = new CommandBuffer(); } void children_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { List commandUsers = new List(); if (e.Action == NotifyCollectionChangedAction.Add) { foreach (IResource resource in e.NewItems) GetCommandUsers(resource, ref commandUsers); foreach (CommandUser user in commandUsers) { user.AssignToRenderCommandNode(this); var node = user as RenderCommandNode; if (node != null) node.ParentRenderCommandNode = this; } this.MarkDirty(); } else if (e.Action == NotifyCollectionChangedAction.Remove) { foreach (IResource resource in e.OldItems) GetCommandUsers(resource, ref commandUsers); foreach (CommandUser user in commandUsers) { var node = user as RenderCommandNode; if (node != null) node.ParentRenderCommandNode = null; user.UnassignFromRenderCommandNode(this); } this.MarkDirty(); } } public void MarkDirty() { IsDirty = true; if (ParentRenderCommandNode != null) ParentRenderCommandNode.MarkDirty(); } public void ProcessCommands() { if (IsDirty) { this.GenerateDeviceCommands(); CommandBuffer.Optimize(); } CommandBuffer.Perform(true); } public void GenerateDeviceCommands() { if (!IsDirty) return; IsDirty = false; CommandBuffer.Clear(); List commandUsers = new List(); foreach (var child in children) GetCommandUsers(child, ref commandUsers); foreach (CommandUser user in commandUsers) { // Add the commands all commands CommandBuffer.BufferedCommands.AddRange(user.Commands); // Walk further if we found another RenderCommandNode var node = user as RenderCommandNode; if (node != null) { node.GenerateDeviceCommands(); // Merge the buffers CommandBuffer.AddChildCommandBuffer(node.CommandBuffer); } } } private void GetCommandUsers(IResource resource, ref List commandUsers) { if (resource as CommandUser != null) commandUsers.Add(resource as CommandUser); else foreach (var child in resource.Children) GetCommandUsers(child, ref commandUsers); } #endregion public override CommandExecuteResult ExecuteCommand(byte argCommandType, CommandBuffer argCurrentBuffer, int argCurrentPositon) { return CommandExecuteResult.None; } #region IUpdatable Members public void Update(bool forceUpdate) { List commandUsers = new List(); foreach (var child in children) GetCommandUsers(child, ref commandUsers); // Walk through all updatables and update them. foreach (var user in commandUsers) { var updatable = user as IUpdatable; if (updatable != null && (updatable.WantsUpdate || forceUpdate)) updatable.Update(forceUpdate); } } public bool WantsUpdate { get { return true; } } #endregion #region IDisposable Members public override void Dispose() { if (ParentRenderCommandNode != null) ParentRenderCommandNode.Children.Remove(this); while (Children.Count > 0) Children.RemoveAt(0); base.Dispose(); } #endregion public override ICreationParams CreationParams { get { return null; } } public override ObservableCollection Children { get { return children; } } } }