Newer
Older
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class FactSpawner : MonoBehaviour
{
John Schihada
committed
private GameObject FactRepresentation;
AddFactEvent.AddListener(FactAction);
RemoveFactEvent.AddListener(DeleteObject);
John Schihada
committed
//Default FactRepresenation = Sphere-Prefab for Points
this.FactRepresentation = (GameObject) Resources.Load("Prefabs/Sphere", typeof(GameObject));
public void FactAction(Fact fact)
{
switch (fact)
{
case PointFact pointFact:
SpawnPoint(pointFact);
break;
case LineFact lineFact:
SpawnLine(lineFact);
break;
case AngleFact angleFact:
SpawnAngle(angleFact);
break;
}
}
public void SpawnPoint(PointFact fact)
John Schihada
committed
this.FactRepresentation = (GameObject)Resources.Load("Prefabs/Sphere", typeof(GameObject));
John Schihada
committed
GameObject point = GameObject.Instantiate(FactRepresentation);
point.transform.position = fact.Point;
point.transform.up = fact.Normal;
string letter = ((Char)(64+fact.Id+1)).ToString();
point.GetComponentInChildren<TextMeshPro>().text = letter;
point.GetComponent<FactObject>().Id = fact.Id;
John Schihada
committed
//If a new Point was spawned -> We are in MarkPointMode -> Then we want the collider to be disabled
//Hint: Thats why by now, if we mark a Point in an other mode than MarkPointMode, the
//Collider will be set disabled
if(CommunicationEvents.ActiveToolMode != ToolMode.ExtraMode)
point.GetComponentInChildren<SphereCollider>().enabled = false;
John Schihada
committed
John Schihada
committed
public void SpawnLine(LineFact lineFact)
PointFact pointFact1 = (Facts[lineFact.Pid1] as PointFact);
PointFact pointFact2 = (Facts[lineFact.Pid2] as PointFact);
Vector3 point1 = pointFact1.Point;
Vector3 point2 = pointFact2.Point;
John Schihada
committed
//Change FactRepresentation to Line
John Schihada
committed
this.FactRepresentation = (GameObject)Resources.Load("Prefabs/Line", typeof(GameObject));
John Schihada
committed
GameObject line = GameObject.Instantiate(FactRepresentation);
//Place the Line in the centre of the two points
line.transform.position = Vector3.Lerp(point1, point2, 0.5f);
John Schihada
committed
//Change scale and rotation, so that the two points are connected by the line
//Get the Line-GameObject as the first Child of the Line-Prefab -> That's the Collider
var v3T = line.transform.GetChild(0).localScale;
v3T.x = (point2 - point1).magnitude;
//For every Coordinate x,y,z we have to devide it by the LocalScale of the Child,
//because actually the Child should be of this length and not the parent, which is only the Collider
v3T.x = v3T.x / line.transform.GetChild(0).GetChild(0).localScale.x;
//y and z of the line/Cube-GameObject here hard coded = ratio of sphere-prefab
v3T.y = 0.1f / line.transform.GetChild(0).GetChild(0).localScale.y;
v3T.z = 0.1f / line.transform.GetChild(0).GetChild(0).localScale.z;
//Change Scale/Rotation of the Line-GameObject without affecting Scale of the Text
line.transform.GetChild(0).localScale = v3T;
line.transform.GetChild(0).rotation = Quaternion.FromToRotation(Vector3.right, point2 - point1);
John Schihada
committed
//string letter = ((Char)(64 + lineFact.Id + 1)).ToString();
//line.GetComponentInChildren<TextMeshPro>().text = letter;
line.GetComponentInChildren<TextMeshPro>().text = ((Char)(64 + pointFact1.Id + 1)).ToString() + ((Char)(64 + pointFact2.Id + 1)).ToString();
line.GetComponentInChildren<TextMeshPro>().text += " = " + Math.Round((point1-point2).magnitude, 2).ToString() + " m";
John Schihada
committed
line.GetComponentInChildren<FactObject>().Id = lineFact.Id;
John Schihada
committed
//If a new Line was spawned -> We are in CreateLineMode -> Then we want the collider to be disabled
if (CommunicationEvents.ActiveToolMode != ToolMode.ExtraMode)
John Schihada
committed
//Deactivate the Collider of the Line itself
line.transform.GetComponentInChildren<BoxCollider>().enabled = false;
lineFact.Representation = line;
John Schihada
committed
}
John Schihada
committed
//Spawn an angle: point with id = angleFact.Pid2 is the point where the angle gets applied
public void SpawnAngle(AngleFact angleFact)
{
Vector3 point1 = (Facts[angleFact.Pid1] as PointFact).Point;
Vector3 point2 = (Facts[angleFact.Pid2] as PointFact).Point;
Vector3 point3 = (Facts[angleFact.Pid3] as PointFact).Point;
Vector3 tempPoint1;
Vector3 tempPoint3;
//Length of the Angle relative to the Length of the shortest of the two lines (point2->point1) and (point2->point3)
float lengthFactor = 0.3f;
//AngleGO: Triangle-Length: 3/4, Circle-Length: 1/4
John Schihada
committed
float angleGoFactorTriangleToCircle = 1.27f;
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
//Make 2 TempPoints positioned on length% from Point2 to Point3 and on length% from Point2 to Point1
//Will be used for z-Coordinate of the Angle
float length = 0;
if ((point1 - point2).magnitude >= (point3 - point2).magnitude)
{
length = lengthFactor * (point3 - point2).magnitude;
tempPoint1 = point2 + length * (point1 - point2).normalized;
tempPoint3 = point2 + length * (point3 - point2).normalized;
}
else
{
length = lengthFactor * (point1 - point2).magnitude;
tempPoint1 = point2 + length * (point1 - point2).normalized;
tempPoint3 = point2 + length * (point3 - point2).normalized;
}
//Change FactRepresentation to Angle
this.FactRepresentation = (GameObject)Resources.Load("Prefabs/Angle", typeof(GameObject));
GameObject angle = GameObject.Instantiate(FactRepresentation);
//Place the Angle at position of point2
angle.transform.position = point2;
//Change scale and rotation, so that the angle is in between the two lines
var v3T = angle.transform.localScale;
//Calculate the Vector from point 2 to a POINT, where (point2->POINT) is orthogonal to (POINT->tempPoint3)
Vector3 tempProjection = Vector3.Project((tempPoint3 - point2), (Vector3.Lerp((tempPoint1 - point2).normalized, (tempPoint3 - point2).normalized, 0.5f)));
//Make the Angle as long as length + length of the half-circle
v3T.x = (tempProjection).magnitude * angleGoFactorTriangleToCircle;
//For every Coordinate x,y,z we have to devide it by the LocalScale of the Child,
//because actually the Child should be of this length and not the parent, which is only the Collider
v3T.x = v3T.x / angle.transform.GetChild(0).GetChild(0).localScale.x;
//y of the angle-GameObject here hard coded = ratio of sphere-prefab
v3T.y = 0.05f / angle.transform.GetChild(0).GetChild(0).localScale.y;
//z should be as long as the distance between tempPoint1 and tempPoint3
v3T.z = (tempPoint3 - tempPoint1).magnitude / angle.transform.GetChild(0).GetChild(0).localScale.z;
//Change Scale/Rotation of the Line-GameObject without affecting Scale of the Text
angle.transform.GetChild(0).localScale = v3T;
//Rotate so that the rotation points from point2 to the middle of point3 and point1
angle.transform.GetChild(0).rotation = Quaternion.FromToRotation(Vector3.right, (Vector3.Lerp((tempPoint1 - point2).normalized, (tempPoint3 - point2).normalized, 0.5f)));
//Now the rotation around that direction must also be adjusted
John Schihada
committed
//We calculate the Angle not with Vector3.Angle() because it only returns absolute angle-values
float signedAngle = Mathf.Atan2(Vector3.Dot((Vector3.Lerp((tempPoint1 - point2).normalized, (tempPoint3 - point2).normalized, 0.5f)), Vector3.Cross(angle.transform.GetChild(0).forward.normalized, (tempPoint1 - tempPoint3).normalized)), Vector3.Dot(angle.transform.GetChild(0).forward.normalized, (tempPoint1 - tempPoint3).normalized)) * Mathf.Rad2Deg;
if (signedAngle < 0)
{
angle.transform.GetChild(0).RotateAround(point2, (Vector3.Lerp((tempPoint1 - point2).normalized, (tempPoint3 - point2).normalized, 0.5f)), Vector3.Angle(angle.transform.GetChild(0).forward.normalized, (tempPoint3 - tempPoint1).normalized));
}
else
angle.transform.GetChild(0).RotateAround(point2, (Vector3.Lerp((tempPoint1 - point2).normalized, (tempPoint3 - point2).normalized, 0.5f)), Vector3.Angle(angle.transform.GetChild(0).forward.normalized, (tempPoint1 - tempPoint3).normalized));
//string letter = ((Char)(64 + angleFact.Id + 1)).ToString();
//Don't need next line anymore: Cause Text is now not above, but in the centre of the angle
//angle.GetComponentInChildren<TextMeshPro>().transform.localPosition = new Vector3((0.5f * tempProjection).x, angle.GetComponentInChildren<TextMeshPro>().transform.localPosition.y, (0.5f * tempProjection).z);
TextMeshPro[] texts = angle.GetComponentsInChildren<TextMeshPro>();
foreach (TextMeshPro t in texts) {
//Change Text not to the id, but to the angle-value (from both sides) AND change font-size relative to length of the angle (from both sides)
t.text = Math.Abs(Math.Round(Vector3.Angle((point1 - point2).normalized, (point3 - point2).normalized), 1)).ToString() + "°";
t.fontSize = angle.GetComponentInChildren<TextMeshPro>().fontSize * angle.transform.GetChild(0).transform.GetChild(0).localScale.x;
}
angle.GetComponentInChildren<FactObject>().Id = angleFact.Id;
//If a new Angle was spawned -> We are in CreateAngleMode -> Then we want the collider to be disabled
if (CommunicationEvents.ActiveToolMode != ToolMode.ExtraMode)
//Deactivate the Collider of the Angle itself
angle.transform.GetComponentInChildren<MeshCollider>().enabled = false;
angleFact.Representation = angle;
}
John Schihada
committed
public void DeleteObject(Fact fact)
{
Debug.Log("delete obj of "+ fact.Id);
John Schihada
committed
GameObject factRepresentation = fact.Representation;
GameObject.Destroy(factRepresentation);
}