Ejemplo n.º 1
0
        // This loads the textures
        public override ICollection <ImageData> LoadSprites()
        {
            Dictionary <long, ImageData> images = new Dictionary <long, ImageData>();
            ICollection <ImageData>      collection;
            List <ImageData>             imgset = new List <ImageData>();

            // Error when suspended
            if (issuspended)
            {
                throw new Exception("Data reader is suspended");
            }

            // Load from wad files
            // Note the backward order, because the last wad's images have priority
            for (int i = wads.Count - 1; i >= 0; i--)
            {
                collection = wads[i].LoadSprites();
                AddImagesToList(images, collection);
            }

            // Load TEXTURES lump file
            imgset.Clear();
            string[] alltexturefiles = GetAllFilesWithTitle("", "TEXTURES", false);
            foreach (string texturesfile in alltexturefiles)
            {
                MemoryStream filedata = LoadFile(texturesfile);
                WADReader.LoadHighresSprites(filedata, texturesfile, ref imgset, null, null);
                filedata.Dispose();
            }

            // Add images from TEXTURES lump file
            AddImagesToList(images, imgset);

            return(new List <ImageData>(images.Values));
        }
Ejemplo n.º 2
0
    public void Awake()
    {
        using (var fs = new FileStream(WADFilename, FileMode.Open))
        {
            var  wad    = WADReader.GetInfo(fs);
            bool adding = false;
            foreach (var e in wad.Entries)
            {
                if (e.Name == "S_START")
                {
                    adding = true;
                    continue;
                }
                if (e.Name == "S_END")
                {
                    break;
                }

                if (!adding)
                {
                    continue;
                }
                SpriteEntries.Add(e);
            }

            AvailableSprites = new string[SpriteEntries.Count];
            for (int i = 0; i < AvailableSprites.Length; i++)
            {
                AvailableSprites[i] = SpriteEntries[i].Name;
            }
        }
    }
Ejemplo n.º 3
0
        public void ReadWAD(String p)
        {
            var reader = new WADReader(p);

            ContentHolder = reader.ReadFile();

            Debugger.Break();
        }
Ejemplo n.º 4
0
    void Start()
    {
        map = WADReader.LoadMap("E1M1");

        vertices = new List <Vector3>();
        List <CombineInstance> floorCIs = new List <CombineInstance>();

        foreach (SubSector ssector in map.subsectors)
        {
            List <Vector3> floorVerts = new List <Vector3>();
            //SubSector ssector = map.subsectors[0];
            for (int i = 0; i < ssector.num; i++)
            {
                Seg     seg     = map.segs[ssector.start + i];
                Vertex  vertS   = map.vertexes[seg.start];
                Vertex  vertE   = map.vertexes[seg.end];
                Linedef line    = map.linedefs[seg.linedef];
                Sidedef sideR   = map.sidedefs[line.right];
                Sector  sectorR = map.sectors[sideR.sector];
                if (line.left >= 0)
                {
                    Sidedef sideL   = map.sidedefs[line.left];
                    Sector  sectorL = map.sectors[sideL.sector];
                }
                Vector3 vStart = new Vector3(vertS.x, 0, vertS.y) * scale;
                Vector3 vEnd   = new Vector3(vertE.x, 0, vertE.y) * scale;
                /*if (!floorVerts.Contains(vStart))*/ floorVerts.Add(vStart);
                /*if (!floorVerts.Contains(vEnd))*/ floorVerts.Add(vEnd);
            }

            List <int> floorTris = new List <int>();
            int        p0        = 0;
            int        pHelper   = 1;
            for (int i = 2; i < floorVerts.Count; i++)
            {
                int pTemp = i;
                floorTris.AddRange(new int[] { p0, pHelper, pTemp });
                pHelper = pTemp;
            }

            CombineInstance ci   = new CombineInstance();
            Mesh            mesh = new Mesh();
            mesh.vertices  = floorVerts.ToArray();
            mesh.triangles = floorTris.ToArray();
            mesh.RecalculateNormals();
            ci.mesh      = mesh;
            ci.transform = transform.localToWorldMatrix;
            floorCIs.Add(ci);
        }

        Mesh combinedFloor = new Mesh();

        combinedFloor.CombineMeshes(floorCIs.ToArray());

        meshFilter.sharedMesh = combinedFloor;

        inited = true;
    }
