Inheritance: System.Windows.Forms.Form
Esempio n. 1
0
		private static System.Collections.IEnumerable FirstTimeSetup(ProcessingBigTaskDialog.WorkerInterface workerInterface)
		{
			PackageManager manager = workerInterface.Data as PackageManager;
			LocalPackage[] packagesToVerify = manager.LocalPackages.ToArray();

			foreach (LocalPackage package in packagesToVerify)
			{
				if (package.Version != null)
					workerInterface.StateDesc = string.Format("Package '{0}', Version {1}...", package.Id, package.Version);
				else
					workerInterface.StateDesc = string.Format("Package '{0}'...", package.Id);
				workerInterface.Progress += 0.5f / packagesToVerify.Length;
				yield return null;

				try
				{
					manager.VerifyPackage(package);
				}
				catch (Exception e)
				{
					Log.Editor.WriteError("An error occurred verifying Package '{0}', Version {1}: {2}", 
						package.Id, 
						package.Version, 
						Log.Exception(e));
				}
				workerInterface.Progress += 0.5f / packagesToVerify.Length;
				yield return null;
			}

			yield break;
		}
Esempio n. 2
0
		private static void Main(string[] args)
		{
			// Parse command line arguments
			bool recover = false;
			foreach (string a in args)
			{
				if (a == "debug")
					System.Diagnostics.Debugger.Launch();
				else if (a == "recover")
					recover = true;
			}

			// Culture setup
			Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
			Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;

			Application.CurrentCulture = Thread.CurrentThread.CurrentCulture;
			Application.EnableVisualStyles();
			Application.SetCompatibleTextRenderingDefault(false);
			Application.ThreadException += Application_ThreadException;

			// Perform the initial package update - even before initializing the editor
			{
				PackageManager packageManager = new PackageManager();
				if (packageManager.IsPackageUpdateRequired)
				{
					Log.Editor.Write("Updating Packages...");
					Log.Editor.PushIndent();
					ProcessingBigTaskDialog setupDialog = new ProcessingBigTaskDialog(
						GeneralRes.TaskInstallPackages_Caption, 
						GeneralRes.TaskInstallPackages_Desc, 
						FirstTimeSetup, 
						packageManager);
					setupDialog.ShowInTaskbar = true;
					setupDialog.MainThreadRequired = false;
					setupDialog.ShowDialog();
					Log.Editor.PopIndent();
				}
				if (packageManager.ApplyUpdate())
				{
					Application.Exit();
					return;
				}
			}

			// Run the editor
			SplashScreen splashScreen = new SplashScreen(recover);
			splashScreen.Show();
			Application.Run();
		}
Esempio n. 3
0
        private void formatXml_Click(object sender, EventArgs e)
        {
            if (Duality.Serialization.Serializer.DefaultMethod == Duality.Serialization.SerializeMethod.Xml) return;
            Duality.Serialization.Serializer.DefaultMethod = Duality.Serialization.SerializeMethod.Xml;
            this.UpdateToolbar();

            ProcessingBigTaskDialog taskDialog = new ProcessingBigTaskDialog(this,
                Properties.GeneralRes.TaskChangeDataFormat_Caption,
                string.Format(Properties.GeneralRes.TaskChangeDataFormat_Desc, Duality.Serialization.Serializer.DefaultMethod.ToString()),
                this.async_ChangeDataFormat, null);
            taskDialog.ShowDialog();
        }
Esempio n. 4
0
 private void formatUpdateAll_Click(object sender, EventArgs e)
 {
     ProcessingBigTaskDialog taskDialog = new ProcessingBigTaskDialog(this,
         Properties.GeneralRes.TaskFormatUpdateAll_Caption,
         Properties.GeneralRes.TaskFormatUpdateAll_Desc,
         this.async_ChangeDataFormat, null);
     taskDialog.ShowDialog();
 }
Esempio n. 5
0
        private System.Collections.IEnumerable async_ChangeDataFormat(ProcessingBigTaskDialog.WorkerInterface state)
        {
            state.StateDesc = "DualityApp Data"; yield return null;
            DualityApp.LoadAppData();
            DualityApp.LoadUserData();
            state.Progress += 0.05f; yield return null;

            DualityApp.SaveAppData();
            DualityApp.SaveUserData();
            state.Progress += 0.05f; yield return null;

            // Special case: Current Scene in sandbox mode
            if (Sandbox.IsActive && !string.IsNullOrEmpty(Scene.CurrentPath))
            {
                // Because changes we'll do will be discarded when leaving the sandbox we'll need to
                // do it the hard way - manually load an save the file.
                state.StateDesc = "Current Scene"; yield return null;
                Scene curScene = Resource.Load<Scene>(Scene.CurrentPath, null, false);
                if (curScene != null)
                {
                    curScene.Save(null, false);
                }
            }

            var loadedContent = ContentProvider.GetLoadedContent<Resource>();
            string[] resFiles = Resource.GetResourceFiles().ToArray();
            foreach (string file in resFiles)
            {
                if (Sandbox.IsActive && file == Scene.CurrentPath) continue; // Skip current Scene in Sandbox
                state.StateDesc = file; yield return null;

                // Wasn't loaded before? Unload it later to keep the memory footprint small.
                bool wasLoaded = loadedContent.Any(r => r.Path == file);

                if (wasLoaded)
                {
                    // Retrieve already loaded content
                    var cr = ContentProvider.RequestContent(file);
                    state.Progress += 0.45f / resFiles.Length; yield return null;

                    // Perform rename and flag unsaved / modified
                    cr.Res.Save();
                    state.Progress += 0.45f / resFiles.Length; yield return null;
                }
                else
                {
                    // Load content without initializing it
                    Resource res = Resource.Load<Resource>(file, null, false);
                    state.Progress += 0.45f / resFiles.Length; yield return null;

                    // Perform rename and save it without making it globally available
                    res.Save(null, false);
                    state.Progress += 0.45f / resFiles.Length; yield return null;
                }
            }
        }
Esempio n. 6
0
        private void formatSetDefault_Click(object sender, EventArgs e)
        {
            MenuModelItem item = sender as MenuModelItem;

            Type clickedSerializerType = item.Tag as Type;
            if (clickedSerializerType == null) return;
            if (clickedSerializerType == Serializer.DefaultType) return;

            Serializer.DefaultType = clickedSerializerType;
            this.UpdateToolbar();

            ProcessingBigTaskDialog taskDialog = new ProcessingBigTaskDialog(this,
                Properties.GeneralRes.TaskChangeDataFormat_Caption,
                string.Format(Properties.GeneralRes.TaskChangeDataFormat_Desc, Serializer.DefaultType.ToString()),
                this.async_ChangeDataFormat, null);
            taskDialog.ShowDialog();
        }
Esempio n. 7
0
        private static void Main(string[] args)
        {
            // Parse command line arguments
            bool recover = false;
            foreach (string a in args)
            {
                if (a == "debug")
                    System.Diagnostics.Debugger.Launch();
                else if (a == "recover")
                    recover = true;
            }

            // Culture setup
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
            Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;

            // Set up file logging
            StreamWriter logfileWriter = null;
            TextWriterLogOutput logfileOutput = null;
            try
            {
                // If there is an existing logfile, preserve it under a different name
                if (File.Exists(DualityEditorApp.EditorLogfilePath))
                {
                    if (File.Exists(DualityEditorApp.EditorPrevLogfilePath))
                        File.Delete(DualityEditorApp.EditorPrevLogfilePath);
                    File.Move(DualityEditorApp.EditorLogfilePath, DualityEditorApp.EditorPrevLogfilePath);
                }

                // Create a new logfile
                logfileWriter = new StreamWriter(DualityEditorApp.EditorLogfilePath);
                logfileWriter.AutoFlush = true;
                logfileOutput = new TextWriterLogOutput(logfileWriter);
                Log.AddGlobalOutput(logfileOutput);
            }
            catch (Exception e)
            {
                Log.Core.WriteWarning("Text Logfile unavailable: {0}", Log.Exception(e));
            }

            // Winforms Setup
            Application.CurrentCulture = Thread.CurrentThread.CurrentCulture;
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.ThreadException += Application_ThreadException;

            {
                PackageManager packageManager = new PackageManager();

                // On the first install startup, display a generic license agreement for Duality
                if (packageManager.IsFirstInstall)
                {
                    LicenseAcceptDialog licenseDialog = new LicenseAcceptDialog
                    {
                        DescriptionText = GeneralRes.LicenseAcceptDialog_FirstStartGeneric,
                        LicenseUrl = new Uri(DualityMainLicenseUrl)
                    };
                    DialogResult result = licenseDialog.ShowDialog();
                    if (result != DialogResult.OK)
                    {
                        Application.Exit();
                        return;
                    }
                }

                // Perform the initial package update - even before initializing the editor
                if (packageManager.IsPackageSyncRequired)
                {
                    Log.Editor.Write("Updating Packages...");
                    Log.Editor.PushIndent();
                    ProcessingBigTaskDialog setupDialog = new ProcessingBigTaskDialog(
                        GeneralRes.TaskInstallPackages_Caption,
                        GeneralRes.TaskInstallPackages_Desc,
                        SynchronizePackages,
                        packageManager);
                    setupDialog.ShowInTaskbar = true;
                    setupDialog.MainThreadRequired = false;
                    setupDialog.ShowDialog();
                    Log.Editor.PopIndent();
                }
                if (packageManager.ApplyUpdate())
                {
                    Application.Exit();
                    return;
                }
            }

            // Run the editor
            SplashScreen splashScreen = new SplashScreen(recover);
            splashScreen.Show();
            Application.Run();

            // Clean up the log file
            if (logfileWriter != null)
            {
                Log.RemoveGlobalOutput(logfileOutput);
                logfileWriter.Flush();
                logfileWriter.Close();
                logfileWriter = null;
                logfileOutput = null;
            }
        }
