<commit_before>﻿using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

namespace UnityEditorToolkit {
	public class SnappingMenuItems : Editor {
		static readonly string SnapToOriginMessage = "Snap to Origin";
		static readonly string SnapToGroundMessage = "Snap to Ground";
		static readonly string SnapYToZeroMessage = "Snap Y to Zero";

		// The maximum distance between "lowest" vertices
		const float EPSILON = 0.0001f;

		// TODO: Refactor into helper funtions class
		static bool Approximately(float a, float b, float epsilon) {
			return (a >= (b - epsilon)) && (a <= (b + epsilon));
		}

		[MenuItem(Constants.SnapToZeroItem, false, Constants.SnapToZeroPriority)]
		static void SnapToOrigin() {
			// Get transform data
			Transform snapTransform = Selection.activeTransform;
			if(snapTransform == null) {
				Debug.Log("Cannot snap to origin because" +
					" no gameobject is selected");
				return;
			}

			if(snapTransform.position.y == 0f) {
				// Snap object transform to origin
				Undo.RecordObject(snapTransform, SnapToOriginMessage);
				snapTransform.localPosition = Vector3.zero;
			}
			else {
				// Snap transform y to zero
				Undo.RecordObject(snapTransform, SnapYToZeroMessage);
				snapTransform.localPosition = new Vector3(
					snapTransform.localPosition.x,
					0,
					snapTransform.localPosition.z
				);
			}
		}

		[MenuItem(Constants.SnapToZeroItem, true)]
		static bool SelectionNotAtOrigin() {
			return (Selection.activeTransform != null)
				&& (!(Selection.activeTransform.position == Vector3.zero));
		}

