From 8bd06fe3da873a0b08f6abf3eb892bc81c662edf Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Thu, 6 May 2021 16:57:35 -0700 Subject: [PATCH] Made a new scale transform control that has width depth height --- .../ApplicationView/SceneOperations.cs | 4 +- .../Braille/BrailleCardObject3D.cs | 2 +- .../DesignApps/Parts/ImageCoinObject3D.cs | 2 +- .../Parts/RibbonWithNameObject3D.cs | 2 +- .../ScaleControls/ScaleController.cs | 13 +- .../DesignTools/Operations/ScaleObject3D_2.cs | 219 ++++++++---------- .../MatterControl/InteractiveSceneTests.cs | 9 +- 7 files changed, 117 insertions(+), 134 deletions(-) diff --git a/MatterControlLib/ApplicationView/SceneOperations.cs b/MatterControlLib/ApplicationView/SceneOperations.cs index ad42f6118..e0c4f34e1 100644 --- a/MatterControlLib/ApplicationView/SceneOperations.cs +++ b/MatterControlLib/ApplicationView/SceneOperations.cs @@ -591,11 +591,11 @@ namespace MatterHackers.MatterControl return new SceneOperation("Scale") { OperationType = typeof(IObject3D), - ResultType = typeof(ScaleObject3D), + ResultType = typeof(ScaleObject3D_2), TitleResolver = () => "Scale".Localize(), Action = (sceneContext) => { - new ScaleObject3D().WrapSelectedItemAndSelect(sceneContext.Scene); + new ScaleObject3D_2().WrapSelectedItemAndSelect(sceneContext.Scene); }, Icon = (invertIcon) => StaticData.Instance.LoadIcon("scale_32x32.png", 16, 16, invertIcon).SetPreMultiply(), HelpTextResolver = () => "*At least 1 part must be selected*".Localize(), diff --git a/MatterControlLib/DesignTools/Braille/BrailleCardObject3D.cs b/MatterControlLib/DesignTools/Braille/BrailleCardObject3D.cs index 243d08540..03e985e9e 100644 --- a/MatterControlLib/DesignTools/Braille/BrailleCardObject3D.cs +++ b/MatterControlLib/DesignTools/Braille/BrailleCardObject3D.cs @@ -104,7 +104,7 @@ namespace MatterHackers.MatterControl.DesignTools var scaleRatio = Math.Max(letterObject.XSize() / 17, letterObject.ZSize() / 17); if (scaleRatio > 1) { - letterObject = new ScaleObject3D(letterObject, 1.0 / scaleRatio, 1, 1.0 / scaleRatio); + letterObject = new ScaleObject3D_2(letterObject, 1.0 / scaleRatio, 1, 1.0 / scaleRatio); } letterObject = new AlignObject3D(letterObject, FaceAlign.Bottom | FaceAlign.Front, brailleLetter, FaceAlign.Top | FaceAlign.Front, 0, 0, 3.5); letterObject = new SetCenterObject3D(letterObject, brailleLetter.GetCenter(), true, false, false); diff --git a/MatterControlLib/DesignTools/EditorTools/DesignApps/Parts/ImageCoinObject3D.cs b/MatterControlLib/DesignTools/EditorTools/DesignApps/Parts/ImageCoinObject3D.cs index 55a416cd7..4331e4e42 100644 --- a/MatterControlLib/DesignTools/EditorTools/DesignApps/Parts/ImageCoinObject3D.cs +++ b/MatterControlLib/DesignTools/EditorTools/DesignApps/Parts/ImageCoinObject3D.cs @@ -188,7 +188,7 @@ namespace MatterHackers.MatterControl.DesignTools IObject3D extrusionObject = imageObject; var loadingScale = 32 / extrusionObject.XSize(); - extrusionObject = new ScaleObject3D(extrusionObject, loadingScale, loadingScale, 1 / extrusionObject.ZSize()); + extrusionObject = new ScaleObject3D_2(extrusionObject, loadingScale, loadingScale, 1 / extrusionObject.ZSize()); extrusionObject = PlaceOnBase(logoBase, extrusionObject); this.Children.Add(coinBlank); diff --git a/MatterControlLib/DesignTools/EditorTools/DesignApps/Parts/RibbonWithNameObject3D.cs b/MatterControlLib/DesignTools/EditorTools/DesignApps/Parts/RibbonWithNameObject3D.cs index 52163ea1c..76056f7f3 100644 --- a/MatterControlLib/DesignTools/EditorTools/DesignApps/Parts/RibbonWithNameObject3D.cs +++ b/MatterControlLib/DesignTools/EditorTools/DesignApps/Parts/RibbonWithNameObject3D.cs @@ -68,7 +68,7 @@ namespace MatterHackers.MatterControl.DesignTools var textArea = new Vector2(25, 6); double scale = Math.Min(textArea.X / textBounds.XSize, textArea.Y / textBounds.YSize); - nameMesh = new ScaleObject3D(nameMesh, scale, scale, 2 / textBounds.ZSize); + nameMesh = new ScaleObject3D_2(nameMesh, scale, scale, 2 / textBounds.ZSize); nameMesh = new AlignObject3D(nameMesh, FaceAlign.Bottom | FaceAlign.Front, cancerRibbonStl, FaceAlign.Top | FaceAlign.Front, 0, 0, -1); nameMesh = new SetCenterObject3D(nameMesh, cancerRibbonStl.GetCenter(), true, false, false); diff --git a/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleController.cs b/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleController.cs index 74327268c..515a5eb57 100644 --- a/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleController.cs +++ b/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleController.cs @@ -30,6 +30,7 @@ either expressed or implied, of the FreeBSD Project. using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.MatterControl.DesignTools; +using MatterHackers.MatterControl.DesignTools.Operations; using MatterHackers.MeshVisualizer; using MatterHackers.VectorMath; using System; @@ -132,7 +133,8 @@ namespace MatterHackers.Plugins.EditorTools { FinalState = new ScaleStates(InitialState); FinalState.Depth = newDepth; - if (context.GuiSurface.ModifierKeys == Keys.Shift) + if (context.GuiSurface.ModifierKeys == Keys.Shift + || (selectedItem is IScaleLocker scaleLocker && scaleLocker.ScaleLocked)) { ScaleProportional(newDepth / InitialState.Depth); } @@ -156,7 +158,8 @@ namespace MatterHackers.Plugins.EditorTools { FinalState = new ScaleStates(InitialState); FinalState.Height = newHeight; - if (context.GuiSurface.ModifierKeys == Keys.Shift) + if (context.GuiSurface.ModifierKeys == Keys.Shift + || (selectedItem is IScaleLocker scaleLocker && scaleLocker.ScaleLocked)) { ScaleProportional(newHeight / InitialState.Height); } @@ -168,7 +171,8 @@ namespace MatterHackers.Plugins.EditorTools { FinalState = new ScaleStates(InitialState); FinalState.Width = newWidth; - if (context.GuiSurface.ModifierKeys == Keys.Shift) + if (context.GuiSurface.ModifierKeys == Keys.Shift + || (selectedItem is IScaleLocker scaleLocker && scaleLocker.ScaleLocked)) { ScaleProportional(newWidth / InitialState.Width); } @@ -207,7 +211,8 @@ namespace MatterHackers.Plugins.EditorTools FinalState = new ScaleStates(InitialState); FinalState.Width = newWidth; FinalState.Depth = newDepth; - if (context.GuiSurface.ModifierKeys == Keys.Shift) + if (context.GuiSurface.ModifierKeys == Keys.Shift + || (selectedItem is IScaleLocker scaleLocker && scaleLocker.ScaleLocked)) { ScaleProportional(newWidth / InitialState.Width); } diff --git a/MatterControlLib/DesignTools/Operations/ScaleObject3D_2.cs b/MatterControlLib/DesignTools/Operations/ScaleObject3D_2.cs index 7064ace8f..50db978ba 100644 --- a/MatterControlLib/DesignTools/Operations/ScaleObject3D_2.cs +++ b/MatterControlLib/DesignTools/Operations/ScaleObject3D_2.cs @@ -42,9 +42,14 @@ using Newtonsoft.Json; namespace MatterHackers.MatterControl.DesignTools.Operations { - public class ScaleObject3D_2 : TransformWrapperObject3D, IObjectWithHeight, IObjectWithWidthAndDepth, ISelectedEditorDraw, IPropertyGridModifier + public interface IScaleLocker { - public enum ScaleType + bool ScaleLocked { get; } + } + + public class ScaleObject3D_2 : TransformWrapperObject3D, IObjectWithHeight, IObjectWithWidthAndDepth, IPropertyGridModifier, IScaleLocker + { + public enum ScaleTypes { Custom, Inches_to_mm, @@ -98,102 +103,126 @@ namespace MatterHackers.MatterControl.DesignTools.Operations // this is the size we actually serialize public Vector3 ScaleRatio = Vector3.One; - public ScaleType Operation { get; set; } = ScaleType.Custom; + public ScaleTypes ScaleType { get; set; } = ScaleTypes.Custom; + public enum ScaleMethods + { + Direct, + Percentage, + } + + [EnumDisplay(Mode = EnumDisplayAttribute.PresentationMode.Tabs)] + public ScaleMethods ScaleMethod { get; set; } = ScaleMethods.Direct; + + [Description("Ensure that the part maintains its proportions.")] + public bool LockProportions { get; set; } = true; + + + [MaxDecimalPlaces(3)] [JsonIgnore] public double Width { get { - if (UsePercentage) - { - return ScaleRatio.X * 100; - } - return ScaleRatio.X * UntransformedChildren.GetAxisAlignedBoundingBox().XSize; } set { - if (UsePercentage) - { - ScaleRatio.X = value / 100; - } - else - { - ScaleRatio.X = value / UntransformedChildren.GetAxisAlignedBoundingBox().XSize; - } + ScaleRatio.X = value / UntransformedChildren.GetAxisAlignedBoundingBox().XSize; + FixIfLockedProportions(0); } } + [MaxDecimalPlaces(3)] [JsonIgnore] public double Depth { get { - if (UsePercentage) - { - return ScaleRatio.Y * 100; - } - return ScaleRatio.Y * UntransformedChildren.GetAxisAlignedBoundingBox().YSize; } set { - if (UsePercentage) - { - ScaleRatio.Y = value / 100; - } - else - { - ScaleRatio.Y = value / UntransformedChildren.GetAxisAlignedBoundingBox().YSize; - } + ScaleRatio.Y = value / UntransformedChildren.GetAxisAlignedBoundingBox().YSize; + FixIfLockedProportions(1); } } + [MaxDecimalPlaces(3)] [JsonIgnore] public double Height { get { - if (UsePercentage) - { - return ScaleRatio.Z * 100; - } - return ScaleRatio.Z * UntransformedChildren.GetAxisAlignedBoundingBox().ZSize; } set { - if (UsePercentage) - { - ScaleRatio.Z = value / 100; - } - else - { - ScaleRatio.Z = value / UntransformedChildren.GetAxisAlignedBoundingBox().ZSize; - } + ScaleRatio.Z = value / UntransformedChildren.GetAxisAlignedBoundingBox().ZSize; + FixIfLockedProportions(2); } } - [Description("Ensure that the part maintains its proportions.")] - [DisplayName("Maintain Proportions")] - public bool MaitainProportions { get; set; } = true; - - [Description("Toggle between specifying the size or the percentage to scale.")] - public bool UsePercentage { get; set; } - - [Description("This is the position to perform the scale about.")] - public Vector3 ScaleAbout { get; set; } - - public void DrawEditor(Object3DControlsLayer layer, List transparentMeshes, DrawEventArgs e) + [MaxDecimalPlaces(2)] + [JsonIgnore] + public double WidthPercent { - if (layer.Scene.SelectedItem != null - && layer.Scene.SelectedItem.DescendantsAndSelf().Where((i) => i == this).Any()) + get { - layer.World.RenderAxis(ScaleAbout, this.WorldMatrix(), 30, 1); + return ScaleRatio.X * 100; + } + + set + { + ScaleRatio.X = value / 100; + FixIfLockedProportions(0); + } + } + + [MaxDecimalPlaces(2)] + [JsonIgnore] + public double DepthPercent + { + get + { + return ScaleRatio.Y * 100; + } + + set + { + ScaleRatio.Y = value / 100; + FixIfLockedProportions(1); + } + } + + [MaxDecimalPlaces(2)] + [JsonIgnore] + public double HeightPercent + { + get + { + return ScaleRatio.Z * 100; + } + + set + { + ScaleRatio.Z = value / 100; + FixIfLockedProportions(2); + } + } + + public bool ScaleLocked => LockProportions; + + private void FixIfLockedProportions(int index) + { + if (LockProportions) + { + ScaleRatio[(index + 1) % 3] = ScaleRatio[index]; + ScaleRatio[(index + 2) % 3] = ScaleRatio[index]; + Invalidate(new InvalidateArgs(null, InvalidateType.DisplayValues)); } } @@ -228,9 +257,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations { // set the matrix for the transform object ItemWithTransform.Matrix = Matrix4X4.Identity; - ItemWithTransform.Matrix *= Matrix4X4.CreateTranslation(-ScaleAbout); ItemWithTransform.Matrix *= Matrix4X4.CreateScale(ScaleRatio); - ItemWithTransform.Matrix *= Matrix4X4.CreateTranslation(ScaleAbout); } } @@ -241,29 +268,30 @@ namespace MatterHackers.MatterControl.DesignTools.Operations public void UpdateControls(PublicPropertyChange change) { - change.SetRowVisible(nameof(Width), () => Operation == ScaleType.Custom); - change.SetRowVisible(nameof(Depth), () => Operation == ScaleType.Custom); - change.SetRowVisible(nameof(Height), () => Operation == ScaleType.Custom); - change.SetRowVisible(nameof(MaitainProportions), () => Operation == ScaleType.Custom); - change.SetRowVisible(nameof(UsePercentage), () => Operation == ScaleType.Custom); - change.SetRowVisible(nameof(ScaleAbout), () => Operation == ScaleType.Custom); + change.SetRowVisible(nameof(Width), () => ScaleType == ScaleTypes.Custom && ScaleMethod == ScaleMethods.Direct); + change.SetRowVisible(nameof(Depth), () => ScaleType == ScaleTypes.Custom && ScaleMethod == ScaleMethods.Direct); + change.SetRowVisible(nameof(Height), () => ScaleType == ScaleTypes.Custom && ScaleMethod == ScaleMethods.Direct); + change.SetRowVisible(nameof(WidthPercent), () => ScaleType == ScaleTypes.Custom && ScaleMethod == ScaleMethods.Percentage); + change.SetRowVisible(nameof(DepthPercent), () => ScaleType == ScaleTypes.Custom && ScaleMethod == ScaleMethods.Percentage); + change.SetRowVisible(nameof(HeightPercent), () => ScaleType == ScaleTypes.Custom && ScaleMethod == ScaleMethods.Percentage); + change.SetRowVisible(nameof(LockProportions), () => ScaleType == ScaleTypes.Custom); - if (change.Changed == nameof(Operation)) + if (change.Changed == nameof(ScaleType)) { // recalculate the scaling double scale = 1; - switch (Operation) + switch (ScaleType) { - case ScaleType.Inches_to_mm: + case ScaleTypes.Inches_to_mm: scale = 25.4; break; - case ScaleType.mm_to_Inches: + case ScaleTypes.mm_to_Inches: scale = .0393; break; - case ScaleType.mm_to_cm: + case ScaleTypes.mm_to_cm: scale = .1; break; - case ScaleType.cm_to_mm: + case ScaleTypes.cm_to_mm: scale = 10; break; } @@ -271,14 +299,9 @@ namespace MatterHackers.MatterControl.DesignTools.Operations ScaleRatio = new Vector3(scale, scale, scale); Rebuild(); } - else if (change.Changed == nameof(UsePercentage)) + else if (change.Changed == nameof(LockProportions)) { - // make sure we update the controls on screen to reflect the different data type - Invalidate(new InvalidateArgs(null, InvalidateType.DisplayValues)); - } - else if (change.Changed == nameof(MaitainProportions)) - { - if (MaitainProportions) + if (LockProportions) { var maxScale = Math.Max(ScaleRatio.X, Math.Max(ScaleRatio.Y, ScaleRatio.Z)); ScaleRatio = new Vector3(maxScale, maxScale, maxScale); @@ -287,48 +310,6 @@ namespace MatterHackers.MatterControl.DesignTools.Operations Invalidate(new InvalidateArgs(null, InvalidateType.DisplayValues)); } } - else if (change.Changed == nameof(Width)) - { - if (MaitainProportions) - { - // scale y and z to match - ScaleRatio[1] = ScaleRatio[0]; - ScaleRatio[2] = ScaleRatio[0]; - Rebuild(); - // and invalidate the other properties - Invalidate(new InvalidateArgs(this, InvalidateType.Properties)); - // then update the display values - Invalidate(new InvalidateArgs(null, InvalidateType.DisplayValues)); - } - } - else if (change.Changed == nameof(Depth)) - { - if (MaitainProportions) - { - // scale y and z to match - ScaleRatio[0] = ScaleRatio[1]; - ScaleRatio[2] = ScaleRatio[1]; - Rebuild(); - // and invalidate the other properties - Invalidate(new InvalidateArgs(this, InvalidateType.Properties)); - // then update the display values - Invalidate(new InvalidateArgs(null, InvalidateType.DisplayValues)); - } - } - else if (change.Changed == nameof(Height)) - { - if (MaitainProportions) - { - // scale y and z to match - ScaleRatio[0] = ScaleRatio[2]; - ScaleRatio[1] = ScaleRatio[2]; - Rebuild(); - // and invalidate the other properties - Invalidate(new InvalidateArgs(this, InvalidateType.Properties)); - // then update the display values - Invalidate(new InvalidateArgs(null, InvalidateType.DisplayValues)); - } - } } } } \ No newline at end of file diff --git a/Tests/MatterControl.Tests/MatterControl/InteractiveSceneTests.cs b/Tests/MatterControl.Tests/MatterControl/InteractiveSceneTests.cs index 08b468767..857bae866 100644 --- a/Tests/MatterControl.Tests/MatterControl/InteractiveSceneTests.cs +++ b/Tests/MatterControl.Tests/MatterControl/InteractiveSceneTests.cs @@ -417,11 +417,10 @@ namespace MatterControl.Tests.MatterControl var undoBuffer = new UndoBuffer(); // add a scale to it (that is not scaled) - var scaleObject = new ScaleObject3D(); + var scaleObject = new ScaleObject3D_2(); scaleObject.WrapItems(new IObject3D[] { cube }, undoBuffer); // ensure that the object did not move - Assert.IsTrue(scaleObject.ScaleAbout.Equals(Vector3.Zero), "The objects have been moved to be scalling about 0."); Assert.AreEqual(4, root.DescendantsAndSelf().Count()); var postScaleAabb = root.GetAxisAlignedBoundingBox(); @@ -441,10 +440,9 @@ namespace MatterControl.Tests.MatterControl var preScaleAabb = root.GetAxisAlignedBoundingBox(); // add a scale to it (that is not scaled) - var scaleObject = new ScaleObject3D(cube); + var scaleObject = new ScaleObject3D_2(cube); // ensure that the object did not move - Assert.IsTrue(scaleObject.ScaleAbout.Equals(Vector3.Zero), "The objects have been moved to be scalling about 0."); Assert.AreEqual(4, root.DescendantsAndSelf().Count()); var postScaleAabb = root.GetAxisAlignedBoundingBox(); @@ -467,10 +465,9 @@ namespace MatterControl.Tests.MatterControl var preScaleAabb = root.GetAxisAlignedBoundingBox(); // add a scale to it (that is not scaled) - var scaleObject = new ScaleObject3D(cube); + var scaleObject = new ScaleObject3D_2(cube); // ensure that the object did not move - Assert.IsTrue(scaleObject.ScaleAbout.Equals(Vector3.Zero), "The objects have been moved to be scalling about 0."); Assert.AreEqual(4, root.DescendantsAndSelf().Count()); var postScaleAabb = root.GetAxisAlignedBoundingBox();