Esempio n. 8
0
        private static System.Collections.IEnumerable SynchronizePackages(ProcessingBigTaskDialog.WorkerInterface workerInterface)
        {
            PackageManager manager = workerInterface.Data as PackageManager;

            // Set the working state and yield, so the UI can update properly in case we're in the main thread
            workerInterface.Progress = 0.0f;
            workerInterface.StateDesc = GeneralRes.TaskPrepareInfo;
            yield return null;

            // Retrieve all registered Duality packages and sort them so we don't accidentally install an old dependency
            LocalPackage[] packagesToVerify = manager.LocalPackages.ToArray();
            manager.OrderByDependencies(packagesToVerify);
            yield return null;

            // Uninstall all "shadow" Duality packages that are installed, but not registered
            manager.UninstallNonRegisteredPackages();
            yield return null;

            // Iterate over previously reigstered local packages and verify / install them.
            foreach (LocalPackage package in packagesToVerify)
            {
                // Update the task dialog's UI
                if (package.Version != null)
                    workerInterface.StateDesc = string.Format("Package '{0}', Version {1}...", package.Id, package.Version);
                else
                    workerInterface.StateDesc = string.Format("Package '{0}'...", package.Id);
                workerInterface.Progress += 0.5f / packagesToVerify.Length;
                yield return null;

                // Verify / Install the local package as needed
                try
                {
                    manager.VerifyPackage(package);
                }
                catch (Exception e)
                {
                    Log.Editor.WriteError("An error occurred verifying Package '{0}', Version {1}: {2}",
                        package.Id,
                        package.Version,
                        Log.Exception(e));
                }
                workerInterface.Progress += 0.5f / packagesToVerify.Length;
                yield return null;
            }

            yield break;
        }
Esempio n. 9
0
        private void batchActionRenameType_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderDialog = new FolderBrowserDialog();
            folderDialog.ShowNewFolderButton = false;
            folderDialog.SelectedPath = Path.GetFullPath(DualityApp.DataDirectory);
            folderDialog.Description = "Select a folder to process..";
            if (folderDialog.ShowDialog(this) == DialogResult.OK)
            {
                RenameTypeDialog dialog = new RenameTypeDialog(this.GetAvailTypes());
                if (dialog.ShowDialog(this) == DialogResult.OK)
                {
                    int replaced = 0;
                    ProcessingBigTaskDialog taskDialog = new ProcessingBigTaskDialog(
                        Properties.ResourceHackerRes.TaskBatchRenameType_Caption,
                        string.Format(Properties.ResourceHackerRes.TaskBatchRenameType_Desc, dialog.SearchFor, dialog.ReplaceWith),
                        this.async_PerformBatchAction,
                        new BatchActionTaskData(folderDialog.SelectedPath, n => replaced += n.ReplaceTypeStrings(dialog.SearchFor, dialog.ReplaceWith)));
                    taskDialog.MainThreadRequired = false;
                    taskDialog.ShowDialog();

                    MessageBox.Show(
                        string.Format(Properties.ResourceHackerRes.MessageBox_RenameType_Text, replaced, dialog.SearchFor, dialog.ReplaceWith),
                        Properties.ResourceHackerRes.MessageBox_RenameType_Title,
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
                }
            }
        }
