2018-01-29 13:50:55 -08:00
/ *
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 ;
2018-03-19 09:27:15 -07:00
using System.Collections.Generic ;
using System.ComponentModel ;
2018-03-26 16:29:23 -07:00
using System.Linq ;
2019-01-24 14:47:24 -08:00
using System.Threading.Tasks ;
2018-03-19 09:27:15 -07:00
using MatterHackers.Agg.UI ;
2018-01-29 13:50:55 -08:00
using MatterHackers.DataConverters3D ;
using MatterHackers.VectorMath ;
2018-05-15 13:56:05 -07:00
using Newtonsoft.Json ;
using Newtonsoft.Json.Converters ;
2018-01-29 13:50:55 -08:00
namespace MatterHackers.MatterControl.DesignTools.Operations
{
2018-03-19 09:27:15 -07:00
using Aabb = AxisAlignedBoundingBox ;
2018-05-15 13:56:05 -07:00
[JsonConverter(typeof(StringEnumConverter))]
2018-03-26 16:29:23 -07:00
public enum Align { None , Min , Center , Max , Origin }
2018-03-19 09:27:15 -07:00
2018-05-15 13:56:05 -07:00
[JsonConverter(typeof(StringEnumConverter))]
2018-01-29 13:50:55 -08:00
public enum Alignment { X , Y , Z , negX , negY , negZ } ;
2018-05-15 13:56:05 -07:00
[JsonConverter(typeof(StringEnumConverter))]
2018-01-29 13:50:55 -08:00
[Flags]
public enum Edge
{
2018-06-02 22:29:56 -07:00
LeftFront = FaceAlign . Left | FaceAlign . Front ,
LeftBack = FaceAlign . Left | FaceAlign . Back ,
LeftBottom = FaceAlign . Left | FaceAlign . Bottom ,
LeftTop = FaceAlign . Left | FaceAlign . Top ,
RightFront = FaceAlign . Right | FaceAlign . Front ,
RightBack = FaceAlign . Right | FaceAlign . Back ,
RightBottom = FaceAlign . Right | FaceAlign . Bottom ,
RightTop = FaceAlign . Right | FaceAlign . Top ,
FrontBottom = FaceAlign . Front | FaceAlign . Bottom ,
FrontTop = FaceAlign . Front | FaceAlign . Top ,
BackBottom = FaceAlign . Back | FaceAlign . Bottom ,
BackTop = FaceAlign . Back | FaceAlign . Top
2018-01-29 13:50:55 -08:00
}
2018-05-15 13:56:05 -07:00
[JsonConverter(typeof(StringEnumConverter))]
2018-01-29 13:50:55 -08:00
[Flags]
2018-06-02 22:29:56 -07:00
public enum FaceAlign
2018-01-29 13:50:55 -08:00
{
Left = 0x01 ,
Right = 0x02 ,
Front = 0x04 ,
Back = 0x08 ,
Bottom = 0x10 ,
Top = 0x20 ,
} ;
2018-05-15 13:56:05 -07:00
[JsonConverter(typeof(StringEnumConverter))]
2018-03-13 17:17:28 -07:00
[Flags]
public enum Side2D
{
Left = 0x01 ,
Right = 0x02 ,
Bottom = 0x10 ,
Top = 0x20 ,
} ;
2019-02-04 08:38:58 -08:00
public abstract class SelectedChildContainer : Object3D
{
public abstract SelectedChildren SelectedChild { get ; set ; }
}
public class AlignObject3D : SelectedChildContainer , IPropertyGridModifier
2018-01-29 13:50:55 -08:00
{
2018-03-19 09:27:15 -07:00
// We need to serialize this so we can remove the arrange and get back to the objects before arranging
public List < Aabb > OriginalChildrenBounds = new List < Aabb > ( ) ;
2019-01-25 16:46:23 -08:00
private SelectedChildren _anchorObjectSelector = new SelectedChildren ( ) ;
2018-03-19 09:27:15 -07:00
2018-06-21 21:02:37 -07:00
public AlignObject3D ( )
2018-01-29 13:50:55 -08:00
{
2018-03-19 09:27:15 -07:00
Name = "Align" ;
2018-01-29 13:50:55 -08:00
}
2018-06-21 21:02:37 -07:00
public AlignObject3D ( IObject3D objectToAlign , FaceAlign boundingFacesToAlign , IObject3D objectToAlignTo , FaceAlign boundingFacesToAlignTo , double offsetX = 0 , double offsetY = 0 , double offsetZ = 0 , string name = "" )
2018-01-29 13:50:55 -08:00
: this ( objectToAlign , boundingFacesToAlign , GetPositionToAlignTo ( objectToAlignTo , boundingFacesToAlignTo , new Vector3 ( offsetX , offsetY , offsetZ ) ) , name )
{
if ( objectToAlign = = objectToAlignTo )
{
2018-03-13 17:17:28 -07:00
throw new Exception ( "You cannot align an object to itself." ) ;
2018-01-29 13:50:55 -08:00
}
}
2018-06-21 21:02:37 -07:00
public AlignObject3D ( IObject3D objectToAlign , FaceAlign boundingFacesToAlign , double positionToAlignToX = 0 , double positionToAlignToY = 0 , double positionToAlignToZ = 0 , string name = "" )
2018-03-13 08:26:54 -07:00
: this ( objectToAlign , boundingFacesToAlign , new Vector3 ( positionToAlignToX , positionToAlignToY , positionToAlignToZ ) , name )
2018-01-29 13:50:55 -08:00
{
}
2018-06-21 21:02:37 -07:00
public AlignObject3D ( IObject3D objectToAlign , FaceAlign boundingFacesToAlign , Vector3 positionToAlignTo , double offsetX , double offsetY , double offsetZ , string name = "" )
2018-01-29 13:50:55 -08:00
: this ( objectToAlign , boundingFacesToAlign , positionToAlignTo + new Vector3 ( offsetX , offsetY , offsetZ ) , name )
{
}
2018-06-21 21:02:37 -07:00
public AlignObject3D ( IObject3D item , FaceAlign boundingFacesToAlign , Vector3 positionToAlignTo , string name = "" )
2018-01-29 13:50:55 -08:00
{
AxisAlignedBoundingBox bounds = item . GetAxisAlignedBoundingBox ( ) ;
2018-06-02 22:29:56 -07:00
if ( IsSet ( boundingFacesToAlign , FaceAlign . Left , FaceAlign . Right ) )
2018-01-29 13:50:55 -08:00
{
2019-01-11 16:49:34 -08:00
positionToAlignTo . X = positionToAlignTo . X - bounds . MinXYZ . X ;
2018-01-29 13:50:55 -08:00
}
2018-06-02 22:29:56 -07:00
if ( IsSet ( boundingFacesToAlign , FaceAlign . Right , FaceAlign . Left ) )
2018-01-29 13:50:55 -08:00
{
2019-01-11 16:49:34 -08:00
positionToAlignTo . X = positionToAlignTo . X - bounds . MinXYZ . X - ( bounds . MaxXYZ . X - bounds . MinXYZ . X ) ;
2018-01-29 13:50:55 -08:00
}
2018-06-02 22:29:56 -07:00
if ( IsSet ( boundingFacesToAlign , FaceAlign . Front , FaceAlign . Back ) )
2018-01-29 13:50:55 -08:00
{
2019-01-11 16:49:34 -08:00
positionToAlignTo . Y = positionToAlignTo . Y - bounds . MinXYZ . Y ;
2018-01-29 13:50:55 -08:00
}
2018-06-02 22:29:56 -07:00
if ( IsSet ( boundingFacesToAlign , FaceAlign . Back , FaceAlign . Front ) )
2018-01-29 13:50:55 -08:00
{
2019-01-11 16:49:34 -08:00
positionToAlignTo . Y = positionToAlignTo . Y - bounds . MinXYZ . Y - ( bounds . MaxXYZ . Y - bounds . MinXYZ . Y ) ;
2018-01-29 13:50:55 -08:00
}
2018-06-02 22:29:56 -07:00
if ( IsSet ( boundingFacesToAlign , FaceAlign . Bottom , FaceAlign . Top ) )
2018-01-29 13:50:55 -08:00
{
2019-01-11 16:49:34 -08:00
positionToAlignTo . Z = positionToAlignTo . Z - bounds . MinXYZ . Z ;
2018-01-29 13:50:55 -08:00
}
2018-06-02 22:29:56 -07:00
if ( IsSet ( boundingFacesToAlign , FaceAlign . Top , FaceAlign . Bottom ) )
2018-01-29 13:50:55 -08:00
{
2019-01-11 16:49:34 -08:00
positionToAlignTo . Z = positionToAlignTo . Z - bounds . MinXYZ . Z - ( bounds . MaxXYZ . Z - bounds . MinXYZ . Z ) ;
2018-01-29 13:50:55 -08:00
}
Matrix * = Matrix4X4 . CreateTranslation ( positionToAlignTo ) ;
Children . Add ( item . Clone ( ) ) ;
}
2018-08-13 13:48:10 -07:00
[ShowAsList]
2018-12-28 18:29:49 -08:00
[DisplayName("Primary")]
2019-02-04 08:38:58 -08:00
public override SelectedChildren SelectedChild
2019-01-25 16:46:23 -08:00
{
get
{
if ( Children . Count > 0 )
{
if ( _anchorObjectSelector . Count ! = 1 )
{
_anchorObjectSelector . Clear ( ) ;
_anchorObjectSelector . Add ( Children . First ( ) . ID ) ;
}
if ( ! this . Children . Any ( c = > c . ID = = _anchorObjectSelector [ 0 ] ) )
{
// we don't have an id of any of our current children
_anchorObjectSelector . Clear ( ) ;
_anchorObjectSelector . Add ( Children . First ( ) . ID ) ;
}
}
else
{
_anchorObjectSelector . Clear ( ) ;
}
return _anchorObjectSelector ;
}
set = > _anchorObjectSelector = value ;
}
2018-08-13 13:48:10 -07:00
2018-04-12 09:54:31 -07:00
public bool Advanced { get ; set ; } = false ;
2018-12-28 18:29:49 -08:00
[SectionStart("X Axis"), DisplayName("Align")]
2018-03-26 16:29:23 -07:00
[Icons(new string[] { "424.png" , "align_left.png" , "align_center_x.png" , "align_right.png" , "align_origin.png" } ) ]
2018-03-19 09:27:15 -07:00
public Align XAlign { get ; set ; } = Align . None ;
2018-12-28 18:29:49 -08:00
[DisplayName("Anchor")]
2019-02-01 08:31:55 -08:00
[Icons(new string[] { "424.png" , "align_to_left.png" , "align_to_center_x.png" , "align_to_right.png" , "align_origin.png" } , InvertIcons = true ) ]
2018-03-19 09:27:15 -07:00
public Align XAlignTo { get ; set ; } = Align . None ;
2018-12-28 18:29:49 -08:00
[DisplayName("Offset")]
2018-03-19 09:27:15 -07:00
public double XOffset { get ; set ; } = 0 ;
2018-12-28 18:29:49 -08:00
[SectionStart("Y Axis"), DisplayName("Align")]
2018-08-19 18:10:28 -07:00
[Icons(new string[] { "424.png" , "align_bottom.png" , "align_center_y.png" , "align_Top.png" , "align_origin.png" } ) ]
2018-03-19 09:27:15 -07:00
public Align YAlign { get ; set ; } = Align . None ;
2018-12-28 18:29:49 -08:00
[DisplayName("Anchor")]
2019-02-01 08:31:55 -08:00
[Icons(new string[] { "424.png" , "align_to_bottom.png" , "align_to_center_y.png" , "align_to_top.png" , "align_origin.png" } , InvertIcons = true ) ]
2018-03-19 09:27:15 -07:00
public Align YAlignTo { get ; set ; } = Align . None ;
2018-12-28 18:29:49 -08:00
[DisplayName("Offset")]
2018-03-19 09:27:15 -07:00
public double YOffset { get ; set ; } = 0 ;
2018-12-28 18:29:49 -08:00
[SectionStart("Z Axis"), DisplayName("Align")]
2018-08-19 18:10:28 -07:00
[Icons(new string[] { "424.png" , "align_bottom.png" , "align_center_y.png" , "align_Top.png" , "align_origin.png" } ) ]
2018-03-19 09:27:15 -07:00
public Align ZAlign { get ; set ; } = Align . None ;
2018-12-28 18:29:49 -08:00
[DisplayName("Anchor")]
2019-02-01 08:31:55 -08:00
[Icons(new string[] { "424.png" , "align_to_bottom.png" , "align_to_center_y.png" , "align_to_top.png" , "align_origin.png" } , InvertIcons = true ) ]
2018-03-19 09:27:15 -07:00
public Align ZAlignTo { get ; set ; } = Align . None ;
2018-12-28 18:29:49 -08:00
[DisplayName("Offset")]
2018-03-19 09:27:15 -07:00
public double ZOffset { get ; set ; } = 0 ;
2018-10-04 10:17:57 -07:00
public override bool CanFlatten = > true ;
2018-03-19 09:27:15 -07:00
private List < Aabb > CurrentChildrenBounds
{
get
{
2018-08-08 13:59:34 -07:00
var currentChildrenBounds = new List < Aabb > ( ) ;
2018-03-19 09:27:15 -07:00
this . Children . Modify ( list = >
{
foreach ( var child in list )
{
currentChildrenBounds . Add ( child . GetAxisAlignedBoundingBox ( ) ) ;
}
} ) ;
return currentChildrenBounds ;
}
}
2018-08-13 13:48:10 -07:00
[JsonIgnore]
private IObject3D AnchorObject
{
get
{
2019-02-04 08:38:58 -08:00
return this . Children . Where ( c = > c . ID = = SelectedChild [ 0 ] ) . FirstOrDefault ( ) ;
2018-08-13 13:48:10 -07:00
}
}
[JsonIgnore]
private int AnchorObjectIndex
{
get
{
int index = 0 ;
2019-01-25 16:46:23 -08:00
foreach ( var child in this . Children )
{
if ( child = = AnchorObject )
2018-08-13 13:48:10 -07:00
{
return index ;
}
index + + ;
}
2019-01-24 14:47:24 -08:00
return 0 ;
2018-08-13 13:48:10 -07:00
}
}
2018-06-02 22:29:56 -07:00
public static Vector3 GetPositionToAlignTo ( IObject3D objectToAlignTo , FaceAlign boundingFacesToAlignTo , Vector3 extraOffset )
2018-01-29 13:50:55 -08:00
{
Vector3 positionToAlignTo = new Vector3 ( ) ;
2018-06-02 22:29:56 -07:00
if ( IsSet ( boundingFacesToAlignTo , FaceAlign . Left , FaceAlign . Right ) )
2018-01-29 13:50:55 -08:00
{
2019-01-11 16:49:34 -08:00
positionToAlignTo . X = objectToAlignTo . GetAxisAlignedBoundingBox ( ) . MinXYZ . X ;
2018-01-29 13:50:55 -08:00
}
2018-06-02 22:29:56 -07:00
if ( IsSet ( boundingFacesToAlignTo , FaceAlign . Right , FaceAlign . Left ) )
2018-01-29 13:50:55 -08:00
{
2019-01-11 16:49:34 -08:00
positionToAlignTo . X = objectToAlignTo . GetAxisAlignedBoundingBox ( ) . MaxXYZ . X ;
2018-01-29 13:50:55 -08:00
}
2018-06-02 22:29:56 -07:00
if ( IsSet ( boundingFacesToAlignTo , FaceAlign . Front , FaceAlign . Back ) )
2018-01-29 13:50:55 -08:00
{
2019-01-11 16:49:34 -08:00
positionToAlignTo . Y = objectToAlignTo . GetAxisAlignedBoundingBox ( ) . MinXYZ . Y ;
2018-01-29 13:50:55 -08:00
}
2018-06-02 22:29:56 -07:00
if ( IsSet ( boundingFacesToAlignTo , FaceAlign . Back , FaceAlign . Front ) )
2018-01-29 13:50:55 -08:00
{
2019-01-11 16:49:34 -08:00
positionToAlignTo . Y = objectToAlignTo . GetAxisAlignedBoundingBox ( ) . MaxXYZ . Y ;
2018-01-29 13:50:55 -08:00
}
2018-06-02 22:29:56 -07:00
if ( IsSet ( boundingFacesToAlignTo , FaceAlign . Bottom , FaceAlign . Top ) )
2018-01-29 13:50:55 -08:00
{
2019-01-11 16:49:34 -08:00
positionToAlignTo . Z = objectToAlignTo . GetAxisAlignedBoundingBox ( ) . MinXYZ . Z ;
2018-01-29 13:50:55 -08:00
}
2018-06-02 22:29:56 -07:00
if ( IsSet ( boundingFacesToAlignTo , FaceAlign . Top , FaceAlign . Bottom ) )
2018-01-29 13:50:55 -08:00
{
2019-01-11 16:49:34 -08:00
positionToAlignTo . Z = objectToAlignTo . GetAxisAlignedBoundingBox ( ) . MaxXYZ . Z ;
2018-01-29 13:50:55 -08:00
}
return positionToAlignTo + extraOffset ;
}
2019-01-28 14:19:40 -08:00
public override async void OnInvalidate ( InvalidateArgs invalidateType )
2018-05-04 13:47:16 -07:00
{
2019-01-28 14:19:40 -08:00
if ( ( invalidateType . InvalidateType . HasFlag ( InvalidateType . Children )
| | invalidateType . InvalidateType . HasFlag ( InvalidateType . Matrix )
| | invalidateType . InvalidateType . HasFlag ( InvalidateType . Mesh ) )
2018-05-22 16:17:13 -07:00
& & invalidateType . Source ! = this
2018-06-20 17:16:38 -07:00
& & ! RebuildLocked )
{
2019-01-28 14:19:40 -08:00
await Rebuild ( ) ;
2018-06-20 17:16:38 -07:00
}
2019-01-28 14:19:40 -08:00
else if ( invalidateType . InvalidateType . HasFlag ( InvalidateType . Properties )
2018-06-20 17:16:38 -07:00
& & invalidateType . Source = = this )
2018-05-04 13:47:16 -07:00
{
2019-01-28 14:19:40 -08:00
await Rebuild ( ) ;
2018-05-29 17:46:59 -07:00
}
2019-02-03 13:09:13 -08:00
else
{
// and also always pass back the actual type
base . OnInvalidate ( invalidateType ) ;
}
2018-05-04 13:47:16 -07:00
}
2019-01-24 14:47:24 -08:00
public override Task Rebuild ( )
2018-01-29 13:50:55 -08:00
{
2018-05-29 17:46:59 -07:00
this . DebugDepth ( "Rebuild" ) ;
2018-08-13 13:48:10 -07:00
var childrenIds = Children . Select ( c = > c . ID ) . ToArray ( ) ;
// if the count of our children changed clear our cache of the bounds
if ( Children . Count ! = OriginalChildrenBounds . Count )
{
OriginalChildrenBounds . Clear ( ) ;
}
2018-06-20 08:09:35 -07:00
using ( RebuildLock ( ) )
2018-01-29 13:50:55 -08:00
{
2018-06-20 08:09:35 -07:00
var aabb = this . GetAxisAlignedBoundingBox ( ) ;
2018-01-29 13:50:55 -08:00
2018-06-20 08:09:35 -07:00
// TODO: check if the has code for the children
if ( OriginalChildrenBounds . Count = = 0 )
2018-05-04 13:47:16 -07:00
{
2018-06-20 08:09:35 -07:00
this . Children . Modify ( list = >
{
foreach ( var child in list )
{
OriginalChildrenBounds . Add ( child . GetAxisAlignedBoundingBox ( ) ) ;
}
} ) ;
2018-05-04 13:47:16 -07:00
}
2018-06-20 08:09:35 -07:00
2019-01-11 16:49:34 -08:00
this . Children . Modify ( ( Action < List < IObject3D > > ) ( ( List < IObject3D > list ) = >
2018-03-19 09:27:15 -07:00
{
2018-06-20 08:09:35 -07:00
if ( list . Count = = 0 )
{
return ;
}
2018-08-13 13:48:10 -07:00
int anchorIndex = AnchorObjectIndex ;
var anchorBounds = CurrentChildrenBounds [ anchorIndex ] ;
2018-06-20 08:09:35 -07:00
int i = 0 ;
2018-08-13 13:48:10 -07:00
// first align the anchor object
2018-06-20 08:09:35 -07:00
foreach ( var child in list )
2018-03-19 09:27:15 -07:00
{
2019-04-19 09:52:49 -07:00
// only process the anchor object
2019-03-03 08:24:32 -08:00
if ( i ! = anchorIndex )
{
i + + ;
continue ;
}
if ( XAlign = = Align . None )
2018-08-13 13:48:10 -07:00
{
if ( i < OriginalChildrenBounds . Count )
{
// make sure it is where it started
2019-01-11 16:49:34 -08:00
AlignAxis ( 0 , Align . Min , ( double ) OriginalChildrenBounds [ i ] . MinXYZ . X , 0 , child ) ;
2018-08-13 13:48:10 -07:00
}
}
2019-03-03 08:24:32 -08:00
if ( YAlign = = Align . None )
2018-03-19 09:27:15 -07:00
{
2018-08-13 13:48:10 -07:00
if ( i < OriginalChildrenBounds . Count )
2018-05-09 09:29:54 -07:00
{
2019-01-11 16:49:34 -08:00
AlignAxis ( 1 , Align . Min , ( double ) OriginalChildrenBounds [ i ] . MinXYZ . Y , 0 , child ) ;
2018-08-13 13:48:10 -07:00
}
}
2019-03-03 08:24:32 -08:00
if ( ZAlign = = Align . None )
2018-08-13 13:48:10 -07:00
{
if ( i < OriginalChildrenBounds . Count )
{
2019-01-11 16:49:34 -08:00
AlignAxis ( 2 , Align . Min , ( double ) OriginalChildrenBounds [ i ] . MinXYZ . Z , 0 , child ) ;
2018-08-13 13:48:10 -07:00
}
}
2019-03-03 08:24:32 -08:00
2018-08-13 13:48:10 -07:00
i + + ;
}
2019-02-01 08:31:55 -08:00
// then align all the objects to it
2018-08-13 13:48:10 -07:00
i = 0 ;
foreach ( var child in list )
{
2019-04-19 09:52:49 -07:00
// skip the anchor object
2019-03-03 08:24:32 -08:00
if ( i = = anchorIndex )
{
i + + ;
continue ;
}
if ( XAlign ! = Align . None )
2018-08-13 13:48:10 -07:00
{
2019-02-01 08:31:55 -08:00
AlignAxis ( 0 , XAlign , GetAlignToOffset ( CurrentChildrenBounds , 0 , ( ! Advanced | | XAlignTo = = Align . None ) ? XAlign : XAlignTo ) , XOffset , child ) ;
2018-08-13 13:48:10 -07:00
}
2019-03-03 08:24:32 -08:00
if ( YAlign ! = Align . None )
2018-08-13 13:48:10 -07:00
{
2019-02-01 08:31:55 -08:00
AlignAxis ( 1 , YAlign , GetAlignToOffset ( CurrentChildrenBounds , 1 , ( ! Advanced | | YAlignTo = = Align . None ) ? YAlign : YAlignTo ) , YOffset , child ) ;
2018-08-13 13:48:10 -07:00
}
2019-03-03 08:24:32 -08:00
if ( ZAlign ! = Align . None )
2018-08-13 13:48:10 -07:00
{
2019-02-01 08:31:55 -08:00
AlignAxis ( 2 , ZAlign , GetAlignToOffset ( CurrentChildrenBounds , 2 , ( ! Advanced | | ZAlignTo = = Align . None ) ? ZAlign : ZAlignTo ) , ZOffset , child ) ;
2018-03-19 09:27:15 -07:00
}
2019-03-03 08:24:32 -08:00
2018-06-20 08:09:35 -07:00
i + + ;
2018-03-19 09:27:15 -07:00
}
2019-01-11 16:49:34 -08:00
} ) ) ;
2018-06-20 08:09:35 -07:00
}
2018-05-04 13:47:16 -07:00
2019-02-13 15:45:33 -08:00
Parent ? . Invalidate ( new InvalidateArgs ( this , InvalidateType . Matrix ) ) ;
2019-01-24 14:47:24 -08:00
return Task . CompletedTask ;
2018-03-13 17:17:28 -07:00
}
2018-05-02 14:34:44 -07:00
public override void Remove ( UndoBuffer undoBuffer )
2018-03-13 17:17:28 -07:00
{
2018-06-20 08:09:35 -07:00
using ( RebuildLock ( ) )
2018-03-13 17:17:28 -07:00
{
2018-06-20 08:09:35 -07:00
// put everything back to where it was before the arrange started
if ( OriginalChildrenBounds . Count = = Children . Count )
2018-03-19 09:27:15 -07:00
{
2018-06-20 08:09:35 -07:00
int i = 0 ;
foreach ( var child in Children )
{
// Where you are minus where you started to get back to where you started
2019-01-11 16:49:34 -08:00
child . Translate ( - ( child . GetAxisAlignedBoundingBox ( ) . MinXYZ - OriginalChildrenBounds [ i ] . MinXYZ ) ) ;
2018-06-20 08:09:35 -07:00
i + + ;
}
2018-03-19 09:27:15 -07:00
}
2018-03-13 17:17:28 -07:00
2018-06-20 08:09:35 -07:00
base . Remove ( undoBuffer ) ;
}
2018-06-01 17:44:46 -07:00
2019-01-28 17:44:00 -08:00
Invalidate ( InvalidateType . Children ) ;
2018-03-13 17:17:28 -07:00
}
2018-07-06 17:11:33 -07:00
public void UpdateControls ( PublicPropertyChange change )
2018-03-13 17:17:28 -07:00
{
2019-02-03 07:37:53 -08:00
change . SetRowVisible ( nameof ( XAlignTo ) , ( ) = > Advanced ) ;
change . SetRowVisible ( nameof ( XOffset ) , ( ) = > Advanced ) ;
change . SetRowVisible ( nameof ( YAlignTo ) , ( ) = > Advanced ) ;
change . SetRowVisible ( nameof ( YOffset ) , ( ) = > Advanced ) ;
change . SetRowVisible ( nameof ( ZAlignTo ) , ( ) = > Advanced ) ;
change . SetRowVisible ( nameof ( ZOffset ) , ( ) = > Advanced ) ;
2018-03-13 17:17:28 -07:00
}
2018-06-02 22:29:56 -07:00
private static bool IsSet ( FaceAlign variableToCheck , FaceAlign faceToCheckFor , FaceAlign faceToAssertNot )
2018-03-13 17:17:28 -07:00
{
2018-03-19 09:27:15 -07:00
if ( ( variableToCheck & faceToCheckFor ) ! = 0 )
2018-03-13 17:17:28 -07:00
{
2018-03-19 09:27:15 -07:00
if ( ( variableToCheck & faceToAssertNot ) ! = 0 )
{
throw new Exception ( "You cannot have both " + faceToCheckFor . ToString ( ) + " and " + faceToAssertNot . ToString ( ) + " set when calling Align. The are mutually exclusive." ) ;
}
return true ;
2018-03-13 17:17:28 -07:00
}
2018-03-19 09:27:15 -07:00
return false ;
2018-03-13 17:17:28 -07:00
}
2018-03-26 16:29:23 -07:00
private void AlignAxis ( int axis , Align align , double alignTo , double offset , IObject3D item )
2018-03-13 17:17:28 -07:00
{
2018-03-19 09:27:15 -07:00
var aabb = item . GetAxisAlignedBoundingBox ( ) ;
var translate = Vector3 . Zero ;
switch ( align )
2018-03-13 17:17:28 -07:00
{
2018-03-19 09:27:15 -07:00
case Align . Min :
2019-01-11 16:49:34 -08:00
translate [ axis ] = alignTo - aabb . MinXYZ [ axis ] + offset ;
2018-03-19 09:27:15 -07:00
break ;
case Align . Center :
translate [ axis ] = alignTo - aabb . Center [ axis ] + offset ;
break ;
case Align . Max :
2019-01-11 16:49:34 -08:00
translate [ axis ] = alignTo - aabb . MaxXYZ [ axis ] + offset ;
2018-03-19 09:27:15 -07:00
break ;
2019-02-01 08:31:55 -08:00
case Align . Origin :
// find the origin in world space of the item
var itemOrigin = Vector3Ex . Transform ( Vector3 . Zero , item . WorldMatrix ( ) ) ;
translate [ axis ] = alignTo - itemOrigin [ axis ] + offset ;
break ;
2018-03-13 17:17:28 -07:00
}
2018-03-19 09:27:15 -07:00
item . Translate ( translate ) ;
2018-03-13 17:17:28 -07:00
}
2018-03-19 09:27:15 -07:00
private double GetAlignToOffset ( List < Aabb > currentChildrenBounds , int axis , Align alignTo )
2018-03-13 17:17:28 -07:00
{
2018-03-19 09:27:15 -07:00
switch ( alignTo )
2018-03-13 17:17:28 -07:00
{
2018-03-19 09:27:15 -07:00
case Align . Min :
2019-01-11 16:49:34 -08:00
return currentChildrenBounds [ AnchorObjectIndex ] . MinXYZ [ axis ] ;
2018-03-13 17:17:28 -07:00
2018-03-19 09:27:15 -07:00
case Align . Center :
2018-08-13 13:48:10 -07:00
return currentChildrenBounds [ AnchorObjectIndex ] . Center [ axis ] ;
2018-03-19 09:27:15 -07:00
case Align . Max :
2019-01-11 16:49:34 -08:00
return currentChildrenBounds [ AnchorObjectIndex ] . MaxXYZ [ axis ] ;
2018-03-19 09:27:15 -07:00
2019-02-01 08:31:55 -08:00
case Align . Origin :
return Vector3Ex . Transform ( Vector3 . Zero , AnchorObject . WorldMatrix ( ) ) [ axis ] ;
2018-03-19 09:27:15 -07:00
default :
throw new NotImplementedException ( ) ;
}
2018-03-13 17:17:28 -07:00
}
}
2018-01-29 13:50:55 -08:00
}