integrating offline changes
This commit is contained in:
parent
121623bad3
commit
3f8eeda65b
125 changed files with 5442 additions and 5434 deletions
|
|
@ -52,7 +52,7 @@ namespace MatterHackers.MatterControl.Library.Export
|
|||
|
||||
public bool ExportPossible(ILibraryAsset libraryItem) => true;
|
||||
|
||||
public async Task<List<ValidationError>> Generate(IEnumerable<ILibraryItem> libraryItems, string outputPath, IProgress<ProgressStatus> progress, CancellationToken cancellationToken)
|
||||
public async Task<List<ValidationError>> Generate(IEnumerable<ILibraryItem> libraryItems, string outputPath, Action<double, string> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var firstItem = libraryItems.OfType<ILibraryAsset>().FirstOrDefault();
|
||||
if (firstItem is ILibraryAsset libraryItem)
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ namespace MatterHackers.MatterControl.Library.Export
|
|||
|
||||
public bool ExportPossible(ILibraryAsset libraryItem) => true;
|
||||
|
||||
public async Task<List<ValidationError>> Generate(IEnumerable<ILibraryItem> libraryItems, string outputPath, IProgress<ProgressStatus> progress, CancellationToken cancellationToken)
|
||||
public async Task<List<ValidationError>> Generate(IEnumerable<ILibraryItem> libraryItems, string outputPath, Action<double, string> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var streamItems = libraryItems.OfType<ILibraryAssetStream>();
|
||||
if (streamItems.Any())
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ namespace MatterHackers.MatterControl.Library.Export
|
|||
return container;
|
||||
}
|
||||
|
||||
public virtual async Task<List<ValidationError>> Generate(IEnumerable<ILibraryItem> libraryItems, string outputPath, IProgress<ProgressStatus> progress, CancellationToken cancellationToken)
|
||||
public virtual async Task<List<ValidationError>> Generate(IEnumerable<ILibraryItem> libraryItems, string outputPath, Action<double, string> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var firstItem = libraryItems.OfType<ILibraryAsset>().FirstOrDefault();
|
||||
if (firstItem != null)
|
||||
|
|
@ -185,16 +185,12 @@ namespace MatterHackers.MatterControl.Library.Export
|
|||
}
|
||||
else if (firstItem is ILibraryObject3D object3DItem)
|
||||
{
|
||||
var status = new ProgressStatus()
|
||||
{
|
||||
Status = "Saving Asset".Localize()
|
||||
};
|
||||
var status = "Saving Asset".Localize();
|
||||
|
||||
loadedItem = await object3DItem.CreateContent(null);
|
||||
await loadedItem.PersistAssets((percentComplete, text) =>
|
||||
await loadedItem.PersistAssets((progress2, text) =>
|
||||
{
|
||||
status.Progress0To1 = percentComplete;
|
||||
progress.Report(status);
|
||||
progress?.Invoke(progress2, status);
|
||||
});
|
||||
}
|
||||
else if (assetStream != null)
|
||||
|
|
@ -340,7 +336,7 @@ namespace MatterHackers.MatterControl.Library.Export
|
|||
return accumulatedStream;
|
||||
}
|
||||
|
||||
private void ApplyStreamPipelineAndExport(GCodeFileStream gCodeFileStream, string outputPath, IProgress<ProgressStatus> progress)
|
||||
private void ApplyStreamPipelineAndExport(GCodeFileStream gCodeFileStream, string outputPath, Action<double, string> progress)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -349,10 +345,7 @@ namespace MatterHackers.MatterControl.Library.Export
|
|||
var totalLines = gCodeFileStream.GCodeFile.LineCount;
|
||||
var currentLine = 0;
|
||||
|
||||
var status = new ProgressStatus()
|
||||
{
|
||||
Status = "Writing G-Code".Localize()
|
||||
};
|
||||
var status = "Writing G-Code".Localize();
|
||||
|
||||
// Run each line from the source gcode through the loaded pipeline and dump to the output location
|
||||
using (var file = new StreamWriter(outputPath))
|
||||
|
|
@ -387,8 +380,7 @@ namespace MatterHackers.MatterControl.Library.Export
|
|||
|
||||
if (currentLine % 1024 == 0)
|
||||
{
|
||||
status.Progress0To1 = currentLine / (double)totalLines;
|
||||
progress.Report(status);
|
||||
progress?.Invoke(currentLine / (double)totalLines, status);
|
||||
}
|
||||
currentLine++;
|
||||
}
|
||||
|
|
@ -403,7 +395,7 @@ namespace MatterHackers.MatterControl.Library.Export
|
|||
}
|
||||
}
|
||||
|
||||
private void ApplyStreamPipelineAndExport(string gcodeFilename, string outputPath, IProgress<ProgressStatus> progress)
|
||||
private void ApplyStreamPipelineAndExport(string gcodeFilename, string outputPath, Action<double, string> progress)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ namespace MatterHackers.MatterControl
|
|||
|
||||
void Initialize(PrinterConfig printer);
|
||||
|
||||
Task<List<ValidationError>> Generate(IEnumerable<ILibraryItem> libraryItems, string outputPath, IProgress<ProgressStatus> progress, CancellationToken cancellationToken);
|
||||
Task<List<ValidationError>> Generate(IEnumerable<ILibraryItem> libraryItems, string outputPath, Action<double, string> progress, CancellationToken cancellationToken);
|
||||
|
||||
bool Enabled { get; }
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ namespace MatterHackers.MatterControl.Library.Export
|
|||
|
||||
public bool ExportPossible(ILibraryAsset libraryItem) => true;
|
||||
|
||||
public async Task<List<ValidationError>> Generate(IEnumerable<ILibraryItem> libraryItems, string outputPath, IProgress<ProgressStatus> progress, CancellationToken cancellationToken)
|
||||
public async Task<List<ValidationError>> Generate(IEnumerable<ILibraryItem> libraryItems, string outputPath, Action<double, string> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -38,67 +38,69 @@ using MatterHackers.Localizations;
|
|||
|
||||
namespace MatterHackers.MatterControl.Library.Export
|
||||
{
|
||||
public static class MeshExport
|
||||
{
|
||||
public static async Task<bool> ExportMesh(ILibraryItem source, string filePathToSave, bool mergeMeshes, IProgress<ProgressStatus> progress)
|
||||
{
|
||||
try
|
||||
{
|
||||
var status = new ProgressStatus()
|
||||
{
|
||||
Status = "Exporting".Localize()
|
||||
};
|
||||
|
||||
if (source is ILibraryObject3D contentItem)
|
||||
{
|
||||
// If the content is an IObject3D, then we need to load it and MeshFileIO save to the target path
|
||||
var content = await contentItem.GetObject3D(null);
|
||||
return Object3D.Save(content, filePathToSave, mergeMeshes, CancellationToken.None, reportProgress: (ratio, name) =>
|
||||
public static class MeshExport
|
||||
{
|
||||
/// <summary>
|
||||
/// Export the source item(s) to a single or multiple STL files
|
||||
/// </summary>
|
||||
/// <param name="source">The source item(s)</param>
|
||||
/// <param name="filePathToSave">The destination to save to (only the folder will be used in saveMultipleStls</param>
|
||||
/// <param name="mergeMeshes">Do a Combine on the individual meshes to ensure they are a single item</param>
|
||||
/// <param name="saveMultipleStls">Save multiple stls using the name of the objects in the scene</param>
|
||||
/// <param name="progress">Update the save progress</param>
|
||||
/// <returns>If the function succeded</returns>
|
||||
public static async Task<bool> ExportMesh(ILibraryItem source, string filePathToSave, bool mergeMeshes, Action<double, string> progress, bool saveMultipleStls = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (source is ILibraryObject3D contentItem)
|
||||
{
|
||||
// If the content is an IObject3D, then we need to load it and MeshFileIO save to the target path
|
||||
var content = await contentItem.GetObject3D(null);
|
||||
return Object3D.Save(content, filePathToSave, mergeMeshes, CancellationToken.None, reportProgress: (ratio, name) =>
|
||||
{
|
||||
status.Progress0To1 = ratio;
|
||||
progress.Report(status);
|
||||
});
|
||||
}
|
||||
else if (source is ILibraryAssetStream streamContent)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePathToSave))
|
||||
{
|
||||
// If the file is already the target type, it just needs copied to the target path
|
||||
if (Path.GetExtension(streamContent.FileName).ToUpper() == Path.GetExtension(filePathToSave).ToUpper())
|
||||
{
|
||||
using (var result = await streamContent.GetStream(null))
|
||||
using (var fileStream = File.Create(filePathToSave))
|
||||
{
|
||||
result.Stream.CopyTo(fileStream);
|
||||
}
|
||||
progress?.Invoke(ratio, "Exporting".Localize());
|
||||
}, saveMultipleStls: saveMultipleStls);
|
||||
}
|
||||
else if (source is ILibraryAssetStream streamContent)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePathToSave))
|
||||
{
|
||||
// If the file is already the target type, it just needs copied to the target path
|
||||
if (Path.GetExtension(streamContent.FileName).ToUpper() == Path.GetExtension(filePathToSave).ToUpper())
|
||||
{
|
||||
using (var result = await streamContent.GetStream(null))
|
||||
using (var fileStream = File.Create(filePathToSave))
|
||||
{
|
||||
result.Stream.CopyTo(fileStream);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise we need to load the content and MeshFileIO save to the target path
|
||||
using (var result = await streamContent.GetStream(null))
|
||||
{
|
||||
IObject3D item = Object3D.Load(result.Stream, Path.GetExtension(streamContent.FileName), CancellationToken.None);
|
||||
if (item != null)
|
||||
{
|
||||
return Object3D.Save(item, filePathToSave, mergeMeshes, CancellationToken.None, reportProgress: (ratio, name) =>
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise we need to load the content and MeshFileIO save to the target path
|
||||
using (var result = await streamContent.GetStream(null))
|
||||
{
|
||||
IObject3D item = Object3D.Load(result.Stream, Path.GetExtension(streamContent.FileName), CancellationToken.None);
|
||||
if (item != null)
|
||||
{
|
||||
return Object3D.Save(item, filePathToSave, mergeMeshes, CancellationToken.None, reportProgress: (ratio, name) =>
|
||||
{
|
||||
status.Progress0To1 = ratio;
|
||||
progress.Report(status);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine("Error exporting file: " + ex.Message);
|
||||
}
|
||||
progress?.Invoke(ratio, null);
|
||||
}, saveMultipleStls: saveMultipleStls);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine("Error exporting file: " + ex.Message);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ namespace MatterHackers.MatterControl.Library.Export
|
|||
|
||||
public async Task<List<ValidationError>> Generate(IEnumerable<ILibraryItem> libraryItems,
|
||||
string outputPath,
|
||||
IProgress<ProgressStatus> progress,
|
||||
Action<double, string> progress,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var first = true;
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ namespace MatterHackers.MatterControl.Library.Export
|
|||
|
||||
public bool ExportPossible(ILibraryAsset libraryItem) => true;
|
||||
|
||||
public async Task<List<ValidationError>> Generate(IEnumerable<ILibraryItem> libraryItems, string outputPath, IProgress<ProgressStatus> progress, CancellationToken cancellationToken)
|
||||
public async Task<List<ValidationError>> Generate(IEnumerable<ILibraryItem> libraryItems, string outputPath, Action<double, string> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var streamItems = libraryItems.OfType<ILibraryAssetStream>();
|
||||
if (streamItems.Any())
|
||||
|
|
|
|||
|
|
@ -43,456 +43,449 @@ using MatterHackers.MatterControl.DataStorage;
|
|||
|
||||
namespace MatterHackers.MatterControl.Library
|
||||
{
|
||||
public class FileSystemContainer : WritableContainer, ICustomSearch
|
||||
{
|
||||
private FileSystemWatcher directoryWatcher;
|
||||
public class FileSystemContainer : WritableContainer, ICustomSearch
|
||||
{
|
||||
private FileSystemWatcher directoryWatcher;
|
||||
|
||||
private bool isActiveContainer;
|
||||
private bool isDirty;
|
||||
private string keywordFilter;
|
||||
private bool isActiveContainer;
|
||||
private bool isDirty;
|
||||
private string keywordFilter;
|
||||
|
||||
private long lastTimeContentsChanged;
|
||||
private long lastTimeContentsChanged;
|
||||
|
||||
private RunningInterval waitingForRefresh;
|
||||
private RunningInterval waitingForRefresh;
|
||||
|
||||
public FileSystemContainer(string fullPath)
|
||||
{
|
||||
this.CustomSearch = this;
|
||||
this.FullPath = fullPath;
|
||||
this.Name = Path.GetFileName(fullPath);
|
||||
public FileSystemContainer(string fullPath)
|
||||
{
|
||||
this.CustomSearch = this;
|
||||
this.FullPath = fullPath;
|
||||
this.Name = Path.GetFileName(fullPath);
|
||||
|
||||
this.IsProtected = false;
|
||||
this.IsProtected = false;
|
||||
|
||||
this.ChildContainers = new SafeList<ILibraryContainerLink>();
|
||||
this.Items = new SafeList<ILibraryItem>();
|
||||
this.ChildContainers = new SafeList<ILibraryContainerLink>();
|
||||
this.Items = new SafeList<ILibraryItem>();
|
||||
|
||||
if (AggContext.OperatingSystem == OSType.Windows
|
||||
&& Directory.Exists(fullPath))
|
||||
{
|
||||
directoryWatcher = new FileSystemWatcher(fullPath);
|
||||
directoryWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
|
||||
directoryWatcher.Changed += DirectoryContentsChanged;
|
||||
directoryWatcher.Created += DirectoryContentsChanged;
|
||||
directoryWatcher.Deleted += DirectoryContentsChanged;
|
||||
directoryWatcher.Renamed += DirectoryContentsChanged;
|
||||
directoryWatcher.IncludeSubdirectories = false;
|
||||
if (AggContext.OperatingSystem == OSType.Windows
|
||||
&& Directory.Exists(fullPath))
|
||||
{
|
||||
directoryWatcher = new FileSystemWatcher(fullPath);
|
||||
directoryWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
|
||||
directoryWatcher.Changed += DirectoryContentsChanged;
|
||||
directoryWatcher.Created += DirectoryContentsChanged;
|
||||
directoryWatcher.Deleted += DirectoryContentsChanged;
|
||||
directoryWatcher.Renamed += DirectoryContentsChanged;
|
||||
directoryWatcher.IncludeSubdirectories = false;
|
||||
|
||||
// Begin watching.
|
||||
directoryWatcher.EnableRaisingEvents = true;
|
||||
}
|
||||
}
|
||||
// Begin watching.
|
||||
directoryWatcher.EnableRaisingEvents = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task Save(ILibraryItem item, IObject3D content)
|
||||
{
|
||||
if (item is FileSystemFileItem fileItem)
|
||||
{
|
||||
if (fileItem.FilePath.Contains(ApplicationDataStorage.Instance.ApplicationLibraryDataPath))
|
||||
{
|
||||
// save using the normal uncompressed mcx file
|
||||
// Serialize the scene to disk using a modified Json.net pipeline with custom ContractResolvers and JsonConverters
|
||||
File.WriteAllText(fileItem.FilePath, content.ToJson().Result);
|
||||
|
||||
this.OnItemContentChanged(new LibraryItemChangedEventArgs(fileItem));
|
||||
}
|
||||
else
|
||||
{
|
||||
await ApplicationController.Instance.Tasks.Execute(
|
||||
"Saving Changes".Localize(),
|
||||
null,
|
||||
async (reporter, cancellationTokenSource) =>
|
||||
{
|
||||
var status = new ProgressStatus()
|
||||
{
|
||||
Status = "Saving Asset".Localize()
|
||||
};
|
||||
|
||||
var directory = Path.GetDirectoryName(fileItem.FilePath);
|
||||
var filename = Path.GetFileNameWithoutExtension(fileItem.FilePath);
|
||||
var backupName = Path.Combine(directory, Path.ChangeExtension(filename + "_bak", ".mcx"));
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(backupName))
|
||||
{
|
||||
File.Delete(backupName);
|
||||
}
|
||||
|
||||
// rename any existing file
|
||||
if (File.Exists(fileItem.FilePath))
|
||||
{
|
||||
File.Move(fileItem.FilePath, backupName);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
// make sure we have all the mesh items in the cache for saving to the archive
|
||||
await content.PersistAssets((percentComplete, text) =>
|
||||
{
|
||||
status.Progress0To1 = percentComplete * .9;
|
||||
reporter.Report(status);
|
||||
}, true);
|
||||
|
||||
var persistableItems = content.GetPersistable(true);
|
||||
var persistCount = persistableItems.Count();
|
||||
var savedCount = 0;
|
||||
|
||||
// save to a binary mcx file (a zip with a scene.mcx and an assets folder)
|
||||
using (var file = File.OpenWrite(fileItem.FilePath))
|
||||
{
|
||||
using (var zip = new ZipArchive(file, ZipArchiveMode.Create))
|
||||
{
|
||||
var savedItems = new HashSet<string>();
|
||||
foreach (var persistableItem in persistableItems)
|
||||
{
|
||||
string sourcePath = null;
|
||||
if (persistableItem.MeshPath != null)
|
||||
{
|
||||
sourcePath = Path.Combine(ApplicationDataStorage.Instance.LibraryAssetsPath, Path.GetFileName(persistableItem.MeshPath));
|
||||
}
|
||||
|
||||
if (persistableItem is AssetObject3D assetObject3D)
|
||||
{
|
||||
sourcePath = Path.Combine(ApplicationDataStorage.Instance.LibraryAssetsPath, Path.GetFileName(assetObject3D.AssetPath));
|
||||
}
|
||||
|
||||
var destFilename = Path.GetFileName(sourcePath);
|
||||
if (File.Exists(sourcePath))
|
||||
{
|
||||
if (!savedItems.Contains(destFilename))
|
||||
{
|
||||
savedItems.Add(destFilename);
|
||||
var assetName = Path.Combine("Assets", destFilename);
|
||||
zip.CreateEntryFromFile(sourcePath, assetName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int a = 0;
|
||||
}
|
||||
|
||||
savedCount++;
|
||||
status.Progress0To1 = .9 + .1 * (savedCount / persistCount);
|
||||
reporter.Report(status);
|
||||
}
|
||||
|
||||
var sceneEntry = zip.CreateEntry("scene.mcx");
|
||||
using (var sceneStream = sceneEntry.Open())
|
||||
{
|
||||
using (var writer = new StreamWriter(sceneStream))
|
||||
{
|
||||
writer.Write(await content.ToJson());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize the scene to disk using a modified Json.net pipeline with custom ContractResolvers and JsonConverters
|
||||
this.OnItemContentChanged(new LibraryItemChangedEventArgs(fileItem));
|
||||
|
||||
// remove the existing file after a successfull save
|
||||
try
|
||||
{
|
||||
if (File.Exists(backupName))
|
||||
{
|
||||
File.Delete(backupName);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetThumbnail(ILibraryItem item, int width, int height, ImageBuffer imageBuffer)
|
||||
{
|
||||
#if DEBUG
|
||||
// throw new NotImplementedException();
|
||||
#endif
|
||||
}
|
||||
|
||||
public override ICustomSearch CustomSearch { get; }
|
||||
|
||||
public string FullPath { get; protected set; }
|
||||
|
||||
// Indicates if the new AMF file should use the original file name incremented until no name collision occurs
|
||||
public bool UseIncrementedNameDuringTypeChange { get; internal set; }
|
||||
|
||||
public override void Activate()
|
||||
{
|
||||
this.isActiveContainer = true;
|
||||
base.Activate();
|
||||
}
|
||||
|
||||
public async override void Add(IEnumerable<ILibraryItem> items)
|
||||
{
|
||||
if (!items.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (directoryWatcher != null)
|
||||
{
|
||||
// turn them off whil ewe add the content
|
||||
directoryWatcher.EnableRaisingEvents = false;
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(this.FullPath);
|
||||
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
switch (item)
|
||||
{
|
||||
case CreateFolderItem newFolder:
|
||||
string targetFolderPath = Path.Combine(this.FullPath, newFolder.Name);
|
||||
|
||||
// TODO: write adaption of GetNonCollidingName for directories
|
||||
Directory.CreateDirectory(targetFolderPath);
|
||||
this.isDirty = true;
|
||||
|
||||
break;
|
||||
|
||||
case ILibraryAssetStream streamItem:
|
||||
string targetPath = Path.Combine(this.FullPath, streamItem.FileName);
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(targetPath))
|
||||
{
|
||||
targetPath = GetNonCollidingName(Path.GetFileName(targetPath));
|
||||
}
|
||||
|
||||
using (var outputStream = File.OpenWrite(targetPath))
|
||||
using (var contentStream = await streamItem.GetStream(null))
|
||||
{
|
||||
contentStream.Stream.CopyTo(outputStream);
|
||||
}
|
||||
|
||||
this.Items.Add(new FileSystemFileItem(targetPath));
|
||||
this.isDirty = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
ApplicationController.Instance.LogError($"Error adding file: {targetPath}\r\n{ex.Message}");
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (directoryWatcher != null)
|
||||
{
|
||||
// turn them back on
|
||||
directoryWatcher.EnableRaisingEvents = true;
|
||||
}
|
||||
|
||||
if (this.isDirty)
|
||||
{
|
||||
this.ReloadContent();
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyFilter(string filter, ILibraryContext libraryContext)
|
||||
{
|
||||
keywordFilter = filter;
|
||||
this.Load();
|
||||
this.OnContentChanged();
|
||||
}
|
||||
|
||||
public void ClearFilter()
|
||||
{
|
||||
keywordFilter = null;
|
||||
this.Load();
|
||||
this.OnContentChanged();
|
||||
}
|
||||
|
||||
public override void Deactivate()
|
||||
{
|
||||
this.isActiveContainer = false;
|
||||
base.Deactivate();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (directoryWatcher != null)
|
||||
{
|
||||
directoryWatcher.EnableRaisingEvents = false;
|
||||
|
||||
directoryWatcher.Changed -= DirectoryContentsChanged;
|
||||
directoryWatcher.Created -= DirectoryContentsChanged;
|
||||
directoryWatcher.Deleted -= DirectoryContentsChanged;
|
||||
directoryWatcher.Renamed -= DirectoryContentsChanged;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
this.Load(false);
|
||||
}
|
||||
|
||||
public void Load(bool recursive)
|
||||
{
|
||||
SearchOption searchDepth = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||||
|
||||
try
|
||||
{
|
||||
string filter = keywordFilter?.Trim() ?? "";
|
||||
|
||||
var allFiles = Directory.GetFiles(FullPath, "*.*", searchDepth);
|
||||
|
||||
var zipFiles = allFiles.Where(f => Path.GetExtension(f).IndexOf(".zip", StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
var nonZipFiles = allFiles.Except(zipFiles);
|
||||
|
||||
if (filter == "")
|
||||
{
|
||||
var directories = Directory.GetDirectories(FullPath, "*.*", searchDepth).Select(p => new DirectoryContainerLink(p)).ToList<ILibraryContainerLink>();
|
||||
this.ChildContainers = new SafeList<ILibraryContainerLink>(directories.Concat(zipFiles.Select(f => new LocalZipContainerLink(f))));
|
||||
var libraryFiles = allFiles.Where(f => Path.GetExtension(f).IndexOf(".library", StringComparison.OrdinalIgnoreCase) != -1);
|
||||
this.ChildContainers.AddRange(libraryFiles.Select(f => LibraryJsonFile.ContainerFromLocalFile(f)));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ChildContainers = new SafeList<ILibraryContainerLink>();
|
||||
}
|
||||
|
||||
var matchedFiles = nonZipFiles.Where(filePath =>
|
||||
{
|
||||
string fileName = Path.GetFileName(filePath);
|
||||
|
||||
return (filter == "" || FileNameContainsFilter(filePath, filter))
|
||||
&& ApplicationController.Instance.Library.IsContentFileType(fileName);
|
||||
});
|
||||
|
||||
this.ChildContainers.Modify((list) =>
|
||||
{
|
||||
list.Sort((a, b) => a.Name.CompareTo(b.Name));
|
||||
});
|
||||
|
||||
// Matched files projected onto FileSystemFileItem
|
||||
this.Items = new SafeList<ILibraryItem>(matchedFiles.OrderBy(f => f).Select(f => new FileSystemFileItem(f)));
|
||||
|
||||
var indexMd = nonZipFiles.Where(f => f.EndsWith("index.md")).FirstOrDefault();
|
||||
if (indexMd != null)
|
||||
public override async Task Save(ILibraryItem item, IObject3D content)
|
||||
{
|
||||
if (item is FileSystemFileItem fileItem)
|
||||
{
|
||||
if (fileItem.FilePath.Contains(ApplicationDataStorage.Instance.ApplicationLibraryDataPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
HeaderMarkdown = File.ReadAllText(indexMd);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
// save using the normal uncompressed mcx file
|
||||
// Serialize the scene to disk using a modified Json.net pipeline with custom ContractResolvers and JsonConverters
|
||||
File.WriteAllText(fileItem.FilePath, content.ToJson().Result);
|
||||
|
||||
this.isDirty = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.ChildContainers = new SafeList<ILibraryContainerLink>();
|
||||
this.Items = new SafeList<ILibraryItem>()
|
||||
{
|
||||
new MessageItem("Error loading container - " + ex.Message)
|
||||
};
|
||||
}
|
||||
}
|
||||
this.OnItemContentChanged(new LibraryItemChangedEventArgs(fileItem));
|
||||
}
|
||||
else
|
||||
{
|
||||
await ApplicationController.Instance.Tasks.Execute(
|
||||
"Saving Changes".Localize(),
|
||||
null,
|
||||
async (reporter, cancellationTokenSource) =>
|
||||
{
|
||||
var directory = Path.GetDirectoryName(fileItem.FilePath);
|
||||
var filename = Path.GetFileNameWithoutExtension(fileItem.FilePath);
|
||||
var backupName = Path.Combine(directory, Path.ChangeExtension(filename + "_bak", ".mcx"));
|
||||
|
||||
public override void Remove(IEnumerable<ILibraryItem> items)
|
||||
{
|
||||
if (AggContext.OperatingSystem == OSType.Windows)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is FileSystemItem fileItem
|
||||
&& File.Exists(fileItem.FilePath))
|
||||
{
|
||||
File.Delete(fileItem.FilePath);
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
if (File.Exists(backupName))
|
||||
{
|
||||
File.Delete(backupName);
|
||||
}
|
||||
|
||||
this.ReloadContent();
|
||||
}
|
||||
}
|
||||
// rename any existing file
|
||||
if (File.Exists(fileItem.FilePath))
|
||||
{
|
||||
File.Move(fileItem.FilePath, backupName);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
private void DirectoryContentsChanged(object sender, EventArgs e)
|
||||
{
|
||||
// Flag for reload
|
||||
isDirty = true;
|
||||
// make sure we have all the mesh items in the cache for saving to the archive
|
||||
await content.PersistAssets((percentComplete, text) =>
|
||||
{
|
||||
reporter?.Invoke(percentComplete * .9, null);
|
||||
}, true);
|
||||
|
||||
lastTimeContentsChanged = UiThread.CurrentTimerMs;
|
||||
var persistableItems = content.GetPersistable(true);
|
||||
var persistCount = persistableItems.Count();
|
||||
var savedCount = 0;
|
||||
|
||||
// Only refresh content if we're the active container
|
||||
if (isActiveContainer
|
||||
&& waitingForRefresh == null)
|
||||
{
|
||||
waitingForRefresh = UiThread.SetInterval(WaitToRefresh, .5);
|
||||
}
|
||||
}
|
||||
// save to a binary mcx file (a zip with a scene.mcx and an assets folder)
|
||||
using (var file = File.OpenWrite(fileItem.FilePath))
|
||||
{
|
||||
using (var zip = new ZipArchive(file, ZipArchiveMode.Create))
|
||||
{
|
||||
var savedItems = new HashSet<string>();
|
||||
foreach (var persistableItem in persistableItems)
|
||||
{
|
||||
string sourcePath = null;
|
||||
if (persistableItem.MeshPath != null)
|
||||
{
|
||||
sourcePath = Path.Combine(ApplicationDataStorage.Instance.LibraryAssetsPath, Path.GetFileName(persistableItem.MeshPath));
|
||||
}
|
||||
|
||||
private bool FileNameContainsFilter(string filename, string filter)
|
||||
{
|
||||
string nameWithSpaces = Path.GetFileNameWithoutExtension(filename.Replace('_', ' '));
|
||||
if (persistableItem is AssetObject3D assetObject3D)
|
||||
{
|
||||
sourcePath = Path.Combine(ApplicationDataStorage.Instance.LibraryAssetsPath, Path.GetFileName(assetObject3D.AssetPath));
|
||||
}
|
||||
|
||||
// Split the filter on word boundaries and determine if all terms in the given file name
|
||||
foreach (string word in filter.Split(' '))
|
||||
{
|
||||
if (nameWithSpaces.IndexOf(word, StringComparison.OrdinalIgnoreCase) == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var destFilename = Path.GetFileName(sourcePath);
|
||||
if (File.Exists(sourcePath))
|
||||
{
|
||||
if (!savedItems.Contains(destFilename))
|
||||
{
|
||||
savedItems.Add(destFilename);
|
||||
var assetName = Path.Combine("Assets", destFilename);
|
||||
zip.CreateEntryFromFile(sourcePath, assetName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int a = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
savedCount++;
|
||||
reporter?.Invoke(.9 + .1 * (savedCount / persistCount), null);
|
||||
}
|
||||
|
||||
private string GetNonCollidingName(string fileName)
|
||||
{
|
||||
// Switching from .stl, .obj or similar to AMF. Save the file and update the
|
||||
// the filename with an incremented (n) value to reflect the extension change in the UI
|
||||
var similarFileNames = Directory.GetFiles(this.FullPath, $"{Path.GetFileNameWithoutExtension(fileName)}.*");
|
||||
var sceneEntry = zip.CreateEntry("scene.mcx");
|
||||
using (var sceneStream = sceneEntry.Open())
|
||||
{
|
||||
using (var writer = new StreamWriter(sceneStream))
|
||||
{
|
||||
writer.Write(await content.ToJson());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ;
|
||||
var validName = agg_basics.GetNonCollidingName(fileName, (testName) => !File.Exists(testName));
|
||||
// Serialize the scene to disk using a modified Json.net pipeline with custom ContractResolvers and JsonConverters
|
||||
this.OnItemContentChanged(new LibraryItemChangedEventArgs(fileItem));
|
||||
|
||||
return validName;
|
||||
}
|
||||
// remove the existing file after a successfull save
|
||||
try
|
||||
{
|
||||
if (File.Exists(backupName))
|
||||
{
|
||||
File.Delete(backupName);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void WaitToRefresh()
|
||||
{
|
||||
if (UiThread.CurrentTimerMs > lastTimeContentsChanged + 500
|
||||
&& waitingForRefresh != null)
|
||||
{
|
||||
UiThread.ClearInterval(waitingForRefresh);
|
||||
public override void SetThumbnail(ILibraryItem item, int width, int height, ImageBuffer imageBuffer)
|
||||
{
|
||||
#if DEBUG
|
||||
// throw new NotImplementedException();
|
||||
#endif
|
||||
}
|
||||
|
||||
waitingForRefresh = null;
|
||||
this.ReloadContent();
|
||||
}
|
||||
}
|
||||
public override ICustomSearch CustomSearch { get; }
|
||||
|
||||
public class DirectoryContainerLink : FileSystemItem, ILibraryContainerLink
|
||||
{
|
||||
public DirectoryContainerLink(string path)
|
||||
: base(path)
|
||||
{
|
||||
}
|
||||
public string FullPath { get; protected set; }
|
||||
|
||||
public bool IsReadOnly { get; set; } = false;
|
||||
// Indicates if the new AMF file should use the original file name incremented until no name collision occurs
|
||||
public bool UseIncrementedNameDuringTypeChange { get; internal set; }
|
||||
|
||||
public bool UseIncrementedNameDuringTypeChange { get; set; }
|
||||
public override void Activate()
|
||||
{
|
||||
this.isActiveContainer = true;
|
||||
base.Activate();
|
||||
}
|
||||
|
||||
public Task<ILibraryContainer> GetContainer(Action<double, string> reportProgress)
|
||||
{
|
||||
return Task.FromResult<ILibraryContainer>(
|
||||
new FileSystemContainer(this.FilePath)
|
||||
{
|
||||
UseIncrementedNameDuringTypeChange = this.UseIncrementedNameDuringTypeChange,
|
||||
Name = this.Name
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
public async override void Add(IEnumerable<ILibraryItem> items)
|
||||
{
|
||||
if (!items.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (directoryWatcher != null)
|
||||
{
|
||||
// turn them off whil ewe add the content
|
||||
directoryWatcher.EnableRaisingEvents = false;
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(this.FullPath);
|
||||
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
switch (item)
|
||||
{
|
||||
case CreateFolderItem newFolder:
|
||||
string targetFolderPath = Path.Combine(this.FullPath, newFolder.Name);
|
||||
|
||||
// TODO: write adaption of GetNonCollidingName for directories
|
||||
Directory.CreateDirectory(targetFolderPath);
|
||||
this.isDirty = true;
|
||||
|
||||
break;
|
||||
|
||||
case ILibraryAssetStream streamItem:
|
||||
string targetPath = Path.Combine(this.FullPath, streamItem.FileName);
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(targetPath))
|
||||
{
|
||||
targetPath = GetNonCollidingName(Path.GetFileName(targetPath));
|
||||
}
|
||||
|
||||
using (var outputStream = File.OpenWrite(targetPath))
|
||||
using (var contentStream = await streamItem.GetStream(null))
|
||||
{
|
||||
contentStream.Stream.CopyTo(outputStream);
|
||||
}
|
||||
|
||||
this.Items.Add(new FileSystemFileItem(targetPath));
|
||||
this.isDirty = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
ApplicationController.Instance.LogError($"Error adding file: {targetPath}\r\n{ex.Message}");
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (directoryWatcher != null)
|
||||
{
|
||||
// turn them back on
|
||||
directoryWatcher.EnableRaisingEvents = true;
|
||||
}
|
||||
|
||||
if (this.isDirty)
|
||||
{
|
||||
this.ReloadContent();
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyFilter(string filter, ILibraryContext libraryContext)
|
||||
{
|
||||
keywordFilter = filter;
|
||||
this.Load();
|
||||
this.OnContentChanged();
|
||||
}
|
||||
|
||||
public void ClearFilter()
|
||||
{
|
||||
keywordFilter = null;
|
||||
this.Load();
|
||||
this.OnContentChanged();
|
||||
}
|
||||
|
||||
public override void Deactivate()
|
||||
{
|
||||
this.isActiveContainer = false;
|
||||
base.Deactivate();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (directoryWatcher != null)
|
||||
{
|
||||
directoryWatcher.EnableRaisingEvents = false;
|
||||
|
||||
directoryWatcher.Changed -= DirectoryContentsChanged;
|
||||
directoryWatcher.Created -= DirectoryContentsChanged;
|
||||
directoryWatcher.Deleted -= DirectoryContentsChanged;
|
||||
directoryWatcher.Renamed -= DirectoryContentsChanged;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
this.Load(false);
|
||||
}
|
||||
|
||||
public void Load(bool recursive)
|
||||
{
|
||||
SearchOption searchDepth = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||||
|
||||
try
|
||||
{
|
||||
string filter = keywordFilter?.Trim() ?? "";
|
||||
|
||||
var allFiles = Directory.GetFiles(FullPath, "*.*", searchDepth);
|
||||
|
||||
var zipFiles = allFiles.Where(f => Path.GetExtension(f).IndexOf(".zip", StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
var nonZipFiles = allFiles.Except(zipFiles);
|
||||
|
||||
if (filter == "")
|
||||
{
|
||||
var directories = Directory.GetDirectories(FullPath, "*.*", searchDepth).Select(p => new DirectoryContainerLink(p)).ToList<ILibraryContainerLink>();
|
||||
this.ChildContainers = new SafeList<ILibraryContainerLink>(directories.Concat(zipFiles.Select(f => new LocalZipContainerLink(f))));
|
||||
var libraryFiles = allFiles.Where(f => Path.GetExtension(f).IndexOf(".library", StringComparison.OrdinalIgnoreCase) != -1);
|
||||
this.ChildContainers.AddRange(libraryFiles.Select(f => LibraryJsonFile.ContainerFromLocalFile(f)));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ChildContainers = new SafeList<ILibraryContainerLink>();
|
||||
}
|
||||
|
||||
var matchedFiles = nonZipFiles.Where(filePath =>
|
||||
{
|
||||
string fileName = Path.GetFileName(filePath);
|
||||
|
||||
return (filter == "" || FileNameContainsFilter(filePath, filter))
|
||||
&& ApplicationController.Instance.Library.IsContentFileType(fileName);
|
||||
});
|
||||
|
||||
this.ChildContainers.Modify((list) =>
|
||||
{
|
||||
list.Sort((a, b) => a.Name.CompareTo(b.Name));
|
||||
});
|
||||
|
||||
// Matched files projected onto FileSystemFileItem
|
||||
this.Items = new SafeList<ILibraryItem>(matchedFiles.OrderBy(f => f).Select(f => new FileSystemFileItem(f)));
|
||||
|
||||
var indexMd = nonZipFiles.Where(f => f.EndsWith("index.md")).FirstOrDefault();
|
||||
if (indexMd != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
HeaderMarkdown = File.ReadAllText(indexMd);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
this.isDirty = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.ChildContainers = new SafeList<ILibraryContainerLink>();
|
||||
this.Items = new SafeList<ILibraryItem>()
|
||||
{
|
||||
new MessageItem("Error loading container - " + ex.Message)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public override void Remove(IEnumerable<ILibraryItem> items)
|
||||
{
|
||||
if (AggContext.OperatingSystem == OSType.Windows)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is FileSystemItem fileItem
|
||||
&& File.Exists(fileItem.FilePath))
|
||||
{
|
||||
File.Delete(fileItem.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
this.ReloadContent();
|
||||
}
|
||||
}
|
||||
|
||||
private void DirectoryContentsChanged(object sender, EventArgs e)
|
||||
{
|
||||
// Flag for reload
|
||||
isDirty = true;
|
||||
|
||||
lastTimeContentsChanged = UiThread.CurrentTimerMs;
|
||||
|
||||
// Only refresh content if we're the active container
|
||||
if (isActiveContainer
|
||||
&& waitingForRefresh == null)
|
||||
{
|
||||
waitingForRefresh = UiThread.SetInterval(WaitToRefresh, .5);
|
||||
}
|
||||
}
|
||||
|
||||
private bool FileNameContainsFilter(string filename, string filter)
|
||||
{
|
||||
string nameWithSpaces = Path.GetFileNameWithoutExtension(filename.Replace('_', ' '));
|
||||
|
||||
// Split the filter on word boundaries and determine if all terms in the given file name
|
||||
foreach (string word in filter.Split(' '))
|
||||
{
|
||||
if (nameWithSpaces.IndexOf(word, StringComparison.OrdinalIgnoreCase) == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private string GetNonCollidingName(string fileName)
|
||||
{
|
||||
// Switching from .stl, .obj or similar to AMF. Save the file and update the
|
||||
// the filename with an incremented (n) value to reflect the extension change in the UI
|
||||
var similarFileNames = Directory.GetFiles(this.FullPath, $"{Path.GetFileNameWithoutExtension(fileName)}.*");
|
||||
|
||||
// ;
|
||||
var validName = Util.GetNonCollidingName(fileName, (testName) => !File.Exists(testName));
|
||||
|
||||
return validName;
|
||||
}
|
||||
|
||||
private void WaitToRefresh()
|
||||
{
|
||||
if (UiThread.CurrentTimerMs > lastTimeContentsChanged + 500
|
||||
&& waitingForRefresh != null)
|
||||
{
|
||||
UiThread.ClearInterval(waitingForRefresh);
|
||||
|
||||
waitingForRefresh = null;
|
||||
this.ReloadContent();
|
||||
}
|
||||
}
|
||||
|
||||
public class DirectoryContainerLink : FileSystemItem, ILibraryContainerLink
|
||||
{
|
||||
public DirectoryContainerLink(string path)
|
||||
: base(path)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsReadOnly { get; set; } = false;
|
||||
|
||||
public bool UseIncrementedNameDuringTypeChange { get; set; }
|
||||
|
||||
public Task<ILibraryContainer> GetContainer(Action<double, string> reportProgress)
|
||||
{
|
||||
return Task.FromResult<ILibraryContainer>(
|
||||
new FileSystemContainer(this.FilePath)
|
||||
{
|
||||
UseIncrementedNameDuringTypeChange = this.UseIncrementedNameDuringTypeChange,
|
||||
Name = this.Name
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -75,7 +75,7 @@ namespace MatterHackers.MatterControl.Library
|
|||
|
||||
public DateTime DateModified { get; }
|
||||
|
||||
public virtual string ID => agg_basics.GetLongHashCode(this.FilePath).ToString();
|
||||
public virtual string ID => Util.GetLongHashCode(this.FilePath).ToString();
|
||||
|
||||
public virtual bool IsProtected => false;
|
||||
|
||||
|
|
|
|||
|
|
@ -317,7 +317,7 @@ namespace MatterHackers.MatterControl.Library
|
|||
|
||||
public long FileSize { get; } = -1;
|
||||
|
||||
public string ID => agg_basics.GetLongHashCode(AssetPath).ToString();
|
||||
public string ID => Util.GetLongHashCode(AssetPath).ToString();
|
||||
|
||||
public bool IsProtected => true;
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ namespace MatterHackers.MatterControl.Library
|
|||
|
||||
public long FileSize { get; private set; }
|
||||
|
||||
public string ID => agg_basics.GetLongHashCode(Url).ToString();
|
||||
public string ID => Util.GetLongHashCode(Url).ToString();
|
||||
|
||||
public bool IsLocked { get; internal set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ namespace MatterHackers.MatterControl.Library
|
|||
|
||||
public string Category { get; } = "";
|
||||
|
||||
public string ID => agg_basics.GetLongHashCode(AssetPath).ToString();
|
||||
public string ID => Util.GetLongHashCode(AssetPath).ToString();
|
||||
|
||||
public event EventHandler NameChanged;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (c) 2022, John Lewin, Lars Brubaker
|
||||
Copyright (c) 2023, John Lewin, Lars Brubaker
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -48,34 +48,26 @@ namespace MatterHackers.MatterControl.Library
|
|||
|
||||
this.ChildContainers.Add(
|
||||
new DynamicContainerLink(
|
||||
"Calibration Parts".Localize(),
|
||||
StaticData.Instance.LoadIcon(Path.Combine("Library", "folder.png")),
|
||||
StaticData.Instance.LoadIcon(Path.Combine("Library", "calibration_library_icon.png")),
|
||||
() => new CalibrationPartsContainer())
|
||||
{
|
||||
IsReadOnly = true
|
||||
});
|
||||
|
||||
this.ChildContainers.Add(
|
||||
new DynamicContainerLink(
|
||||
"Scripting".Localize(),
|
||||
StaticData.Instance.LoadIcon(Path.Combine("Library", "folder.png")),
|
||||
StaticData.Instance.LoadIcon(Path.Combine("Library", "scripting_icon.png")),
|
||||
() => new ScriptingPartsContainer())
|
||||
{
|
||||
IsReadOnly = true
|
||||
});
|
||||
|
||||
this.ChildContainers.Add(
|
||||
new DynamicContainerLink(
|
||||
"Primitives".Localize(),
|
||||
"Primitives 3D".Localize(),
|
||||
StaticData.Instance.LoadIcon(Path.Combine("Library", "folder.png")),
|
||||
StaticData.Instance.LoadIcon(Path.Combine("Library", "primitives_library_icon.png")),
|
||||
() => new PrimitivesContainer())
|
||||
() => new Primitives3DContainer())
|
||||
{
|
||||
IsReadOnly = true
|
||||
});
|
||||
|
||||
#if DEBUG
|
||||
this.ChildContainers.Add(
|
||||
new DynamicContainerLink(
|
||||
"Primitives 2D".Localize(),
|
||||
StaticData.Instance.LoadIcon(Path.Combine("Library", "folder.png")),
|
||||
StaticData.Instance.LoadIcon(Path.Combine("Library", "primitives_library_icon.png")),
|
||||
() => new Primitives2DContainer())
|
||||
{
|
||||
IsReadOnly = true
|
||||
});
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
int index = 0;
|
||||
|
||||
|
|
@ -114,10 +106,11 @@ namespace MatterHackers.MatterControl.Library
|
|||
return Task.FromResult<IObject3D>(path);
|
||||
})
|
||||
{ DateCreated = new System.DateTime(index++) },
|
||||
}
|
||||
},
|
||||
Name = "Experimental".Localize()
|
||||
})
|
||||
{
|
||||
IsReadOnly = true
|
||||
IsReadOnly = true,
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
Copyright (c) 2019, John Lewin
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of the FreeBSD Project.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.DesignTools;
|
||||
using MatterHackers.MatterControl.DesignTools.Primitives;
|
||||
|
||||
namespace MatterHackers.MatterControl.Library
|
||||
{
|
||||
public class Primitives2DContainer : LibraryContainer
|
||||
{
|
||||
public Primitives2DContainer()
|
||||
{
|
||||
Name = "Primitives 2D".Localize();
|
||||
DefaultSort = new LibrarySortBehavior()
|
||||
{
|
||||
SortKey = SortKey.ModifiedDate,
|
||||
Ascending = true,
|
||||
};
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
var library = ApplicationController.Instance.Library;
|
||||
|
||||
long index = DateTime.Now.Ticks;
|
||||
var libraryItems = new List<GeneratorItem>()
|
||||
{
|
||||
new GeneratorItem(
|
||||
"Box".Localize(),
|
||||
async () => await BoxPathObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Triangle".Localize(),
|
||||
async () => await PyramidObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Trapezoid".Localize(),
|
||||
async () => await WedgeObject3D_2.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Text".Localize(),
|
||||
async () => await TextObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Oval".Localize(),
|
||||
async () => await CylinderObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Star".Localize(),
|
||||
async () => await ConeObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Ring".Localize(),
|
||||
async () => await RingObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Circle".Localize(),
|
||||
async () => await SphereObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
};
|
||||
|
||||
string title = "2D Shapes".Localize();
|
||||
|
||||
foreach (var item in libraryItems)
|
||||
{
|
||||
item.Category = title;
|
||||
Items.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -40,9 +40,9 @@ using MatterHackers.MatterControl.DesignTools.Operations;
|
|||
|
||||
namespace MatterHackers.MatterControl.Library
|
||||
{
|
||||
public class PrimitivesContainer : LibraryContainer
|
||||
public class Primitives3DContainer : LibraryContainer
|
||||
{
|
||||
public PrimitivesContainer()
|
||||
public Primitives3DContainer()
|
||||
{
|
||||
Name = "Primitives".Localize();
|
||||
DefaultSort = new LibrarySortBehavior()
|
||||
|
|
@ -81,7 +81,7 @@ namespace MatterHackers.MatterControl.Library
|
|||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Text".Localize(),
|
||||
async () => await TextObject3D.Create(true))
|
||||
async () => await TextObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Cylinder".Localize(),
|
||||
|
|
@ -188,67 +188,4 @@ namespace MatterHackers.MatterControl.Library
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
public class Primitives2DContainer : LibraryContainer
|
||||
{
|
||||
public Primitives2DContainer()
|
||||
{
|
||||
Name = "Primitives 2D".Localize();
|
||||
DefaultSort = new LibrarySortBehavior()
|
||||
{
|
||||
SortKey = SortKey.ModifiedDate,
|
||||
Ascending = true,
|
||||
};
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
var library = ApplicationController.Instance.Library;
|
||||
|
||||
long index = DateTime.Now.Ticks;
|
||||
var libraryItems = new List<GeneratorItem>()
|
||||
{
|
||||
new GeneratorItem(
|
||||
"Box".Localize(),
|
||||
async () => await BoxPathObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Triangle".Localize(),
|
||||
async () => await PyramidObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Trapezoid".Localize(),
|
||||
async () => await WedgeObject3D_2.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Text".Localize(),
|
||||
async () => await TextObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Oval".Localize(),
|
||||
async () => await CylinderObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Star".Localize(),
|
||||
async () => await ConeObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Ring".Localize(),
|
||||
async () => await RingObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
new GeneratorItem(
|
||||
"Circle".Localize(),
|
||||
async () => await SphereObject3D.Create())
|
||||
{ DateCreated = new DateTime(index++) },
|
||||
};
|
||||
|
||||
string title = "2D Shapes".Localize();
|
||||
|
||||
foreach (var item in libraryItems)
|
||||
{
|
||||
item.Category = title;
|
||||
Items.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ namespace MatterHackers.MatterControl.Library
|
|||
|
||||
public string Category { get; } = "";
|
||||
|
||||
public string ID => agg_basics.GetLongHashCode(AssetPath).ToString();
|
||||
public string ID => Util.GetLongHashCode(AssetPath).ToString();
|
||||
|
||||
public event EventHandler NameChanged;
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ namespace MatterHackers.MatterControl.Library
|
|||
/// </summary>
|
||||
public long FileSize { get; private set; }
|
||||
|
||||
public override string ID => agg_basics.GetLongHashCode($"{this.FilePath}/{this.RelativePath}").ToString();
|
||||
public override string ID => Util.GetLongHashCode($"{this.FilePath}/{this.RelativePath}").ToString();
|
||||
|
||||
public ZipMemoryContainer ContainingZip { get; }
|
||||
public string RelativePath { get; set; }
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ namespace MatterHackers.MatterControl.Library
|
|||
|
||||
this.url = url;
|
||||
this.Name = name ?? "Unknown".Localize();
|
||||
this.ID = agg_basics.GetLongHashCode(url).ToString();
|
||||
this.ID = Util.GetLongHashCode(url).ToString();
|
||||
}
|
||||
|
||||
public string ID { get; set; }
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ namespace MatterHackers.MatterControl.Library.Widgets
|
|||
{
|
||||
string printerName = treeView.SelectedNode.Tag.ToString();
|
||||
|
||||
printerNameInput.Text = agg_basics.GetNonCollidingName(printerName, this.ExistingPrinterNames);
|
||||
printerNameInput.Text = Util.GetNonCollidingName(printerName, this.ExistingPrinterNames);
|
||||
|
||||
this.SelectedPrinter = treeView.SelectedNode.Tag as MakeModelInfo;
|
||||
|
||||
|
|
|
|||
|
|
@ -786,8 +786,6 @@ namespace MatterHackers.MatterControl.Library.Widgets
|
|||
null,
|
||||
async (reporter, cancellationTokenSource) =>
|
||||
{
|
||||
var progressStatus = new ProgressStatus();
|
||||
|
||||
// Change loaded scene to new context
|
||||
await printer.Bed.LoadContent(
|
||||
new EditContext()
|
||||
|
|
@ -796,12 +794,7 @@ namespace MatterHackers.MatterControl.Library.Widgets
|
|||
// No content store for GCode
|
||||
ContentStore = null
|
||||
},
|
||||
(progress, message) =>
|
||||
{
|
||||
progressStatus.Progress0To1 = progress;
|
||||
progressStatus.Status = message;
|
||||
reporter.Report(progressStatus);
|
||||
}).ConfigureAwait(false);
|
||||
reporter).ConfigureAwait(false);
|
||||
});
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -611,7 +611,6 @@ namespace MatterHackers.MatterControl.CustomWidgets
|
|||
null,
|
||||
async (reporter, cancellationTokenSource) =>
|
||||
{
|
||||
var progressStatus = new ProgressStatus();
|
||||
var editContext = new EditContext()
|
||||
{
|
||||
ContentStore = writableContainer,
|
||||
|
|
@ -619,9 +618,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
|
|||
};
|
||||
await workspace.SceneContext.LoadContent(editContext, (progress, message) =>
|
||||
{
|
||||
progressStatus.Progress0To1 = progress;
|
||||
progressStatus.Status = message;
|
||||
reporter.Report(progressStatus);
|
||||
reporter?.Invoke(progress, message);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue