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; }
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( PluginRes.ResourceHackerRes.TaskBatchRenameType_Caption, string.Format(PluginRes.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(PluginRes.ResourceHackerRes.MessageBox_RenameType_Text, replaced, dialog.SearchFor, dialog.ReplaceWith), PluginRes.ResourceHackerRes.MessageBox_RenameType_Title, MessageBoxButtons.OK, MessageBoxIcon.Information); } } }
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.IsContentAvailable(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(EditorRes.GeneralRes.Msg_ConfirmReloadResource_Text, e.FullPath), EditorRes.GeneralRes.Msg_ConfirmReloadResource_Caption, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation); if (result == DialogResult.Yes) { string curScenePath = Scene.CurrentPath; ContentProvider.RemoveContent(args.Path); if (isCurrentScene) Scene.Current = ContentProvider.RequestContent<Scene>(curScenePath).Res; } } 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(EditorRes.GeneralRes.Msg_ImportConfirmOverwrite_Text, e.FullPath), EditorRes.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(EditorRes.GeneralRes.Msg_CantImport_Text, e.FullPath), EditorRes.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 isSkippedPath = false; if (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( EditorRes.GeneralRes.TaskRenameContentRefs_Caption, EditorRes.GeneralRes.TaskRenameContentRefs_Desc, async_RenameContentRefs, renameEventBuffer); taskDialog.ShowDialog(DualityEditorApp.MainForm); }); } }
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(); DualityApp.LoadMetaData(); state.Progress += 0.04f; yield return null; totalCounter += async_RenameContentRefs_Perform(DualityApp.AppData, renameData); totalCounter += async_RenameContentRefs_Perform(DualityApp.UserData, renameData); totalCounter += async_RenameContentRefs_Perform(DualityApp.MetaData, renameData); state.Progress += 0.02f; yield return null; DualityApp.SaveAppData(); DualityApp.SaveUserData(); DualityApp.SaveMetaData(); 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>(); List<string> resFiles = Resource.GetResourceFiles(); 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); bool canReferenceRes = false; foreach (Type targetType in targetResTypes) { if (ReflectionHelper.CanReferenceResource(resType, targetType)) { canReferenceRes = true; break; } } if (!canReferenceRes) { state.Progress += 0.9f / resFiles.Count; 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.Count; 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.Count; 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.Count; yield return null; } // Notify the editor about modified Resources if (modifiedRes.Count > 0) { DualityEditorApp.NotifyObjPropChanged(null, new ObjectSelection(modifiedRes)); } }
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(); DualityApp.LoadMetaData(); state.Progress += 0.04f; yield return null; totalCounter += async_RenameContentRefs_Perform(DualityApp.AppData, renameData); totalCounter += async_RenameContentRefs_Perform(DualityApp.UserData, renameData); totalCounter += async_RenameContentRefs_Perform(DualityApp.MetaData, renameData); state.Progress += 0.02f; yield return null; DualityApp.SaveAppData(); DualityApp.SaveUserData(); DualityApp.SaveMetaData(); 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.LoadResource<Scene>(Scene.CurrentPath); fileCounter = async_RenameContentRefs_Perform(curScene, renameData); totalCounter += fileCounter; if (fileCounter > 0) curScene.Save(Scene.CurrentPath); } // 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 availContent = ContentProvider.GetAvailContent<Resource>(); var reloadContent = new List<IContentRef>(); List<string> resFiles = Resource.GetResourceFiles(); List<Resource> modifiedRes = new List<Resource>(); foreach (string file in resFiles) { state.StateDesc = file; yield return null; // Loaded for the first time? Schedule for later reload. bool reload = !availContent.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. // Load content var cr = ContentProvider.RequestContent(file); state.Progress += 0.35f / resFiles.Count; yield return null; // Perform rename and flag unsaved / modified fileCounter = async_RenameContentRefs_Perform(cr.Res, renameData); totalCounter += fileCounter; if (fileCounter > 0) { if (!reload) modifiedRes.Add(cr.Res); else reloadContent.Add(cr); } state.Progress += 0.35f / resFiles.Count; yield return null; } if (modifiedRes.Count > 0) DualityEditorApp.NotifyObjPropChanged(null, new ObjectSelection(modifiedRes)); // Perform Resource unload where scheduled state.StateDesc = "Saving Resources.."; yield return null; foreach (IContentRef cr in reloadContent) { cr.Res.Save(); ContentProvider.UnregisterContent(cr.Path); state.Progress += 0.2f / reloadContent.Count; yield return null; } }