private void SelectPivot() { if (!RTInputDevice.Get.Device.HasPointer()) { return; } var boundsQConfig = GetObjectBoundsQConfig(); Vector2 inputDevicePos = RTInputDevice.Get.Device.GetPositionYAxisUp(); float minDistFromDevice = float.MaxValue; foreach (var targetObject in _targetObjects) { if (targetObject == null) { continue; } OBB worldOBB = ObjectBounds.CalcWorldOBB(targetObject, boundsQConfig); if (worldOBB.IsValid) { Camera camera = RTFocusCamera.Get.TargetCamera; List <Vector3> centerAndCorners = worldOBB.GetCenterAndCornerPoints(); List <Vector2> screenCenterAndCorners = camera.ConvertWorldToScreenPoints(centerAndCorners); for (int ptIndex = 0; ptIndex < screenCenterAndCorners.Count; ++ptIndex) { float distance = (inputDevicePos - screenCenterAndCorners[ptIndex]).magnitude; if (distance < minDistFromDevice) { minDistFromDevice = distance; _snapPivotPoint = centerAndCorners[ptIndex]; } } } } }
protected bool GetWorldPointClosestToInputDevice(Camera focusCamera, IEnumerable <GameObject> gameObjects, out Vector3 point) { point = Vector3.zero; if (gameObjects == null) { return(false); } if (!RTInputDevice.Get.Device.HasPointer()) { return(false); } Vector2 inputDeviceScreenPt = RTInputDevice.Get.Device.GetPositionYAxisUp(); float minDistSqr = float.MaxValue; bool foundPoint = false; foreach (GameObject srcObject in gameObjects) { Mesh mesh = srcObject.GetMesh(); if (mesh != null) { MeshVertexChunkCollection meshVChunkCollection = MeshVertexChunkCollectionDb.Get[mesh]; if (meshVChunkCollection == null) { continue; } Matrix4x4 worldMtx = srcObject.transform.localToWorldMatrix; List <MeshVertexChunk> testChunks = meshVChunkCollection.GetWorldChunksHoveredByPoint(inputDeviceScreenPt, worldMtx, focusCamera); if (testChunks.Count == 0) { MeshVertexChunk closestChunk = meshVChunkCollection.GetWorldVertChunkClosestToScreenPt(inputDeviceScreenPt, worldMtx, focusCamera); if (closestChunk != null && closestChunk.VertexCount != 0) { testChunks.Add(closestChunk); } } foreach (MeshVertexChunk chunk in testChunks) { Vector3 worldVert = chunk.GetWorldVertClosestToScreenPt(inputDeviceScreenPt, worldMtx, focusCamera); Vector2 screenVert = focusCamera.WorldToScreenPoint(worldVert); float distSqr = (inputDeviceScreenPt - screenVert).sqrMagnitude; if (distSqr < minDistSqr) { minDistSqr = distSqr; point = worldVert; foundPoint = true; } } } else { OBB spriteWorldOBB = ObjectBounds.CalcSpriteWorldOBB(srcObject); if (spriteWorldOBB.IsValid) { List <Vector3> obbPoints = spriteWorldOBB.GetCenterAndCornerPoints(); List <Vector2> screenPoints = focusCamera.ConvertWorldToScreenPoints(obbPoints); int closestPtIndex = Vector2Ex.GetPointClosestToPoint(screenPoints, inputDeviceScreenPt); if (closestPtIndex >= 0) { Vector2 closestPt = screenPoints[closestPtIndex]; float distSqr = (inputDeviceScreenPt - closestPt).sqrMagnitude; if (distSqr < minDistSqr) { minDistSqr = distSqr; point = obbPoints[closestPtIndex]; foundPoint = true; } } } } } return(foundPoint); }
public static SnapResult CalculateSnapResult(GameObject root, Config snapConfig) { if (snapConfig.IgnoreDestObjects == null) { snapConfig.IgnoreDestObjects = new List <GameObject>(); } List <GameObject> sourceObjects = root.GetAllChildrenAndSelf(); if (sourceObjects.Count > MaxSourceObjects) { return(new SnapResult(SnapFailReson.MaxObjectsExceeded)); } List <GameObject> sourceMeshObjects = root.GetMeshObjectsInHierarchy(); List <GameObject> sourceSpriteObjects = root.GetSpriteObjectsInHierarchy(); if (sourceMeshObjects.Count == 0 && sourceSpriteObjects.Count == 0) { return(new SnapResult(SnapFailReson.InvalidSourceObjects)); } ObjectBounds.QueryConfig boundsQConfig = new ObjectBounds.QueryConfig(); boundsQConfig.ObjectTypes = GameObjectType.Mesh | GameObjectType.Sprite; Vector3 overlapSizeAdd = Vector3.one * snapConfig.SnapRadius * 2.0f; List <BoxFace> allSnapFaces = BoxMath.AllBoxFaces; bool tryMatchAreas = (snapConfig.Prefs & Prefs.TryMatchArea) != 0; bool foundMatchingAreas = false; List <SnapSortData> sortedSnapData = new List <SnapSortData>(10); SnapSortData sortData = new SnapSortData(); foreach (GameObject sourceObject in sourceObjects) { OBB overlapOBB = ObjectBounds.CalcWorldOBB(sourceObject, boundsQConfig); overlapOBB.Size = overlapOBB.Size + overlapSizeAdd; List <GameObject> nearbyObjects = RTScene.Get.OverlapBox(overlapOBB); nearbyObjects.RemoveAll(item => item.transform.IsChildOf(root.transform) || snapConfig.IgnoreDestObjects.Contains(item) || !LayerEx.IsLayerBitSet(snapConfig.DestinationLayers, item.layer)); if (nearbyObjects.Count == 0) { continue; } Object2ObjectSnapData sourceSnapData = Object2ObjectSnapDataDb.Get.GetObject2ObjectSnapData(sourceObject); if (sourceSnapData == null) { continue; } sortData.SrcObject = sourceObject; foreach (BoxFace srcSnapFace in allSnapFaces) { BoxFaceAreaDesc srcAreaDesc = sourceSnapData.GetWorldSnapAreaDesc(srcSnapFace); OBB srcAreaBounds = sourceSnapData.GetWorldSnapAreaBounds(srcSnapFace); List <Vector3> srcAreaPts = srcAreaBounds.GetCenterAndCornerPoints(); sortData.SrcSnapFace = srcSnapFace; foreach (GameObject destObject in nearbyObjects) { Object2ObjectSnapData destSnapData = Object2ObjectSnapDataDb.Get.GetObject2ObjectSnapData(destObject); if (destSnapData == null) { continue; } sortData.DestObject = destObject; foreach (BoxFace destSnapFace in allSnapFaces) { sortData.DestSnapFace = destSnapFace; BoxFaceAreaDesc destAreaDesc = destSnapData.GetWorldSnapAreaDesc(destSnapFace); sortData.FaceAreasMatch = false; if (tryMatchAreas && destAreaDesc.AreaType == srcAreaDesc.AreaType) { sortData.FaceAreaDiff = Mathf.Abs(destAreaDesc.Area - srcAreaDesc.Area); if (sortData.FaceAreaDiff <= 1000.0f) { sortData.FaceAreasMatch = true; } } OBB destAreaBounds = destSnapData.GetWorldSnapAreaBounds(destSnapFace); List <Vector3> destAreaPts = destAreaBounds.GetCenterAndCornerPoints(); foreach (Vector3 srcPt in srcAreaPts) { sortData.SnapPivot = srcPt; foreach (Vector3 destPt in destAreaPts) { sortData.SnapDistance = (destPt - srcPt).magnitude; if (sortData.SnapDistance < snapConfig.SnapRadius) { sortData.SnapDest = destPt; sortedSnapData.Add(sortData); if (sortData.FaceAreasMatch) { foundMatchingAreas = true; } } } } } } } } if (sortedSnapData.Count != 0) { if (!tryMatchAreas || !foundMatchingAreas) { sortedSnapData.Sort(delegate(SnapSortData s0, SnapSortData s1) { return(s0.SnapDistance.CompareTo(s1.SnapDistance)); }); } else { while (true) { if (!sortedSnapData[0].FaceAreasMatch) { sortedSnapData.RemoveAt(0); } else { break; } } sortedSnapData.Sort(delegate(SnapSortData s0, SnapSortData s1) { return(s0.FaceAreaDiff.CompareTo(s1.FaceAreaDiff)); }); } return(new SnapResult(sortedSnapData[0].SnapPivot, sortedSnapData[0].SnapDest, sortedSnapData[0].SnapDistance)); } return(new SnapResult(SnapFailReson.NoDestinationFound)); }