Made fit to bounds scale with new inline controls

This commit is contained in:
Lars Brubaker 2021-05-13 12:19:42 -07:00
parent 4500f0fa8b
commit 4ef7ecfeb7
13 changed files with 758 additions and 55 deletions

View file

@ -591,11 +591,11 @@ namespace MatterHackers.MatterControl
return new SceneOperation("Scale")
{
OperationType = typeof(IObject3D),
ResultType = typeof(ScaleObject3D_2),
ResultType = typeof(ScaleObject3D_3),
TitleResolver = () => "Scale".Localize(),
Action = (sceneContext) =>
{
new ScaleObject3D_2().WrapSelectedItemAndSelect(sceneContext.Scene);
new ScaleObject3D_3().WrapSelectedItemAndSelect(sceneContext.Scene);
},
Icon = (invertIcon) => StaticData.Instance.LoadIcon("scale_32x32.png", 16, 16, invertIcon).SetPreMultiply(),
HelpTextResolver = () => "*At least 1 part must be selected*".Localize(),
@ -1014,7 +1014,7 @@ namespace MatterHackers.MatterControl
return new SceneOperation("Fit to Bounds")
{
OperationType = typeof(IObject3D),
ResultType = typeof(FitToBoundsObject3D_2),
ResultType = typeof(FitToBoundsObject3D_3),
TitleResolver = () => "Fit to Bounds".Localize(),
Action = async (sceneContext) =>
{
@ -1022,7 +1022,7 @@ namespace MatterHackers.MatterControl
var selectedItem = scene.SelectedItem;
using (new SelectionMaintainer(scene))
{
var fit = await FitToBoundsObject3D_2.Create(selectedItem.Clone());
var fit = await FitToBoundsObject3D_3.Create(selectedItem.Clone());
fit.MakeNameNonColliding();
scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { selectedItem }, new[] { fit }));

View file

@ -104,7 +104,7 @@ namespace MatterHackers.MatterControl.DesignTools
var scaleRatio = Math.Max(letterObject.XSize() / 17, letterObject.ZSize() / 17);
if (scaleRatio > 1)
{
letterObject = new ScaleObject3D_2(letterObject, 1.0 / scaleRatio, 1, 1.0 / scaleRatio);
letterObject = new ScaleObject3D_3(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);

View file

@ -188,7 +188,7 @@ namespace MatterHackers.MatterControl.DesignTools
IObject3D extrusionObject = imageObject;
var loadingScale = 32 / extrusionObject.XSize();
extrusionObject = new ScaleObject3D_2(extrusionObject, loadingScale, loadingScale, 1 / extrusionObject.ZSize());
extrusionObject = new ScaleObject3D_3(extrusionObject, loadingScale, loadingScale, 1 / extrusionObject.ZSize());
extrusionObject = PlaceOnBase(logoBase, extrusionObject);
this.Children.Add(coinBlank);

View file

@ -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_2(nameMesh, scale, scale, 2 / textBounds.ZSize);
nameMesh = new ScaleObject3D_3(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);

View file

@ -133,8 +133,7 @@ namespace MatterHackers.Plugins.EditorTools
{
FinalState = new ScaleStates(InitialState);
FinalState.Depth = newDepth;
if (context.GuiSurface.ModifierKeys == Keys.Shift
|| (selectedItem is IScaleLocker scaleLocker && scaleLocker.ScaleLocked))
if (context.GuiSurface.ModifierKeys == Keys.Shift || selectedItem is IScaleLocker)
{
ScaleProportional(newDepth / InitialState.Depth);
}
@ -158,8 +157,7 @@ namespace MatterHackers.Plugins.EditorTools
{
FinalState = new ScaleStates(InitialState);
FinalState.Height = newHeight;
if (context.GuiSurface.ModifierKeys == Keys.Shift
|| (selectedItem is IScaleLocker scaleLocker && scaleLocker.ScaleLocked))
if (context.GuiSurface.ModifierKeys == Keys.Shift || selectedItem is IScaleLocker)
{
ScaleProportional(newHeight / InitialState.Height);
}
@ -171,8 +169,7 @@ namespace MatterHackers.Plugins.EditorTools
{
FinalState = new ScaleStates(InitialState);
FinalState.Width = newWidth;
if (context.GuiSurface.ModifierKeys == Keys.Shift
|| (selectedItem is IScaleLocker scaleLocker && scaleLocker.ScaleLocked))
if (context.GuiSurface.ModifierKeys == Keys.Shift || selectedItem is IScaleLocker)
{
ScaleProportional(newWidth / InitialState.Width);
}
@ -211,8 +208,7 @@ namespace MatterHackers.Plugins.EditorTools
FinalState = new ScaleStates(InitialState);
FinalState.Width = newWidth;
FinalState.Depth = newDepth;
if (context.GuiSurface.ModifierKeys == Keys.Shift
|| (selectedItem is IScaleLocker scaleLocker && scaleLocker.ScaleLocked))
if (context.GuiSurface.ModifierKeys == Keys.Shift || selectedItem is IScaleLocker)
{
ScaleProportional(newWidth / InitialState.Width);
}
@ -245,12 +241,38 @@ namespace MatterHackers.Plugins.EditorTools
private void ScaleProportional(double scale)
{
FinalState.Width = InitialState.Width * scale;
FinalState.Depth = InitialState.Depth * scale;
FinalState.Height = InitialState.Height * scale;
for (int i = 0; i < FinalState.Diameters.Count; i++)
if (selectedItem is IScaleLocker scaleLocker)
{
FinalState.Diameters[i] = InitialState.Diameters[i] * scale;
switch (scaleLocker.LockProportion)
{
case LockProportions.None:
break;
case LockProportions.X_Y:
if (FinalState.Width != InitialState.Width
|| FinalState.Depth != InitialState.Depth)
{
FinalState.Width = InitialState.Width * scale;
FinalState.Depth = InitialState.Depth * scale;
}
break;
case LockProportions.X_Y_Z:
FinalState.Width = InitialState.Width * scale;
FinalState.Depth = InitialState.Depth * scale;
FinalState.Height = InitialState.Height * scale;
break;
}
}
else
{
FinalState.Width = InitialState.Width * scale;
FinalState.Depth = InitialState.Depth * scale;
FinalState.Height = InitialState.Height * scale;
for (int i = 0; i < FinalState.Diameters.Count; i++)
{
FinalState.Diameters[i] = InitialState.Diameters[i] * scale;
}
}
}

View file

@ -63,7 +63,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
X_Y_Z
}
[Obsolete("Not used anymore. Replaced with FitToBoundsObject3D_2", true)]
[Obsolete("Not used anymore. Replaced with FitToBoundsObject3D_3", true)]
public class FitToBoundsObject3D : Object3D, ISelectedEditorDraw, IPropertyGridModifier
{
[Description("Set the shape the part will be fit into.")]

View file

@ -27,16 +27,19 @@ of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
/*********************************************************************/
/**************************** OBSOLETE! ******************************/
/************************ USE NEWER VERSION **************************/
/*********************************************************************/
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.DataConverters3D;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.PartPreviewWindow;
using MatterHackers.MeshVisualizer;
using MatterHackers.PolygonMesh;
using MatterHackers.RenderOpenGl;
using MatterHackers.VectorMath;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@ -45,6 +48,7 @@ using System.Threading.Tasks;
namespace MatterHackers.MatterControl.DesignTools.Operations
{
[Obsolete("Not used anymore. Replaced with FitToBoundsObject3D_3", true)]
public class FitToBoundsObject3D_2 : TransformWrapperObject3D, ISelectedEditorDraw
{
private Vector3 boundsSize;

View file

@ -0,0 +1,289 @@
/*
Copyright (c) 2018, Lars Brubaker, 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 MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.DataConverters3D;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.PartPreviewWindow;
using MatterHackers.PolygonMesh;
using MatterHackers.RenderOpenGl;
using MatterHackers.VectorMath;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
namespace MatterHackers.MatterControl.DesignTools.Operations
{
public class FitToBoundsObject3D_3 : TransformWrapperObject3D, ISelectedEditorDraw, IObjectWithWidthAndDepth, IObjectWithHeight
{
private Vector3 boundsSize;
private InvalidateType additonalInvalidate;
public FitToBoundsObject3D_3()
{
Name = "Fit to Bounds".Localize();
}
private IObject3D FitBounds => Children.Last();
[EnumDisplay(Mode = EnumDisplayAttribute.PresentationMode.Buttons)]
[Description("Ensure that the part maintains its proportions.")]
public LockProportions LockProportion { get; set; } = LockProportions.X_Y_Z;
public double Width
{
get => boundsSize.X;
set
{
boundsSize.X = value;
if (this.Children.Count() > 0)
{
Rebuild();
}
}
}
public double Depth
{
get => boundsSize.Y;
set
{
boundsSize.Y = value;
if (this.Children.Count() > 0)
{
Rebuild();
}
}
}
public double Height
{
get => boundsSize.Z;
set
{
boundsSize.Z = value;
if (this.Children.Count() > 0)
{
Rebuild();
}
}
}
[Description("Allows you turn on and off applying the fit to the x axis.")]
public bool StretchX { get; set; } = true;
[Description("Allows you turn on and off applying the fit to the y axis.")]
public bool StretchY { get; set; } = true;
[Description("Allows you turn on and off applying the fit to the z axis.")]
public bool StretchZ { get; set; } = true;
public static async Task<FitToBoundsObject3D_3> Create(IObject3D itemToFit)
{
var fitToBounds = new FitToBoundsObject3D_3();
using (fitToBounds.RebuildLock())
{
var startingAabb = itemToFit.GetAxisAlignedBoundingBox();
itemToFit.Translate(-startingAabb.Center);
// add the fit item
var scaleItem = new Object3D();
fitToBounds.Children.Add(scaleItem);
scaleItem.Children.Add(itemToFit);
// create an object that just represents the bounds in the scene
var fitBounds = new Object3D()
{
Visible = false,
Color = new Color(Color.Red, 100),
Mesh = PlatonicSolids.CreateCube()
};
// add the item that holds the bounds
fitToBounds.Children.Add(fitBounds);
fitToBounds.boundsSize.X = startingAabb.XSize;
fitToBounds.boundsSize.Y = startingAabb.YSize;
fitToBounds.boundsSize.Z = startingAabb.ZSize;
await fitToBounds.Rebuild();
var finalAabb = fitToBounds.GetAxisAlignedBoundingBox();
fitToBounds.Translate(startingAabb.Center - finalAabb.Center);
}
return fitToBounds;
}
public void DrawEditor(Object3DControlsLayer layer, List<Object3DView> transparentMeshes, DrawEventArgs e)
{
var aabb = UntransformedChildren.GetAxisAlignedBoundingBox();
var center = aabb.Center;
var worldMatrix = this.WorldMatrix();
var minXyz = center - new Vector3(Width / 2, Depth / 2, Height / 2);
var maxXyz = center + new Vector3(Width / 2, Depth / 2, Height / 2);
var bounds = new AxisAlignedBoundingBox(minXyz, maxXyz);
layer.World.RenderAabb(bounds, worldMatrix, Color.Red, 1, 1);
}
public override AxisAlignedBoundingBox GetAxisAlignedBoundingBox(Matrix4X4 matrix)
{
if (Children.Count == 2)
{
AxisAlignedBoundingBox bounds;
using (FitBounds.RebuildLock())
{
FitBounds.Visible = true;
bounds = base.GetAxisAlignedBoundingBox(matrix);
FitBounds.Visible = false;
}
return bounds;
}
return base.GetAxisAlignedBoundingBox(matrix);
}
public override async void OnInvalidate(InvalidateArgs invalidateType)
{
additonalInvalidate = invalidateType.InvalidateType;
if ((invalidateType.InvalidateType.HasFlag(InvalidateType.Children)
|| invalidateType.InvalidateType.HasFlag(InvalidateType.Matrix)
|| invalidateType.InvalidateType.HasFlag(InvalidateType.Mesh))
&& invalidateType.Source != this
&& !RebuildLocked)
{
await Rebuild();
}
else if (invalidateType.InvalidateType.HasFlag(InvalidateType.Properties)
&& invalidateType.Source == this)
{
await Rebuild();
}
else if (invalidateType.InvalidateType.HasFlag(InvalidateType.Properties)
|| invalidateType.InvalidateType.HasFlag(InvalidateType.Matrix)
|| invalidateType.InvalidateType.HasFlag(InvalidateType.Mesh)
|| invalidateType.InvalidateType.HasFlag(InvalidateType.Children))
{
base.OnInvalidate(invalidateType);
}
base.OnInvalidate(invalidateType);
additonalInvalidate = InvalidateType.None;
}
public override Task Rebuild()
{
this.DebugDepth("Rebuild");
using (RebuildLock())
{
using (new CenterAndHeightMaintainer(this))
{
AdjustChildSize(null, null);
UpdateBoundsItem();
}
}
Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Matrix | additonalInvalidate));
return Task.CompletedTask;
}
private void AdjustChildSize(object sender, EventArgs e)
{
if (Children.Count > 0)
{
var aabb = UntransformedChildren.GetAxisAlignedBoundingBox();
ItemWithTransform.Matrix = Matrix4X4.Identity;
var scale = Vector3.One;
if (StretchX)
{
scale.X = Width / aabb.XSize;
}
if (StretchY)
{
scale.Y = Depth / aabb.YSize;
}
if (StretchZ)
{
scale.Z = Height / aabb.ZSize;
}
switch (LockProportion)
{
case LockProportions.None:
break;
case LockProportions.X_Y:
var minXy = Math.Min(scale.X, scale.Y);
scale.X = minXy;
scale.Y = minXy;
break;
case LockProportions.X_Y_Z:
var minXyz = Math.Min(Math.Min(scale.X, scale.Y), scale.Z);
scale.X = minXyz;
scale.Y = minXyz;
scale.Z = minXyz;
break;
}
if (aabb.XSize > 0 && aabb.YSize > 0 && aabb.ZSize > 0)
{
ItemWithTransform.Matrix = Object3DExtensions.ApplyAtPosition(ItemWithTransform.Matrix, aabb.Center, Matrix4X4.CreateScale(scale));
}
}
}
private void UpdateBoundsItem()
{
if (Children.Count == 2)
{
var transformAabb = ItemWithTransform.GetAxisAlignedBoundingBox();
var fitAabb = FitBounds.GetAxisAlignedBoundingBox();
var fitSize = fitAabb.Size;
if (boundsSize.X != 0 && boundsSize.Y != 0 && boundsSize.Z != 0
&& (fitSize != boundsSize
|| fitAabb.Center != transformAabb.Center))
{
FitBounds.Matrix *= Matrix4X4.CreateScale(
boundsSize.X / fitSize.X,
boundsSize.Y / fitSize.Y,
boundsSize.Z / fitSize.Z);
FitBounds.Matrix *= Matrix4X4.CreateTranslation(
transformAabb.Center - FitBounds.GetAxisAlignedBoundingBox().Center);
}
}
}
}
}

View file

@ -47,7 +47,7 @@ using Newtonsoft.Json;
namespace MatterHackers.MatterControl.DesignTools.Operations
{
[Obsolete("Use ScaleObject3D_2 instead", false)]
[Obsolete("Use ScaleObject3D_3 instead", false)]
public class ScaleObject3D : TransformWrapperObject3D, ISelectedEditorDraw, IPropertyGridModifier
{
public enum ScaleType

View file

@ -27,6 +27,11 @@ of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
/*********************************************************************/
/**************************** OBSOLETE! ******************************/
/************************ USE NEWER VERSION **************************/
/*********************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
@ -39,11 +44,7 @@ using Newtonsoft.Json;
namespace MatterHackers.MatterControl.DesignTools.Operations
{
public interface IScaleLocker
{
bool ScaleLocked { get; }
}
[Obsolete("Use ScaleObject3D_3 instead", false)]
public class ScaleObject3D_2 : TransformWrapperObject3D, IObjectWithHeight, IObjectWithWidthAndDepth, IPropertyGridModifier, IScaleLocker
{
public enum ScaleTypes
@ -232,7 +233,7 @@ namespace MatterHackers.MatterControl.DesignTools.Operations
}
}
public bool ScaleLocked => LockProportions;
public LockProportions LockProportion => LockProportions ? Operations.LockProportions.X_Y_Z: Operations.LockProportions.None;
private void FixIfLockedProportions(int index, double newScale)
{

View file

@ -0,0 +1,386 @@
/*
Copyright (c) 2018, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
using MatterHackers.Agg.UI;
using MatterHackers.DataConverters3D;
using MatterHackers.Localizations;
using MatterHackers.VectorMath;
using Newtonsoft.Json;
namespace MatterHackers.MatterControl.DesignTools.Operations
{
public enum LockProportions
{
[Description("Scale Freely")]
None,
[Description("Lock the Width & Depth together")]
X_Y,
[Description("Lock the Width, Depth & Height together")]
X_Y_Z
}
public interface IScaleLocker
{
LockProportions LockProportion { get; }
}
public class ScaleObject3D_3 : TransformWrapperObject3D, IObjectWithHeight, IObjectWithWidthAndDepth, IPropertyGridModifier, IScaleLocker
{
public enum ScaleTypes
{
Custom,
Inches_to_mm,
mm_to_Inches,
mm_to_cm,
cm_to_mm,
Ultrafuse_316L,
}
public ScaleObject3D_3()
{
Name = "Scale".Localize();
}
public ScaleObject3D_3(IObject3D item, double x = 1, double y = 1, double z = 1)
: this(item, new Vector3(x, y, z))
{
}
public ScaleObject3D_3(IObject3D itemToScale, Vector3 scale)
: this()
{
WrapItems(new IObject3D[] { itemToScale });
ScaleRatio = scale;
Rebuild();
}
public override void WrapSelectedItemAndSelect(InteractiveScene scene)
{
base.WrapSelectedItemAndSelect(scene);
// use source item as it may be a copy of item by the time we have wrapped it
var aabb = UntransformedChildren.GetAxisAlignedBoundingBox();
var newCenter = new Vector3(aabb.Center.X, aabb.Center.Y, aabb.MinXYZ.Z);
UntransformedChildren.Translate(-newCenter);
this.Translate(newCenter);
}
public override void WrapItems(IEnumerable<IObject3D> items, UndoBuffer undoBuffer = null)
{
base.WrapItems(items, undoBuffer);
// use source item as it may be a copy of item by the time we have wrapped it
var aabb = UntransformedChildren.GetAxisAlignedBoundingBox();
var newCenter = new Vector3(aabb.Center.X, aabb.Center.Y, aabb.MinXYZ.Z);
UntransformedChildren.Translate(-newCenter);
this.Translate(newCenter);
}
// this is the size we actually serialize
public Vector3 ScaleRatio = Vector3.One;
public ScaleTypes ScaleType { get; set; } = ScaleTypes.Custom;
public enum ScaleMethods
{
Direct,
Percentage,
}
[EnumDisplay(Mode = EnumDisplayAttribute.PresentationMode.Tabs)]
public ScaleMethods ScaleMethod { get; set; } = ScaleMethods.Direct;
[EnumDisplay(Mode = EnumDisplayAttribute.PresentationMode.Buttons)]
[Description("Ensure that the part maintains its proportions.")]
public LockProportions LockProportion { get; set; } = LockProportions.X_Y_Z;
[MaxDecimalPlaces(3)]
[JsonIgnore]
public double Width
{
get
{
var children = UntransformedChildren;
if (children == null)
{
return 0;
}
return ScaleRatio.X * UntransformedChildren.GetAxisAlignedBoundingBox().XSize;
}
set
{
var children = UntransformedChildren;
if (children != null)
{
FixIfLockedProportions(0, value / UntransformedChildren.GetAxisAlignedBoundingBox().XSize);
}
}
}
[MaxDecimalPlaces(3)]
[JsonIgnore]
public double Depth
{
get
{
var children = UntransformedChildren;
if (children == null)
{
return 0;
}
return ScaleRatio.Y * children.GetAxisAlignedBoundingBox().YSize;
}
set
{
var children = UntransformedChildren;
if (children != null)
{
FixIfLockedProportions(1, value / children.GetAxisAlignedBoundingBox().YSize);
}
}
}
[MaxDecimalPlaces(3)]
[JsonIgnore]
public double Height
{
get
{
var children = UntransformedChildren;
if (children == null)
{
return 0;
}
return ScaleRatio.Z * children.GetAxisAlignedBoundingBox().ZSize;
}
set
{
var children = UntransformedChildren;
if (children != null)
{
FixIfLockedProportions(2, value / children.GetAxisAlignedBoundingBox().ZSize);
}
}
}
[MaxDecimalPlaces(2)]
[JsonIgnore]
public double WidthPercent
{
get
{
return ScaleRatio.X * 100;
}
set
{
FixIfLockedProportions(0, value / 100);
}
}
[MaxDecimalPlaces(2)]
[JsonIgnore]
public double DepthPercent
{
get
{
return ScaleRatio.Y * 100;
}
set
{
FixIfLockedProportions(1, value / 100);
}
}
[MaxDecimalPlaces(2)]
[JsonIgnore]
public double HeightPercent
{
get
{
return ScaleRatio.Z * 100;
}
set
{
FixIfLockedProportions(2, value / 100);
}
}
private void FixIfLockedProportions(int index, double newScale)
{
if (Math.Abs(newScale - ScaleRatio[index]) > .001)
{
ScaleRatio[index] = newScale;
if (ScaleType != ScaleTypes.Custom)
{
// WIP: switch back to custom scaling (as we are no longer on a fixed scaling)
// needs to:
// - create an undo point for the switch
// - update the properties control to show the right drop down
// - show all the settings
}
if (LockProportion == LockProportions.X_Y_Z)
{
ScaleRatio[(index + 1) % 3] = ScaleRatio[index];
ScaleRatio[(index + 2) % 3] = ScaleRatio[index];
Invalidate(new InvalidateArgs(null, InvalidateType.DisplayValues));
}
else if (LockProportion == LockProportions.X_Y)
{
if (index == 0)
{
ScaleRatio[1] = ScaleRatio[index];
Invalidate(new InvalidateArgs(null, InvalidateType.DisplayValues));
}
else if(index == 1)
{
ScaleRatio[0] = ScaleRatio[index];
Invalidate(new InvalidateArgs(null, InvalidateType.DisplayValues));
}
}
Rebuild();
}
}
public async override void OnInvalidate(InvalidateArgs invalidateArgs)
{
if ((invalidateArgs.InvalidateType.HasFlag(InvalidateType.Children)
|| invalidateArgs.InvalidateType.HasFlag(InvalidateType.Matrix)
|| invalidateArgs.InvalidateType.HasFlag(InvalidateType.Mesh))
&& invalidateArgs.Source != this
&& !RebuildLocked)
{
await Rebuild();
}
else if (invalidateArgs.InvalidateType.HasFlag(InvalidateType.Properties)
&& invalidateArgs.Source == this)
{
await Rebuild();
}
else
{
base.OnInvalidate(invalidateArgs);
}
}
public override Task Rebuild()
{
this.DebugDepth("Rebuild");
using (RebuildLock())
{
using (new CenterAndHeightMaintainer(this))
{
// set the matrix for the transform object
ItemWithTransform.Matrix = Matrix4X4.Identity;
ItemWithTransform.Matrix *= Matrix4X4.CreateScale(ScaleRatio);
}
}
Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Matrix));
return Task.CompletedTask;
}
public void UpdateControls(PublicPropertyChange change)
{
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);
change.SetRowVisible(nameof(ScaleMethod), () => ScaleType == ScaleTypes.Custom);
if (change.Changed == nameof(ScaleType))
{
// recalculate the scaling
double scale = 1;
switch (ScaleType)
{
case ScaleTypes.Inches_to_mm:
scale = 25.4;
break;
case ScaleTypes.mm_to_Inches:
scale = .0393;
break;
case ScaleTypes.mm_to_cm:
scale = .1;
break;
case ScaleTypes.cm_to_mm:
scale = 10;
break;
case ScaleTypes.Ultrafuse_316L:
ScaleRatio = new Vector3(1.1982, 1.1982, 1.261);
Rebuild();
Invalidate(new InvalidateArgs(null, InvalidateType.DisplayValues));
return;
}
ScaleRatio = new Vector3(scale, scale, scale);
Rebuild();
Invalidate(new InvalidateArgs(null, InvalidateType.DisplayValues));
}
else if (change.Changed == nameof(LockProportion))
{
if (LockProportion == LockProportions.X_Y_Z)
{
var maxScale = Math.Max(ScaleRatio.X, Math.Max(ScaleRatio.Y, ScaleRatio.Z));
ScaleRatio = new Vector3(maxScale, maxScale, maxScale);
Rebuild();
// make sure we update the controls on screen to reflect the different data type
Invalidate(new InvalidateArgs(null, InvalidateType.DisplayValues));
}
else if (LockProportion == LockProportions.X_Y)
{
var maxScale = Math.Max(ScaleRatio.X, ScaleRatio.Y);
ScaleRatio = new Vector3(maxScale, maxScale, ScaleRatio.Z);
Rebuild();
// make sure we update the controls on screen to reflect the different data type
Invalidate(new InvalidateArgs(null, InvalidateType.DisplayValues));
}
}
}
}
}

View file

@ -100,7 +100,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
break;
case EnumDisplayAttribute.PresentationMode.Buttons:
AddButtons(enumItems);
AddButtons(enumItems, enumDescriptions);
break;
default:
@ -157,7 +157,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
this.Content = menuRow;
}
private void AddButtons(IEnumerable<(string Key, string Value)> enumItems)
private void AddButtons(IEnumerable<(string Key, string Value)> enumItems, List<string> descriptions)
{
var menuRow = new FlowLayoutWidget();
@ -177,6 +177,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
SelectedBackgroundColor = theme.PrimaryAccentColor,
UnselectedBackgroundColor = theme.MinimalShade,
BackgroundColor = theme.MinimalShade,
ToolTipText = descriptions[index]
};
radioButton.CheckedStateChanged += (s, e) =>

View file

@ -325,11 +325,11 @@ namespace MatterControl.Tests.MatterControl
root.Children.Add(cube);
Assert.IsTrue(root.GetAxisAlignedBoundingBox().Equals(new AxisAlignedBoundingBox(new Vector3(-10, -10, -10), new Vector3(10, 10, 10)), .001));
root.Children.Remove(cube);
var fit = await FitToBoundsObject3D_2.Create(cube);
var fit = await FitToBoundsObject3D_3.Create(cube);
fit.SizeX = 50;
fit.SizeY = 20;
fit.SizeZ = 20;
fit.Width = 50;
fit.Depth = 20;
fit.Height = 20;
root.Children.Add(fit);
var rootAabb = root.GetAxisAlignedBoundingBox();
Assert.IsTrue(rootAabb.Equals(new AxisAlignedBoundingBox(new Vector3(-25, -10, -10), new Vector3(25, 10, 10)), .001));
@ -339,11 +339,11 @@ namespace MatterControl.Tests.MatterControl
{
var root = new Object3D();
var cube = await CubeObject3D.Create(20, 20, 20);
var fit = await FitToBoundsObject3D_2.Create(cube);
var fit = await FitToBoundsObject3D_3.Create(cube);
fit.SizeX = 50;
fit.SizeY = 20;
fit.SizeZ = 20;
fit.Width = 50;
fit.Depth = 20;
fit.Height = 20;
var pinch = new PinchObject3D_3();
pinch.Children.Add(fit);
@ -384,11 +384,11 @@ namespace MatterControl.Tests.MatterControl
{
var root = new Object3D();
var cube = await CubeObject3D.Create(20, 20, 20);
var fit = await FitToBoundsObject3D_2.Create(cube);
var fit = await FitToBoundsObject3D_3.Create(cube);
fit.SizeX = 50;
fit.SizeY = 20;
fit.SizeZ = 20;
fit.Width = 50;
fit.Depth = 20;
fit.Height = 20;
var translate = new TranslateObject3D(fit, 11, 0, 0);
@ -417,7 +417,7 @@ namespace MatterControl.Tests.MatterControl
var undoBuffer = new UndoBuffer();
// add a scale to it (that is not scaled)
var scaleObject = new ScaleObject3D_2();
var scaleObject = new ScaleObject3D_3();
scaleObject.WrapItems(new IObject3D[] { cube }, undoBuffer);
// ensure that the object did not move
@ -440,7 +440,7 @@ namespace MatterControl.Tests.MatterControl
var preScaleAabb = root.GetAxisAlignedBoundingBox();
// add a scale to it (that is not scaled)
var scaleObject = new ScaleObject3D_2(cube);
var scaleObject = new ScaleObject3D_3(cube);
// ensure that the object did not move
Assert.AreEqual(4, root.DescendantsAndSelf().Count());
@ -465,7 +465,7 @@ namespace MatterControl.Tests.MatterControl
var preScaleAabb = root.GetAxisAlignedBoundingBox();
// add a scale to it (that is not scaled)
var scaleObject = new ScaleObject3D_2(cube);
var scaleObject = new ScaleObject3D_3(cube);
// ensure that the object did not move
Assert.AreEqual(4, root.DescendantsAndSelf().Count());
@ -525,11 +525,11 @@ namespace MatterControl.Tests.MatterControl
var root = new Object3D();
var cube = await CubeObject3D.Create(20, 20, 20);
var fit = await FitToBoundsObject3D_2.Create(cube);
var fit = await FitToBoundsObject3D_3.Create(cube);
fit.SizeX = 10;
fit.SizeY = 10;
fit.SizeZ = 6;
fit.Width = 10;
fit.Depth = 10;
fit.Height = 6;
Assert.IsTrue(fit.GetAxisAlignedBoundingBox().Equals(new AxisAlignedBoundingBox(new Vector3(-5, -5, -10), new Vector3(5, 5, -4)), .01));
@ -635,11 +635,11 @@ namespace MatterControl.Tests.MatterControl
var root = new Object3D();
var cube = await CubeObject3D.Create(20, 20, 20);
var fit = await FitToBoundsObject3D_2.Create(cube);
var fit = await FitToBoundsObject3D_3.Create(cube);
fit.SizeX = 50;
fit.SizeY = 20;
fit.SizeZ = 20;
fit.Width = 50;
fit.Depth = 20;
fit.Height = 20;
Assert.IsTrue(fit.GetAxisAlignedBoundingBox().Equals(new AxisAlignedBoundingBox(new Vector3(-25, -10, -10), new Vector3(25, 10, 10)), 1.0));