/// <summary> /// Returns true if the given scene node is a child /// of this node. /// </summary> /// <param name="child">Scene node to look for.</param> public bool ChildExists(SceneNode child) { return _childList.Contains(child); }
/// <summary> /// Adds the given scene node to this nodes child list. /// </summary> /// <param name="child">Scene node to add as child.</param> public virtual void AddChild(SceneNode child) { if (_childList.Contains(child)) return; _childList.Add(child); child.Parent = this; SceneGraph.AttachNode(child); }
/// <summary> /// Moves the given child to the front of the rendering list. /// </summary> /// <param name="child">Child to move.</param> public void BringChildToFront(SceneNode child) { _childList.Remove(child); _childList.Add(child); }
/// <summary> /// Initializes a new instance of this class. /// </summary> /// <param name="node">Node that was transformed.</param> /// <param name="originalTransformation">Nodes original transformation.</param> /// <param name="newTransformation">Nodes new transformation.</param> public TransformNodeUndoOperation(SceneNode node, Transformation originalTransformation, Transformation newTransformation) { _node = node; _newTransformation = newTransformation; _originalTransformation = originalTransformation; }
/// <summary> /// Saves the given node and all of its children into a given binary writer. /// </summary> /// <param name="writer">Binary writer to save the given node into.</param> /// <param name="node">Node to save into binary writer.</param> private void SaveNode(BinaryWriter writer, SceneNode node) { // Write in the name of this node. writer.Write(node.GetType().FullName); // Save the nodes details into the stream. node.Save(writer); // Save the children. writer.Write(node.Children.Count); foreach (SceneNode childNode in node.Children) SaveNode(writer, childNode); }
/// <summary> /// Removes the given scene node from this nodes child list. /// </summary> /// <param name="child">Scene node to remove.</param> public virtual void RemoveChild(SceneNode child) { _childList.Remove(child); child.Parent = null; SceneGraph.DetachNode(child); }
/// <summary> /// Loads this map from a given object or file path. /// </summary> /// <param name="url">Url of file to open map from. </param> /// <param name="password">If a password is required to open this map, this will be used.</param> /// <param name="baseNode">The base node that all loading should be started from, this allows you to ignore this node and any nodes higher in the graph like the Root Camera.</param> /// <param name="keepPersistent">If set to true persistent ob jects will be kept.</param> /// <param name="keepCameras">If set to true all cameras will not be destroyed.</param> public void Load(object url, string password, SceneNode baseNode, bool keepPersistent, bool keepCameras) { // Keep track of the url. if (url is string) _url = url as string; // Try and open a stream to the file. Stream stream = StreamFactory.RequestStream(url, StreamMode.Open); if (stream == null) return; BinaryReader reader = new BinaryReader(stream); // Check the header of this file to make sure it really is a Fusion map file. if (reader.ReadChar() != 'F' || reader.ReadChar() != 'M' || reader.ReadChar() != 'P') throw new Exception("Fusion map file has invalid header, file may be corrupt."); // Read in the bit mask explaining the header. int headerBitMask = reader.ReadByte(); if ((headerBitMask & 4) != 0) _mapProperties.Name = reader.ReadString(); if ((headerBitMask & 8) != 0) _mapProperties.Author = reader.ReadString(); if ((headerBitMask & 16) != 0) _mapProperties.Description = reader.ReadString(); if ((headerBitMask & 32) != 0) _mapProperties.Version = reader.ReadSingle(); // Read in the rest of the file into memory so we can decompress / decrypt it. byte[] fileData = reader.ReadBytes((int)(stream.Length - stream.Position)); // Decrypt the data if required. if ((headerBitMask & 2) != 0) fileData = DataMethods.Decrypt(fileData, password); // Decompress the data if required. if ((headerBitMask & 1) != 0) fileData = DataMethods.Inflate(fileData); // Create a memory stream and a binary reader so we can minipulate the data better. MemoryStream memStream = new MemoryStream(fileData, 0, fileData.Length); BinaryReader memStreamReader = new BinaryReader(memStream); // Read in the encryption header to make sure everything went correctly. if ((headerBitMask & 2) != 0 || (headerBitMask & 1) != 0) if (memStreamReader.ReadChar() != 'C' || memStreamReader.ReadChar() != 'H' || memStreamReader.ReadChar() != 'K') throw new Exception("Unable to open Fusion map file, password is invalid or fils is corrupted."); // Read in the tileset pool used to render tilemap segments. int tilesetCount = memStreamReader.ReadByte(); Tileset.TilesetPool.Clear(); for (int i = 0; i < tilesetCount; i++) { if (memStreamReader.ReadBoolean() == true) { string newTilesetUrl = memStreamReader.ReadString(); if (newTilesetUrl.ToString().ToLower().StartsWith("pak@")) newTilesetUrl = newTilesetUrl.ToString().Substring(4); // Legacy support. if (Runtime.Resources.ResourceManager.ResourceIsCached(newTilesetUrl)) Tileset.AddToTilesetPool(Runtime.Resources.ResourceManager.RetrieveResource(newTilesetUrl) as Tileset); else { Runtime.Debug.DebugLogger.WriteLog("Loading tileset from " + newTilesetUrl); Tileset newTileset = new Tileset(); newTileset.Load(newTilesetUrl); Tileset.AddToTilesetPool(newTileset); Runtime.Resources.ResourceManager.CacheResource(newTilesetUrl, newTileset); } } } // Tell the scene graph to load itself from this memory stream. _sceneGraph.Load(memStreamReader, keepPersistent, keepCameras, baseNode); // Free up the memory stream and reader. memStream.Close(); memStream = null; // Free up the reader and stream. stream.Close(); stream = null; // Reclaim memory used during loading. GC.Collect(); }
/// <summary> /// Clear out every scene node from this scene graph. /// </summary> public void Clear() { _rootNode.ClearChildren(); _rootNode = new SceneNode("Root"); _cameraList.Clear(); }
/// <summary> /// Loads the scene graph from a given binary reader. /// </summary> /// <param name="stream">Binary reader to load this scene graph from.</param> /// <param name="baseNode">The base node that all loading should be started from, this allows you to ignore this node and any nodes higher in the graph like the Root Camera.</param> /// <param name="keepPersistent">If set to true persistent ob jects will be kept.</param> /// <param name="keepCameras">If set to true all cameras will not be destroyed.</param> public void Load(BinaryReader reader, bool keepPersistent, bool keepCameras, SceneNode baseNode) { // Dispose of all old entities. // Lets compile a list of all peristent nodes if we are keeping them. ArrayList persistentList = new ArrayList(); if (keepPersistent == true) { ArrayList entityList = new ArrayList(_nodeList); foreach (SceneNode node in entityList) if (node.IsPersistent == true) persistentList.Add(node); else node.Dispose(); entityList.Clear(); entityList = null; } // Get starting memory. long startingMemory = GC.GetTotalMemory(true); // Clear out any non-persistent cameras. if (keepCameras == false) { ArrayList removalList = new ArrayList(); foreach (CameraNode camera in _cameraList) if (camera.IsPersistent == false) removalList.Add(camera); foreach (CameraNode camera in removalList) _cameraList.Remove(camera); } // Reset unique ID counter. _uniqueIDTracker = 0; // Clean out base node. if (baseNode != null) baseNode.ClearChildren(); else _rootNode.ClearChildren(); bool baseNodeExists = reader.ReadBoolean(); if (baseNodeExists == true) { int childCount = reader.ReadInt32(); for(int i = 0; i < childCount; i++) { if (baseNode != null) baseNode.AddChild(LoadNode(reader)); else _rootNode.AddChild(LoadNode(reader)); } } else _rootNode = LoadNode(reader, true); // Lets see if we can reattached any persistent nodes, if not lets just // tack them onto the root node. if (keepPersistent == true) { foreach (SceneNode node in persistentList) { if (node.Parent == null || node.Parent.IsPersistent == false) (baseNode == null ? _rootNode : baseNode).AddChild(node); } } // Say how many have been created. DebugLogger.WriteLog("Loaded " + _uniqueIDTracker + " nodes into scene graph, with a cumulative memory allocation of " + (((GC.GetTotalMemory(true) - startingMemory) / 1024.0f) / 1024.0f) + "mb."); // Go through each node and grab its properties SyncronizeNodes(); // Reset loading percentage. _loadingProgress = 0; }
/// <summary> /// Adds a node from the global node list. /// </summary> /// <param name="node">Node to add to global node list.</param> public static void AttachNode(SceneNode node) { if (_nodeList.Contains(node)) return; _nodeList.Add(node); }
/// <summary> /// Removes a node from the global node list. /// </summary> /// <param name="node">Node to remove to global node list.</param> public static void DetachNode(SceneNode node) { _nodeList.Remove(node); }
/// <summary> /// Moves the given child 1 step forewards in the rendering list. /// </summary> /// <param name="child">Child to move.</param> public void ShiftChildForewards(SceneNode child) { int index = _childList.IndexOf(child); _childList.Remove(child); _childList.Insert(Math.Min(_childList.Count, index + 1), child); }
/// <summary> /// Moves the given child 1 step backwards in the rendering list. /// </summary> /// <param name="child">Child to move.</param> public void ShiftChildBackwards(SceneNode child) { int index = _childList.IndexOf(child); _childList.Remove(child); _childList.Insert(Math.Max(0, index - 1), child); }
/// <summary> /// Moves the given child to the back of the rendering list. /// </summary> /// <param name="child">Child to move.</param> public void SendChildToBack(SceneNode child) { _childList.Remove(child); _childList.Insert(0, child); }
/// <summary> /// Copys all the data contained in this scene node to another scene node. /// </summary> /// <param name="node">Scene node to copy data into.</param> public virtual void CopyTo(SceneNode node) { }
/// <summary> /// Saves this scene graph into a given binary writer. /// </summary> /// <param name="stream">Binary writer to save this scene graph into.</param> /// <param name="baseNode">The base node that all saving should be started from, this allows you to ignore this node and any nodes higher in the graph like the Root Camera.</param> public void Save(BinaryWriter writer, SceneNode baseNode) { writer.Write(baseNode != null); if (baseNode != null) { writer.Write(baseNode.Children.Count); foreach (SceneNode childNode in baseNode.Children) SaveNode(writer, childNode); } else SaveNode(writer, _rootNode); }
/// <summary> /// Responsable for removing references of this object and deallocated /// resources that have been allocated. /// </summary> public virtual void Dispose() { // Clear out references if (_parent != null) _parent.RemoveChild(this); _parent = null; SceneGraph.DetachNode(this); // Remove all the childrens references. (Don't tell them to dispose, that is done elsewhere). ClearChildren(); // Remove all the script references. VirtualMachine.GlobalInstance.RemoveReferences(this); Statistics.StoreInt("Disposal Counted Scene Node Count", Statistics.ReadInt("Disposal Counted Scene Node Count") - 1); }
/// <summary> /// Used by the EnumerateNodes function to add all the children of /// a node to the given array list. /// </summary> /// <param name="nodeList">Array list to add children to.</param> /// <param name="node">Node to add children from.</param> private void EnumerateChildrenOfNode(ArrayList nodeList, SceneNode node) { nodeList.AddRange(node.Children); for (int i = 0; i < node.Children.Count; i++) EnumerateChildrenOfNode(nodeList, (SceneNode)node.Children[i]); }
/// <summary> /// Fills the scene graph tree view with the given scene node and its child nodes. /// </summary> /// <param name="node">Node to add to scene graph.</param> /// <param name="collection">Collection to add node to.</param> private void FillSceneGraph(SceneNode node, TreeNodeCollection collection) { foreach (SceneNode subNode in node.Children) { TreeNode treeNode = new TreeNode((subNode.Name == null ? "Untitled" : subNode.Name) + "("+subNode.Transformation.X+","+subNode.Transformation.Y+","+subNode.Transformation.Z+")"); collection.Add(treeNode); _nodeHashTable.Add(treeNode, subNode); FillSceneGraph(subNode, treeNode.Nodes); } }
/// <summary> /// Loads the next node in the given binary reader and returns it. /// </summary> /// <param name="reader">Binary reader to read node from.</param> /// <param name="getProgress">If set to true this node is used to judge the current progress.</param> /// <returns>Scene node that was loaded from the binary reader.</returns> private SceneNode LoadNode(BinaryReader reader, bool getProgress) { // Read in the name of this node's class. string name = reader.ReadString(); //HighPreformanceTimer timer = new HighPreformanceTimer(); // Create a new instance of this entity and tell it to load itself. // (See if its a known object first as its quicker to get it without reflection) SceneNode node = null; if (name.ToLower().EndsWith("binaryphoenix.fusion.engine.entitys.entitynode")) node = new EntityNode(); else if (name.ToLower().EndsWith("binaryphoenix.fusion.engine.entitys.scriptedentitynode")) node = new ScriptedEntityNode(); else if (name.ToLower().EndsWith("binaryphoenix.fusion.engine.scenenode")) node = new SceneNode(); else if (name.ToLower().EndsWith("binaryphoenix.fusion.engine.entitys.groupnode")) node = new GroupNode(); else if (name.ToLower().EndsWith("binaryphoenix.fusion.engine.entitys.emitternode")) node = new EmitterNode(); else if (name.ToLower().EndsWith("binaryphoenix.fusion.engine.entitys.tilemapsegmentnode")) node = new TilemapSegmentNode(); else if (name.ToLower().EndsWith("binaryphoenix.fusion.engine.entitys.pathmarkernode")) node = new PathMarkerNode(); else if (name.ToLower().EndsWith("binaryphoenix.fusion.engine.entitys.tilenode")) node = new TileNode(); else node = (SceneNode)ReflectionMethods.CreateObject(name); //DebugLogger.WriteLog("Created scene graph node " + name + " in " + timer.DurationMillisecond + ".\n"); //timer.Restart(); // Load in this nodes details. node.UniqueID = (_uniqueIDTracker++); node.Load(reader); //DebugLogger.WriteLog("Loaded scene graph node " + name + " in " + timer.DurationMillisecond + ".\n"); // Read in all the children of this node, and attach // them to this node. DebugLogger.IncreaseIndent(); int childCount = reader.ReadInt32(); for (int i = 0; i < childCount; i++) { SceneNode childNode = LoadNode(reader); node.AddChild(childNode); if (getProgress == true) _loadingProgress = (int)(((float)(i + 1) / (float)childCount) * 100.0f); } DebugLogger.DecreaseIndent(); return node; }
/// <summary> /// Saves this map into the given file you pass. /// </summary> /// <param name="url">Url of file to save map to.</param> /// <param name="baseNode">The base node that all saving should be started from, this allows you to ignore this node and any nodes higher in the graph like the Root Camera.</param> public void Save(object url, SceneNode baseNode) { // Try and open a stream to the file. Stream stream = StreamFactory.RequestStream(url, StreamMode.Truncate); if (stream == null) return; BinaryWriter writer = new BinaryWriter(stream); // Write in the magic number (Always FMP). writer.Write(new char[] { 'F', 'M', 'P' }); // Write in the file header. byte stateHeader = 0; if (_mapProperties.Compress == true) stateHeader |= 1; if (_mapProperties.Encrypt == true) stateHeader |= 2; if (_mapProperties.Name != null) stateHeader |= 4; if (_mapProperties.Author != null) stateHeader |= 8; if (_mapProperties.Description != null) stateHeader |= 16; if (_mapProperties.Version != 0) stateHeader |= 32; writer.Write(stateHeader); if (_mapProperties.Name != null) writer.Write(_mapProperties.Name); if (_mapProperties.Author != null) writer.Write(_mapProperties.Author); if (_mapProperties.Description != null) writer.Write(_mapProperties.Description); if (_mapProperties.Version != 0) writer.Write(_mapProperties.Version); // Create a new memory stream to write main data into. MemoryStream memStream = new MemoryStream(); BinaryWriter memStreamWriter = new BinaryWriter(memStream); // Write in a encryption / compression checker. if (_mapProperties.Compress == true || (_mapProperties.Encrypt && _mapProperties.Password != "")) memStreamWriter.Write(new char[] { 'C', 'H', 'K' }); // Save in the tileset pool used to render tilemap segments. memStreamWriter.Write((byte)Tileset.TilesetPool.Count); foreach (Tileset tileset in Tileset.TilesetPool) { memStreamWriter.Write(tileset.Url is string); if (tileset.Url is string) memStreamWriter.Write((string)tileset.Url); } // Tell the scene graph to save itself into the stream. _sceneGraph.Save(memStreamWriter, baseNode); // Close the memory stream. byte[] buffer = memStream.ToArray(); memStreamWriter.Close(); memStream.Close(); // Compress the data if required. if (_mapProperties.Compress == true) buffer = DataMethods.Deflate(buffer); // Encrypt the data if required. if (_mapProperties.Encrypt == true && _mapProperties.Password != "") buffer = DataMethods.Encrypt(buffer, _mapProperties.Password); // Write main data into main stream. writer.Write(buffer, 0, buffer.Length); // Sweep up the dirt. writer.Close(); }
/// <summary> /// Initializes a new instance of this class. /// </summary> /// <param name="nodes">Nodes that were inserted.</param> public InsertNodesUndoOperation(SceneNode[] nodes) { _nodes = nodes; foreach (SceneNode node in nodes) _nodeParents.Add(node, node.Parent); }