From c4b58c9d39376006dd86f42dd5537b455172b95b Mon Sep 17 00:00:00 2001 From: MatterHackers Date: Sun, 12 Nov 2023 21:16:03 -0800 Subject: [PATCH] Changed to IComponentObject3D Fixed a crash in convex hull Improving path editor widget Added x only pinch to radial pinch object --- .../ApplicationView/SceneOperations.cs | 12 +- MatterControlLib/DesignTools/Expressions.cs | 4 +- .../DesignTools/Operations/ArrayObject3D.cs | 4 +- .../Operations/ObjectCircleExtensions.cs | 4 + .../Operations/PathEditorWidget.cs | 98 +++- .../Operations/RadialPinchObject3D.cs | 18 +- .../Primitives/ComponentObject3D.cs | 525 +++++++++--------- .../Primitives/HalfCylinderObject3D.cs | 1 - .../PartPreviewWindow/Object3DTreeBuilder.cs | 363 ++++++------ .../PartPreviewWindow/SelectedObjectPanel.cs | 10 +- .../PartPreviewWindow/View3D/View3DWidget.cs | 1 - StaticData/Translations/Master.txt | 3 + Submodules/agg-sharp | 2 +- 13 files changed, 555 insertions(+), 490 deletions(-) diff --git a/MatterControlLib/ApplicationView/SceneOperations.cs b/MatterControlLib/ApplicationView/SceneOperations.cs index a785e3480..b9c9080ac 100644 --- a/MatterControlLib/ApplicationView/SceneOperations.cs +++ b/MatterControlLib/ApplicationView/SceneOperations.cs @@ -219,19 +219,19 @@ namespace MatterHackers.MatterControl return new SceneOperation("EditComponent") { TitleGetter = () => "Edit Component".Localize(), - ResultType = typeof(ComponentObject3D), + ResultType = typeof(IComponentObject3D), Action = (sceneContext) => { var scene = sceneContext.Scene; var sceneItem = scene.SelectedItem; - if (sceneItem is ComponentObject3D componentObject) + if (sceneItem is IComponentObject3D componentObject) { // Enable editing mode componentObject.Finalized = false; // Force editor rebuild scene.SelectedItem = null; - scene.SelectedItem = componentObject; + scene.SelectedItem = componentObject as Object3D; scene.Invalidate(new InvalidateArgs(null, InvalidateType.Children)); } @@ -242,13 +242,13 @@ namespace MatterHackers.MatterControl var sceneItem = scene.SelectedItem; return sceneItem.Parent != null && sceneItem.Parent.Parent == null - && sceneItem is ComponentObject3D componentObject + && sceneItem is IComponentObject3D componentObject && componentObject.Finalized && !componentObject.ProOnly; }, Icon = (theme) => StaticData.Instance.LoadIcon("scale_32x32.png", 16, 16).GrayToColor(theme.TextColor).SetPreMultiply(), HelpTextGetter = () => "A component must be selected".Localize().Stars(), - IsEnabled = (sceneContext) => sceneContext.Scene.SelectedItem != null && (sceneContext.Scene.SelectedItem is ComponentObject3D), + IsEnabled = (sceneContext) => sceneContext.Scene.SelectedItem != null && (sceneContext.Scene.SelectedItem is IComponentObject3D), }; } @@ -274,7 +274,7 @@ namespace MatterHackers.MatterControl return new SceneOperation("ImageConverter") { TitleGetter = () => "Image Converter".Localize(), - ResultType = typeof(ComponentObject3D), + ResultType = typeof(IComponentObject3D), Action = (sceneContext) => { var scene = sceneContext.Scene; diff --git a/MatterControlLib/DesignTools/Expressions.cs b/MatterControlLib/DesignTools/Expressions.cs index a2b35fb14..5f3df967b 100644 --- a/MatterControlLib/DesignTools/Expressions.cs +++ b/MatterControlLib/DesignTools/Expressions.cs @@ -198,7 +198,7 @@ namespace MatterHackers.MatterControl.DesignTools } } - public static IEnumerable GetComponentExpressions(ComponentObject3D component, string checkForString, bool startsWith) + public static IEnumerable GetComponentExpressions(IComponentObject3D component, string checkForString, bool startsWith) { for (var i = 0; i < component.SurfacedEditors.Count; i++) { @@ -239,7 +239,7 @@ namespace MatterHackers.MatterControl.DesignTools foreach (var item in itemToCheck.DescendantsAndSelf()) { if (GetActiveExpression(item, checkForString, startsWith).Any() - || itemToCheck is ComponentObject3D component + || itemToCheck is IComponentObject3D component && GetComponentExpressions(component, checkForString, startsWith).Any()) { // three is one so return true diff --git a/MatterControlLib/DesignTools/Operations/ArrayObject3D.cs b/MatterControlLib/DesignTools/Operations/ArrayObject3D.cs index 801f636a1..7363c19c5 100644 --- a/MatterControlLib/DesignTools/Operations/ArrayObject3D.cs +++ b/MatterControlLib/DesignTools/Operations/ArrayObject3D.cs @@ -58,7 +58,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations } // Also convert index expressions in ComponentObjects to their constants - if (item is ComponentObject3D component) + if (item is IComponentObject3D component) { for (int i = 0; i < component.SurfacedEditors.Count; i++) { @@ -105,7 +105,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations // we don't need to rebuild our source object return false; } - else if (item.Parent is ComponentObject3D) + else if (item.Parent is IComponentObject3D) { return false; } diff --git a/MatterControlLib/DesignTools/Operations/ObjectCircleExtensions.cs b/MatterControlLib/DesignTools/Operations/ObjectCircleExtensions.cs index ae8c32ff7..2b3ada403 100644 --- a/MatterControlLib/DesignTools/Operations/ObjectCircleExtensions.cs +++ b/MatterControlLib/DesignTools/Operations/ObjectCircleExtensions.cs @@ -46,6 +46,10 @@ namespace MatterHackers.MatterControl.DesignTools foreach (var visibleMesh in visibleMeshes) { var matrix = visibleMesh.source.WorldMatrix(object3D); + if (visibleMesh.convexHull == null) + { + continue; + } foreach (var positon in visibleMesh.convexHull.Vertices) { var transformed = positon.Transform(matrix); diff --git a/MatterControlLib/DesignTools/Operations/PathEditorWidget.cs b/MatterControlLib/DesignTools/Operations/PathEditorWidget.cs index 307fd71f2..b946f7f3a 100644 --- a/MatterControlLib/DesignTools/Operations/PathEditorWidget.cs +++ b/MatterControlLib/DesignTools/Operations/PathEditorWidget.cs @@ -68,6 +68,9 @@ namespace MatterHackers.MatterControl.DesignTools private VertexStorage vertexStorage; + // the last vertex storage before the last change + private VertexStorage beforeLastChange; + private ControlPointConstraint controlPointConstraint = ControlPointConstraint.Free; public PathEditorWidget(VertexStorage vertexStorage, @@ -92,6 +95,7 @@ namespace MatterHackers.MatterControl.DesignTools this.unscaledRenderOffset = unscaledRenderOffset; this.layerScale = layerScale; + this.undoBuffer = undoBuffer; var topToBottom = this; @@ -105,6 +109,8 @@ namespace MatterHackers.MatterControl.DesignTools this.vertexChanged = vertexChanged; this.theme = theme; this.vertexStorage = vertexStorage; + this.beforeLastChange = new VertexStorage(); + beforeLastChange.SvgDString = vertexStorage.SvgDString; var toolBar = new FlowLayoutWidget() { @@ -148,7 +154,7 @@ namespace MatterHackers.MatterControl.DesignTools var oldPosition = vertexStorage[controlPointBeingDragged].Position; var newPosition = new Vector2(xEditWidget.ActuallNumberEdit.Value, yEditWidget.ActuallNumberEdit.Value); var delta = newPosition - oldPosition; - OffsetSelectedPoint(delta); + OffsetSelectedPoint(delta, true); }; xEditWidget.ActuallNumberEdit.KeyDown += NumberField.InternalTextEditWidget_KeyDown; @@ -168,7 +174,7 @@ namespace MatterHackers.MatterControl.DesignTools var oldPosition = vertexStorage[controlPointBeingDragged].Position; var newPosition = new Vector2(xEditWidget.ActuallNumberEdit.Value, yEditWidget.ActuallNumberEdit.Value); var delta = newPosition - oldPosition; - OffsetSelectedPoint(delta); + OffsetSelectedPoint(delta, true); }; yEditWidget.ActuallNumberEdit.KeyDown += NumberField.InternalTextEditWidget_KeyDown; @@ -234,6 +240,8 @@ namespace MatterHackers.MatterControl.DesignTools public ETransformState TransformState { get; set; } private double layerScale { get; set; } = 1; + private UndoBuffer undoBuffer; + private Affine ScalingTransform => Affine.NewScaling(layerScale, layerScale); private Affine TotalTransform => Affine.NewTranslation(unscaledRenderOffset) * ScalingTransform * Affine.NewTranslation(Width / 2, Height / 2); @@ -246,6 +254,7 @@ namespace MatterHackers.MatterControl.DesignTools private ThemedRadioTextButton sharpButton; private ThemedRadioTextButton alignedButton; private ThemedRadioTextButton freeButton; + private bool hasBeenStartupPositioned; public void CenterPartInView() { @@ -254,15 +263,29 @@ namespace MatterHackers.MatterControl.DesignTools var partBounds = vertexStorage.GetBounds(); var weightedCenter = partBounds.Center; + var bottomPixels = 20; + var margin = 30; unscaledRenderOffset = -weightedCenter; - layerScale = Math.Min((Height - 30) / partBounds.Height, (Width - 30) / partBounds.Width); + layerScale = Math.Min((Height - margin - bottomPixels * 2) / partBounds.Height, (Width - margin) / partBounds.Width); + unscaledRenderOffset += new Vector2(0, bottomPixels) / layerScale; Invalidate(); + scaleChanged?.Invoke(unscaledRenderOffset, layerScale); } } public override void OnDraw(Graphics2D graphics2D) { + if (!hasBeenStartupPositioned) + { + if (unscaledRenderOffset == Vector2.Zero + && layerScale == 1) + { + CenterPartInView(); + } + hasBeenStartupPositioned = true; + } + new VertexSourceApplyTransform(vertexStorage, TotalTransform).RenderPath(graphics2D, theme.TextColor, 2, true, theme.PrimaryAccentColor.Blend(theme.TextColor, .5), theme.PrimaryAccentColor); //if (vertexStorage.GetType().GetCustomAttributes(typeof(PathEditorFactory.ShowAxisAttribute), true).FirstOrDefault() is PathEditorFactory.ShowAxisAttribute showAxisAttribute) @@ -412,7 +435,7 @@ namespace MatterHackers.MatterControl.DesignTools if (mouseDelta.LengthSquared > 0) { ScalingTransform.inverse_transform(ref mouseDelta); - OffsetSelectedPoint(mouseDelta); + OffsetSelectedPoint(mouseDelta, false); UpdateControlsForSelection(); } } @@ -425,38 +448,67 @@ namespace MatterHackers.MatterControl.DesignTools lastMousePosition = mouseEvent.Position; } - private void OffsetSelectedPoint(Vector2 delta) + public override void OnMouseUp(MouseEventArgs mouseEvent) + { + OffsetSelectedPoint(new Vector2(), true); + base.OnMouseUp(mouseEvent); + } + + private void OffsetSelectedPoint(Vector2 delta, bool recordUndo) { if (controlPointBeingDragged < 0 - || controlPointBeingDragged >= vertexStorage.Count - || delta.LengthSquared == 0) + || controlPointBeingDragged >= vertexStorage.Count) { return; } - var vertexData = vertexStorage[controlPointBeingDragged]; - - if (vertexData.Hint == CommandHint.C4Point) + if (delta.LengthSquared > 0) { - for (int i = -1; i < 2; i++) + var vertexData = vertexStorage[controlPointBeingDragged]; + + if (vertexData.Hint == CommandHint.C4Point) { - var pointIndex = controlPointBeingDragged + i; - // the prev point - if (pointIndex > 0 - && pointIndex < vertexStorage.Count) + for (int i = -1; i < 2; i++) { - var vertexData2 = vertexStorage[pointIndex]; - vertexStorage[pointIndex] = new VertexData(vertexData2.Command, vertexData2.Position + delta, vertexData2.Hint); + var pointIndex = controlPointBeingDragged + i; + // the prev point + if (pointIndex > 0 + && pointIndex < vertexStorage.Count) + { + var vertexData2 = vertexStorage[pointIndex]; + vertexStorage[pointIndex] = new VertexData(vertexData2.Command, vertexData2.Position + delta, vertexData2.Hint); + } } } - } - else - { - // only drag the point - vertexStorage[controlPointBeingDragged] = new VertexData(vertexData.Command, vertexData.Position + delta, vertexData.Hint); + else + { + // only drag the point + vertexStorage[controlPointBeingDragged] = new VertexData(vertexData.Command, vertexData.Position + delta, vertexData.Hint); + } + + vertexChanged?.Invoke(); } - vertexChanged?.Invoke(); + if (recordUndo) + { + var doVertexBuffer = new VertexStorage(); + doVertexBuffer.SvgDString = vertexStorage.SvgDString; + + var undoVertexBuffer = new VertexStorage(); + undoVertexBuffer.SvgDString = beforeLastChange.SvgDString; + + undoBuffer.AddAndDo(new UndoRedoActions(() => + { + vertexStorage.SvgDString = undoVertexBuffer.SvgDString; + vertexChanged?.Invoke(); + }, () => + { + vertexStorage.SvgDString = doVertexBuffer.SvgDString; + vertexChanged?.Invoke(); + })); + // record the change + beforeLastChange.SvgDString = vertexStorage.SvgDString; + } } private void DoTranslateAndZoom(MouseEventArgs mouseEvent) diff --git a/MatterControlLib/DesignTools/Operations/RadialPinchObject3D.cs b/MatterControlLib/DesignTools/Operations/RadialPinchObject3D.cs index e860fcbe4..aac6af9cd 100644 --- a/MatterControlLib/DesignTools/Operations/RadialPinchObject3D.cs +++ b/MatterControlLib/DesignTools/Operations/RadialPinchObject3D.cs @@ -65,9 +65,15 @@ namespace MatterHackers.MatterControl.DesignTools [Slider(0, 50, snapDistance: 1)] public IntOrExpression PinchSlices { get; set; } = 20; + [EnumDisplay(Mode = EnumDisplayAttribute.PresentationMode.Buttons)] + [Description("Enable advanced features.")] public bool Advanced { get; set; } = false; + public enum PinchType { Radial, XAxis } + + public PinchType PinchTypeValue { get; set; } = PinchType.Radial; + [Description("Allows for the repositioning of the rotation origin")] public Vector2 RotationOffset { get; set; } @@ -203,15 +209,11 @@ namespace MatterHackers.MatterControl.DesignTools } var positionXy = new Vector2(position) - rotationCenter; - var fromLine = true; - if (fromLine) + positionXy *= horizontalOffset.GetXAtY(position.Z * 10) / (maxRadius * 10); + if (PinchTypeValue == PinchType.XAxis) { - positionXy *= horizontalOffset.GetXAtY(position.Z * 10) / (maxRadius * 10); - //positionXy *= xAtYInterpolator.Get(position.Z * 10) / maxRadius; - } - else - { - positionXy *= Easing.Quadratic.InOut(ratio); + // only use the x value + positionXy.Y = position.Y; } positionXy += rotationCenter; transformedMesh.Vertices[i] = new Vector3Float(positionXy.X, positionXy.Y, position.Z); diff --git a/MatterControlLib/DesignTools/Primitives/ComponentObject3D.cs b/MatterControlLib/DesignTools/Primitives/ComponentObject3D.cs index bc77749f7..0b67bc38d 100644 --- a/MatterControlLib/DesignTools/Primitives/ComponentObject3D.cs +++ b/MatterControlLib/DesignTools/Primitives/ComponentObject3D.cs @@ -27,275 +27,284 @@ 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.ComponentModel; -using System.Linq; -using System.Threading; using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.DataConverters3D.UndoCommands; using MatterHackers.Localizations; using MatterHackers.MatterControl.DesignTools.Operations; -using MatterHackers.MatterControl.PartPreviewWindow; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Threading; namespace MatterHackers.MatterControl.DesignTools { - [HideChildrenFromTreeView] - public class ComponentObject3D : Object3D, IRightClickMenuProvider - { - private const string ImageConverterComponentID = "4D9BD8DB-C544-4294-9C08-4195A409217A"; + public interface IComponentObject3D : IObject3D + { + bool Finalized { get; set; } + bool ProOnly { get; set; } - public ComponentObject3D() - { - } + (string cellId, string cellData) DecodeContent(int editorIndex); - public ComponentObject3D(IEnumerable children) - : base(children) - { - } + List SurfacedEditors { get; set; } + } - public override bool CanApply => !Finalized || Persistable; + [HideChildrenFromTreeView] + public class ComponentObject3D : Object3D, IRightClickMenuProvider, IComponentObject3D + { + private const string ImageConverterComponentID = "4D9BD8DB-C544-4294-9C08-4195A409217A"; - public override bool Persistable => ApplicationController.Instance.UserHasPermission(this); - - private bool _finalizade = true; - - [Description("Switch from editing to distribution")] - public bool Finalized - { - get => _finalizade; - - set - { - _finalizade = value; - // on any invalidate ensure that the visibility setting are correct for embedded sheet objects - foreach (var child in this.Descendants()) - { - if (child is SheetObject3D) - { - child.Visible = !this.Finalized; - } - } - } - } - - public List SurfacedEditors { get; set; } = new List(); - - [HideFromEditor] - public string ComponentID { get; set; } = ""; - - [Description("MatterHackers Internal Use")] - public bool ProOnly { get; set; } - - public override void Apply(UndoBuffer undoBuffer) - { - // we want to end up with just a group of all the visible mesh objects - using (RebuildLock()) - { - var newChildren = new List(); - - // push our matrix into a copy of our visible children - foreach (var child in this.VisibleMeshes()) - { - var meshOnlyItem = new Object3D - { - Matrix = child.WorldMatrix(this), - Color = child.WorldColor(this), - MaterialIndex = child.WorldMaterialIndex(this), - OutputType = child.WorldOutputType(this), - Mesh = child.Mesh, - Name = "Mesh".Localize() - }; - newChildren.Add(meshOnlyItem); - } - - if (newChildren.Count > 1) - { - var group = new GroupHolesAppliedObject3D - { - Name = this.Name - }; - group.Children.Modify(list => - { - list.AddRange(newChildren); - }); - newChildren.Clear(); - newChildren.Add(group); - } - else if (newChildren.Count == 1) - { - newChildren[0].Name = this.Name; - } - - // and replace us with the children - undoBuffer.AddAndDo(new ReplaceCommand(new[] { this }, newChildren)); - } - - Invalidate(InvalidateType.Children); - } - - public (string cellId, string cellData) DecodeContent(int editorIndex) - { - if (SurfacedEditors[editorIndex].StartsWith("!")) - { - var cellData2 = SurfacedEditors[editorIndex].Substring(1); - var cellId2 = cellData2.ToLower(); - // check if it has embededdata - var separator = cellData2.IndexOf(','); - if (separator != -1) - { - cellId2 = cellData2.Substring(0, separator).ToLower(); - cellData2 = cellData2.Substring(separator + 1); - } - else - { - var controledSheet = ControledSheet; - if (controledSheet != null) - { - // We don't have any cache of the cell content, get the current content - cellData2 = controledSheet.SheetData.GetCellValue(cellId2); - } - } - - return (cellId2, cellData2); - } - - return (null, null); - } - - private SheetObject3D ControledSheet => this.Descendants().ToArray()[0];//.FirstOrDefault(); - // this.Children.Where(s => s is SheetObject3D).FirstOrDefault() as SheetObject3D; - - private void RecalculateSheet() - { - // if there are editors that reference cells - for (int i=0; i - { - // wait until the sheet is done rebuilding (or 30 seconds) - var startTime = UiThread.CurrentTimerMs; - while (controledSheet.RebuildLocked - && startTime + 30000 < UiThread.CurrentTimerMs) - { - Thread.Sleep(1); - } - - componentLock.Dispose(); - }); - } - } - - public override void OnInvalidate(InvalidateArgs invalidateType) + public ComponentObject3D() { - switch(invalidateType.InvalidateType) + } + + public ComponentObject3D(IEnumerable children) + : base(children) + { + } + + public override bool CanApply => !Finalized || Persistable; + + public override bool Persistable => ApplicationController.Instance.UserHasPermission(this); + + private bool _finalizade = true; + + [Description("Switch from editing to distribution")] + public bool Finalized + { + get => _finalizade; + + set { - case InvalidateType.SheetUpdated: - case InvalidateType.Properties: - RecalculateSheet(); - break; + _finalizade = value; + // on any invalidate ensure that the visibility setting are correct for embedded sheet objects + foreach (var child in this.Descendants()) + { + if (child is SheetObject3D) + { + child.Visible = !this.Finalized; + } + } + } + } + + public List SurfacedEditors { get; set; } = new List(); + + [HideFromEditor] + public string ComponentID { get; set; } = ""; + + [Description("MatterHackers Internal Use")] + public bool ProOnly { get; set; } + + public override void Apply(UndoBuffer undoBuffer) + { + // we want to end up with just a group of all the visible mesh objects + using (RebuildLock()) + { + var newChildren = new List(); + + // push our matrix into a copy of our visible children + foreach (var child in this.VisibleMeshes()) + { + var meshOnlyItem = new Object3D + { + Matrix = child.WorldMatrix(this), + Color = child.WorldColor(this), + MaterialIndex = child.WorldMaterialIndex(this), + OutputType = child.WorldOutputType(this), + Mesh = child.Mesh, + Name = "Mesh".Localize() + }; + newChildren.Add(meshOnlyItem); + } + + if (newChildren.Count > 1) + { + var group = new GroupHolesAppliedObject3D + { + Name = this.Name + }; + group.Children.Modify(list => + { + list.AddRange(newChildren); + }); + newChildren.Clear(); + newChildren.Add(group); + } + else if (newChildren.Count == 1) + { + newChildren[0].Name = this.Name; + } + + // and replace us with the children + undoBuffer.AddAndDo(new ReplaceCommand(new[] { this }, newChildren)); + } + + Invalidate(InvalidateType.Children); + } + + public (string cellId, string cellData) DecodeContent(int editorIndex) + { + if (SurfacedEditors[editorIndex].StartsWith("!")) + { + var cellData2 = SurfacedEditors[editorIndex].Substring(1); + var cellId2 = cellData2.ToLower(); + // check if it has embededdata + var separator = cellData2.IndexOf(','); + if (separator != -1) + { + cellId2 = cellData2.Substring(0, separator).ToLower(); + cellData2 = cellData2.Substring(separator + 1); + } + else + { + var controledSheet = ControledSheet; + if (controledSheet != null) + { + // We don't have any cache of the cell content, get the current content + cellData2 = controledSheet.SheetData.GetCellValue(cellId2); + } + } + + return (cellId2, cellData2); + } + + return (null, null); + } + + private SheetObject3D ControledSheet => this.Descendants().ToArray()[0];//.FirstOrDefault(); + // this.Children.Where(s => s is SheetObject3D).FirstOrDefault() as SheetObject3D; + + private void RecalculateSheet() + { + // if there are editors that reference cells + for (int i = 0; i < SurfacedEditors.Count; i++) + { + var (cellId, cellData) = this.DecodeContent(i); + if (cellData != null + && cellData.StartsWith("=")) + { + var expression = new DoubleOrExpression(cellData); + var controledSheet = ControledSheet; + if (controledSheet != null) + { + var cell = controledSheet.SheetData[cellId]; + if (cell != null) + { + cell.Expression = expression.Value(this).ToString(); + } + } + } + } + + if (SurfacedEditors.Any(se => se.StartsWith("!")) + && !this.RebuildLocked) + { + var controledSheet = ControledSheet; + + var componentLock = this.RebuildLock(); + controledSheet.SheetData.Recalculate(); + + UiThread.RunOnIdle(() => + { + // wait until the sheet is done rebuilding (or 30 seconds) + var startTime = UiThread.CurrentTimerMs; + while (controledSheet.RebuildLocked + && startTime + 30000 < UiThread.CurrentTimerMs) + { + Thread.Sleep(1); + } + + componentLock.Dispose(); + }); + } + } + + public override void OnInvalidate(InvalidateArgs invalidateType) + { + switch (invalidateType.InvalidateType) + { + case InvalidateType.SheetUpdated: + case InvalidateType.Properties: + RecalculateSheet(); + break; } base.OnInvalidate(invalidateType); } public override void Cancel(UndoBuffer undoBuffer) - { - // Make any hiden children visible - // on any invalidate ensure that the visibility setting are correct for embedded sheet objects - foreach (var child in this.Descendants()) - { - if (child is SheetObject3D) - { - child.Visible = true; - } - } + { + // Make any hiden children visible + // on any invalidate ensure that the visibility setting are correct for embedded sheet objects + foreach (var child in this.Descendants()) + { + if (child is SheetObject3D) + { + child.Visible = true; + } + } - // Custom remove for ImageConverter - if (this.ComponentID == ImageConverterComponentID) - { - var parent = this.Parent; + // Custom remove for ImageConverter + if (this.ComponentID == ImageConverterComponentID) + { + var parent = this.Parent; - using (RebuildLock()) - { - if (this.Descendants().FirstOrDefault() is ImageObject3D imageObject3D) - { - imageObject3D.Matrix = this.Matrix; + using (RebuildLock()) + { + if (this.Descendants().FirstOrDefault() is ImageObject3D imageObject3D) + { + imageObject3D.Matrix = this.Matrix; - if (undoBuffer != null) - { - undoBuffer.AddAndDo(new ReplaceCommand(new[] { this }, new[] { imageObject3D })); - } - else - { - parent.Children.Modify(list => - { - list.Remove(this); - list.Add(imageObject3D); - }); - } - } - } + if (undoBuffer != null) + { + undoBuffer.AddAndDo(new ReplaceCommand(new[] { this }, new[] { imageObject3D })); + } + else + { + parent.Children.Modify(list => + { + list.Remove(this); + list.Add(imageObject3D); + }); + } + } + } - parent.Invalidate(new InvalidateArgs(this, InvalidateType.Children)); - } - else - { - if (ProOnly) - { - // just delete it - var parent = this.Parent; + parent.Invalidate(new InvalidateArgs(this, InvalidateType.Children)); + } + else + { + if (ProOnly) + { + // just delete it + var parent = this.Parent; - using (RebuildLock()) - { - if (undoBuffer != null) - { - // and replace us with nothing - undoBuffer.AddAndDo(new ReplaceCommand(new[] { this }, new List(), false)); - } - else - { - parent.Children.Modify(list => - { - list.Remove(this); - }); - } - } + using (RebuildLock()) + { + if (undoBuffer != null) + { + // and replace us with nothing + undoBuffer.AddAndDo(new ReplaceCommand(new[] { this }, new List(), false)); + } + else + { + parent.Children.Modify(list => + { + list.Remove(this); + }); + } + } - parent.Invalidate(new InvalidateArgs(this, InvalidateType.Children)); - } - else - { - // remove the component and leave the inside parts - base.Cancel(undoBuffer); - } - } - } + parent.Invalidate(new InvalidateArgs(this, InvalidateType.Children)); + } + else + { + // remove the component and leave the inside parts + base.Cancel(undoBuffer); + } + } + } public void AddRightClickMenuItemsItems(PopupMenu popupMenu, ThemeConfig theme) { @@ -303,20 +312,20 @@ namespace MatterHackers.MatterControl.DesignTools string componentID = this.ComponentID; - var helpItem = popupMenu.CreateMenuItem("Help".Localize()); - var helpArticlesByID = ApplicationController.Instance.HelpArticlesByID; - helpItem.Enabled = !string.IsNullOrEmpty(componentID) && helpArticlesByID.ContainsKey(componentID); - helpItem.Click += (s, e) => - { - var helpTab = ApplicationController.Instance.ActivateHelpTab("Docs"); - if (helpTab.TabContent is HelpTreePanel helpTreePanel) - { - if (helpArticlesByID.TryGetValue(componentID, out HelpArticle helpArticle)) - { - helpTreePanel.ActiveNodePath = componentID; - } - } - }; - } + var helpItem = popupMenu.CreateMenuItem("Help".Localize()); + var helpArticlesByID = ApplicationController.Instance.HelpArticlesByID; + helpItem.Enabled = !string.IsNullOrEmpty(componentID) && helpArticlesByID.ContainsKey(componentID); + helpItem.Click += (s, e) => + { + var helpTab = ApplicationController.Instance.ActivateHelpTab("Docs"); + if (helpTab.TabContent is HelpTreePanel helpTreePanel) + { + if (helpArticlesByID.TryGetValue(componentID, out HelpArticle helpArticle)) + { + helpTreePanel.ActiveNodePath = componentID; + } + } + }; + } } } \ No newline at end of file diff --git a/MatterControlLib/DesignTools/Primitives/HalfCylinderObject3D.cs b/MatterControlLib/DesignTools/Primitives/HalfCylinderObject3D.cs index 8ed3d5ceb..86fb3bc5f 100644 --- a/MatterControlLib/DesignTools/Primitives/HalfCylinderObject3D.cs +++ b/MatterControlLib/DesignTools/Primitives/HalfCylinderObject3D.cs @@ -29,7 +29,6 @@ either expressed or implied, of the FreeBSD Project. using System; using System.Threading.Tasks; -using MatterHackers.Agg; using MatterHackers.Agg.VertexSource; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; diff --git a/MatterControlLib/PartPreviewWindow/Object3DTreeBuilder.cs b/MatterControlLib/PartPreviewWindow/Object3DTreeBuilder.cs index 002fcd123..b3f0e32ef 100644 --- a/MatterControlLib/PartPreviewWindow/Object3DTreeBuilder.cs +++ b/MatterControlLib/PartPreviewWindow/Object3DTreeBuilder.cs @@ -1,5 +1,5 @@ /* -Copyright (c) 2018, Lars Brubaker, John Lewin +Copyright (c) 2023, Lars Brubaker, John Lewin All rights reserved. Redistribution and use in source and binary forms, with or without @@ -27,225 +27,222 @@ 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 System.Linq; -using System.Threading.Tasks; using MatterHackers.Agg; -using MatterHackers.Agg.Image; using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; -using MatterHackers.MatterControl.CustomWidgets; using MatterHackers.MatterControl.DesignTools; using MatterHackers.MatterControl.DesignTools.Operations; using MatterHackers.MatterControl.Library; using MatterHackers.MatterControl.PartPreviewWindow.View3D; +using System.Collections.Generic; +using System.Linq; namespace MatterHackers.MatterControl.PartPreviewWindow { - public static class Object3DTreeBuilder - { - public static TreeNode BuildTree(IObject3D rootItem, Dictionary keyValues, ThemeConfig theme) - { - return AddTree(BuildItemView(rootItem), null, keyValues, theme); - } + public static class Object3DTreeBuilder + { + public static TreeNode BuildTree(IObject3D rootItem, Dictionary keyValues, ThemeConfig theme) + { + return AddTree(BuildItemView(rootItem), null, keyValues, theme); + } - private static TreeNode AddTree(ObjectView objectView, TreeNode parentTreeNode, Dictionary keyValues, ThemeConfig theme) - { - // Suppress MeshWrapper and OperationSource nodes in tree - bool shouldCollapseToParent = objectView.Source is ModifiedMeshObject3D || objectView.Source is OperationSourceObject3D; - TreeNode contextNode; - if (shouldCollapseToParent - && parentTreeNode != null - && !keyValues.ContainsKey(objectView.Source)) - { - contextNode = parentTreeNode; - } - else - { - var itemName = GetName(objectView); - contextNode = AddItem(objectView.Source, itemName, parentTreeNode, keyValues, theme); - } + private static TreeNode AddTree(ObjectView objectView, TreeNode parentTreeNode, Dictionary keyValues, ThemeConfig theme) + { + // Suppress MeshWrapper and OperationSource nodes in tree + bool shouldCollapseToParent = objectView.Source is ModifiedMeshObject3D || objectView.Source is OperationSourceObject3D; + TreeNode contextNode; - using (contextNode.LayoutLock()) - { - var componentObject3D = objectView.Source as ComponentObject3D; - var hideChildren = objectView.Source.GetType().GetCustomAttributes(typeof(HideChildrenFromTreeViewAttribute), true).Any(); + if (shouldCollapseToParent + && parentTreeNode != null + && !keyValues.ContainsKey(objectView.Source)) + { + contextNode = parentTreeNode; + } + else + { + var itemName = GetName(objectView); + contextNode = AddItem(objectView.Source, itemName, parentTreeNode, keyValues, theme); + } - if ((componentObject3D?.Finalized == false - || !hideChildren) - && objectView.Children?.Any() == true) - { - var orderChildrenByIndex = objectView.Source.GetType().GetCustomAttributes(typeof(OrderChildrenByIndexAttribute), true).Any(); - IEnumerable children = objectView.Children; + using (contextNode.LayoutLock()) + { + var componentObject3D = objectView.Source as IComponentObject3D; + var hideChildren = objectView.Source.GetType().GetCustomAttributes(typeof(HideChildrenFromTreeViewAttribute), true).Any(); - if (!orderChildrenByIndex) - { - children = objectView.Children.OrderBy(i => i.Name); - } - foreach (var child in children) - { - if (child != null - && !child.GetType().GetCustomAttributes(typeof(HideFromTreeViewAttribute), true).Any()) - { - AddTree(BuildItemView(child), contextNode, keyValues, theme); - } - } - } - } + if ((componentObject3D?.Finalized == false + || !hideChildren) + && objectView.Children?.Any() == true) + { + var orderChildrenByIndex = objectView.Source.GetType().GetCustomAttributes(typeof(OrderChildrenByIndexAttribute), true).Any(); + IEnumerable children = objectView.Children; - return contextNode; - } + if (!orderChildrenByIndex) + { + children = objectView.Children.OrderBy(i => i.Name); + } + foreach (var child in children) + { + if (child != null + && !child.GetType().GetCustomAttributes(typeof(HideFromTreeViewAttribute), true).Any()) + { + AddTree(BuildItemView(child), contextNode, keyValues, theme); + } + } + } + } - private static TreeNode AddItem(IObject3D item, string itemName, TreeNode parentNode, Dictionary keyValues, ThemeConfig theme) - { - if (item is InsertionGroupObject3D insertionGroup) - { - return new TreeNode(theme) - { - Text = "Loading".Localize(), - Tag = item, - TextColor = theme.TextColor, - PointSize = theme.DefaultFontSize, - }; - } + return contextNode; + } - var node = new TreeNode(theme) - { - Text = itemName, - Tag = item, - TextColor = theme.TextColor, - PointSize = theme.DefaultFontSize, - }; + private static TreeNode AddItem(IObject3D item, string itemName, TreeNode parentNode, Dictionary keyValues, ThemeConfig theme) + { + if (item is InsertionGroupObject3D insertionGroup) + { + return new TreeNode(theme) + { + Text = "Loading".Localize(), + Tag = item, + TextColor = theme.TextColor, + PointSize = theme.DefaultFontSize, + }; + } - if (!keyValues.ContainsKey(item)) - { - keyValues.Add(item, node); - } + var node = new TreeNode(theme) + { + Text = itemName, + Tag = item, + TextColor = theme.TextColor, + PointSize = theme.DefaultFontSize, + }; - // Check for operation resulting in the given type - var image = SceneOperations.GetIcon(item.GetType(), theme); + if (!keyValues.ContainsKey(item)) + { + keyValues.Add(item, node); + } - if (image != null) - { - node.Image = image; - } - else - { - node.Image = ApplicationController.Instance.Thumbnails.DefaultThumbnail(); + // Check for operation resulting in the given type + var image = SceneOperations.GetIcon(item.GetType(), theme); - node.Load += (s, e) => - { - string contentID = item.MeshRenderId().ToString(); - if (item is IStaticThumbnail staticThumbnail) - { - contentID = $"MatterHackers/ItemGenerator/{staticThumbnail.ThumbnailName}".GetLongHashCode().ToString(); - } + if (image != null) + { + node.Image = image; + } + else + { + node.Image = ApplicationController.Instance.Thumbnails.DefaultThumbnail(); - var thumbnail = ApplicationController.Instance.Thumbnails.LoadCachedImage(contentID, 16, 16); + node.Load += (s, e) => + { + string contentID = item.MeshRenderId().ToString(); + if (item is IStaticThumbnail staticThumbnail) + { + contentID = $"MatterHackers/ItemGenerator/{staticThumbnail.ThumbnailName}".GetLongHashCode().ToString(); + } - node.Image = thumbnail ?? ApplicationController.Instance.Thumbnails.DefaultThumbnail(); - }; - } + var thumbnail = ApplicationController.Instance.Thumbnails.LoadCachedImage(contentID, 16, 16); - if (parentNode != null) - { - parentNode.Nodes.Add(node); - if (parentNode.Tag is IObject3D object3D) - { - parentNode.Expanded = object3D.Expanded; - } - } + node.Image = thumbnail ?? ApplicationController.Instance.Thumbnails.DefaultThumbnail(); + }; + } - node.ExpandedChanged += (s, e) => - { - if (item is Object3D object3D) - { - object3D.Expanded = node.Expanded; - } - }; + if (parentNode != null) + { + parentNode.Nodes.Add(node); + if (parentNode.Tag is IObject3D object3D) + { + parentNode.Expanded = object3D.Expanded; + } + } - return node; - } + node.ExpandedChanged += (s, e) => + { + if (item is Object3D object3D) + { + object3D.Expanded = node.Expanded; + } + }; - private static string GetName(ObjectView item) - { - return !string.IsNullOrEmpty(item.Name) ? $"{item.Name}" : $"{item.GetType().Name}"; - } + return node; + } - private static ObjectView BuildItemView(IObject3D item) - { - string GetArrayName(ArrayObject3D arrayItem) - { - if (string.IsNullOrWhiteSpace(item.Name) - && arrayItem?.SourceContainer?.Children?.Any() == true) - { - var childName = arrayItem.SourceContainer.Children.First().Name; - if (childName.Length > 20) - { - childName = childName.Substring(0, 20) + "..."; - } + private static string GetName(ObjectView item) + { + return !string.IsNullOrEmpty(item.Name) ? $"{item.Name}" : $"{item.GetType().Name}"; + } - return $"{childName} - x{arrayItem.Count}"; - } + private static ObjectView BuildItemView(IObject3D item) + { + string GetArrayName(ArrayObject3D arrayItem) + { + if (string.IsNullOrWhiteSpace(item.Name) + && arrayItem?.SourceContainer?.Children?.Any() == true) + { + var childName = arrayItem.SourceContainer.Children.First().Name; + if (childName.Length > 20) + { + childName = childName.Substring(0, 20) + "..."; + } - return arrayItem.Name; - } + return $"{childName} - x{arrayItem.Count}"; + } - if (item is ArrayObject3D array) - { - return new ObjectView() - { - Children = item.Children.OfType().ToList(), - Name = GetArrayName(array), - Source = item - }; - } - else - { - switch (item) - { - case TransformWrapperObject3D transformWrapperObject3D: - return new ObjectView() - { - Children = transformWrapperObject3D.UntransformedChildren, - Name = item.Name, - Source = item - }; + return arrayItem.Name; + } - case OperationSourceContainerObject3D operationSourceContainerObject3D: - return new ObjectView() - { - Children = item.Children.OfType().ToList(), - Name = operationSourceContainerObject3D.Name, - Source = item - }; + if (item is ArrayObject3D array) + { + return new ObjectView() + { + Children = item.Children.OfType().ToList(), + Name = GetArrayName(array), + Source = item + }; + } + else + { + switch (item) + { + case TransformWrapperObject3D transformWrapperObject3D: + return new ObjectView() + { + Children = transformWrapperObject3D.UntransformedChildren, + Name = item.Name, + Source = item + }; - default: - return new ObjectView(item); - } - } - } + case OperationSourceContainerObject3D operationSourceContainerObject3D: + return new ObjectView() + { + Children = item.Children.OfType().ToList(), + Name = operationSourceContainerObject3D.Name, + Source = item + }; - private class ObjectView - { - public ObjectView() - { - } + default: + return new ObjectView(item); + } + } + } - public ObjectView(IObject3D source) - { - this.Source = source; - this.Children = this.Source.Children; - this.Name = this.Source.Name; - } + private class ObjectView + { + public ObjectView() + { + } - public IEnumerable Children { get; set; } + public ObjectView(IObject3D source) + { + this.Source = source; + this.Children = this.Source.Children; + this.Name = this.Source.Name; + } - public string Name { get; set; } + public IEnumerable Children { get; set; } - public IObject3D Source { get; set; } - } - } + public string Name { get; set; } + + public IObject3D Source { get; set; } + } + } } \ No newline at end of file diff --git a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs index 569da8a1d..04a194bb1 100644 --- a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs +++ b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs @@ -304,7 +304,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow var rows = new SafeList(); // put in the normal editor - if (selectedItem is ComponentObject3D componentObject + if (selectedItem is IComponentObject3D componentObject && componentObject.Finalized) { AddComponentEditor(selectedItem, undoBuffer, rows, componentObject, ref tabIndex); @@ -538,7 +538,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } } - private void AddComponentEditor(IObject3D selectedItem, UndoBuffer undoBuffer, SafeList rows, ComponentObject3D componentObject, ref int tabIndex) + private void AddComponentEditor(IObject3D selectedItem, UndoBuffer undoBuffer, SafeList rows, IComponentObject3D componentObject, ref int tabIndex) { var context = new EditorContext(); PropertyEditor.AddUnlockLinkIfRequired(selectedItem, editorPanel, theme); @@ -600,7 +600,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } } - private void AddSheetCellEditor(UndoBuffer undoBuffer, ComponentObject3D componentObject, List editorList, int editorIndex) + private void AddSheetCellEditor(UndoBuffer undoBuffer, IComponentObject3D componentObject, List editorList, int editorIndex) { var firtSheet = componentObject.Descendants().FirstOrDefault(); if (firtSheet != null) @@ -633,7 +633,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow editorList[editorIndex] = "!" + cellId + "," + oldValue; var expression = new StringOrExpression(oldValue); cell.Expression = expression.Value(componentObject).ToString(); - componentObject.Invalidate(InvalidateType.SheetUpdated); + (componentObject as Object3D).Invalidate(InvalidateType.SheetUpdated); doOrUndoing = false; }, () => @@ -642,7 +642,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow editorList[editorIndex] = "!" + cellId + "," + newValue; var expression = new StringOrExpression(newValue); cell.Expression = expression.Value(componentObject).ToString(); - componentObject.Invalidate(InvalidateType.SheetUpdated); + (componentObject as Object3D).Invalidate(InvalidateType.SheetUpdated); doOrUndoing = false; })); } diff --git a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs index f78796bc6..949ed8406 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs @@ -30,7 +30,6 @@ either expressed or implied, of the FreeBSD Project. using AngleSharp.Dom; using AngleSharp.Html.Parser; -using g3; using MatterHackers.Agg; using MatterHackers.Agg.Platform; using MatterHackers.Agg.UI; diff --git a/StaticData/Translations/Master.txt b/StaticData/Translations/Master.txt index a782f5881..649ae3665 100644 --- a/StaticData/Translations/Master.txt +++ b/StaticData/Translations/Master.txt @@ -3727,6 +3727,9 @@ Translated:Pinch English:Pinch Slices Translated:Pinch Slices +English:Pinch Type Value +Translated:Pinch Type Value + English:Pipe Works Translated:Pipe Works diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index 9545c19b1..35f4dca6e 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit 9545c19b13d294e47d87ab3b9ae67366827072b3 +Subproject commit 35f4dca6e1635d328eaae0df6ab23bc8a300bad2