Skip to content
Snippets Groups Projects
FactSpawner.cs 10.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • using System;
    using System.Collections;
    using System.Collections.Generic;
    using TMPro;
    using UnityEngine;
    
    using static CommunicationEvents;
    
    
    public class FactSpawner : MonoBehaviour
    {
    
           
            AddFactEvent.AddListener(FactAction);
            RemoveFactEvent.AddListener(DeleteObject);
    
    Richard Marcus's avatar
    Richard Marcus committed
    
    
            //Default FactRepresenation = Sphere-Prefab for Points
            this.FactRepresentation = (GameObject) Resources.Load("Prefabs/Sphere", typeof(GameObject));
    
    Richard Marcus's avatar
    Richard Marcus committed
    
    
        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);
    
    John Schihada's avatar
    John Schihada committed
            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's avatar
    John Schihada committed
            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
    
    Richard Marcus's avatar
    Richard Marcus committed
            if(CommunicationEvents.ActiveToolMode != ToolMode.ExtraMode)
                point.GetComponentInChildren<SphereCollider>().enabled = false;
    
        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;
    
            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<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";
    
            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;
    
        //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
    
            float angleGoFactorTriangleToCircle = 1.27f;
    
    
            //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));
    
    John Schihada's avatar
    John Schihada committed
            //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;
    
        }
    
    
            Debug.Log("delete obj of "+ fact.Id);
    
            GameObject factRepresentation = fact.Representation;
            GameObject.Destroy(factRepresentation);
       
        }