Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
Vector2Editor.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Windows;
5 using System.Windows.Controls;
6 using System.Windows.Data;
7 
8 using SiliconStudio.Core.Mathematics;
9 
10 namespace SiliconStudio.Presentation.Controls
11 {
12  public class Vector2Editor : Control
13  {
14  private bool interlock;
15 
16  /// <summary>
17  /// Identifies the <see cref="Vector"/> dependency property.
18  /// </summary>
19  public static readonly DependencyProperty VectorProperty = DependencyProperty.Register("Vector", typeof(Vector2), typeof(Vector2Editor), new FrameworkPropertyMetadata(default(Vector2), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnVectorPropertyChanged, null, false, UpdateSourceTrigger.Explicit));
20 
21  /// <summary>
22  /// Identifies the <see cref="X"/> dependency property.
23  /// </summary>
24  public static readonly DependencyProperty XProperty = DependencyProperty.Register("X", typeof(float), typeof(Vector2Editor), new FrameworkPropertyMetadata(.0f, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnCartesianPropertyChanged));
25 
26  /// <summary>
27  /// Identifies the <see cref="Y"/> dependency property.
28  /// </summary>
29  public static readonly DependencyProperty YProperty = DependencyProperty.Register("Y", typeof(float), typeof(Vector2Editor), new FrameworkPropertyMetadata(.0f, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnCartesianPropertyChanged));
30 
31  /// <summary>
32  /// Identifies the <see cref="Length"/> dependency property.
33  /// </summary>
34  public static readonly DependencyProperty LengthProperty = DependencyProperty.Register("Length", typeof(float), typeof(Vector2Editor), new FrameworkPropertyMetadata(0.0f, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnPolarPropertyChanged, CoerceLengthValue));
35 
36  /// <summary>
37  /// Identifies the <see cref="Angle"/> dependency property.
38  /// </summary>
39  public static readonly DependencyProperty AngleProperty = DependencyProperty.Register("Angle", typeof(float), typeof(Vector2Editor), new FrameworkPropertyMetadata(0.0f, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnPolarPropertyChanged, CoerceAngleValue));
40 
41  /// <summary>
42  /// The <see cref="Vector2"/> associated to this control.
43  /// </summary>
44  public Vector2 Vector { get { return (Vector2)GetValue(VectorProperty); } set { SetValue(VectorProperty, value); } }
45 
46  /// <summary>
47  /// The X component (in Cartesian coordinate system) of the <see cref="Vector2"/> associated to this control.
48  /// </summary>
49  public float X { get { return (float)GetValue(XProperty); } set { SetValue(XProperty, value); } }
50 
51  /// <summary>
52  /// The Y component (in Cartesian coordinate system) of the <see cref="Vector2"/> associated to this control.
53  /// </summary>
54  public float Y { get { return (float)GetValue(YProperty); } set { SetValue(YProperty, value); } }
55 
56  /// <summary>
57  /// The length (in polar coordinate system) of the <see cref="Vector2"/> associated to this control.
58  /// </summary>
59  public float Length { get { return (float)GetValue(LengthProperty); } set { SetValue(LengthProperty, value); } }
60 
61  /// <summary>
62  /// The angle (in polar coordinate system) of the <see cref="Vector2"/> associated to this control.
63  /// </summary>
64  public float Angle { get { return (float)GetValue(AngleProperty); } set { SetValue(AngleProperty, value); } }
65 
66  /// <summary>
67  /// Raised when the <see cref="Vector"/> property is modified.
68  /// </summary>
69  private void OnVectorValueChanged()
70  {
71  if (!interlock)
72  {
73  interlock = true;
74  SetCurrentValue(XProperty, Vector.X);
75  SetCurrentValue(YProperty, Vector.Y);
76  SetCurrentValue(LengthProperty, Vector.Length());
77  SetCurrentValue(AngleProperty, MathUtil.RadiansToDegrees((float)Math.Atan2(Vector.Y, Vector.X)));
78  interlock = false;
79  }
80 
81  UpdateBinding(VectorProperty);
82  }
83 
84  /// <summary>
85  /// Raised when the <see cref="X"/> or <see cref="Y"/> properties are modified.
86  /// </summary>
87  /// <param name="e">The dependency property that has changed.</param>
88  private void OnCartesianValueChanged(DependencyPropertyChangedEventArgs e)
89  {
90  if (!interlock)
91  {
92  interlock = true;
93  if (e.Property == XProperty)
94  Vector = new Vector2((float)e.NewValue, Vector.Y);
95  else if (e.Property == YProperty)
96  Vector = new Vector2(Vector.X, (float)e.NewValue);
97  else
98  throw new ArgumentException("Property unsupported by method OnCartesianPropertyChanged.");
99 
100  SetCurrentValue(LengthProperty, Vector.Length());
101  SetCurrentValue(AngleProperty, MathUtil.RadiansToDegrees((float)Math.Atan2(Vector.Y, Vector.X)));
102  interlock = false;
103  }
104 
105  UpdateBinding(e.Property);
106  }
107 
108  /// <summary>
109  /// Raised when the <see cref="Length"/> or <see cref="Angle"/> properties are modified.
110  /// </summary>
111  /// <param name="e">The dependency property that has changed.</param>
112  private void OnPolarValueChanged(DependencyPropertyChangedEventArgs e)
113  {
114  if (!interlock)
115  {
116  interlock = true;
117  float length = Length;
118  float angle = Angle;
119  if (e.Property == LengthProperty)
120  {
121  length = (float)e.NewValue;
122  }
123  else if (e.Property == AngleProperty)
124  {
125  angle = (float)e.NewValue;
126  }
127  else
128  throw new ArgumentException("Property unsupported by method OnCartesianPropertyChanged.");
129 
130  angle = MathUtil.DegreesToRadians(angle);
131  Vector = new Vector2((float)(length * Math.Cos(angle)), (float)(length * Math.Sin(MathUtil.DegreesToRadians(angle))));
132  SetCurrentValue(XProperty, Vector.X);
133  SetCurrentValue(YProperty, Vector.Y);
134  interlock = false;
135  }
136 
137  UpdateBinding(e.Property);
138  }
139 
140  /// <summary>
141  /// Updates the binding of the given dependency property.
142  /// </summary>
143  /// <param name="dependencyProperty">The dependency property.</param>
144  private void UpdateBinding(DependencyProperty dependencyProperty)
145  {
146  BindingExpression expression = GetBindingExpression(dependencyProperty);
147  if (expression != null)
148  expression.UpdateSource();
149  }
150 
151  /// <summary>
152  /// Raised by <see cref="VectorProperty"/> when the <see cref="Vector"/> dependency property is modified.
153  /// </summary>
154  /// <param name="sender">The dependency object where the event handler is attached.</param>
155  /// <param name="e">The event data.</param>
156  private static void OnVectorPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
157  {
158  var editor = (Vector2Editor)sender;
159  editor.OnVectorValueChanged();
160  }
161 
162  /// <summary>
163  /// Raised by <see cref="XProperty"/> or <see cref="YProperty"/> when respectively the
164  /// <see cref="X"/> or <see cref="Y"/> dependency property is modified.
165  /// </summary>
166  /// <param name="sender">The dependency object where the event handler is attached.</param>
167  /// <param name="e">The event data.</param>
168  private static void OnCartesianPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
169  {
170  var editor = (Vector2Editor)sender;
171  editor.OnCartesianValueChanged(e);
172  }
173 
174  /// <summary>
175  /// Raised by <see cref="LengthProperty"/> or <see cref="AngleProperty"/> when respectively the
176  /// <see cref="Length"/> or <see cref="Angle"/> dependency property is modified.
177  /// </summary>
178  /// <param name="sender">The dependency object where the event handler is attached.</param>
179  /// <param name="e">The event data.</param>
180  private static void OnPolarPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
181  {
182  var editor = (Vector2Editor)sender;
183  editor.OnPolarValueChanged(e);
184  }
185 
186  /// <summary>
187  /// Coerce the value of the Length so it is always positive
188  /// </summary>
189  private static object CoerceLengthValue(DependencyObject sender, object baseValue)
190  {
191  return Math.Max(0.0f, (float)baseValue);
192  }
193 
194  /// <summary>
195  /// Coerce the value of the Angle so it is always contained between 0 and 360
196  /// </summary>
197  private static object CoerceAngleValue(DependencyObject sender, object baseValue)
198  {
199  return (float)baseValue % 360.0f;
200  }
201  }
202 }
SiliconStudio.Paradox.Games.Mathematics.Vector2 Vector2
Represents a two dimensional mathematical vector.
Definition: Vector2.cs:42
static float RadiansToDegrees(float radian)
Converts radians to degrees.
Definition: MathUtil.cs:264