Using Mouse Input
If only working with mouse input, there is no need for "DrawInVR." As a result, the flow chart would appear as follows:
Creation Process in EzDimStarter Component
When one of the public void functions inside the EzDimStarter
component is called by pressing a UI button, such as the "Point To Point" button, the corresponding code will run.
public void EzPointToPointDimension()
{
if (!isCreating)
{
isCreating = true; // this bool will set to false after draw the dimension.
SelectionList.Clear(); // deselect selected dimensions
Funcs.UpdateAll(this, DimensionsList, SelectionList);
GameObject EzPointToPointDimensionGO = new GameObject("EzPointToPointDimension");
EzPointToPointDimensionGO.transform.parent = this.transform;
var p2PDim = EzPointToPointDimensionGO.AddComponent<PointToPointDimension>();
if (createDimensionCort != null)
StopCoroutine(createDimensionCort);
createDimensionCort = StartCoroutine(CreatePointToPointDimension(p2PDim));
DimensionsList.Add(EzPointToPointDimensionGO.gameObject); // add the parent GO to the list.
}
}
At the beginning, it checks that the isCreating
Boolean is off to avoid the duplication of the creation process. Then, it will turn on isCreating
and will deselect the selected dimensions by clearing the selectionList
. After that, it calls the updateAll
function from EzDimFunctions
to update the dimensions' appearance based on the new cleared selectionList
. Now everything is ready to create a GameObject as a child of this GameObject to add the PointToPointDimension
component. Then, the code will loop inside the IEnumerator CreatePointToPointDimension()
while the added PointToPointDimension
component isDone
Boolean is not true. This Boolean will be set to true at the end of this IEnumerator. When this part is passed, the new dimension will be added to the dimensionsList
as a new dimension.
Let's check what is inside the IEnumerator CreatePointToPointDimension()
:
IEnumerator CreatePointToPointDimension(PointToPointDimension _p2PDim)
{
bool secondDrawStep = false;
Vector2 p0MousePosOnScreen = Vector2.zero;
while (_p2PDim.isDone != true)
{
if (Mouse.current.leftButton.wasPressedThisFrame && !secondDrawStep && !_p2PDim.isDone && isCreating == true)
{
p0MousePosOnScreen = Mouse.current.position.ReadValue();
RaycastHit hit;
Ray ray = rendererCamera.gameObject.GetComponent<Camera>().ScreenPointToRay(Mouse.current.position.ReadValue());
if (Physics.Raycast(ray, out hit, Mathf.Infinity))
{
_p2PDim.firstPointHitNormal = hit.normal;
_p2PDim.pointA = hit.point;
_p2PDim.objectA = hit.transform.gameObject;
_p2PDim.objectATransformGO.transform.position = hit.transform.position;
_p2PDim.objectATransformGO.transform.rotation = hit.transform.rotation;
_p2PDim.objectATransformGO.transform.localScale = hit.transform.localScale;
_p2PDim.pointATransformGO.transform.position = _p2PDim.pointA;
if (!hit.transform.gameObject.TryGetComponent<EzDynamicTargetObject>(out EzDynamicTargetObject EzDynamicTarget))
{
hit.transform.gameObject.AddComponent<EzDynamicTargetObject>().p2PDimComponentsList.Add(_p2PDim);
hit.transform.gameObject.GetComponent<EzDynamicTargetObject>().starterScript = this;
}
else
{
var p2PDimComp = hit.transform.gameObject.GetComponent<EzDynamicTargetObject>();
p2PDimComp.p2PDimComponentsList.Add(_p2PDim);
}
secondDrawStep = true;
}
}
else if (secondDrawStep && p0MousePosOnScreen != Mouse.current.position.ReadValue())
{
Funcs.SetActiveAllChilds(_p2PDim.gameObject.transform, true);
RaycastHit hit;
Ray ray = rendererCamera.gameObject.GetComponent<Camera>().ScreenPointToRay(Mouse.current.position.ReadValue());
if (Physics.Raycast(ray, out hit, Mathf.Infinity))
{
_p2PDim.pointB = hit.point;
_p2PDim.objectB = hit.transform.gameObject;
_p2PDim.objectBTransformGO.transform.position = hit.transform.position;
_p2PDim.objectBTransformGO.transform.rotation = hit.transform.rotation;
_p2PDim.objectBTransformGO.transform.localScale = hit.transform.localScale;
_p2PDim.pointBTransformGO.transform.position = _p2PDim.pointB;
_p2PDim.UpdateDimension(_p2PDim.pointA, _p2PDim.pointB, _p2PDim.lineThickness, _p2PDim.textSize, _p2PDim.textOffset,
_p2PDim.numberColor, _p2PDim.mainColor, _p2PDim.arrowColor,
_p2PDim.mainLineMat, _p2PDim.arrowMat, _p2PDim.cameraTransform, _p2PDim.mainParent, _p2PDim.arrowHeight,
InternalFunctions.LengthUnitCalculator(this), textTowardsCameraOffset, hitNormalOffset);
if (Mouse.current.leftButton.wasPressedThisFrame && secondDrawStep)
{
if (!hit.transform.gameObject.TryGetComponent<EzDynamicTargetObject>(out EzDynamicTargetObject EzDynamicTarget))
{
hit.transform.gameObject.AddComponent<EzDynamicTargetObject>().p2PDimComponentsList.Add(_p2PDim);
hit.transform.gameObject.GetComponent<EzDynamicTargetObject>().starterScript = this;
}
else
{
var p2PDimComp = hit.transform.gameObject.GetComponent<EzDynamicTargetObject>();
p2PDimComp.p2PDimComponentsList.Add(_p2PDim);
}
secondDrawStep = false;
_p2PDim.isDone = true;
isCreating = false; // end of drawing of the dimension.
}
}
}
yield return null;
}
}
Inside the IEnumerator, several steps are executed after each mouse click. On the first click, a rayCast
is used to obtain the first hitPoint
and hit.transform.gameObject
, which defines the first point. The script then unhides every part of the dimension by running the Funcs.SetActiveAllChilds()
function from the EzDimension
namespace inside the EzDimFunctions
component. Next, the second point is defined by moving the mouse and clicking again.
After the second click, every frame, the rayCast
of Camera.ScreenPointToRay(Mouse.current.position.ReadValue())
defines the second point of the dimension. The UpdateDimension()
function from the added pointToPointDimension
component updates the dimension based on the second point, which updates every frame depending on the mouse position. After the second click, the isDone
boolean inside the added pointToPointDimension
component will be set to true, and the isCreating
boolean inside the EzDimStarter
will be set to false, which indicates the end of the creation process.
This process has the same logic for all dimensions. The EzDimStarter
always creates a set of gameObjects
and adds the Dimension Component on their parents. It gets and sets the required position from mouse input and updates the dimension until the creation process is complete. Note that the Create and Update dimension functions are inside the dimension components (pointToPointDimension.cs
). The Create function is only called once since it's in the start void of the dimension component.
Overview of Dimension Components and Functions
void Start()
{
CreateDimension(mainParent, arrowPrefab);
Funcs.SetActiveAllChilds(this.transform, false);
}
There are CreateDimension()
and UpdateDimension()
voids inside all of the dimension components except for the area measure. Some dimensions also have additional functions, such as UpdateTextTransform()
in pointToPointDimension.cs
, LinearDimension.cs
, and AlignedDimension.cs
, and UpdateTextAndIndicator()
in AngleDimension.cs
.
The LinearAreaMeasure.cs
component does not have CreateDimension()
, Start()
, or Update()
voids. Instead, required gameObjects are created in the Awake()
void, and there are five other voids named UpdatePointsList()
, UpdateBorderLine()
, DrawArea()
, UpdateAreaNumber()
, and UpdateNumberPositionAndRotation()
.
The EzDimFunctions.cs
component contains most of the functions and is under the EzDimension
namespace. Other components that use any of these functions need to include using EzDimension
.
There are more specific details in the Scripting API section.