Ejemplo n.º 5
0
 public void Generate()
 {
     using (var fs = new FileStream(WADFilename, FileMode.Open))
     {
         var pal = WADReader.GetPalette(fs, 0);
         var sd  = WADReader.GetPictureSprite(fs, SpriteEntries[TestSpriteIndex]);
         ResultTexture = SpriteGenerator.GenerateSprite(sd, pal);
     }
 }
Ejemplo n.º 6
0
        // This loads the textures
        public override ICollection <ImageData> LoadFlats()
        {
            Dictionary <long, ImageData> images = new Dictionary <long, ImageData>();
            ICollection <ImageData>      collection;
            List <ImageData>             imgset = new List <ImageData>();

            // Error when suspended
            if (issuspended)
            {
                throw new Exception("Data reader is suspended");
            }

            // Load from wad files
            // Note the backward order, because the last wad's images have priority
            for (int i = wads.Count - 1; i >= 0; i--)
            {
                collection = wads[i].LoadFlats();
                AddImagesToList(images, collection);
            }

            // Should we load the images in this directory as flats?
            if (rootflats)
            {
                collection = LoadDirectoryImages("", ImageDataFormat.DOOMFLAT, false);
                AddImagesToList(images, collection);
            }

            // Add images from flats directory
            collection = LoadDirectoryImages(FLATS_DIR, ImageDataFormat.DOOMFLAT, true);
            AddImagesToList(images, collection);

            // Add images to the container-specific texture set
            foreach (ImageData img in images.Values)
            {
                textureset.AddFlat(img);
            }

            // Load TEXTURES lump file
            imgset.Clear();
            string[] alltexturefiles = GetAllFilesWithTitle("", "TEXTURES", false);
            foreach (string texturesfile in alltexturefiles)
            {
                MemoryStream filedata = LoadFile(texturesfile);
                WADReader.LoadHighresFlats(filedata, texturesfile, ref imgset, null, images);
                filedata.Dispose();
            }

            // Add images from TEXTURES lump file
            AddImagesToList(images, imgset);

            return(new List <ImageData>(images.Values));
        }
Ejemplo n.º 7
0
        public ScriptResource(TextResourceData source, ScriptType type)
        {
            resource            = source.Source;
            resourcepath        = resource.Location.location;
            resourcedisplayname = resource.Location.GetDisplayName();
            filename            = source.Filename.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
            filepathname        = Path.Combine(resourcepath, filename);
            entries             = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
            lumpindex           = source.LumpIndex;
            scripttype          = type;
            isreadonly          = resource.IsReadOnly;

            // Embedded resources require additional tender loving care...
            if (resource is WADReader)
            {
                WADReader wr = (WADReader)resource;
                if (wr.ParentResource is PK3Reader)
                {
                    parentresourcelocation = wr.ParentResource.Location.location;
                }
            }
        }
Ejemplo n.º 8
0
    void Start()
    {
        playpal  = WADReader.GetPlaypal();
        colormap = WADReader.GetColormap();

        LUTTexture            = new Texture3D(textureSize, textureSize, textureSize, TextureFormat.RGB24, false);
        LUTTexture.filterMode = FilterMode.Point;
        Color[] colors = new Color[textureSize * textureSize * textureSize];
        for (int r = 0; r < textureSize; r++)
        {
            for (int g = 0; g < textureSize; g++)
            {
                for (int b = 0; b < textureSize; b++)
                {
                    Vector4 source = new Vector4(r, g, b) / textureSize;
                    Vector4 color  = Vector4.zero;
                    for (int i = 0; i < playpal.GetLength(1) / 3; i++)
                    {
                        Vector4 target = new Vector4(playpal[0, i * 3], playpal[0, i * 3 + 1], playpal[0, i * 3 + 2]) / 255;
                        if (Vector4.Distance(source, target) < Vector4.Distance(source, color))
                        {
                            color = target;
                        }
                    }
                    color.w = 1;
                    colors[r + g * textureSize + b * textureSize * textureSize] = color;
                }
            }
        }
        LUTTexture.SetPixels(colors);
        LUTTexture.Apply();

        ColorCorrectionLookup lookup = GetComponent <ColorCorrectionLookup>();

        lookup.converted3DLut = LUTTexture;
    }
