////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Loads a structure bsp. </summary>
        ///
        /// <param name="path">	Tags relative pathname of the bsp tag. </param>
        ///
        /// <returns>	The loaded structure bsp. </returns>
        structure_bsp_group LoadStructureBSP(string tagsDirectory, string path)
        {
            // Load the structure bsp
            var tagsPath = new BlamPath(tagsDirectory);

            mTagHandler = new TagIndexHandler <BlamLib.Managers.TagIndex>(BlamLib.BlamVersion.Halo1_CE, tagsPath.Root);

            mBSPDatumIndex = mTagHandler.IndexInterface.Open(path, BlamLib.Blam.Halo1.TagGroups.sbsp);
            if (!BlamLib.Managers.TagIndex.IsValid(mBSPDatumIndex))
            {
                SendMessage("Failed to load the target BSP");
                return(null);
            }

            var tagManager   = mTagHandler.IndexInterface[mBSPDatumIndex];
            var structureBSP = tagManager.TagDefinition as structure_bsp_group;

            if (structureBSP == null)
            {
                SendMessage("Failed to load the target BSP");
                return(null);
            }

            return(structureBSP);
        }
		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Loads a structure bsp. </summary>
		///
		/// <param name="path">	Tags relative pathname of the bsp tag. </param>
		///
		/// <returns>	The loaded structure bsp. </returns>
		structure_bsp_group LoadStructureBSP(string tagsDirectory, string path)
		{
			// Load the structure bsp
			var tagsPath = new BlamPath(tagsDirectory);
			mTagHandler = new TagIndexHandler<BlamLib.Managers.TagIndex>(BlamLib.BlamVersion.Halo1_CE, tagsPath.Root);

			mBSPDatumIndex = mTagHandler.IndexInterface.Open(path, BlamLib.Blam.Halo1.TagGroups.sbsp);
			if (!BlamLib.Managers.TagIndex.IsValid(mBSPDatumIndex))
			{
				SendMessage("Failed to load the target BSP");
				return null;
			}

			var tagManager = mTagHandler.IndexInterface[mBSPDatumIndex];
			var structureBSP = tagManager.TagDefinition as structure_bsp_group;
			if (structureBSP == null)
			{
				SendMessage("Failed to load the target BSP");
				return null;
			}

			return structureBSP;
		}
        /// <summary>	Imports lightmap coordinates into a bsp. </summary>
        public void ImportLightmap()
        {
            // Verify the directory settings are correct
            var importerSettings = GetImporterSettings();

            if (!Directory.Exists(importerSettings.DataFolder))
            {
                mMessageHandler.SendMessage("The selected data directory does not exist");
                return;
            }

            if (!Directory.Exists(importerSettings.TagsFolder))
            {
                mMessageHandler.SendMessage("The selected tags directory does not exist");
                return;
            }

            var tagsDir = new BlamPath(importerSettings.TagsFolder);
            var dataDir = new BlamPath(importerSettings.DataFolder);

            // Get the input files
            string structureBSPPath = GetInputFile(GetImporterSettings().TagsFolder, "Select the BSP tag", "Structure BSP (*.scenario_structure_bsp)|*.scenario_structure_bsp");

            if (String.IsNullOrEmpty(structureBSPPath))
            {
                mMessageHandler.SendMessage("No BSP tag was selected");
                return;
            }

            string colladaPath = GetInputFile(GetImporterSettings().DataFolder, "Select the COLLADA file", "COLLADA (*.dae)|*.dae");

            if (String.IsNullOrEmpty(colladaPath))
            {
                mMessageHandler.SendMessage("No COLLADA file was selected");
                return;
            }

            // Verify the selected files are under the right directories
            var absoluteBSPFile = Path.GetFullPath(structureBSPPath);

            if (System.String.Compare(absoluteBSPFile, 0, tagsDir.AbsoluteFolder, 0, tagsDir.AbsoluteFolder.Length, true) != 0)
            {
                System.Windows.Forms.MessageBox.Show("The selected BSP file is not under the tags directory", "Invalid File Path", System.Windows.Forms.MessageBoxButtons.OK);
                return;
            }

            var absoluteCOLLADAFile = Path.GetFullPath(colladaPath);

            if (System.String.Compare(absoluteCOLLADAFile, 0, dataDir.AbsoluteFolder, 0, dataDir.AbsoluteFolder.Length, true) != 0)
            {
                System.Windows.Forms.MessageBox.Show("The selected COLLADA file is not under the data directory", "Invalid File Path", System.Windows.Forms.MessageBoxButtons.OK);
                return;
            }

            // Run the import process
            var lightmapImporter = new Importer.LightmapImporter();

            SetState(LightmapImporterStateEnum.ImporterImporting);
            lightmapImporter.MessageSent += MessageRedirect;

            var tagPath = new BlamTagPath(tagsDir.AbsoluteFolder);

            tagPath.SetPath(absoluteBSPFile);

            bool result = lightmapImporter.ImportTexcoords(tagsDir.AbsoluteFolder, tagPath.TagPath, absoluteCOLLADAFile);

            lightmapImporter.MessageSent -= MessageRedirect;
            SetState(LightmapImporterStateEnum.ImporterReady);

            if (!result)
            {
                mMessageHandler.SendMessage("Lightmap UV import failed");
                return;
            }

            mMessageHandler.SendMessage("Lightmap UV import completed");
        }
        /// <summary>	Extracts a model. </summary>
        public void Extract()
        {
            var extractorSettings = SettingsHandler.ModelExtractor.Extractor;

            if (!Directory.Exists(extractorSettings.DataFolder))
            {
                mMessageHandler.SendMessage("The selected data directory does not exist");
                return;
            }

            if (!Directory.Exists(extractorSettings.TagsFolder))
            {
                mMessageHandler.SendMessage("The selected tags directory does not exist");
                return;
            }

            var tagsDir = new BlamPath(extractorSettings.TagsFolder);
            var dataDir = new BlamPath(extractorSettings.DataFolder);

            // Get the input files
            var modelFiles = GetInputFiles(tagsDir.AbsoluteFolder);

            if (modelFiles == null)
            {
                mMessageHandler.SendMessage("No models selected");
                return;
            }

            // Check that all of the selected models reside in the tags directory
            foreach (var modelFile in modelFiles)
            {
                var absoluteModelFile = Path.GetFullPath(modelFile);
                if (System.String.Compare(absoluteModelFile, 0, tagsDir.AbsoluteFolder, 0, tagsDir.AbsoluteFolder.Length, true) != 0)
                {
                    System.Windows.Forms.MessageBox.Show("A selected model file is not under the tags directory", "Invalid File Path", System.Windows.Forms.MessageBoxButtons.OK);
                    return;
                }
            }

            // Partially set up the model extraction data
            var modelExtractionData = new ModelExtractionData()
            {
                JobInterface = this,

                TagsDirectory = tagsDir,
                DataDirectory = dataDir
            };

            // Build the Collada settings
            var colladaSettings         = SettingsHandler.ModelExtractor.Collada;
            var colladaSettingsInstance = new ColladaSettingsInstance()
            {
                Overwrite     = colladaSettings.Overwrite,
                BitmapFormat  = colladaSettings.BitmapFormat,
                RootDirectory = dataDir.AbsoluteFolder
            };

            // Create extraction jobs for the selected models
            foreach (var modelFile in modelFiles)
            {
                var extractionData = new ExtractionData();

                extractionData.Set(modelExtractionData);
                extractionData.Set(colladaSettingsInstance, typeof(IColladaSettings));

                foreach (var extractorUI in mExtractors)
                {
                    var data = extractorUI.GetExtractionData();

                    if (data != null)
                    {
                        extractionData.Set(data);
                    }
                }

                AddJob(modelFile, extractionData);
            }
        }