├── CameraControl.cs ├── DataManager.cs ├── Demo_Model.obj ├── DetectTransformChange.cs ├── DoubleFaces.cs ├── DrawMeshLines.cs ├── GenerateMesh.cs ├── GetSetImage.cs ├── GetSetImg.cs ├── LICENSE ├── LayerMask.cs ├── LinkToToogle.cs ├── Map.cs ├── MapControl.cs ├── Mapbox.cs ├── MeshLog.cs ├── Model.obj ├── OpenFile.cs ├── OpenMesh.cs ├── OutlineSelection.cs ├── PanZoomOrbitCenter.cs ├── RoundFloat.cs ├── SaveFile.cs ├── SaveMesh.cs ├── SelectMove.cs ├── SelectTransformGizmo.cs ├── Selection.cs ├── SetGetData.cs ├── Sphere.obj ├── SphereCast.cs ├── TransformUI.cs ├── TraverseAllChildren.cs ├── UI.cs └── com.shtif.runtimetransformhandle@0.1.3.zip /CameraControl.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | 23 | public class CameraControl : MonoBehaviour 24 | { 25 | private float rotationSpeed = 500.0f; 26 | private Vector3 mouseWorldPosStart; 27 | private float zoomScale = 50.0f; 28 | private float zoomMin = 0.5f; 29 | private float zoomMax = 1000.0f; 30 | 31 | // Start is called before the first frame update void Start(){} 32 | 33 | // Update is called once per frame 34 | void Update() 35 | { 36 | if (Input.GetKey(KeyCode.LeftShift) && Input.GetKey(KeyCode.Mouse2)) //Check for orbit 37 | { 38 | CamOrbit(); 39 | } 40 | 41 | if (Input.GetMouseButtonDown(2) && !Input.GetKey(KeyCode.LeftShift)) //Check for Pan 42 | { 43 | mouseWorldPosStart = Camera.main.ScreenToWorldPoint(Input.mousePosition); 44 | } 45 | if (Input.GetMouseButton(2) && !Input.GetKey(KeyCode.LeftShift)) 46 | { 47 | Pan(); 48 | } 49 | 50 | Zoom(Input.GetAxis("Mouse ScrollWheel")); //Check for Zoom 51 | } 52 | 53 | 54 | private void CamOrbit() 55 | { 56 | if (Input.GetAxis("Mouse Y") != 0 || Input.GetAxis("Mouse X") != 0) 57 | { 58 | float verticalInput = Input.GetAxis("Mouse Y") * rotationSpeed * Time.deltaTime; 59 | float horizontalInput = Input.GetAxis("Mouse X") * rotationSpeed * Time.deltaTime; 60 | transform.Rotate(Vector3.right, verticalInput); 61 | transform.Rotate(Vector3.up, horizontalInput, Space.World); 62 | } 63 | } 64 | 65 | void Pan() 66 | { 67 | if (Input.GetAxis("Mouse Y") != 0 || Input.GetAxis("Mouse X") != 0) 68 | { 69 | Vector3 mouseWorldPosDiff = mouseWorldPosStart - Camera.main.ScreenToWorldPoint(Input.mousePosition); 70 | transform.position += mouseWorldPosDiff; 71 | } 72 | } 73 | 74 | void Zoom(float zoomDiff) 75 | { 76 | if (zoomDiff != 0) 77 | { 78 | mouseWorldPosStart = Camera.main.ScreenToWorldPoint(Input.mousePosition); 79 | Camera.main.orthographicSize = Mathf.Clamp(Camera.main.orthographicSize - zoomDiff * zoomScale, zoomMin, zoomMax); 80 | Vector3 mouseWorldPosDiff = mouseWorldPosStart - Camera.main.ScreenToWorldPoint(Input.mousePosition); 81 | transform.position += mouseWorldPosDiff; 82 | } 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /DataManager.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | //-----------------------------------------------------// 20 | // Data persistence between Scenes & Sessions 21 | //-----------------------------------------------------// 22 | using System.Collections; 23 | using System.Collections.Generic; 24 | using UnityEngine; 25 | using System.IO; 26 | 27 | public class DataManager : MonoBehaviour 28 | { 29 | public static DataManager Instance { get; private set; } 30 | 31 | //Variables that need to be stored 32 | public Color color; 33 | public float speed; 34 | 35 | private void Awake() 36 | { 37 | if (Instance != null) 38 | { 39 | Destroy(gameObject); 40 | return; 41 | } 42 | 43 | Instance = this; 44 | DontDestroyOnLoad(gameObject); 45 | LoadData(); 46 | } 47 | 48 | [System.Serializable] 49 | class SaveData 50 | { 51 | //Variables that need to be stored 52 | public Color color; 53 | public float speed; 54 | } 55 | 56 | public void WriteData() 57 | { 58 | SaveData data = new SaveData(); 59 | 60 | //Variables that need to be stored 61 | data.color = color; 62 | data.speed = speed; 63 | 64 | string json = JsonUtility.ToJson(data); 65 | File.WriteAllText(Application.persistentDataPath + "/savefile.json", json); 66 | Debug.Log("Application.persistentDataPath: " + Application.persistentDataPath); 67 | } 68 | 69 | public void LoadData() 70 | { 71 | string path = Application.persistentDataPath + "/savefile.json"; 72 | if (File.Exists(path)) 73 | { 74 | string json = File.ReadAllText(path); 75 | SaveData data = JsonUtility.FromJson(json); 76 | 77 | //Variables that need to be stored 78 | color = data.color; 79 | speed = data.speed; 80 | } 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /DetectTransformChange.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | 23 | public class DetectTransformChange : MonoBehaviour 24 | { 25 | public GameObject trackedObject; 26 | private Vector3 lastPosition; 27 | private Quaternion lastRotation; 28 | private Vector3 lastScale; 29 | 30 | // Start is called before the first frame update 31 | void Start() 32 | { 33 | lastPosition = trackedObject.transform.position; 34 | lastRotation = trackedObject.transform.rotation; 35 | lastScale = trackedObject.transform.localScale; 36 | } 37 | 38 | // Update is called once per frame 39 | void Update() 40 | { 41 | OnTransformChanged(); 42 | } 43 | 44 | void OnTransformChanged() 45 | { 46 | if (trackedObject.transform.position != lastPosition || trackedObject.transform.rotation != lastRotation || trackedObject.transform.localScale != lastScale) 47 | { 48 | Debug.Log("Transform has changed!"); 49 | // Perform some action in response to the change 50 | } 51 | 52 | lastPosition = trackedObject.transform.position; 53 | lastRotation = trackedObject.transform.rotation; 54 | lastScale = trackedObject.transform.localScale; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /DoubleFaces.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | 23 | public class DoubleFaces : MonoBehaviour 24 | { 25 | public GameObject model; 26 | // Start is called before the first frame update 27 | void Start() 28 | { 29 | 30 | } 31 | 32 | // Update is called once per frame 33 | // Update is called once per frame 34 | void Update() 35 | { 36 | 37 | } 38 | 39 | 40 | // Doublicate the size of mesh components, in which the second half of the tringles winding order and normals are reverse of the first half to enable displaying front and back faces 41 | //https://answers.unity.com/questions/280741/how-make-visible-the-back-face-of-a-mesh.html 42 | public void DoublicateFaces() 43 | { 44 | for (int i = 0; i < model.GetComponentsInChildren().Length; i++) //Loop through the model children 45 | { 46 | // Get oringal mesh components: vertices, normals triangles and texture coordinates 47 | Mesh mesh = model.GetComponentsInChildren()[i].mesh; 48 | Vector3[] vertices = mesh.vertices; 49 | int numOfVertices = vertices.Length; 50 | Vector3[] normals = mesh.normals; 51 | int[] triangles = mesh.triangles; 52 | int numOfTriangles = triangles.Length; 53 | Vector2[] textureCoordinates = mesh.uv; 54 | if (textureCoordinates.Length < numOfTriangles) //Check if mesh doesn't have texture coordinates 55 | { 56 | textureCoordinates = new Vector2[numOfVertices * 2]; 57 | } 58 | 59 | // Create a new mesh component, double the size of the original 60 | Vector3[] newVertices = new Vector3[numOfVertices * 2]; 61 | Vector3[] newNormals = new Vector3[numOfVertices * 2]; 62 | int[] newTriangle = new int[numOfTriangles * 2]; 63 | Vector2[] newTextureCoordinates = new Vector2[numOfVertices * 2]; 64 | 65 | for (int j = 0; j < numOfVertices; j++) 66 | { 67 | newVertices[j] = newVertices[j + numOfVertices] = vertices[j]; //Copy original vertices to make the second half of the mew vertices array 68 | newTextureCoordinates[j] = newTextureCoordinates[j + numOfVertices] = textureCoordinates[j]; //Copy original texture coordinates to make the second half of the mew texture coordinates array 69 | newNormals[j] = normals[j]; //First half of the new normals array is a copy original normals 70 | newNormals[j + numOfVertices] = -normals[j]; //Second half of the new normals array reverse the original normals 71 | } 72 | 73 | for (int x = 0; x < numOfTriangles; x += 3) 74 | { 75 | // copy the original triangle for the first half of array 76 | newTriangle[x] = triangles[x]; 77 | newTriangle[x + 1] = triangles[x + 1]; 78 | newTriangle[x + 2] = triangles[x + 2]; 79 | // Reversed triangles for the second half of array 80 | int j = x + numOfTriangles; 81 | newTriangle[j] = triangles[x] + numOfVertices; 82 | newTriangle[j + 2] = triangles[x + 1] + numOfVertices; 83 | newTriangle[j + 1] = triangles[x + 2] + numOfVertices; 84 | } 85 | mesh.vertices = newVertices; 86 | mesh.uv = newTextureCoordinates; 87 | mesh.normals = newNormals; 88 | mesh.triangles = newTriangle; 89 | } 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /DrawMeshLines.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | 23 | public class DrawMeshLines : MonoBehaviour 24 | { 25 | public Camera currentCamera; 26 | public Color lineColor; 27 | private float thresholdDist = 0.001f; 28 | private List linesMeshesObjs = new List(); 29 | private List linesVertices = new List(); 30 | private List linesIndices = new List(); 31 | private bool isNewLine = false; 32 | private Vector3 endWorldPos = Vector3.one * float.MaxValue; //Highest value 33 | private int indexCount = 0; 34 | 35 | 36 | void Start() 37 | { 38 | currentCamera = Camera.main; 39 | Mesh newLinesMesh = new Mesh(); 40 | newLinesMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; //By default mesh support 16-bit index format which support buffer of 65535 41 | gameObject.AddComponent(); 42 | gameObject.AddComponent(); 43 | gameObject.GetComponent().mesh = newLinesMesh; 44 | gameObject.GetComponent().material = new Material(Shader.Find("Sprites/Default")); 45 | linesMeshesObjs.Add(gameObject); 46 | } 47 | 48 | 49 | void Update() 50 | { 51 | if (Input.GetMouseButtonDown(0)) //Check for mouse left click 52 | { 53 | Vector3 mousePxlPos = Input.mousePosition; 54 | mousePxlPos.z = currentCamera.nearClipPlane + currentCamera.nearClipPlane * 0.01f; //Add a bit to near clip plane to make lines visible 55 | Vector3 mouseWorldPos = currentCamera.ScreenToWorldPoint(mousePxlPos); 56 | float distToEndPoint = Vector3.Distance(endWorldPos, mouseWorldPos); 57 | if (distToEndPoint <= thresholdDist) 58 | { 59 | return; 60 | } 61 | endWorldPos = mouseWorldPos; 62 | linesVertices.Add(mouseWorldPos); 63 | if (indexCount > 1) //Because MeshTopology.Lines needs two indices to draw each line 64 | { 65 | linesIndices.Add(indexCount - 1); 66 | linesIndices.Add(indexCount); 67 | } 68 | else 69 | { 70 | linesIndices.Add(indexCount); 71 | } 72 | UpdateLinesMesh(); 73 | indexCount++; 74 | } 75 | 76 | if (Input.GetMouseButtonDown(1)) //Check for mouse right click 77 | { 78 | StartNewLinesMesh(); 79 | } 80 | } 81 | 82 | 83 | private void UpdateLinesMesh() 84 | { 85 | GameObject currentGameObj = linesMeshesObjs[linesMeshesObjs.Count - 1]; 86 | Mesh linesMesh = currentGameObj.GetComponent().mesh; 87 | linesMesh.vertices = linesVertices.ToArray(); 88 | linesMesh.normals = new Vector3[linesVertices.Count]; //Populate with Zero normals to have lines with constant colour 89 | linesMesh.SetIndices(linesIndices.ToArray(), MeshTopology.Lines, 0); //Select lines for mesh topology 90 | currentGameObj.GetComponent().material.color = lineColor; 91 | isNewLine = false; 92 | } 93 | 94 | 95 | private void StartNewLinesMesh() 96 | { 97 | if (!isNewLine) 98 | { 99 | GameObject newLinesGameObj = new GameObject(); 100 | Mesh newLinesMesh = new Mesh(); 101 | newLinesMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; //By default mesh support 16-bit index format which support buffer of 65535 102 | linesVertices = new List(); //Reset vertices list 103 | linesIndices = new List(); //Reset indices list 104 | indexCount = 0; //Reset index count 105 | newLinesGameObj.AddComponent(); 106 | newLinesGameObj.AddComponent(); 107 | newLinesGameObj.GetComponent().mesh = newLinesMesh; 108 | newLinesGameObj.GetComponent().material = new Material(Shader.Find("Sprites/Default")); 109 | linesMeshesObjs.Add(newLinesGameObj); 110 | isNewLine = true; 111 | } 112 | 113 | } 114 | } 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /GenerateMesh.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class GenerateMesh : MonoBehaviour 6 | { 7 | // Start is called before the first frame update 8 | void Start() 9 | { 10 | 11 | } 12 | 13 | // Update is called once per frame 14 | void Update() 15 | { 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /GetSetImage.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using UnityEngine.UI; 23 | using TMPro; 24 | 25 | public class GetSetImage : MonoBehaviour 26 | { 27 | public GameObject imageGameObj; 28 | public GameObject inputWidthGameObj; 29 | public GameObject inputHeightGameObj; 30 | 31 | TMP_InputField inputWidth; 32 | TMP_InputField inputHeight; 33 | Image image; 34 | float width; 35 | float height; 36 | Rect rect; 37 | 38 | // Start is called before the first frame update 39 | void Start() 40 | { 41 | image = imageGameObj.GetComponent(); 42 | inputWidth = inputWidthGameObj.GetComponent(); 43 | inputHeight = inputHeightGameObj.GetComponent(); 44 | } 45 | 46 | // Update is called once per frame void Update(){} 47 | 48 | public void GetImageSize() 49 | { 50 | rect = image.rectTransform.rect; 51 | width = rect.width; 52 | height = rect.height; 53 | inputWidth.text = width.ToString(); 54 | inputHeight.text = height.ToString(); 55 | } 56 | 57 | public void SetImageSize() 58 | { 59 | Debug.Log("inputWidth.text: " + inputWidth.text); 60 | width = float.Parse(inputWidth.text); 61 | height = float.Parse(inputHeight.text); 62 | image.rectTransform.sizeDelta = new Vector2(width, height); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /GetSetImg.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using UnityEngine.UI; 23 | 24 | public class GetSetImg : MonoBehaviour 25 | { 26 | public GameObject imageGameObj; 27 | Image image; 28 | float width; 29 | float height; 30 | Rect rect; 31 | 32 | // Start is called before the first frame update 33 | void Start() 34 | { 35 | image = imageGameObj.GetComponent(); 36 | } 37 | 38 | public void GetImageSize() 39 | { 40 | rect = image.rectTransform.rect; 41 | width = rect.width; 42 | height = rect.height; 43 | } 44 | 45 | public void SetImageSize() 46 | { 47 | image.rectTransform.sizeDelta = new Vector2(width, height); 48 | } 49 | } 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LayerMask.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | 23 | public class LayerMask : MonoBehaviour 24 | { 25 | private int layerNumber = 6; 26 | private int layerMask; 27 | private RaycastHit raycastHit; 28 | 29 | // Start is called before the first frame update 30 | void Start() 31 | { 32 | layerMask = 1 << layerNumber; // Bitwise left shift operator to represent layer number by a single bit in the 32-bit integer 33 | } 34 | 35 | // Update is called once per frame 36 | void Update() 37 | { 38 | Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); 39 | 40 | 41 | if (Physics.Raycast(ray, out raycastHit, Mathf.Infinity, layerMask)) 42 | 43 | 44 | { 45 | Debug.Log("Ray hit " + raycastHit.transform.gameObject.layer); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /LinkToToogle.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using TMPro; 23 | 24 | public class LinkToToogle : MonoBehaviour 25 | { 26 | public GameObject tmpGameOBJ; 27 | private TMP_Text tmpText; 28 | private bool isToggleOn = true; 29 | 30 | // Start is called before the first frame update 31 | void Start() 32 | { 33 | tmpText = tmpGameOBJ.GetComponent(); 34 | tmpText.text = "Toggle is On!"; 35 | } 36 | 37 | // Update is called once per frame void Update() {} 38 | 39 | public void OnToggleChange(bool tickOn) 40 | { 41 | if(tickOn) 42 | { 43 | tmpText.text = "Toggle is On!"; 44 | } 45 | else 46 | { 47 | tmpText.text = "Toggle is Off!"; 48 | } 49 | isToggleOn = tickOn; //Pass boolean to another variable if needed 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Map.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using UnityEngine.UI; 23 | using UnityEngine.Networking; 24 | using System; 25 | 26 | public class Map : MonoBehaviour 27 | { 28 | public string accessToken; 29 | public enum style { Light, Dark, Streets, Outdoors, Satellite, SatelliteStreets }; 30 | public style mapStyle = style.Streets; 31 | public enum resolution { low = 1, high = 2 }; 32 | public resolution mapResolution = resolution.low; 33 | public double[] boundingBox = new double[] { 151.196023022085, -33.8777251205232, 151.216012372138, -33.8683894791246 }; //[lon(min), lat(min), lon(max), lat(max)] 34 | 35 | private string[] styleStr = new string[] { "light-v10", "dark-v10", "streets-v11", "outdoors-v11", "satellite-v9", "satellite-streets-v11" }; 36 | private string url = ""; 37 | private Material mapMaterial; 38 | private int mapWidthPx = 1280; 39 | private int mapHeightPx = 1280; 40 | private double planeWidth; 41 | private double planeHeight; 42 | 43 | 44 | // Start is called before the first frame update 45 | void Start() 46 | { 47 | MatchPlaneToScreenSize(); 48 | if (gameObject.GetComponent() == null) 49 | { 50 | gameObject.AddComponent(); 51 | } 52 | mapMaterial = new Material(Shader.Find("Unlit/Texture")); 53 | gameObject.GetComponent().material = mapMaterial; 54 | StartCoroutine(GetMapbox()); 55 | } 56 | 57 | // Update is called once per frame void Update(){ } 58 | 59 | public void GenerateMapOnClick() 60 | { 61 | StartCoroutine(GetMapbox()); 62 | } 63 | 64 | IEnumerator GetMapbox() 65 | { 66 | url = "https://api.mapbox.com/styles/v1/mapbox/" + styleStr[(int)mapStyle] + "/static/[" + boundingBox[0] + "," + boundingBox[1] + "," + boundingBox[2] + "," + boundingBox[3] + "]/" + mapWidthPx + "x" + mapHeightPx + "?" + "access_token=" + accessToken; 67 | UnityWebRequest www = UnityWebRequestTexture.GetTexture(url); 68 | yield return www.SendWebRequest(); 69 | if (www.result != UnityWebRequest.Result.Success) 70 | { 71 | Debug.Log("WWW ERROR: " + www.error); 72 | } 73 | else 74 | { 75 | gameObject.GetComponent().material.SetTexture("_MainTex", ((DownloadHandlerTexture)www.downloadHandler).texture); 76 | } 77 | } 78 | 79 | 80 | //Set the scale of plane to match the screen size 81 | private void MatchPlaneToScreenSize() 82 | { 83 | double planeToCameraDistance = Vector3.Distance(gameObject.transform.position, Camera.main.transform.position); 84 | double planeHeightScale = (2.0 * Math.Tan(0.5f * Camera.main.fieldOfView * (Math.PI / 180)) * planeToCameraDistance) / 10.0; //Radians = (Math.PI / 180) * degrees. Default plane is 10 units in x and z 85 | double planeWidthScale = planeHeightScale * Camera.main.aspect; 86 | gameObject.transform.localScale = new Vector3((float)planeWidthScale, 1, (float)planeHeightScale); 87 | //Set map width and height in pixel based on view aspec ratio 88 | if (Camera.main.aspect > 1) //Width is bigger than height 89 | { 90 | mapWidthPx = 1280; //Mapbox width should be a number between 1 and 1280 pixels. 91 | mapHeightPx = (int)Math.Round(1280 / Camera.main.aspect); //Height is proportional to to view aspect ratio 92 | } 93 | else //Height is bigger than width 94 | { 95 | mapHeightPx = 1280; //Mapbox height should be a number between 1 and 1280 pixels. 96 | mapWidthPx = (int)Math.Round(1280 / Camera.main.aspect); //Width is proportional to to view aspect ratio 97 | } 98 | } 99 | 100 | 101 | } -------------------------------------------------------------------------------- /MapControl.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using UnityEngine.Networking; 23 | using System; 24 | using TMPro; 25 | 26 | public class MapControl : MonoBehaviour 27 | { 28 | //Public variables for Mapbox request 29 | public string accessToken; 30 | public double centerLongitude = 151.20601823658595; //Change to the longitude of the centre of the area you need 31 | public double centerLatitude = -33.87305769270712; //Change to the latitude of the centre of the area you need 32 | public enum style { Light, Dark, Streets, Outdoors, Satellite, SatelliteStreets }; 33 | public style mapStyle = style.Streets; 34 | public enum resolution { low = 1, high = 2 }; 35 | public resolution mapResolution = resolution.low; 36 | 37 | public TextMeshProUGUI loadingText; //Text to show while map is loading 38 | 39 | //Private variables update map setting and update 40 | private double[] boundingBox; 41 | private string[] styleStr = new string[] { "light-v10", "dark-v10", "streets-v11", "outdoors-v11", "satellite-v9", "satellite-streets-v11" }; 42 | private string url = ""; 43 | private bool updateMap = true; 44 | private bool ResetMap = false; 45 | private Material mapMaterial; 46 | private Vector2 screenResolution; 47 | private double mapWidthMeter; 48 | private double mapHeightMeter; 49 | private int mapWidthPx = 1280; 50 | private int mapHeightPx = 1280; 51 | private double planeToCameraDistance; 52 | private bool mapIsLoading = false; 53 | private int framesSinceMapLoaded = 0; 54 | private int minFramesSinceMapLoaded = 60; 55 | 56 | //Variables to keep track of change in public variables and trigger update when user change them 57 | private string accessTokenLast; 58 | private double centerLongitudeLast = 151.20601823658595; 59 | private double centerLatitudeLast = -33.87305769270712; 60 | private style mapStyleLast = style.Streets; 61 | private resolution mapResolutionLast = resolution.low; 62 | 63 | 64 | // Start is called before the first frame update 65 | void Start() 66 | { 67 | planeToCameraDistance = Vector3.Distance(gameObject.transform.position, Camera.main.transform.position); 68 | screenResolution = new Vector2(Screen.width, Screen.height); 69 | MatchPlaneToScreenSize(); 70 | if (gameObject.GetComponent() == null) 71 | { 72 | gameObject.AddComponent(); 73 | } 74 | mapMaterial = new Material(Shader.Find("Unlit/Texture")); 75 | gameObject.GetComponent().material = mapMaterial; 76 | StartCoroutine(GetMapbox()); 77 | } 78 | 79 | // Update is called once per frame 80 | void Update() 81 | { 82 | if (mapIsLoading) 83 | { 84 | loadingText.gameObject.SetActive(true); 85 | gameObject.GetComponent().enabled = false; 86 | framesSinceMapLoaded = 0; 87 | } 88 | else 89 | { 90 | framesSinceMapLoaded++; 91 | if (framesSinceMapLoaded > minFramesSinceMapLoaded) //Show map after defined time since last map load to avoid map flickering 92 | { 93 | loadingText.gameObject.SetActive(false); 94 | gameObject.GetComponent().enabled = true; 95 | framesSinceMapLoaded = 0; 96 | } 97 | if (ResetMap || screenResolution.x != Screen.width || screenResolution.y != Screen.height || !Mathf.Approximately((float)planeToCameraDistance, Vector3.Distance(gameObject.transform.position, Camera.main.transform.position))) //Check change to screen size or camera position 98 | { 99 | planeToCameraDistance = Vector3.Distance(gameObject.transform.position, Camera.main.transform.position); 100 | screenResolution.x = Screen.width; 101 | screenResolution.y = Screen.height; 102 | MatchPlaneToScreenSize(); 103 | StartCoroutine(GetMapbox()); 104 | updateMap = false; 105 | } 106 | 107 | else if (ResetMap || (updateMap && (accessTokenLast != accessToken || !Mathf.Approximately((float)centerLongitudeLast, (float)centerLongitude) || !Mathf.Approximately((float)centerLatitudeLast, (float)centerLatitude) || mapStyleLast != mapStyle || mapResolutionLast != mapResolution))) //Check if user change any public variable 108 | { 109 | StartCoroutine(GetMapbox()); 110 | updateMap = false; 111 | } 112 | } 113 | } 114 | 115 | 116 | IEnumerator GetMapbox() 117 | { 118 | mapIsLoading = true; 119 | boundingBox = GetRecMinMaxLonLat(centerLongitude, centerLatitude, mapWidthMeter, mapHeightMeter); 120 | url = "https://api.mapbox.com/styles/v1/mapbox/" + styleStr[(int)mapStyle] + "/static/[" + boundingBox[0] + "," + boundingBox[1] + "," + boundingBox[2] + "," + boundingBox[3] + "]/" + mapWidthPx + "x" + mapHeightPx + "?" + "access_token=" + accessToken; 121 | UnityWebRequest www = UnityWebRequestTexture.GetTexture(url); 122 | yield return www.SendWebRequest(); 123 | if (www.result != UnityWebRequest.Result.Success) 124 | { 125 | Debug.Log("WWW ERROR: " + www.error); 126 | //Reset to previously working status 127 | accessToken = accessTokenLast; 128 | centerLongitude = centerLongitudeLast; 129 | centerLatitude = centerLatitudeLast; 130 | mapStyle = mapStyleLast; 131 | mapResolution = mapResolutionLast; 132 | updateMap = true; 133 | ResetMap = true; 134 | } 135 | else 136 | { 137 | gameObject.GetComponent().material.SetTexture("_MainTex", ((DownloadHandlerTexture)www.downloadHandler).texture); 138 | //Update variables to keep track of changes in public variables by the user 139 | accessTokenLast = accessToken; 140 | centerLongitudeLast = centerLongitude; 141 | centerLatitudeLast = centerLatitude; 142 | mapStyleLast = mapStyle; 143 | mapResolutionLast = mapResolution; 144 | updateMap = true; 145 | ResetMap = false; 146 | } 147 | mapIsLoading = false; 148 | } 149 | 150 | 151 | //Set the scale of plane to match the screen size 152 | private void MatchPlaneToScreenSize() 153 | { 154 | double planeHeightScale = 2.0 * Camera.main.orthographicSize / 10.0; //Orthographic Camera. Radians = (Math.PI / 180) * degrees. Default plane is 10 units in x and z 155 | double planeWidthScale = planeHeightScale * Camera.main.aspect; 156 | gameObject.transform.localScale = new Vector3((float)planeWidthScale, 1, (float)planeHeightScale); 157 | mapWidthMeter = planeWidthScale * 10.0; //Assuming each Unity unit is 1 m in real world. Default plane is 10 units in x and z 158 | mapHeightMeter = planeHeightScale * 10.0; //Assuming each Unity unit is 1 m in real world. Default plane is 10 units in x and z 159 | //Set map width and height in pixel based on view aspec ratio 160 | if (Camera.main.aspect > 1) //Width is bigger than height 161 | { 162 | mapWidthPx = 1280; //Mapbox width should be a number between 1 and 1280 pixels. 163 | mapHeightPx = (int)Math.Round(1280 / Camera.main.aspect); //Height is proportional to to view aspect ratio 164 | } 165 | else //Height is bigger than width 166 | { 167 | mapHeightPx = 1280; //Mapbox height should be a number between 1 and 1280 pixels. 168 | mapWidthPx = (int)Math.Round(1280 / Camera.main.aspect); //Width is proportional to to view aspect ratio 169 | } 170 | } 171 | 172 | 173 | //Return map bounding box [minLon, minLat, maxLon, maxLat] using center(lon, lat) in decimal degree, and map width and height 174 | private double[] GetRecMinMaxLonLat(double centerLon, double centerLat, double width, double height) 175 | { 176 | double distance = Math.Sqrt(Math.Pow(height / 2.0, 2) + Math.Pow(width / 2.0, 2)); //Hypotenuse from two sides 177 | double topRightBearing = Math.Atan((width / 2.0) / (height / 2.0)); //Bearing in radian 178 | double bottomLeftBearing = 3.14159f + topRightBearing; //bottomLeftBearing = 180 + topRightBearing. 180 degree = 3.14159 radian. 179 | double[] bottomLeft = GetPointLonLat(centerLon, centerLat, distance, bottomLeftBearing); 180 | double[] topRight = GetPointLonLat(centerLon, centerLat, distance, topRightBearing); 181 | return new double[] { bottomLeft[0], bottomLeft[1], topRight[0], topRight[1] }; 182 | } 183 | 184 | 185 | //Based on on a Stackoverflow answer by David M https://stackoverflow.com/questions/7222382/get-lat-long-given-current-point-distance-and-bearing 186 | //Return a point(lon, lat) in decimal degree using start point (lon, lat) in decimal degree and distance from it in meter and bearing (Agnle measured clockwise from north) in radian 187 | private double[] GetPointLonLat(double startLonDegree, double startLatDegree, double distance, double bearingRadian) 188 | { 189 | double earthRadius = 6378100.000; //In meters 190 | double startLatRadians = startLatDegree * (Math.PI / 180); //Radians = Degree * (PI / 180) 191 | double startLonRadians = startLonDegree * (Math.PI / 180); //Radians = Degree * (PI / 180) 192 | double targetLatRadians = Math.Asin(Math.Sin(startLatRadians) * Math.Cos(distance / earthRadius) + Math.Cos(startLatRadians) * Math.Sin(distance / earthRadius) * Math.Cos(bearingRadian)); 193 | double targetLonRadians = startLonRadians + Math.Atan2(Math.Sin(bearingRadian) * Math.Sin(distance / earthRadius) * Math.Cos(startLatRadians), Math.Cos(distance / earthRadius) - Math.Sin(startLatRadians) * Math.Sin(targetLatRadians)); 194 | return new double[] { targetLonRadians * (180.0 / Math.PI), targetLatRadians * (180.0 / Math.PI) }; //Degree = (180 / Math.PI) * Radian 195 | } 196 | 197 | } -------------------------------------------------------------------------------- /Mapbox.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using UnityEngine.UI; 23 | using UnityEngine.Networking; 24 | using System; 25 | 26 | public class Mapbox : MonoBehaviour 27 | { 28 | public string accessToken; 29 | public float centerLatitude = -33.8873f; 30 | public float centerLongitude = 151.2189f; 31 | public float zoom = 12.0f; 32 | public int bearing = 0; 33 | public int pitch = 0; 34 | public enum style {Light, Dark, Streets, Outdoors, Satellite, SatelliteStreets}; 35 | public style mapStyle = style.Streets; 36 | public enum resolution { low = 1, high = 2 }; 37 | public resolution mapResolution = resolution.low; 38 | 39 | private int mapWidth = 800; 40 | private int mapHeight = 600; 41 | private string[] styleStr = new string[] { "light-v10", "dark-v10", "streets-v11", "outdoors-v11", "satellite-v9", "satellite-streets-v11" }; 42 | private string url = ""; 43 | private bool mapIsLoading = false; 44 | private Rect rect; 45 | private bool updateMap = true; 46 | 47 | private string accessTokenLast; 48 | private float centerLatitudeLast = -33.8873f; 49 | private float centerLongitudeLast = 151.2189f; 50 | private float zoomLast = 12.0f; 51 | private int bearingLast = 0; 52 | private int pitchLast = 0; 53 | private style mapStyleLast = style.Streets; 54 | private resolution mapResolutionLast = resolution.low; 55 | 56 | // Start is called before the first frame update 57 | void Start() 58 | { 59 | StartCoroutine(GetMapbox()); 60 | rect = gameObject.GetComponent().rectTransform.rect; 61 | mapWidth = (int)Math.Round(rect.width); 62 | mapHeight = (int)Math.Round(rect.height); 63 | } 64 | 65 | // Update is called once per frame 66 | void Update() 67 | { 68 | if (updateMap && (accessTokenLast != accessToken || !Mathf.Approximately(centerLatitudeLast, centerLatitude) || !Mathf.Approximately(centerLongitudeLast, centerLongitude) || zoomLast != zoom || bearingLast != bearing || pitchLast != pitch || mapStyleLast != mapStyle || mapResolutionLast != mapResolution)) 69 | { 70 | rect = gameObject.GetComponent().rectTransform.rect; 71 | mapWidth = (int)Math.Round(rect.width); 72 | mapHeight = (int)Math.Round(rect.height); 73 | StartCoroutine(GetMapbox()); 74 | updateMap = false; 75 | } 76 | } 77 | 78 | 79 | IEnumerator GetMapbox() 80 | { 81 | url = "https://api.mapbox.com/styles/v1/mapbox/" + styleStr[(int)mapStyle] + "/static/" + centerLongitude + "," + centerLatitude + "," + zoom + "," + bearing + "," + pitch + "/" + mapWidth + "x" + mapHeight + "?" + "access_token=" + accessToken; 82 | mapIsLoading = true; 83 | UnityWebRequest www = UnityWebRequestTexture.GetTexture(url); 84 | yield return www.SendWebRequest(); 85 | if (www.result != UnityWebRequest.Result.Success) 86 | { 87 | Debug.Log("WWW ERROR: " + www.error); 88 | } 89 | else 90 | { 91 | mapIsLoading = false; 92 | gameObject.GetComponent().texture = ((DownloadHandlerTexture)www.downloadHandler).texture; 93 | 94 | accessTokenLast = accessToken; 95 | centerLatitudeLast = centerLatitude; 96 | centerLongitudeLast = centerLongitude; 97 | zoomLast = zoom; 98 | bearingLast = bearing; 99 | pitchLast = pitch; 100 | mapStyleLast = mapStyle; 101 | mapResolutionLast = mapResolution; 102 | updateMap = true; 103 | } 104 | } 105 | } 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /MeshLog.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using System.Text; 23 | using System; 24 | 25 | public class MeshLog : MonoBehaviour 26 | { 27 | public GameObject model; 28 | private Color modelColor; 29 | // Start is called before the first frame update void Start(){} 30 | // Update is called once per frame void Update(){} 31 | 32 | private string V3ArrayToStr(string varStr, Vector3[] v3Arr) 33 | { 34 | string str = "Vector3[] " + varStr + " = new Vector3[] {"; 35 | foreach (Vector3 vertex in v3Arr) 36 | { 37 | str = str + "new Vector3(" + vertex.x + "f, " + vertex.y + "f, " + vertex.z + "f), "; 38 | } 39 | if (str.Length > 1) 40 | { 41 | str = str.Remove(str.Length - 2); //Remove comma and the space at the end 42 | } 43 | str += "};"; 44 | return str; 45 | } 46 | 47 | 48 | private string IntArrayToStr(string varStr, int[] intArr) 49 | { 50 | string str = "int[] " + varStr + " = new int[] {"; 51 | foreach (int index in intArr) 52 | { 53 | str = str + index + ", "; 54 | } 55 | if (str.Length > 1) 56 | { 57 | str = str.Remove(str.Length - 2); //Remove comma and the space at the end 58 | } 59 | str += "};"; 60 | return str; 61 | } 62 | 63 | public void PrintModel() 64 | { 65 | for (int i = 0; i < model.GetComponentsInChildren().Length; i++) 66 | { 67 | Mesh mesh = model.GetComponentsInChildren()[i].mesh; 68 | modelColor = model.GetComponentsInChildren()[i].material.color; 69 | PrintMesh(mesh); 70 | } 71 | } 72 | 73 | 74 | private void PrintMesh(Mesh mesh) 75 | { 76 | Vector3[] vertices = mesh.vertices; 77 | Vector3[] normals = mesh.normals; 78 | int[] triangles = mesh.triangles; 79 | int[] indicies = mesh.GetIndices(0); 80 | if (model.GetComponent() == null) 81 | { 82 | model.AddComponent(); 83 | } 84 | 85 | StringBuilder sb = new StringBuilder(); 86 | sb.Append(V3ArrayToStr("vertices", vertices)); //vertices 87 | sb.Append(Environment.NewLine); 88 | sb.Append(V3ArrayToStr("normals", normals)); //normals 89 | sb.Append(Environment.NewLine); 90 | sb.Append(IntArrayToStr("triangles", triangles)); //triangles 91 | sb.Append(Environment.NewLine); 92 | sb.Append(IntArrayToStr("indicies", indicies)); //indicies 93 | sb.Append(Environment.NewLine); 94 | sb.Append("Color color = new Color(" + modelColor.r + "f, " + modelColor.g + "f, " + modelColor.b + "f, " + modelColor.a + "f);"); 95 | sb.Append(Environment.NewLine); 96 | sb.Append("Mesh mesh = new Mesh();"); 97 | sb.Append(Environment.NewLine); 98 | sb.Append("mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;"); 99 | sb.Append(Environment.NewLine); 100 | sb.Append("mesh.vertices = vertices;"); 101 | sb.Append(Environment.NewLine); 102 | sb.Append("mesh.normals = normals;"); 103 | sb.Append(Environment.NewLine); 104 | sb.Append("mesh.triangles = triangles;"); 105 | sb.Append(Environment.NewLine); 106 | sb.Append("mesh.SetIndices(indicies, MeshTopology." + mesh.GetTopology(0) + ", 0);"); 107 | sb.Append(Environment.NewLine); 108 | sb.Append("GameObject meshGameObj = new GameObject();"); 109 | sb.Append(Environment.NewLine); 110 | sb.Append("meshGameObj.AddComponent();"); 111 | sb.Append(Environment.NewLine); 112 | sb.Append("meshGameObj.AddComponent();"); 113 | sb.Append(Environment.NewLine); 114 | sb.Append("meshGameObj.GetComponent().mesh = mesh;"); 115 | sb.Append(Environment.NewLine); 116 | sb.Append("meshGameObj.GetComponent().material.color = color;"); 117 | 118 | Debug.Log(sb); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /Model.obj: -------------------------------------------------------------------------------- 1 | mtllib Model.mtl 2 | v -40.417620 -16.083082 -0.000000 3 | v -36.724971 25.747162 -0.000000 4 | v -40.417620 -16.083082 47.926505 5 | v -36.724971 25.747162 47.926505 6 | v -36.467448 28.664379 -0.000000 7 | v -36.467448 28.664379 47.926505 8 | v -46.709901 29.655886 -0.000000 9 | v -46.709901 29.655886 47.926505 10 | v -50.660072 -15.091573 -0.000000 11 | v -50.660072 -15.091573 47.926505 12 | vn 0.996126 -0.087935 0.000000 13 | vn 0.996126 -0.087935 0.000000 14 | vn 0.096353 0.995347 0.000000 15 | vn -0.996126 0.087935 0.000000 16 | vn -0.096354 -0.995347 -0.000000 17 | vn -0.000000 -0.000000 -1.000000 18 | vn 0.000000 0.000000 1.000000 19 | usemtl Model_Model.dgn_Default_0_0_255_vis 20 | f 1//1 2//1 4//1 21 | f 4//1 3//1 1//1 22 | f 2//2 5//2 6//2 23 | f 6//2 4//2 2//2 24 | f 5//3 7//3 8//3 25 | f 8//3 6//3 5//3 26 | f 7//4 9//4 10//4 27 | f 10//4 8//4 7//4 28 | f 9//5 1//5 3//5 29 | f 3//5 10//5 9//5 30 | f 2//6 1//6 9//6 31 | f 9//6 7//6 2//6 32 | f 7//6 5//6 2//6 33 | f 4//7 10//7 3//7 34 | f 10//7 4//7 8//7 35 | f 8//7 4//7 6//7 36 | 37 | v 46.730040 -24.506285 -0.000000 38 | v 50.660072 20.013084 -0.000000 39 | v 46.730040 -24.506285 47.926505 40 | v 50.660072 20.013084 47.926505 41 | v 40.599441 20.986992 -0.000000 42 | v 40.599441 20.986992 47.926505 43 | v 40.344897 18.103522 -0.000000 44 | v 40.344897 18.103522 47.926505 45 | v 36.669409 -23.532375 -0.000000 46 | v 36.669409 -23.532375 47.926505 47 | vn 0.996126 -0.087935 0.000000 48 | vn 0.096354 0.995347 0.000000 49 | vn -0.996126 0.087935 0.000000 50 | vn -0.996126 0.087935 0.000000 51 | vn -0.096354 -0.995347 -0.000000 52 | vn -0.000000 -0.000000 -1.000000 53 | vn 0.000000 0.000000 1.000000 54 | usemtl Model_Model.dgn_Default_0_0_255_vis 55 | f 11//8 12//8 14//8 56 | f 14//8 13//8 11//8 57 | f 12//9 15//9 16//9 58 | f 16//9 14//9 12//9 59 | f 15//10 17//10 18//10 60 | f 18//10 16//10 15//10 61 | f 17//11 19//11 20//11 62 | f 20//11 18//11 17//11 63 | f 19//12 11//12 13//12 64 | f 13//12 20//12 19//12 65 | f 12//13 11//13 17//13 66 | f 17//13 15//13 12//13 67 | f 11//13 19//13 17//13 68 | f 14//14 18//14 13//14 69 | f 18//14 14//14 16//14 70 | f 13//14 18//14 20//14 71 | 72 | v -2.738225 -27.406685 -0.000000 73 | v 2.081086 26.950696 -0.000000 74 | v -2.738225 -27.406685 50.000000 75 | v 2.081086 26.950696 50.000000 76 | v 23.579662 24.869555 -0.000000 77 | v 23.579662 24.869555 50.000000 78 | v 23.129492 19.770036 -0.000000 79 | v 23.129492 19.770036 50.000000 80 | v 21.008258 -22.016312 -0.000000 81 | v 21.008258 -22.016312 50.000000 82 | v 20.327426 -29.655886 -0.000000 83 | v 20.327426 -29.655886 50.000000 84 | vn -0.996093 0.088313 0.000000 85 | vn 0.096353 0.995347 0.000000 86 | vn 0.996126 -0.087935 0.000000 87 | vn 0.998714 -0.050699 0.000000 88 | vn 0.996052 -0.088767 0.000000 89 | vn -0.097053 -0.995279 -0.000000 90 | vn 0.000000 0.000000 -1.000000 91 | vn 0.000000 0.000000 1.000000 92 | usemtl Model_Model.dgn_Default_0_0_255_vis 93 | f 21//15 24//15 22//15 94 | f 24//15 21//15 23//15 95 | f 22//16 26//16 25//16 96 | f 26//16 22//16 24//16 97 | f 25//17 28//17 27//17 98 | f 28//17 25//17 26//17 99 | f 27//18 30//18 29//18 100 | f 30//18 27//18 28//18 101 | f 29//19 32//19 31//19 102 | f 32//19 29//19 30//19 103 | f 31//20 23//20 21//20 104 | f 23//20 31//20 32//20 105 | f 21//21 29//21 31//21 106 | f 29//21 21//21 27//21 107 | f 27//21 21//21 22//21 108 | f 27//21 22//21 25//21 109 | f 23//22 32//22 30//22 110 | f 30//22 28//22 23//22 111 | f 28//22 24//22 23//22 112 | f 28//22 26//22 24//22 113 | 114 | v 2.081086 26.950696 -0.000000 115 | v -19.417490 29.031837 -0.000000 116 | v 2.081086 26.950696 50.000000 117 | v -19.417490 29.031837 50.000000 118 | v -19.851643 24.113762 -0.000000 119 | v -19.851643 24.113762 50.000000 120 | v -25.127086 -17.563266 -0.000000 121 | v -25.127086 -17.563266 50.000000 122 | v -25.803877 -25.157485 -0.000000 123 | v -25.803877 -25.157485 50.000000 124 | v -2.738225 -27.406685 -0.000000 125 | v -2.738225 -27.406685 50.000000 126 | vn 0.096353 0.995347 0.000000 127 | vn -0.996126 0.087935 0.000000 128 | vn -0.992084 0.125577 0.000000 129 | vn -0.996052 0.088767 0.000000 130 | vn -0.097053 -0.995279 -0.000000 131 | vn 0.996093 -0.088313 0.000000 132 | vn 0.000000 0.000000 -1.000000 133 | vn 0.000000 0.000000 1.000000 134 | usemtl Model_Model.dgn_Default_0_0_255_vis 135 | f 33//23 34//23 36//23 136 | f 36//23 35//23 33//23 137 | f 34//24 37//24 38//24 138 | f 38//24 36//24 34//24 139 | f 37//25 39//25 40//25 140 | f 40//25 38//25 37//25 141 | f 39//26 41//26 42//26 142 | f 42//26 40//26 39//26 143 | f 41//27 43//27 44//27 144 | f 44//27 42//27 41//27 145 | f 43//28 33//28 35//28 146 | f 35//28 44//28 43//28 147 | f 39//29 37//29 43//29 148 | f 43//29 41//29 39//29 149 | f 37//29 33//29 43//29 150 | f 37//29 34//29 33//29 151 | f 40//30 44//30 38//30 152 | f 44//30 40//30 42//30 153 | f 38//30 44//30 35//30 154 | f 38//30 35//30 36//30 155 | 156 | v 40.344897 18.103522 -0.000000 157 | v 36.669409 -23.532375 -0.000000 158 | v 40.344897 18.103522 45.000000 159 | v 36.669409 -23.532375 45.000000 160 | v 21.008258 -22.016312 -0.000000 161 | v 21.008258 -22.016312 45.000000 162 | v 23.129492 19.770036 -0.000000 163 | v 23.129492 19.770036 45.000000 164 | vn 0.996126 -0.087935 0.000000 165 | vn -0.096354 -0.995347 -0.000000 166 | vn -0.998714 0.050699 0.000000 167 | vn 0.096353 0.995347 0.000000 168 | vn 0.000000 0.000000 -1.000000 169 | vn 0.000000 0.000000 1.000000 170 | usemtl Model_Model.dgn_Default_0_0_255_vis 171 | f 45//31 48//31 46//31 172 | f 48//31 45//31 47//31 173 | f 46//32 50//32 49//32 174 | f 50//32 46//32 48//32 175 | f 49//33 52//33 51//33 176 | f 52//33 49//33 50//33 177 | f 51//34 47//34 45//34 178 | f 47//34 51//34 52//34 179 | f 49//35 45//35 46//35 180 | f 45//35 49//35 51//35 181 | f 50//36 48//36 47//36 182 | f 47//36 52//36 50//36 183 | 184 | v -25.127086 -17.563266 -0.000000 185 | v -19.851643 24.113762 -0.000000 186 | v -25.127086 -17.563266 45.000000 187 | v -19.851643 24.113762 45.000000 188 | v -36.724971 25.747162 -0.000000 189 | v -36.724971 25.747162 45.000000 190 | v -40.417620 -16.083082 -0.000000 191 | v -40.417620 -16.083082 45.000000 192 | vn 0.992084 -0.125577 0.000000 193 | vn 0.096353 0.995347 0.000000 194 | vn -0.996126 0.087935 0.000000 195 | vn -0.096354 -0.995347 -0.000000 196 | vn -0.000000 -0.000000 -1.000000 197 | vn 0.000000 0.000000 1.000000 198 | usemtl Model_Model.dgn_Default_0_0_255_vis 199 | f 53//37 54//37 56//37 200 | f 56//37 55//37 53//37 201 | f 54//38 57//38 58//38 202 | f 58//38 56//38 54//38 203 | f 57//39 59//39 60//39 204 | f 60//39 58//39 57//39 205 | f 59//40 53//40 55//40 206 | f 55//40 60//40 59//40 207 | f 53//41 59//41 57//41 208 | f 57//41 54//41 53//41 209 | f 55//42 58//42 60//42 210 | f 58//42 55//42 56//42 211 | 212 | v 23.579662 24.869555 50.000000 213 | v 2.081086 26.950696 53.577660 214 | v -2.738225 -27.406685 53.577660 215 | v 20.327426 -29.655886 50.000000 216 | vn 0.162780 -0.014432 0.986557 217 | vn 0.152403 -0.009090 0.988277 218 | usemtl Model_Model.dgn_Default_0_0_255_vis 219 | f 63//43 61//43 62//43 220 | f 61//44 63//44 64//44 221 | 222 | v 2.081086 26.950696 53.577660 223 | v -2.738225 -27.406685 53.577660 224 | v -25.803877 -25.157485 50.000000 225 | v -19.417490 29.031837 50.000000 226 | vn 0.162780 -0.014432 -0.986557 227 | vn 0.151549 -0.017861 -0.988288 228 | usemtl Model_Model.dgn_Default_0_0_255_vis 229 | f 66//45 68//45 65//45 230 | f 68//46 66//46 67//46 231 | 232 | v 23.579662 24.869555 50.000000 233 | v 2.081086 26.950696 53.577660 234 | v -19.417490 29.031837 50.000000 235 | v 2.081086 26.950696 50.000000 236 | vn -0.096353 -0.995347 -0.000000 237 | vn -0.096353 -0.995347 0.000000 238 | usemtl Model_Model.dgn_Default_0_0_255_vis 239 | f 70//47 72//47 69//47 240 | f 72//48 70//48 71//48 241 | 242 | v -25.803877 -25.157485 50.000000 243 | v -2.738225 -27.406685 53.577660 244 | v 20.327426 -29.655886 50.000000 245 | v -2.738225 -27.406685 50.000000 246 | vn 0.097053 0.995279 0.000000 247 | vn 0.097053 0.995279 0.000000 248 | usemtl Model_Model.dgn_Default_0_0_255_vis 249 | f 74//49 76//49 73//49 250 | f 76//50 74//50 75//50 251 | 252 | v -46.709901 29.655886 47.926505 253 | v -36.467448 28.664379 49.926505 254 | v -40.417620 -16.083082 49.926505 255 | v -50.660072 -15.091573 47.926505 256 | vn 0.190055 -0.016777 -0.981630 257 | vn 0.190055 -0.016777 -0.981630 258 | usemtl Model_Model.dgn_Default_0_0_255_vis 259 | f 78//51 80//51 77//51 260 | f 80//52 78//52 79//52 261 | 262 | v 46.730040 -24.506285 47.926505 263 | v 36.669409 -23.532375 49.926505 264 | v 40.599441 20.986992 49.926505 265 | v 50.660072 20.013084 47.926505 266 | vn -0.193361 0.017069 -0.980979 267 | vn -0.193361 0.017069 -0.980979 268 | usemtl Model_Model.dgn_Default_0_0_255_vis 269 | f 82//53 84//53 81//53 270 | f 84//54 82//54 83//54 271 | 272 | v 21.008258 -22.016312 50.000000 273 | v 23.129492 19.770036 50.000000 274 | v 40.344897 18.103522 45.000000 275 | v 36.669409 -23.532375 45.000000 276 | vn -0.301689 0.026632 -0.953034 277 | vn -0.277626 0.014093 -0.960586 278 | usemtl Model_Model.dgn_Default_0_0_255_vis 279 | f 85//55 87//55 88//55 280 | f 87//56 85//56 86//56 281 | 282 | v -19.851643 24.113762 50.000000 283 | v -25.127086 -17.563266 50.000000 284 | v -40.417620 -16.083082 45.000000 285 | v -36.724971 25.747162 45.000000 286 | v -19.987421 24.469981 49.972056 287 | vn 0.286997 0.034294 -0.957317 288 | vn 0.280771 -0.035540 -0.959117 289 | vn 0.308308 -0.027217 -0.950897 290 | usemtl Model_Model.dgn_Default_0_0_255_vis 291 | f 89//57 92//57 93//57 292 | f 92//58 89//58 90//58 293 | f 92//59 90//59 91//59 294 | 295 | v -46.709901 29.655886 -0.000000 296 | v -50.660072 -15.091573 -0.000000 297 | v -25.127086 -17.563266 -0.000000 298 | v -25.803877 -25.157485 -0.000000 299 | v 20.327426 -29.655886 -0.000000 300 | v 21.008258 -22.016312 -0.000000 301 | v 46.730040 -24.506285 -0.000000 302 | v 50.660072 20.013084 -0.000000 303 | v 40.599441 20.986992 -0.000000 304 | v 40.344897 18.103522 -0.000000 305 | v 23.129492 19.770036 -0.000000 306 | v 23.579662 24.869555 -0.000000 307 | v -19.417490 29.031837 -0.000000 308 | v -19.851643 24.113762 -0.000000 309 | v -36.724971 25.747162 -0.000000 310 | v -36.467448 28.664379 -0.000000 311 | v -46.709901 29.655886 47.926505 312 | v -36.467448 28.664379 49.926505 313 | v -36.467448 28.664379 47.926505 314 | v -40.417620 -16.083082 49.926505 315 | v -50.660072 -15.091573 47.926505 316 | v -40.417620 -16.083082 47.926505 317 | v -40.417620 -16.083082 49.926505 318 | v -36.467448 28.664379 49.926505 319 | v -36.467448 28.664379 47.926505 320 | v -40.417620 -16.083082 47.926505 321 | v 36.669409 -23.532375 49.926505 322 | v 46.730040 -24.506285 47.926505 323 | v 36.669409 -23.532375 47.926505 324 | v 50.660072 20.013084 47.926505 325 | v 40.599441 20.986992 49.926505 326 | v 40.599441 20.986992 47.926505 327 | v 40.599441 20.986992 49.926505 328 | v 36.669409 -23.532375 49.926505 329 | v 36.669409 -23.532375 47.926505 330 | v 40.599441 20.986992 47.926505 331 | v 40.344897 18.103522 45.000000 332 | v 23.129492 19.770036 50.000000 333 | v 23.129492 19.770036 45.000000 334 | v 21.008258 -22.016312 45.000000 335 | v 21.008258 -22.016312 50.000000 336 | v 36.669409 -23.532375 45.000000 337 | v -25.127086 -17.563266 50.000000 338 | v -40.417620 -16.083082 45.000000 339 | v -25.127086 -17.563266 45.000000 340 | v -19.851643 24.113762 45.000000 341 | v -19.987421 24.469981 49.972056 342 | v -36.724971 25.747162 45.000000 343 | vn 0.000000 0.000000 1.000000 344 | vn 0.096353 0.995347 0.000000 345 | vn -0.096354 -0.995347 -0.000000 346 | vn -0.996126 0.087935 0.000000 347 | vn 0.096354 0.995347 0.000000 348 | vn -0.096354 -0.995347 0.000000 349 | vn 0.996126 -0.087935 0.000000 350 | vn -0.096353 -0.995347 0.000000 351 | vn 0.096354 0.995347 0.000000 352 | vn -0.096354 -0.995347 -0.000000 353 | vn -0.096127 -0.993008 0.068518 354 | usemtl Model_Model.dgn_Default_0_0_255_vis 355 | f 108//60 94//60 95//60 356 | f 94//60 108//60 109//60 357 | f 96//60 108//60 95//60 358 | f 108//60 96//60 107//60 359 | f 103//60 100//60 101//60 360 | f 100//60 103//60 99//60 361 | f 99//60 103//60 104//60 362 | f 99//60 104//60 96//60 363 | f 99//60 96//60 97//60 364 | f 99//60 97//60 98//60 365 | f 96//60 104//60 107//60 366 | f 107//60 105//60 106//60 367 | f 105//60 107//60 104//60 368 | f 103//60 101//60 102//60 369 | f 110//61 111//61 112//61 370 | f 113//62 114//62 115//62 371 | f 117//63 119//63 116//63 372 | f 119//63 117//63 118//63 373 | f 120//64 121//64 122//64 374 | f 123//65 124//65 125//65 375 | f 127//66 129//66 126//66 376 | f 129//66 127//66 128//66 377 | f 130//67 131//67 132//67 378 | f 133//68 134//68 135//68 379 | f 136//69 137//69 138//69 380 | f 139//70 140//70 141//70 381 | 382 | -------------------------------------------------------------------------------- /OpenFile.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.IO; 20 | using System.Text; 21 | using System.Collections; 22 | using System.Collections.Generic; 23 | using UnityEngine; 24 | using System.Runtime.InteropServices; 25 | using UnityEngine.UI; 26 | using SFB; 27 | using TMPro; 28 | using UnityEngine.Networking; 29 | using Dummiesman; //Load OBJ Model 30 | 31 | public class OpenFile : MonoBehaviour 32 | { 33 | public TextMeshProUGUI textMeshPro; 34 | public GameObject model; //Load OBJ Model 35 | 36 | #if UNITY_WEBGL && !UNITY_EDITOR 37 | // WebGL 38 | [DllImport("__Internal")] 39 | private static extern void UploadFile(string gameObjectName, string methodName, string filter, bool multiple); 40 | 41 | public void OnClickOpen() { 42 | UploadFile(gameObject.name, "OnFileUpload", ".obj", false); 43 | } 44 | 45 | // Called from browser 46 | public void OnFileUpload(string url) { 47 | StartCoroutine(OutputRoutineOpen(url)); 48 | } 49 | #else 50 | 51 | // Standalone platforms & editor 52 | public void OnClickOpen() 53 | { 54 | string[] paths = StandaloneFileBrowser.OpenFilePanel("Open File", "", "obj", false); 55 | if (paths.Length > 0) 56 | { 57 | StartCoroutine(OutputRoutineOpen(new System.Uri(paths[0]).AbsoluteUri)); 58 | } 59 | } 60 | #endif 61 | 62 | private IEnumerator OutputRoutineOpen(string url) 63 | { 64 | UnityWebRequest www = UnityWebRequest.Get(url); 65 | yield return www.SendWebRequest(); 66 | if (www.result != UnityWebRequest.Result.Success) 67 | { 68 | Debug.Log("WWW ERROR: " + www.error); 69 | } 70 | else 71 | { 72 | //textMeshPro.text = www.downloadHandler.text; 73 | 74 | //Load OBJ Model 75 | MemoryStream textStream = new MemoryStream(Encoding.UTF8.GetBytes(www.downloadHandler.text)); 76 | if (model != null) 77 | { 78 | Destroy(model); 79 | } 80 | model = new OBJLoader().Load(textStream); 81 | model.transform.localScale = new Vector3(-1, 1, 1); // set the position of parent model. Reverse X to show properly 82 | FitOnScreen(); 83 | DoublicateFaces(); 84 | } 85 | } 86 | 87 | private Bounds GetBound(GameObject gameObj) 88 | { 89 | Bounds bound = new Bounds(gameObj.transform.position, Vector3.zero); 90 | var rList = gameObj.GetComponentsInChildren(typeof(Renderer)); 91 | foreach (Renderer r in rList) 92 | { 93 | bound.Encapsulate(r.bounds); 94 | } 95 | return bound; 96 | } 97 | 98 | public void FitOnScreen() 99 | { 100 | Bounds bound = GetBound(model); 101 | Vector3 boundSize = bound.size; 102 | float diagonal = Mathf.Sqrt((boundSize.x * boundSize.x) + (boundSize.y * boundSize.y) + (boundSize.z * boundSize.z)); //Get box diagonal 103 | Camera.main.orthographicSize = diagonal / 2.0f; 104 | Camera.main.transform.position = bound.center; 105 | } 106 | 107 | 108 | 109 | // Doublicate the size of mesh components, in which the second half of the tringles winding order and normals are reverse of the first half to enable displaying front and back faces 110 | //https://answers.unity.com/questions/280741/how-make-visible-the-back-face-of-a-mesh.html 111 | public void DoublicateFaces() 112 | { 113 | for (int i = 0; i < model.GetComponentsInChildren().Length; i++) //Loop through the model children 114 | { 115 | // Get oringal mesh components: vertices, normals triangles and texture coordinates 116 | Mesh mesh = model.GetComponentsInChildren()[i].mesh; 117 | Vector3[] vertices = mesh.vertices; 118 | int numOfVertices = vertices.Length; 119 | Vector3[] normals = mesh.normals; 120 | int[] triangles = mesh.triangles; 121 | int numOfTriangles = triangles.Length; 122 | Vector2[] textureCoordinates = mesh.uv; 123 | if (textureCoordinates.Length < numOfTriangles) //Check if mesh doesn't have texture coordinates 124 | { 125 | textureCoordinates = new Vector2[numOfVertices * 2]; 126 | } 127 | 128 | // Create a new mesh component, double the size of the original 129 | Vector3[] newVertices = new Vector3[numOfVertices * 2]; 130 | Vector3[] newNormals = new Vector3[numOfVertices * 2]; 131 | int[] newTriangle = new int[numOfTriangles * 2]; 132 | Vector2[] newTextureCoordinates = new Vector2[numOfVertices * 2]; 133 | 134 | for (int j = 0; j < numOfVertices; j++) 135 | { 136 | newVertices[j] = newVertices[j + numOfVertices] = vertices[j]; //Copy original vertices to make the second half of the mew vertices array 137 | newTextureCoordinates[j] = newTextureCoordinates[j + numOfVertices] = textureCoordinates[j]; //Copy original texture coordinates to make the second half of the mew texture coordinates array 138 | newNormals[j] = normals[j]; //First half of the new normals array is a copy original normals 139 | newNormals[j + numOfVertices] = -normals[j]; //Second half of the new normals array reverse the original normals 140 | } 141 | 142 | for (int x = 0; x < numOfTriangles; x += 3) 143 | { 144 | // copy the original triangle for the first half of array 145 | newTriangle[x] = triangles[x]; 146 | newTriangle[x + 1] = triangles[x + 1]; 147 | newTriangle[x + 2] = triangles[x + 2]; 148 | // Reversed triangles for the second half of array 149 | int j = x + numOfTriangles; 150 | newTriangle[j] = triangles[x] + numOfVertices; 151 | newTriangle[j + 2] = triangles[x + 1] + numOfVertices; 152 | newTriangle[j + 1] = triangles[x + 2] + numOfVertices; 153 | } 154 | mesh.vertices = newVertices; 155 | mesh.uv = newTextureCoordinates; 156 | mesh.normals = newNormals; 157 | mesh.triangles = newTriangle; 158 | } 159 | } 160 | 161 | } -------------------------------------------------------------------------------- /OpenMesh.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using System.IO; 23 | 24 | public class OpenMesh : MonoBehaviour 25 | { 26 | public GameObject model; 27 | // Start is called before the first frame update void Start(){ } 28 | // Update is called once per frame void Update(){ } 29 | 30 | 31 | // Convert string "Vx Vy Vz'v|'Vx Vy Vz'v|'Vx Vy Vz'v|'Vx Vy Vz" to array of Vector3 32 | public Vector3[] StrToV3Arr(string arrStr, string splitStr) 33 | { 34 | string[] v3StrArr = arrStr.Split(splitStr); 35 | Vector3[] result = new Vector3[v3StrArr.Length]; 36 | for (int i = 0; i < v3StrArr.Length; i++) 37 | { 38 | string[] valuesStr = v3StrArr[i].Split(' '); 39 | if (valuesStr.Length != 3) 40 | { 41 | Debug.Log("component count mismatch. Expected 3 components but got " + valuesStr.Length); 42 | } 43 | result[i] = new Vector3(float.Parse(valuesStr[0]), float.Parse(valuesStr[1]), float.Parse(valuesStr[2])); 44 | } 45 | return result; 46 | } 47 | 48 | 49 | // Convert string "int int int int" to array of int 50 | public int[] StrToIntArr(string arrStr) 51 | { 52 | string[] intStrArr = arrStr.Split(' '); 53 | int[] result = new int[intStrArr.Length]; 54 | for (int i = 0; i < intStrArr.Length; i++) 55 | { 56 | result[i] = int.Parse(intStrArr[i]); 57 | } 58 | return result; 59 | } 60 | 61 | 62 | // Convert string: "r g b a" to colour 63 | public Color StrToColour(string colourStr) 64 | { 65 | Color resultColour = new Color(); 66 | string[] colourStrArr = colourStr.Split(' '); 67 | if (colourStrArr.Length != 4) 68 | { 69 | Debug.Log("StrToColour count mismatch. Expected 4 components but got " + colourStrArr.Length); 70 | } 71 | else 72 | { 73 | resultColour.r = float.Parse(colourStrArr[0]); 74 | resultColour.g = float.Parse(colourStrArr[1]); 75 | resultColour.b = float.Parse(colourStrArr[2]); 76 | resultColour.a = float.Parse(colourStrArr[3]); 77 | } 78 | return resultColour; 79 | } 80 | 81 | 82 | public void OnClickOpen() 83 | { 84 | string path = Application.persistentDataPath + "/model.dalab"; 85 | Debug.Log(Application.persistentDataPath); 86 | if (File.Exists(path)) 87 | { 88 | if (model != null) 89 | { 90 | foreach (Transform child in model.transform) 91 | { 92 | GameObject.Destroy(child.gameObject); 93 | } 94 | } 95 | model = StrToModel(File.ReadAllText(path), "mo|"); //Read Model ; 96 | } 97 | } 98 | 99 | 100 | // Convert model string to parent gameobject model containing children gameobjects meshe and material 101 | public GameObject StrToModel(string modelStr, string splitStr) 102 | { 103 | GameObject resultModel = new GameObject(); 104 | string[] modelStrArr = modelStr.Split(splitStr); 105 | for (int i = 0; i < modelStrArr.Length; i++) 106 | { 107 | GameObject resultObj = StrToGameObjectMesh(modelStrArr[i], "m|"); 108 | resultObj.transform.parent = resultModel.transform; //make the gameobj with mesh and material inside child of the model 109 | } 110 | resultModel.transform.localScale = new Vector3(-1, 1, 1); // set the position of parent model. Reverse X to show properly 111 | return resultModel; 112 | } 113 | 114 | 115 | // Convert string mesh: vertices(v3'v|'v3'v|'v3'v|'v3)'m|'normals(v3'n|'v3'n|'v3'n|'v3)'m|'triangles(int int int int)'m|'indicies(int int int int)'m|'meshTopology'm|'colour(r g b a) to GameObject containing a mesh 116 | public GameObject StrToGameObjectMesh(string meshStr, string splitStr) 117 | { 118 | GameObject meshObj = new GameObject(); 119 | Mesh resultMesh = new Mesh(); 120 | resultMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; //By default mesh support 16-bit index format which support buffer of 65535 so we need to increase is to 32 121 | Color resultColor = new Color(); 122 | string[] meshStrArr = meshStr.Split(splitStr); 123 | if (meshStrArr.Length != 6) 124 | { 125 | Debug.Log("StrToGameObjectMesh Warning. Number of elements in string array is: " + meshStrArr.Length + ". No mesh found!"); 126 | } 127 | else 128 | { 129 | Vector3[] resultVertices = StrToV3Arr(meshStrArr[0], "v|"); 130 | Vector3[] resultNormals = StrToV3Arr(meshStrArr[1], "n|"); 131 | int[] resultTriangles = StrToIntArr(meshStrArr[2]); 132 | int[] resultIndices = StrToIntArr(meshStrArr[3]); 133 | string meshTopoStr = meshStrArr[4]; 134 | resultColor = StrToColour(meshStrArr[5]); 135 | resultMesh.vertices = resultVertices; 136 | resultMesh.normals = resultNormals; 137 | resultMesh.triangles = resultTriangles; 138 | 139 | if (meshTopoStr == "Lines") //You can add conditions for other mesh topologies 140 | { 141 | resultMesh.SetIndices(resultIndices, MeshTopology.Lines, 0); 142 | } 143 | else 144 | { 145 | resultMesh.SetIndices(resultIndices, MeshTopology.Triangles, 0); 146 | } 147 | } 148 | meshObj.AddComponent(); 149 | meshObj.AddComponent(); 150 | meshObj.GetComponent().mesh = resultMesh; 151 | meshObj.GetComponent().material.color = resultColor; 152 | return meshObj; 153 | } 154 | 155 | 156 | 157 | 158 | } 159 | -------------------------------------------------------------------------------- /OutlineSelection.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using UnityEngine.EventSystems; 23 | 24 | public class OutlineSelection : MonoBehaviour 25 | { 26 | private Transform highlight; 27 | private Transform selection; 28 | private RaycastHit raycastHit; 29 | 30 | void Update() 31 | { 32 | // Highlight 33 | if (highlight != null) 34 | { 35 | highlight.gameObject.GetComponent().enabled = false; 36 | highlight = null; 37 | } 38 | Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); 39 | if (!EventSystem.current.IsPointerOverGameObject() && Physics.Raycast(ray, out raycastHit)) //Make sure you have EventSystem in the hierarchy before using EventSystem 40 | { 41 | highlight = raycastHit.transform; 42 | if (highlight.CompareTag("Selectable") && highlight != selection) 43 | { 44 | if (highlight.gameObject.GetComponent() != null) 45 | { 46 | highlight.gameObject.GetComponent().enabled = true; 47 | } 48 | else 49 | { 50 | Outline outline = highlight.gameObject.AddComponent(); 51 | outline.enabled = true; 52 | highlight.gameObject.GetComponent().OutlineColor = Color.magenta; 53 | highlight.gameObject.GetComponent().OutlineWidth = 7.0f; 54 | } 55 | } 56 | else 57 | { 58 | highlight = null; 59 | } 60 | } 61 | 62 | // Selection 63 | if (Input.GetMouseButtonDown(0)) 64 | { 65 | if (highlight) 66 | { 67 | if (selection != null) 68 | { 69 | selection.gameObject.GetComponent().enabled = false; 70 | } 71 | selection = raycastHit.transform; 72 | selection.gameObject.GetComponent().enabled = true; 73 | highlight = null; 74 | } 75 | else 76 | { 77 | if (selection) 78 | { 79 | selection.gameObject.GetComponent().enabled = false; 80 | selection = null; 81 | } 82 | } 83 | } 84 | } 85 | 86 | } 87 | 88 | -------------------------------------------------------------------------------- /PanZoomOrbitCenter.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using UnityEngine.EventSystems; 23 | 24 | public class PanZoomOrbitCenter : MonoBehaviour 25 | { 26 | private float rotationSpeed = 500.0f; 27 | private Vector3 mouseWorldPosStart; 28 | private float zoomScale = 5.0f; 29 | private float zoomMin = 0.5f; 30 | private float zoomMax = 100.0f; 31 | 32 | // Start is called before the first frame update 33 | void Start() 34 | { 35 | } 36 | 37 | // Update is called once per frame 38 | void Update() 39 | { 40 | // Check for Orbit, Pan, Zoom 41 | if (Input.GetKey(KeyCode.LeftShift) && Input.GetKey(KeyCode.Mouse2) && !EventSystem.current.IsPointerOverGameObject()) //Check for orbit 42 | { 43 | CamOrbit(); 44 | } 45 | if (Input.GetMouseButtonDown(2) && !Input.GetKey(KeyCode.LeftShift) && !EventSystem.current.IsPointerOverGameObject()) //Check for Pan 46 | { 47 | mouseWorldPosStart = Camera.main.ScreenToWorldPoint(Input.mousePosition); 48 | } 49 | if (Input.GetMouseButton(2) && !Input.GetKey(KeyCode.LeftShift) && !EventSystem.current.IsPointerOverGameObject()) 50 | { 51 | Pan(); 52 | } 53 | if (!EventSystem.current.IsPointerOverGameObject()) 54 | { 55 | Zoom(Input.GetAxis("Mouse ScrollWheel")); //Check for Zoom 56 | } 57 | } 58 | 59 | 60 | private void CamOrbit() 61 | { 62 | if (Input.GetAxis("Mouse Y") != 0 || Input.GetAxis("Mouse X") != 0) 63 | { 64 | float verticalInput = Input.GetAxis("Mouse Y") * rotationSpeed * Time.deltaTime; 65 | float horizontalInput = Input.GetAxis("Mouse X") * rotationSpeed * Time.deltaTime; 66 | transform.Rotate(Vector3.right, -verticalInput); 67 | transform.Rotate(Vector3.up, horizontalInput, Space.World); 68 | } 69 | } 70 | 71 | void Pan() 72 | { 73 | if (Input.GetAxis("Mouse Y") != 0 || Input.GetAxis("Mouse X") != 0) 74 | { 75 | Vector3 mouseWorldPosDiff = mouseWorldPosStart - Camera.main.ScreenToWorldPoint(Input.mousePosition); 76 | Camera.main.transform.position += mouseWorldPosDiff; 77 | } 78 | } 79 | 80 | void Zoom(float zoomDiff) 81 | { 82 | if (zoomDiff != 0) 83 | { 84 | mouseWorldPosStart = Camera.main.ScreenToWorldPoint(Input.mousePosition); 85 | Camera.main.orthographicSize = Mathf.Clamp(Camera.main.orthographicSize - zoomDiff * zoomScale, zoomMin, zoomMax); 86 | Vector3 mouseWorldPosDiff = mouseWorldPosStart - Camera.main.ScreenToWorldPoint(Input.mousePosition); 87 | Camera.main.transform.position += mouseWorldPosDiff; 88 | } 89 | } 90 | 91 | } 92 | 93 | -------------------------------------------------------------------------------- /RoundFloat.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | 23 | public class RoundFloat : MonoBehaviour 24 | { 25 | // Start is called before the first frame update 26 | void Start() 27 | { 28 | int numOfRoundedDecimals = 3; // The number of decimal points to preserve 29 | float currFloat = 55.00031f; 30 | currFloat = Mathf.Round(currFloat * Mathf.Pow(10, numOfRoundedDecimals)) / Mathf.Pow(10, numOfRoundedDecimals); 31 | 32 | Debug.Log("currFloat: " + currFloat); 33 | } 34 | 35 | // Update is called once per frame 36 | void Update() 37 | { 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SaveFile.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.IO; 20 | using System.Text; 21 | using System.Runtime.InteropServices; 22 | using System.Collections; 23 | using System.Collections.Generic; 24 | using UnityEngine; 25 | using UnityEngine.UI; 26 | using SFB; 27 | using System; 28 | using TMPro; 29 | 30 | public class SaveFile : MonoBehaviour 31 | { 32 | public TextMeshProUGUI textMeshPro; 33 | 34 | #if UNITY_WEBGL && !UNITY_EDITOR 35 | // WebGL 36 | [DllImport("__Internal")] 37 | private static extern void DownloadFile(string gameObjectName, string methodName, string filename, byte[] byteArray, int byteArraySize); 38 | 39 | public void OnClickSave() { 40 | var bytes = Encoding.UTF8.GetBytes(textMeshPro.text); 41 | DownloadFile(gameObject.name, "OnFileDownload", "model.obj", bytes, bytes.Length); 42 | } 43 | 44 | // Called from browser 45 | public void OnFileDownload() { } 46 | #else 47 | 48 | // Standalone platforms & editor 49 | public void OnClickSave() 50 | { 51 | string path = StandaloneFileBrowser.SaveFilePanel("Save File", "", "model", "obj"); 52 | if (!string.IsNullOrEmpty(path)) 53 | { 54 | File.WriteAllText(path, textMeshPro.text); 55 | } 56 | } 57 | #endif 58 | 59 | } 60 | -------------------------------------------------------------------------------- /SaveMesh.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using System.Text; 23 | using System.IO; 24 | 25 | public class SaveMesh : MonoBehaviour 26 | { 27 | public GameObject model; 28 | 29 | // Start is called before the first frame update 30 | void Start() 31 | { 32 | //Code generated mesh: https://youtu.be/_-UPgQ-k4ds 33 | Vector3[] vertices = new Vector3[] { new Vector3(-1f, 1f, -1f), new Vector3(1f, -1f, -1f), new Vector3(-1f, -1f, -1f), new Vector3(1f, 1f, -1f), new Vector3(1f, -1f, 1f), new Vector3(1f, 1f, -1f), new Vector3(1f, 1f, 1f), new Vector3(1f, -1f, -1f), new Vector3(-1f, -1f, 1f), new Vector3(1f, -1f, 1f), new Vector3(-0.999999f, 1f, 1.000001f), new Vector3(1f, 1f, 1f), new Vector3(-1f, -1f, -1f), new Vector3(-1f, -1f, 1f), new Vector3(-1f, 1f, -1f), new Vector3(-0.999999f, 1f, 1.000001f), new Vector3(-1f, 1f, -1f), new Vector3(-0.999999f, 1f, 1.000001f), new Vector3(1f, 1f, -1f), new Vector3(1f, 1f, 1f), new Vector3(-1f, -1f, -1f), new Vector3(1f, -1f, 1f), new Vector3(-1f, -1f, 1f), new Vector3(1f, -1f, -1f) }; 34 | Vector3[] normals = new Vector3[] { new Vector3(0f, 0f, -1f), new Vector3(0f, 0f, -1f), new Vector3(0f, 0f, -1f), new Vector3(0f, 0f, -1f), new Vector3(1f, 0f, 0f), new Vector3(1f, 0f, 0f), new Vector3(1f, 0f, 0f), new Vector3(1f, 0f, 0f), new Vector3(0f, 0f, 1f), new Vector3(0f, 0f, 1f), new Vector3(0f, 0f, 1f), new Vector3(0f, 0f, 1f), new Vector3(-1f, 0f, 0f), new Vector3(-1f, 0f, 0f), new Vector3(-1f, 0f, 0f), new Vector3(-1f, 0f, 0f), new Vector3(0f, 1f, 0f), new Vector3(0f, 1f, 0f), new Vector3(0f, 1f, 0f), new Vector3(0f, 1f, 0f), new Vector3(0f, -1f, 0f), new Vector3(0f, -1f, 0f), new Vector3(0f, -1f, 0f), new Vector3(0f, -1f, 0f) }; 35 | int[] triangles = new int[] { 0, 1, 2, 0, 3, 1, 4, 5, 6, 4, 7, 5, 8, 9, 10, 10, 9, 11, 12, 13, 14, 14, 13, 15, 16, 17, 18, 18, 17, 19, 20, 21, 22, 20, 23, 21 }; 36 | int[] indicies = new int[] { 0, 1, 2, 0, 3, 1, 4, 5, 6, 4, 7, 5, 8, 9, 10, 10, 9, 11, 12, 13, 14, 14, 13, 15, 16, 17, 18, 18, 17, 19, 20, 21, 22, 20, 23, 21 }; 37 | Color color = new Color(0f, 0.5334923f, 1f, 1f); 38 | Mesh mesh = new Mesh(); 39 | mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; 40 | mesh.vertices = vertices; 41 | mesh.normals = normals; 42 | mesh.triangles = triangles; 43 | mesh.SetIndices(indicies, MeshTopology.Triangles, 0); 44 | model = new GameObject(); 45 | model.AddComponent(); 46 | model.AddComponent(); 47 | model.GetComponent().mesh = mesh; 48 | model.GetComponent().material.color = color; 49 | } 50 | 51 | // Update is called once per frame void Update(){ } 52 | 53 | // Convert array of Vector3 to string "Vx Vy Vz'v|'Vx Vy Vz'v|'Vx Vy Vz'v|'Vx Vy Vz" 54 | public string V3ArrToStr(Vector3[] v3Arr, string splitStr) 55 | { 56 | StringBuilder sb = new StringBuilder(); 57 | foreach (Vector3 v3 in v3Arr) 58 | { 59 | sb.Append(v3.x).Append(" ").Append(v3.y).Append(" ").Append(v3.z).Append(splitStr); 60 | } 61 | if (sb.Length > 0) 62 | { 63 | sb.Remove(sb.Length - splitStr.Length, splitStr.Length); //remove last splitStr 64 | } 65 | return sb.ToString(); 66 | } 67 | 68 | 69 | // Convert array of int to string "int int int int" 70 | public string intArrToStr(int[] intArr) 71 | { 72 | StringBuilder sb = new StringBuilder(); 73 | foreach (int i in intArr) 74 | { 75 | sb.Append(i).Append(" "); 76 | } 77 | if (sb.Length > 0) 78 | { 79 | sb.Remove(sb.Length - 1, 1); //remove the last " " 80 | } 81 | return sb.ToString(); 82 | } 83 | 84 | 85 | // Convert RGBA colour to string: "r g b a" 86 | public string ColourToStr(Color colour) 87 | { 88 | StringBuilder sb = new StringBuilder(); 89 | sb.Append(colour.r).Append(" ").Append(colour.g).Append(" ").Append(colour.b).Append(" ").Append(colour.a); 90 | return sb.ToString(); 91 | } 92 | 93 | 94 | public void OnClickSave() 95 | { 96 | File.WriteAllText(Application.persistentDataPath + "/model.dalab", ModelToStr(ref model, "mo|")); 97 | Debug.Log(Application.persistentDataPath); 98 | } 99 | 100 | 101 | // Convery an GameObject model with meshes and materials inside to string 102 | public string ModelToStr(ref GameObject model, string splitStr) 103 | { 104 | StringBuilder sb = new StringBuilder(); 105 | for (int i = 0; i < model.GetComponentsInChildren().Length; i++) 106 | { 107 | Mesh mesh = model.GetComponentsInChildren()[i].mesh; 108 | Material material = model.GetComponentsInChildren()[i].material; 109 | sb.Append(MeshToStr(mesh, material.color, "m|")).Append(splitStr); 110 | } 111 | if (sb.Length > 0) 112 | { 113 | sb.Remove(sb.Length - splitStr.Length, splitStr.Length); // remove the last splitStr 114 | } 115 | return sb.ToString(); 116 | } 117 | 118 | 119 | // Convert a mesh to string: vertices(v3'v|'v3'v|'v3'v|'v3)'m|'normals(v3'n|'v3'n|'v3'n|'v3)'m|'triangles(int int int int)'m|'indicies(int int int int)'m|'meshTopology'm|'colour(r g b a) 120 | public string MeshToStr(Mesh mesh, Color meshColour, string splitStr) 121 | { 122 | StringBuilder sb = new StringBuilder(); 123 | sb.Append(V3ArrToStr(mesh.vertices, "v|")).Append(splitStr).Append(V3ArrToStr(mesh.normals, "n|")).Append(splitStr).Append(intArrToStr(mesh.triangles)) 124 | .Append(splitStr).Append(intArrToStr(mesh.GetIndices(0))).Append(splitStr).Append(mesh.GetTopology(0)).Append(splitStr).Append(ColourToStr(meshColour)); 125 | return sb.ToString(); 126 | } 127 | 128 | 129 | } 130 | -------------------------------------------------------------------------------- /SelectMove.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using UnityEngine.EventSystems; 23 | using TMPro; 24 | 25 | public class SelectMove : MonoBehaviour 26 | { 27 | public Material highlightMaterial; 28 | public Material selectionMaterial; 29 | public GameObject inputPosXGameObj; 30 | public GameObject inputPosYGameObj; 31 | public GameObject inputPosZGameObj; 32 | 33 | private Material originalMaterialHighlight; 34 | private Material originalMaterialSelection; 35 | private Transform highlight; 36 | private Transform selection; 37 | private RaycastHit raycastHit; 38 | private TMP_InputField inputPosX; 39 | private TMP_InputField inputPosY; 40 | private TMP_InputField inputPosZ; 41 | private float posX; 42 | private float posY; 43 | private float posZ; 44 | 45 | 46 | private void Start() 47 | { 48 | // Get InputField components from the GameObjects 49 | inputPosX = inputPosXGameObj.GetComponent(); 50 | inputPosY = inputPosYGameObj.GetComponent(); 51 | inputPosZ = inputPosZGameObj.GetComponent(); 52 | } 53 | 54 | 55 | void Update() 56 | { 57 | // Highlight 58 | if (highlight != null) 59 | { 60 | highlight.GetComponent().sharedMaterial = originalMaterialHighlight; 61 | highlight = null; 62 | } 63 | Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); 64 | if (!EventSystem.current.IsPointerOverGameObject() && Physics.Raycast(ray, out raycastHit)) //Make sure you have EventSystem in the hierarchy before using EventSystem 65 | { 66 | highlight = raycastHit.transform; 67 | if (highlight.CompareTag("Selectable") && highlight != selection) 68 | { 69 | if (highlight.GetComponent().material != highlightMaterial) 70 | { 71 | originalMaterialHighlight = highlight.GetComponent().material; 72 | highlight.GetComponent().material = highlightMaterial; 73 | } 74 | } 75 | else 76 | { 77 | highlight = null; 78 | } 79 | } 80 | 81 | // Selection 82 | if (Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject()) 83 | { 84 | if (highlight) 85 | { 86 | if (selection != null) 87 | { 88 | selection.GetComponent().material = originalMaterialSelection; 89 | } 90 | selection = raycastHit.transform; 91 | if (selection.GetComponent().material != selectionMaterial) 92 | { 93 | originalMaterialSelection = originalMaterialHighlight; 94 | selection.GetComponent().material = selectionMaterial; 95 | GetSelectedPos(); 96 | } 97 | highlight = null; 98 | } 99 | else 100 | { 101 | if (selection) 102 | { 103 | selection.GetComponent().material = originalMaterialSelection; 104 | selection = null; 105 | GetSelectedPos(); 106 | } 107 | } 108 | } 109 | 110 | } 111 | 112 | 113 | // Assign the positions X, Y, and Z of the selected Object to input fields. Hide the input fields if no object is selected 114 | private void GetSelectedPos() 115 | { 116 | if (selection) 117 | { 118 | Debug.Log("Check if"); 119 | inputPosXGameObj.SetActive(true); 120 | inputPosYGameObj.SetActive(true); 121 | inputPosZGameObj.SetActive(true); 122 | inputPosX.text = selection.position.x.ToString(); 123 | inputPosY.text = selection.position.y.ToString(); 124 | inputPosZ.text = selection.position.z.ToString(); 125 | } 126 | else 127 | { 128 | inputPosXGameObj.SetActive(false); 129 | inputPosYGameObj.SetActive(false); 130 | inputPosZGameObj.SetActive(false); 131 | } 132 | } 133 | 134 | 135 | // Attach to OnValueChanged event of corresponding input fields. Get value from the field and call the SetSelectedPos method 136 | public void SetPosX() 137 | { 138 | if (float.TryParse(inputPosX.text, out posX)) 139 | { 140 | SetSelectedPos(); 141 | } 142 | } 143 | public void SetPosY() 144 | { 145 | if (float.TryParse(inputPosY.text, out posY)) 146 | { 147 | SetSelectedPos(); 148 | } 149 | } 150 | public void SetPosZ() 151 | { 152 | if (float.TryParse(inputPosZ.text, out posZ)) 153 | { 154 | SetSelectedPos(); 155 | } 156 | } 157 | 158 | 159 | // Set the position of the selected object to match the user input 160 | public void SetSelectedPos() 161 | { 162 | if (selection && (inputPosX.isFocused || inputPosY.isFocused || inputPosZ.isFocused)) 163 | { 164 | 165 | selection.position = new Vector3(posX, posY, posZ); 166 | inputPosX.text = selection.position.x.ToString(); 167 | inputPosY.text = selection.position.y.ToString(); 168 | inputPosZ.text = selection.position.z.ToString(); 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /SelectTransformGizmo.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using UnityEngine.EventSystems; 23 | using RuntimeHandle; 24 | 25 | public class SelectTransformGizmo : MonoBehaviour 26 | { 27 | public Material highlightMaterial; 28 | public Material selectionMaterial; 29 | 30 | private Material originalMaterialHighlight; 31 | private Material originalMaterialSelection; 32 | private Transform highlight; 33 | private Transform selection; 34 | private RaycastHit raycastHit; 35 | private RaycastHit raycastHitHandle; 36 | private GameObject runtimeTransformGameObj; 37 | private RuntimeTransformHandle runtimeTransformHandle; 38 | private int runtimeTransformLayer = 6; 39 | private int runtimeTransformLayerMask; 40 | 41 | private void Start() 42 | { 43 | runtimeTransformGameObj = new GameObject(); 44 | runtimeTransformHandle = runtimeTransformGameObj.AddComponent(); 45 | runtimeTransformGameObj.layer = runtimeTransformLayer; 46 | runtimeTransformLayerMask = 1 << runtimeTransformLayer; //Layer number represented by a single bit in the 32-bit integer using bit shift 47 | runtimeTransformHandle.type = HandleType.POSITION; 48 | runtimeTransformHandle.autoScale = true; 49 | runtimeTransformHandle.autoScaleFactor = 1.0f; 50 | runtimeTransformGameObj.SetActive(false); 51 | } 52 | 53 | void Update() 54 | { 55 | // Highlight 56 | if (highlight != null) 57 | { 58 | highlight.GetComponent().sharedMaterial = originalMaterialHighlight; 59 | highlight = null; 60 | } 61 | Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); 62 | if (!EventSystem.current.IsPointerOverGameObject() && Physics.Raycast(ray, out raycastHit)) //Make sure you have EventSystem in the hierarchy before using EventSystem 63 | { 64 | highlight = raycastHit.transform; 65 | if (highlight.CompareTag("Selectable") && highlight != selection) 66 | { 67 | if (highlight.GetComponent().material != highlightMaterial) 68 | { 69 | originalMaterialHighlight = highlight.GetComponent().material; 70 | highlight.GetComponent().material = highlightMaterial; 71 | } 72 | } 73 | else 74 | { 75 | highlight = null; 76 | } 77 | } 78 | 79 | // Selection 80 | if (Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject()) 81 | { 82 | ApplyLayerToChildren(runtimeTransformGameObj); 83 | if (Physics.Raycast(ray, out raycastHit)) 84 | { 85 | if (Physics.Raycast(ray, out raycastHitHandle, Mathf.Infinity, runtimeTransformLayerMask)) //Raycast towards runtime transform handle only 86 | { 87 | } 88 | else if (highlight) 89 | { 90 | if (selection != null) 91 | { 92 | selection.GetComponent().material = originalMaterialSelection; 93 | } 94 | selection = raycastHit.transform; 95 | if (selection.GetComponent().material != selectionMaterial) 96 | { 97 | originalMaterialSelection = originalMaterialHighlight; 98 | selection.GetComponent().material = selectionMaterial; 99 | runtimeTransformHandle.target = selection; 100 | runtimeTransformGameObj.SetActive(true); 101 | } 102 | highlight = null; 103 | } 104 | else 105 | { 106 | if (selection) 107 | { 108 | selection.GetComponent().material = originalMaterialSelection; 109 | selection = null; 110 | 111 | runtimeTransformGameObj.SetActive(false); 112 | } 113 | } 114 | } 115 | else 116 | { 117 | if (selection) 118 | { 119 | selection.GetComponent().material = originalMaterialSelection; 120 | selection = null; 121 | 122 | runtimeTransformGameObj.SetActive(false); 123 | } 124 | } 125 | } 126 | 127 | //Hot Keys for move, rotate, scale, local and Global/World transform 128 | if (runtimeTransformGameObj.activeSelf) 129 | { 130 | if (Input.GetKeyDown(KeyCode.W)) 131 | { 132 | runtimeTransformHandle.type = HandleType.POSITION; 133 | } 134 | if (Input.GetKeyDown(KeyCode.E)) 135 | { 136 | runtimeTransformHandle.type = HandleType.ROTATION; 137 | } 138 | if (Input.GetKeyDown(KeyCode.R)) 139 | { 140 | runtimeTransformHandle.type = HandleType.SCALE; 141 | } 142 | if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) 143 | { 144 | if (Input.GetKeyDown(KeyCode.G)) 145 | { 146 | runtimeTransformHandle.space = HandleSpace.WORLD; 147 | } 148 | if (Input.GetKeyDown(KeyCode.L)) 149 | { 150 | runtimeTransformHandle.space = HandleSpace.LOCAL; 151 | } 152 | } 153 | } 154 | 155 | } 156 | 157 | 158 | private void ApplyLayerToChildren(GameObject parentGameObj) 159 | { 160 | foreach (Transform transform1 in parentGameObj.transform) 161 | { 162 | int layer = parentGameObj.layer; 163 | transform1.gameObject.layer = layer; 164 | foreach (Transform transform2 in transform1) 165 | { 166 | transform2.gameObject.layer = layer; 167 | foreach (Transform transform3 in transform2) 168 | { 169 | transform3.gameObject.layer = layer; 170 | foreach (Transform transform4 in transform3) 171 | { 172 | transform4.gameObject.layer = layer; 173 | foreach (Transform transform5 in transform4) 174 | { 175 | transform5.gameObject.layer = layer; 176 | } 177 | } 178 | } 179 | } 180 | } 181 | } 182 | 183 | } -------------------------------------------------------------------------------- /Selection.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using UnityEngine.EventSystems; 23 | 24 | public class Selection : MonoBehaviour 25 | { 26 | public Material highlightMaterial; 27 | public Material selectionMaterial; 28 | 29 | private Material originalMaterialHighlight; 30 | private Material originalMaterialSelection; 31 | private Transform highlight; 32 | private Transform selection; 33 | private RaycastHit raycastHit; 34 | 35 | void Update() 36 | { 37 | // Highlight 38 | if (highlight != null) 39 | { 40 | highlight.GetComponent().sharedMaterial = originalMaterialHighlight; 41 | highlight = null; 42 | } 43 | Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); 44 | if (!EventSystem.current.IsPointerOverGameObject() && Physics.Raycast(ray, out raycastHit)) //Make sure you have EventSystem in the hierarchy before using EventSystem 45 | { 46 | highlight = raycastHit.transform; 47 | if (highlight.CompareTag("Selectable") && highlight != selection) 48 | { 49 | if (highlight.GetComponent().material != highlightMaterial) 50 | { 51 | originalMaterialHighlight = highlight.GetComponent().material; 52 | highlight.GetComponent().material = highlightMaterial; 53 | } 54 | } 55 | else 56 | { 57 | highlight = null; 58 | } 59 | } 60 | 61 | // Selection 62 | if (Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject()) 63 | { 64 | if (highlight) 65 | { 66 | if (selection != null) 67 | { 68 | selection.GetComponent().material = originalMaterialSelection; 69 | } 70 | selection = raycastHit.transform; 71 | if (selection.GetComponent().material != selectionMaterial) 72 | { 73 | originalMaterialSelection = originalMaterialHighlight; 74 | selection.GetComponent().material = selectionMaterial; 75 | } 76 | highlight = null; 77 | } 78 | else 79 | { 80 | if (selection) 81 | { 82 | selection.GetComponent().material = originalMaterialSelection; 83 | selection = null; 84 | } 85 | } 86 | } 87 | 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /SetGetData.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | 23 | public class SetGetData : MonoBehaviour 24 | { 25 | public Color colorValue; 26 | public float speedValue; 27 | 28 | // Start is called before the first frame update void Start(){} 29 | // Update is called once per frame void Update(){} 30 | 31 | public void SaveOnClick() 32 | { 33 | DataManager.Instance.color = colorValue; 34 | DataManager.Instance.speed = speedValue; 35 | DataManager.Instance.WriteData(); 36 | } 37 | 38 | public void LoadOnClick() 39 | { 40 | DataManager.Instance.LoadData(); 41 | colorValue = DataManager.Instance.color; 42 | speedValue = DataManager.Instance.speed; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Sphere.obj: -------------------------------------------------------------------------------- 1 | mtllib Sphere.mtl 2 | v -5.000000 0.000000 -0.000000 3 | v -4.619398 0.000000 -1.913417 4 | v -4.619398 -1.913417 -0.000000 5 | v -4.267767 -1.767767 -1.913417 6 | v -4.619398 1.913417 -0.000000 7 | v -4.267767 1.767767 -1.913417 8 | v -4.619398 0.000000 1.913417 9 | v -4.267767 -1.767767 1.913417 10 | v -3.535534 0.000000 -3.535534 11 | v -3.266407 -1.352990 -3.535534 12 | v -3.535534 -3.535534 -0.000000 13 | v -4.267767 1.767767 1.913417 14 | v -3.266407 -3.266407 -1.913417 15 | v -3.266407 1.352990 -3.535534 16 | v -3.266407 -3.266407 1.913417 17 | v -3.266407 3.266407 -1.913417 18 | v -3.535534 3.535534 -0.000000 19 | v -2.500000 -2.500000 -3.535534 20 | v -3.535534 0.000000 3.535534 21 | v -3.266407 -1.352990 3.535534 22 | v -2.500000 2.500000 -3.535534 23 | v -3.266407 3.266407 1.913417 24 | v -3.266407 1.352990 3.535534 25 | v -1.913417 0.000000 -4.619398 26 | v -1.767767 -0.732233 -4.619398 27 | v -1.767767 -4.267767 -1.913417 28 | v -1.767767 0.732233 -4.619398 29 | v -1.913417 -4.619398 -0.000000 30 | v -2.500000 -2.500000 3.535534 31 | v -1.352990 -3.266407 -3.535534 32 | v -1.352990 -1.352990 -4.619398 33 | v -1.767767 -4.267767 1.913417 34 | v -1.352990 1.352990 -4.619398 35 | v -2.500000 2.500000 3.535534 36 | v -1.767767 4.267767 -1.913417 37 | v -1.352990 3.266407 -3.535534 38 | v -0.732233 -1.767767 -4.619398 39 | v -1.913417 4.619398 -0.000000 40 | v -1.913417 0.000000 4.619398 41 | v -0.732233 1.767767 -4.619398 42 | v -1.767767 -0.732233 4.619398 43 | v -1.352990 -3.266407 3.535534 44 | v -1.767767 4.267767 1.913417 45 | v -1.767767 0.732233 4.619398 46 | v -1.352990 -1.352990 4.619398 47 | v 0.000000 -1.913417 -4.619398 48 | v -0.000000 -3.535534 -3.535534 49 | v 0.000000 -0.000000 -5.000000 50 | v -0.000000 -4.619398 -1.913417 51 | v -1.352990 1.352990 4.619398 52 | v -1.352990 3.266407 3.535534 53 | v 0.000000 1.913417 -4.619398 54 | v -0.000000 -5.000000 0.000000 55 | v -0.732233 -1.767767 4.619398 56 | v 0.000000 3.535534 -3.535534 57 | v -0.000000 -4.619398 1.913417 58 | v 0.732233 -1.767767 -4.619398 59 | v -0.732233 1.767767 4.619398 60 | v 0.000000 4.619398 -1.913417 61 | v -0.000000 -3.535534 3.535534 62 | v 0.732233 1.767767 -4.619398 63 | v 0.000000 5.000000 0.000000 64 | v -0.000000 -1.913417 4.619398 65 | v 1.352990 -3.266407 -3.535534 66 | v 1.352990 -1.352990 -4.619398 67 | v 0.000000 4.619398 1.913417 68 | v -0.000000 0.000000 5.000000 69 | v 0.000000 3.535534 3.535534 70 | v -0.000000 1.913417 4.619398 71 | v 1.352990 1.352990 -4.619398 72 | v 1.767767 -0.732233 -4.619398 73 | v 1.767767 -4.267767 -1.913417 74 | v 1.352990 3.266407 -3.535534 75 | v 1.767767 0.732233 -4.619398 76 | v 0.732233 -1.767767 4.619398 77 | v 1.913417 -0.000000 -4.619398 78 | v 1.913417 -4.619398 0.000000 79 | v 0.732233 1.767767 4.619398 80 | v 1.352990 -3.266407 3.535534 81 | v 1.767767 -4.267767 1.913417 82 | v 2.500000 -2.500000 -3.535534 83 | v 1.352990 -1.352990 4.619398 84 | v 1.767767 4.267767 -1.913417 85 | v 1.352990 1.352990 4.619398 86 | v 1.352990 3.266407 3.535534 87 | v 2.500000 2.500000 -3.535534 88 | v 1.913417 4.619398 0.000000 89 | v 1.767767 -0.732233 4.619398 90 | v 1.767767 4.267767 1.913417 91 | v 1.767767 0.732233 4.619398 92 | v 1.913417 -0.000000 4.619398 93 | v 3.266407 -1.352990 -3.535534 94 | v 3.266407 -3.266407 -1.913417 95 | v 2.500000 -2.500000 3.535534 96 | v 3.266407 1.352990 -3.535534 97 | v 3.535534 -0.000000 -3.535534 98 | v 2.500000 2.500000 3.535534 99 | v 3.535534 -3.535534 0.000000 100 | v 3.266407 -3.266407 1.913417 101 | v 3.266407 3.266407 -1.913417 102 | v 3.266407 -1.352990 3.535534 103 | v 3.266407 3.266407 1.913417 104 | v 4.267767 -1.767767 -1.913417 105 | v 3.535534 3.535534 0.000000 106 | v 3.266407 1.352990 3.535534 107 | v 3.535534 -0.000000 3.535534 108 | v 4.267767 1.767767 -1.913417 109 | v 4.619398 -0.000000 -1.913417 110 | v 4.267767 -1.767767 1.913417 111 | v 4.619398 -1.913417 0.000000 112 | v 4.267767 1.767767 1.913417 113 | v 4.619398 1.913417 0.000000 114 | v 4.619398 -0.000000 1.913417 115 | v 5.000000 -0.000000 0.000000 116 | vn -1.000000 0.000000 -0.000000 117 | vn -0.923682 0.000000 -0.383160 118 | vn -0.923880 -0.382683 -0.000000 119 | vn -0.853371 -0.353478 -0.383160 120 | vn -0.923880 0.382683 -0.000000 121 | vn -0.853371 0.353478 -0.383160 122 | vn -0.923682 0.000000 0.383160 123 | vn -0.853371 -0.353478 0.383160 124 | vn -0.706584 0.000000 -0.707629 125 | vn -0.652799 -0.270398 -0.707629 126 | vn -0.707107 -0.707107 -0.000000 127 | vn -0.853371 0.353478 0.383160 128 | vn -0.653142 -0.653142 -0.383160 129 | vn -0.652799 0.270398 -0.707629 130 | vn -0.653142 -0.653142 0.383160 131 | vn -0.653142 0.653142 -0.383160 132 | vn -0.707107 0.707107 -0.000000 133 | vn -0.499631 -0.499631 -0.707629 134 | vn -0.706584 0.000000 0.707629 135 | vn -0.652799 -0.270398 0.707629 136 | vn -0.499631 0.499631 -0.707629 137 | vn -0.653142 0.653142 0.383160 138 | vn -0.652799 0.270398 0.707629 139 | vn -0.382195 0.000000 -0.924082 140 | vn -0.353102 -0.146260 -0.924082 141 | vn -0.353478 -0.853371 -0.383160 142 | vn -0.353102 0.146260 -0.924082 143 | vn -0.382683 -0.923880 -0.000000 144 | vn -0.499631 -0.499631 0.707629 145 | vn -0.270398 -0.652799 -0.707629 146 | vn -0.270253 -0.270253 -0.924082 147 | vn -0.353478 -0.853371 0.383160 148 | vn -0.270253 0.270253 -0.924082 149 | vn -0.499631 0.499631 0.707629 150 | vn -0.353478 0.853371 -0.383160 151 | vn -0.270398 0.652799 -0.707629 152 | vn -0.146260 -0.353102 -0.924082 153 | vn -0.382683 0.923880 -0.000000 154 | vn -0.382195 0.000000 0.924082 155 | vn -0.146260 0.353102 -0.924082 156 | vn -0.353102 -0.146260 0.924082 157 | vn -0.270398 -0.652799 0.707629 158 | vn -0.353478 0.853371 0.383160 159 | vn -0.353102 0.146260 0.924082 160 | vn -0.270253 -0.270253 0.924082 161 | vn 0.000000 -0.382195 -0.924082 162 | vn -0.000000 -0.706584 -0.707629 163 | vn 0.000000 0.000000 -1.000000 164 | vn -0.000000 -0.923682 -0.383160 165 | vn -0.270253 0.270253 0.924082 166 | vn -0.270398 0.652799 0.707629 167 | vn 0.000000 0.382195 -0.924082 168 | vn -0.000000 -1.000000 0.000000 169 | vn -0.146260 -0.353102 0.924082 170 | vn 0.000000 0.706584 -0.707629 171 | vn -0.000000 -0.923682 0.383160 172 | vn 0.146260 -0.353102 -0.924082 173 | vn -0.146260 0.353102 0.924082 174 | vn 0.000000 0.923682 -0.383160 175 | vn -0.000000 -0.706584 0.707629 176 | vn 0.146260 0.353102 -0.924082 177 | vn 0.000000 1.000000 0.000000 178 | vn -0.000000 -0.382195 0.924082 179 | vn 0.270398 -0.652799 -0.707629 180 | vn 0.270253 -0.270253 -0.924082 181 | vn 0.000000 0.923682 0.383160 182 | vn -0.000000 0.000000 1.000000 183 | vn 0.000000 0.706584 0.707629 184 | vn -0.000000 0.382195 0.924082 185 | vn 0.270253 0.270253 -0.924082 186 | vn 0.353102 -0.146260 -0.924082 187 | vn 0.353478 -0.853371 -0.383160 188 | vn 0.270398 0.652799 -0.707629 189 | vn 0.353102 0.146260 -0.924082 190 | vn 0.146260 -0.353102 0.924082 191 | vn 0.382195 -0.000000 -0.924082 192 | vn 0.382683 -0.923880 0.000000 193 | vn 0.146260 0.353102 0.924082 194 | vn 0.270398 -0.652799 0.707629 195 | vn 0.353478 -0.853371 0.383160 196 | vn 0.499631 -0.499631 -0.707629 197 | vn 0.270253 -0.270253 0.924082 198 | vn 0.353478 0.853371 -0.383160 199 | vn 0.270253 0.270253 0.924082 200 | vn 0.270398 0.652799 0.707629 201 | vn 0.499631 0.499631 -0.707629 202 | vn 0.382683 0.923880 0.000000 203 | vn 0.353102 -0.146260 0.924082 204 | vn 0.353478 0.853371 0.383160 205 | vn 0.353102 0.146260 0.924082 206 | vn 0.382195 -0.000000 0.924082 207 | vn 0.652799 -0.270398 -0.707629 208 | vn 0.653142 -0.653142 -0.383160 209 | vn 0.499631 -0.499631 0.707629 210 | vn 0.652799 0.270398 -0.707629 211 | vn 0.706584 -0.000000 -0.707629 212 | vn 0.499631 0.499631 0.707629 213 | vn 0.707107 -0.707107 0.000000 214 | vn 0.653142 -0.653142 0.383160 215 | vn 0.653142 0.653142 -0.383160 216 | vn 0.652799 -0.270398 0.707629 217 | vn 0.653142 0.653142 0.383160 218 | vn 0.853371 -0.353478 -0.383160 219 | vn 0.707107 0.707107 0.000000 220 | vn 0.652799 0.270398 0.707629 221 | vn 0.706584 -0.000000 0.707629 222 | vn 0.853371 0.353478 -0.383160 223 | vn 0.923682 -0.000000 -0.383160 224 | vn 0.853371 -0.353478 0.383160 225 | vn 0.923880 -0.382683 0.000000 226 | vn 0.853371 0.353478 0.383160 227 | vn 0.923880 0.382683 0.000000 228 | vn 0.923682 -0.000000 0.383160 229 | vn 1.000000 -0.000000 0.000000 230 | usemtl Sphere_Sphere.dgn_Default_255_0_255_vis 231 | f 67//67 88//88 91//91 232 | f 67//67 82//82 88//88 233 | f 67//67 75//75 82//82 234 | f 67//67 63//63 75//75 235 | f 67//67 54//54 63//63 236 | f 67//67 45//45 54//54 237 | f 67//67 41//41 45//45 238 | f 67//67 39//39 41//41 239 | f 67//67 44//44 39//39 240 | f 67//67 50//50 44//44 241 | f 67//67 58//58 50//50 242 | f 67//67 69//69 58//58 243 | f 67//67 78//78 69//69 244 | f 67//67 84//84 78//78 245 | f 67//67 90//90 84//84 246 | f 67//67 91//91 90//90 247 | f 76//76 71//71 48//48 248 | f 71//71 65//65 48//48 249 | f 65//65 57//57 48//48 250 | f 57//57 46//46 48//48 251 | f 46//46 37//37 48//48 252 | f 37//37 31//31 48//48 253 | f 31//31 25//25 48//48 254 | f 25//25 24//24 48//48 255 | f 24//24 27//27 48//48 256 | f 27//27 33//33 48//48 257 | f 33//33 40//40 48//48 258 | f 40//40 52//52 48//48 259 | f 52//52 61//61 48//48 260 | f 61//61 70//70 48//48 261 | f 70//70 74//74 48//48 262 | f 74//74 76//76 48//48 263 | f 106//106 91//91 101//101 264 | f 101//101 91//91 88//88 265 | f 101//101 88//88 94//94 266 | f 94//94 88//88 82//82 267 | f 79//79 94//94 75//75 268 | f 75//75 94//94 82//82 269 | f 79//79 75//75 60//60 270 | f 60//60 75//75 63//63 271 | f 42//42 60//60 54//54 272 | f 54//54 60//60 63//63 273 | f 29//29 42//42 45//45 274 | f 45//45 42//42 54//54 275 | f 29//29 45//45 41//41 276 | f 29//29 41//41 20//20 277 | f 19//19 20//20 39//39 278 | f 39//39 20//20 41//41 279 | f 23//23 19//19 44//44 280 | f 44//44 19//19 39//39 281 | f 34//34 23//23 50//50 282 | f 50//50 23//23 44//44 283 | f 34//34 50//50 51//51 284 | f 51//51 50//50 58//58 285 | f 68//68 51//51 69//69 286 | f 69//69 51//51 58//58 287 | f 68//68 69//69 78//78 288 | f 68//68 78//78 85//85 289 | f 85//85 78//78 97//97 290 | f 97//97 78//78 84//84 291 | f 97//97 84//84 90//90 292 | f 97//97 90//90 105//105 293 | f 106//106 105//105 90//90 294 | f 106//106 90//90 91//91 295 | f 109//109 113//113 101//101 296 | f 101//101 113//113 106//106 297 | f 109//109 101//101 99//99 298 | f 99//99 101//101 94//94 299 | f 80//80 99//99 79//79 300 | f 79//79 99//99 94//94 301 | f 56//56 80//80 60//60 302 | f 60//60 80//80 79//79 303 | f 32//32 56//56 42//42 304 | f 42//42 56//56 60//60 305 | f 15//15 32//32 29//29 306 | f 29//29 32//32 42//42 307 | f 8//8 15//15 20//20 308 | f 20//20 15//15 29//29 309 | f 7//7 8//8 19//19 310 | f 19//19 8//8 20//20 311 | f 7//7 19//19 23//23 312 | f 7//7 23//23 12//12 313 | f 22//22 12//12 23//23 314 | f 22//22 23//23 34//34 315 | f 43//43 22//22 51//51 316 | f 51//51 22//22 34//34 317 | f 66//66 43//43 68//68 318 | f 68//68 43//43 51//51 319 | f 89//89 66//66 85//85 320 | f 85//85 66//66 68//68 321 | f 102//102 89//89 97//97 322 | f 97//97 89//89 85//85 323 | f 111//111 102//102 105//105 324 | f 105//105 102//102 97//97 325 | f 113//113 111//111 106//106 326 | f 106//106 111//111 105//105 327 | f 110//110 114//114 109//109 328 | f 109//109 114//114 113//113 329 | f 98//98 110//110 99//99 330 | f 99//99 110//110 109//109 331 | f 77//77 98//98 99//99 332 | f 77//77 99//99 80//80 333 | f 77//77 80//80 56//56 334 | f 77//77 56//56 53//53 335 | f 53//53 56//56 28//28 336 | f 28//28 56//56 32//32 337 | f 11//11 28//28 32//32 338 | f 11//11 32//32 15//15 339 | f 11//11 15//15 8//8 340 | f 11//11 8//8 3//3 341 | f 1//1 3//3 7//7 342 | f 7//7 3//3 8//8 343 | f 1//1 7//7 5//5 344 | f 5//5 7//7 12//12 345 | f 17//17 5//5 12//12 346 | f 17//17 12//12 22//22 347 | f 17//17 22//22 43//43 348 | f 17//17 43//43 38//38 349 | f 38//38 43//43 62//62 350 | f 62//62 43//43 66//66 351 | f 87//87 62//62 66//66 352 | f 87//87 66//66 89//89 353 | f 104//104 87//87 102//102 354 | f 102//102 87//87 89//89 355 | f 112//112 104//104 102//102 356 | f 112//112 102//102 111//111 357 | f 112//112 111//111 114//114 358 | f 114//114 111//111 113//113 359 | f 103//103 108//108 110//110 360 | f 110//110 108//108 114//114 361 | f 103//103 110//110 93//93 362 | f 93//93 110//110 98//98 363 | f 72//72 93//93 98//98 364 | f 72//72 98//98 77//77 365 | f 49//49 72//72 77//77 366 | f 49//49 77//77 53//53 367 | f 26//26 49//49 28//28 368 | f 28//28 49//49 53//53 369 | f 13//13 26//26 11//11 370 | f 11//11 26//26 28//28 371 | f 4//4 13//13 11//11 372 | f 4//4 11//11 3//3 373 | f 2//2 4//4 3//3 374 | f 2//2 3//3 1//1 375 | f 2//2 1//1 6//6 376 | f 6//6 1//1 5//5 377 | f 16//16 6//6 5//5 378 | f 16//16 5//5 17//17 379 | f 35//35 16//16 38//38 380 | f 38//38 16//16 17//17 381 | f 59//59 35//35 62//62 382 | f 62//62 35//35 38//38 383 | f 83//83 59//59 87//87 384 | f 87//87 59//59 62//62 385 | f 100//100 83//83 104//104 386 | f 104//104 83//83 87//87 387 | f 107//107 100//100 112//112 388 | f 112//112 100//100 104//104 389 | f 108//108 107//107 112//112 390 | f 108//108 112//112 114//114 391 | f 92//92 96//96 108//108 392 | f 92//92 108//108 103//103 393 | f 92//92 103//103 81//81 394 | f 81//81 103//103 93//93 395 | f 64//64 81//81 72//72 396 | f 72//72 81//81 93//93 397 | f 47//47 64//64 49//49 398 | f 49//49 64//64 72//72 399 | f 30//30 47//47 26//26 400 | f 26//26 47//47 49//49 401 | f 18//18 30//30 13//13 402 | f 13//13 30//30 26//26 403 | f 18//18 13//13 10//10 404 | f 10//10 13//13 4//4 405 | f 9//9 10//10 2//2 406 | f 2//2 10//10 4//4 407 | f 14//14 9//9 6//6 408 | f 6//6 9//9 2//2 409 | f 21//21 14//14 16//16 410 | f 16//16 14//14 6//6 411 | f 21//21 16//16 36//36 412 | f 36//36 16//16 35//35 413 | f 36//36 35//35 55//55 414 | f 55//55 35//35 59//59 415 | f 55//55 59//59 73//73 416 | f 73//73 59//59 83//83 417 | f 73//73 83//83 86//86 418 | f 86//86 83//83 100//100 419 | f 95//95 86//86 100//100 420 | f 95//95 100//100 107//107 421 | f 96//96 95//95 108//108 422 | f 108//108 95//95 107//107 423 | f 71//71 76//76 92//92 424 | f 92//92 76//76 96//96 425 | f 65//65 71//71 92//92 426 | f 65//65 92//92 81//81 427 | f 65//65 81//81 64//64 428 | f 65//65 64//64 57//57 429 | f 46//46 57//57 47//47 430 | f 47//47 57//57 64//64 431 | f 37//37 46//46 30//30 432 | f 30//30 46//46 47//47 433 | f 31//31 37//37 18//18 434 | f 18//18 37//37 30//30 435 | f 25//25 31//31 18//18 436 | f 25//25 18//18 10//10 437 | f 24//24 25//25 9//9 438 | f 9//9 25//25 10//10 439 | f 27//27 24//24 14//14 440 | f 14//14 24//24 9//9 441 | f 33//33 27//27 21//21 442 | f 21//21 27//27 14//14 443 | f 40//40 33//33 36//36 444 | f 36//36 33//33 21//21 445 | f 40//40 36//36 52//52 446 | f 52//52 36//36 55//55 447 | f 61//61 52//52 55//55 448 | f 61//61 55//55 73//73 449 | f 70//70 61//61 86//86 450 | f 86//86 61//61 73//73 451 | f 74//74 70//70 86//86 452 | f 74//74 86//86 95//95 453 | f 76//76 74//74 96//96 454 | f 96//96 74//74 95//95 455 | 456 | -------------------------------------------------------------------------------- /SphereCast.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class SphereCast : MonoBehaviour 6 | { 7 | private Ray ray; 8 | private RaycastHit raycastHit; 9 | private float sphereCastRadius = 12.0f; 10 | 11 | // Update is called once per frame 12 | void Update() 13 | { 14 | 15 | if (Physics.SphereCast(ray, sphereCastRadius, out raycastHit)) 16 | { 17 | GameObject sphereGameObject = raycastHit.transform.gameObject; 18 | } 19 | 20 | } 21 | } 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /TransformUI.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using UnityEngine.EventSystems; 23 | using TMPro; 24 | 25 | public class TransformUI : MonoBehaviour 26 | { 27 | public Material highlightMaterial; 28 | public Material selectionMaterial; 29 | public GameObject inputPosXGameObj; 30 | public GameObject inputPosYGameObj; 31 | public GameObject inputPosZGameObj; 32 | public GameObject inputRotationXGameObj; 33 | public GameObject inputRotationYGameObj; 34 | public GameObject inputRotationZGameObj; 35 | public GameObject inputScaleXGameObj; 36 | public GameObject inputScaleYGameObj; 37 | public GameObject inputScaleZGameObj; 38 | public GameObject axisDropDownGameObj; 39 | public GameObject scaleDropDownGameObj; 40 | 41 | private Material originalMaterialHighlight; 42 | private Material originalMaterialSelection; 43 | private Transform highlight; 44 | private Transform selection; 45 | private Ray ray; 46 | private RaycastHit raycastHit; 47 | private TMP_InputField inputPosX; 48 | private TMP_InputField inputPosY; 49 | private TMP_InputField inputPosZ; 50 | private TMP_InputField inputRotationX; 51 | private TMP_InputField inputRotationY; 52 | private TMP_InputField inputRotationZ; 53 | private TMP_InputField inputScaleX; 54 | private TMP_InputField inputScaleY; 55 | private TMP_InputField inputScaleZ; 56 | private float posX; 57 | private float posY; 58 | private float posZ; 59 | private float rotationX; 60 | private float rotationY; 61 | private float rotationZ; 62 | private float scaleX; 63 | private float scaleY; 64 | private float scaleZ; 65 | private TMP_Dropdown axisDropDown; 66 | private TMP_Dropdown scaleDropDown; 67 | private bool isAxisGlobal = true; 68 | private bool isScaleEven = true; 69 | 70 | private void Start() 71 | { 72 | inputPosX = inputPosXGameObj.GetComponent(); 73 | inputPosY = inputPosYGameObj.GetComponent(); 74 | inputPosZ = inputPosZGameObj.GetComponent(); 75 | inputRotationX = inputRotationXGameObj.GetComponent(); 76 | inputRotationY = inputRotationYGameObj.GetComponent(); 77 | inputRotationZ = inputRotationZGameObj.GetComponent(); 78 | inputScaleX = inputScaleXGameObj.GetComponent(); 79 | inputScaleY = inputScaleYGameObj.GetComponent(); 80 | inputScaleZ = inputScaleZGameObj.GetComponent(); 81 | axisDropDown = axisDropDownGameObj.GetComponent(); 82 | scaleDropDown = scaleDropDownGameObj.GetComponent(); 83 | } 84 | 85 | void Update() 86 | { 87 | if (!Input.GetMouseButton(0)) 88 | { 89 | // Highlight 90 | ray = Camera.main.ScreenPointToRay(Input.mousePosition); 91 | if (highlight != null) 92 | { 93 | highlight.GetComponent().sharedMaterial = originalMaterialHighlight; 94 | highlight = null; 95 | } 96 | if (!EventSystem.current.IsPointerOverGameObject() && Physics.Raycast(ray, out raycastHit)) 97 | { 98 | highlight = raycastHit.transform; 99 | if (highlight.CompareTag("Selectable") && highlight != selection) 100 | { 101 | if (highlight.GetComponent().material != highlightMaterial) 102 | { 103 | originalMaterialHighlight = highlight.GetComponent().material; 104 | highlight.GetComponent().material = highlightMaterial; 105 | } 106 | } 107 | else 108 | { 109 | highlight = null; 110 | } 111 | } 112 | } 113 | 114 | // Selection 115 | if (Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject()) 116 | { 117 | if (Physics.Raycast(ray, out raycastHit)) 118 | { 119 | if (highlight) 120 | { 121 | if (selection != null) 122 | { 123 | selection.GetComponent().material = originalMaterialSelection; 124 | } 125 | selection = raycastHit.transform; 126 | if (selection.GetComponent().material != selectionMaterial) 127 | { 128 | originalMaterialSelection = originalMaterialHighlight; 129 | selection.GetComponent().material = selectionMaterial; 130 | } 131 | highlight = null; 132 | } 133 | else 134 | { 135 | if (selection) 136 | { 137 | selection.GetComponent().material = originalMaterialSelection; 138 | selection = null; 139 | } 140 | } 141 | } 142 | else 143 | { 144 | if (selection) 145 | { 146 | selection.GetComponent().material = originalMaterialSelection; 147 | selection = null; 148 | } 149 | } 150 | } 151 | 152 | if (selection && !inputPosX.isFocused && !inputPosY.isFocused && !inputPosZ.isFocused) 153 | { 154 | GetSelectedPos(); 155 | } 156 | if (selection && !inputRotationX.isFocused && !inputRotationY.isFocused && !inputRotationZ.isFocused) 157 | { 158 | GetSelectedRotation(); 159 | } 160 | if (selection && !inputScaleX.isFocused && !inputScaleY.isFocused && !inputScaleZ.isFocused) 161 | { 162 | GetSelectedScale(); 163 | } 164 | } 165 | 166 | 167 | /// ----------------------------------------------/// 168 | /// Position 169 | /// ----------------------------------------------/// 170 | private void GetSelectedPos() 171 | { 172 | if (selection) 173 | { 174 | Vector3 currPos; 175 | if (isAxisGlobal) 176 | { 177 | currPos = selection.position; 178 | } 179 | else 180 | { 181 | currPos = selection.InverseTransformPoint(selection.position); //world to local 182 | } 183 | inputPosXGameObj.SetActive(true); 184 | inputPosYGameObj.SetActive(true); 185 | inputPosZGameObj.SetActive(true); 186 | posX = currPos.x; 187 | posY = currPos.y; 188 | posZ = currPos.z; 189 | posX = Mathf.Round(posX * 1000f) / 1000f; 190 | posY = Mathf.Round(posY * 1000f) / 1000f; 191 | posZ = Mathf.Round(posZ * 1000f) / 1000f; 192 | inputPosX.text = posX.ToString(); 193 | inputPosY.text = posY.ToString(); 194 | inputPosZ.text = posZ.ToString(); 195 | } 196 | else 197 | { 198 | inputPosXGameObj.SetActive(false); 199 | inputPosYGameObj.SetActive(false); 200 | inputPosZGameObj.SetActive(false); 201 | } 202 | } 203 | 204 | public void SetPosX() 205 | { 206 | if (float.TryParse(inputPosX.text, out posX)) 207 | { 208 | SetSelectedPos(); 209 | } 210 | } 211 | public void SetPosY() 212 | { 213 | if (float.TryParse(inputPosY.text, out posY)) 214 | { 215 | SetSelectedPos(); 216 | } 217 | } 218 | public void SetPosZ() 219 | { 220 | if (float.TryParse(inputPosZ.text, out posZ)) 221 | { 222 | SetSelectedPos(); 223 | } 224 | } 225 | 226 | public void SetSelectedPos() 227 | { 228 | if (selection) 229 | { 230 | if (isAxisGlobal) 231 | { 232 | selection.position = new Vector3(posX, posY, posZ); 233 | } 234 | else 235 | { 236 | selection.position = selection.TransformPoint(new Vector3(posX, posY, posZ)); //local to world 237 | } 238 | } 239 | } 240 | 241 | 242 | /// ----------------------------------------------/// 243 | /// Rotation 244 | /// ----------------------------------------------/// 245 | private void GetSelectedRotation() 246 | { 247 | if (selection) 248 | { 249 | Vector3 currRotation; 250 | if (isAxisGlobal) 251 | { 252 | currRotation = selection.eulerAngles; 253 | } 254 | else 255 | { 256 | currRotation = Vector3.zero; 257 | } 258 | inputRotationXGameObj.SetActive(true); 259 | inputRotationYGameObj.SetActive(true); 260 | inputRotationZGameObj.SetActive(true); 261 | rotationX = currRotation.x; 262 | rotationY = currRotation.y; 263 | rotationZ = currRotation.z; 264 | rotationX = Mathf.Round(rotationX * 1000f) / 1000f; 265 | rotationY = Mathf.Round(rotationY * 1000f) / 1000f; 266 | rotationZ = Mathf.Round(rotationZ * 1000f) / 1000f; 267 | inputRotationX.text = rotationX.ToString(); 268 | inputRotationY.text = rotationY.ToString(); 269 | inputRotationZ.text = rotationZ.ToString(); 270 | } 271 | else 272 | { 273 | inputRotationXGameObj.SetActive(false); 274 | inputRotationYGameObj.SetActive(false); 275 | inputRotationZGameObj.SetActive(false); 276 | } 277 | } 278 | 279 | public void SetRotationX() 280 | { 281 | if (float.TryParse(inputRotationX.text, out rotationX)) 282 | { 283 | SetSelectedRotation(); 284 | } 285 | } 286 | public void SetRotationY() 287 | { 288 | if (float.TryParse(inputRotationY.text, out rotationY)) 289 | { 290 | SetSelectedRotation(); 291 | } 292 | } 293 | public void SetRotationZ() 294 | { 295 | if (float.TryParse(inputRotationZ.text, out rotationZ)) 296 | { 297 | SetSelectedRotation(); 298 | } 299 | } 300 | 301 | public void SetSelectedRotation() 302 | { 303 | if (selection) 304 | { 305 | if (isAxisGlobal) 306 | { 307 | selection.eulerAngles = new Vector3(rotationX, rotationY, rotationZ); 308 | } 309 | else 310 | { 311 | selection.eulerAngles = selection.eulerAngles + selection.TransformVector(new Vector3(rotationX, rotationY, rotationZ)); 312 | rotationX = 0.0f; 313 | rotationY = 0.0f; 314 | rotationZ = 0.0f; 315 | } 316 | } 317 | } 318 | 319 | 320 | /// ----------------------------------------------/// 321 | /// Scale 322 | /// ----------------------------------------------/// 323 | private void GetSelectedScale() 324 | { 325 | if (selection) 326 | { 327 | Vector3 currScale; 328 | if (isAxisGlobal) 329 | { 330 | currScale = selection.lossyScale; 331 | } 332 | else 333 | { 334 | currScale = Vector3.one; 335 | } 336 | inputScaleXGameObj.SetActive(true); 337 | inputScaleYGameObj.SetActive(true); 338 | inputScaleZGameObj.SetActive(true); 339 | scaleX = currScale.x; 340 | scaleY = currScale.y; 341 | scaleZ = currScale.z; 342 | scaleX = Mathf.Round(scaleX * 1000f) / 1000f; 343 | scaleY = Mathf.Round(scaleY * 1000f) / 1000f; 344 | scaleZ = Mathf.Round(scaleZ * 1000f) / 1000f; 345 | inputScaleX.text = scaleX.ToString(); 346 | inputScaleY.text = scaleY.ToString(); 347 | inputScaleZ.text = scaleZ.ToString(); 348 | } 349 | else 350 | { 351 | inputScaleXGameObj.SetActive(false); 352 | inputScaleYGameObj.SetActive(false); 353 | inputScaleZGameObj.SetActive(false); 354 | } 355 | } 356 | 357 | public void SetScaleX() 358 | { 359 | if (float.TryParse(inputScaleX.text, out scaleX)) 360 | { 361 | if (isScaleEven) 362 | { 363 | float scaleDiff; 364 | if (isAxisGlobal) 365 | { 366 | scaleDiff = scaleX / selection.localScale.x; 367 | } 368 | else 369 | { 370 | scaleDiff = scaleX; 371 | } 372 | scaleX = selection.localScale.x * scaleDiff; 373 | scaleY = selection.localScale.y * scaleDiff; 374 | scaleZ = selection.localScale.z * scaleDiff; 375 | } 376 | else if(!isAxisGlobal) 377 | { 378 | scaleX = selection.localScale.x * scaleX; 379 | scaleY = selection.localScale.y; 380 | scaleZ = selection.localScale.z; 381 | } 382 | SetSelectedScale(); 383 | } 384 | } 385 | public void SetScaleY() 386 | { 387 | if (float.TryParse(inputScaleY.text, out scaleY)) 388 | { 389 | if (isScaleEven) 390 | { 391 | float scaleDiff; 392 | if (isAxisGlobal) 393 | { 394 | scaleDiff = scaleY / selection.localScale.y; 395 | } 396 | else 397 | { 398 | scaleDiff = scaleY; 399 | } 400 | scaleX = selection.localScale.x * scaleDiff; 401 | scaleY = selection.localScale.y * scaleDiff; 402 | scaleZ = selection.localScale.z * scaleDiff; 403 | } 404 | else if (!isAxisGlobal) 405 | { 406 | scaleX = selection.localScale.x; 407 | scaleY = selection.localScale.y * scaleY; 408 | scaleZ = selection.localScale.z; 409 | } 410 | SetSelectedScale(); 411 | } 412 | } 413 | public void SetScaleZ() 414 | { 415 | if (float.TryParse(inputScaleZ.text, out scaleZ)) 416 | { 417 | if (isScaleEven) 418 | { 419 | float scaleDiff; 420 | if (isAxisGlobal) 421 | { 422 | scaleDiff = scaleZ / selection.localScale.z; 423 | } 424 | else 425 | { 426 | scaleDiff = scaleZ; 427 | } 428 | scaleX = selection.localScale.x * scaleDiff; 429 | scaleY = selection.localScale.y * scaleDiff; 430 | scaleZ = selection.localScale.z * scaleDiff; 431 | } 432 | else if (!isAxisGlobal) 433 | { 434 | scaleX = selection.localScale.x; 435 | scaleY = selection.localScale.y; 436 | scaleZ = selection.localScale.z * scaleZ; 437 | } 438 | SetSelectedScale(); 439 | } 440 | } 441 | 442 | public void SetSelectedScale() 443 | { 444 | if (selection) 445 | { 446 | selection.localScale = new Vector3(scaleX, scaleY, scaleZ); 447 | } 448 | } 449 | 450 | //Axis drop down menu 451 | public void OnAxisDropDownChange() 452 | { 453 | if (axisDropDown.value == 0) 454 | { 455 | isAxisGlobal = true; 456 | } 457 | else 458 | { 459 | isAxisGlobal = false; 460 | } 461 | } 462 | 463 | //Scale drop down menu 464 | public void OnScaleDropDownChange() 465 | { 466 | if (scaleDropDown.value == 0) 467 | { 468 | isScaleEven = true; 469 | } 470 | else 471 | { 472 | isScaleEven = false; 473 | } 474 | } 475 | 476 | } -------------------------------------------------------------------------------- /TraverseAllChildren.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | 23 | public class TraverseAllChildren : MonoBehaviour 24 | { 25 | public GameObject parent; 26 | 27 | // Start is called before the first frame update 28 | void Start() 29 | { 30 | TraverseChildren(parent.transform); 31 | } 32 | 33 | // Update is called once per frame 34 | void Update() 35 | { 36 | 37 | } 38 | 39 | 40 | void TraverseChildren(Transform parent) 41 | { 42 | foreach (Transform child in parent) 43 | { 44 | // Do something with the child, such as print its name 45 | Debug.Log(child.name); 46 | 47 | TraverseChildren(child); // Recursively call TraverseChildren for each child 48 | } 49 | } 50 | } 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /UI.cs: -------------------------------------------------------------------------------- 1 | //MIT License 2 | //Copyright (c) 2023 DA LAB (https://www.youtube.com/@DA-LAB) 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | //The above copyright notice and this permission notice shall be included in all 10 | //copies or substantial portions of the Software. 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | //SOFTWARE. 18 | 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using UnityEngine; 22 | using UnityEngine.UI; 23 | 24 | public class UI : MonoBehaviour 25 | { 26 | public GameObject fileMenuBody; 27 | public GameObject fileMenuExpand; 28 | public GameObject fileMenuCollapse; 29 | 30 | // Update is called once per frame 31 | void Update() 32 | { 33 | if (fileMenuCollapse.activeSelf) 34 | { 35 | if (!IsMouseOverUI(fileMenuBody) && !IsMouseOverUI(fileMenuCollapse)) 36 | { 37 | fileMenuCollapseButton.onClick.Invoke(); 38 | } 39 | } 40 | } 41 | 42 | private bool IsMouseOverUI(GameObject ui) 43 | { 44 | if (ui.activeSelf) 45 | { 46 | RectTransform rectTrasform = ui.GetComponent(); 47 | Vector2 localMousePos = rectTrasform.InverseTransformPoint(Input.mousePosition); 48 | if (rectTrasform.rect.Contains(localMousePos)) 49 | { 50 | return true; 51 | } 52 | } 53 | return false; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /com.shtif.runtimetransformhandle@0.1.3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DA-LAB-Tutorials/YouTube-Unity-Tutorials/72e9a0ba3c10e8015eeff0c5b517d1cd65db49c5/com.shtif.runtimetransformhandle@0.1.3.zip --------------------------------------------------------------------------------