Ejemplo n.º 9
0
        //mxd. This tries to find all possible sprite rotations. Returns true when voxel substitute exists
        internal bool SetupSpriteFrame(HashSet <string> allspritenames, HashSet <string> allvoxelnames)
        {
            // Empty, invalid or internal sprites don't have rotations
            // Info: we can have either partial 5-char sprite name from DECORATE parser,
            // or fully defined 6/8-char sprite name defined in Game configuration or by $Sprite property
            if (string.IsNullOrEmpty(sprite) || sprite.StartsWith(DataManager.INTERNAL_PREFIX) ||
                (sprite.Length != 5 && sprite.Length != 6 && sprite.Length != 8))
            {
                return(false);
            }

            string sourcename  = sprite.Substring(0, 4);
            char   sourceframe = sprite[4];

            // First try voxels
            if (allvoxelnames.Count > 0)
            {
                // Find a voxel, which matches sourcename
                HashSet <string> voxelnames = new HashSet <string>();
                foreach (string s in allvoxelnames)
                {
                    if (s.StartsWith(sourcename))
                    {
                        voxelnames.Add(s);
                    }
                }

                // Find a voxel, which matches baseframe
                // Valid voxel can be either 4-char (POSS), 5-char (POSSA) or 6-char (POSSA0)
                string newsprite = string.Empty;

                // Check 6-char voxels...
                foreach (string v in voxelnames)
                {
                    if (v.Length == 6 && v.StartsWith(sourcename + sourceframe) && WADReader.IsValidSpriteName(v))
                    {
                        newsprite = v;
                        break;
                    }
                }

                // Check 5-char voxels...
                if (voxelnames.Contains(sourcename + sourceframe))
                {
                    newsprite = sourcename + sourceframe;
                }

                // Check 4-char voxels...
                if (voxelnames.Contains(sourcename))
                {
                    newsprite = sourcename;
                }

                // Voxel found?
                if (!string.IsNullOrEmpty(newsprite))
                {
                    // Assign new sprite
                    sprite = newsprite;

                    // Recreate sprite frame
                    spriteframe = new[] { new SpriteFrameInfo {
                                              Sprite = sprite, SpriteLongName = Lump.MakeLongName(sprite, true)
                                          } };

                    // Substitute voxel found
                    return(true);
                }
            }

            // Then try sprites
            // Find a sprite, which matches sourcename
            string           sourcesprite = string.Empty;
            HashSet <string> spritenames  = new HashSet <string>();

            foreach (string s in allspritenames)
            {
                if (s.StartsWith(sourcename))
                {
                    spritenames.Add(s);
                }
            }

            // Find a sprite, which matches baseframe
            foreach (string s in spritenames)
            {
                if (s[4] == sourceframe || (s.Length == 8 && s[6] == sourceframe))
                {
                    sourcesprite = s;
                    break;
                }
            }

            // Abort if no sprite was found
            if (string.IsNullOrEmpty(sourcesprite))
            {
                return(false);
            }

            // Get sprite angle
            string anglestr = sourcesprite.Substring(5, 1);
            int    sourceangle;

            if (!int.TryParse(anglestr, NumberStyles.Integer, CultureInfo.InvariantCulture, out sourceangle))
            {
                General.ErrorLogger.Add(ErrorType.Error, "Error in actor \"" + title + "\":" + index + ". Unable to get sprite angle from sprite \"" + sourcesprite + "\"");
                return(false);
            }

            if (sourceangle < 0 || sourceangle > 8)
            {
                General.ErrorLogger.Add(ErrorType.Error, "Error in actor \"" + title + "\":" + index + ", sprite \"" + sourcesprite + "\". Sprite angle must be in [0..8] range");
                return(false);
            }

            // No rotations? Then spriteframe is already setup
            if (sourceangle == 0)
            {
                // Sprite name still incomplete?
                if (sprite.Length < 6)
                {
                    sprite = sourcesprite;

                    // Recreate sprite frame. Mirror the sprite if sourceframe matches the second frame block
                    spriteframe = new[] { new SpriteFrameInfo {
                                              Sprite = sprite, SpriteLongName = Lump.MakeLongName(sprite, true),
                                              Mirror = (sprite.Length == 8 && sprite[6] == sourceframe)
                                          } };
                }

                return(false);
            }

            // Gather rotations
            string[] frames         = new string[8];
            bool[]   mirror         = new bool[8];
            int      processedcount = 0;

            // Process gathered sprites
            foreach (string s in spritenames)
            {
                // Check first frame block
                char targetframe = s[4];
                if (targetframe == sourceframe)
                {
                    // Check angle
                    int targetangle;
                    anglestr = s.Substring(5, 1);
                    if (!int.TryParse(anglestr, NumberStyles.Integer, CultureInfo.InvariantCulture, out targetangle))
                    {
                        General.ErrorLogger.Add(ErrorType.Error, "Error in actor \"" + title + "\":" + index + ". Unable to get sprite angle from sprite \"" + s + "\"");
                        return(false);
                    }

                    // Sanity checks
                    if (targetangle == 0)
                    {
                        General.ErrorLogger.Add(ErrorType.Warning, "Warning: actor \"" + title + "\":" + index + ", sprite \"" + sourcename + "\", frame " + targetframe + " has both rotated and non-rotated versions");
                        continue;
                    }

                    // More sanity checks
                    if (targetangle < 1 || targetangle > 8)
                    {
                        General.ErrorLogger.Add(ErrorType.Error, "Error in actor \"" + title + "\":" + index + ", sprite \"" + s + "\". Expected sprite angle in [1..8] range");
                        return(false);
                    }

                    // Even more sanity checks
                    if (!string.IsNullOrEmpty(frames[targetangle - 1]))
                    {
                        General.ErrorLogger.Add(ErrorType.Warning, "Warning in actor \"" + title + "\":" + index
                                                + ". Sprite \"" + sourcename + "\", frame " + targetframe + ", angle " + targetangle
                                                + " is double-defined in sprites \"" + frames[targetangle - 1] + "\" and \"" + s + "\"");
                    }
                    else
                    {
                        // Add to collection
                        frames[targetangle - 1] = s;
                        processedcount++;
                    }
                }

                // Check second frame block?
                if (s.Length == 6)
                {
                    continue;
                }

                targetframe = s[6];
                if (targetframe == sourceframe)
                {
                    // Check angle
                    int targetangle;
                    anglestr = s.Substring(7, 1);
                    if (!int.TryParse(anglestr, NumberStyles.Integer, CultureInfo.InvariantCulture, out targetangle))
                    {
                        General.ErrorLogger.Add(ErrorType.Error, "Error in actor \"" + title + "\":" + index + ". Unable to get sprite angle from sprite \"" + s + "\"");
                        return(false);
                    }

                    // Sanity checks
                    if (targetangle == 0)
                    {
                        General.ErrorLogger.Add(ErrorType.Warning, "Warning: actor \"" + title + "\":" + index + ", sprite \"" + sourcename + "\", frame " + targetframe + " has both rotated and non-rotated versions");
                        continue;
                    }

                    // More sanity checks
                    if (targetangle < 1 || targetangle > 8)
                    {
                        General.ErrorLogger.Add(ErrorType.Error, "Error in actor \"" + title + "\":" + index + ", sprite \"" + s + "\". Expected sprite angle in [1..8] range");
                        return(false);
                    }

                    // Even more sanity checks
                    if (!string.IsNullOrEmpty(frames[targetangle - 1]))
                    {
                        General.ErrorLogger.Add(ErrorType.Warning, "Warning in actor \"" + title + "\":" + index
                                                + ". Sprite \"" + sourcename + "\", frame " + targetframe + ", angle " + targetangle
                                                + " is double-defined in sprites \"" + frames[targetangle - 1] + "\" and \"" + s + "\"");
                    }
                    else
                    {
                        // Add to collections
                        frames[targetangle - 1] = s;
                        mirror[targetangle - 1] = true;
                        processedcount++;
                    }
                }

                // Gathered all sprites?
                if (processedcount == 8)
                {
                    break;
                }
            }

            // Check collected data
            if (processedcount != 8)
            {
                // Check which angles are missing
                List <string> missingangles = new List <string>();
                for (int i = 0; i < frames.Length; i++)
                {
                    if (string.IsNullOrEmpty(frames[i]))
                    {
                        missingangles.Add((i + 1).ToString());
                    }
                }

                // Assemble angles to display
                string ma = string.Join(", ", missingangles.ToArray());
                if (missingangles.Count > 2)
                {
                    int pos = ma.LastIndexOf(",", StringComparison.Ordinal);
                    if (pos != -1)
                    {
                        ma = ma.Remove(pos, 1).Insert(pos, " and");
                    }
                }

                General.ErrorLogger.Add(ErrorType.Error, "Error in actor \"" + title + "\":" + index + ". Sprite rotations " + ma + " for sprite " + sourcename + ", frame " + sourceframe + " are missing");
                return(false);
            }

            // Create collection
            spriteframe = new SpriteFrameInfo[frames.Length];
            for (int i = 0; i < frames.Length; i++)
            {
                spriteframe[i] = new SpriteFrameInfo {
                    Sprite = frames[i], SpriteLongName = Lump.MakeLongName(frames[i]), Mirror = mirror[i]
                };
            }

            // Update preview sprite
            sprite = spriteframe[1].Sprite;

            // Done
            return(false);
        }
