From d647cf8a865bdb2f118fe2dbd9081204a49ebd5d Mon Sep 17 00:00:00 2001 From: John Lewin Date: Wed, 5 Apr 2017 19:03:04 -0700 Subject: [PATCH] Add DragDrop support for image content --- ApplicationView/MainApplicationWidget.cs | 35 ++++++++ PartPreviewWindow/View3D/View3DWidget.cs | 100 ++++++++++++++++------- Queue/QueueDataWidget.cs | 30 ++++++- 3 files changed, 136 insertions(+), 29 deletions(-) diff --git a/ApplicationView/MainApplicationWidget.cs b/ApplicationView/MainApplicationWidget.cs index 794dce74a..2276b1201 100644 --- a/ApplicationView/MainApplicationWidget.cs +++ b/ApplicationView/MainApplicationWidget.cs @@ -56,11 +56,44 @@ namespace MatterHackers.MatterControl using Agg.Image; using System.Net; using CustomWidgets; + using MatterHackers.DataConverters3D; public class OemProfileDictionary : Dictionary> { } + public class ContentResult + { + public IObject3D Object3D { get; set; } + public Task MeshLoaded { get; set; } + } + + public interface IContentProvider + { + ContentResult CreateItem(string filePath); + } + + public class SimpleContentProvider : IContentProvider + { + public Func Generator { get; set; } + + public ContentResult CreateItem(string filePath) + { + return this.Generator(filePath); + } + } + + public static class ExtensionMethods + { + public static void Add(this Dictionary list, IEnumerable extensions, IContentProvider provider) + { + foreach(var extension in extensions) + { + list.Add(extension, provider); + } + } + } + public class PublicDevice { public string DeviceToken { get; set; } @@ -224,6 +257,8 @@ namespace MatterHackers.MatterControl public SlicePresetsWindow EditQualityPresetsWindow { get; set; } + public Dictionary SceneContentProviders = new Dictionary(); + public ApplicationView MainView; public event EventHandler ApplicationClosed; diff --git a/PartPreviewWindow/View3D/View3DWidget.cs b/PartPreviewWindow/View3D/View3DWidget.cs index fdbd0a985..6c58f022d 100644 --- a/PartPreviewWindow/View3D/View3DWidget.cs +++ b/PartPreviewWindow/View3D/View3DWidget.cs @@ -186,6 +186,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow public partial class View3DWidget : PartPreview3DWidget { private bool DoBooleanTest = false; + private bool deferEditorTillMouseUp = false; + public FlowLayoutWidget doEdittingButtonsContainer; public UndoBuffer UndoBuffer { get; private set; } = new UndoBuffer(); public readonly int EditButtonHeight = 44; @@ -872,22 +874,27 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { if (AllowDragDrop()) { - foreach (string file in mouseEvent.DragFiles) - { - string extension = Path.GetExtension(file).ToLower(); - if (extension != "" && ApplicationSettings.OpenDesignFileParams.Contains(extension)) - { - mouseEvent.AcceptDrop = true; - } - } + mouseEvent.AcceptDrop = mouseEvent.DragFiles.TrueForAll(filePath => AllowFileDrop(filePath)); if (mouseEvent.AcceptDrop) { - DragDropSource = new Object3D + string filePath = mouseEvent.DragFiles.FirstOrDefault(); + string extensionWithoutPeriod = Path.GetExtension(filePath).Trim('.'); + + IContentProvider contentProvider; + if (!string.IsNullOrEmpty(filePath) + && ApplicationController.Instance.SceneContentProviders.TryGetValue(extensionWithoutPeriod, out contentProvider)) { - ItemType = Object3DTypes.Model, - Mesh = PlatonicSolids.CreateCube(10, 10, 10) - }; + DragDropSource = contentProvider.CreateItem(filePath).Object3D; + } + else + { + DragDropSource = new Object3D + { + ItemType = Object3DTypes.Model, + Mesh = PlatonicSolids.CreateCube(10, 10, 10) + }; + } } } } @@ -903,7 +910,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow /// Provides a View3DWidget specific drag implementation /// /// The screen space mouse position. - /// A value indicating in the DragDropSource was added to the scene + /// A value indicating if a new item was generated for the DragDropSource and added to the scene public bool AltDragOver(Vector2 screenSpaceMousePosition) { if (this.HasBeenClosed) @@ -942,6 +949,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow CurrentSelectInfo.PlaneDownHitPos = intersectInfo.hitPosition; CurrentSelectInfo.LastMoveDelta = Vector3.Zero; + this.deferEditorTillMouseUp = true; + // Add item to scene and select it Scene.ModifyChildren(children => { @@ -987,14 +996,19 @@ namespace MatterHackers.MatterControl.PartPreviewWindow IObject3D loadedItem = await Task.Run(() => { - return Object3D.Load(dragSource.MeshPath, progress: new DragDropLoadProgress(this, dragSource).UpdateLoadProgress); + string extensionWithoutPeriod = Path.GetExtension(dragSource.MeshPath).Trim('.'); + if (ApplicationController.Instance.SceneContentProviders.ContainsKey(extensionWithoutPeriod)) + { + return null; + } + else + { + return Object3D.Load(dragSource.MeshPath, progress: new DragDropLoadProgress(this, dragSource).UpdateLoadProgress); + } }); if (loadedItem != null) { - // TODO: Changing an item in the scene has a risk of collection modified during enumeration errors. This approach works as - // a proof of concept but needs to take the more difficult route of managing state and swapping the dragging instance with - // the new loaded item data Vector3 meshGroupCenter = loadedItem.GetAxisAlignedBoundingBox(Matrix4X4.Identity).Center; dragSource.Mesh = loadedItem.Mesh; dragSource.Children.AddRange(loadedItem.Children); @@ -1247,7 +1261,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow // the "loading" mesh with the actual file contents if (AltDragOver(screenSpaceMousePosition)) { - DragDropSource.MeshPath = mouseEvent.DragFiles.First(); + DragDropSource.MeshPath = mouseEvent.DragFiles.FirstOrDefault(); // Run the rest of the OnDragOver pipeline since we're starting a new thread and won't finish for an unknown time base.OnMouseMove(mouseEvent); @@ -1291,10 +1305,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow else if (AllowDragDrop()) { // Items need to be added to the scene - var partsToAdd = (from droppedFileName in mouseEvent.DragFiles - let extension = Path.GetExtension(droppedFileName).ToLower() - where !string.IsNullOrEmpty(extension) && ApplicationSettings.OpenDesignFileParams.Contains(extension) - select droppedFileName).ToArray(); + var partsToAdd = mouseEvent.DragFiles.Where(filePath => AllowFileDrop(filePath)).ToArray(); if (partsToAdd.Length > 0) { @@ -1307,6 +1318,12 @@ namespace MatterHackers.MatterControl.PartPreviewWindow loadAndAddPartsToPlate(partsToAdd); } } + + if (deferEditorTillMouseUp) + { + this.deferEditorTillMouseUp = false; + Scene_SelectionChanged(null, null); + } } if (meshViewerWidget.TrackballTumbleWidget.TransformState == TrackBallController.MouseDownType.None @@ -1520,6 +1537,17 @@ namespace MatterHackers.MatterControl.PartPreviewWindow flowToAddTo.AddChild(saveButtons); } + // Indicates if DragDrop operations should be allowed for the given file type + private bool AllowFileDrop(string filePath) + { + string extension = Path.GetExtension(filePath).ToLower(); + string extensionWithoutPeriod = extension.Trim('.'); + + return !string.IsNullOrEmpty(extension) + && (ApplicationSettings.OpenDesignFileParams.Contains(extension) || ApplicationController.Instance.SceneContentProviders.Keys.Contains(extensionWithoutPeriod)); + } + + // Indicates if MatterControl is in a mode that allows DragDrop private bool AllowDragDrop() { if ((!enterEditButtonsContainer.Visible @@ -1753,6 +1781,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow return; } + if (deferEditorTillMouseUp) + { + return; + } + var selectedItem = Scene.SelectedItem; HashSet mappedEditors; @@ -1952,13 +1985,24 @@ namespace MatterHackers.MatterControl.PartPreviewWindow foreach (string loadedFileName in filesToLoad) { - IObject3D newItem = Object3D.Load(loadedFileName, itemCache, (double progress0To1, string processingState, out bool continueProcessing) => + IObject3D newItem; + + string extension = Path.GetExtension(loadedFileName).ToLower(); + IContentProvider contentProvider; + if (ApplicationController.Instance.SceneContentProviders.TryGetValue(extension.Trim('.'), out contentProvider)) { - continueProcessing = !this.HasBeenClosed; - double ratioAvailable = (ratioPerFile * .5); - double currentRatio = currentRatioDone + progress0To1 * ratioAvailable; - ReportProgressChanged(currentRatio, progressMessage, out continueProcessing); - }); + newItem = contentProvider.CreateItem(loadedFileName).Object3D; + } + else + { + newItem = Object3D.Load(loadedFileName, itemCache, (double progress0To1, string processingState, out bool continueProcessing) => + { + continueProcessing = !this.HasBeenClosed; + double ratioAvailable = (ratioPerFile * .5); + double currentRatio = currentRatioDone + progress0To1 * ratioAvailable; + ReportProgressChanged(currentRatio, progressMessage, out continueProcessing); + }); + } if (HasBeenClosed) { diff --git a/Queue/QueueDataWidget.cs b/Queue/QueueDataWidget.cs index 270a20e64..15c1745d3 100644 --- a/Queue/QueueDataWidget.cs +++ b/Queue/QueueDataWidget.cs @@ -50,6 +50,7 @@ using MatterHackers.Agg.VertexSource; using MatterHackers.DataConverters3D; using MatterHackers.MatterControl.PartPreviewWindow; using System.Threading.Tasks; +using MatterHackers.MeshVisualizer; namespace MatterHackers.MatterControl.PrintQueue { @@ -426,15 +427,19 @@ namespace MatterHackers.MatterControl.PrintQueue ActionButtonLabel = "Add to Queue", Title = "MatterControl: Select A File" }, - (openParams) => + async (openParams) => { if (openParams.FileNames != null) { int preAddCount = QueueData.Instance.ItemCount; + IContentProvider contentProvider; + foreach (string fileNameToLoad in openParams.FileNames) { string extension = Path.GetExtension(fileNameToLoad).ToUpper(); + string extensionWithoutPeriod = extension.ToLower().Trim('.'); + if (extension == ".ZIP") { List partFiles = ProjectFileHandler.ImportFromProjectArchive(fileNameToLoad); @@ -446,6 +451,29 @@ namespace MatterHackers.MatterControl.PrintQueue } } } + else if (extension != "" && ApplicationController.Instance.SceneContentProviders.TryGetValue(extensionWithoutPeriod, out contentProvider)) + { + // Generate the object + var result = contentProvider.CreateItem(fileNameToLoad); + + await result.MeshLoaded; + + // Save to the library + string fileName = Path.ChangeExtension(Path.GetRandomFileName(), ".mcx"); + string libraryPath = Path.Combine(ApplicationDataStorage.Instance.ApplicationLibraryDataPath, fileName); + + var tempScene = new InteractiveScene(); + tempScene.Children.Add(result.Object3D); + tempScene.Save(libraryPath, ApplicationDataStorage.Instance.ApplicationLibraryDataPath); + + // Add the generated .mcx file to the queue + QueueData.Instance.AddItem( + new PrintItemWrapper( + new PrintItem( + Path.GetFileNameWithoutExtension(fileNameToLoad), + libraryPath))); + + } else if (extension != "" && ApplicationSettings.OpenDesignFileParams.Contains(extension.ToLower())) { // Only add files if they have an extension and if it's in the OpenDesignFileParams list