Esempio n. 10
0
        private System.Collections.IEnumerable async_PerformBatchAction(ProcessingBigTaskDialog.WorkerInterface state)
        {
            BatchActionTaskData data = state.Data as BatchActionTaskData;

            // Retrieve files to perform action on
            List<string> files = Resource.GetResourceFiles(data.FolderPath);
            state.Progress += 0.05f; yield return null;

            // Perform action on files
            foreach (string file in files)
            {
                state.StateDesc = file; yield return null;

                MetaFormatHelper.FilePerformAction(file, data.Action);

                state.Progress += 0.9f / files.Count; yield return null;
            }

            // Assure reloading the modified resources
            if (PathHelper.IsPathLocatedIn(data.FolderPath, "."))
            {
                string dataPath = PathHelper.MakeFilePathRelative(data.FolderPath);
                ContentProvider.RemoveContentTree(dataPath);
            }
            state.Progress += 0.05f;
        }
Esempio n. 11
0
		private static System.Collections.IEnumerable async_RenameContentRefs(ProcessingBigTaskDialog.WorkerInterface state)
		{
			var renameData = state.Data as List<ResourceRenamedEventArgs>;
			int totalCounter = 0;
			int fileCounter = 0;
			
			// Rename in static application data
			state.StateDesc = "DualityApp Data"; yield return null;
			DualityApp.LoadAppData();
			DualityApp.LoadUserData();
			state.Progress += 0.04f; yield return null;

			totalCounter += async_RenameContentRefs_Perform(DualityApp.AppData, renameData);
			totalCounter += async_RenameContentRefs_Perform(DualityApp.UserData, renameData);
			state.Progress += 0.02f; yield return null;

			DualityApp.SaveAppData();
			DualityApp.SaveUserData();
			state.Progress += 0.04f; yield return null;

			// Special case: Current Scene in sandbox mode
			if (Sandbox.IsActive)
			{
				// Because changes we'll do will be discarded when leaving the sandbox we'll need to
				// do it the hard way - manually load an save the file.
				state.StateDesc = "Current Scene"; yield return null;
				Scene curScene = Resource.Load<Scene>(Scene.CurrentPath, null, false);
				fileCounter = async_RenameContentRefs_Perform(curScene, renameData);
				totalCounter += fileCounter;
				if (fileCounter > 0) curScene.Save(Scene.CurrentPath, false);
			}
			// Special case: Current Scene NOT in sandbox mode, but still unsaved
			else if (Scene.Current.IsRuntimeResource)
			{
				state.StateDesc = "Current Scene"; yield return null;
				fileCounter = async_RenameContentRefs_Perform(Scene.Current, renameData);
				if (fileCounter > 0)
					DualityEditorApp.NotifyObjPropChanged(null, new ObjectSelection(Scene.Current.AllObjects));
				totalCounter += fileCounter;
			}

			// Rename in actual content
			var targetResTypes = renameData.Any(e => e.IsDirectory) ? null : renameData.Select(e => e.ContentType).ToArray();
			var loadedContent = ContentProvider.GetLoadedContent<Resource>();
			var reloadContent = new List<IContentRef>();
			string[] resFiles = Resource.GetResourceFiles().ToArray();
			List<Resource> modifiedRes = new List<Resource>();
			foreach (string file in resFiles)
			{
				// Early-out, if this kind of Resource isn't able to reference the renamed Resource
				if (targetResTypes != null)
				{
					Type resType = Resource.GetTypeByFileName(file);

					if (resType == null)
					{
						Log.Editor.WriteWarning("Could not determine Resource type for File '{0}' using file name only. Skipping it during rename.", file);
						continue;
					}

					bool canReferenceRes = false;
					foreach (Type targetType in targetResTypes)
					{
						if (ReflectionHelper.CanReferenceResource(resType, targetType))
						{
							canReferenceRes = true;
							break;
						}
					}
					if (!canReferenceRes)
					{
						state.Progress += 0.9f / resFiles.Length;
						continue;
					}
				}

				// Set displayed name
				state.StateDesc = file; yield return null;

				// Wasn't loaded before? Unload it later to keep the memory footprint small.
				bool wasLoaded = loadedContent.Any(r => r.Path == file);
				// Keep in mind that this operation is performed while Duality content was
				// in an inconsistent state. Loading Resources now may lead to wrong data.
				// Because the ContentRefs might be wrong right now.

				if (wasLoaded)
				{
					// Retrieve already loaded content
					IContentRef cr = ContentProvider.RequestContent(file);
					state.Progress += 0.45f / resFiles.Length; yield return null;

					// Perform rename and flag unsaved / modified
					fileCounter = async_RenameContentRefs_Perform(cr.Res, renameData);
					if (fileCounter > 0) modifiedRes.Add(cr.Res);
				}
				else
				{
					// Load content without initializing it
					Resource res = Resource.Load<Resource>(file, null, false);
					state.Progress += 0.45f / resFiles.Length; yield return null;

					// Perform rename and save it without making it globally available
					fileCounter = async_RenameContentRefs_Perform(res, renameData);
					if (fileCounter > 0) res.Save(null, false);
				}

				totalCounter += fileCounter;
				state.Progress += 0.45f / resFiles.Length; yield return null;
			}

			// Notify the editor about modified Resources
			if (modifiedRes.Count > 0)
			{
				DualityEditorApp.NotifyObjPropChanged(null, new ObjectSelection(modifiedRes));
			}
		}
Esempio n. 12
0
		private static void ProcessDataDirEvents()
		{
			List<ResourceRenamedEventArgs> renameEventBuffer = null;

			// Process events
			while (dataDirEventBuffer.Count > 0)
			{
				FileSystemEventArgs e = FetchFileSystemEvent(dataDirEventBuffer, DualityApp.DataDirectory);
				if (e == null) continue;

				// Determine whether we're dealing with a directory
				bool isDirectory = Directory.Exists(e.FullPath);
				{
					// If this is a deletion, nothing exists anymore, rely on metadata instead.
					DeletedEventArgsExt de = e as DeletedEventArgsExt;
					if (de != null && de.IsDirectory)
						isDirectory = true;
				}

				if (e.ChangeType == WatcherChangeTypes.Changed)
				{
					// Ignore stuff saved by the editor itself
					if (IsPathEditorModified(e.FullPath))
						continue;

					if (Resource.IsResourceFile(e.FullPath) || isDirectory)
					{
						ContentRef<Resource> resRef = new ContentRef<Resource>(null, e.FullPath);

						// Unregister outdated resources, if modified outside the editor
						if (!isDirectory && ContentProvider.HasContent(e.FullPath))
						{
							bool isCurrentScene = resRef.Is<Scene>() && Scene.Current == resRef.Res;
							if (isCurrentScene || DualityEditorApp.IsResourceUnsaved(e.FullPath))
							{
								DialogResult result = MessageBox.Show(
									String.Format(Properties.GeneralRes.Msg_ConfirmReloadResource_Text, e.FullPath), 
									Properties.GeneralRes.Msg_ConfirmReloadResource_Caption, 
									MessageBoxButtons.YesNo,
									MessageBoxIcon.Exclamation);
								if (result == DialogResult.Yes)
								{
									string curScenePath = Scene.CurrentPath;
									ContentProvider.RemoveContent(e.FullPath);
									if (isCurrentScene) Scene.SwitchTo(ContentProvider.RequestContent<Scene>(curScenePath), true);
								}
							}
							else
								ContentProvider.RemoveContent(e.FullPath);
						}

						if (ResourceModified != null)
							ResourceModified(null, new ResourceEventArgs(e.FullPath, isDirectory));
					}
				}
				else if (e.ChangeType == WatcherChangeTypes.Created)
				{
					if (File.Exists(e.FullPath))
					{
						// Register newly detected Resource file
						if (Resource.IsResourceFile(e.FullPath))
						{
							if (ResourceCreated != null)
								ResourceCreated(null, new ResourceEventArgs(e.FullPath, false));
						}
					}
					else if (Directory.Exists(e.FullPath))
					{
						// Register newly detected Resource directory
						if (ResourceCreated != null)
							ResourceCreated(null, new ResourceEventArgs(e.FullPath, true));
					}
				}
				else if (e.ChangeType == WatcherChangeTypes.Deleted)
				{
					// Is it a Resource file or just something else?
					if (Resource.IsResourceFile(e.FullPath) || isDirectory)
					{
						ResourceEventArgs args = new ResourceEventArgs(e.FullPath, isDirectory);

						// Organize the Source/Media directory accordingly
						DeleteSourceMediaFile(args);

						// Unregister no-more existing resources
						if (isDirectory)	ContentProvider.RemoveContentTree(args.Path);
						else				ContentProvider.RemoveContent(args.Path);

						if (ResourceDeleted != null)
							ResourceDeleted(null, args);
					}
				}
				else if (e.ChangeType == WatcherChangeTypes.Renamed)
				{
					// Is it a Resource file or just something else?
					RenamedEventArgs re = e as RenamedEventArgs;
					ResourceRenamedEventArgs args = new ResourceRenamedEventArgs(re.FullPath, re.OldFullPath, isDirectory);
					if (Resource.IsResourceFile(e.FullPath) || isDirectory)
					{
						// Determine which Source / Media files would belong to this Resource - before moving it
						string[] oldMediaPaths = PreMoveSourceMediaFile(args);;

						// Rename content registerations
						if (isDirectory)	ContentProvider.RenameContentTree(args.OldPath, args.Path);
						else				ContentProvider.RenameContent(args.OldPath, args.Path);

						// Query skipped paths
						bool isEmptyDir = isDirectory && !Directory.EnumerateFileSystemEntries(args.Path).Any();
						bool isSkippedPath = isEmptyDir;
						if (!isSkippedPath && BeginGlobalRename != null)
						{
							BeginGlobalRenameEventArgs beginGlobalRenameArgs = new BeginGlobalRenameEventArgs(args.Path, args.OldPath, isDirectory);
							BeginGlobalRename(null, beginGlobalRenameArgs);
							isSkippedPath = beginGlobalRenameArgs.Cancel;
						}

						if (!isSkippedPath)
						{
							// Buffer rename event to perform the global rename for all at once.
							if (renameEventBuffer == null) renameEventBuffer = new List<ResourceRenamedEventArgs>();
							renameEventBuffer.Add(args);
						}

						if (ResourceRenamed != null)
							ResourceRenamed(null, args);

						if (!isSkippedPath)
						{
							// Organize the Source/Media directory accordingly
							MoveSourceMediaFile(args, oldMediaPaths);
						}
					}
				}
			}

			// If required, perform a global rename operation in all existing content
			if (renameEventBuffer != null)
			{
				// Don't do it now - schedule it for the main form event loop so we don't block here.
				DualityEditorApp.MainForm.BeginInvoke((Action)delegate() {
					ProcessingBigTaskDialog taskDialog = new ProcessingBigTaskDialog( 
						Properties.GeneralRes.TaskRenameContentRefs_Caption, 
						Properties.GeneralRes.TaskRenameContentRefs_Desc, 
						async_RenameContentRefs, renameEventBuffer);
					taskDialog.ShowDialog(DualityEditorApp.MainForm);
				});
			}
		}
