private void SetObjectSurfaceInfo(GameObject gameObject, ObjectSurfaceInfo surfaceInfo) { if (gameObject == null) { return; } if (_objectToSurfaceInfo.ContainsKey(gameObject)) { _objectToSurfaceInfo[gameObject] = surfaceInfo; } else { _objectToSurfaceInfo.Add(gameObject, surfaceInfo); } }
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); } } } }