public static void AlignSelectionToAxis(Axis axis) { int axisIndex = (int)axis; List <GameObject> allSelectedObjects = ObjectSelection.Get().GetAllSelectedGameObjects(); List <GameObject> selectedParents = GameObjectExtensions.GetParents(allSelectedObjects); if (selectedParents.Count == 0) { return; } float average = 0.0f; foreach (var parent in selectedParents) { average += parent.transform.position[axisIndex]; } average /= selectedParents.Count; GameObjectExtensions.RecordObjectTransformsForUndo(selectedParents); foreach (var parent in selectedParents) { Transform parentTransform = parent.transform; Vector3 alignedPosition = parentTransform.position; alignedPosition[axisIndex] = average; parentTransform.position = alignedPosition; } }
private void Rotate(float angle, Vector3 axis) { var selectedParents = GameObjectExtensions.GetParents(_selectedObjects.HashSet); GameObjectExtensions.RecordObjectTransformsForUndo(selectedParents); if (Settings.RotateAroundSelectionCenter) { Vector3 selectionCenter = GetWorldCenter(); foreach (var parent in selectedParents) { parent.RotateHierarchyBoxAroundPoint(angle, axis, selectionCenter); } } else { foreach (var parent in selectedParents) { Box worldAABB = parent.GetHierarchyWorldBox(); if (worldAABB.IsValid()) { parent.RotateHierarchyBoxAroundPoint(angle, axis, worldAABB.Center); } } } }
private void SetWorldRotation(Quaternion rotation) { var selectedParents = GameObjectExtensions.GetParents(_selectedObjects.HashSet); GameObjectExtensions.RecordObjectTransformsForUndo(selectedParents); foreach (var parent in selectedParents) { parent.transform.rotation = rotation; } }
public override void RenderHandles(TransformGizmoPivotPoint transformPivotPoint) { if (CanTransformObjects()) { Vector3 newScaleAccumulatedByGizmoInteraction = Handles.ScaleHandle(_scaleAccumulatedByGizmoInteraction, _worldPosition, _worldRotation, HandleUtility.GetHandleSize(_worldPosition)); if (newScaleAccumulatedByGizmoInteraction != _scaleAccumulatedByGizmoInteraction) { GameObjectExtensions.RecordObjectTransformsForUndo(_gameObjectsWhichCanBeTransformed); List <GameObject> topParents = GameObjectExtensions.GetTopParentsFromGameObjectCollection(_gameObjectsWhichCanBeTransformed); Vector3 scaleFactor = CalculateScaleFactorUsedToScaleObjects(newScaleAccumulatedByGizmoInteraction); ScaleObjectsBySpecifiedPivotPoint(transformPivotPoint, scaleFactor, topParents); _scaleAccumulatedByGizmoInteraction = newScaleAccumulatedByGizmoInteraction; GizmoTransformedObjectsMessage.SendToInterestedListeners(this); } } }
public override void RenderHandles(TransformGizmoPivotPoint transformPivotPoint) { if (CanTransformObjects()) { Vector3 newGizmoWorldPosition = Handles.PositionHandle(_worldPosition, _worldRotation); if (newGizmoWorldPosition != _worldPosition) { GameObjectExtensions.RecordObjectTransformsForUndo(_targetObjects); List <GameObject> topParents = GameObjectExtensions.GetParents(_targetObjects); MoveObjects(newGizmoWorldPosition, topParents); UndoEx.RecordForToolAction(this); _worldPosition = newGizmoWorldPosition; GizmoTransformedObjectsMessage.SendToInterestedListeners(this); } } }
public override void RenderHandles(TransformGizmoPivotPoint transformPivotPoint) { if (CanTransformObjects()) { Quaternion newWorldRotationAccumulatedByGizmoInteraction = Handles.RotationHandle(_worldRotation, _worldPosition); if (newWorldRotationAccumulatedByGizmoInteraction.eulerAngles != _worldRotation.eulerAngles) { GameObjectExtensions.RecordObjectTransformsForUndo(_targetObjects); List <GameObject> topParents = GameObjectExtensions.GetParents(_targetObjects); Quaternion rotationAmount = CalculateRotationAmount(newWorldRotationAccumulatedByGizmoInteraction); RotateObjectsAroundSpecifiedPivotPoint(transformPivotPoint, rotationAmount, topParents); UndoEx.RecordForToolAction(this); _worldRotation = newWorldRotationAccumulatedByGizmoInteraction; GizmoTransformedObjectsMessage.SendToInterestedListeners(this); } } }
public void UpdateForMouseMovement() { if (_state == State.Inactive) { return; } if (MouseButtonStates.Instance.IsMouseButtonDown(MouseButton.Left)) { _state = State.Snap; } else { _state = State.SelectPivot; } if (_state == State.SelectPivot && _selectedParents.Count != 0) { Camera camera = SceneViewCamera.Camera; Vector2 mousePos = Event.current.InvMousePos(camera); _isPivotAvailable = false; float minDistanceSq = float.MaxValue; foreach (var parent in _selectedParents) { if (parent == null) { continue; } OrientedBox worldOOBB = parent.GetHierarchyWorldOrientedBox(); if (worldOOBB.IsValid()) { List <Vector3> centerAndCorners = worldOOBB.GetCenterAndCornerPoints(); List <Vector2> oobbScreenPts = Vector2Extensions.GetScreenPoints(centerAndCorners, camera); for (int ptIndex = 0; ptIndex < centerAndCorners.Count; ++ptIndex) { Vector3 worldPt = centerAndCorners[ptIndex]; Vector2 screenPt = oobbScreenPts[ptIndex]; float distSq = (mousePos - screenPt).sqrMagnitude; if (distSq < minDistanceSq) { minDistanceSq = distSq; _pivot = worldPt; _isPivotAvailable = true; } } } } } else if (_state == State.Snap && _isPivotAvailable) { GameObjectExtensions.RecordObjectTransformsForUndo(_selectedParents); MouseCursorRayHit cursorHit = MouseCursor.Instance.GetCursorRayHitForGridCell(); if (cursorHit.WasACellHit) { Camera camera = SceneViewCamera.Camera; Vector2 mousePos = Event.current.InvMousePos(camera); GridCellRayHit cellRayHit = cursorHit.GridCellRayHit; Vector3 snapDestination = Vector3Extensions.GetClosestPointToPoint(cellRayHit.HitCell.Quad.GetCenterAndCornerPoints(), cellRayHit.HitPoint); Vector3 moveVector = snapDestination - _pivot; foreach (var parent in _selectedParents) { if (parent != null) { parent.transform.position += moveVector; } } _pivot = snapDestination; ObjectSelection.Get().ObjectSelectionTransformGizmoSystem.OnObjectSelectionUpdated(); } } }
public void Update() { if (IsActive) { _currentCursorRayHit = GetCursorRayHit(); if (!_currentCursorRayHit.WasAnythingHit) { return; } if (_currentCursorRayHit.WasAnObjectHit) { GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects); GameObjectRayHit objectRayHit = _currentCursorRayHit.ClosestObjectRayHit; _surfaceHitPoint = objectRayHit.HitPoint; foreach (var grabbedObject in _grabbedObjects) { if (grabbedObject == null) { continue; } Transform objectTransform = grabbedObject.transform; objectTransform.position = objectRayHit.HitPoint + _objectToPivotDir[grabbedObject]; if (objectRayHit.WasTerrainHit) { Ray ray = new Ray(grabbedObject.GetHierarchyWorldOrientedBox().Center + Vector3.up, -Vector3.up); GameObjectRayHit sitPointHit = null; if (objectRayHit.HitObject.RaycastTerrainReverseIfFail(ray, out sitPointHit)) { if (_grabSettings.AlignAxis) { AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, sitPointHit.HitNormal); } grabbedObject.PlaceHierarchyOnPlane(new Plane(sitPointHit.HitNormal, sitPointHit.HitPoint)); if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis) { objectTransform.position += _grabSettings.OffsetFromSurface * sitPointHit.HitNormal; } if (_grabSettings.EmbedInSurfaceWhenNoAlign && !_grabSettings.AlignAxis) { grabbedObject.EmbedInSurfaceByVertex(-Vector3.up, objectRayHit.HitObject); } } } else if (objectRayHit.WasMeshHit) { Ray ray = new Ray(grabbedObject.GetHierarchyWorldOrientedBox().Center + objectRayHit.HitNormal * 2.0f, -objectRayHit.HitNormal); GameObjectRayHit sitPointHit = null; if (objectRayHit.HitObject.RaycastMeshReverseIfFail(ray, out sitPointHit)) { if (_grabSettings.AlignAxis) { AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, sitPointHit.HitNormal); } grabbedObject.PlaceHierarchyOnPlane(new Plane(sitPointHit.HitNormal, sitPointHit.HitPoint)); if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis) { objectTransform.position += _grabSettings.OffsetFromSurface * sitPointHit.HitNormal; } if (_grabSettings.EmbedInSurfaceWhenNoAlign && !_grabSettings.AlignAxis) { grabbedObject.EmbedInSurfaceByVertex(-sitPointHit.HitNormal, objectRayHit.HitObject); } } } } } else if (_currentCursorRayHit.WasACellHit) { GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects); GridCellRayHit cellRayHit = _currentCursorRayHit.GridCellRayHit; _surfaceHitPoint = cellRayHit.HitPoint; foreach (var grabbedObject in _grabbedObjects) { if (grabbedObject == null) { continue; } Transform objectTransform = grabbedObject.transform; objectTransform.position = cellRayHit.HitPoint + _objectToPivotDir[grabbedObject]; if (_grabSettings.AlignAxis) { AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, cellRayHit.HitNormal); } grabbedObject.PlaceHierarchyOnPlane(new Plane(cellRayHit.HitNormal, cellRayHit.HitPoint)); if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis) { objectTransform.position += _grabSettings.OffsetFromSurface * cellRayHit.HitNormal; } } } } }
public void UpdateOnMouseMove() { if (_isActive) { MouseCursorRayHit cursorRayHit = GetCursorRayHit(); if (cursorRayHit == null || !cursorRayHit.WasAnythingHit) { return; } Vector3 hitPoint = Vector3.zero; Vector3 hitNormal = Vector3.zero; if (!cursorRayHit.WasAnObjectHit && cursorRayHit.WasACellHit) { hitPoint = cursorRayHit.GridCellRayHit.HitPoint; hitNormal = cursorRayHit.GridCellRayHit.HitNormal; } else if (cursorRayHit.WasAnObjectHit && !cursorRayHit.WasACellHit) { hitPoint = cursorRayHit.ClosestObjectRayHit.HitPoint; hitNormal = cursorRayHit.ClosestObjectRayHit.HitNormal; } else if (cursorRayHit.WasAnObjectHit && cursorRayHit.WasACellHit) { if (cursorRayHit.ClosestObjectRayHit.HitEnter < cursorRayHit.GridCellRayHit.HitEnter) { hitPoint = cursorRayHit.ClosestObjectRayHit.HitPoint; hitNormal = cursorRayHit.ClosestObjectRayHit.HitNormal; } else { hitPoint = cursorRayHit.GridCellRayHit.HitPoint; hitNormal = cursorRayHit.GridCellRayHit.HitNormal; } } Plane hitPlane = new Plane(hitNormal, hitPoint); Box selectionWorldAABB = ObjectSelection.Get().GetWorldBox(); if (selectionWorldAABB.IsInvalid()) { return; } Vector3 oldCenter = selectionWorldAABB.Center; selectionWorldAABB.Center = hitPoint; selectionWorldAABB.MoveInFrontOfPlane(hitPlane); Vector3 moveVector = selectionWorldAABB.Center - oldCenter; float snapEps = ObjectSelection.Get().Settings.Object2ObjectSnapSettings.SnapEps; GameObjectExtensions.RecordObjectTransformsForUndo(_selectedParents); foreach (var parent in _selectedParents) { parent.transform.position += moveVector; } var ignoreObjects = new List <GameObject>(_allSelectedObjects); ignoreObjects.AddRange(ObjectSnapping.Get().ObjectSnapMask.ObjectCollectionMask.GetAllMaskedGameObjects()); Object2ObjectSnap.Snap(_selectedParents, snapEps, ignoreObjects); } }
public void Update() { if (IsActive) { if (AllShortcutCombos.Instance.GrabRotateSelection.IsActive()) { _state = State.Rotating; } else if (AllShortcutCombos.Instance.GrabScaleSelection.IsActive()) { if (_state != State.Scaling) { _objectToWorldScale.Clear(); foreach (var grabbedObject in _grabbedObjects) { if (grabbedObject != null) { _objectToWorldScale.Add(grabbedObject, grabbedObject.transform.lossyScale); } } _cursorPosAtScaleBegin = MouseCursor.Instance.Position; _state = State.Scaling; } } else { // Need to reset the anchor relationships because the cursor was moved without // the objects following it. if (_state == State.Rotating || _state == State.Scaling) { _objectToPivotDir.Clear(); foreach (var grabbedObject in _grabbedObjects) { if (grabbedObject != null) { _objectToPivotDir.Add(grabbedObject, grabbedObject.transform.position - _surfaceHitPoint); } } } _state = State.Moving; } _currentCursorRayHit = GetCursorRayHit(); if (!_currentCursorRayHit.WasAnythingHit) { return; } if (_currentCursorRayHit.WasAnythingHit) { if (_currentCursorRayHit.WasAnObjectHit) { _surfaceHitPoint = _currentCursorRayHit.ClosestObjectRayHit.HitPoint; } else { _surfaceHitPoint = _currentCursorRayHit.GridCellRayHit.HitPoint; } } if (_state == State.Moving || _objectToSurfaceInfo.Count == 0) { if (_currentCursorRayHit.WasAnObjectHit) { GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects); GameObjectRayHit objectRayHit = _currentCursorRayHit.ClosestObjectRayHit; foreach (var grabbedObject in _grabbedObjects) { if (grabbedObject == null) { continue; } Transform objectTransform = grabbedObject.transform; objectTransform.position = objectRayHit.HitPoint + _objectToPivotDir[grabbedObject]; if (objectRayHit.WasTerrainHit) { Ray ray = new Ray(grabbedObject.GetHierarchyWorldOrientedBox().Center + Vector3.up, -Vector3.up); GameObjectRayHit sitPointHit = null; if (objectRayHit.HitObject.RaycastTerrainReverseIfFail(ray, out sitPointHit)) { Plane surfacePlane = new Plane(sitPointHit.HitNormal, sitPointHit.HitPoint); if (_grabSettings.AlignAxis) { AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, sitPointHit.HitNormal); } grabbedObject.PlaceHierarchyOnPlane(surfacePlane); if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis) { objectTransform.position += _grabSettings.OffsetFromSurface * sitPointHit.HitNormal; } if (_grabSettings.EmbedInSurfaceWhenNoAlign && !_grabSettings.AlignAxis) { grabbedObject.EmbedInSurfaceByVertex(-Vector3.up, objectRayHit.HitObject); } ObjectSurfaceInfo surfaceInfo = new ObjectSurfaceInfo(); surfaceInfo.SurfacePlane = surfacePlane; surfaceInfo.SitPoint = sitPointHit.HitPoint; SetObjectSurfaceInfo(grabbedObject, surfaceInfo); } } else if (objectRayHit.WasMeshHit) { Ray ray = new Ray(grabbedObject.GetHierarchyWorldOrientedBox().Center + objectRayHit.HitNormal * 2.0f, -objectRayHit.HitNormal); GameObjectRayHit sitPointHit = null; if (objectRayHit.HitObject.RaycastMeshReverseIfFail(ray, out sitPointHit)) { Plane surfacePlane = new Plane(sitPointHit.HitNormal, sitPointHit.HitPoint); if (_grabSettings.AlignAxis) { AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, sitPointHit.HitNormal); } grabbedObject.PlaceHierarchyOnPlane(surfacePlane); if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis) { objectTransform.position += _grabSettings.OffsetFromSurface * sitPointHit.HitNormal; } if (_grabSettings.EmbedInSurfaceWhenNoAlign && !_grabSettings.AlignAxis) { grabbedObject.EmbedInSurfaceByVertex(-sitPointHit.HitNormal, objectRayHit.HitObject); } ObjectSurfaceInfo surfaceInfo = new ObjectSurfaceInfo(); surfaceInfo.SurfacePlane = surfacePlane; surfaceInfo.SitPoint = sitPointHit.HitPoint; SetObjectSurfaceInfo(grabbedObject, surfaceInfo); } } } } else if (_currentCursorRayHit.WasACellHit) { GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects); GridCellRayHit cellRayHit = _currentCursorRayHit.GridCellRayHit; foreach (var grabbedObject in _grabbedObjects) { if (grabbedObject == null) { continue; } Transform objectTransform = grabbedObject.transform; objectTransform.position = cellRayHit.HitPoint + _objectToPivotDir[grabbedObject]; Plane surfacePlane = new Plane(cellRayHit.HitNormal, cellRayHit.HitPoint); Vector3 sitPoint = surfacePlane.ProjectPoint(grabbedObject.GetWorldOrientedBox().Center); if (_grabSettings.AlignAxis) { AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, cellRayHit.HitNormal); } grabbedObject.PlaceHierarchyOnPlane(surfacePlane); if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis) { objectTransform.position += _grabSettings.OffsetFromSurface * cellRayHit.HitNormal; } ObjectSurfaceInfo surfaceInfo = new ObjectSurfaceInfo(); surfaceInfo.SurfacePlane = surfacePlane; surfaceInfo.SitPoint = sitPoint; SetObjectSurfaceInfo(grabbedObject, surfaceInfo); } } } else if (_state == State.Rotating) { GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects); float rotationSensitivity = _grabSettings.RotationSensitivity; foreach (var grabbedObject in _grabbedObjects) { if (!_objectToSurfaceInfo.ContainsKey(grabbedObject)) { continue; } var surfaceInfo = _objectToSurfaceInfo[grabbedObject]; OrientedBox worldOOBB = grabbedObject.GetHierarchyWorldOrientedBox(); grabbedObject.RotateHierarchyBoxAroundPoint(MouseCursor.Instance.OffsetSinceLastMouseMove.x * rotationSensitivity, _grabSettings.AlignAxis ? surfaceInfo.SurfacePlane.normal : Vector3.up, worldOOBB.Center); } } else if (_state == State.Scaling) { GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects); Vector2 currentCursorPos = MouseCursor.Instance.Position; Vector2 cursorOffsetFromScaleBegin = currentCursorPos - _cursorPosAtScaleBegin; float scaleFactor = 1.0f + _grabSettings.ScaleSensitivity * cursorOffsetFromScaleBegin.x; foreach (var grabbedObject in _grabbedObjects) { if (!_objectToSurfaceInfo.ContainsKey(grabbedObject) || !_objectToWorldScale.ContainsKey(grabbedObject)) { continue; } var surfaceInfo = _objectToSurfaceInfo[grabbedObject]; grabbedObject.SetHierarchyWorldScaleByPivotPoint(_objectToWorldScale[grabbedObject] * scaleFactor, surfaceInfo.SitPoint); } } } }
public override void RenderHandles(TransformGizmoPivotPoint transformPivotPoint) { Box targetWorldAABB = Box.FromObjectWorldAABB(_targetObjects); //Color[] axesColors = new Color[] { Handles.xAxisColor, Handles.xAxisColor, Handles.yAxisColor, Handles.yAxisColor, Handles.zAxisColor, Handles.zAxisColor }; //Vector3[] axesDirs = new Vector3[] { Vector3.right, -Vector3.right, Vector3.up, -Vector3.up, Vector3.forward, -Vector3.forward }; //float[] snapValues = new float[] { targetWorldAABB.Size.x, targetWorldAABB.Size.x, targetWorldAABB.Size.y, targetWorldAABB.Size.y, targetWorldAABB.Size.z, targetWorldAABB.Size.z }; Color[] axesColors = new Color[] { Handles.xAxisColor, Handles.yAxisColor, Handles.zAxisColor }; Vector3[] axesDirs = new Vector3[] { Vector3.right, Vector3.up, Vector3.forward }; float[] snapValues = new float[] { targetWorldAABB.Size.x *_snapSteps[0], targetWorldAABB.Size.y *_snapSteps[1], targetWorldAABB.Size.z *_snapSteps[2] }; Vector3 oldPosition = WorldPosition; for (int axisIndex = 0; axisIndex < 3; ++axisIndex) { Handles.color = axesColors[axisIndex]; Vector3 newGizmoPosition = Handles.Slider(oldPosition, axesDirs[axisIndex], HandleUtility.GetHandleSize(oldPosition), Handles.ArrowHandleCap, snapValues[axisIndex]); if (newGizmoPosition != oldPosition) { Vector3 moveOffset = (newGizmoPosition - oldPosition); WorldPosition = newGizmoPosition; oldPosition = newGizmoPosition; if (Event.current.control) { float absNumGroups = Mathf.Abs(moveOffset[axisIndex] / snapValues[axisIndex]); float absFractional = absNumGroups - (int)absNumGroups; int numCloneGroups = Mathf.FloorToInt(absNumGroups); if (Mathf.Abs(absFractional - 1.0f) < 1e-4f) { ++numCloneGroups; } for (int cloneGroupIndex = 0; cloneGroupIndex < numCloneGroups; ++cloneGroupIndex) { var clonedRoots = Octave3DWorldBuilder.ActiveInstance.GetRoots(ObjectActions.Duplicate(_targetObjects)); ObjectHierarchyRootsWerePlacedInSceneMessage.SendToInterestedListeners(clonedRoots, ObjectHierarchyRootsWerePlacedInSceneMessage.PlacementType.Selection); ObjectHierarchyRootsWerePlacedInSceneMessage.SendToInterestedListeners(ObjectSelection.Get().Mirror.MirrorGameObjectHierarchies(clonedRoots), ObjectHierarchyRootsWerePlacedInSceneMessage.PlacementType.Selection); if (cloneGroupIndex != 0) { Vector3 offset = axesDirs[axisIndex] * snapValues[axisIndex] * cloneGroupIndex *Mathf.Sign(moveOffset[axisIndex]); foreach (var root in clonedRoots) { root.transform.position += offset; } } } } GameObjectExtensions.RecordObjectTransformsForUndo(_targetObjects); var targetParents = GameObjectExtensions.GetParents(_targetObjects); foreach (var parent in targetParents) { parent.transform.position += moveOffset; } } } Handles.BeginGUI(); GUI.BeginGroup(new Rect(0.0f, -15.0f, 200.0f, 200.0f)); var content = new GUIContent(); string[] snapStepLabels = new string[] { "Snap step X", "Snap step Y", "Snap step Z" }; for (int axisIndex = 0; axisIndex < 3; ++axisIndex) { EditorGUILayout.BeginHorizontal(); content.text = snapStepLabels[axisIndex]; EditorGUILayout.LabelField(content, GUILayout.Width(80.0f)); int newInt = EditorGUILayout.IntField("", _snapSteps[axisIndex], GUILayout.Width(50.0f)); if (newInt != _snapSteps[axisIndex]) { UndoEx.RecordForToolAction(this); SetSnapStep(axisIndex, newInt); } EditorGUILayout.EndHorizontal(); } GUI.EndGroup(); Handles.EndGUI(); }