Ejemplo n.º 10
0
        // This loads the textures
        public override ICollection <ImageData> LoadTextures(PatchNames pnames)
        {
            Dictionary <long, ImageData> images = new Dictionary <long, ImageData>();
            ICollection <ImageData>      collection;
            List <ImageData>             imgset = new List <ImageData>();

            // Error when suspended
            if (issuspended)
            {
                throw new Exception("Data reader is suspended");
            }

            // Load from wad files (NOTE: backward order, because the last wad's images have priority)
            for (int i = wads.Count - 1; i >= 0; i--)
            {
                collection = wads[i].LoadTextures(pnames);
                AddImagesToList(images, collection);
            }

            // Should we load the images in this directory as textures?
            if (roottextures)
            {
                collection = LoadDirectoryImages("", ImageDataFormat.DOOMPICTURE, false);
                AddImagesToList(images, collection);
            }

            // Add images from texture directory
            collection = LoadDirectoryImages(TEXTURES_DIR, ImageDataFormat.DOOMPICTURE, true);
            AddImagesToList(images, collection);

            // Load TEXTURE1 lump file
            imgset.Clear();
            string texture1file = FindFirstFile("TEXTURE1", false);

            if ((texture1file != null) && FileExists(texture1file))
            {
                MemoryStream filedata = LoadFile(texture1file);
                WADReader.LoadTextureSet("TEXTURE1", filedata, ref imgset, pnames);
                filedata.Dispose();
            }

            // Load TEXTURE2 lump file
            string texture2file = FindFirstFile("TEXTURE2", false);

            if ((texture2file != null) && FileExists(texture2file))
            {
                MemoryStream filedata = LoadFile(texture2file);
                WADReader.LoadTextureSet("TEXTURE2", filedata, ref imgset, pnames);
                filedata.Dispose();
            }

            // Add images from TEXTURE1 and TEXTURE2 lump files
            AddImagesToList(images, imgset);

            // Load TEXTURES lump file
            imgset.Clear();
            string[] alltexturefiles = GetAllFilesWithTitle("", "TEXTURES", false);
            foreach (string texturesfile in alltexturefiles)
            {
                MemoryStream filedata = LoadFile(texturesfile);
                WADReader.LoadHighresTextures(filedata, texturesfile, ref imgset, images, null);
                filedata.Dispose();
            }

            // Add images from TEXTURES lump file
            AddImagesToList(images, imgset);

            // Add images to the container-specific texture set
            foreach (ImageData img in images.Values)
            {
                textureset.AddImage(img);
            }

            return(new List <ImageData>(images.Values));
        }
