/// <summary> /// Called when a mouse button was pressed. /// </summary> public void OnButtonPress(ButtonPressEventArgs args) { Vector2 mousePos = new Vector2((float)args.Event.X, (float)args.Event.Y); ModifierType modifierMask = Accelerator.DefaultModMask; bool shift = (args.Event.State & modifierMask) == ModifierType.ShiftMask; if (args.Event.Button == 1) // left click { MeshInfo underCursor = GetMeshAtScreenPos(mousePos); ModifyMeshInfosOperation op = new ModifyMeshInfosOperation(); // clear current selection unless shift is pressed if (!shift) { MeshManager.Instance.SelectedMeshes.ForEach(m => m.IsSelected = false); } if (underCursor != null) { underCursor.IsActive = true; } op.Complete(); } }
/// <summary> /// Clones a <see cref="MeshInfo"/> instance. /// </summary> /// <param name="info">The instance to clone.</param> public MeshInfo(MeshInfo info) { m_mesh = info.m_mesh; m_color = info.m_color; m_visible = info.m_visible; m_selected = info.m_selected; m_active = info.m_active; }
/// <summary> /// Finds the mesh under a screen position if there is one. /// </summary> /// <param name="screenPos">The screen space corrdinates in pixels.</param> /// <returns>The mesh at the given position, or null of there is none.</returns> private MeshInfo GetMeshAtScreenPos(Vector2 screenPos) { // get the ray pointing along the cursor position on the screen Camera cam = m_window.Camera.Camera; Vector3 rayOrigin = cam.Transform.Position; Vector3 rayDir = cam.ScreenPointToWorldDirection(screenPos); MeshInfo underCursor = null; float minDistance = float.MaxValue; foreach (MeshInfo info in MeshManager.Instance.VisibleMeshes) { Entity entity = m_meshToEntity[info]; Mesh mesh = info.Mesh; // we do the calculations in local space to avoid needing to transform // the mesh vertices to world space. Matrix4 toLocal = entity.Transform.WorldToLocalMatrix; Vector3 orig = Vector3.TransformPosition(rayOrigin, toLocal); Vector3 dir = Vector3.TransformVector(rayDir, toLocal); // first check if the mesh's bounding box is under the cursor since it is way faster if (mesh.Bounds.Raycast(orig, dir)) { Matrix4 toWorld = entity.Transform.LocalToWorldMatix; Vector3[] verts = mesh.Vertices; Triangle[] tris = mesh.Triangles; // raycast each triangle in the mesh and get the intersect if there is a hit for (int i = 0; i < tris.Length; i++) { Triangle tri = tris[i]; Vector3 localIntersect; if (Utils.RaycastTriangle( verts[tri.index0], verts[tri.index1], verts[tri.index2], orig, dir, out localIntersect)) { // transform the intersect back into world space Vector3 intersect = Vector3.TransformPosition(localIntersect, toWorld); float dist = (intersect - rayOrigin).Length; // select the mesh if close but not before or after the camera clip planes if (dist < minDistance && cam.NearClip < dist && dist < cam.FarClip) { minDistance = dist; underCursor = info; } } } } } return(underCursor); }
/// <summary> /// Compares the values of this instance against another /// <see cref="MeshInfo"/> instance. /// </summary> public bool Equals(MeshInfo info) { return (Mesh == info.Mesh && Color == info.Color && IsVisible == info.IsVisible && IsSelected == info.IsSelected && IsActive == IsActive); }
/// <summary> /// Called when the selected meshes have changed. /// Enables drawing bounding boxes around selected meshes. /// </summary> private void OnSelectionChanged(MeshInfo mesh) { Entity entity; if (m_meshToEntity.TryGetValue(mesh, out entity)) { entity.GetComponent <BoundsRenderer>().Enabled = mesh.IsSelected; } }
/// <summary> /// Called when the visibility for a mesh has been changed. /// </summary> private void OnVisibilityChanged(MeshInfo mesh) { Entity entity; if (m_meshToEntity.TryGetValue(mesh, out entity)) { foreach (MeshRenderer renderer in entity.GetComponents <MeshRenderer>()) { renderer.Enabled = mesh.IsVisible; } } }
/// <summary> /// Called when a mesh is removed from the scene. /// </summary> private void OnMeshRemoved(MeshInfo mesh) { Entity entity; if (m_meshToEntity.TryGetValue(mesh, out entity)) { mesh.SelectionChanged -= OnSelectionChanged; mesh.VisibilityChanged -= OnVisibilityChanged; m_meshToEntity.Remove(mesh); m_entityToMesh.Remove(entity); entity.Dispose(); } }
/// <summary> /// Called when a mesh has had its visibility changed. /// </summary> private void OnVisibilityChanged(MeshInfo mesh) { m_treeView.Selection.Changed -= OnListSelectionChanged; TreePath path = new TreePath(m_meshToIndex[mesh].ToString()); TreeIter iter; if (m_listStore.GetIter(out iter, path)) { m_listStore.SetValue(iter, 0, mesh.IsVisible); m_treeView.Selection.UnselectPath(path); } m_treeView.Selection.Changed += OnListSelectionChanged; }
/// <summary> /// Called when the active mesh in the user's selection has changed. /// </summary> /// <param name="prevActive">The mesh.</param> private void SetDisplayedMesh(MeshInfo mesh) { if (mesh != null && mesh.IsActive) { m_name.Text = mesh.Mesh.Name; m_vertexCount.Text = mesh.Mesh.VertexCount.ToString(); m_triangleCount.Text = mesh.Mesh.TriangleCount.ToString(); m_hiddenOnNoActive.ForEach(w => w.ShowAll()); } else { m_hiddenOnNoActive.ForEach(w => w.HideAll()); } }
/// <summary> /// Called when the selected meshes have changed. /// </summary> private void OnMeshSelectionChanged(MeshInfo mesh) { m_treeView.Selection.Changed -= OnListSelectionChanged; TreePath path = new TreePath(m_meshToIndex[mesh].ToString()); if (mesh.IsSelected) { m_treeView.Selection.SelectPath(path); } else { m_treeView.Selection.UnselectPath(path); } m_treeView.Selection.Changed += OnListSelectionChanged; }
/// <summary> /// Gets a list of meshes corresponding to the users selection. /// </summary> private List <MeshInfo> GetSelectedMeshes() { List <MeshInfo> meshes = new List <MeshInfo>(); foreach (TreePath path in m_treeView.Selection.GetSelectedRows()) { MeshInfo mesh = m_indexToMesh[path.Indices[0]]; if (mesh.IsVisible) { meshes.Add(mesh); } else { m_treeView.Selection.UnselectPath(path); } } return(meshes); }
/// <summary> /// Called when a mesh is added to the scene. /// </summary> private void OnMeshRemoved(MeshInfo mesh) { mesh.SelectionChanged -= OnMeshSelectionChanged; mesh.VisibilityChanged -= OnVisibilityChanged; }
/// <summary> /// Called when a mesh is added to the scene. /// </summary> private void OnMeshRemoved(MeshInfo mesh) { mesh.ActiveChanged -= SetDisplayedMesh; }