const float jointsDistance = 0.25f; //distance between two standard joints in brick (scale 1) public override ProposedPosition GetPosition(Vector3 mousePosition, bool snapToGrid, float gridSize) { var simplePosition = base.GetPosition(mousePosition, false, gridSize); brick.transform.position = simplePosition.position; if (!(brick is AgaQBrick)) { return(simplePosition); } //calculate distance betweeen two standard joints in screen space. var joint1Pos = simplePosition.position + cam.transform.right * jointsDistance * brick.transform.localScale.x; var joint2Pos = simplePosition.position - cam.transform.right * jointsDistance * brick.transform.localScale.x; var jointsScreenDistance = (cam.WorldToScreenPoint(joint1Pos) - cam.WorldToScreenPoint(joint2Pos)).magnitude * 0.5f; //transform our moving brick joints postions to screen space var brickJoints = ProjectionTool.ProjectJoints(brick as AgaQBrick); //get possible joints var gameObjectsBehind = GetOtherBricks(mousePosition); var possibleJoints = GetClosetsJoins(brickJoints, gameObjectsBehind, jointsScreenDistance); //iterate over possible joints foreach (var possibleJoint in possibleJoints) { if (CheckJoint(possibleJoint, snapToGrid)) { return(new ProposedPosition(brick.transform, true, true)); } } if (!snapToGrid) { return(simplePosition); } return(base.GetPosition(mousePosition, snapToGrid, gridSize)); }
/// <summary> /// Get joints from other brics that are close enouth to try join brick with. /// List is sorted by distance after projeting to the plane. /// </summary> /// <param name="projectedDragingBrickJoints"></param> /// <param name="positionTolerance">Position tolerance.</param> /// <returns>The closets joins.</returns> PossibleJoint[] GetClosetsJoins(ProjectedJoint[] projectedDragingBrickJoints, GameObject[] gameObjects, float positionTolerance) { List <PossibleJoint> possibleJoints = new List <PossibleJoint> (); //iterate over all colliders foreach (var otherGameObject in gameObjects) { //skip grid and itself if (otherGameObject.tag == "background" || otherGameObject == this.brick.gameObject) { continue; } //check if collider is AgaQ brick var otherBrick = otherGameObject.GetComponent <AgaQBrick> (); if (otherBrick == null) { //try to get AgaQScript from parent otherBrick = otherGameObject.GetComponentInParent <AgaQBrick>(); if (otherBrick == null) { continue; } } //iterate over all brick joints foreach (var otherBrickJoint in otherBrick.joints) { if (otherBrickJoint.other == null) { foreach (var projectedDragingBrickJoint in projectedDragingBrickJoints) { var projectedJoint = ProjectionTool.ProjectJoint(otherBrickJoint); if (projectedDragingBrickJoint.Compare(projectedJoint, positionTolerance)) { possibleJoints.Add(new PossibleJoint(projectedDragingBrickJoint, projectedJoint)); } } } } } //draw possible joints in editor for debuging purpose #if UNITY_EDITOR foreach (var j in possibleJoints) { DebugExtension.DebugCircle( j.projectedOtherJoint.joint.transform.position, Color.red, 0.1f, 02.2f, false ); //Debug.DrawLine( // j.projectedBrickJoint.joint.transform.position, // j.projectedOtherJoint.joint.transform.position, // Color.red, // 0.2f, // false //); } #endif //possibleJoints.OrderBy (x => x.cameraVectorDistance); // order joints by distance to camera //possibleJoints.OrderBy (x => x.projectedDistance); // order joints by distance after project //sort by brick to camera distance than by projected distance possibleJoints.Sort((x, y) => { if (x.projectedOtherJoint.joint.parentBrick != y.projectedOtherJoint.joint.parentBrick) { return(x.cameraVectorDistance.CompareTo(y.cameraVectorDistance)); } return(x.projectedDistance.CompareTo(y.projectedDistance)); }); return(possibleJoints.ToArray()); }