Merge pull request #2456 from jlewin/design_tools
Rewrite library/view3D DragDrop for multi-select and clarity
This commit is contained in:
commit
13b1e415ed
10 changed files with 259 additions and 366 deletions
|
|
@ -632,7 +632,7 @@ namespace MatterHackers.MatterControl
|
|||
public View3DWidget ActiveView3DWidget { get; internal set; }
|
||||
|
||||
public string PrintingItemName { get; set; }
|
||||
|
||||
|
||||
public string CachePath(ILibraryItem libraryItem)
|
||||
{
|
||||
// TODO: Use content SHA
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ namespace MatterHackers.MatterControl
|
|||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
using MatterHackers.MatterControl.PrinterCommunication;
|
||||
using MatterHackers.PolygonMesh;
|
||||
using MatterHackers.RayTracer;
|
||||
using MatterHackers.VectorMath;
|
||||
|
|
|
|||
53
Library/Interfaces/LibraryExtensionMethods.cs
Normal file
53
Library/Interfaces/LibraryExtensionMethods.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Copyright (c) 2017, 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;
|
||||
|
||||
namespace MatterHackers.MatterControl.Library
|
||||
{
|
||||
public static class LibraryExtensionMethods
|
||||
{
|
||||
public static ContentResult CreateContent(this ILibraryItem libraryItem, Action<double, string> progressReporter)
|
||||
{
|
||||
if (ApplicationController.Instance.Library.GetContentProvider(libraryItem) is ISceneContentProvider contentProvider)
|
||||
{
|
||||
return contentProvider?.CreateItem(libraryItem, progressReporter);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool IsContentFileType(this ILibraryItem item)
|
||||
{
|
||||
return item is ILibraryItem
|
||||
|| (item is ILibraryContentStream contentStream
|
||||
&& ApplicationController.Instance.Library.IsContentFileType(contentStream.FileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.MatterControl.CustomWidgets;
|
||||
|
||||
namespace MatterHackers.MatterControl.Library
|
||||
{
|
||||
|
|
@ -62,38 +62,21 @@ namespace MatterHackers.MatterControl.Library
|
|||
// TODO: Needed?
|
||||
public event EventHandler LibraryItemsChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Storage for plugin 'Creators' added via RegisterCreator
|
||||
/// </summary>
|
||||
//private CreatorsContainer registeredCreators;
|
||||
|
||||
private List<ILibraryContainerLink> libraryProviders;
|
||||
|
||||
private ILibraryContainer activeContainer;
|
||||
|
||||
public LibraryConfig()
|
||||
{
|
||||
//registeredCreators = new CreatorsContainer()
|
||||
//{
|
||||
// Name = "Creators",
|
||||
// ChildContainers = new List<ILibraryContainerLink>(),
|
||||
// Items = new List<ILibraryItem>()
|
||||
//};
|
||||
|
||||
libraryProviders = new List<ILibraryContainerLink>()
|
||||
{
|
||||
/*
|
||||
new DynamicContainerLink(
|
||||
registeredCreators.Name,
|
||||
AggContext.StaticData.LoadIcon("icon_creator.png"),
|
||||
() => registeredCreators), */
|
||||
};
|
||||
libraryProviders = new List<ILibraryContainerLink>();
|
||||
|
||||
this.RootLibaryContainer = new RootLibraryContainer(libraryProviders);
|
||||
|
||||
this.ActiveContainer = this.RootLibaryContainer;
|
||||
}
|
||||
|
||||
public ListView ActiveViewWidget { get; internal set; }
|
||||
|
||||
public ILibraryContainer RootLibaryContainer { get; }
|
||||
|
||||
public Dictionary<string, IContentProvider> ContentProviders = new Dictionary<string, IContentProvider>();
|
||||
|
|
|
|||
73
Library/Widgets/InsertionGroup.cs
Normal file
73
Library/Widgets/InsertionGroup.cs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
Copyright (c) 2017, Kevin Pope, 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl.PrintLibrary
|
||||
{
|
||||
public class InsertionGroup : Object3D
|
||||
{
|
||||
// TODO: Figure out how to collapse the InsertionGroup after the load task completes
|
||||
public InsertionGroup(IEnumerable<ILibraryItem> items)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var newItemOffset = Vector2.Zero;
|
||||
|
||||
// Filter to content file types only
|
||||
foreach (var item in items.Where(item => item.IsContentFileType()))
|
||||
{
|
||||
// Acquire
|
||||
var contentResult = item.CreateContent(null);
|
||||
if (contentResult != null)
|
||||
{
|
||||
// Add the placeholder
|
||||
var object3D = contentResult.Object3D;
|
||||
this.Children.Add(object3D);
|
||||
|
||||
// Position at accumulating offset
|
||||
object3D.Matrix *= Matrix4X4.CreateTranslation(newItemOffset.x, newItemOffset.y, 0);
|
||||
|
||||
// Wait for content to load
|
||||
await contentResult.MeshLoaded;
|
||||
|
||||
// Adjust next item position
|
||||
// TODO: do something more interesting than increment in x
|
||||
newItemOffset.x += contentResult.Object3D.GetAxisAlignedBoundingBox(Matrix4X4.Identity).XSize;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -172,11 +172,6 @@ namespace MatterHackers.MatterControl.CustomWidgets
|
|||
Margin = 0,
|
||||
};
|
||||
|
||||
imageWidget.Click += (sender, e) =>
|
||||
{
|
||||
this.OnItemSelect();
|
||||
};
|
||||
|
||||
container.AddChild(imageWidget);
|
||||
|
||||
int maxWidth = thumbWidth - 4;
|
||||
|
|
|
|||
|
|
@ -246,66 +246,29 @@ namespace MatterHackers.MatterControl.CustomWidgets
|
|||
mouseDownInBounds = true;
|
||||
mouseDownAt = mouseEvent.Position;
|
||||
|
||||
// Force selection in mousedown to ensure DragDropOperations see the item in ListView.SelectedItems - no worse than common tab behavior that apply on mousedown
|
||||
this.OnItemSelect();
|
||||
|
||||
if (IsDoubleClick(mouseEvent))
|
||||
{
|
||||
listViewItem.OnDoubleClick();
|
||||
}
|
||||
|
||||
// On mouse down update the view3DWidget reference that will be used in MouseMove and MouseUp
|
||||
view3DWidget = ApplicationController.Instance.ActiveView3DWidget;
|
||||
view3DWidget = ApplicationController.Instance.DragDropData.View3DWidget;
|
||||
|
||||
base.OnMouseDown(mouseEvent);
|
||||
}
|
||||
|
||||
|
||||
private bool contentLoadActive = false;
|
||||
|
||||
public override void OnMouseMove(MouseEventArgs mouseEvent)
|
||||
{
|
||||
var delta = mouseDownAt - mouseEvent.Position;
|
||||
|
||||
// TODO: dragActive in this case is better determined by the mouse being over the View3D control
|
||||
bool dragActive = mouseDownInBounds && delta.Length > 40;
|
||||
|
||||
// If dragging and the drag threshold has been hit, start a drag operation but loading the drag items
|
||||
if (dragActive
|
||||
&& (listViewItem.Model is ILibraryContentStream || listViewItem.Model is ILibraryContentItem))
|
||||
// If mouseDown on us and we've moved past are drag determination threshold, notify view3DWidget
|
||||
if (mouseDownInBounds && delta.Length > 40)
|
||||
{
|
||||
if (view3DWidget != null
|
||||
&& !contentLoadActive
|
||||
&& view3DWidget.DragDropSource == null)
|
||||
{
|
||||
contentLoadActive = true;
|
||||
|
||||
if (listViewItem.Model is ILibraryContentStream contentModel)
|
||||
{
|
||||
// Update the ListView pointer for the dragging item
|
||||
listViewItem.ListView.DragSourceRowItem = listViewItem;
|
||||
|
||||
var progressBar = new DragDropLoadProgress(this.view3DWidget, null);
|
||||
|
||||
var contentResult = contentModel.CreateContent(progressBar.ProgressReporter);
|
||||
|
||||
progressBar.TrackingObject = contentResult.Object3D;
|
||||
|
||||
// Assign a new drag source
|
||||
view3DWidget.DragDropSource = contentResult?.Object3D;
|
||||
|
||||
contentLoadActive = false;
|
||||
}
|
||||
else if (listViewItem.Model is ILibraryContentItem contentItem)
|
||||
{
|
||||
contentItem.GetContent(null).ContinueWith((task) =>
|
||||
{
|
||||
view3DWidget.DragDropSource = task.Result;
|
||||
contentLoadActive = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Performs move in View3DWidget and indicates if add occurred
|
||||
var screenSpaceMousePosition = this.TransformToScreenSpace(mouseEvent.Position);
|
||||
view3DWidget.AltDragOver(screenSpaceMousePosition);
|
||||
// Performs move and possible Scene add in View3DWidget
|
||||
view3DWidget.ExternalDragOver(screenSpaceMousePosition: this.TransformToScreenSpace(mouseEvent.Position));
|
||||
}
|
||||
|
||||
base.OnMouseMove(mouseEvent);
|
||||
|
|
@ -314,27 +277,14 @@ namespace MatterHackers.MatterControl.CustomWidgets
|
|||
public override void OnMouseUp(MouseEventArgs mouseEvent)
|
||||
{
|
||||
var dropData = ApplicationController.Instance.DragDropData;
|
||||
|
||||
if (dropData.View3DWidget?.DragDropSource != null && dropData.Scene.Children.Contains(view3DWidget.DragDropSource))
|
||||
if (dropData.View3DWidget?.DragOperationActive == true)
|
||||
{
|
||||
// Mouse and widget positions
|
||||
var screenSpaceMousePosition = this.TransformToScreenSpace(mouseEvent.Position);
|
||||
var meshViewerPosition = this.view3DWidget.meshViewerWidget.TransformToScreenSpace(view3DWidget.meshViewerWidget.LocalBounds);
|
||||
|
||||
// If the mouse is not within the meshViewer, remove the inserted drag item
|
||||
if (!meshViewerPosition.Contains(screenSpaceMousePosition))
|
||||
{
|
||||
dropData.Scene.ModifyChildren(children => children.Remove(view3DWidget.DragDropSource));
|
||||
dropData.Scene.ClearSelection();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create and push the undo operation
|
||||
view3DWidget.AddUndoOperation(
|
||||
new InsertCommand(view3DWidget, dropData.Scene, view3DWidget.DragDropSource));
|
||||
}
|
||||
|
||||
view3DWidget.FinishDrop();
|
||||
// Notify of drag operation complete
|
||||
view3DWidget.FinishDrop(mouseUpInBounds: meshViewerPosition.Contains(screenSpaceMousePosition));
|
||||
}
|
||||
|
||||
mouseDownInBounds = false;
|
||||
|
|
|
|||
|
|
@ -34,15 +34,12 @@ using System.Linq;
|
|||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.Agg.VertexSource;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.CustomWidgets;
|
||||
using MatterHackers.MatterControl.DataStorage;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.MatterControl.PrintQueue;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl.PrintLibrary
|
||||
{
|
||||
|
|
@ -80,6 +77,8 @@ namespace MatterHackers.MatterControl.PrintLibrary
|
|||
BackgroundColor = ActiveTheme.Instance.TertiaryBackgroundColor,
|
||||
};
|
||||
|
||||
ApplicationController.Instance.Library.ActiveViewWidget = libraryView;
|
||||
|
||||
libraryView.SelectedItems.CollectionChanged += SelectedItems_CollectionChanged;
|
||||
|
||||
ApplicationController.Instance.Library.ContainerChanged += Library_ContainerChanged;
|
||||
|
|
@ -384,46 +383,10 @@ namespace MatterHackers.MatterControl.PrintLibrary
|
|||
AllowContainers = false,
|
||||
Action = async (selectedLibraryItems, listView) =>
|
||||
{
|
||||
var itemsToAdd = new List<IObject3D>();
|
||||
|
||||
var library = ApplicationController.Instance.Library;
|
||||
|
||||
foreach (var item in selectedLibraryItems)
|
||||
{
|
||||
if (item is ILibraryContentStream contentModel)
|
||||
{
|
||||
var contentProvider = library.GetContentProvider(item) as ISceneContentProvider;
|
||||
|
||||
var result = contentProvider?.CreateItem(item, null);
|
||||
|
||||
// Wait for the content to load
|
||||
await result.MeshLoaded;
|
||||
|
||||
if (result?.Object3D != null)
|
||||
{
|
||||
itemsToAdd.Add(result.Object3D);
|
||||
}
|
||||
}
|
||||
else if (item is ILibraryContentItem contentItem)
|
||||
{
|
||||
var content = await contentItem.GetContent(null);
|
||||
if (content != null)
|
||||
{
|
||||
itemsToAdd.Add(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationController.Instance.ActiveView3DWidget.partHasBeenEdited = true;
|
||||
|
||||
var scene = ApplicationController.Instance.DragDropData.Scene;
|
||||
scene.ModifyChildren(children =>
|
||||
{
|
||||
foreach (var sceneItem in itemsToAdd)
|
||||
{
|
||||
PlatingHelper.MoveToOpenPosition(sceneItem, children);
|
||||
children.Add(sceneItem);
|
||||
}
|
||||
children.Add(new InsertionGroup(selectedLibraryItems));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -144,6 +144,8 @@
|
|||
<Compile Include="CustomWidgets\RadioPanelWidget.cs" />
|
||||
<Compile Include="CustomWidgets\ValueDisplayInfo.cs" />
|
||||
<Compile Include="CustomWidgets\DisableablePanel.cs" />
|
||||
<Compile Include="Library\Interfaces\LibraryExtensionMethods.cs" />
|
||||
<Compile Include="Library\Widgets\InsertionGroup.cs" />
|
||||
<Compile Include="Utilities\InspectForm.cs" Condition="'$(Configuration)' == 'Debug'">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ using MatterHackers.MatterControl.CustomWidgets;
|
|||
using MatterHackers.MatterControl.DataStorage;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
using MatterHackers.MatterControl.PrinterCommunication;
|
||||
using MatterHackers.MatterControl.PrintLibrary;
|
||||
using MatterHackers.MatterControl.PrintQueue;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using MatterHackers.MeshVisualizer;
|
||||
|
|
@ -583,31 +584,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
}
|
||||
}
|
||||
|
||||
public ILibraryContentStream DragSourceModel { get; set; }
|
||||
|
||||
// TODO: Rename to DragDropItem
|
||||
|
||||
private IObject3D dragDropSource;
|
||||
public IObject3D DragDropSource
|
||||
{
|
||||
get
|
||||
{
|
||||
return dragDropSource;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
// <IObject3D>
|
||||
dragDropSource = value;
|
||||
|
||||
// Clear the DragSourceModel - <ILibraryItem>
|
||||
DragSourceModel = null;
|
||||
|
||||
// Suppress ui volumes when dragDropSource is not null
|
||||
meshViewerWidget.SuppressUiVolumes = (dragDropSource != null);
|
||||
}
|
||||
}
|
||||
|
||||
private void TrackballTumbleWidget_DrawGlContent(object sender, DrawEventArgs e)
|
||||
{
|
||||
if (CurrentSelectInfo.DownOnPart
|
||||
|
|
@ -851,42 +827,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
base.OnClosed(e);
|
||||
}
|
||||
|
||||
public override void OnMouseEnterBounds(MouseEventArgs mouseEvent)
|
||||
{
|
||||
if (mouseEvent.DragFiles?.Count > 0)
|
||||
{
|
||||
if (AllowDragDrop())
|
||||
{
|
||||
mouseEvent.AcceptDrop = mouseEvent.DragFiles.TrueForAll(filePath => ApplicationController.Instance.IsLoadableFile(filePath));
|
||||
|
||||
if (mouseEvent.AcceptDrop)
|
||||
{
|
||||
string filePath = mouseEvent.DragFiles.FirstOrDefault();
|
||||
string extensionWithoutPeriod = Path.GetExtension(filePath).Trim('.');
|
||||
|
||||
IContentProvider contentProvider;
|
||||
if (!string.IsNullOrEmpty(filePath)
|
||||
&& ApplicationController.Instance.Library.ContentProviders.TryGetValue(extensionWithoutPeriod, out contentProvider)
|
||||
&& contentProvider is ISceneContentProvider)
|
||||
{
|
||||
var sceneProvider = contentProvider as ISceneContentProvider;
|
||||
this.DragDropSource = sceneProvider.CreateItem(new FileSystemFileItem(filePath), null).Object3D;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.DragDropSource = new Object3D
|
||||
{
|
||||
ItemType = Object3DTypes.Model,
|
||||
Mesh = PlatonicSolids.CreateCube(10, 10, 10)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.OnMouseEnterBounds(mouseEvent);
|
||||
}
|
||||
|
||||
public override void OnVisibleChanged(EventArgs e)
|
||||
{
|
||||
var dragDropData = ApplicationController.Instance.DragDropData;
|
||||
|
|
@ -912,89 +852,119 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
|
||||
private PlaneShape bedPlane = new PlaneShape(Vector3.UnitZ, 0, null);
|
||||
|
||||
public bool DragOperationActive { get; private set; }
|
||||
|
||||
public IObject3D DragDropObject { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Provides a View3DWidget specific drag implementation
|
||||
/// </summary>
|
||||
/// <param name="screenSpaceMousePosition">The screen space mouse position.</param>
|
||||
/// <returns>A value indicating if a new item was generated for the DragDropSource and added to the scene</returns>
|
||||
public bool AltDragOver(Vector2 screenSpaceMousePosition)
|
||||
public void ExternalDragOver(Vector2 screenSpaceMousePosition)
|
||||
{
|
||||
if (this.HasBeenClosed || this.DragDropSource == null)
|
||||
if (this.HasBeenClosed)
|
||||
{
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
bool itemAddedToScene = false;
|
||||
|
||||
// If the mouse is within the MeshViewer process the Drag move
|
||||
var meshViewerPosition = this.meshViewerWidget.TransformToScreenSpace(meshViewerWidget.LocalBounds);
|
||||
|
||||
// If the mouse is within this control
|
||||
if (meshViewerPosition.Contains(screenSpaceMousePosition)
|
||||
&& this.DragDropSource != null)
|
||||
if (meshViewerPosition.Contains(screenSpaceMousePosition))
|
||||
{
|
||||
var localPosition = this.TransformFromParentSpace(topMostParent, screenSpaceMousePosition);
|
||||
|
||||
// Inject the DragDropSource if it's missing from the scene, using the default "loading" mesh
|
||||
if (!Scene.Children.Contains(DragDropSource))
|
||||
// If already started, process drag move
|
||||
if (this.DragOperationActive)
|
||||
{
|
||||
// Set the hitplane to the bed plane
|
||||
CurrentSelectInfo.HitPlane = bedPlane;
|
||||
this.DragOver(screenSpaceMousePosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise begin an externally started DragDropOperation hard-coded to use LibraryView->SelectedItems
|
||||
|
||||
// Find intersection position of the mouse with the bed plane
|
||||
var intersectInfo = GetIntersectPosition(screenSpaceMousePosition);
|
||||
if (intersectInfo == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the initial transform on the inject part to the current transform mouse position
|
||||
var sourceItemBounds = DragDropSource.GetAxisAlignedBoundingBox(Matrix4X4.Identity);
|
||||
var center = sourceItemBounds.Center;
|
||||
|
||||
DragDropSource.Matrix *= Matrix4X4.CreateTranslation(-center.x, -center.y, -sourceItemBounds.minXYZ.z);
|
||||
DragDropSource.Matrix *= Matrix4X4.CreateTranslation(new Vector3(intersectInfo.HitPosition));
|
||||
|
||||
CurrentSelectInfo.PlaneDownHitPos = intersectInfo.HitPosition;
|
||||
CurrentSelectInfo.LastMoveDelta = Vector3.Zero;
|
||||
|
||||
this.deferEditorTillMouseUp = true;
|
||||
|
||||
// Add item to scene and select it
|
||||
Scene.ModifyChildren(children =>
|
||||
{
|
||||
children.Add(DragDropSource);
|
||||
});
|
||||
Scene.SelectedItem = DragDropSource;
|
||||
|
||||
itemAddedToScene = true;
|
||||
this.StartDragDrop(
|
||||
// Project from ListViewItem to ILibraryItem
|
||||
ApplicationController.Instance.Library.ActiveViewWidget.SelectedItems.Select(l => l.Model),
|
||||
screenSpaceMousePosition);
|
||||
}
|
||||
|
||||
// Move the object being dragged
|
||||
if (Scene.HasSelection)
|
||||
{
|
||||
// Pass the mouse position, transformed to local cords, through to the view3D widget to move the target item
|
||||
localPosition = meshViewerWidget.TransformFromScreenSpace(screenSpaceMousePosition);
|
||||
DragSelectedObject(localPosition);
|
||||
}
|
||||
|
||||
return itemAddedToScene;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void FinishDrop()
|
||||
private void DragOver(Vector2 screenSpaceMousePosition)
|
||||
{
|
||||
this.DragDropSource = null;
|
||||
this.DragSourceModel = null;
|
||||
// Move the object being dragged
|
||||
if (this.DragOperationActive
|
||||
&& this.DragDropObject != null)
|
||||
{
|
||||
// Move the DropDropObject the target item
|
||||
DragSelectedObject(localMousePostion: this.TransformFromParentSpace(topMostParent, screenSpaceMousePosition));
|
||||
}
|
||||
}
|
||||
|
||||
this.deferEditorTillMouseUp = false;
|
||||
Scene_SelectionChanged(null, null);
|
||||
private void StartDragDrop(IEnumerable<ILibraryItem> items, Vector2 screenSpaceMousePosition)
|
||||
{
|
||||
this.DragOperationActive = true;
|
||||
|
||||
this.PartHasBeenChanged();
|
||||
// Set the hitplane to the bed plane
|
||||
CurrentSelectInfo.HitPlane = bedPlane;
|
||||
|
||||
// Set focus to View3DWidget after drag-drop
|
||||
UiThread.RunOnIdle(this.Focus);
|
||||
DragDropObject = new InsertionGroup(items);
|
||||
|
||||
// Find intersection position of the mouse with the bed plane
|
||||
var intersectInfo = GetIntersectPosition(screenSpaceMousePosition);
|
||||
if (intersectInfo != null)
|
||||
{
|
||||
// Set the initial transform on the inject part to the current transform mouse position
|
||||
var sourceItemBounds = DragDropObject.GetAxisAlignedBoundingBox(Matrix4X4.Identity);
|
||||
var center = sourceItemBounds.Center;
|
||||
|
||||
this.DragDropObject.Matrix *= Matrix4X4.CreateTranslation(-center.x, -center.y, -sourceItemBounds.minXYZ.z);
|
||||
this.DragDropObject.Matrix *= Matrix4X4.CreateTranslation(new Vector3(intersectInfo.HitPosition));
|
||||
|
||||
CurrentSelectInfo.PlaneDownHitPos = intersectInfo.HitPosition;
|
||||
CurrentSelectInfo.LastMoveDelta = Vector3.Zero;
|
||||
}
|
||||
|
||||
this.deferEditorTillMouseUp = true;
|
||||
|
||||
// Add item to scene and select it
|
||||
this.Scene.ModifyChildren(children =>
|
||||
{
|
||||
children.Add(this.DragDropObject);
|
||||
});
|
||||
Scene.SelectedItem = this.DragDropObject;
|
||||
|
||||
}
|
||||
|
||||
internal void FinishDrop(bool mouseUpInBounds)
|
||||
{
|
||||
if (this.DragOperationActive)
|
||||
{
|
||||
this.DragOperationActive = false;
|
||||
|
||||
if (mouseUpInBounds)
|
||||
{
|
||||
// Create and push the undo operation
|
||||
this.AddUndoOperation(
|
||||
new InsertCommand(this, this.Scene, this.DragDropObject));
|
||||
}
|
||||
else
|
||||
{
|
||||
Scene.ModifyChildren(children => children.Remove(this.DragDropObject));
|
||||
Scene.ClearSelection();
|
||||
}
|
||||
|
||||
this.DragDropObject = null;
|
||||
|
||||
this.deferEditorTillMouseUp = false;
|
||||
Scene_SelectionChanged(null, null);
|
||||
|
||||
this.PartHasBeenChanged();
|
||||
|
||||
// Set focus to View3DWidget after drag-drop
|
||||
UiThread.RunOnIdle(this.Focus);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnLoad(EventArgs args)
|
||||
|
|
@ -1009,86 +979,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
base.OnLoad(args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the referenced DragDropSource object.
|
||||
/// </summary>
|
||||
/// <param name="dragSource">The drag source at the original time of invocation.</param>
|
||||
/// <returns></returns>
|
||||
public async Task LoadDragSource(ListViewItem sourceListItem)
|
||||
{
|
||||
// Hold initial reference
|
||||
IObject3D dragDropItem = DragDropSource;
|
||||
if (dragDropItem == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.DragSourceModel = sourceListItem?.Model as ILibraryContentStream;
|
||||
|
||||
IObject3D loadedItem = await Task.Run(async () =>
|
||||
{
|
||||
if (File.Exists(dragDropItem.MeshPath))
|
||||
{
|
||||
string extensionWithoutPeriod = Path.GetExtension(dragDropItem.MeshPath).Trim('.');
|
||||
|
||||
if (ApplicationController.Instance.Library.ContentProviders.ContainsKey(extensionWithoutPeriod))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Object3D.Load(dragDropItem.MeshPath, CancellationToken.None, progress: new DragDropLoadProgress(this, dragDropItem).ProgressReporter);
|
||||
}
|
||||
}
|
||||
else if (DragSourceModel != null)
|
||||
{
|
||||
var loadProgress = new DragDropLoadProgress(this, dragDropItem);
|
||||
|
||||
ContentResult contentResult;
|
||||
|
||||
if (sourceListItem == null)
|
||||
{
|
||||
contentResult = DragSourceModel.CreateContent(loadProgress.ProgressReporter);
|
||||
await contentResult.MeshLoaded;
|
||||
}
|
||||
else
|
||||
{
|
||||
sourceListItem.StartProgress();
|
||||
|
||||
contentResult = DragSourceModel.CreateContent((double ratio, string state) =>
|
||||
{
|
||||
sourceListItem.ProgressReporter(ratio, state);
|
||||
loadProgress.ProgressReporter(ratio, state);
|
||||
});
|
||||
|
||||
await contentResult.MeshLoaded;
|
||||
|
||||
sourceListItem.EndProgress();
|
||||
|
||||
loadProgress.ProgressReporter(1, "");
|
||||
}
|
||||
|
||||
return contentResult?.Object3D;
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
if (loadedItem != null)
|
||||
{
|
||||
Vector3 meshGroupCenter = loadedItem.GetAxisAlignedBoundingBox(Matrix4X4.Identity).Center;
|
||||
|
||||
dragDropItem.Mesh = loadedItem.Mesh;
|
||||
dragDropItem.Children = loadedItem.Children;
|
||||
|
||||
// TODO: jlewin - also need to apply the translation to the scale/rotation from the source (loadedItem.Matrix)
|
||||
dragDropItem.Matrix = loadedItem.Matrix * dragDropItem.Matrix;
|
||||
dragDropItem.Matrix *= Matrix4X4.CreateTranslation(-meshGroupCenter.x, -meshGroupCenter.y, -dragDropItem.GetAxisAlignedBoundingBox(Matrix4X4.Identity).minXYZ.z);
|
||||
}
|
||||
|
||||
this.PartHasBeenChanged();
|
||||
}
|
||||
|
||||
public override void OnDraw(Graphics2D graphics2D)
|
||||
{
|
||||
if (Scene.HasSelection)
|
||||
|
|
@ -1491,29 +1381,28 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
|
||||
public override void OnMouseMove(MouseEventArgs mouseEvent)
|
||||
{
|
||||
if (AllowDragDrop() && mouseEvent.DragFiles?.Count == 1)
|
||||
// File system Drop validation
|
||||
mouseEvent.AcceptDrop = this.AllowDragDrop()
|
||||
&& mouseEvent.DragFiles?.Count > 0
|
||||
&& mouseEvent.DragFiles.TrueForAll(filePath => ApplicationController.Instance.IsLoadableFile(filePath));
|
||||
|
||||
// View3DWidgets Filesystem DropDrop handler
|
||||
if (mouseEvent.AcceptDrop
|
||||
&& this.PositionWithinLocalBounds(mouseEvent.X, mouseEvent.Y))
|
||||
{
|
||||
var screenSpaceMousePosition = this.TransformToScreenSpace(new Vector2(mouseEvent.X, mouseEvent.Y));
|
||||
|
||||
// If the DragDropSource was added to the scene on this DragOver call, we start a task to replace
|
||||
// the "loading" mesh with the actual file contents
|
||||
if (AltDragOver(screenSpaceMousePosition))
|
||||
if (this.DragOperationActive)
|
||||
{
|
||||
this.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);
|
||||
|
||||
LoadDragSource(null);
|
||||
|
||||
// Don't fall through to the base.OnDragOver because we preemptively invoked it above
|
||||
return;
|
||||
DragOver(screenSpaceMousePosition: this.TransformToScreenSpace(mouseEvent.Position));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project DragFiles to IEnumerable<FileSystemFileItem>
|
||||
this.StartDragDrop(
|
||||
mouseEvent.DragFiles.Select(path => new FileSystemFileItem(path)),
|
||||
screenSpaceMousePosition: this.TransformToScreenSpace(mouseEvent.Position));
|
||||
}
|
||||
}
|
||||
|
||||
// AcceptDrop anytime a DropSource has been queued
|
||||
mouseEvent.AcceptDrop = this.DragDropSource != null;
|
||||
|
||||
if (CurrentSelectInfo.DownOnPart && this.TrackballTumbleWidget.TransformState == TrackBallController.MouseDownType.None)
|
||||
{
|
||||
DragSelectedObject(new Vector2(mouseEvent.X, mouseEvent.Y));
|
||||
|
|
@ -1563,23 +1452,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
|
||||
public override void OnMouseUp(MouseEventArgs mouseEvent)
|
||||
{
|
||||
if (mouseEvent.DragFiles?.Count > 0)
|
||||
if (this.DragOperationActive)
|
||||
{
|
||||
if (AllowDragDrop() && mouseEvent.DragFiles.Count == 1)
|
||||
{
|
||||
// Item is already in the scene
|
||||
this.DragDropSource = null;
|
||||
}
|
||||
else if (AllowDragDrop())
|
||||
{
|
||||
// Items need to be added to the scene
|
||||
var partsToAdd = mouseEvent.DragFiles.Where(filePath => ApplicationController.Instance.IsLoadableFile(filePath)).ToArray();
|
||||
|
||||
if (partsToAdd.Length > 0)
|
||||
{
|
||||
loadAndAddPartsToPlate(partsToAdd);
|
||||
}
|
||||
}
|
||||
this.FinishDrop(mouseUpInBounds: true);
|
||||
}
|
||||
|
||||
if (this.TrackballTumbleWidget.TransformState == TrackBallController.MouseDownType.None)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue