//-----------------------------------------------------------------------------
// 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;
}
}
}