Ejemplo n.º 11
0
		private void UpdateResourcesTree(ScriptType filtertype, string filterfilename)
		{
			TreeNode selected = projecttree.SelectedNode;
			TreeNode toselect = null;
			
			projecttree.BeginUpdate();
			projecttree.Nodes.Clear();

			char[] splitter = { Path.DirectorySeparatorChar };
			bool filenamefiltered = !string.IsNullOrEmpty(filterfilename);
			bool filteringapplied = (filenamefiltered || filtertype != ScriptType.UNKNOWN);

			// Create nodes
			foreach(KeyValuePair<string, Dictionary<ScriptType, HashSet<ScriptResource>>> group in resourcesperlocation)
			{
				foreach(ScriptTypeItem item in usedscripttypes)
				{
					// Filter by script type?
					if(filtertype != ScriptType.UNKNOWN && item.Type != filtertype) continue;

					// Current resource has this scrit type?
					if(!group.Value.ContainsKey(item.Type)) continue;

					HashSet<ScriptResource> resources = group.Value[item.Type];
					foreach(ScriptResource res in resources)
					{
						bool asreadonly = res.Resource.IsReadOnly;
						
						// Filter by filename?
						if(filenamefiltered && Path.GetFileName(res.Filename).IndexOf(filterfilename, StringComparison.OrdinalIgnoreCase) == -1)
							continue;

						// Resource type node added?
						TreeNode root;
						string key = res.Resource.Location.location;
						
						// WAD resource inside another resource?
						if(res.Resource is WADReader && ((WADReader)res.Resource).ParentResource != null)
						{
							WADReader wr = (WADReader)res.Resource;
							string parentkey = wr.ParentResource.Location.location;
							TreeNode parent = GetResourceNode(projecttree.Nodes, wr.ParentResource.Location.GetDisplayName(), parentkey, wr.ParentResource);

							if(parent.Nodes.ContainsKey(key))
							{
								root = parent.Nodes[key];
							}
							else
							{
								root = GetResourceNode(parent.Nodes, Path.GetFileName(wr.Location.GetDisplayName()), key, res.Resource);
								TrySelectNode(selected, root, ref toselect);
							}
						}
						else if(projecttree.Nodes.ContainsKey(key))
						{
							root = projecttree.Nodes[key];
						}
						else
						{
							root = GetResourceNode(projecttree.Nodes, res.Resource.Location.GetDisplayName(), key, res.Resource);
							TrySelectNode(selected, root, ref toselect);
						}

						// Single resource item or active filtering?
						int iconindex = scriptpanel.Icons.GetScriptIcon(res.ScriptType);
						if(filteringapplied || (resources.Count == 1 && res.ScriptType != ScriptType.ACS))
						{
							// Create new node
							var data = new TextResourceNodeData
									   {
										   ResourceLocation = key, 
										   LocationInResource = Path.GetDirectoryName(res.Filename), 
										   NodeType = TextResourceNodeType.NODE, 
										   Resource = res, 
										   ScriptType = res.ScriptType,
									   };
							TreeNode scriptnode = new TreeNode(res.ToString(), iconindex, iconindex) { Tag = data, ToolTipText = data.ToString() };
							if(asreadonly) scriptnode.ForeColor = SystemColors.GrayText;
							TrySelectNode(selected, scriptnode, ref toselect);

							// Add the node
							root.Nodes.Add(scriptnode);
						}
						else
						{
							// Script type added?
							string typename = "[" + Enum.GetName(typeof(ScriptType), res.ScriptType) + "]";
							int groupiconindex = scriptpanel.Icons.GetScriptFolderIcon(res.ScriptType, false);

							TreeNode scriptroot;
							if(root.Nodes.ContainsKey(typename))
							{
								scriptroot = root.Nodes[typename];
							}
							else
							{
								var rdata = new TextResourceNodeData
											{
												ResourceLocation = key,
												NodeType = TextResourceNodeType.DIRECTORY,
												ScriptType = res.ScriptType,
											};
								scriptroot = new TreeNode(typename, groupiconindex, groupiconindex)
											 {
												 Tag = rdata, 
												 Name = typename, 
												 ToolTipText = rdata.ToString()
											 };
								if(asreadonly) scriptroot.ForeColor = SystemColors.GrayText;
								root.Nodes.Add(scriptroot);
								
								TrySelectNode(selected, scriptroot, ref toselect);
							}

							// Add the resource path nodes if needed...
							string path = Path.GetDirectoryName(res.Filename);
							TreeNode pathnode = scriptroot;
							string localpath = string.Empty;

							if(!string.IsNullOrEmpty(path))
							{
								List<string> parts = new List<string>(path.Split(splitter, StringSplitOptions.RemoveEmptyEntries));
								while(parts.Count > 0)
								{
									if(pathnode.Nodes.ContainsKey(parts[0]))
									{
										pathnode = pathnode.Nodes[parts[0]];
									}
									else
									{
										localpath = Path.Combine(localpath, parts[0]);

										TreeNode child = new TreeNode(parts[0], groupiconindex, groupiconindex);
										child.Name = parts[0];
										var cdata = new TextResourceNodeData
										            {
											            ResourceLocation = key, 
														LocationInResource = path, 
														NodeType = TextResourceNodeType.DIRECTORY, 
														ScriptType = res.ScriptType
										            };
										child.Tag = cdata;
										child.ToolTipText = cdata.ToString();
										if(asreadonly) child.ForeColor = SystemColors.GrayText;
										pathnode.Nodes.Add(child);
										pathnode = child;
										
										TrySelectNode(selected, pathnode, ref toselect);
									}

									parts.RemoveAt(0);
								}
							}

							// Create new node
							TextResourceNodeData data = new TextResourceNodeData
							                            {
								                            ResourceLocation = key, 
															LocationInResource = path, 
															NodeType = TextResourceNodeType.NODE, 
															Resource = res,
															ScriptType = res.ScriptType,
							                            };
							string includepath = (res.ScriptType == ScriptType.ACS ? "\nInclude path: \"" + res.Filename + "\"" : "");
							TreeNode scriptnode = new TreeNode(res.ToString(), iconindex, iconindex) { Tag = data, ToolTipText = data + includepath };
							if(asreadonly) scriptnode.ForeColor = SystemColors.GrayText;
							TrySelectNode(selected, scriptnode, ref toselect);

							// Add the node
							pathnode.Nodes.Add(scriptnode);
						}
					}
				}
			}

			// If there's only one root node, shift all nodes up
			if(projecttree.Nodes.Count == 1 && projecttree.Nodes[0].Nodes.Count > 0)
			{
				TreeNode[] children = new TreeNode[projecttree.Nodes[0].Nodes.Count];
				projecttree.Nodes[0].Nodes.CopyTo(children, 0);

				projecttree.Nodes.Clear();
				projecttree.Nodes.AddRange(children);
			}

			// Sort the nodes
			projecttree.TreeViewNodeSorter = new ScriptNodesSorter();
			
			// Have valid selection?
			if(toselect != null) projecttree.SelectedNode = toselect;

			// Expand all nodes when filtered
			if(filenamefiltered) projecttree.ExpandAll();

			projecttree.EndUpdate();
		}