-
John Schihada authored
Now really Fixed the problem. Problem was: Vector3.angle() not only returns only values < 180° but also only absolute angle-values
John Schihada authoredNow really Fixed the problem. Problem was: Vector3.angle() not only returns only values < 180° but also only absolute angle-values
FactSpawner.cs 9.13 KiB
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using static CommunicationEvents;
public class FactSpawner : MonoBehaviour
{
private GameObject FactRepresentation;
void Start()
{
AddFactEvent.AddListener(FactAction);
RemoveFactEvent.AddListener(DeleteObject);
//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)
{
this.FactRepresentation = (GameObject)Resources.Load("Prefabs/Sphere", typeof(GameObject));
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;
fact.Representation = point;
//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;
}
public void SpawnLine(LineFact lineFact)
{
Vector3 point1 = (Facts[lineFact.Pid1] as PointFact).Point;
Vector3 point2 = (Facts[lineFact.Pid2] as PointFact).Point;
//Change FactRepresentation to Line
this.FactRepresentation = (GameObject)Resources.Load("Prefabs/Line", typeof(GameObject));
GameObject line = GameObject.Instantiate(FactRepresentation);
//Place the Line in the centre of the two points
line.transform.position = Vector3.Lerp(point1, point2, 0.5f);
//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);
string letter = ((Char)(64 + lineFact.Id + 1)).ToString();
line.GetComponentInChildren<TextMeshPro>().text = letter;
line.GetComponentInChildren<FactObject>().Id = lineFact.Id;
//If a new Line was spawned -> We are in CreateLineMode -> Then we want the collider to be disabled
if (CommunicationEvents.ActiveToolMode != ToolMode.ExtraMode)
//Deactivate the Collider of the Line itself
line.transform.GetComponentInChildren<BoxCollider>().enabled = false;
lineFact.Representation = line;
}
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
float angleGoFactorTriangleToCircle = 1.25f;
//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
//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();
angle.GetComponentInChildren<TextMeshPro>().transform.localPosition = new Vector3((0.5f * tempProjection).x, angle.GetComponentInChildren<TextMeshPro>().transform.localPosition.y, (0.5f * tempProjection).z);
angle.GetComponentInChildren<TextMeshPro>().text = letter;
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;
}
public void DeleteObject(Fact fact)
{
Debug.Log("delete obj of "+ fact.Id);
GameObject factRepresentation = fact.Representation;
GameObject.Destroy(factRepresentation);
}
}