Hoy/JeuHoyEtudiants/JeuHoy_WPF_Natif/View/wEntrainement.xaml.cs
Merlin Gélinas deb08be6fc merge
2023-05-03 10:56:18 -04:00

304 lines
11 KiB
C#

using JeuHoy_WPF_Natif.Presenter;
using JeuHoy_WPF_Natif.View;
using Microsoft.Kinect;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace JeuHoy_WPF.View
{
/// <summary>
/// Auteur: Hugo St-Louis
/// Description: Permet de faire l'entrainement des différentes figures de danse.
/// Date: 2023-04-17
/// </summary>
public partial class wEntrainement : Window, IwEntrainement
{
private Dictionary<string, BitmapImage> _dicImgFigure = new Dictionary<string, BitmapImage>();
private JouerSon _son = new JouerSon();
private int _positionEnCours = 1;
private PresentateurWEntrainement _presentateur;
public event EventHandler EntrainementEvt;
public Image Image { get => picKinect; set => picKinect = value; }
public string Console { get => txtConsole.Text; set => txtConsole.Text = value; }
public Canvas Canvas { get => pDessinSquelette; set => pDessinSquelette = value; }
private KinectSensor _sensor;
private MultiSourceFrameReader _multiSourceFrameReader;
private BodyFrameReader _bodyFrameReader;
private WriteableBitmap _bitmap;
//private DisplayFrameType _displayFrameType = DisplayFrameType.Color;
private byte[] _picPixels = null;
/// <summary>
/// Constructeur
/// </summary>
public wEntrainement()
{
_presentateur = new PresentateurWEntrainement(this);
InitializeComponent();
_sensor = KinectSensor.GetDefault();
if (_sensor != null)
{
_sensor.Open();
//Lecture des images
_multiSourceFrameReader = _sensor.OpenMultiSourceFrameReader(FrameSourceTypes.Color);
_multiSourceFrameReader.MultiSourceFrameArrived += MultiSourceFrameReader_MultiSourceFrameArrived;
FrameDescription frameDescription = _sensor.ColorFrameSource.FrameDescription;
_picPixels = new byte[frameDescription.Width * frameDescription.Height * 4];
//Lecture des squelettes détectés
_bodyFrameReader = _sensor.BodyFrameSource.OpenReader();
_bodyFrameReader.FrameArrived += BodyFrameReader_FrameArrived;
}
for (int i = 1; i <= CstApplication.NBFIGURE; i++)
{
Uri uriSource = new Uri(AppDomain.CurrentDomain.BaseDirectory + @"./HoyContent/fig" + i + ".png", UriKind.Absolute);
_dicImgFigure.Add("fig" + i, new BitmapImage(uriSource));
}
lblNbPositions.Content = "/ " + CstApplication.NBFIGURE.ToString();
ChargerFigure();
_son.JouerSonAsync(@"./HoyContent/hoy.wav");
}
private void MultiSourceFrameReader_MultiSourceFrameArrived(object sender, MultiSourceFrameArrivedEventArgs e)
{
MultiSourceFrame multiSource = e.FrameReference.AcquireFrame();
if (multiSource == null)
return;
using (ColorFrame colorFrame = multiSource.ColorFrameReference.AcquireFrame())
{
if (colorFrame != null)
{
FrameDescription frameDescription = colorFrame.FrameDescription;
if (_bitmap == null)
_bitmap = new WriteableBitmap(frameDescription.Width,
frameDescription.Height,
96.0,
96.0,
PixelFormats.Bgra32,
null);
colorFrame.CopyConvertedFrameDataToArray(_picPixels, ColorImageFormat.Bgra);
_bitmap.Lock();
Marshal.Copy(_picPixels, 0, _bitmap.BackBuffer, _picPixels.Length);
_bitmap.AddDirtyRect(new Int32Rect(0, 0, _bitmap.PixelWidth, _bitmap.PixelHeight));
_bitmap.Unlock();
picKinect.Source = _bitmap;
}
}
}
private void BodyFrameReader_FrameArrived(object sender, BodyFrameArrivedEventArgs e)
{
using (BodyFrame bodyFrame = e.FrameReference.AcquireFrame())
{
if (bodyFrame == null)
return;
Body[] bodies = new Body[bodyFrame.BodyCount];
bodyFrame.GetAndRefreshBodyData(bodies);
Body body = bodies.FirstOrDefault(b => b.IsTracked);
if (body != null)
{
DessinerSquelette(body, _sensor);
}
}
}
/// <summary>
/// Dessine un ellipse pour chacune des jointure du squelette détecté.
/// </summary>
/// <param name="joueur">Le joueur détecté</param>
/// <param name="sensor">Le sensor Kinect</param>
private void DessinerSquelette(Body body, KinectSensor sensor)
{
try
{
if (body != null)
{
pDessinSquelette.Children.Clear();
Joint[] joints = body.Joints.Values.ToArray();
for (int i = 0; i < joints.Count(); i++)
DrawJoint(sensor, joints[i], CstApplication.BODY_ELLIPSE_SIZE, pDessinSquelette);
}
}
catch (Exception ex)
{
txtConsole.Text = ex.Message;
}
}
/// <summary>
/// Dessine le joint d'un squellete d'un senseur Kinect sur le canvas passé en paramètre
/// </summary>
/// <param name="sensor"></param>
/// <param name="joint"></param>
/// <param name="size"></param>
/// <param name="canvas"></param>
private void DrawJoint(KinectSensor sensor, Joint joint, int size, Canvas canvas)
{
if (joint.Position.X != 0 && joint.Position.Y != 0 && joint.Position.Z != 0)
{
// Convertir la position du joint en coordonnées d'écran
System.Windows.Point point = GetPoint(sensor, joint.Position, canvas.Height, canvas.Width);
// Créer un cercle à la position du joint
Ellipse ellipse = new Ellipse();
ellipse.Fill = new SolidColorBrush(Colors.Yellow);
ellipse.Width = size;
ellipse.Height = size;
// Positionner le cercle sur l'élément de dessin Canvas
Canvas.SetLeft(ellipse, point.X - size / 2);
Canvas.SetTop(ellipse, point.Y - size / 2);
// Ajouter le cercle à l'élément de dessin Canvas
canvas.Children.Add(ellipse);
}
}
/// <summary>
/// Retourne le point x,y d'un joint par rapport à la taille d'un canvas.
/// J'ai permis de dépasser le canvas car je trouvais ça drole :-)
/// </summary>
/// <param name="sensor"></param>
/// <param name="position"></param>
/// <param name="iCanvasHeight"></param>
/// <param name="iCanvasWidth"></param>
/// <returns></returns>
public System.Windows.Point GetPoint(KinectSensor sensor, CameraSpacePoint position, double iCanvasHeight, double iCanvasWidth)
{
System.Windows.Point point = new System.Windows.Point();
DepthSpacePoint depthPoint = sensor.CoordinateMapper.MapCameraPointToDepthSpace(position);
point.X = float.IsInfinity(depthPoint.X) ? 0.0 : depthPoint.X;
point.Y = float.IsInfinity(depthPoint.Y) ? 0.0 : depthPoint.Y;
// La Kinect pour Xbox One utilise également le SDK 2 de Microsoft, et sa résolution de profondeur est de 512x424 pixels.
//// Ainsi, la résolution de la carte de profondeur pour la Kinect pour Xbox One est également de 512x424 pixels.
point.X = point.X / 512 * iCanvasHeight;
point.Y = point.Y / 424 * iCanvasWidth;
return point;
}
/// <summary>
/// Charger la figure de danse en cours.
/// </summary>
private void ChargerFigure()
{
BitmapImage imgValue;
bool bResultat;
if (_positionEnCours > CstApplication.NBFIGURE)
_positionEnCours = 1;
if (_positionEnCours < 1)
_positionEnCours = CstApplication.NBFIGURE;
lblFigureEnCours.Content = _positionEnCours.ToString();
bResultat = _dicImgFigure.TryGetValue("fig" + _positionEnCours, out imgValue);
if (bResultat == true)
picPositionAFaire.Source = imgValue;
}
/// <summary>
/// Fermeture de la fenêtre.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void picRetour_Click(object sender, EventArgs e)
{
this.Close();
}
/// <summary>
/// Change le curseur lorsque le curseur est sur l'image
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void picRetour_MouseHover(object sender, EventArgs e)
{
this.Cursor = Cursors.Hand;
}
/// <summary>
/// Change le curseur lorsque le curseur est sur l'image
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void picRetour_MouseLeave(object sender, EventArgs e)
{
this.Cursor = Cursors.Arrow;
}
/// <summary>
/// Lorsqu'on appuie sur le bouton suivant ou précédent, modifier la figure en conséquence.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnClickChangerFigure_Click(object sender, RoutedEventArgs e)
{
Control bouton = (Control)sender;
if (bouton.Name == "btnSuivant")
_positionEnCours++;
else if (bouton.Name == "btnPrecedent")
_positionEnCours--;
ChargerFigure();
}
/// <summary>
/// Apprentissage avec la position obtenu à partir de la Kinect versus l'image affichée.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnApprendre_Click(object sender, RoutedEventArgs e)
{
//Ajouter du code ICI
EntrainementEvt(this, e);
}
}
}