//----------------------------------------------------------------------------- // EditCurveKeySelection.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.Text; using Microsoft.Xna.Framework; namespace Xna.Tools { /// /// This class contains EditCurveKey selction information. /// [Serializable] public class EditCurveKeySelection : Dictionary, IEquatable { #region Constructors. /// /// Create new instance of EditCurveKeySelection from EditCurve. /// /// /// New instance of EditCurveKeySelection public EditCurveKeySelection(ICollection keys) : this() { foreach (EditCurveKey key in keys) { if ( key.Selection != EditCurveSelections.None ) Select(key.Id, key.Selection); } } public EditCurveKeySelection() : base() { } protected EditCurveKeySelection(SerializationInfo info, StreamingContext context): base(info, context) { } #endregion #region Equality override methods. public override bool Equals(object obj) { bool isSame = false; EditCurveKeySelection other = obj as EditCurveKeySelection; if (other != null) isSame = Equals(other); return isSame; } public override int GetHashCode() { int hashCode = 0; foreach (long key in Keys) hashCode += key.GetHashCode() + this[key].GetHashCode(); return hashCode; } public bool Equals(EditCurveKeySelection other) { if (other == null) return false; if (this.Count != other.Count) return false; foreach (long key in Keys) { if (!other.ContainsKey(key)) return false; if (this[key] != other[key]) return false; } return true; } #endregion /// /// Add CurveKey to selection. /// /// EditCurveKey id /// slection type public void Select(long id, EditCurveSelections selectTypes) { // Update selectTypes if it already in selection, otherwise, // just add to selection. if (ContainsKey(id)) this[id] = this[id] | selectTypes; else Add(id, selectTypes); } /// /// Create clone of a selection. /// /// /// public EditCurveKeySelection Clone() { EditCurveKeySelection newSelection = new EditCurveKeySelection(); foreach (long keyId in Keys) newSelection.Add(keyId, this[keyId]); return newSelection; } /// /// Compare given EditCueveKey collection and this selection. /// /// It returns true if seleciton are same, /// otherwise it returns false. public bool CompareSelection(ICollection editCurveKeys) { if (this.Count != editCurveKeys.Count) return false; foreach ( EditCurveKey key in editCurveKeys ) { if (!ContainsKey(key.Id)) return false; if (this[key.Id] != key.Selection) return false; } return true; } /// /// Select intersected EditCurveKey. /// /// Selection target EditCurveKeys. /// Select region in unit coordinate. /// It select only one EditCurveKey /// if this value is true. /// It returns true if any EditCurveKey selected; /// otherwise it returns false. public bool SelectKeys(ICollection editCurveKeys, BoundingBox selectRegion, bool singleSelect) { bool selected = false; foreach (EditCurveKey key in editCurveKeys) { Vector3 p = new Vector3(key.OriginalKey.Position, key.OriginalKey.Value, 0); if (selectRegion.Contains(p) != ContainmentType.Disjoint) { Select(key.Id, EditCurveSelections.Key); selected = true; if (singleSelect) break; } } return selected; } /// /// Select intersected tangents. /// /// Selection target EditCurveKeys. /// Select region in unit coordinate. /// Tangent length in unit coordinate. /// It select only one EditCurveKey /// if this value is true. /// It returns true if any EditCurveKey selected; /// otherwise it returns false. public bool SelectTangents(ICollection editCurveKeys, BoundingBox selectRegion, Vector2 tangentScale, bool singleSelect) { bool selected = false; foreach (EditCurveKey key in editCurveKeys) { CurveKey orgKey = key.OriginalKey; // User can't select stepped continuity key tangents. if (orgKey.Continuity == CurveContinuity.Step) continue; Vector3 rayOrigin = new Vector3(orgKey.Position, orgKey.Value, 0); for (int i = 0; i < 2; ++i) { float tsx = tangentScale.X; float tsy = tangentScale.Y; Vector3 dir = (i == 0) ? new Vector3(-tsx, -orgKey.TangentIn * tsy, 0) : new Vector3(tsx, orgKey.TangentOut * tsy, 0); float length = dir.Length(); dir.Normalize(); Ray ray = new Ray(rayOrigin, dir); Nullable result; selectRegion.Intersects(ref ray, out result); if (result.HasValue && result.Value < length) { Select( key.Id, (i==0)? EditCurveSelections.TangentIn: EditCurveSelections.TangentOut); selected = true; if (singleSelect) break; } } } return selected; } /// /// Create new selection that result of toggle selection given two selections. /// /// Current selection /// New selection /// Toggle selection result. public static EditCurveKeySelection ToggleSelection( EditCurveKeySelection selection, EditCurveKeySelection newSelection) { EditCurveKeySelection result = selection.Clone(); foreach (long key in newSelection.Keys) { EditCurveSelections s; if (result.TryGetValue(key, out s)) { // Both selection contains same key, toggle selections value. s = s ^ newSelection[key]; if (s != EditCurveSelections.None) result[key] = s; else result.Remove(key); } else { result.Add(key, newSelection[key]); } } return result; } } }