private Coordinate GetResizeDistance(Viewport2D viewport, ViewportEvent e, BaseBoxTool.BoxState state, Document document) { var origin = GetResizeOrigin(viewport, state, document); if (origin == null) { return(null); } var before = state.MoveStart; var after = viewport.ScreenToWorld(e.X, viewport.Height - e.Y); return(SnapIfNeeded(origin + after - before, document) - origin); }
private Coordinate GetResizeOrigin(Viewport2D viewport, BaseBoxTool.BoxState state, Document document) { if (state.Action != BaseBoxTool.BoxAction.Resizing || state.Handle != BaseBoxTool.ResizeHandle.Center) { return(null); } var sel = document.Selection.GetSelectedParents().ToList(); if (sel.Count == 1 && sel[0] is Entity && !sel[0].HasChildren) { return(viewport.Flatten(((Entity)sel[0]).Origin)); } var st = viewport.Flatten(state.PreTransformBoxStart); var ed = viewport.Flatten(state.PreTransformBoxEnd); var points = new[] { st, ed, new Coordinate(st.X, ed.Y, 0), new Coordinate(ed.X, st.Y, 0) }; return(points.OrderBy(x => (state.MoveStart - x).LengthSquared()).First()); }
private static Coordinate GetOriginForTransform(Viewport2D viewport, BaseBoxTool.BoxState state) { decimal x = 0; decimal y = 0; var cstart = viewport.Flatten(state.PreTransformBoxStart); var cend = viewport.Flatten(state.PreTransformBoxEnd); switch (state.Handle) { case BaseBoxTool.ResizeHandle.TopLeft: case BaseBoxTool.ResizeHandle.Top: case BaseBoxTool.ResizeHandle.TopRight: case BaseBoxTool.ResizeHandle.Left: case BaseBoxTool.ResizeHandle.Right: y = cstart.Y; break; case BaseBoxTool.ResizeHandle.BottomLeft: case BaseBoxTool.ResizeHandle.Bottom: case BaseBoxTool.ResizeHandle.BottomRight: y = cend.Y; break; } switch (state.Handle) { case BaseBoxTool.ResizeHandle.Top: case BaseBoxTool.ResizeHandle.TopRight: case BaseBoxTool.ResizeHandle.Right: case BaseBoxTool.ResizeHandle.BottomRight: case BaseBoxTool.ResizeHandle.Bottom: x = cstart.X; break; case BaseBoxTool.ResizeHandle.TopLeft: case BaseBoxTool.ResizeHandle.Left: case BaseBoxTool.ResizeHandle.BottomLeft: x = cend.X; break; } return(viewport.Expand(new Coordinate(x, y, 0))); }
public override Matrix4?GetTransformationMatrix(Viewport2D viewport, ViewportEvent e, BaseBoxTool.BoxState state, Document doc, IEnumerable <Widget> activeWidgets) { var origin = viewport.ZeroUnusedCoordinate((state.PreTransformBoxStart + state.PreTransformBoxEnd) / 2); var rw = activeWidgets.OfType <RotationWidget>().FirstOrDefault(); if (rw != null) { origin = rw.GetPivotPoint(); } var forigin = viewport.Flatten(origin); var origv = (state.MoveStart - forigin).Normalise(); var newv = (viewport.ScreenToWorld(e.X, viewport.Height - e.Y) - forigin).Normalise(); var angle = DMath.Acos(Math.Max(-1, Math.Min(1, origv.Dot(newv)))); if ((origv.Cross(newv).Z < 0)) { angle = 2 * DMath.PI - angle; } var shf = KeyboardState.Shift; var def = Select.RotationStyle; var snap = (def == RotationStyle.SnapOnShift && shf) || (def == RotationStyle.SnapOffShift && !shf); if (snap) { var deg = angle * (180 / DMath.PI); var rnd = Math.Round(deg / 15) * 15; angle = rnd * (DMath.PI / 180); } Matrix4 rotm; if (viewport.Direction == Viewport2D.ViewDirection.Top) { rotm = Matrix4.CreateRotationZ((float)angle); } else if (viewport.Direction == Viewport2D.ViewDirection.Front) { rotm = Matrix4.CreateRotationX((float)angle); } else { rotm = Matrix4.CreateRotationY((float)-angle); // The Y axis rotation goes in the reverse direction for whatever reason } var mov = Matrix4.CreateTranslation((float)-origin.X, (float)-origin.Y, (float)-origin.Z); var rot = Matrix4.Mult(mov, rotm); return(Matrix4.Mult(rot, Matrix4.Invert(mov))); }
public override Matrix4?GetTransformationMatrix(Viewport2D viewport, ViewportEvent e, BaseBoxTool.BoxState state, Document doc, IEnumerable <Widget> activeWidgets) { var shearUpDown = state.Handle == BaseBoxTool.ResizeHandle.Left || state.Handle == BaseBoxTool.ResizeHandle.Right; var shearTopRight = state.Handle == BaseBoxTool.ResizeHandle.Top || state.Handle == BaseBoxTool.ResizeHandle.Right; var nsmd = viewport.ScreenToWorld(e.X, viewport.Height - e.Y) - state.MoveStart; var mouseDiff = SnapIfNeeded(nsmd, doc); if (KeyboardState.Shift) { mouseDiff = doc.Snap(nsmd, doc.Map.GridSpacing / 2); } var relative = viewport.Flatten(state.PreTransformBoxEnd - state.PreTransformBoxStart); var shearOrigin = (shearTopRight) ? state.PreTransformBoxStart : state.PreTransformBoxEnd; var shearAmount = new Coordinate(mouseDiff.X / relative.Y, mouseDiff.Y / relative.X, 0); if (!shearTopRight) { shearAmount *= -1; } var shearMatrix = Matrix4.Identity; var sax = (float)shearAmount.X; var say = (float)shearAmount.Y; switch (viewport.Direction) { case Viewport2D.ViewDirection.Top: if (shearUpDown) { shearMatrix.M12 = say; } else { shearMatrix.M21 = sax; } break; case Viewport2D.ViewDirection.Front: if (shearUpDown) { shearMatrix.M23 = say; } else { shearMatrix.M32 = sax; } break; case Viewport2D.ViewDirection.Side: if (shearUpDown) { shearMatrix.M13 = say; } else { shearMatrix.M31 = sax; } break; } var stran = Matrix4.CreateTranslation((float)-shearOrigin.X, (float)-shearOrigin.Y, (float)-shearOrigin.Z); var shear = Matrix4.Mult(stran, shearMatrix); return(Matrix4.Mult(shear, Matrix4.Invert(stran))); }
public abstract Matrix4?GetTransformationMatrix(Viewport2D viewport, ViewportEvent mouseEventArgs, BaseBoxTool.BoxState state, Document doc, IEnumerable <Widget> activeWidgets);
private Tuple <Coordinate, Coordinate> GetBoxCoordinatesForSelectionResize(Viewport2D viewport, ViewportEvent e, BaseBoxTool.BoxState state, Document document) { if (state.Action != BaseBoxTool.BoxAction.Resizing) { return(Tuple.Create(state.BoxStart, state.BoxEnd)); } var now = SnapIfNeeded(viewport.ScreenToWorld(e.X, viewport.Height - e.Y), document); var cstart = viewport.Flatten(state.BoxStart); var cend = viewport.Flatten(state.BoxEnd); // Proportional scaling var ostart = viewport.Flatten(state.PreTransformBoxStart ?? Coordinate.Zero); var oend = viewport.Flatten(state.PreTransformBoxEnd ?? Coordinate.Zero); var owidth = oend.X - ostart.X; var oheight = oend.Y - ostart.Y; var proportional = KeyboardState.Ctrl && state.Action == BaseBoxTool.BoxAction.Resizing && owidth != 0 && oheight != 0; switch (state.Handle) { case BaseBoxTool.ResizeHandle.TopLeft: cstart.X = Math.Min(now.X, cend.X - 1); cend.Y = Math.Max(now.Y, cstart.Y + 1); break; case BaseBoxTool.ResizeHandle.Top: cend.Y = Math.Max(now.Y, cstart.Y + 1); break; case BaseBoxTool.ResizeHandle.TopRight: cend.X = Math.Max(now.X, cstart.X + 1); cend.Y = Math.Max(now.Y, cstart.Y + 1); break; case BaseBoxTool.ResizeHandle.Left: cstart.X = Math.Min(now.X, cend.X - 1); break; case BaseBoxTool.ResizeHandle.Center: var cdiff = cend - cstart; cstart = viewport.Flatten(state.PreTransformBoxStart) + now - SnapIfNeeded(state.MoveStart, document); cend = cstart + cdiff; break; case BaseBoxTool.ResizeHandle.Right: cend.X = Math.Max(now.X, cstart.X + 1); break; case BaseBoxTool.ResizeHandle.BottomLeft: cstart.X = Math.Min(now.X, cend.X - 1); cstart.Y = Math.Min(now.Y, cend.Y - 1); break; case BaseBoxTool.ResizeHandle.Bottom: cstart.Y = Math.Min(now.Y, cend.Y - 1); break; case BaseBoxTool.ResizeHandle.BottomRight: cend.X = Math.Max(now.X, cstart.X + 1); cstart.Y = Math.Min(now.Y, cend.Y - 1); break; default: throw new ArgumentOutOfRangeException(); } if (proportional) { var nwidth = cend.X - cstart.X; var nheight = cend.Y - cstart.Y; var mult = Math.Max(nwidth / owidth, nheight / oheight); var pwidth = owidth * mult; var pheight = oheight * mult; var wdiff = pwidth - nwidth; var hdiff = pheight - nheight; switch (state.Handle) { case BaseBoxTool.ResizeHandle.TopLeft: cstart.X -= wdiff; cend.Y += hdiff; break; case BaseBoxTool.ResizeHandle.TopRight: cend.X += wdiff; cend.Y += hdiff; break; case BaseBoxTool.ResizeHandle.BottomLeft: cstart.X -= wdiff; cstart.Y -= hdiff; break; case BaseBoxTool.ResizeHandle.BottomRight: cend.X += wdiff; cstart.Y -= hdiff; break; } } return(SnapBoxCoordinatesIfNeeded(viewport, state, document, cstart, cend)); }
public override Matrix4?GetTransformationMatrix(Viewport2D viewport, ViewportEvent e, BaseBoxTool.BoxState state, Document doc, IEnumerable <Widget> activeWidgets) { var coords = GetBoxCoordinatesForSelectionResize(viewport, e, state, doc); state.BoxStart = coords.Item1; state.BoxEnd = coords.Item2; Matrix4 resizeMatrix; if (state.Handle == BaseBoxTool.ResizeHandle.Center) { var movement = state.BoxStart - state.PreTransformBoxStart; resizeMatrix = Matrix4.CreateTranslation((float)movement.X, (float)movement.Y, (float)movement.Z); } else { var resize = (state.PreTransformBoxStart - state.BoxStart) + (state.BoxEnd - state.PreTransformBoxEnd); resize = resize.ComponentDivide(state.PreTransformBoxEnd - state.PreTransformBoxStart); resize += new Coordinate(1, 1, 1); var offset = -GetOriginForTransform(viewport, state); var trans = Matrix4.CreateTranslation((float)offset.X, (float)offset.Y, (float)offset.Z); var scale = Matrix4.Mult(trans, Matrix4.Scale((float)resize.X, (float)resize.Y, (float)resize.Z)); resizeMatrix = Matrix4.Mult(scale, Matrix4.Invert(trans)); } return(resizeMatrix); }
private Tuple <Coordinate, Coordinate> SnapBoxCoordinatesIfNeeded(Viewport2D viewport, BaseBoxTool.BoxState state, Document document, Coordinate start, Coordinate end) { if (state.Action == BaseBoxTool.BoxAction.Resizing && state.Handle == BaseBoxTool.ResizeHandle.Center) { // Pick the corner to snap var ms = state.MoveStart; var pts = viewport.Flatten(state.PreTransformBoxStart); var pte = viewport.Flatten(state.PreTransformBoxEnd); var ss = SnapIfNeeded(start, document); var se = SnapIfNeeded(end, document); var middle = (pts + pte) / 2; var delta = ss - start; if (ms.Y > middle.Y) { // Top delta.Y = se.Y - end.Y; } if (ms.X > middle.X) { // Right delta.X = se.X - end.X; } start += delta; end += delta; } var cstart = viewport.Expand(start) + viewport.GetUnusedCoordinate(state.BoxStart); var cend = viewport.Expand(end) + viewport.GetUnusedCoordinate(state.BoxEnd); return(Tuple.Create(cstart, cend)); }