Skip to content
Snippets Groups Projects
FactSpawner.cs 8.37 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
        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);
   
    }
}