public override bool FilterHandle(BaseBoxTool.ResizeHandle handle) { return handle == BaseBoxTool.ResizeHandle.Bottom || handle == BaseBoxTool.ResizeHandle.Left || handle == BaseBoxTool.ResizeHandle.Top || handle == BaseBoxTool.ResizeHandle.Right; }
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) { 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)); }
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) { 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; }
public abstract Matrix4? GetTransformationMatrix(Viewport2D viewport, ViewportEvent mouseEventArgs, BaseBoxTool.BoxState state, Document doc, IEnumerable<Widget> activeWidgets);
public abstract bool FilterHandle(BaseBoxTool.ResizeHandle handle);
public abstract Cursor CursorForHandle(BaseBoxTool.ResizeHandle handle);
public abstract Matrix4? GetTransformationMatrix(Viewport2D viewport, ViewportEvent mouseEventArgs, BaseBoxTool.BoxState state, Document doc);
public override bool FilterHandle(BaseBoxTool.ResizeHandle handle) { return true; }
public override Cursor CursorForHandle(BaseBoxTool.ResizeHandle handle) { return null; }
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); }
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); 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(); } return SnapBoxCoordinatesIfNeeded(viewport, state, document, cstart, cend); }
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 Cursor CursorForHandle(BaseBoxTool.ResizeHandle handle) { return (handle == BaseBoxTool.ResizeHandle.Top || handle == BaseBoxTool.ResizeHandle.Bottom) ? Cursors.SizeWE : Cursors.SizeNS; }
public override Cursor CursorForHandle(BaseBoxTool.ResizeHandle handle) { return SledgeCursors.RotateCursor; }