I am using XR class from Unity and trying to add all button inputs to m_SelectUsage. But unfortunately it does not take an array of values. Here in the picture as you can see, only one button can be used "Grip". Is there a way to add all the button inputs to this class?
using UnityEngine.SpatialTracking;
#if LIH_PRESENT
using UnityEngine.Experimental.XR.Interaction;
#endif
namespace UnityEngine.XR.Interaction.Toolkit
{
/// <summary>
/// <see cref="XRBaseController"/> <see cref="MonoBehaviour"/> that interprets
/// feature values on an input device in the XR input subsystem into
/// XR Interaction Interactor position, rotation, and interaction states.
/// </summary>
[AddComponentMenu("XR/XR Controller (Device-based)")]
public class XRController : XRBaseController
{
[SerializeField]
[Tooltip("The XRNode for this controller.")]
XRNode m_ControllerNode = XRNode.RightHand;
/// <summary>
/// The <see cref="XRNode"/> for this controller.
/// </summary>
public XRNode controllerNode
{
get => m_ControllerNode;
set => m_ControllerNode = value;
}
[SerializeField]
[Tooltip("The input to use for detecting a select.")]
InputHelpers.Button m_SelectUsage = InputHelpers.Button.Grip;
/// <summary>
/// The input to use for detecting a select.
/// </summary>
public InputHelpers.Button selectUsage
{
get => m_SelectUsage;
set => m_SelectUsage = value;
}
[SerializeField]
[Tooltip("The input to use for detecting activation.")]
InputHelpers.Button m_ActivateUsage = InputHelpers.Button.Trigger;
/// <summary>
/// The input to use for detecting activation.
/// </summary>
public InputHelpers.Button activateUsage
{
get => m_ActivateUsage;
set => m_ActivateUsage = value;
}
[SerializeField]
[Tooltip("The input to use for detecting a UI press.")]
InputHelpers.Button m_UIPressUsage = InputHelpers.Button.Trigger;
/// <summary>
/// The input to use for detecting a UI press.
/// </summary>
public InputHelpers.Button uiPressUsage
{
get => m_UIPressUsage;
set => m_UIPressUsage = value;
}
[SerializeField]
[Tooltip("The amount an axis needs to be pressed to trigger an interaction event.")]
float m_AxisToPressThreshold = 0.1f;
/// <summary>
/// The amount an axis needs to be pressed to trigger an interaction event.
/// </summary>
public float axisToPressThreshold
{
get => m_AxisToPressThreshold;
set => m_AxisToPressThreshold = value;
}
[SerializeField]
[Tooltip("The input to use to rotate an anchor to the Left.")]
InputHelpers.Button m_RotateAnchorLeft = InputHelpers.Button.PrimaryAxis2DLeft;
/// <summary>
/// The input to use to rotate an anchor to the Left.
/// </summary>
public InputHelpers.Button rotateObjectLeft
{
get => m_RotateAnchorLeft;
set => m_RotateAnchorLeft = value;
}
[SerializeField]
[Tooltip("The input to use to rotate an anchor to the Right.")]
InputHelpers.Button m_RotateAnchorRight = InputHelpers.Button.PrimaryAxis2DRight;
/// <summary>
/// The input to use to rotate an anchor to the Right.
/// </summary>
public InputHelpers.Button rotateObjectRight
{
get => m_RotateAnchorRight;
set => m_RotateAnchorRight = value;
}
[SerializeField]
[Tooltip("The input that will be used to translate the anchor away from the interactor.")]
InputHelpers.Button m_MoveObjectIn = InputHelpers.Button.PrimaryAxis2DUp;
/// <summary>
/// The input that will be used to translate the anchor away from the interactor.
/// </summary>
public InputHelpers.Button moveObjectIn
{
get => m_MoveObjectIn;
set => m_MoveObjectIn = value;
}
[SerializeField]
[Tooltip("The input that will be used to translate the anchor towards the interactor.")]
InputHelpers.Button m_MoveObjectOut = InputHelpers.Button.PrimaryAxis2DDown;
/// <summary>
/// The input that will be used to translate the anchor towards the interactor.
/// </summary>
public InputHelpers.Button moveObjectOut
{
get => m_MoveObjectOut;
set => m_MoveObjectOut = value;
}
#if LIH_PRESENT
[SerializeField, Tooltip("Pose provider used to provide tracking data separate from the XR Node.")]
BasePoseProvider m_PoseProvider;
/// <summary>
/// Pose provider used to provide tracking data separate from the <see cref="XRNode"/>.
/// </summary>
public BasePoseProvider poseProvider
{
get => m_PoseProvider;
set => m_PoseProvider = value;
}
#endif
InputDevice m_InputDevice;
/// <summary>
/// (Read Only) The <see cref="InputDevice"/> being used to read data from.
/// </summary>
public InputDevice inputDevice => m_InputDevice.isValid ? m_InputDevice : m_InputDevice = InputDevices.GetDeviceAtXRNode(controllerNode);
/// <inheritdoc />
protected override void UpdateTrackingInput(XRControllerState controllerState)
{
controllerState.poseDataFlags = PoseDataFlags.NoData;
#if LIH_PRESENT_V1API
if (m_PoseProvider != null)
{
if (m_PoseProvider.TryGetPoseFromProvider(out var poseProviderPose))
{
controllerState.position = poseProviderPose.position;
controllerState.rotation = poseProviderPose.rotation;
controllerState.poseDataFlags = PoseDataFlags.Position | PoseDataFlags.Rotation;
}
}
else
#elif LIH_PRESENT_V2API
if (m_PoseProvider != null)
{
var retFlags = m_PoseProvider.GetPoseFromProvider(out var poseProviderPose);
if ((retFlags & PoseDataFlags.Position) != 0)
{
controllerState.position = poseProviderPose.position;
controllerState.poseDataFlags |= PoseDataFlags.Position;
}
if ((retFlags & PoseDataFlags.Rotation) != 0)
{
controllerState.rotation = poseProviderPose.rotation;
controllerState.poseDataFlags |= PoseDataFlags.Rotation;
}
}
else
#endif
{
if (inputDevice.TryGetFeatureValue(CommonUsages.devicePosition, out controllerState.position))
{
controllerState.poseDataFlags |= PoseDataFlags.Position;
}
if (inputDevice.TryGetFeatureValue(CommonUsages.deviceRotation, out controllerState.rotation))
{
controllerState.poseDataFlags |= PoseDataFlags.Rotation;
}
}
}
/// <inheritdoc />
protected override void UpdateInput(XRControllerState controllerState)
{
controllerState.ResetFrameDependentStates();
HandleInteractionAction(m_SelectUsage, ref controllerState.selectInteractionState);
HandleInteractionAction(m_ActivateUsage, ref controllerState.activateInteractionState);
HandleInteractionAction(m_UIPressUsage, ref controllerState.uiPressInteractionState);
}
void HandleInteractionAction(InputHelpers.Button button, ref InteractionState interactionState)
{
inputDevice.IsPressed(button, out var pressed, m_AxisToPressThreshold);
if (pressed)
{
Debug.Log("Detect");
if (!interactionState.active)
{
interactionState.activatedThisFrame = true;
interactionState.active = true;
}
}
else
{
if (interactionState.active)
{
interactionState.deactivatedThisFrame = true;
interactionState.active = false;
}
}
}
/// <inheritdoc />
public override bool SendHapticImpulse(float amplitude, float duration)
{
if (inputDevice.TryGetHapticCapabilities(out var capabilities) &&
capabilities.supportsImpulse)
{
return inputDevice.SendHapticImpulse(0u, amplitude, duration);
}
return false;
}
}
}
You can overwrite XRController to accept an array for each of the input values.
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
public class MyXRController : XRController
{
[SerializeField]
InputHelpers.Button[] m_SelectUsageArray;
protected override void UpdateInput(XRControllerState controllerState)
{
// Because we use base input m_SelectUsage will still be accepted if provided
base.UpdateInput(controllerState);
// Iterate over all buttons
foreach (var selectUsage in m_SelectUsageArray)
{
HandleInteractionAction(selectUsage, ref controllerState.selectInteractionState);
}
}
}
You can overwrite other interactions in a similar manner.
Then in your GameObject, use MyXRController instead of XRController
Related
I have a media player in which I want to hide the aspect ratio, cast to device and full screen icon in media player. This is the screenshot of my media player in which I have marked the icon which I need to hide in red color.
So I have taken this media player from this link. This is the my Xaml code
<StackLayout>
<Button Text="Stretch" Clicked="Button_Clicked"/>
<forms1:MediaElement HorizontalOptions="Fill" BackgroundColor="Green" VerticalOptions="Center" HeightRequest="180" x:Name="Media" IsLooping="True" AreTransportControlsEnabled="true" Source="http://video.ch9.ms/ch9/334f/891b78a5-642d-40b4-8d02-ff40ffdd334f/LoginToLinkedinUSingXamarinAuth_mid.mp4"/>
</StackLayout>
This is my media element code-
public sealed class MediaElement : View
{
/// <summary>
/// Identifies the AreTransportControlsEnabled dependency property.
/// </summary>
public static readonly BindableProperty AreTransportControlsEnabledProperty =
BindableProperty.Create(nameof(AreTransportControlsEnabled), typeof(bool), typeof(MediaElement), false);
/// <summary>
/// Identifies the AutoPlay dependency property.
/// </summary>
public static readonly BindableProperty AutoPlayProperty =
BindableProperty.Create(nameof(AutoPlay), typeof(bool), typeof(MediaElement), true);
/// <summary>
/// Identifies the BufferingProgress dependency property.
/// </summary>
public static readonly BindableProperty BufferingProgressProperty =
BindableProperty.Create(nameof(BufferingProgress), typeof(double), typeof(MediaElement), 0.0);
/// <summary>
/// Identifies the IsLooping dependency property.
/// </summary>
public static readonly BindableProperty IsLoopingProperty =
BindableProperty.Create(nameof(IsLooping), typeof(bool), typeof(MediaElement), false);
/// <summary>
/// Identifies the KeepScreenOn dependency property.
/// </summary>
public static readonly BindableProperty KeepScreenOnProperty =
BindableProperty.Create(nameof(KeepScreenOn), typeof(bool), typeof(MediaElement), false);
/// <summary>
/// Identifies the Source dependency property.
/// </summary>
public static readonly BindableProperty SourceProperty =
BindableProperty.Create(nameof(Source), typeof(Uri), typeof(MediaElement));
/// <summary>
/// Identifies the CurrentState dependency property.
/// </summary>
public static readonly BindableProperty CurrentStateProperty =
BindableProperty.Create(nameof(CurrentState), typeof(MediaElementState), typeof(MediaElement), MediaElementState.Closed);
/// <summary>
/// Identifies the Position dependency property.
/// </summary>
public static readonly BindableProperty PositionProperty =
BindableProperty.Create(nameof(Position), typeof(TimeSpan), typeof(MediaElement), TimeSpan.Zero, validateValue: ValidatePosition);
private static bool ValidatePosition(BindableObject bindable, object value)
{
MediaElement element = bindable as MediaElement;
if (element != null)
{
if (element._renderer != null)
{
element._renderer.Seek((TimeSpan)value);
}
}
return true;
}
/// <summary>
/// Identifies the Stretch dependency property.
/// </summary>
public static readonly BindableProperty StretchProperty =
BindableProperty.Create(nameof(Stretch), typeof(Stretch), typeof(MediaElement), Stretch.Uniform);
private IMediaElementRenderer _renderer = null;
public void SetRenderer(IMediaElementRenderer renderer)
{
_renderer = renderer;
}
/// <summary>
/// Gets or sets a value that determines whether the standard transport controls are enabled.
/// </summary>
public bool AreTransportControlsEnabled
{
get { return (bool)GetValue(AreTransportControlsEnabledProperty); }
set { SetValue(AreTransportControlsEnabledProperty, value); }
}
/// <summary>
/// Gets or sets a value that indicates whether media will begin playback automatically when the <see cref="Source"/> property is set.
/// </summary>
public bool AutoPlay
{
get { return (bool)GetValue(AutoPlayProperty); }
set { SetValue(AutoPlayProperty, value); }
}
/// <summary>
/// Gets a value that indicates the current buffering progress.
/// </summary>
/// <value>The amount of buffering that is completed for media content.
/// The value ranges from 0 to 1.
/// Multiply by 100 to obtain a percentage.</value>
public double BufferingProgress
{
get
{
return (double)GetValue(BufferingProgressProperty);
}
}
/// <summary>
/// Gets or sets a value that describes whether the media source currently loaded in the media engine should automatically set the position to the media start after reaching its end.
/// </summary>
public bool IsLooping
{
get { return (bool)GetValue(IsLoopingProperty); }
set { SetValue(IsLoopingProperty, value); }
}
/// <summary>
/// Gets or sets a value that specifies whether the control should stop the screen from timing out when playing media.
/// </summary>
public bool KeepScreenOn
{
get { return (bool)GetValue(KeepScreenOnProperty); }
set { SetValue(KeepScreenOnProperty, value); }
}
public TimeSpan NaturalDuration
{
get
{
if (_renderer != null)
{
return _renderer.NaturalDuration;
}
return TimeSpan.Zero;
}
}
public int NaturalVideoHeight
{
get
{
if (_renderer != null)
{
return _renderer.NaturalVideoHeight;
}
return 0;
}
}
public int NaturalVideoWidth
{
get
{
if (_renderer != null)
{
return _renderer.NaturalVideoWidth;
}
return 0;
}
}
/// <summary>
/// Gets or sets a media source on the MediaElement.
/// </summary>
[TypeConverter(typeof(Xamarin.Forms.UriTypeConverter))]
public Uri Source
{
get { return (Uri)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
private IDictionary<string, string> _httpHeaders = new Dictionary<string, string>();
public IDictionary<string, string> HttpHeaders
{
get
{
return _httpHeaders;
}
}
/// <summary>
/// Gets the status of this MediaElement.
/// </summary>
public MediaElementState CurrentState
{
get { return (MediaElementState)GetValue(CurrentStateProperty); }
internal set
{
SetValue(CurrentStateProperty, value);
}
}
public void RaiseCurrentStateChanged()
{
CurrentStateChanged?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// Gets or sets the current position of progress through the media's playback time.
/// </summary>
public System.TimeSpan Position
{
get
{
if (_renderer != null)
{
return _renderer.Position;
}
return (TimeSpan)GetValue(PositionProperty);
}
set
{
SetValue(PositionProperty, value);
}
}
/// <summary>
/// Plays media from the current position.
/// </summary>
public void Play()
{
CurrentState = MediaElementState.Playing;
}
/// <summary>
/// Pauses media at the current position.
/// </summary>
public void Pause()
{
if (CurrentState == MediaElementState.Playing)
{
CurrentState = MediaElementState.Paused;
}
}
/// <summary>
/// Stops and resets media to be played from the beginning.
/// </summary>
public void Stop()
{
if (CurrentState != MediaElementState.Stopped)
{
CurrentState = MediaElementState.Stopped;
}
}
/// <summary>
/// Gets or sets a value that describes how an MediaElement should be stretched to fill the destination rectangle.
/// </summary>
/// <value>A value of the <see cref="Stretch"/> enumeration that specifies how the source visual media is rendered.
/// The default value is Uniform.</value>
public Stretch Stretch
{
get
{
return (Stretch)GetValue(StretchProperty);
}
set
{
SetValue(StretchProperty, value);
}
}
/// <summary>
/// Occurs when the value of the <see cref="CurrentState"/> property changes.
/// </summary>
public event EventHandler CurrentStateChanged;
/// <summary>
/// Occurs when the MediaElement finishes playing audio or video.
/// </summary>
public event EventHandler MediaEnded;
public void RaiseMediaOpened()
{
MediaOpened?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// Occurs when the media stream has been validated and opened, and the file headers have been read.
/// </summary>
public event EventHandler MediaOpened;
public void RaiseSeekCompleted()
{
SeekCompleted?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// Occurs when the seek point of a requested seek operation is ready for playback.
/// </summary>
public event EventHandler SeekCompleted;
public void OnMediaEnded()
{
CurrentState = MediaElementState.Stopped;
if (MediaEnded != null)
{
System.Diagnostics.Debug.WriteLine("Media Ended");
MediaEnded(this, EventArgs.Empty);
}
}
internal void RaisePropertyChanged(string propertyName)
{
OnPropertyChanged(propertyName);
}
}
public interface IMediaElementRenderer
{
double BufferingProgress { get; }
TimeSpan NaturalDuration { get; }
int NaturalVideoHeight { get; }
int NaturalVideoWidth { get; }
TimeSpan Position { get; }
void Seek(TimeSpan time);
}
}
I don't have any clue how hide those icons. Any suggestions?
I have this code in front but I can't build a linked list with more than one element. I see that in the methode "einsetzenNach" the code block in the if statement will never executed. The reason is that the cursor will never get != 0
The code original was in Java.
I am thankful for any tips.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace EinfachVerketteteListe
{
class Program
{
static void Main(string[] args)
{
Liste myList = new Liste();
myList.einsetzenVor(1, "Nr01");
myList.einsetzenVor(2, "Nr02");
myList.einsetzenNach(2, "Nr02");
myList.einsetzenNach(3, "Nr03");
myList.inhalt(3);
myList.laenge();
myList.ToString();
}
}
Here is the Cell class
class Zelle
{
// Contents
public Object inhalt;
// Next cell
public Zelle next;
public Zelle(Object el)
{
inhalt = el;
}
public Zelle(Object el, Zelle z)
{
inhalt = el;
next = z;
}
public Zelle(Zelle z)
{
next = z;
}
}
Our custom list class
public class Liste
{
// Start element
private Zelle anfang;
// Current Element
private Zelle cursor;
/// <summary>
/// There are no more items in the list, start is null
/// </summary>
/// <returns>start == null</returns>
public Boolean IstLeer()
{
return anfang == null;
}
/// <summary>
/// Length of the list
/// </summary>
/// <returns>l = listlenght</returns>
public int laenge()
{
Zelle cur = anfang;
int l = 0;
while (cur != null)
{
l++;
cur = cur.next;
}
return l;
}
/// <summary>
/// Check of the declared position is valid
/// </summary>
/// <param name="p">Position</param>
/// <returns>true/false</returns>
public Boolean istGueltigePosition(int p)
{
return (p >= 1) && (p <= laenge() );
}
/// <summary>
///
/// </summary>
/// <param name="p">Set cursor on a specific position</param>
public void setzeCursor(int p)
{
cursor = null;
if (istGueltigePosition(p))
{
Zelle cur = anfang;
// cur.next is null. The reason is that there is only one element in the list
// How can I fix this block. However I assume the code will work.
// Maybe I handle something not in the correct order.
for (int i = 0; i < p; i++)
{ cur = cur.next; }
cursor = cur;
}
}
Maybe the Methode initCursor() is the answer to my understanding problem.
However I have no idea in which way I can use this methode to print out the first element.
/// <summary>
/// Initial Position Cursor
/// </summary>
public void initCursor()
{
cursor = anfang;
}
/// <summary>
/// Search for specific object and return it's index
/// </summary>
/// <param name="e">Zu findende Daten</param>
/// <returns>p = Index</returns>
public int suche(Object e)
{
cursor = null;
int p = 0, l = 0;
Zelle z = anfang;
while (z != null)
{
l++;
if ( z.inhalt == e )
{
p = l;
cursor = z;
break;
}
z = z.next;
}
return p;
}
/// <summary>
/// Insert cell after element p
/// </summary>
/// <param name="p">Position</param>
/// <param name="e">Daten</param>
public void einsetzenNach(int p, Object e)
{
setzeCursor(p);
This if statment will never get !=0
if (cursor != null)
{
Zelle z = new Zelle(e, cursor.next);
cursor.next = z;
}
}
/// <summary>
/// Insert cell after element p
/// </summary>
/// <param name="p">Position</param>
/// <param name="e">Daten</param>
public void einsetzenVor(int p, Object e)
{
if (p > 1) einsetzenNach(p-1,e);
else
{
// Insert at the beginning
Zelle z = new Zelle(e, anfang);
anfang = z;
}
}
public void loesche(int p)
{
if (istGueltigePosition(p))
{
if (p == 1) // Lösche 1. Object
anfang = anfang.next;
else
{
setzeCursor(p - 1);
cursor.next = cursor.next.next;
}
}
}
/// <summary>
/// Show the content
/// </summary>
/// <param name="p">position</param>
/// <returns></returns>
public Object inhalt(int p)
{
setzeCursor(p);
if (cursor == null) return null;
return cursor.inhalt;
}
/// <summary>
/// next cell/data
/// </summary>
/// <returns>Daten</returns>
public Object naechstes()
{
if (cursor == null) return null;
Object e = cursor.inhalt;
cursor = cursor.next;
return e;
}
}
}
Let's assume you added the first element successfully to the list and now you want to add the second element.
After checking for a valid position you set your current cell to start (Zelle cur = anfang;). After that you want to get to the position where you want to insert your object. But since it is your first element there are no following elements. So cur will always be null after the loop.
Since your list has not a zero-based index you should start your loop with the first index of your list. Try the following loop:
for (int i = 1; i < p; i++)
{
if (cur.next == null)
{
break;
}
cur = cur.next;
}
cursor = cur;
Well, first try was with a readily made spinning wheel (a gif). After that, I found a code that dynamically generates a wheel, but no way in both cases to have full transparency.
Depending on what I set as parent (form or panel) and the position on my wheel on form, the spin is just half transparent.
I use C# express (VS 2008).
All I want is a nice wheel in center of form, activated when BG is doing something, but full transparent so I can resize form.
Thanks,
Update:
I worked on some code that is draw a spinning wheel just fine. Almost working except OnPantBackground() which needs to be empty to paint behind, but in this case, a black rectangle is drawn because of ControlStyles.OptimizedDoubleBuffer enabled.
Any suggestions? Thank you.
using System;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Drawing2D;
namespace WinFormsControls
{
/// <summary>
/// A label that can be transparent.
/// </summary>
public class TransparentLabel : Control
{
// Constants =========================================================
private const double NumberOfDegreesInCircle = 360;
private const double NumberOfDegreesInHalfCircle = NumberOfDegreesInCircle / 2;
private const int DefaultInnerCircleRadius = 8;
private const int DefaultOuterCircleRadius = 10;
private const int DefaultNumberOfSpoke = 10;
private const int DefaultSpokeThickness = 4;
private readonly Color DefaultColor = Color.DarkGray;
private const int MacOSXInnerCircleRadius = 5;
private const int MacOSXOuterCircleRadius = 11;
private const int MacOSXNumberOfSpoke = 12;
private const int MacOSXSpokeThickness = 2;
private const int FireFoxInnerCircleRadius = 6;
private const int FireFoxOuterCircleRadius = 7;
private const int FireFoxNumberOfSpoke = 9;
private const int FireFoxSpokeThickness = 4;
private const int IE7InnerCircleRadius = 8;
private const int IE7OuterCircleRadius = 9;
private const int IE7NumberOfSpoke = 24;
private const int IE7SpokeThickness = 4;
// Enumeration =======================================================
public enum StylePresets
{
MacOSX,
Firefox,
IE7,
Custom
}
// Attributes ========================================================
private Timer m_Timer;
private bool m_IsTimerActive;
private int m_NumberOfSpoke;
private int m_SpokeThickness;
private int m_ProgressValue;
private int m_OuterCircleRadius;
private int m_InnerCircleRadius;
private PointF m_CenterPoint;
private Color m_Color;
private Color[] m_Colors;
private double[] m_Angles;
private StylePresets m_StylePreset;
// Properties ========================================================
/// <summary>
/// Gets or sets the lightest color of the circle.
/// </summary>
/// <value>The lightest color of the circle.</value>
[TypeConverter("System.Drawing.ColorConverter"),
Category("LoadingCircle"),
Description("Sets the color of spoke.")]
public Color Color
{
get
{
return m_Color;
}
set
{
m_Color = value;
GenerateColorsPallet();
Invalidate();
}
}
/// <summary>
/// Gets or sets the outer circle radius.
/// </summary>
/// <value>The outer circle radius.</value>
[System.ComponentModel.Description("Gets or sets the radius of outer circle."),
System.ComponentModel.Category("LoadingCircle")]
public int OuterCircleRadius
{
get
{
if (m_OuterCircleRadius == 0)
m_OuterCircleRadius = DefaultOuterCircleRadius;
return m_OuterCircleRadius;
}
set
{
m_OuterCircleRadius = value;
Invalidate();
}
}
/// <summary>
/// Gets or sets the inner circle radius.
/// </summary>
/// <value>The inner circle radius.</value>
[System.ComponentModel.Description("Gets or sets the radius of inner circle."),
System.ComponentModel.Category("LoadingCircle")]
public int InnerCircleRadius
{
get
{
if (m_InnerCircleRadius == 0)
m_InnerCircleRadius = DefaultInnerCircleRadius;
return m_InnerCircleRadius;
}
set
{
m_InnerCircleRadius = value;
Invalidate();
}
}
/// <summary>
/// Gets or sets the number of spoke.
/// </summary>
/// <value>The number of spoke.</value>
[System.ComponentModel.Description("Gets or sets the number of spoke."),
System.ComponentModel.Category("LoadingCircle")]
public int NumberSpoke
{
get
{
if (m_NumberOfSpoke == 0)
m_NumberOfSpoke = DefaultNumberOfSpoke;
return m_NumberOfSpoke;
}
set
{
if (m_NumberOfSpoke != value && m_NumberOfSpoke > 0)
{
m_NumberOfSpoke = value;
GenerateColorsPallet();
GetSpokesAngles();
Invalidate();
}
}
}
/// <summary>
/// Gets or sets a value indicating whether this <see cref="T:LoadingCircle"/> is active.
/// </summary>
/// <value><c>true</c> if active; otherwise, <c>false</c>.</value>
[System.ComponentModel.Description("Gets or sets the number of spoke."),
System.ComponentModel.Category("LoadingCircle")]
public bool Active
{
get
{
return m_IsTimerActive;
}
set
{
m_IsTimerActive = value;
ActiveTimer();
}
}
/// <summary>
/// Gets or sets the spoke thickness.
/// </summary>
/// <value>The spoke thickness.</value>
[System.ComponentModel.Description("Gets or sets the thickness of a spoke."),
System.ComponentModel.Category("LoadingCircle")]
public int SpokeThickness
{
get
{
if (m_SpokeThickness <= 0)
m_SpokeThickness = DefaultSpokeThickness;
return m_SpokeThickness;
}
set
{
m_SpokeThickness = value;
Invalidate();
}
}
/// <summary>
/// Gets or sets the rotation speed.
/// </summary>
/// <value>The rotation speed.</value>
[System.ComponentModel.Description("Gets or sets the rotation speed. Higher the slower."),
System.ComponentModel.Category("LoadingCircle")]
public int RotationSpeed
{
get
{
return m_Timer.Interval;
}
set
{
if (value > 0)
m_Timer.Interval = value;
}
}
/// <summary>
/// Quickly sets the style to one of these presets, or a custom style if desired
/// </summary>
/// <value>The style preset.</value>
[Category("LoadingCircle"),
Description("Quickly sets the style to one of these presets, or a custom style if desired"),
DefaultValue(typeof(StylePresets), "Custom")]
public StylePresets StylePreset
{
get { return m_StylePreset; }
set
{
m_StylePreset = value;
switch (m_StylePreset)
{
case StylePresets.MacOSX:
SetCircleAppearance(MacOSXNumberOfSpoke,
MacOSXSpokeThickness, MacOSXInnerCircleRadius,
MacOSXOuterCircleRadius);
break;
case StylePresets.Firefox:
SetCircleAppearance(FireFoxNumberOfSpoke,
FireFoxSpokeThickness, FireFoxInnerCircleRadius,
FireFoxOuterCircleRadius);
break;
case StylePresets.IE7:
SetCircleAppearance(IE7NumberOfSpoke,
IE7SpokeThickness, IE7InnerCircleRadius,
IE7OuterCircleRadius);
break;
case StylePresets.Custom:
SetCircleAppearance(DefaultNumberOfSpoke,
DefaultSpokeThickness,
DefaultInnerCircleRadius,
DefaultOuterCircleRadius);
break;
}
}
}
/// <summary>
/// Creates a new <see cref="TransparentLabel"/> instance.
/// </summary>
public TransparentLabel()
{
TabStop = false;
InitializeComponent();
SetStyle(ControlStyles.UserPaint, true);
//SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
m_Color = DefaultColor;
GenerateColorsPallet();
GetSpokesAngles();
GetControlCenterPoint();
m_Timer = new Timer();
m_Timer.Tick += new EventHandler(aTimer_Tick);
ActiveTimer();
this.Resize += new EventHandler(LoadingCircle_Resize);
this.DoubleBuffered = true;
this.SetStyle(ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.ResizeRedraw |
ControlStyles.ContainerControl |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.SupportsTransparentBackColor
, true);
}
// Events ============================================================
/// <summary>
/// Handles the Resize event of the LoadingCircle control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
void LoadingCircle_Resize(object sender, EventArgs e)
{
GetControlCenterPoint();
}
/// <summary>
/// Handles the Tick event of the aTimer control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
void aTimer_Tick(object sender, EventArgs e)
{
m_ProgressValue = ++m_ProgressValue % m_NumberOfSpoke;
Invalidate();
}
/// <summary>
/// Gets the creation parameters.
/// </summary>
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20;
return cp;
}
}
// Overridden Methods ================================================
/// <summary>
/// Retrieves the size of a rectangular area into which a control can be fitted.
/// </summary>
/// <param name="proposedSize">The custom-sized area for a control.</param>
/// <returns>
/// An ordered pair of type <see cref="T:System.Drawing.Size"></see> representing the width and height of a rectangle.
/// </returns>
public override Size GetPreferredSize(Size proposedSize)
{
proposedSize.Width =
(m_OuterCircleRadius + m_SpokeThickness) * 2;
return proposedSize;
}
/// <summary>
/// Paints the background.
/// </summary>
/// <param name="e">E.</param>
///
protected override void OnPaintBackground(PaintEventArgs e)
{
// do nothing
}
/// <summary>
/// Paints the control.
/// </summary>
/// <param name="e">E.</param>
protected override void OnPaint(PaintEventArgs e)
{
//DrawText();
if (m_NumberOfSpoke > 0)
{
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
int intPosition = m_ProgressValue;
for (int intCounter = 0; intCounter < m_NumberOfSpoke; intCounter++)
{
intPosition = intPosition % m_NumberOfSpoke;
DrawLine(e.Graphics,
GetCoordinate(m_CenterPoint, m_InnerCircleRadius, m_Angles[intPosition]),
GetCoordinate(m_CenterPoint, m_OuterCircleRadius, m_Angles[intPosition]),
m_Colors[intCounter], m_SpokeThickness);
intPosition++;
}
}
base.OnPaint(e);
}
/*
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x000F)
{
DrawText();
}
}
private void DrawText()
{
using (Graphics graphics = CreateGraphics())
using (SolidBrush brush = new SolidBrush(ForeColor))
{
SizeF size = graphics.MeasureString(Text, Font);
// first figure out the top
float top = 0;
switch (textAlign)
{
case ContentAlignment.MiddleLeft:
case ContentAlignment.MiddleCenter:
case ContentAlignment.MiddleRight:
top = (Height - size.Height) / 2;
break;
case ContentAlignment.BottomLeft:
case ContentAlignment.BottomCenter:
case ContentAlignment.BottomRight:
top = Height - size.Height;
break;
}
float left = -1;
switch (textAlign)
{
case ContentAlignment.TopLeft:
case ContentAlignment.MiddleLeft:
case ContentAlignment.BottomLeft:
if (RightToLeft == RightToLeft.Yes)
left = Width - size.Width;
else
left = -1;
break;
case ContentAlignment.TopCenter:
case ContentAlignment.MiddleCenter:
case ContentAlignment.BottomCenter:
left = (Width - size.Width) / 2;
break;
case ContentAlignment.TopRight:
case ContentAlignment.MiddleRight:
case ContentAlignment.BottomRight:
if (RightToLeft == RightToLeft.Yes)
left = -1;
else
left = Width - size.Width;
break;
}
graphics.DrawString(Text, Font, brush, left, top);
}
}
*/
/*
/// <summary>
/// Gets or sets the text associated with this control.
/// </summary>
/// <returns>
/// The text associated with this control.
/// </returns>
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
RecreateHandle();
}
}
/// <summary>
/// Gets or sets a value indicating whether control's elements are aligned to support locales using right-to-left fonts.
/// </summary>
/// <value></value>
/// <returns>
/// One of the <see cref="T:System.Windows.Forms.RightToLeft"/> values. The default is <see cref="F:System.Windows.Forms.RightToLeft.Inherit"/>.
/// </returns>
/// <exception cref="T:System.ComponentModel.InvalidEnumArgumentException">
/// The assigned value is not one of the <see cref="T:System.Windows.Forms.RightToLeft"/> values.
/// </exception>
public override RightToLeft RightToLeft
{
get
{
return base.RightToLeft;
}
set
{
base.RightToLeft = value;
RecreateHandle();
}
}
/// <summary>
/// Gets or sets the font of the text displayed by the control.
/// </summary>
/// <value></value>
/// <returns>
/// The <see cref="T:System.Drawing.Font"/> to apply to the text displayed by the control. The default is the value of the <see cref="P:System.Windows.Forms.Control.DefaultFont"/> property.
/// </returns>
public override Font Font
{
get
{
return base.Font;
}
set
{
base.Font = value;
RecreateHandle();
}
}
private ContentAlignment textAlign = ContentAlignment.TopLeft;
/// <summary>
/// Gets or sets the text alignment.
/// </summary>
public ContentAlignment TextAlign
{
get { return textAlign; }
set
{
textAlign = value;
RecreateHandle();
}
}
*/
private void InitializeComponent()
{
this.SuspendLayout();
this.ResumeLayout(false);
}
// Methods ===========================================================
/// <summary>
/// Darkens a specified color.
/// </summary>
/// <param name="_objColor">Color to darken.</param>
/// <param name="_intPercent">The percent of darken.</param>
/// <returns>The new color generated.</returns>
private Color Darken(Color _objColor, int _intPercent)
{
int intRed = _objColor.R;
int intGreen = _objColor.G;
int intBlue = _objColor.B;
return Color.FromArgb(_intPercent, Math.Min(intRed, byte.MaxValue), Math.Min(intGreen, byte.MaxValue), Math.Min(intBlue, byte.MaxValue));
}
/// <summary>
/// Generates the colors pallet.
/// </summary>
private void GenerateColorsPallet()
{
m_Colors = GenerateColorsPallet(m_Color, Active, m_NumberOfSpoke);
}
/// <summary>
/// Generates the colors pallet.
/// </summary>
/// <param name="_objColor">Color of the lightest spoke.</param>
/// <param name="_blnShadeColor">if set to <c>true</c> the color will be shaded on X spoke.</param>
/// <returns>An array of color used to draw the circle.</returns>
private Color[] GenerateColorsPallet(Color _objColor, bool _blnShadeColor, int _intNbSpoke)
{
Color[] objColors = new Color[NumberSpoke];
// Value is used to simulate a gradient feel... For each spoke, the
// color will be darken by value in intIncrement.
byte bytIncrement = (byte)(byte.MaxValue / NumberSpoke);
//Reset variable in case of multiple passes
byte PERCENTAGE_OF_DARKEN = 0;
for (int intCursor = 0; intCursor < NumberSpoke; intCursor++)
{
if (_blnShadeColor)
{
if (intCursor == 0 || intCursor < NumberSpoke - _intNbSpoke)
objColors[intCursor] = _objColor;
else
{
// Increment alpha channel color
PERCENTAGE_OF_DARKEN += bytIncrement;
// Ensure that we don't exceed the maximum alpha
// channel value (255)
if (PERCENTAGE_OF_DARKEN > byte.MaxValue)
PERCENTAGE_OF_DARKEN = byte.MaxValue;
// Determine the spoke forecolor
objColors[intCursor] = Darken(_objColor, PERCENTAGE_OF_DARKEN);
}
}
else
objColors[intCursor] = _objColor;
}
return objColors;
}
/// <summary>
/// Gets the control center point.
/// </summary>
private void GetControlCenterPoint()
{
m_CenterPoint = GetControlCenterPoint(this);
}
/// <summary>
/// Gets the control center point.
/// </summary>
/// <returns>PointF object</returns>
private PointF GetControlCenterPoint(Control _objControl)
{
return new PointF(_objControl.Width / 2, _objControl.Height / 2 - 1);
}
/// <summary>
/// Draws the line with GDI+.
/// </summary>
/// <param name="_objGraphics">The Graphics object.</param>
/// <param name="_objPointOne">The point one.</param>
/// <param name="_objPointTwo">The point two.</param>
/// <param name="_objColor">Color of the spoke.</param>
/// <param name="_intLineThickness">The thickness of spoke.</param>
private void DrawLine(Graphics _objGraphics, PointF _objPointOne, PointF _objPointTwo,
Color _objColor, int _intLineThickness)
{
using (Pen objPen = new Pen(new SolidBrush(_objColor), _intLineThickness))
{
objPen.StartCap = LineCap.Round;
objPen.EndCap = LineCap.Round;
_objGraphics.DrawLine(objPen, _objPointOne, _objPointTwo);
}
}
/// <summary>
/// Gets the coordinate.
/// </summary>
/// <param name="_objCircleCenter">The Circle center.</param>
/// <param name="_intRadius">The radius.</param>
/// <param name="_dblAngle">The angle.</param>
/// <returns></returns>
private PointF GetCoordinate(PointF _objCircleCenter, int _intRadius, double _dblAngle)
{
double dblAngle = Math.PI * _dblAngle / NumberOfDegreesInHalfCircle;
return new PointF(_objCircleCenter.X + _intRadius * (float)Math.Cos(dblAngle),
_objCircleCenter.Y + _intRadius * (float)Math.Sin(dblAngle));
}
/// <summary>
/// Gets the spokes angles.
/// </summary>
private void GetSpokesAngles()
{
m_Angles = GetSpokesAngles(NumberSpoke);
}
/// <summary>
/// Gets the spoke angles.
/// </summary>
/// <param name="_shtNumberSpoke">The number spoke.</param>
/// <returns>An array of angle.</returns>
private double[] GetSpokesAngles(int _intNumberSpoke)
{
double[] Angles = new double[_intNumberSpoke];
double dblAngle = (double)NumberOfDegreesInCircle / _intNumberSpoke;
for (int shtCounter = 0; shtCounter < _intNumberSpoke; shtCounter++)
Angles[shtCounter] = (shtCounter == 0 ? dblAngle : Angles[shtCounter - 1] + dblAngle);
return Angles;
}
/// <summary>
/// Actives the timer.
/// </summary>
private void ActiveTimer()
{
if (m_IsTimerActive)
{
m_Timer.Start();
}
else
{
m_Timer.Stop();
m_ProgressValue = 0;
}
GenerateColorsPallet();
Invalidate();
}
/// <summary>
/// Sets the circle appearance.
/// </summary>
/// <param name="numberSpoke">The number spoke.</param>
/// <param name="spokeThickness">The spoke thickness.</param>
/// <param name="innerCircleRadius">The inner circle radius.</param>
/// <param name="outerCircleRadius">The outer circle radius.</param>
public void SetCircleAppearance(int numberSpoke, int spokeThickness,
int innerCircleRadius, int outerCircleRadius)
{
NumberSpoke = numberSpoke;
SpokeThickness = spokeThickness;
InnerCircleRadius = innerCircleRadius;
OuterCircleRadius = outerCircleRadius;
Invalidate();
}
}
}
Sorry for answering my own post, but after testing a lot of projects, modify without success, I finally found one that is almost full transparent
https://www.codeproject.com/Articles/27185/WYSIWYG-Progress-Circle-for-NET-Framework-C
That guy made a very well job almost 10 years ago, at least inner part of spin is copied and re-drawn in OnPaint so quite nice transparent over RichTextBox control where all other projects failed :)
The only small problem is that the circle trail, don't copy the bmp behind so there will always be a comet effect, but I can live with that! Much pleasant effect than other solutions, including few on stackoverflow.
In case anyone will need!
Wow that seems incredibly complicated. I don't know much about wpf, but on iOS what we usually do is load an image that has the exact properties we need (here, transparent background), and just rotate the image to make the spinning effect.
You only need very little logic to make it appear/disappear and rotate. For a very basic spinner you get to create and use that class in a matter of seconds.
At least that's the route I'd go for, instead of writing 300 lines of code to manually handle the spinner :p
I am trying to create a settings page for my windows phone 7 application and i am using this article as the basis http://msdn.microsoft.com/en-us/library/ff769510(v=vs.92).aspx so my application class is :
public class AppSettings
{
// Our isolated storage settings
IsolatedStorageSettings isolatedStore;
// The isolated storage key names of our settings
const string CheckBoxSettingKeyName = "CheckBoxSetting";
const string ListBoxSettingKeyName = "ListBoxSetting";
const string RadioButton1SettingKeyName = "RadioButton1Setting";
const string RadioButton2SettingKeyName = "RadioButton2Setting";
const string RadioButton3SettingKeyName = "RadioButton3Setting";
const string UsernameSettingKeyName = "UsernameSetting";
const string PasswordSettingKeyName = "PasswordSetting";
// The default value of our settings
const bool CheckBoxSettingDefault = true;
const int ListBoxSettingDefault = 0;
const bool RadioButton1SettingDefault = true;
const bool RadioButton2SettingDefault = false;
const bool RadioButton3SettingDefault = false;
const string UsernameSettingDefault = "";
const string PasswordSettingDefault = "";
/// <summary>
/// Constructor that gets the application settings.
/// </summary>
public AppSettings()
{
try
{
// Get the settings for this application.
isolatedStore = IsolatedStorageSettings.ApplicationSettings;
}
catch (Exception e)
{
Debug.WriteLine("Exception while using IsolatedStorageSettings: " + e.ToString());
}
}
/// <summary>
/// Update a setting value for our application. If the setting does not
/// exist, then add the setting.
/// </summary>
/// <param name="Key"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool AddOrUpdateValue(string Key, Object value)
{
bool valueChanged = false;
// If the key exists
if (isolatedStore.Contains(Key))
{
// If the value has changed
if (isolatedStore[Key] != value)
{
// Store the new value
isolatedStore[Key] = value;
valueChanged = true;
}
}
// Otherwise create the key.
else
{
isolatedStore.Add(Key, value);
valueChanged = true;
}
return valueChanged;
}
/// <summary>
/// Get the current value of the setting, or if it is not found, set the
/// setting to the default setting.
/// </summary>
/// <typeparam name="valueType"></typeparam>
/// <param name="Key"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public valueType GetValueOrDefault<valueType>(string Key, valueType defaultValue)
{
valueType value;
// If the key exists, retrieve the value.
if (isolatedStore.Contains(Key))
{
value = (valueType)isolatedStore[Key];
}
// Otherwise, use the default value.
else
{
value = defaultValue;
}
return value;
}
/// <summary>
/// Save the settings.
/// </summary>
public void Save()
{
isolatedStore.Save();
}
/// <summary>
/// Property to get and set a CheckBox Setting Key.
/// </summary>
public bool CheckBoxSetting
{
get
{
return GetValueOrDefault<bool>(CheckBoxSettingKeyName, CheckBoxSettingDefault);
}
set
{
AddOrUpdateValue(CheckBoxSettingKeyName, value);
Save();
}
}
/// <summary>
/// Property to get and set a ListBox Setting Key.
/// </summary>
public int ListBoxSetting
{
get
{
return GetValueOrDefault<int>(ListBoxSettingKeyName, ListBoxSettingDefault);
}
set
{
AddOrUpdateValue(ListBoxSettingKeyName, value);
Save();
}
}
/// <summary>
/// Property to get and set a RadioButton Setting Key.
/// </summary>
public bool RadioButton1Setting
{
get
{
return GetValueOrDefault<bool>(RadioButton1SettingKeyName, RadioButton1SettingDefault);
}
set
{
AddOrUpdateValue(RadioButton1SettingKeyName, value);
Save();
}
}
/// <summary>
/// Property to get and set a RadioButton Setting Key.
/// </summary>
public bool RadioButton2Setting
{
get
{
return GetValueOrDefault<bool>(RadioButton2SettingKeyName, RadioButton2SettingDefault);
}
set
{
AddOrUpdateValue(RadioButton2SettingKeyName, value);
Save();
}
}
/// <summary>
/// Property to get and set a RadioButton Setting Key.
/// </summary>
public bool RadioButton3Setting
{
get
{
return GetValueOrDefault<bool>(RadioButton3SettingKeyName, RadioButton3SettingDefault);
}
set
{
AddOrUpdateValue(RadioButton3SettingKeyName, value);
Save();
}
}
/// <summary>
/// Property to get and set a Username Setting Key.
/// </summary>
public string UsernameSetting
{
get
{
return GetValueOrDefault<string>(UsernameSettingKeyName, UsernameSettingDefault);
}
set
{
AddOrUpdateValue(UsernameSettingKeyName, value);
Save();
}
}
/// <summary>
/// Property to get and set a Password Setting Key.
/// </summary>
public string PasswordSetting
{
get
{
return GetValueOrDefault<string>(PasswordSettingKeyName, PasswordSettingDefault);
}
set
{
AddOrUpdateValue(PasswordSettingKeyName, value);
Save();
}
}
}
Everything is working fine and i am able to update the settings value from a xaml settings page and i can access the setting values in my main application using
IsolatedStorageSettings Settings;
Settings = IsolatedStorageSettings.ApplicationSettings;
string checkboxvalue = (string)Settings["CheckBoxSetting"];
Now what i want is to be able to know when a value in the application settings is changed/updated , so that i can perform a action when settings are updated .
Similar to the other answer but more concrate. If you already use properties to work with, implement INotifyPropertyChanged interface, write your own RaisePropertyChanged/NotifyPropertyChanged and in the destination class subscribe to PropertyChanged event.
IsolatedStorageSettings.ApplicationSettings is a Dictionary. It is not observable by default.
There are lots of ways you could do this but the easiest way to get startred is if you just query the settings when you need to know them.
The other simple alternative woudl be for your AppSettings object to raise events when something was changed and have the relevant other classes subscribe to them.
I've begun writing a game using XNA Framework and have hit some simple problem I do not know how to solve correctly.
I'm displaying a menu using Texture2D and using the keyboard (or gamepad) I change the menu item that is selected. My problem is that the current function used to toggle between menu items is way too fast. I might click the down button and it will go down 5 or 6 menu items (due to the fact that Update() is called many time thus updating the selected item).
ex.
(> indicate selected)
> MenuItem1
MenuItem2
MenuItem3
MenuItem4
MenuItem5
I press the down key for just a second), then I have this state:
MenuItem1
MenuItem2
MenuItem3
> MenuItem4
MenuItem5
What I want is (until I press the key again)
MenuItem1
> MenuItem2
MenuItem3
MenuItem4
MenuItem5
What I am looking for is a way to either have the player click the up/down key many time in order to go from one menu item to the other, or to have some sort of minimum wait time before going to the next menu item.
the best way to implement this is to cache the keyboard/gamepad state from the update statement that just passed.
KeyboardState oldState;
...
var newState = Keyboard.GetState();
if (newState.IsKeyDown(Keys.Down) && !oldState.IsKeyDown(Keys.Down))
{
// the player just pressed down
}
else if (newState.IsKeyDown(Keys.Down) && oldState.IsKeyDown(Keys.Down))
{
// the player is holding the key down
}
else if (!newState.IsKeyDown(Keys.Down) && oldState.IsKeyDown(Keys.Down))
{
// the player was holding the key down, but has just let it go
}
oldState = newState;
In your case, you probably only want to move "down" in the first case above, when the key was just pressed.
I've built a (large) class that helps a lot with any and all XNA input related tasks, it makes what you're asking for easy.
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace YourNamespaceHere
{
/// <summary>
/// an enum of all available mouse buttons.
/// </summary>
public enum MouseButtons
{
LeftButton,
MiddleButton,
RightButton,
ExtraButton1,
ExtraButton2
}
public class InputHelper
{
private GamePadState _lastGamepadState;
private GamePadState _currentGamepadState;
#if (!XBOX)
private KeyboardState _lastKeyboardState;
private KeyboardState _currentKeyboardState;
private MouseState _lastMouseState;
private MouseState _currentMouseState;
#endif
private PlayerIndex _index = PlayerIndex.One;
private bool refreshData = false;
/// <summary>
/// Fetches the latest input states.
/// </summary>
public void Update()
{
if (!refreshData)
refreshData = true;
if (_lastGamepadState == null && _currentGamepadState == null)
{
_lastGamepadState = _currentGamepadState = GamePad.GetState(_index);
}
else
{
_lastGamepadState = _currentGamepadState;
_currentGamepadState = GamePad.GetState(_index);
}
#if (!XBOX)
if (_lastKeyboardState == null && _currentKeyboardState == null)
{
_lastKeyboardState = _currentKeyboardState = Keyboard.GetState();
}
else
{
_lastKeyboardState = _currentKeyboardState;
_currentKeyboardState = Keyboard.GetState();
}
if (_lastMouseState == null && _currentMouseState == null)
{
_lastMouseState = _currentMouseState = Mouse.GetState();
}
else
{
_lastMouseState = _currentMouseState;
_currentMouseState = Mouse.GetState();
}
#endif
}
/// <summary>
/// The previous state of the gamepad.
/// Exposed only for convenience.
/// </summary>
public GamePadState LastGamepadState
{
get { return _lastGamepadState; }
}
/// <summary>
/// the current state of the gamepad.
/// Exposed only for convenience.
/// </summary>
public GamePadState CurrentGamepadState
{
get { return _currentGamepadState; }
}
/// <summary>
/// the index that is used to poll the gamepad.
/// </summary>
public PlayerIndex Index
{
get { return _index; }
set {
_index = value;
if (refreshData)
{
Update();
Update();
}
}
}
#if (!XBOX)
/// <summary>
/// The previous keyboard state.
/// Exposed only for convenience.
/// </summary>
public KeyboardState LastKeyboardState
{
get { return _lastKeyboardState; }
}
/// <summary>
/// The current state of the keyboard.
/// Exposed only for convenience.
/// </summary>
public KeyboardState CurrentKeyboardState
{
get { return _currentKeyboardState; }
}
/// <summary>
/// The previous mouse state.
/// Exposed only for convenience.
/// </summary>
public MouseState LastMouseState
{
get { return _lastMouseState; }
}
/// <summary>
/// The current state of the mouse.
/// Exposed only for convenience.
/// </summary>
public MouseState CurrentMouseState
{
get { return _currentMouseState; }
}
#endif
/// <summary>
/// The current position of the left stick.
/// Y is automatically reversed for you.
/// </summary>
public Vector2 LeftStickPosition
{
get
{
return new Vector2(
_currentGamepadState.ThumbSticks.Left.X,
-CurrentGamepadState.ThumbSticks.Left.Y);
}
}
/// <summary>
/// The current position of the right stick.
/// Y is automatically reversed for you.
/// </summary>
public Vector2 RightStickPosition
{
get
{
return new Vector2(
_currentGamepadState.ThumbSticks.Right.X,
-_currentGamepadState.ThumbSticks.Right.Y);
}
}
/// <summary>
/// The current velocity of the left stick.
/// Y is automatically reversed for you.
/// expressed as:
/// current stick position - last stick position.
/// </summary>
public Vector2 LeftStickVelocity
{
get
{
Vector2 temp =
_currentGamepadState.ThumbSticks.Left -
_lastGamepadState.ThumbSticks.Left;
return new Vector2(temp.X, -temp.Y);
}
}
/// <summary>
/// The current velocity of the right stick.
/// Y is automatically reversed for you.
/// expressed as:
/// current stick position - last stick position.
/// </summary>
public Vector2 RightStickVelocity
{
get
{
Vector2 temp =
_currentGamepadState.ThumbSticks.Right -
_lastGamepadState.ThumbSticks.Right;
return new Vector2(temp.X, -temp.Y);
}
}
/// <summary>
/// the current position of the left trigger.
/// </summary>
public float LeftTriggerPosition
{
get { return _currentGamepadState.Triggers.Left; }
}
/// <summary>
/// the current position of the right trigger.
/// </summary>
public float RightTriggerPosition
{
get { return _currentGamepadState.Triggers.Right; }
}
/// <summary>
/// the velocity of the left trigger.
/// expressed as:
/// current trigger position - last trigger position.
/// </summary>
public float LeftTriggerVelocity
{
get
{
return
_currentGamepadState.Triggers.Left -
_lastGamepadState.Triggers.Left;
}
}
/// <summary>
/// the velocity of the right trigger.
/// expressed as:
/// current trigger position - last trigger position.
/// </summary>
public float RightTriggerVelocity
{
get
{
return _currentGamepadState.Triggers.Right -
_lastGamepadState.Triggers.Right;
}
}
#if (!XBOX)
/// <summary>
/// the current mouse position.
/// </summary>
public Vector2 MousePosition
{
get { return new Vector2(_currentMouseState.X, _currentMouseState.Y); }
}
/// <summary>
/// the current mouse velocity.
/// Expressed as:
/// current mouse position - last mouse position.
/// </summary>
public Vector2 MouseVelocity
{
get
{
return (
new Vector2(_currentMouseState.X, _currentMouseState.Y) -
new Vector2(_lastMouseState.X, _lastMouseState.Y)
);
}
}
/// <summary>
/// the current mouse scroll wheel position.
/// See the Mouse's ScrollWheel property for details.
/// </summary>
public float MouseScrollWheelPosition
{
get
{
return _currentMouseState.ScrollWheelValue;
}
}
/// <summary>
/// the mouse scroll wheel velocity.
/// Expressed as:
/// current scroll wheel position -
/// the last scroll wheel position.
/// </summary>
public float MouseScrollWheelVelocity
{
get
{
return (_currentMouseState.ScrollWheelValue - _lastMouseState.ScrollWheelValue);
}
}
#endif
/// <summary>
/// Used for debug purposes.
/// Indicates if the user wants to exit immediately.
/// </summary>
public bool ExitRequested
{
#if (!XBOX)
get
{
return (
(IsCurPress(Buttons.Start) &&
IsCurPress(Buttons.Back)) ||
IsCurPress(Keys.Escape));
}
#else
get { return (IsCurPress(Buttons.Start) && IsCurPress(Buttons.Back)); }
#endif
}
/// <summary>
/// Checks if the requested button is a new press.
/// </summary>
/// <param name="button">
/// The button to check.
/// </param>
/// <returns>
/// a bool indicating whether the selected button is being
/// pressed in the current state but not the last state.
/// </returns>
public bool IsNewPress(Buttons button)
{
return (
_lastGamepadState.IsButtonUp(button) &&
_currentGamepadState.IsButtonDown(button));
}
/// <summary>
/// Checks if the requested button is a current press.
/// </summary>
/// <param name="button">
/// the button to check.
/// </param>
/// <returns>
/// a bool indicating whether the selected button is being
/// pressed in the current state and in the last state.
/// </returns>
public bool IsCurPress(Buttons button)
{
return (
_lastGamepadState.IsButtonDown(button) &&
_currentGamepadState.IsButtonDown(button));
}
/// <summary>
/// Checks if the requested button is an old press.
/// </summary>
/// <param name="button">
/// the button to check.
/// </param>
/// <returns>
/// a bool indicating whether the selected button is not being
/// pressed in the current state and is being pressed in the last state.
/// </returns>
public bool IsOldPress(Buttons button)
{
return (
_lastGamepadState.IsButtonDown(button) &&
_currentGamepadState.IsButtonUp(button));
}
#if (!XBOX)
/// <summary>
/// Checks if the requested key is a new press.
/// </summary>
/// <param name="key">
/// the key to check.
/// </param>
/// <returns>
/// a bool that indicates whether the selected key is being
/// pressed in the current state and not in the last state.
/// </returns>
public bool IsNewPress(Keys key)
{
return (
_lastKeyboardState.IsKeyUp(key) &&
_currentKeyboardState.IsKeyDown(key));
}
/// <summary>
/// Checks if the requested key is a current press.
/// </summary>
/// <param name="key">
/// the key to check.
/// </param>
/// <returns>
/// a bool that indicates whether the selected key is being
/// pressed in the current state and in the last state.
/// </returns>
public bool IsCurPress(Keys key)
{
return (
_lastKeyboardState.IsKeyDown(key) &&
_currentKeyboardState.IsKeyDown(key));
}
/// <summary>
/// Checks if the requested button is an old press.
/// </summary>
/// <param name="key">
/// the key to check.
/// </param>
/// <returns>
/// a bool indicating whether the selectde button is not being
/// pressed in the current state and being pressed in the last state.
/// </returns>
public bool IsOldPress(Keys key)
{
return (
_lastKeyboardState.IsKeyDown(key) &&
_currentKeyboardState.IsKeyUp(key));
}
/// <summary>
/// Checks if the requested mosue button is a new press.
/// </summary>
/// <param name="button">
/// teh mouse button to check.
/// </param>
/// <returns>
/// a bool indicating whether the selected mouse button is being
/// pressed in the current state but not in the last state.
/// </returns>
public bool IsNewPress(MouseButtons button)
{
switch (button)
{
case MouseButtons.LeftButton:
return (
_lastMouseState.LeftButton == ButtonState.Released &&
_currentMouseState.LeftButton == ButtonState.Pressed);
case MouseButtons.MiddleButton:
return (
_lastMouseState.MiddleButton == ButtonState.Released &&
_currentMouseState.MiddleButton == ButtonState.Pressed);
case MouseButtons.RightButton:
return (
_lastMouseState.RightButton == ButtonState.Released &&
_currentMouseState.RightButton == ButtonState.Pressed);
case MouseButtons.ExtraButton1:
return (
_lastMouseState.XButton1 == ButtonState.Released &&
_currentMouseState.XButton1 == ButtonState.Pressed);
case MouseButtons.ExtraButton2:
return (
_lastMouseState.XButton2 == ButtonState.Released &&
_currentMouseState.XButton2 == ButtonState.Pressed);
default:
return false;
}
}
/// <summary>
/// Checks if the requested mosue button is a current press.
/// </summary>
/// <param name="button">
/// the mouse button to be checked.
/// </param>
/// <returns>
/// a bool indicating whether the selected mouse button is being
/// pressed in the current state and in the last state.
/// </returns>
public bool IsCurPress(MouseButtons button)
{
switch (button)
{
case MouseButtons.LeftButton:
return (
_lastMouseState.LeftButton == ButtonState.Pressed &&
_currentMouseState.LeftButton == ButtonState.Pressed);
case MouseButtons.MiddleButton:
return (
_lastMouseState.MiddleButton == ButtonState.Pressed &&
_currentMouseState.MiddleButton == ButtonState.Pressed);
case MouseButtons.RightButton:
return (
_lastMouseState.RightButton == ButtonState.Pressed &&
_currentMouseState.RightButton == ButtonState.Pressed);
case MouseButtons.ExtraButton1:
return (
_lastMouseState.XButton1 == ButtonState.Pressed &&
_currentMouseState.XButton1 == ButtonState.Pressed);
case MouseButtons.ExtraButton2:
return (
_lastMouseState.XButton2 == ButtonState.Pressed &&
_currentMouseState.XButton2 == ButtonState.Pressed);
default:
return false;
}
}
/// <summary>
/// Checks if the requested mosue button is an old press.
/// </summary>
/// <param name="button">
/// the mouse button to check.
/// </param>
/// <returns>
/// a bool indicating whether the selected mouse button is not being
/// pressed in the current state and is being pressed in the old state.
/// </returns>
public bool IsOldPress(MouseButtons button)
{
switch (button)
{
case MouseButtons.LeftButton:
return (
_lastMouseState.LeftButton == ButtonState.Pressed &&
_currentMouseState.LeftButton == ButtonState.Released);
case MouseButtons.MiddleButton:
return (
_lastMouseState.MiddleButton == ButtonState.Pressed &&
_currentMouseState.MiddleButton == ButtonState.Released);
case MouseButtons.RightButton:
return (
_lastMouseState.RightButton == ButtonState.Pressed &&
_currentMouseState.RightButton == ButtonState.Released);
case MouseButtons.ExtraButton1:
return (
_lastMouseState.XButton1 == ButtonState.Pressed &&
_currentMouseState.XButton1 == ButtonState.Released);
case MouseButtons.ExtraButton2:
return (
_lastMouseState.XButton2 == ButtonState.Pressed &&
_currentMouseState.XButton2 == ButtonState.Released);
default:
return false;
}
}
#endif
}
}
Just copy it into a separate class fie and move it to your namespace, then declare one (inputHelper variable), initialize it in the initialiaze portion, and call inputHelper.Update() in your update loop before the update logic. Then whenever you need something related to input, just use the InputHelper! for instance, in your situation, you would use InputHelper.IsNewPress([type of input button/key here]) to check if you want to move the menu item down or up. For this example: inputHelper.IsNewPress(Keys.Down)
A nice way of dealing with this kind of thing is to store a counter for each key you're interested in, which you increment every frame if the key is down, and reset to 0 if it's up.
The advantage of this is that you can then test for both the absolute state of the key (if the counter is non-zero the key is down) and also easily check if it's just been pressed this frame for menus and the like (counter is 1). Plus key repeat becomes easy (counter % repeat delay is zero).
If your application is for a Windows machine, I've had great success using this event driven class that I found here: gamedev.net forum post
It handles typical key presses and the short pauses before the repeating starts, just like normal text entry in a Windows application. Also included is mouse move/wheel events.
You can subscribe to the events, for example, using the following code:
InputSystem.KeyDown += new KeyEventHandler(KeyDownFunction);
InputSystem.KeyUp += new KeyEventHandler(KeyUpFunction);
Then in the methods themselves:
void KeyDownFunction(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.F)
facepalm();
}
void KeyUpFunction(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.F)
release();
}
...and so forth. It really is a great class. I've found it's flexibility much improved over XNA's default keyboard handling. Good Luck!
I thought the previous answers were a bit over-complicated, so I'm giving this one here...
Copy the KeyPress class below in a new file, declare the KeyPress variables, initialize them in your Initialize() method. From there you can do if ([yourkey].IsPressed()) ...
Note: this answer works only for Keyboard input, but it should be easily ported to Gamepad or any other input. I think keeping the code for the different types of input separate is better.
public class KeyPress
{
public KeyPress(Keys Key)
{
key = Key;
isHeld = false;
}
public bool IsPressed { get { return isPressed(); } }
public static void Update() { state = Keyboard.GetState(); }
private Keys key;
private bool isHeld;
private static KeyboardState state;
private bool isPressed()
{
if (state.IsKeyDown(key))
{
if (isHeld) return false;
else
{
isHeld = true;
return true;
}
}
else
{
if (isHeld) isHeld = false;
return false;
}
}
}
Usage:
// Declare variable
KeyPress escape;
// Initialize()
escape = new KeyPress(Keys.Escape)
// Update()
KeyPress.Update();
if (escape.IsPressed())
...
I might be wrong, but I think my answer is easier on resources than the accepted answer and also more readable!
You could store in integer value time from last key pressed (left,right...) and if this time is bigger than some limit you could poll for new key pressed. However this could be done only for menu, because in-game you would need that information immediately.
What you can also do is make yourself a functions combining KyeUp and KeyDown that tells you when the key has been pressed once, only in 1 loop of the update, so that it only works everytime you press the key again.
Ok, I've figured it out. First, I added a
private Keys keyPressed = Keys.None;
and in my Update() method, I do the following:
KeyboardState keyboardState = Keyboard.GetState();
if (keyboardState.IsKeyUp(keyPressed))
{
keyPressed = Keys.None;
}
if (keyboardState.IsKeyDown(keyPressed))
{
return;
}
// Some additionnal stuff is done according to direction
if (keyboardState.IsKeyDown(Keys.Up))
{
keyPressed = Keys.Up;
}
else if (keyboardState.IsKeyDown(Keys.Down))
{
keyPressed = Keys.Down;
}
It seems to be working correctly.
I save the GamePadState and KeyboardState from the previous update run. At the next update run i check for buttons that were not pressed last run, but are pressed now. Then I save the current state.
I have all of this wrapped up in a static class that I can use to query for specific buttons and/or get a list of pressed buttons since the last update. This makes it really easy to work with multiple keys simultaneously (something you certainly want in games) and it would be trivially extensible to chords.
Ranieri, what does that look like? I am having a hard time juggling these update cycles...
Hrmmm...
public static bool CheckKeyPress(Keys key)
{
return keyboardState.IsKeyUp(key) && lastKeyboardState.IsKeyDown(key);
}
SetStates() is private and it is called in the Update()
private static void SetStates()
{
lastKeyboardState = keyboardState;
keyboardState = Keyboard.GetState();
}
Here is the update...
public sealed override void Update(GameTime gameTime)
{
// Called to set the states of the input devices
SetStates();
base.Update(gameTime);
}
I've tried adding extra checks..
if (Xin.CheckKeyPress(Keys.Enter) ||
Xin.CheckButtonPress(Buttons.A))
{
if (Xin.LastKeyboardState != Xin.KeyboardState ||
Xin.LastGamePadState(PlayerIndex.One) != Xin.GamePadState(PlayerIndex.One))
{
doesn't seem to have any noticeable effects - I can't seem to slow down the menu confirmations,
Well what you could do is something like this (Also will track every key)
int[] keyVals;
TimeSpan pressWait = new TimeSpan(0, 0, 1);
Dictionary<Keys, bool> keyDowns = new Dictionary<Keys, bool>();
Dictionary<Keys, DateTime> keyTimes = new Dictionary<Keys, DateTime>();
public ConstructorNameHere
{
keyVals = Enum.GetValues(typeof(Keys)) as int[];
foreach (int k in keyVals)
{
keyDowns.Add((Keys)k, false);
keyTimes.Add((Keys)k, new DateTime()+ new TimeSpan(1,0,0));
}
}
protected override void Update(GameTime gameTime)
{
foreach (int i in keyVals)
{
Keys key = (Keys)i;
switch (key)
{
case Keys.Enter:
keyTimes[key] = (Keyboard.GetState().IsKeyUp(key)) ? ((keyDowns[key]) ? DateTime.Now + pressWait : keyTimes[key]) : keyTimes[key];
keyDowns[key] = (keyTimes[key] > DateTime.Now) ? false : Keyboard.GetState().IsKeyDown(key);
if (keyTimes[key] < DateTime.Now)
{
// Code for what happens when Keys.Enter is pressed goes here.
}
break;
}
}
By doing it this way you're able to check every key. You could also do this for just every key by create separate DateTimes and seperate bool values.
I know this is old, but how about:
Add a threadsafe dictionary:
private ConcurrentDictionary<Keys, DateTime> _keyBounceDict = new ConcurrentDictionary<Keys, DateTime>();
Then use this method to track the keys pressed and determine if there is a key bounce:
///////////////////////////////////////////////////////////////////////////////////////////
/// IsNotKeyBounce - determines if a key is bouncing and therefore not valid within
/// a certain "delay" period
///////////////////////////////////////////////////////////////////////////////////////////
private bool IsNotKeyBounce(Keys thekey, double delay)
{
bool OKtoPress = true;
if (_keyBounceDict.ContainsKey(thekey))
{
TimeSpan ts = DateTime.Now - _keyBounceDict[thekey];
if (ts.TotalMilliseconds < _tsKeyBounceTiming)
{
OKtoPress = false;
}
else
{
DateTime dummy;
_keyBounceDict.TryRemove(thekey, out dummy);
}
}
else
{
_keyBounceDict.AddOrUpdate(thekey, DateTime.Now, (key, oldValue) => oldValue);
}
return OKtoPress;
}
Here is what I put in my Update method:
if (Keyboard.GetState().IsKeyDown(Keys.W))
{
if (IsNotKeyBounce(Keys.W, 50.0)) _targetNew.Distance *= 1.1f;
}
I use 50 ms, but you could use whatever makes sense for your app or tie it to GameTime or whatever...