		[MenuItem(Constants.SnapToGroundItem, false, Constants.SnapToGroundPriority)]
		static void SnapToGround() {
			// Get current selected gameobject in the scene
			GameObject snapObject = Selection.activeGameObject;
			if(snapObject == null) {
				Debug.Log("Cannot snap to ground because" +
					" no gameobject is selected.");
				return;
			}
			Transform snapTransform = snapObject.transform;

			// Get object mesh if it exists
			MeshFilter filter = snapObject.GetComponent<MeshFilter>();
			if(filter == null) {
				Debug.Log("Cannot snap to ground because" +
					" the selected object has no mesh filter attached.");
				return;
			}
			Mesh mesh = filter.sharedMesh;
			if(mesh == null) {
				Debug.Log("Cannot snap to ground because" +
					" the selected object has no mesh attached.");
				return;
			}

			// Storage of mesh data
			Vector3[] vertices = mesh.vertices;
			List<Vector3> lowestVertices = new List<Vector3>();
			lowestVertices.Add(snapTransform.TransformPoint(vertices[0]));
			int vertexCount = mesh.vertexCount;

			// Find lowest vertices in world space
			for(int i = 1; i < vertexCount; i++) {
				Vector3 v = snapTransform.TransformPoint(vertices[i]);
				if(Approximately(v.y, lowestVertices[0].y, EPSILON)) {
					lowestVertices.Add(v);
				}
				else if(v.y < lowestVertices[0].y) {
					lowestVertices.Clear();
					lowestVertices.Add(v);
				}
			}

			// Cast ray(s) downwards then snap object to closest surface
			RaycastHit hit;
			float minSnapDistance = Mathf.Infinity;

			// Ignore the current object when raycasting
			int currentLayer = snapObject.layer;
			snapObject.layer = LayerMask.NameToLayer("Ignore Raycast");

			for(int i = 0; i < lowestVertices.Count; i++) {
				if(Physics.Raycast(lowestVertices[i], Vector3.down, out hit)) {
					minSnapDistance = Mathf.Min(hit.distance, minSnapDistance);<commit_msg>Snap to ground functionality on GameObjects with no mesh<commit_after>﻿using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

namespace UnityEditorToolkit {
	public class SnappingMenuItems : Editor {
		static readonly string SnapToOriginMessage = "Snap to Origin";
		static readonly string SnapToGroundMessage = "Snap to Ground";
		static readonly string SnapYToZeroMessage = "Snap Y to Zero";

		// The maximum distance between "lowest" vertices
		const float EPSILON = 0.0001f;

		// TODO: Refactor into helper funtions class
		static bool Approximately(float a, float b, float epsilon) {
			return (a >= (b - epsilon)) && (a <= (b + epsilon));
		}

		[MenuItem(Constants.SnapToZeroItem, false, Constants.SnapToZeroPriority)]
		static void SnapToOrigin() {
			// Get transform data
			Transform snapTransform = Selection.activeTransform;
			if(snapTransform == null) {
				Debug.Log("Cannot snap to origin because" +
					" no gameobject is selected");
				return;
			}

			if(snapTransform.position.y == 0f) {
				// Snap object transform to origin
				Undo.RecordObject(snapTransform, SnapToOriginMessage);
				snapTransform.localPosition = Vector3.zero;
			}
			else {
				// Snap transform y to zero
				Undo.RecordObject(snapTransform, SnapYToZeroMessage);
				snapTransform.localPosition = new Vector3(
					snapTransform.localPosition.x,
					0,
					snapTransform.localPosition.z
				);
			}
		}

		[MenuItem(Constants.SnapToZeroItem, true)]
		static bool SelectionNotAtOrigin() {
			return (Selection.activeTransform != null)
				&& (!(Selection.activeTransform.position == Vector3.zero));
		}

		[MenuItem(Constants.SnapToGroundItem, false, Constants.SnapToGroundPriority)]
		static void SnapToGround() {
			// Get current selected gameobject in the scene
			GameObject snapObject = Selection.activeGameObject;
			if(snapObject == null) {
				Debug.Log("Cannot snap to ground because" +
					" no gameobject is selected.");
				return;
			}
			Transform snapTransform = snapObject.transform;

			// Get object mesh if it exists
			bool hasMesh = false;
			Mesh mesh = null;
			MeshFilter filter = snapObject.GetComponent<MeshFilter>();
			if(filter != null) {
				mesh = filter.sharedMesh;
				if(mesh != null && mesh.vertexCount > 0) {
					hasMesh = true;
				}
			}

			List<Vector3> lowestVertices = new List<Vector3>();

			if(hasMesh) {
				// Storage of mesh data
				Vector3[] vertices = mesh.vertices;
				lowestVertices.Add(snapTransform.TransformPoint(vertices[0]));
				int vertexCount = mesh.vertexCount;

				// Find lowest vertices in world space
				for(int i = 1; i < vertexCount; i++) {
					Vector3 v = snapTransform.TransformPoint(vertices[i]);
					if(Approximately(v.y, lowestVertices[0].y, EPSILON)) {
						lowestVertices.Add(v);
					}
					else if(v.y < lowestVertices[0].y) {
						lowestVertices.Clear();
						lowestVertices.Add(v);
					}
				}
			}
			else {
				lowestVertices.Add(snapTransform.position);
			}

			// Cast ray(s) downwards then snap object to closest surface
			RaycastHit hit;
			float minSnapDistance = Mathf.Infinity;

			// Ignore the current object when raycasting
			int currentLayer = snapObject.layer;
			snapObject.layer = LayerMask.NameToLayer("Ignore Raycast");

			for(int i = 0; i < lowestVertices.Count; i++) {
				if(Physics.Raycast(lowestVertices[i], Vector3.down, out hit)) {
					minSnapDistance = Mathf.Min(hit.distance, minSnapDistance);
{'fraction_non_alphanumeric': 0.1066957787481805, 'fraction_numerical': 0.005967976710334789, 'mean_word_length': 3.5806666666666667, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4220902', 'n_tokens_mistral': 2523, 'n_tokens_neox': 2031, 'n_words': 544}