Esempio n. 13
0
		private static void ProcessDataDirEvents()
		{
			List<ResourceRenamedEventArgs> renameEventBuffer = null;

			// Process events
			while (dataDirEventBuffer.Count > 0)
			{
				FileSystemEventArgs e = FetchFileSystemEvent(dataDirEventBuffer, dataDirWatcher.Path);
				if (e == null) continue;

				if (e.ChangeType == WatcherChangeTypes.Changed)
				{
					ResourceEventArgs args = new ResourceEventArgs(e.FullPath);
					bool justSaved = editorJustSavedRes.Contains(Path.GetFullPath(e.FullPath));
					// Ignore stuff saved by the editor itself
					if (!justSaved && (Resource.IsResourceFile(e.FullPath) || args.IsDirectory))
					{
						// Unregister outdated resources, if modified outside the editor
						if (!args.IsDirectory && ContentProvider.HasContent(args.Path))
						{
							bool isCurrentScene = args.Content.Is<Scene>() && Scene.Current == args.Content.Res;
							if (isCurrentScene || DualityEditorApp.IsResourceUnsaved(e.FullPath))
							{
								DialogResult result = MessageBox.Show(
									String.Format(Properties.GeneralRes.Msg_ConfirmReloadResource_Text, e.FullPath), 
									Properties.GeneralRes.Msg_ConfirmReloadResource_Caption, 
									MessageBoxButtons.YesNo,
									MessageBoxIcon.Exclamation);
								if (result == DialogResult.Yes)
								{
									string curScenePath = Scene.CurrentPath;
									ContentProvider.RemoveContent(args.Path);
									if (isCurrentScene) Scene.SwitchTo(ContentProvider.RequestContent<Scene>(curScenePath), true);
								}
							}
							else
								ContentProvider.RemoveContent(args.Path);
						}

						if (ResourceModified != null) ResourceModified(null, args);
					}
				}
				else if (e.ChangeType == WatcherChangeTypes.Created)
				{
					if (File.Exists(e.FullPath))
					{
						// Register newly detected ressource file
						if (Resource.IsResourceFile(e.FullPath))
						{
							if (ResourceCreated != null)
								ResourceCreated(null, new ResourceEventArgs(e.FullPath));
						}
						// Import non-ressource file
						else
						{
							bool abort = false;

							if (FileImportProvider.IsImportFileExisting(e.FullPath))
							{
								DialogResult result = MessageBox.Show(
									String.Format(Properties.GeneralRes.Msg_ImportConfirmOverwrite_Text, e.FullPath), 
									Properties.GeneralRes.Msg_ImportConfirmOverwrite_Caption, 
									MessageBoxButtons.YesNo, 
									MessageBoxIcon.Warning);
								abort = result == DialogResult.No;
							}

							if (!abort)
							{
								bool importedSuccessfully = FileImportProvider.ImportFile(e.FullPath);
								if (!importedSuccessfully)
								{
									MessageBox.Show(
										String.Format(Properties.GeneralRes.Msg_CantImport_Text, e.FullPath), 
										Properties.GeneralRes.Msg_CantImport_Caption, 
										MessageBoxButtons.OK, 
										MessageBoxIcon.Error);
								}
								abort = !importedSuccessfully;
							}
						}
					}
					else if (Directory.Exists(e.FullPath))
					{
						// Register newly detected ressource directory
						if (ResourceCreated != null)
							ResourceCreated(null, new ResourceEventArgs(e.FullPath));
					}
				}
				else if (e.ChangeType == WatcherChangeTypes.Deleted)
				{
					// Is it a Resource file or just something else?
					ResourceEventArgs args = new ResourceEventArgs(e.FullPath);
					if (Resource.IsResourceFile(e.FullPath) || args.IsDirectory)
					{

						// Unregister no-more existing resources
						if (args.IsDirectory)	ContentProvider.RemoveContentTree(args.Path);
						else					ContentProvider.RemoveContent(args.Path);

						if (ResourceDeleted != null)
							ResourceDeleted(null, args);
					}
				}
				else if (e.ChangeType == WatcherChangeTypes.Renamed)
				{
					// Is it a Resource file or just something else?
					RenamedEventArgs re = e as RenamedEventArgs;
					ResourceRenamedEventArgs args = new ResourceRenamedEventArgs(re.FullPath, re.OldFullPath);
					if (Resource.IsResourceFile(e.FullPath) || args.IsDirectory)
					{
						// Rename content registerations
						if (args.IsDirectory)	ContentProvider.RenameContentTree(args.OldPath, args.Path);
						else					ContentProvider.RenameContent(args.OldPath, args.Path);

						// Query skipped paths
						bool isEmptyDir = args.IsDirectory && !Directory.EnumerateFileSystemEntries(args.Path).Any();
						bool isSkippedPath = isEmptyDir;
						if (!isSkippedPath && BeginGlobalRename != null)
						{
							BeginGlobalRenameEventArgs beginGlobalRenameArgs = new BeginGlobalRenameEventArgs(args.Path, args.OldPath);
							BeginGlobalRename(null, beginGlobalRenameArgs);
							isSkippedPath = beginGlobalRenameArgs.Cancel;
						}

						if (!isSkippedPath)
						{
							// Buffer rename event to perform the global rename for all at once.
							if (renameEventBuffer == null) renameEventBuffer = new List<ResourceRenamedEventArgs>();
							renameEventBuffer.Add(args);
						}

						if (ResourceRenamed != null) ResourceRenamed(null, args);
					}
				}
			}

			// If required, perform a global rename operation in all existing content
			if (renameEventBuffer != null)
			{
				// Don't do it now - schedule it for the main form event loop so we don't block here.
				DualityEditorApp.MainForm.BeginInvoke((Action)delegate() {
					ProcessingBigTaskDialog taskDialog = new ProcessingBigTaskDialog( 
						Properties.GeneralRes.TaskRenameContentRefs_Caption, 
						Properties.GeneralRes.TaskRenameContentRefs_Desc, 
						async_RenameContentRefs, renameEventBuffer);
					taskDialog.ShowDialog(DualityEditorApp.MainForm);
				});
			}
		}